aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDeb Mukherjee <debargha@google.com>2014-09-14 07:43:27 -0700
committerMichael Niedermayer <michaelni@gmx.at>2014-09-14 20:27:28 +0200
commit04b0dda853198980a14158809e560ea9ca9d7e33 (patch)
tree58a6ed62d757e1f6126294b01d7b048698c697e3
parentb24d74e44ae5fecba51d79cd0d0a1d1dffcaf771 (diff)
downloadffmpeg-04b0dda853198980a14158809e560ea9ca9d7e33.tar.gz
avcodec/libvpxdec: Adds decode support for formats other than 420
Handles decoding of new VP9 profiles 1-3 with different color sampling and bit-depths. For high bitdepth (profiles 2 and 3) support, we currently need to link with the highbitdepth branch of libvpx with --enable-experimental and --enable-vp9-high config options on. But eventually this branch will be merged into master, whereafter to enable high bitdepth support you will need to link with libvpx with configure option --enable-vp9-highbitdepth on. Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r--libavcodec/libvpxdec.c64
1 files changed, 60 insertions, 4 deletions
diff --git a/libavcodec/libvpxdec.c b/libavcodec/libvpxdec.c
index 94e1e4d1ef..8312460f53 100644
--- a/libavcodec/libvpxdec.c
+++ b/libavcodec/libvpxdec.c
@@ -60,6 +60,57 @@ static av_cold int vpx_init(AVCodecContext *avctx,
return 0;
}
+// returns 0 on success, AVERROR_INVALIDDATA otherwise
+static int set_pix_fmt(AVCodecContext *avctx, struct vpx_image *img) {
+ if (avctx->codec_id == AV_CODEC_ID_VP8 && img->fmt != VPX_IMG_FMT_I420)
+ return AVERROR_INVALIDDATA;
+ switch (img->fmt) {
+ case VPX_IMG_FMT_I420:
+ avctx->pix_fmt = AV_PIX_FMT_YUV420P;
+ return 0;
+ case VPX_IMG_FMT_I422:
+ avctx->pix_fmt = AV_PIX_FMT_YUV422P;
+ return 0;
+ case VPX_IMG_FMT_I444:
+ avctx->pix_fmt = AV_PIX_FMT_YUV444P;
+ return 0;
+#ifdef VPX_IMG_FMT_HIGHBITDEPTH
+ case VPX_IMG_FMT_I42016:
+ if (img->bit_depth == 10) {
+ avctx->pix_fmt = AV_PIX_FMT_YUV420P10LE;
+ return 0;
+ } else if (img->bit_depth == 12) {
+ avctx->pix_fmt = AV_PIX_FMT_YUV420P12LE;
+ return 0;
+ } else {
+ return AVERROR_INVALIDDATA;
+ }
+ case VPX_IMG_FMT_I42216:
+ if (img->bit_depth == 10) {
+ avctx->pix_fmt = AV_PIX_FMT_YUV422P10LE;
+ return 0;
+ } else if (img->bit_depth == 12) {
+ avctx->pix_fmt = AV_PIX_FMT_YUV422P12LE;
+ return 0;
+ } else {
+ return AVERROR_INVALIDDATA;
+ }
+ case VPX_IMG_FMT_I44416:
+ if (img->bit_depth == 10) {
+ avctx->pix_fmt = AV_PIX_FMT_YUV444P10LE;
+ return 0;
+ } else if (img->bit_depth == 12) {
+ avctx->pix_fmt = AV_PIX_FMT_YUV444P12LE;
+ return 0;
+ } else {
+ return AVERROR_INVALIDDATA;
+ }
+#endif
+ default:
+ return AVERROR_INVALIDDATA;
+ }
+}
+
static int vp8_decode(AVCodecContext *avctx,
void *data, int *got_frame, AVPacket *avpkt)
{
@@ -82,10 +133,15 @@ static int vp8_decode(AVCodecContext *avctx,
}
if ((img = vpx_codec_get_frame(&ctx->decoder, &iter))) {
- if (img->fmt != VPX_IMG_FMT_I420) {
- av_log(avctx, AV_LOG_ERROR, "Unsupported output colorspace (%d)\n",
- img->fmt);
- return AVERROR_INVALIDDATA;
+ if ((ret = set_pix_fmt(avctx, img)) < 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);
+#else
+ av_log(avctx, AV_LOG_ERROR, "Unsupported output colorspace (%d) / bit_depth (%d)\n",
+ img->fmt, 8);
+#endif
+ return ret;
}
if ((int) img->d_w != avctx->width || (int) img->d_h != avctx->height) {