avcodec/libvpxdec: decode to custom framebuffers for vp9
This avoids copying the full frame after decoding. Signed-off-by: Marton Balint <cus@passwd.hu> Signed-off-by: James Zern <jzern@google.com>
This commit is contained in:
		
							parent
							
								
									98aa1eb1cb
								
							
						
					
					
						commit
						5478e2cc57
					
				@ -25,6 +25,7 @@
 | 
			
		||||
 | 
			
		||||
#define VPX_CODEC_DISABLE_COMPAT 1
 | 
			
		||||
#include <vpx/vpx_decoder.h>
 | 
			
		||||
#include <vpx/vpx_frame_buffer.h>
 | 
			
		||||
#include <vpx/vp8dx.h>
 | 
			
		||||
 | 
			
		||||
#include "libavutil/common.h"
 | 
			
		||||
@ -38,9 +39,46 @@
 | 
			
		||||
typedef struct VPxDecoderContext {
 | 
			
		||||
    struct vpx_codec_ctx decoder;
 | 
			
		||||
    struct vpx_codec_ctx decoder_alpha;
 | 
			
		||||
    AVBufferPool *pool;
 | 
			
		||||
    size_t pool_size;
 | 
			
		||||
    int has_alpha_channel;
 | 
			
		||||
} VPxContext;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int get_frame_buffer(void *priv, size_t min_size, vpx_codec_frame_buffer_t *fb)
 | 
			
		||||
{
 | 
			
		||||
    VPxContext *ctx = priv;
 | 
			
		||||
    AVBufferRef *buf;
 | 
			
		||||
 | 
			
		||||
    if (min_size > ctx->pool_size) {
 | 
			
		||||
        av_buffer_pool_uninit(&ctx->pool);
 | 
			
		||||
        /* According to the libvpx docs the buffer must be zeroed out. */
 | 
			
		||||
        ctx->pool = av_buffer_pool_init(min_size, av_buffer_allocz);
 | 
			
		||||
        if (!ctx->pool) {
 | 
			
		||||
            ctx->pool_size = 0;
 | 
			
		||||
            return AVERROR(ENOMEM);
 | 
			
		||||
        }
 | 
			
		||||
        ctx->pool_size = min_size;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    buf = av_buffer_pool_get(ctx->pool);
 | 
			
		||||
    if (!buf)
 | 
			
		||||
        return AVERROR(ENOMEM);
 | 
			
		||||
 | 
			
		||||
    fb->priv = buf;
 | 
			
		||||
    fb->size = ctx->pool_size;
 | 
			
		||||
    fb->data = buf->data;
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int release_frame_buffer(void *priv, vpx_codec_frame_buffer_t *fb)
 | 
			
		||||
{
 | 
			
		||||
    AVBufferRef *buf = fb->priv;
 | 
			
		||||
    av_buffer_unref(&buf);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static av_cold int vpx_init(AVCodecContext *avctx,
 | 
			
		||||
                            struct vpx_codec_ctx* decoder,
 | 
			
		||||
                            const struct vpx_codec_iface *iface)
 | 
			
		||||
@ -59,6 +97,9 @@ static av_cold int vpx_init(AVCodecContext *avctx,
 | 
			
		||||
        return AVERROR(EINVAL);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (avctx->codec_id == AV_CODEC_ID_VP9)
 | 
			
		||||
        vpx_codec_set_frame_buffer_functions(decoder, get_frame_buffer, release_frame_buffer, avctx->priv_data);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -241,8 +282,6 @@ static int vpx_decode(AVCodecContext *avctx,
 | 
			
		||||
            if (ret < 0)
 | 
			
		||||
                return ret;
 | 
			
		||||
        }
 | 
			
		||||
        if ((ret = ff_get_buffer(avctx, picture, 0)) < 0)
 | 
			
		||||
            return ret;
 | 
			
		||||
 | 
			
		||||
        planes[0] = img->planes[VPX_PLANE_Y];
 | 
			
		||||
        planes[1] = img->planes[VPX_PLANE_U];
 | 
			
		||||
@ -254,8 +293,31 @@ static int vpx_decode(AVCodecContext *avctx,
 | 
			
		||||
        linesizes[2] = img->stride[VPX_PLANE_V];
 | 
			
		||||
        linesizes[3] =
 | 
			
		||||
            ctx->has_alpha_channel ? img_alpha->stride[VPX_PLANE_Y] : 0;
 | 
			
		||||
 | 
			
		||||
        if (img->fb_priv && (!ctx->has_alpha_channel || img_alpha->fb_priv)) {
 | 
			
		||||
            ret = ff_decode_frame_props(avctx, picture);
 | 
			
		||||
            if (ret < 0)
 | 
			
		||||
                return ret;
 | 
			
		||||
            picture->buf[0] = av_buffer_ref(img->fb_priv);
 | 
			
		||||
            if (!picture->buf[0])
 | 
			
		||||
                return AVERROR(ENOMEM);
 | 
			
		||||
            if (ctx->has_alpha_channel) {
 | 
			
		||||
                picture->buf[1] = av_buffer_ref(img_alpha->fb_priv);
 | 
			
		||||
                if (!picture->buf[1]) {
 | 
			
		||||
                    av_frame_unref(picture);
 | 
			
		||||
                    return AVERROR(ENOMEM);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            for (int i = 0; i < 4; i++) {
 | 
			
		||||
                picture->data[i] = planes[i];
 | 
			
		||||
                picture->linesize[i] = linesizes[i];
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            if ((ret = ff_get_buffer(avctx, picture, 0)) < 0)
 | 
			
		||||
                return ret;
 | 
			
		||||
            av_image_copy(picture->data, picture->linesize, (const uint8_t**)planes,
 | 
			
		||||
                          linesizes, avctx->pix_fmt, img->d_w, img->d_h);
 | 
			
		||||
        }
 | 
			
		||||
        *got_frame           = 1;
 | 
			
		||||
    }
 | 
			
		||||
    return avpkt->size;
 | 
			
		||||
@ -267,6 +329,7 @@ static av_cold int vpx_free(AVCodecContext *avctx)
 | 
			
		||||
    vpx_codec_destroy(&ctx->decoder);
 | 
			
		||||
    if (ctx->has_alpha_channel)
 | 
			
		||||
        vpx_codec_destroy(&ctx->decoder_alpha);
 | 
			
		||||
    av_buffer_pool_uninit(&ctx->pool);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -307,7 +370,7 @@ AVCodec ff_libvpx_vp9_decoder = {
 | 
			
		||||
    .init           = vp9_init,
 | 
			
		||||
    .close          = vpx_free,
 | 
			
		||||
    .decode         = vpx_decode,
 | 
			
		||||
    .capabilities   = AV_CODEC_CAP_AUTO_THREADS | AV_CODEC_CAP_DR1,
 | 
			
		||||
    .capabilities   = AV_CODEC_CAP_AUTO_THREADS,
 | 
			
		||||
    .init_static_data = ff_vp9_init_static,
 | 
			
		||||
    .profiles       = NULL_IF_CONFIG_SMALL(ff_vp9_profiles),
 | 
			
		||||
    .wrapper_name   = "libvpx",
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user