avcodec_decode_video2()解码不成功

调用ffmpeg的库从文件中读出视频流信息,利用av_read_frame提取帧,最后调用avcodec_decode_video2接口对帧进行解码,代码如下:
AVFormatContext *pFormatCtx;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
AVFrame *pFrame2;
AVPacket packet2;

int H264GetStream()
{

int             i, videoindex;
char filepath[]="sample.mp4";
av_register_all();
pFormatCtx = avformat_alloc_context();
if(avformat_open_input(&pFormatCtx,filepath,NULL,NULL)!=0){
    printf("无法打开文件\n");
    return -1;
}
    if(avformat_find_stream_info(pFormatCtx,NULL)<0)
{
    printf("Couldn't find stream information.\n");
    return -1;
}
videoindex=-1;
for(i=0; i<pFormatCtx->nb_streams; i++)
    if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO)
    {
        videoindex=i;
        break;
    }
    if(videoindex==-1)
    {
        printf("Didn't find a video stream.\n");
        return -1;
    }
    pCodecCtx=pFormatCtx->streams[videoindex]->codec;
    pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
    if(pCodec==NULL)
    {
        printf("Codec not found.\n");
        return -1;
    }
    printf("pCodec=%d\n",pCodec->id);
    if(avcodec_open2(pCodecCtx, pCodec,NULL)<0)
    {
        printf("Could not open codec.\n");
        return -1;
    }

    pFrame2=avcodec_alloc_frame();
    int ret, got_picture;
    int y_size = pCodecCtx->width * pCodecCtx->height;
    //packet2=(AVPacket *)malloc(sizeof(AVPacket));
    //av_new_packet(packet2, y_size);
    av_init_packet(&packet2);

    char filepath_out[]="bigbuckbunny_1920x1080.yuv";
    fp_out = fopen(filepath_out, "wb");
    if (!fp_out) {
        printf("Could not open output YUV file\n");
        return -1;
    }
    //输出一下信息-----------------------------
    printf("文件信息-----------------------------------------\n");
    av_dump_format(pFormatCtx,0,filepath,0);
    printf("-------------------------------------------------\n");
    //------------------------------
    while(av_read_frame(pFormatCtx, &packet2)>=0)
    {
        printf("packet2->stream_index=%d\n",packet2.stream_index);
        printf("videoindex=%d\n",videoindex);
        if(packet2.stream_index==videoindex)
        {
            printf("decode start!");
            //packet->data[0]=0;packet->data[1]=0;packet->data[2]=0;packet->data[3]=1;
           // packet->size-=4;
            printf("packet2->data=%d %d %d %d\n",packet2.data[0],packet2.data[1],packet2.data[2],packet2.data[3]);
            printf("packet2->size=%d\n",packet2.size);
            ret = avcodec_decode_video2(pCodecCtx, pFrame2, &got_picture, &packet2);
            printf("got_picture=%x\n",got_picture);
            if(ret < 0)
            {
                printf("decode error!\n");
                return -1;
            }

            if(got_picture)
            {
                printf("got_picture=%x\n",got_picture);
                 //Y, U, V
                int i;
                for(i=0;i<pFrame->height;i++)
                {
                  fwrite(pFrame->data[0]+pFrame->linesize[0]*i,1,pFrame->width,fp_out);
                }
                for(i=0;i<pFrame->height/2;i++)
                {
                  fwrite(pFrame->data[1]+pFrame->linesize[1]*i,1,pFrame->width/2,fp_out);
                }
                for(i=0;i<pFrame->height/2;i++)
                {
                  fwrite(pFrame->data[2]+pFrame->linesize[2]*i,1,pFrame->width/2,fp_out);
                }
                printf("Succeed to decode 1 frame!\n");

            }
        }
        av_free_packet(&packet2);
    }
    //av_free(pFrameYUV);
    avcodec_close(pCodecCtx);
    avformat_close_input(&pFormatCtx);

    return 0;

}
每次运行到ret = avcodec_decode_video2(pCodecCtx, pFrame2, &got_picture, &packet2)这一步程序就不再运行下去了,也没有任何返回值。
在这里打印信息检查了一下
while(av_read_frame(pFormatCtx, &packet2)>=0)
{
printf("packet2->stream_index=%d\n",packet2.stream_index);
printf("videoindex=%d\n",videoindex);
发现packet2.stream_index的值一直不变,按道理应该还有一路音频流。
程序是在linux平台下运行的,求问哪里出错了!

2个回答

原因找到了,改为从H264流直接提取帧后解决了问题。经本人验证,从mp4容器提取264流和从h264流读到的数据是一样的,但是从容器读取视频流会使用多核解码,在嵌入式ARM上就跑不了.

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐