开发环境Arm+Ubuntu14.04。
应用环境是 一帧帧的h264数据(顺序的20帧的h264数据,文件名分别是1.h264,2.h264,3.h264, ...... 20.h264且只有I帧 和P帧,无B帧,分辨率1920*1080),要求使用FFmpeg 相关api 编写测试程序解析h264数据,输出yuv文件。
说明本版本的 FFmpeg库 在调用解码avformat_open_input()av_find_stream_info()打开单帧的h264文件的时候报错如下:
ERROR:RkCodecInit:1221 video width(0) * height(0) is invalid
after init
[h264_rkvpu @ 0x13a10] [IMGUTILS @ 0xbeac3f2c] Picture size 0x0 is invalid
[h264_rkvpu @ 0x13a10] video_get_buffer: image parameters invalid
[h264_rkvpu @ 0x13a10] get_buffer() failed
[h264_rkvpu @ 0x13a10] Failed to get buffer!!!:-22Something wrong during decode!!!Picture size 0x0 is invalid
[h264_rkvpu @ 0x13a10] video_get_buffer: image parameters invalid
[h264_rkvpu @ 0x13a10] get_buffer() failed
[h264_rkvpu @ 0x13a10] Failed to get buffer!!!:-22Something wrong during decode!!!Picture size 0x0 is invalid
[[h264_rkvpu @ 0x13a10] Failed to get buffer!!!:-22Something wrong during decode!!!decoding for stream 0 failed
[h264 @ 0x13020] Could not find codec parameters for stream 0 (Video: h264, yuv420p): unspecified size
Consider increasing the value for the 'analyzeduration' and 'probesize' options
最终要求的是当前的开发环境,用不了avformat_open_input()av_find_stream_info()av_read_frame()等函数。
再次致敬雷霄骅博士,参考他的程序,本人程序如下:但是用此程序解码文件问题是解码程序总会丢一帧
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <libavformat/avformat.h> #include <libavcodec/avcodec.h> #include <libswscale/swscale.h> int main(int argc, char* argv[]) { AVCodec *pCodec; AVCodecContext *pCodecCtx= NULL; AVCodecParserContext *pCodecParserCtx=NULL; int frame_count,i; FILE *fp_in; FILE *fp_out; AVFrame *pFrame,*pFrameYUV; uint8_t *out_buffer; const int in_buffer_size=300000; uint8_t in_buffer[300000+32]={0}; uint8_t *cur_ptr; int cur_size; AVPacket packet; int ret, got_picture; int y_size; enum AVCodecID codec_id; codec_id=AV_CODEC_ID_H264; char filepath_out[]="test.yuv"; int first_time=1; int m_skippedframe=0; int DecFrameNum=0; int filesize =0; struct SwsContext *img_convert_ctx; avcodec_register_all(); pCodec = avcodec_find_decoder(codec_id); if (!pCodec) { printf("Codec not found\n"); return -1; } pCodecCtx = avcodec_alloc_context3(pCodec); if (!pCodecCtx) { printf("Could not allocate video codec context\n"); return -1; } /*必须设置,否则程序解码会报error*/ pCodecCtx->width =1920 ; pCodecCtx->height=1080; pCodecParserCtx=av_parser_init(codec_id); if (!pCodecParserCtx) { printf("Could not allocate video parser context\n"); return -1; } if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) { printf("Could not open codec\n"); return -1; } //Output File fp_out = fopen(filepath_out, "wb"); if (!fp_out) { printf("Could not open output YUV file\n"); return -1; } //Input File char filename_body[10]; for(i =1;i<=20;i++) { char filename[20] ={0}; memset(filename_body,0,sizeof(filename_body)); sprintf(filename_body,"%d",i); strcat(filename,filename_body); char filename_tail[5] = ".h264"; strcat(filename,filename_tail); printf("filename =%s\n",filename); fp_in = fopen(filename, "rb"); if (!fp_in) { printf("Could not open input stream\n"); return -1; } fseek(fp_in, 0L, SEEK_END); filesize=ftell(pInFile); pFrame = av_frame_alloc(); av_init_packet(&packet); while (1) { cur_size = fread(in_buffer, 1, in_buffer_size, fp_in); printf("cur_size =%d\n",cur_size); if (cur_size == 0) break; cur_ptr=in_buffer; while (cur_size>0) { int len = av_parser_parse2( pCodecParserCtx, pCodecCtx, &packet.data, &packet.size, cur_ptr , cur_size , AV_NOPTS_VALUE, AV_NOPTS_VALUE, AV_NOPTS_VALUE); cur_ptr += len; cur_size -= len; if(packet.size==0) continue; //Some Info from AVCodecParserContext printf("Packet Size:%6d\t",packet.size); switch(pCodecParserCtx->pict_type) { case AV_PICTURE_TYPE_I: printf("Type: I\t");break; case AV_PICTURE_TYPE_P: printf("Type: P\t");break; case AV_PICTURE_TYPE_B: printf("Type: B\t");break; default: printf("Type: Other\t");break; } printf("Output Number:%4d\t",pCodecParserCtx->output_picture_number); printf("Offset:%lld\n",pCodecParserCtx->cur_offset); ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, &packet); if (ret < 0) { printf("Decode Error.\n"); return ret; } if (got_picture) { if(first_time) { printf("\nCodec Full Name:%s\n",pCodecCtx->codec->long_name); printf("width:%d\nheight:%d\n\n",pCodecCtx->width,pCodecCtx->height); //SwsContext img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL); pFrameYUV=av_frame_alloc(); out_buffer=(uint8_t *)av_malloc(avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height)); avpicture_fill((AVPicture *)pFrameYUV, out_buffer, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height); y_size=pCodecCtx->width*pCodecCtx->height; first_time=0; } DecFrameNum++; printf("Succeed to decode 1 frame!,DecFrameNum =%d\n",DecFrameNum); sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize); fwrite(pFrameYUV->data[0],1,y_size,fp_out); //Y fwrite(pFrameYUV->data[1],1,y_size/4,fp_out); //U fwrite(pFrameYUV->data[2],1,y_size/4,fp_out); //V usleep(40*1000); } else { m_skippedframe++; printf("\n ******m_skippedframe =%d\n",m_skippedframe); } av_free_packet(&packet); } } } //Flush Decoder while(1) { printf("8888\n"); ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, &packet); printf("flush got_picture =%d\n",got_picture); if (ret < 0) { printf("Decode Error.\n"); return ret; } if (!got_picture) break; if (got_picture) { printf("Flush Decoder: Succeed to decode 1 frame!\n"); sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize); fwrite(pFrameYUV->data[0],1,y_size,fp_out); //Y fwrite(pFrameYUV->data[1],1,y_size/4,fp_out); //U fwrite(pFrameYUV->data[2],1,y_size/4,fp_out); //V } av_free_packet(&packet); } printf("99999\n"); fclose(fp_in); fclose(fp_out); sws_freeContext(img_convert_ctx); av_parser_close(pCodecParserCtx); av_frame_free(&pFrameYUV); av_frame_free(&pFrame); avcodec_close(pCodecCtx); av_free(pCodecCtx); return 0; }
恳请诸位高手帮忙分析问题
附上:执行log
root@ubuntu:# ./test
after init
filename =1.h264
cur_size =259391
cur_size =0
filename =2.h264
cur_size =104236
Packet Size:259391 Type: I Output Number: 0 Offset:-9223372036854516417
******m_skippedframe =1
cur_size =0
filename =3.h264
cur_size =68139
Packet Size:104236 Type: P Output Number: 2 Offset:-9223372036854412181
Codec Full Name:h264_rkvpu hw decoder
width:1920
height:1080
Succeed to decode 1 frame!,DecFrameNum =1
cur_size =0
filename =4.h264
cur_size =46712
Packet Size: 68139 Type: P Output Number: 4 Offset:-9223372036854344042
******m_skippedframe =2
cur_size =0
filename =5.h264
cur_size =129677
Packet Size: 46712 Type: P Output Number: 6 Offset:-9223372036854297330
Succeed to decode 1 frame!,DecFrameNum =2
cur_size =0
filename =6.h264
cur_size =50414
Packet Size:129677 Type: I Output Number: 0 Offset:-9223372036854167653
Succeed to decode 1 frame!,DecFrameNum =3
cur_size =0
filename =7.h264
cur_size =52537
Packet Size: 50414 Type: P Output Number: 2 Offset:-9223372036854117239
Succeed to decode 1 frame!,DecFrameNum =4
cur_size =0
filename =8.h264
cur_size =52254
Packet Size: 52537 Type: P Output Number: 4 Offset:-9223372036854064702
Succeed to decode 1 frame!,DecFrameNum =5
cur_size =0
filename =9.h264
cur_size =4793
Packet Size: 52254 Type: P Output Number: 6 Offset:-9223372036854012448
Succeed to decode 1 frame!,DecFrameNum =6
cur_size =0
filename =10.h264
cur_size =127786
Packet Size: 4793 Type: P Output Number: 8 Offset:-9223372036854007655
Succeed to decode 1 frame!,DecFrameNum =7
cur_size =0
filename =11.h264
cur_size =59473
Packet Size:127786 Type: I Output Number: 0 Offset:-9223372036853879869
Succeed to decode 1 frame!,DecFrameNum =8
cur_size =0
filename =12.h264
cur_size =48709
Packet Size: 59473 Type: P Output Number: 2 Offset:-9223372036853820396
Succeed to decode 1 frame!,DecFrameNum =9
cur_size =0
filename =13.h264
cur_size =45737
Packet Size: 48709 Type: P Output Number: 4 Offset:-9223372036853771687
Succeed to decode 1 frame!,DecFrameNum =10
cur_size =0
filename =14.h264
cur_size =45510
Packet Size: 45737 Type: P Output Number: 6 Offset:-9223372036853725950
Succeed to decode 1 frame!,DecFrameNum =11
cur_size =0
filename =15.h264
cur_size =126716
Packet Size: 45510 Type: P Output Number: 8 Offset:-9223372036853680440
Succeed to decode 1 frame!,DecFrameNum =12
cur_size =0
filename =16.h264
cur_size =45331
Packet Size:126716 Type: I Output Number: 0 Offset:-9223372036853553724
Succeed to decode 1 frame!,DecFrameNum =13
cur_size =0
filename =17.h264
cur_size =46676
Packet Size: 45331 Type: P Output Number: 2 Offset:-9223372036853508393
Succeed to decode 1 frame!,DecFrameNum =14
cur_size =0
filename =18.h264
cur_size =45808
Packet Size: 46676 Type: P Output Number: 4 Offset:-9223372036853461717
Succeed to decode 1 frame!,DecFrameNum =15
cur_size =0
filename =19.h264
cur_size =48620
Packet Size: 45808 Type: P Output Number: 6 Offset:-9223372036853415909
Succeed to decode 1 frame!,DecFrameNum =16
cur_size =0
filename =20.h264
cur_size =103297
Packet Size: 48620 Type: P Output Number: 8 Offset:-9223372036853367289
Succeed to decode 1 frame!,DecFrameNum =17
cur_size =0
8888
flush got_picture =1
Flush Decoder: Succeed to decode 1 frame!
8888
flush got_picture =1
Flush Decoder: Succeed to decode 1 frame!
8888
flush got_picture =0
99999
拿走100分 ,可能会送命。
不好意思,不太熟悉发帖,刚才代码格式太乱
那个库没问题。
恩,我描述有问题,解码库只是用不了avformat_open_input()av_find_stream_info()av_read_frame()等函数,不会影响丢帧。丢帧是这个测试程序问题,但是不知道如何改进
如果1.h264等每个文件是一帧,没有其它元数据。不需要avformat_open_input()av_find_stream_info()av_read_frame()等函数,直接完整读取文件,构造一个AVFrame进行解码就行了。
多谢回复,1.h264,就是一帧,没其他数据,也试过读取一帧的文件直接丢到packet,然后解码,也是丢最后一帧
fseek(fp_in, 0L, SEEK_END);
filesize=ftell(fp_in);
fseek(fp_in, 0L, SEEK_SET);
pFrame = av_frame_alloc();
av_init_packet(&packet);
while (1)
{
cur_size = fread(in_buffer, 1, /*in_buffer_size*/filesize, fp_in);
printf("cur_size =%d\n",cur_size);
if (cur_size == 0)
break;
//cur_ptr=in_buffer;
packet.data=in_buffer;
packet.size =filesize;
ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, &packet);
.......