热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

ffmpeg解码出现问题,v1.2.1版本,v2.1版本有问题,v0.6.0版本没有问题

1)当Live555收到的数据中连续来两个I帧,然后P帧,ffmpeg解码有问题;解决办法:当presntationTime不同时候&#

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不能解码的问题;

 

 


推荐阅读
author-avatar
729453686_5be5b9
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有