问题:
解码为YUV420转为Bitmap后显示在屏幕上时,有三分之二为花屏:如图:
首先用h264Visa分析帧:
已经读出了sps等信息,这些信在解码第一帧时被写入环境变量中,所以下边的帧不需要sps了
而且在解码时必须为完整的一帧或者数帧。
只有IDR帧才需要带sps、pps信息。
ffmpeg中的av_read_frame()的作用是读取码流中的音频若干帧或者视频一帧。例如,解码视频的时候,每解码一个视频帧,需要先调用 av_read_frame()获得一帧视频的压缩数据,然后才能对该数据进行解码(例如H.264中一帧压缩数据通常对应一个NAL)。
通过av_read_packet(***),读取一个包,需要说明的是此函数必须是包含整数帧的,不存在半帧的情况,以ts流为例,是读取一个完整的PES包(一个完整pes包包含若干视频或音频es包),读取完毕后,通过av_parser_parse2(***)分析出视频一帧(或音频若干帧),返回,下次进入循环的时候,如果上次的数据没有完全取完,则st = s->cur_st;不会是NULL,即再此进入av_parser_parse2(***)流程,而不是下面的av_read_packet(**)流程,这样就保证了,如果读取一次包含了N帧视频数据(以视频为例),则调用av_read_frame(***)N次都不会去读数据,而是返回第一次读取的数据,直到全部解析完毕。
直接解码00 00 01之间的数据,很可能不是一帧完整的数据,所以需要先取到完整的数据,方法是使用:av_parser_parse2判断也就是说分帧的话在函数av_read_frame()会调用av_parse_parse2()函数,这只针对本地文件,如果解码网络流,需要自己调用av_parse_parse2()函数;
参照:http://blog.163.com/cho_ku2000/blog/static/913118220120553024697/
摘抄1:
如果由H264字节流格式去解码,在每次读取一段数据之后(不管每次读多少都可以),都调用av_parser_parse2去分帧,这个函数会将每次读取的264数据进行存储分析,直到得到完整的H264数据为止,然后送出,此时我们可以用avcodec_decode_video2来解码。
摘抄2:
那么送出的数据有什么规律呢? 对于IDR帧,除了IDR自身的数据外,会连同前面的SPS,PPS,SEI一并合在一起。在avcodec_decode_video2函数里面,包含了对SPS等的解析。
如果是P帧或者B帧,则不会送SPS,PPS等参赛信息。这个也很合理,因为本来就只有IDR帧才需要带参数信息
摘抄3:
需要av_parser_parse2先解析数据,再调用avcodec_decode_video2
如果av_parser_parse2的输入是1000k,但是av_parser_parse2的解析出来的数据可能只有200k
这200k作为avcodec_decode_video2的输入,剩下的800k需要再次av_parser_parse2,循环往复
如果直接将这1000k,扔进avcodec_decode_video2,返回正确,但是没有结果