Kindermann
Kindermann

Reputation: 443

H264 decoding using ffmpeg

I'm trying to decode a video stream with ffmpeg library, that's how I do it basically:

void video_decode(const char *filename)
{
    AVCodec *codec;
    AVCodecContext *c= NULL;
    int frame_count=0;
    FILE *f;
    AVFrame *frame;
    uint8_t inbuf[INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
    AVPacket avpkt;
    av_init_packet(&avpkt);
    memset(inbuf + INBUF_SIZE, 0, AV_INPUT_BUFFER_PADDING_SIZE);
    printf("Decoding video file...\n");
    /* find the h264 video decoder */
    codec = avcodec_find_decoder(AV_CODEC_ID_H264);
    c = avcodec_alloc_context3(codec);
    c->bit_rate = 400000;
    c->width = 1920;
    c->height = 1080;

    if (avcodec_open2(c, codec, NULL) < 0) {
        fprintf(stderr, "Could not open codec\n");
        exit(1);
    }
    frame = av_frame_alloc();
    for (;;) {
        avpkt.size = fread(inbuf, 1, INBUF_SIZE, f);         
    if (avpkt.size == 0)
            break;
        avpkt.data = inbuf;
        while(avpkt.size > 0){

        int len, got_frame;
            len = avcodec_decode_video2(c, frame, &got_frame, &avpkt);          
        if (len < 0) {
                fprintf(stderr, "Errr while decding frame %d\n", frame_count);
                exit (1);
            }
            if (got_frame) {
                //Print out frame information..
        }
            if (avpkt.data) {
                avpkt.size -= len;
                avpkt.data += len;
            }
    }               
    }  
}

But I got the following outputs:

Decoding video file...
[h264 @ 0x303c040] decode_slice_header error
[h264 @ 0x303c040] decode_slice_header error
[h264 @ 0x303c040] decode_slice_header error
[h264 @ 0x303c040] no frame!
Errr while decding frame 0

Obviously the initiation of codec was incomplete. Do you have experience with h264 api? Any help would be appreciated.

Upvotes: 1

Views: 14377

Answers (3)

paint on the Water
paint on the Water

Reputation: 1

may be you should try to use AVCODECPARSER between your fread() and avcodec_decode_video2(); av_parser_parse2(). make your rawdata change into h264 fromat data to feed your decoder. C code like this :

#
while (1)
{
    cur_size = fread(in_buffer, 1, in_buffer_size, fp_in);
    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;

        ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, &packet);  
        if (ret < 0)
        {
            printf("Decode Error\n");
            return ret;
        }
        if (got_picture)
        {
            printf("Succeed to decode 1 frame!\n");
        }
    }

inspired by this : https://blog.csdn.net/leixiaohua1020/article/details/42181571

Upvotes: 0

Sunny Shukla
Sunny Shukla

Reputation: 565

The answer to this question is given under demuxing_decoding.c example of ffmpeg.

One can compile this file independently as below, if your ffmpeg installation directory is default "usr/local/".

gcc -I/usr/local/include  -c demuxing_decoding.c -o demuxing_decoding.o
gcc demuxing_decoding.o -pthread -L/usr/local/lib -lavdevice -lavfilter -lpostproc -lavformat -lavcodec -lva-x11 -lva -lxcb-xfixes -lxcb-render -lxcb-shape -lxcb -lX11 -lx264 -lpthread -ldl -lz -lswresample -lswscale -lavutil -lm  -o demuxing_decoding

In case, if the installation directory is changed to say something like "ffmpeg_ins_dir" replace "usr/local/" in above commands with "path upto ffmpef_ins_dir/".

Run the binary as below.

./demuxing_decoding test.h264 v_out.yuv a_out.yuv

Note : This example has many things you may not need at all, remove things that isn't needed and recompile it again.

Upvotes: 0

szatmary
szatmary

Reputation: 31101

You cant just put a random number (INBUF_SIZE ) of bytes into an AV packet. It should be a full AU or NALU, and if it is not annex B, you must first set the extra data field. For your case, I would recommend use libavformat to open the file and read the AVPackets.

Upvotes: 3

Related Questions