1)当Live555收到的数据中连续来两个I帧,然后P帧,ffmpeg解码有问题;
解决办法:
当presntationTime不同时候,将以前存的buffer(已经是完整一帧)传给avcodec_decode_video2解码; 根据时间戳组帧将sps pps I 帧 I帧的组成一帧,交个ffmpeg解码,搞定;
2) 通过live555将阿波罗的相机的h264码流录制成avi,然后通过ffmpeg转成.h264,在用live555的testDemandRtspServer例子做服务器,然后通过testRtspClient做客户端进行接收,实时解码,发现前面一个GOP的数据解码不出来;前面一个GOP也是有sps pps I帧,然后若干P帧的,但是过了一个GOP后,解码就正常了。诧异!
avcodec_decode_video2返回值=-1;got_picture=0;
错误如下:
第一个Gop的第一个I帧 的sps,pps,I帧 的包是分别丢给解码器的,ffmpeg提示错误是no frame!
后面接着的一个P帧,就解码不出来,提示错误Missing reference picture. default is 0
第2个P帧开始的P帧提示错误:non-existing PPS 0 referenced.
调试记录:
1)根据时间戳不同组包,交给ffmpeg,也是前面一个Gop解码不出来;
2)后面尝试第一次从SDP从获取sps和pps信息,即第一帧数据是sps pps sps pps I帧,然后是若干个P帧,接着sps pps I帧,这样也是第一个GOP不能解码;
3)将第一帧的I帧反复交给ffmpeg,是可以解码的;
解决方案:
1)原因ffmpeg v1.2.1 版本,换成老的ffmpeg V0.6.0解决;
为什么会有问题,还需要分析ffmpeg v1.2.1版本的源码,是不是它需要缓冲多少帧,造成前面的一个GOP的图像解码不出来。
继续定位发现:v1.2.1 版本的第一个I帧解码 avcodec_decode_video2返回值为一帧数据的size,但是
len = avcodec_decode_video2(DecodecContext, m_pFrame, &got_picture,&avpkt);
gop_picture的值=0;
环境搭建:
1) live555 做服务器;客户端使用live555接收数据流;然后将接收到的数据帧插入到一个队列;另外一个显示线程从队列中取一帧数据进行解码,显示;
2) 从2个队列做缓冲区,首先是一个空的队列,在上面分配内存,形成一个链表;收到一帧数据后,从链表的头取一个节点,将一帧数据拷贝到该个节点上,然后插入到另外一个H264数据帧队列,一定要记得到H264数据帧队列的尾部;
3) 显示线程从H264队列的头取一个节点(一定要从头开始取节点);然后解码显示;
出现过的问题:
1) 插入H264队列时,插入到队列的头,取H264帧的时候也从头开始取,这样造成后来的数据显取了,解码出错;
现象:
Live555 sink 的afterGettingFrame函数中进行数据组帧,入队列操作,由于live555已经将rtp包头丢掉了,得到的一帧的数据,有可能有4种包,sps pps I 帧,p帧;
组帧策略:
按时间组帧,首先将时间戳相同的数据包组成一帧,然后插入到队列;
直接在数据到帧前加00 00 00 01 头后,插入到队列;
结论:
两种方法,ffmpeg都可以解码;使用的是ffmpeg 1.2.1 的版本;但是前面有一个GOP不能解码,原因不详;换成v0.6.0版本的ffmpeg库进行测试;解码正常!
有谁知道是什么原因的,麻烦告诉我下,谢谢!
今天又下载了一个最新的版本V2.1进行测试,还是发现前面一个GOP的图像解码失败,难道要用回老的版本v0.6.0
问题搞定:
是初始化解码器的分辨率和实际图像的分辨率不一致的问题;本来解码器是讲H264数据解码成Yuv数据的,但是我将yuv数据转换到RGB了,给RGB分配了内存,在解码器初始化函数里面:
#ifdef OUTPUT_RGB
m_pFrameRGB = avcodec_alloc_frame();
if(m_pFrameRGB == NULL)
{
return false;
}
int numBytes=avpicture_get_size(PIX_FMT_RGB24, DecodecContext->width, DecodecContext->height);
m_Rgbbuffer=new uint8_t[numBytes];
// Assign appropriate parts of buffer to image planes in pFrameRGB
avpicture_fill((AVPicture *)m_pFrameRGB, m_Rgbbuffer, PIX_FMT_RGB24, DecodecContext->width, DecodecContext->height);
img_convert_ctx = sws_getContext(DecodecContext->width, DecodecContext->height, DecodecContext->pix_fmt,
DecodecContext->width, DecodecContext->height, PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL);
if(img_convert_ctx == NULL)
{
fprintf(stderr, "Cannot initialize the conversion context!\n");
return false;
}
iDecodeWidth=DecodecContext->width;
iDecodeHeight=DecodecContext->height;
#endif
实际上,如果不转RGB是跟分辨率没有关系的,转RGB后分配的内存和分辨率有关系,所以在解码后,判断分辨率和我设置的分辨率不一致时,有调用了反解码器函数,释放ffmpeg的资源,然后在重新调用解码器初始化函数,这样就出现了前面一个GOP不能解码的问题;