[FFmpeg-devel] [PATCH] libavcodec/libvpx: Add VPx alpha decode support

Vignesh Venkatasubramanian vigneshv at google.com
Thu Jul 7 21:43:32 EEST 2016


VPx (VP8/VP9) alpha encoding has been part of FFmpeg. Now, add the
ability to decode such files with alpha channel.

Signed-off-by: Vignesh Venkatasubramanian <vigneshv at google.com>
---
 libavcodec/libvpxdec.c          | 111 ++++++++++++++++++++++++++++-------
 tests/fate/vpx.mak              |   3 +
 tests/ref/fate/vp8-alpha-decode | 125 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 219 insertions(+), 20 deletions(-)
 create mode 100644 tests/ref/fate/vp8-alpha-decode

diff --git a/libavcodec/libvpxdec.c b/libavcodec/libvpxdec.c
index adbc6d0..34378d8 100644
--- a/libavcodec/libvpxdec.c
+++ b/libavcodec/libvpxdec.c
@@ -29,6 +29,7 @@
 
 #include "libavutil/common.h"
 #include "libavutil/imgutils.h"
+#include "libavutil/intreadwrite.h"
 #include "avcodec.h"
 #include "internal.h"
 #include "libvpx.h"
@@ -36,12 +37,15 @@
 
 typedef struct VP8DecoderContext {
     struct vpx_codec_ctx decoder;
+    struct vpx_codec_ctx decoder_alpha;
+    int has_alpha_channel;
 } VP8Context;
 
-static av_cold int vpx_init(AVCodecContext *avctx,
-                            const struct vpx_codec_iface *iface)
+static int vpx_codec_dec_init_wrapper(AVCodecContext *avctx,
+                                      VP8Context *ctx,
+                                      const struct vpx_codec_iface *iface,
+                                      int is_alpha_decoder)
 {
-    VP8Context *ctx = avctx->priv_data;
     struct vpx_codec_dec_cfg deccfg = {
         /* token partitions+1 would be a decent choice */
         .threads = FFMIN(avctx->thread_count, 16)
@@ -50,7 +54,9 @@ static av_cold int vpx_init(AVCodecContext *avctx,
     av_log(avctx, AV_LOG_INFO, "%s\n", vpx_codec_version_str());
     av_log(avctx, AV_LOG_VERBOSE, "%s\n", vpx_codec_build_config());
 
-    if (vpx_codec_dec_init(&ctx->decoder, iface, &deccfg, 0) != VPX_CODEC_OK) {
+    if (vpx_codec_dec_init(
+            is_alpha_decoder ? &ctx->decoder_alpha : &ctx->decoder,
+            iface, &deccfg, 0) != VPX_CODEC_OK) {
         const char *error = vpx_codec_error(&ctx->decoder);
         av_log(avctx, AV_LOG_ERROR, "Failed to initialize decoder: %s\n",
                error);
@@ -60,8 +66,16 @@ static av_cold int vpx_init(AVCodecContext *avctx,
     return 0;
 }
 
+static av_cold int vpx_init(AVCodecContext *avctx,
+                            const struct vpx_codec_iface *iface)
+{
+    VP8Context *ctx = avctx->priv_data;
+    return vpx_codec_dec_init_wrapper(avctx, ctx, iface, 0);
+}
+
 // returns 0 on success, AVERROR_INVALIDDATA otherwise
-static int set_pix_fmt(AVCodecContext *avctx, struct vpx_image *img)
+static int set_pix_fmt(AVCodecContext *avctx, struct vpx_image *img,
+                       int has_alpha_channel)
 {
 #if VPX_IMAGE_ABI_VERSION >= 3
     static const enum AVColorSpace colorspaces[8] = {
@@ -82,7 +96,8 @@ static int set_pix_fmt(AVCodecContext *avctx, struct vpx_image *img)
     case VPX_IMG_FMT_I420:
         if (avctx->codec_id == AV_CODEC_ID_VP9)
             avctx->profile = FF_PROFILE_VP9_0;
-        avctx->pix_fmt = AV_PIX_FMT_YUV420P;
+        avctx->pix_fmt =
+            has_alpha_channel ? AV_PIX_FMT_YUVA420P : AV_PIX_FMT_YUV420P;
         return 0;
 #if CONFIG_LIBVPX_VP9_DECODER
     case VPX_IMG_FMT_I422:
@@ -168,29 +183,72 @@ static int set_pix_fmt(AVCodecContext *avctx, struct vpx_image *img)
     }
 }
 
+static int vpx_codec_decode_wrapper(AVCodecContext *avctx,
+                                    vpx_codec_ctx_t *decoder, uint8_t *data,
+                                    uint32_t data_sz)
+{
+    if (vpx_codec_decode(decoder, data, data_sz, NULL, 0) != VPX_CODEC_OK) {
+        const char *error  = vpx_codec_error(decoder);
+        const char *detail = vpx_codec_error_detail(decoder);
+
+        av_log(avctx, AV_LOG_ERROR, "Failed to decode frame: %s\n", error);
+        if (detail) {
+            av_log(avctx, AV_LOG_ERROR, "  Additional information: %s\n",
+                   detail);
+        }
+        return AVERROR_INVALIDDATA;
+    }
+    return 0;
+}
+
 static int vp8_decode(AVCodecContext *avctx,
                       void *data, int *got_frame, AVPacket *avpkt)
 {
     VP8Context *ctx = avctx->priv_data;
     AVFrame *picture = data;
     const void *iter = NULL;
-    struct vpx_image *img;
+    const void *iter_alpha = NULL;
+    struct vpx_image *img, *img_alpha;
     int ret;
+    uint8_t *side_data = NULL;
+    int side_data_size = 0;
 
-    if (vpx_codec_decode(&ctx->decoder, avpkt->data, avpkt->size, NULL, 0) !=
-        VPX_CODEC_OK) {
-        const char *error  = vpx_codec_error(&ctx->decoder);
-        const char *detail = vpx_codec_error_detail(&ctx->decoder);
+    ret = vpx_codec_decode_wrapper(avctx, &ctx->decoder, avpkt->data,
+                                   avpkt->size);
+    if (ret)
+        return ret;
 
-        av_log(avctx, AV_LOG_ERROR, "Failed to decode frame: %s\n", error);
-        if (detail)
-            av_log(avctx, AV_LOG_ERROR, "  Additional information: %s\n",
-                   detail);
-        return AVERROR_INVALIDDATA;
+    side_data = av_packet_get_side_data(avpkt,
+                                        AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL,
+                                        &side_data_size);
+    if (side_data_size > 1) {
+        uint64_t additional_id = AV_RB64(side_data);
+        side_data += 8;
+        side_data_size -= 8;
+        if (additional_id == 1) {  // 1 stands for alpha channel data.
+            if (!ctx->has_alpha_channel) {
+                ctx->has_alpha_channel = 1;
+                ret = vpx_codec_dec_init_wrapper(
+                    avctx, ctx,
+                    (avctx->codec_id == AV_CODEC_ID_VP8) ?
+                        &vpx_codec_vp8_dx_algo : &vpx_codec_vp9_dx_algo,
+                    1);
+                if (ret)
+                    return ret;
+            }
+            ret = vpx_codec_decode_wrapper(avctx, &ctx->decoder_alpha,
+                                           side_data, side_data_size);
+            if (ret)
+                return ret;
+        }
     }
 
-    if ((img = vpx_codec_get_frame(&ctx->decoder, &iter))) {
-        if ((ret = set_pix_fmt(avctx, img)) < 0) {
+    if ((img = vpx_codec_get_frame(&ctx->decoder, &iter)) &&
+        (!ctx->has_alpha_channel ||
+         (img_alpha = vpx_codec_get_frame(&ctx->decoder_alpha, &iter_alpha)))) {
+        uint8_t *planes[4];
+        int linesizes[4];
+        if ((ret = set_pix_fmt(avctx, img, ctx->has_alpha_channel)) < 0) {
 #ifdef VPX_IMG_FMT_HIGHBITDEPTH
             av_log(avctx, AV_LOG_ERROR, "Unsupported output colorspace (%d) / bit_depth (%d)\n",
                    img->fmt, img->bit_depth);
@@ -210,8 +268,19 @@ static int vp8_decode(AVCodecContext *avctx,
         }
         if ((ret = ff_get_buffer(avctx, picture, 0)) < 0)
             return ret;
-        av_image_copy(picture->data, picture->linesize, (const uint8_t **)img->planes,
-                      img->stride, avctx->pix_fmt, img->d_w, img->d_h);
+
+        planes[0] = img->planes[VPX_PLANE_Y];
+        planes[1] = img->planes[VPX_PLANE_U];
+        planes[2] = img->planes[VPX_PLANE_V];
+        planes[3] =
+            ctx->has_alpha_channel ? img_alpha->planes[VPX_PLANE_Y] : NULL;
+        linesizes[0] = img->stride[VPX_PLANE_Y];
+        linesizes[1] = img->stride[VPX_PLANE_U];
+        linesizes[2] = img->stride[VPX_PLANE_V];
+        linesizes[3] =
+            ctx->has_alpha_channel ? img_alpha->stride[VPX_PLANE_Y] : 0;
+        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;
@@ -221,6 +290,8 @@ static av_cold int vp8_free(AVCodecContext *avctx)
 {
     VP8Context *ctx = avctx->priv_data;
     vpx_codec_destroy(&ctx->decoder);
+    if (ctx->has_alpha_channel)
+        vpx_codec_destroy(&ctx->decoder_alpha);
     return 0;
 }
 
diff --git a/tests/fate/vpx.mak b/tests/fate/vpx.mak
index f0bcfac..b29a71a 100644
--- a/tests/fate/vpx.mak
+++ b/tests/fate/vpx.mak
@@ -31,6 +31,9 @@ fate-vp6f: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/flash-vp6/clip10
 FATE_VP8-$(call DEMDEC, FLV, VP8) += fate-vp8-alpha
 fate-vp8-alpha: CMD = framecrc -i $(TARGET_SAMPLES)/vp8_alpha/vp8_video_with_alpha.webm -vcodec copy
 
+FATE_VP8-$(call DEMDEC, FLV, VP8) += fate-vp8-alpha-decode
+fate-vp8-alpha-decode: CMD = framecrc -vcodec libvpx -i $(TARGET_SAMPLES)/vp8_alpha/vp8_video_with_alpha.webm -vcodec rawvideo -pix_fmt yuva420p -f rawvideo
+
 FATE_VP8-$(call DEMDEC, WEBM_DASH_MANIFEST, VP8) += fate-webm-dash-manifest
 fate-webm-dash-manifest: CMD = run $(FFMPEG) -f webm_dash_manifest -i $(TARGET_SAMPLES)/vp8/dash_video1.webm -f webm_dash_manifest -i $(TARGET_SAMPLES)/vp8/dash_video2.webm -f webm_dash_manifest -i $(TARGET_SAMPLES)/vp8/dash_audio1.webm -f webm_dash_manifest -i $(TARGET_SAMPLES)/vp8/dash_audio2.webm -c copy -map 0 -map 1 -map 2 -map 3 -f webm_dash_manifest -adaptation_sets "id=0,streams=0,1 id=1,streams=2,3" -
 
diff --git a/tests/ref/fate/vp8-alpha-decode b/tests/ref/fate/vp8-alpha-decode
new file mode 100644
index 0000000..40b28d2
--- /dev/null
+++ b/tests/ref/fate/vp8-alpha-decode
@@ -0,0 +1,125 @@
+#tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x213
+#sar 0: 1/1
+0,          0,          0,        1,   170560, 0x2a1293ad
+0,          1,          1,        1,   170560, 0x6c88cb4b
+0,          2,          2,        1,   170560, 0x27585dc5
+0,          3,          3,        1,   170560, 0x73cbe037
+0,          4,          4,        1,   170560, 0x4eca3cd5
+0,          5,          5,        1,   170560, 0xdfecde95
+0,          6,          6,        1,   170560, 0x38dfe631
+0,          7,          7,        1,   170560, 0xbbe546a1
+0,          8,          8,        1,   170560, 0xa78ffec3
+0,          9,          9,        1,   170560, 0x917923f7
+0,         10,         10,        1,   170560, 0x82927437
+0,         11,         11,        1,   170560, 0xe1bfa664
+0,         12,         12,        1,   170560, 0x1091e069
+0,         13,         13,        1,   170560, 0x96551722
+0,         14,         14,        1,   170560, 0x9a952c31
+0,         15,         15,        1,   170560, 0xb2e34dff
+0,         16,         16,        1,   170560, 0x09f77a76
+0,         17,         17,        1,   170560, 0xf6f5a3de
+0,         18,         18,        1,   170560, 0x6453bd09
+0,         19,         19,        1,   170560, 0x7d64c755
+0,         20,         20,        1,   170560, 0x1e11c29d
+0,         21,         21,        1,   170560, 0x57dca8ba
+0,         22,         22,        1,   170560, 0x594d982a
+0,         23,         23,        1,   170560, 0xd2017b7d
+0,         24,         24,        1,   170560, 0x46af60e2
+0,         25,         25,        1,   170560, 0x186b60bd
+0,         26,         26,        1,   170560, 0x9bd96210
+0,         27,         27,        1,   170560, 0x6efb7e78
+0,         28,         28,        1,   170560, 0xd0219673
+0,         29,         29,        1,   170560, 0x81bfc1c7
+0,         30,         30,        1,   170560, 0x61a30393
+0,         31,         31,        1,   170560, 0x6cfc30e0
+0,         32,         32,        1,   170560, 0x820557d8
+0,         33,         33,        1,   170560, 0xa4f88301
+0,         34,         34,        1,   170560, 0x072fb542
+0,         35,         35,        1,   170560, 0x8d3cd908
+0,         36,         36,        1,   170560, 0x776be292
+0,         37,         37,        1,   170560, 0x2074ca19
+0,         38,         38,        1,   170560, 0x3f5d8ab8
+0,         39,         39,        1,   170560, 0x393425b3
+0,         40,         40,        1,   170560, 0x8332948c
+0,         41,         41,        1,   170560, 0x151df7b7
+0,         42,         42,        1,   170560, 0xd8e64eb2
+0,         43,         43,        1,   170560, 0xa3512c1c
+0,         44,         44,        1,   170560, 0x27a15536
+0,         45,         45,        1,   170560, 0x2579d29a
+0,         46,         46,        1,   170560, 0x75524551
+0,         47,         47,        1,   170560, 0xc7236dbd
+0,         48,         48,        1,   170560, 0xbf2f7f6f
+0,         49,         49,        1,   170560, 0xaad98788
+0,         50,         50,        1,   170560, 0xf5ab997a
+0,         51,         51,        1,   170560, 0x153e84ef
+0,         52,         52,        1,   170560, 0x79ed8200
+0,         53,         53,        1,   170560, 0x524474a3
+0,         54,         54,        1,   170560, 0x3602695d
+0,         55,         55,        1,   170560, 0x13cd63cd
+0,         56,         56,        1,   170560, 0xdfba6dac
+0,         57,         57,        1,   170560, 0x8b319424
+0,         58,         58,        1,   170560, 0x43b49c67
+0,         59,         59,        1,   170560, 0x2107c194
+0,         60,         60,        1,   170560, 0x5ecb22f3
+0,         61,         61,        1,   170560, 0x1ddb4a99
+0,         62,         62,        1,   170560, 0xc5ac63ed
+0,         63,         63,        1,   170560, 0x3db28c93
+0,         64,         64,        1,   170560, 0x6b98a419
+0,         65,         65,        1,   170560, 0x17deae77
+0,         66,         66,        1,   170560, 0x3bcfb34e
+0,         67,         67,        1,   170560, 0x6f6cb81b
+0,         68,         68,        1,   170560, 0x0655e03b
+0,         69,         69,        1,   170560, 0xde7d06a1
+0,         70,         70,        1,   170560, 0x8e51535c
+0,         71,         71,        1,   170560, 0xea256867
+0,         72,         72,        1,   170560, 0xc08c4fdd
+0,         73,         73,        1,   170560, 0xe30b4791
+0,         74,         74,        1,   170560, 0x981b9218
+0,         75,         75,        1,   170560, 0x29d34848
+0,         76,         76,        1,   170560, 0xafc0000c
+0,         77,         77,        1,   170560, 0x18b477fb
+0,         78,         78,        1,   170560, 0x7f4ac3e3
+0,         79,         79,        1,   170560, 0xc653fcb9
+0,         80,         80,        1,   170560, 0x1bef5046
+0,         81,         81,        1,   170560, 0x34b28216
+0,         82,         82,        1,   170560, 0x2b75c377
+0,         83,         83,        1,   170560, 0x014b226b
+0,         84,         84,        1,   170560, 0x8a964e61
+0,         85,         85,        1,   170560, 0xe49880a4
+0,         86,         86,        1,   170560, 0x4472cbd1
+0,         87,         87,        1,   170560, 0xe56a20f8
+0,         88,         88,        1,   170560, 0x0ab3653f
+0,         89,         89,        1,   170560, 0xadc89f74
+0,         90,         90,        1,   170560, 0xe36dfdaf
+0,         91,         91,        1,   170560, 0xe2514944
+0,         92,         92,        1,   170560, 0xc4eb9ac9
+0,         93,         93,        1,   170560, 0xfde3ec34
+0,         94,         94,        1,   170560, 0x4a1c4a02
+0,         95,         95,        1,   170560, 0xd803acee
+0,         96,         96,        1,   170560, 0x4f8809cc
+0,         97,         97,        1,   170560, 0x566b6b45
+0,         98,         98,        1,   170560, 0x8bd2bc6a
+0,         99,         99,        1,   170560, 0xa509ec67
+0,        100,        100,        1,   170560, 0xeed1fe6d
+0,        101,        101,        1,   170560, 0xa8fe0bef
+0,        102,        102,        1,   170560, 0x909c0af9
+0,        103,        103,        1,   170560, 0xc8f5f598
+0,        104,        104,        1,   170560, 0x3e93c2e3
+0,        105,        105,        1,   170560, 0xa0c275b6
+0,        106,        106,        1,   170560, 0x93085bc0
+0,        107,        107,        1,   170560, 0x7fd646b1
+0,        108,        108,        1,   170560, 0x67a24d63
+0,        109,        109,        1,   170560, 0x184b79f1
+0,        110,        110,        1,   170560, 0x979cc32f
+0,        111,        111,        1,   170560, 0xdc0a064f
+0,        112,        112,        1,   170560, 0xabf94c6f
+0,        113,        113,        1,   170560, 0x614d6043
+0,        114,        114,        1,   170560, 0x4a963b04
+0,        115,        115,        1,   170560, 0x06290370
+0,        116,        116,        1,   170560, 0xb68ccf53
+0,        117,        117,        1,   170560, 0x9e379142
+0,        118,        118,        1,   170560, 0x09a561af
+0,        119,        119,        1,   170560, 0xf0fb1e9a
-- 
2.8.0.rc3.226.g39d4020



More information about the ffmpeg-devel mailing list