我也正在做这个,用了FFMPEG的libavformat去提取数据,可以自己定义大小封装包,包的大小一般只要不超过路由器对转发包的最大值就可以了,收到包查看RTP头信息,做相关的检查。得到真正的数据包,然后用libavcodec解码,FFMPEG给了我们一个例子来实现。他说了这样一段话:As I've already mentioned, a video file can contain several audio and video streams, and each of those streams is split up into packets of a particular size. Our job is to read these packets one by one using libavformat, filter out all those that aren't part of the video stream we're interested in, and hand them on to libavcodec for decoding. In doing this, we'll have to take care of the fact that the boundary between two frames can occur in the middle of a packet.Sound complicated? Lucikly, we can encapsulate this whole process in a routine that simply returns the next video frame:bool GetNextFrame(AVFormatContext *pFormatCtx, AVCodecContext *pCodecCtx, int videoStream, AVFrame *pFrame) { static AVPacket packet; static int bytesRemaining=0; static uint8_t *rawData; static bool fFirstTime=true; int bytesDecoded; int frameFinished; // First time we're called, set packet.data to NULL to indicate it // doesn't have to be freed if(fFirstTime) { fFirstTime=false; packet.data=NULL; } // Decode packets until we have decoded a complete frame while(true) { // 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(pCodecCtx, pFrame, &frameFinished, rawData, bytesRemaining); // Was there an error? if(bytesDecoded < 0) { fprintf(stderr, "Error while decoding frame\n"); return false; } bytesRemaining-=bytesDecoded; rawData+=bytesDecoded; // Did we finish the current frame? Then we can return if(frameFinished) return true; } // Read the next packet, skipping all packets that aren't for this // stream do { // Free old packet if(packet.data!=NULL) av_free_packet(&packet); // Read new packet if(av_read_packet(pFormatCtx, &packet)<0) goto loop_exit; } while(packet.stream_index!=videoStream); bytesRemaining=packet.size; rawData=packet.data; }loop_exit: // Decode the rest of the last frame bytesDecoded=avcodec_decode_video(pCodecCtx, pFrame, &frameFinished, rawData, bytesRemaining); // Free last packet if(packet.data!=NULL) av_free_packet(&packet); return frameFinished!=0; }
udp你了解吧,RTP其实就是在UDP的基础上增加了12个字节。里面包含序列号、时钟戳、媒体的类型等,这些你在网上找找看看,而且还有RFC 的里面就是讲RTP的。
收到了RTP后,首先是要分析了,如根据序列号判断是否有丢包了,计算延时是多少了,这些可以有也可以不要。然后是去掉RTP的包头。剩下的就是数据了,然后是解码的操作了,过程就是这些了。不知道这些是否对你有帮助。
RTP协议帧格式里面,
你把数据体解析出来就OK了啊。
1,对解码出来的数据帧,根据什么规则来对其分包,然后添加RTP头?
2,在接收端如何判断收到一个完整的数据帧?我看到有的用5个“$”符号标识包头,然后根据位来判断是否是尾包,不知道对不对。
3,接收段对包的处理,主要是 去RTP包头,计算时延,反馈RTCP,判断丢包,重复包,排序,还有其他要做的工作没有?
2、和1 一样的,
3、看你的具体的需求了。去掉RTP包后,就是你编码后的数据了,然后解码即可了。
int videoStream, AVFrame *pFrame)
{
static AVPacket packet;
static int bytesRemaining=0;
static uint8_t *rawData;
static bool fFirstTime=true;
int bytesDecoded;
int frameFinished; // First time we're called, set packet.data to NULL to indicate it
// doesn't have to be freed
if(fFirstTime)
{
fFirstTime=false;
packet.data=NULL;
} // Decode packets until we have decoded a complete frame
while(true)
{
// 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(pCodecCtx, pFrame,
&frameFinished, rawData, bytesRemaining); // Was there an error?
if(bytesDecoded < 0)
{
fprintf(stderr, "Error while decoding frame\n");
return false;
} bytesRemaining-=bytesDecoded;
rawData+=bytesDecoded; // Did we finish the current frame? Then we can return
if(frameFinished)
return true;
} // Read the next packet, skipping all packets that aren't for this
// stream
do
{
// Free old packet
if(packet.data!=NULL)
av_free_packet(&packet); // Read new packet
if(av_read_packet(pFormatCtx, &packet)<0)
goto loop_exit;
} while(packet.stream_index!=videoStream); bytesRemaining=packet.size;
rawData=packet.data;
}loop_exit: // Decode the rest of the last frame
bytesDecoded=avcodec_decode_video(pCodecCtx, pFrame, &frameFinished,
rawData, bytesRemaining); // Free last packet
if(packet.data!=NULL)
av_free_packet(&packet); return frameFinished!=0;
}