FFMPEG: While decoding video, is possible to generate result to user's provided buffer?

后端 未结 1 1293
轻奢々
轻奢々 2021-01-03 03:03

In ffmpeg decoding video scenario, H264 for example, typically we allocate an AVFrame and decode the compressed data, then we get the result fr

相关标签:
1条回答
  • 2021-01-03 03:45

    I found the way out.

    There is a public member of AVCodecContext, get_buffer2, which is a callback function. While calling avcodec_decode_video2, this callback function will be invoked, and this callback function is responsible to delegate buffers and some informations to AVFrame, then avcodec_decode_video2 generate the result to the buffers of AVFrame.

    The callback function, get_buffer2, is set avcodec_default_get_buffer2 as default. However, we can override this as our privided function. For example:

    void our_buffer_default_free(void *opaque, uint8_t *data)
    {
        // empty
    }
    int our_get_buffer(struct AVCodecContext *c, AVFrame *pic, int flags)
    {
        assert(c->codec_type == AVMEDIA_TYPE_VIDEO);
        pic->data[0] = lrY.pBits;
        pic->data[1] = lrU.pBits;
        pic->data[2] = lrV.pBits;
        picture->linesize[0] = lrY.Pitch;
        picture->linesize[1] = lrU.Pitch;
        picture->linesize[2] = lrV.Pitch;
        pic->buf[0] = av_buffer_create(pic->data[0], pic->linesize[0] * pic->height, our_buffer_default_free, NULL, 0);
        pic->buf[1] = av_buffer_create(pic->data[1], pic->linesize[1] * pic->height / 2, our_buffer_default_free, NULL, 0);
        pic->buf[2] = av_buffer_create(pic->data[2], pic->linesize[2] * pic->height / 2, our_buffer_default_free, NULL, 0);
        return 0;
    }
    

    Before decoding, we override the callback function:

    context->get_buffer2 = our_get_buffer;
    

    Then avcodec_decode_video2 will generate the result to our provided buffers.

    By the way, for C++ programs which often implementing these processes in classes, we can record this pointer first:

    context->opaque = this;
    

    And define the overridden callback function as static member:

    static int myclass::my_get_buffer(struct AVCodecContext *c, AVFrame *pic, int flags)
    {
        auto this_pointer = static_cast<decode_context*>(c->opaque);
        return this_pointer->my_get_buffer_real(c, pic, flags);
    }
    int myclass::my_get_buffer_real(struct AVCodecContext *c, AVFrame *pic, int flags)
    {
        // ditto with above our_get_buffer.
        // ...
    }
    
    0 讨论(0)
提交回复
热议问题