首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用libavcodec解码H264视频

使用libavcodec解码H264视频
EN

Stack Overflow用户
提问于 2015-01-10 06:49:58
回答 1查看 9.6K关注 1票数 3

我试图用ffmpeg/libavcodec解码一个原始的h264文件,但是无法让它正常工作。输出现在应该是一个原始的YUV文件。用GCC编译代码是可能的

代码语言:javascript
运行
复制
gcc -o decoder decoder.c -L./lib/ -llibavcodec -llibavutil

avcodec.dll、avutil.dll和swresample.dll必须放在目录中,.exe才能启动。CMD中的输出看起来像这样(只是其中的一部分,但总是这样):

代码语言:javascript
运行
复制
[h264 @ 00a80f20] reference picture missing during reorder
[h264 @ 00a80f20] Missing reference picture, default is 65562
[h264 @ 00a80f20] error while decoding MB 80 54, bytestream -10
[h264 @ 00a80f20] concealing 1649 DC, 1649 AC, 1649 MV errors in B frame
[h264 @ 00a80f20] reference picture missing during reorder
[h264 @ 00a80f20] reference picture missing during reorder
[h264 @ 00a80f20] reference picture missing during reorder
[h264 @ 00a80f20] Missing reference picture, default is 65566
[h264 @ 00a80f20] Missing reference picture, default is 65566
[h264 @ 00a80f20] Missing reference picture, default is 65566
[h264 @ 00a80f20] reference picture missing during reorder
[h264 @ 00a80f20] Missing reference picture, default is 65568
[h264 @ 00a80f20] reference picture missing during reorder
[h264 @ 00a80f20] Missing reference picture, default is 65570
[h264 @ 00a80f20] reference picture missing during reorder

下面是我的代码

代码语言:javascript
运行
复制
#include <stdlib.h>
#include <stdio.h>

#ifdef HAVE_AV_CONFIG_H
#undef HAVE_AV_CONFIG_H
#endif

#include "libavcodec/avcodec.h"
//#include "libavcodec/libavutil/mathematics.h"

#define INBUF_SIZE 4096

void video_decode(char *outfilename, char *filename)
{
    AVCodec *codec;
    AVCodecContext *c= NULL;
    int frame, got_picture, len;
    FILE *f, *outf;
    AVFrame *picture;
    uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
    AVPacket avpkt;
    int i;

    av_init_packet(&avpkt);

    memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE);

    codec = avcodec_find_decoder(AV_CODEC_ID_H264);
    if (!codec) {
        fprintf(stderr, "codec not found\n");
        exit(1);
    }

    c = avcodec_alloc_context3(codec);
    picture = av_frame_alloc();

    if((codec->capabilities)&CODEC_CAP_TRUNCATED)
        (c->flags) |= CODEC_FLAG_TRUNCATED;

    c->height = 1080;
    c->width = 1920;

    if (avcodec_open2(c, codec, NULL) < 0) {
        fprintf(stderr, "could not open codec\n");
        exit(1);
    }

    f = fopen(filename, "rb");
    if (!f) {
        fprintf(stderr, "could not open %s\n", filename);
        exit(1);
    }

    outf = fopen(outfilename,"w");
    if(!outf){
        fprintf(stderr, "could not open %s\n", filename);
        exit(1);
    }
    frame = 0;
    for(;;) {
        avpkt.size = fread(inbuf, 1, INBUF_SIZE, f);
        if (avpkt.size == 0)
            break;

        avpkt.data = inbuf;
        while (avpkt.size > 0) {

            len = avcodec_decode_video2(c, picture, &got_picture, &avpkt);

            if (len < 0) {
                fprintf(stderr, "Error while decoding frame %d\n", frame);
                exit(1);
            }
            if (got_picture) {
                printf("saving frame %3d\n", frame);
                fflush(stdout);
                for(i=0; i<c->height; i++)
                    fwrite(picture->data[0] + i * picture->linesize[0], 1, c->width, outf  );
                for(i=0; i<c->height/2; i++)
                    fwrite(picture->data[1] + i * picture->linesize[1], 1, c->width/2, outf );
                for(i=0; i<c->height/2; i++)
                    fwrite(picture->data[2] + i * picture->linesize[2], 1, c->width/2, outf );
                frame++;
            }
            avpkt.size -= len;
            avpkt.data += len;
        }
    }

    avpkt.data = NULL;
    avpkt.size = 0;
    len = avcodec_decode_video2(c,picture, &got_picture, &avpkt);
    if(got_picture) {
        printf("saving last frame %d\n",frame);
        fflush(stdout);
        for(i=0; i<c->height; i++)
            fwrite(picture->data[0] + i * picture->linesize[0], 1, c->width, outf );
        for(i=0; i<c->height/2; i++)
            fwrite(picture->data[1] + i * picture->linesize[1], 1, c->width/2, outf );
        for(i=0; i<c->height/2; i++)
            fwrite(picture->data[2] + i * picture->linesize[2], 1, c->width/2, outf );
        frame++;
    }

    fclose(f);
    fclose(outf);

    avcodec_close(c);
    av_free(c);
    av_frame_free(&picture);
    printf("\n");
}

int main(int argc, char **argv){
    avcodec_register_all();
    video_decode("test", "trailer.264");

    return 0;
}

我也尝试了不同格式的视频(当然,我改变了代码中的编解码器),比如MPEG1,H263,H265,但它们也都不能正常工作。我希望有人能帮我解决这个问题,并告诉我哪里做错了。谢谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-01-10 07:34:11

avcodec_decode_video2的每个输入包(avpkt)应该包含一个帧的完整(且仅)数据,即它不应该在帧NAL的中间被截断。因此,以4096字节块的形式读取和发送数据的代码将无法工作。你需要自己打包,解析附件B数据,找到起始码,分析NAL类型(如果帧有超过1个切片,甚至更多),或者使用H.264的libavformat解析器。作为H.264的变通方法,你可以尝试使用CODEC_FLAG2_CHUNKS标志,但我不确定它有多可靠,仍然认为4096字节的块太小。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27870545

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档