一切都是为了好玩而已
因为前面花了点时间研究了一下EasyDarwin的相关数据结构和流传输的方式,所以,后面做起事情来就方便多了,但也还是有很多不清楚的地方,不过,这并不影响我的使用。
准备工具:
(1)EasyDarwin服务器
(2)EasyPusher库
(3)EasyRTSPClient库
(4)海康摄像头一个
(5)VS2010(或者别的版本,但我没试过)
(6)windows 7系统(其它版本我没试过)
第一步:测试一下海康摄像头,做法如下:
海康摄像头的访问url格式:rtsp://[username]:[password]@[ip]:[port]/[codec]/[channel]/[subtype]/av_stream
username: 用户名。例如admin。
password: 密码。例如12345。
ip: 为设备IP。例如 192.0.0.64。
port: 端口号默认为554,若为默认可不填写。
codec:有h264、MPEG-4、mpeg4这几种。
channel: 通道号,起始为1。例如通道1,则为ch1。
subtype: 码流类型,主码流为main,辅码流为sub。
如:rtsp://admin:[email protected]:554/h264/ch1/main/av_stream
利用VLC访问,测试通过。
第二步:搭建流媒体服务器EasyDarwin
这个可以参照官网http://www.easydarwin.org/unit/EasyDarwin.html
可以用release版本的,但我当时用这个版本的没搭起来(好像是),然后我就直接拿源码在VS2010上编译的。遇到的问题:
(1)因为Lib的库都是release下生成的,所以,VS工程也要设为release模式,否则一堆Link错误;
主要就是这个问题吧。
搭好以后,可以测试一下。要注意的是,按照官网的测试方式,是用一个mp4点播测试的,但我觉得对于新手来说(像我,没接触过编码,流媒体的人),有一个地方要注意的,就是这个Mp4文件是经过hint处理的!我当时也纠结这是什么意思。这个是流化处理,加入了一些东西。那么如何做流化?
我也是找了好久,最后还是要靠强大的ffmpeg来帮忙(windows下):
ffmpeg.exe -i test.mp4 -movflags rtphint out.mp4
经过上面转换后,这个out.mp4就可以被流媒体服务器转发了。具体就不说了,实验去吧。
第三步:利用EasyRTSPClient的demo,加入Pusher模块
这里,我只说关键部分,关于如果初始化pusher模块,去关注EasyPusher就行。
其实很简单,只要是EasyRTSPClient demo中一个回调中调用pusher的推流函数就可以了,关键就是如何组合一个符合推流格式的结构体。
关键的一个结构体:
typedef struct __EASY_AV_Frame
{
Easy_U32 u32AVFrameFlag; /* 帧标志 视频 or 音频 */
Easy_U32 u32AVFrameLen; /* 帧的长度 */
Easy_U32 u32VFrameType; /* 视频的类型,I帧或P帧 */
Easy_U8 *pBuffer; /* 数据 */
Easy_U32 u32TimestampSec; /* 时间戳(秒)*/
Easy_U32 u32TimestampUsec; /* 时间戳(微秒) */
}EASY_AV_Frame;
这个结构体会被/* 推流 frame:具体推送的流媒体帧 */
Easy_API Easy_U32 Easy_APICALL EasyPusher_PushFrame(Easy_Pusher_Handle handle, EASY_AV_Frame* frame );
调用(关注easypusher的demo就可以知道)。
而同时:
/* RTSPClient数据回调 */
int Easy_APICALL __RTSPClientCallBack( int _chid, int *_chPtr, int _frameType, char *_pBuf, RTSP_FRAME_INFO* _frameInfo);
这个回调会自动把RTSP流的信息给我们传进来,也就是说,不用去管它怎么取得信息的,只管知道:
(1)_frameType 指示是视频帧还是音频帧
(2)_pBuf 帧数据
(3)_frameInfo 帧数据信息头
这个结构体如下:
/* 帧信息 */
typedef struct
{
unsigned int codec; /* 音视频格式 */
unsigned int type; /* 视频帧类型 */
unsigned char fps; /* 视频帧率 */
unsigned short width; /* 视频宽 */
unsigned short height; /* 视频高 */
unsigned int reserved1; /* 保留参数1 */
unsigned int reserved2; /* 保留参数2 */
unsigned int sample_rate; /* 音频采样率 */
unsigned int channels; /* 音频声道数 */
unsigned int length; /* 音视频帧大小 */
unsigned int timestamp_usec; /* 时间戳,微妙 */
unsigned int timestamp_sec; /* 时间戳 秒 */
float bitrate; /* 比特率 */
float losspacket; /* 丢包率 */
}RTSP_FRAME_INFO;
上面的信息已经足够做一切事情了。。。。。。不多说了,直接贴上一段加在这个回调中的关键代码吧:
//pusher
//推送要求填写的信息:帧长度,数据(指纯视频数据?),视频帧类型(I,P)
EASY_AV_Frame avFrame;
memset(&avFrame, 0x00, sizeof(EASY_AV_Frame));
avFrame.u32AVFrameLen = _frameInfo->length;
avFrame.pBuffer = (unsigned char*)_pBuf;
avFrame.u32VFrameType = _frameInfo->type;
avFrame.u32AVFrameFlag = EASY_SDK_VIDEO_FRAME_FLAG;//视频还是音频标志
avFrame.u32TimestampSec = _frameInfo->timestamp_sec;
avFrame.u32TimestampUsec = _frameInfo->timestamp_usec;
EasyPusher_PushFrame(fPusherHandle, &avFrame);
好了,到此结束