当前位置:  编程技术>移动开发
本页文章导读:
    ▪RTSP流媒体播放器兑现        RTSP流媒体播放器实现        最近需要做一个RTSP流媒体播放器,研究了一下,封装了一个RTSP播放类CRTSPPlayer,解码库采用ffmpeg。由于需求比较简单,时间也有限,目前只实现了播放、停止、.........
    ▪ BACnet协议栈分析之Makefile资料        BACnet协议栈分析之Makefile文件Makefile参考书籍<GNU make项目管理> # CC = gcc # AR = ar # MAKE = make # SIZE = size # 配置 # If BACNET_DEFINES has not already been set, configure to your needs here # -D 表示引用意思,PRI.........
    ▪ 修改camera录像的时候平台框架设置有关问题       修改camera录像的时候平台框架设置问题. 修改camera录像的时候平台框架设置问题. http://blog.csdn.net/fulinwsuafcie/article/details/8351537 ......

[1]RTSP流媒体播放器兑现
    来源: 互联网  发布时间: 2014-02-18
RTSP流媒体播放器实现

        最近需要做一个RTSP流媒体播放器,研究了一下,封装了一个RTSP播放类CRTSPPlayer,解码库采用ffmpeg。由于需求比较简单,时间也有限,目前只实现了播放、停止、暂停几个基本的接口。下面是基于CRTSPPlayer类实现的简单RTSP播放器。

                                   

       目前视频只测试了H264格式,其它格式的视频还未做测试。播放器也支持直接打开本地视频播放,但播放的帧率和原始视频的码率不同步。目前还不清楚如何处理这个问题,希望懂这方面的大侠指教。

       另外,还有一个开源的库VLC也可以用来开发流媒体播放器,它支持多种流媒体协议,如RTP、RTSP等,CodeProject上已经有牛人在VLCLib的基础上封装可更易使用的库VLCWrapper(地址:http://www.codeproject.com/Articles/38952/VLCWrapper-A-Little-C-wrapper-Around-libvlc)。用它可以很方便的开发视频播放器。

        以下是CRTSPPlayer完整的代码:

头文件:

/******************************************************************** 
filename:   CRTSPPlayer.h 
created:    2013-03-25 
author:     firehood 
purpose:    ffmpeg库实现的RTSP视频播放器
*********************************************************************/ 
#pragma once
#include "windows.h"

extern "C"
{
#include "libavformat\avformat.h"
#include "libavcodec\avcodec.h"
#include "libswscale\swscale.h"
};

// 播放状态
enum RTSP_PLAYSTATUS
{
	RTSP_PLAYSTATUS_NONE,       // 未知状态(未播放)
	RTSP_PLAYSTATUS_PLAYING,    // 正在播放
    RTSP_PLAYSTATUS_PAUSE,      // 已暂停
	RTSP_PLAYSTATUS_STOP,       // 已停止
};

class CRTSPPlayer
{
public:
	CRTSPPlayer(HWND hWnd, LPRECT lpRect);
	~CRTSPPlayer(void);
public:
	// 打开媒体文件
	BOOL OpenMedia(LPCTSTR pFileName);
	// 播放
	void Play();
	// 暂停
	void Pause();
	// 停止
	void Stop();
	// 获取播放状态
	RTSP_PLAYSTATUS GetPlayStatus(void);
private:
	// 解码初始化
	int DecodeInit(LPCTSTR pFileName);
	// 卸载
	void DecodeUninit();
	// 开始解码线程
    BOOL StartDecodeThread();
    // 停止解码线程
	void StopDecodeThread();
    // 解码线程
	static int WINAPI ThreadDecodeVideo(LPVOID lpParam);
    // 开始解码任务
	int BeginDecode();
    // 显示
	void Display();
    // 图像转换
	int ImgConvert(AVPicture * dst, PixelFormat dstFormt, const AVPicture * src, PixelFormat srcFormt, int src_width, int src_height);
    // 设置播放状态
    void SetPlayStatus(RTSP_PLAYSTATUS playStatus);
private:
    HANDLE  m_hDecodeThread;
	BOOL    m_bExitDecodeThread;
    TCHAR   m_strFilePath[MAX_PATH];

	AVFormatContext* m_pFormatContext;
	AVCodecContext*  m_pCodecContext;
	AVCodec* m_pCodec;
	AVPacket m_struPacket;
	int m_nStreamIndex;
	AVFrame* m_pFrameYUV;
	AVFrame* m_pFrameRGB;
	int     m_nFrameWidth; 
	int	    m_nFrameHeight;
	BYTE*   m_pBufRGB;        // 解码后的RGB数据

	RTSP_PLAYSTATUS  m_nPlayStatus;
	HWND    m_hWnd;
	RECT    m_rcWnd;
};


源文件:

/******************************************************************** 
filename:   CRTSPPlayer.cpp 
created:    2013-03-25 
author:     firehood 
purpose:    ffmpeg库实现的RTSP视频播放器
*********************************************************************/ 
#include "StdAfx.h"
#include "RTSPPlayer.h"

#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "avcodec.lib")
#pragma comment(lib, "swscale.lib")
#pragma comment(lib, "avutil.lib")

#define SHOW_TITLE

const char* WcharToUtf8(const wchar_t *pwStr)  
{  
	if (pwStr == NULL)  
	{  
		return NULL;  
	}  

	int len = WideCharToMultiByte(CP_UTF8, 0, pwStr, -1, NULL, 0, NULL, NULL);  
	if (len <= 0)  
	{  
		return NULL;  
	}  
	char *pStr = new char[len];  
	WideCharToMultiByte(CP_UTF8, 0, pwStr, -1, pStr, len, NULL, NULL);  
	return pStr;  
}  

CRTSPPlayer::CRTSPPlayer(HWND hWnd, LPRECT lpRect):
m_hWnd(hWnd),
m_rcWnd(*lpRect),
m_hDecodeThread(NULL),
m_bExitDecodeThread(FALSE),
m_nFrameWidth(0),
m_nFrameHeight(0),
m_pFormatContext(NULL),
m_pCodecContext(NULL),
m_pCodec(NULL),
m_nStreamIndex(-1),
m_pFrameYUV(NULL),
m_pFrameRGB(NULL),
m_pBufRGB(NULL),
m_nPlayStatus(RTSP_PLAYSTATUS_NONE)
{
	memset(m_strFilePath,0,sizeof(m_strFilePath));
}

CRTSPPlayer::~CRTSPPlayer(void)
{
	DecodeUninit();
}

// 打开媒体文件
BOOL CRTSPPlayer::OpenMedia(LPCTSTR pFileName)
{
	if(pFileName == NULL)
		return FALSE;
	DecodeUninit();
	memcpy(m_strFilePath,pFileName,sizeof(m_strFilePath));
	DecodeInit(m_strFilePath);
	return TRUE;
}

// 播放
void CRTSPPlayer::Play()
{ 
	if(GetPlayStatus() == RTSP_PLAYSTATUS_STOP)
	{
		DecodeInit(m_strFilePath);
	}
	BOOL bRet = StartDecodeThread();
	if(bRet)
	{
		SetPlayStatus(RTSP_PLAYSTATUS_PLAYING);
	}
}

// 暂停
void CRTSPPlayer::Pause()
{
	StopDecodeThread();
	SetPlayStatus(RTSP_PLAYSTATUS_PAUSE);
}

// 停止
void CRTSPPlayer::Stop()
{
	StopDecodeThread();
	DecodeUninit();
	SetPlayStatus(RTSP_PLAYSTATUS_STOP);
}

BOOL CRTSPPlayer::StartDecodeThread()
{
	if(m_hDecodeThread == NULL)
	{
		m_hDecodeThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadDecodeVideo, this, 0, NULL);
	}
	return m_hDecodeThread ? TRUE : FALSE;
}

void CRTSPPlayer::StopDecodeThread()
{
	if(m_hDecodeThread)
	{
		m_bExitDecodeThread = TRUE;
		WaitForSingleObject(m_hDecodeThread,INFINITE);
		CloseHandle(m_hDecodeThread);
		m_hDecodeThread = NULL;
	}
}

int CRTSPPlayer::ImgConvert(AVPicture * dst, PixelFormat dst_pix_fmt, const AVPicture * src, PixelFormat src_pix_fmt, int src_width, int src_height)
{

	unsigned char * srcSlice[4];
	int srcStride[4] = {0};

	unsigned char * dstSlice[4];
	int dstStride[4] = {0};


	for (int i=0; i<4; i++)
	{
		srcSlice[i] = src->data[i];
		srcStride[i] = src->linesize[i];

		dstSlice[i] = dst->data[i];
		dstStride[i] = dst->linesize[i];
	}

	SwsContext *pSwsContext = sws_getContext(src_width, src_height, src_pix_fmt, src_width, src_height, dst_pix_fmt, SWS_BICUBIC, NULL, NULL, NULL);

	int nRet = sws_scale(pSwsContext, srcSlice, srcStride, 0, src_height, dstSlice, dstStride);

	if (pSwsContext != NULL)
	{
		sws_freeContext(pSwsContext);
	}

	return nRet;
}

int WINAPI CRTSPPlayer::ThreadDecodeVideo(LPVOID lpParam)
{
	CRTSPPlayer *pPlayer = (CRTSPPlayer*)lpParam;

	pPlayer->BeginDecode();

	return 0;
}

int CRTSPPlayer::DecodeInit(LPCTSTR pFileName)
{
    if(pFileName == NULL)
	{
		return -1;
	}

	av_register_all();

#ifdef  UNICODE   
	const char *filePath = WcharToUtf8(pFileName); 
	// Open video
	if (av_open_input_file(&m_pFormatContext, filePath, NULL, 0, NULL) != 0)
	{
		return -2; // Couldn't open file
	}
	delete[] filePath;
#else
	// Open video
	if (av_open_input_file(&m_pFormatContext, pFileName, NULL, 0, NULL) != 0)
	{
		return -2; // Couldn't open file
	}
#endif
	// Retrieve stream information
	if (av_find_stream_info(m_pFormatContext) < 0)
	{
		return -3; // Couldn't find stream information
	}

	// Find the first video stream
	for (UINT i=0; i<m_pFormatContext->nb_streams; i++)
	{
		if (m_pFormatContext->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO)
		{
			m_nStreamIndex = i;
			break;
		}
	}
	if (m_nStreamIndex == -1)
	{
		return -4; // Didn't find a video stream
	}

	// Get a pointer to the codec context for the video stream
	m_pCodecContext = m_pFormatContext->streams[m_nStreamIndex]->codec;

	// Find the decoder for the video stream
	m_pCodec = avcodec_find_decoder(m_pCodecContext->codec_id);
	if (m_pCodec == NULL)
	{
		return -5 ; // Codec not found
	}

	// Inform the codec that we can handle truncated bitstreams -- i.e.,
	// bitstreams where frame boundaries can fall in the middle of packets
	if (m_pCodec->capabilities & CODEC_CAP_TRUNCATED)
	{
		m_pCodecContext->flags |= CODEC_FLAG_TRUNCATED;  // we do not send complete frames
	}

	// Open codec
	if (avcodec_open(m_pCodecContext, m_pCodec) < 0)
	{
		return -6; // Could not open codec
	}

	// Allocate video frame
	m_pFrameYUV = avcodec_alloc_frame();

	// Allocate an AVFrame structure
	m_pFrameRGB = avcodec_alloc_frame();

	// Determine required buffer size and allocate buffer
	int numBytes = avpicture_get_size(PIX_FMT_BGR24, m_pCodecContext->width, m_pCodecContext->height);
	m_pBufRGB = new BYTE [numBytes];
	memset(m_pBufRGB,0,numBytes);
	// Assign appropriate parts of buffer to image planes in m_pFrameRGB
	avpicture_fill((AVPicture *)m_pFrameRGB, m_pBufRGB, PIX_FMT_BGR24, m_pCodecContext->width, m_pCodecContext->height);

	m_nFrameWidth  = m_pCodecContext->width;
	m_nFrameHeight = m_pCodecContext->height;

	return 0;
}

void CRTSPPlayer::DecodeUninit()
{
	// Close the codec
	if (m_pCodecContext)
	{
		avcodec_close(m_pCodecContext);
		//av_free(m_pCodec);
		m_pCodecContext = NULL;
		m_pCodec = NULL;
	}

	// Close the video file
	if (m_pFormatContext)
	{
		av_close_input_file(m_pFormatContext);
		m_pFormatContext = NULL;
	}

	if (m_pFrameYUV)
	{
		av_free(m_pFrameYUV);
		m_pFrameYUV = NULL;
	}

	if (m_pFrameRGB)
	{
		av_free(m_pFrameRGB);
		m_pFrameRGB = NULL;
	}

	if (m_pBufRGB)
	{
		delete [] m_pBufRGB;
		m_pBufRGB = NULL;
	}
}

int CRTSPPlayer::BeginDecode()
{
	int bytesRemaining = 0, bytesDecoded;
	BYTE * rawData = NULL;

	int frameFinished = 0;

	m_struPacket.data = NULL;
	m_struPacket.size = 0;

	m_bExitDecodeThread = FALSE;

	while (!m_bExitDecodeThread && m_pFormatContext)
	{
		// Read the next packet, skipping all packets that aren't for this stream
		do
		{
			// Read new packet
			if (av_read_frame(m_pFormatContext, &m_struPacket) < 0)
			{

				return -2;
			}
		} while (m_struPacket.stream_index != m_nStreamIndex);

		bytesRemaining = m_struPacket.size;
		rawData = m_struPacket.data;

		// Work on the current packet until we have decoded all of it
		while (bytesRemaining > 0)
		{
			// Decode the next chunk of data
			bytesDecoded = avcodec_decode_video(m_pCodecContext, m_pFrameYUV, &frameFinished, rawData, bytesRemaining);

			// Was there an error?
			if (bytesDecoded < 0)
			{
				return -1;
			}

			bytesRemaining -= bytesDecoded;
			rawData += bytesDecoded;

			// Did we finish the current frame? Then we can return
			if (frameFinished)
			{
				ImgConvert(
					(AVPicture *)m_pFrameRGB,
					PIX_FMT_BGR24,
					(AVPicture *)m_pFrameYUV,
					m_pCodecContext->pix_fmt,
					m_pCodecContext->width,
					m_pCodecContext->height);

				Display();
			}
		}
	}
	m_hDecodeThread = NULL;
	return 0;
}

void CRTSPPlayer::Display()
{
	HDC hdc = GetDC(m_hWnd);
	// 创建内存DC
    HDC hMemDc = CreateCompatibleDC(hdc);     

	// 创建位图
	BITMAPINFOHEADER bmpHdr = {0};  
	bmpHdr.biSize = sizeof (BITMAPINFOHEADER);  
	bmpHdr.biWidth = m_nFrameWidth;  
	bmpHdr.biHeight = -m_nFrameHeight;  
	bmpHdr.biPlanes = 1;  
	bmpHdr.biBitCount = 24;  
	bmpHdr.biCompression = BI_RGB;  

	BYTE *pData = NULL;   
	HBITMAP hBitmap = CreateDIBSection (NULL, (BITMAPINFO *)&bmpHdr, DIB_RGB_COLORS, (void**)&pData, NULL, 0);  

	try
	{
		memcpy(pData, m_pBufRGB, m_nFrameWidth * m_nFrameHeight * 3);
	}
	catch (CMemoryException* e)
	{
		
	}

	HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDc, hBitmap);

#ifdef SHOW_TITLE
	// 设置字体参数
	LOGFONT logfont;
	memset(&logfont, 0, sizeof(LOGFONT));
	logfont.lfHeight = 40;
	logfont.lfWidth = 0;	
	logfont.lfEscapement = 0;
	logfont.lfOrientation = 0;
	logfont.lfWeight = 30;
	logfont.lfItalic = 0;
	logfont.lfUnderline = 0;
	logfont.lfStrikeOut = 0;
	logfont.lfCharSet = DEFAULT_CHARSET;   
	logfont.lfOutPrecision= OUT_DEFAULT_PRECIS;   
	logfont.lfClipPrecision= OUT_DEFAULT_PRECIS;   
	logfont.lfQuality = DEFAULT_QUALITY;   
	logfont.lfPitchAndFamily= DEFAULT_PITCH;  

	// 创建字体并选入环境
	HFONT hFont = CreateFontIndirect(&logfont);
	HFONT hOldFont = (HFONT)SelectObject(hMemDc, hFont);

	// 设置绘图环境
	SetBkMode(hMemDc, TRANSPARENT);  
    SetTextColor(hMemDc, RGB(255, 255, 0));

	// 绘制文字
	TextOut(hMemDc,0,0,m_strFilePath,_tcslen(m_strFilePath));

	// 恢复环境释放字体
	SelectObject(hMemDc, hOldFont);
#endif
	StretchBlt(  
		hdc,  
		m_rcWnd.left,   
		m_rcWnd.top,   
		m_rcWnd.right-m_rcWnd.left,   
		m_rcWnd.bottom-m_rcWnd.top,   
		hMemDc,  
		0,   
		0,   
		m_nFrameWidth,   
		m_nFrameHeight,   
		SRCCOPY);  

	// 恢复并释放环境    
	SelectObject(hMemDc,hOldBitmap);  
	DeleteObject(hBitmap);  
	DeleteDC(hMemDc);  
}

// 获取播放状态
RTSP_PLAYSTATUS CRTSPPlayer::GetPlayStatus(void)
{
	return m_nPlayStatus;
}

// 设置播放状态
void CRTSPPlayer::SetPlayStatus(RTSP_PLAYSTATUS playStatus)
{
	m_nPlayStatus = playStatus;
}




    
[2] BACnet协议栈分析之Makefile资料
    来源: 互联网  发布时间: 2014-02-18
BACnet协议栈分析之Makefile文件

Makefile参考书籍<GNU make项目管理>

# CC = gcc
# AR = ar
# MAKE = make
# SIZE = size

# 配置

# If BACNET_DEFINES has not already been set, configure to your needs here

# -D 表示引用意思,PRINT_ENABLE=1, BACAPP_ALL, BACFILE, INTRINSIC_REPORTING

MY_BACNET_DEFINES = -DPRINT_ENABLED=1
MY_BACNET_DEFINES += -DBACAPP_ALL
MY_BACNET_DEFINES += -DBACFILE
MY_BACNET_DEFINES += -DINTRINSIC_REPORTING
BACNET_DEFINES ?= $(MY_BACNET_DEFINES)

# un-comment the next line to build the routing demo application BACNET默认是开启BACnet IP协议,若想使用MS/TP则需

#使用BACDL_DEFINE=-DBACDL_MSTP=1
#BACNET_DEFINES += -DBAC_ROUTING

#BACDL_DEFINE=-DBACDL_ETHERNET=1
#BACDL_DEFINE=-DBACDL_ARCNET=1
#BACDL_DEFINE=-DBACDL_MSTP=1
BACDL_DEFINE?=-DBACDL_BIP=1

# 定义要支持的BBMD的类型

BBMD_DEFINE ?= -DBBMD_ENABLED=1
#BBMD_DEFINE ?=-DBBMD_ENABLED=0
#BBMD_DEFINE ?= -DBBMD_CLIENT_ENABLED

# 通过命令行来传递参数

MAKE_DEFINE ?=

# 不知道WEAK_FUNC有什么用

DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE) $(BBMD_DEFINE) -DWEAK_FUNC=
DEFINES += $(MAKE_DEFINE)

# 默认是/ports/linux目录

BACNET_PORT ?= linux
BACNET_PORT_DIR = ../ports/${BACNET_PORT}

BACNET_OBJECT = ../demo/object
BACNET_HANDLER = ../demo/handler
BACNET_CORE = ../src
BACNET_INCLUDE = ../include
# 编译器配置

#STANDARDS = -std=c99
INCLUDE1 = -I$(BACNET_PORT_DIR) -I$(BACNET_OBJECT) -I$(BACNET_HANDLER)
INCLUDE2 = -I$(BACNET_INCLUDE)
INCLUDES = $(INCLUDE1) $(INCLUDE2)
OPTIMIZATION = -Os
DEBUGGING =
WARNINGS = -Wall -Wmissing-prototypes
ifeq (${BUILD},debug)
OPTIMIZATION = -O0
DEBUGGING = -g -DDEBUG_ENABLED=1
ifeq (${BACDL_DEFINE},-DBACDL_BIP=1)
DEFINES += -DBIP_DEBUG
endif
endif
CFLAGS  = $(WARNINGS) $(DEBUGGING) $(OPTIMIZATION) $(STANDARDS) $(INCLUDES) $(DEFINES)

# export导出变量

# (see http://www.gnu.org/software/automake/manual/make/Special-Targets.html)
.EXPORT_ALL_VARIABLES:

all: library demos
.PHONY : all library demos clean

library:
 $(MAKE) -C lib all

demos:
 $(MAKE) -C demo all

# 增加想要的开发板类型,比如at91sam7s,atmega168

ports: atmega168 bdk-atxx4-mstp at91sam7s
 @echo "Built the ARM7 and AVR ports"

atmega168: ports/atmega168/Makefile
 $(MAKE) -C ports/atmega168 clean all

at91sam7s: ports/at91sam7s/makefile
 $(MAKE) -C ports/at91sam7s clean all

bdk-atxx4-mstp: ports/bdk-atxx4-mstp/Makefile
 $(MAKE) -C ports/bdk-atxx4-mstp clean all

clean:
 $(MAKE) -C lib clean
 $(MAKE) -C demo clean


    
[3] 修改camera录像的时候平台框架设置有关问题
    来源: 互联网  发布时间: 2014-02-18
修改camera录像的时候平台框架设置问题.


修改camera录像的时候平台框架设置问题.

http://blog.csdn.net/fulinwsuafcie/article/details/8351537


    
最新技术文章:
▪Android开发之登录验证实例教程
▪Android开发之注册登录方法示例
▪Android获取手机SIM卡运营商信息的方法
▪Android实现将已发送的短信写入短信数据库的...
▪Android发送短信功能代码
▪Android根据电话号码获得联系人头像实例代码
▪Android中GPS定位的用法实例
▪Android实现退出时关闭所有Activity的方法
▪Android实现文件的分割和组装
▪Android录音应用实例教程
▪Android双击返回键退出程序的实现方法
▪Android实现侦听电池状态显示、电量及充电动...
▪Android获取当前已连接的wifi信号强度的方法
▪Android实现动态显示或隐藏密码输入框的内容
▪根据USER-AGENT判断手机类型并跳转到相应的app...
▪Android Touch事件分发过程详解
▪Android中实现为TextView添加多个可点击的文本
▪Android程序设计之AIDL实例详解
▪Android显式启动与隐式启动Activity的区别介绍
▪Android按钮单击事件的四种常用写法总结
▪Android消息处理机制Looper和Handler详解
▪Android实现Back功能代码片段总结
▪Android实用的代码片段 常用代码总结
▪Android实现弹出键盘的方法
▪Android中通过view方式获取当前Activity的屏幕截...
▪Android提高之自定义Menu(TabMenu)实现方法
▪Android提高之多方向抽屉实现方法
▪Android提高之MediaPlayer播放网络音频的实现方法...
▪Android提高之MediaPlayer播放网络视频的实现方法...
▪Android提高之手游转电视游戏的模拟操控
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3