[FFmpeg-devel] [PATCH] avcodec/vp9_parser: export profile and pixel format
James Almer
jamrial at gmail.com
Wed Oct 3 20:49:21 EEST 2018
Signed-off-by: James Almer <jamrial at gmail.com>
---
libavcodec/vp9_parser.c | 82 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 80 insertions(+), 2 deletions(-)
diff --git a/libavcodec/vp9_parser.c b/libavcodec/vp9_parser.c
index 9531f34a32..d4110f20bf 100644
--- a/libavcodec/vp9_parser.c
+++ b/libavcodec/vp9_parser.c
@@ -23,36 +23,114 @@
#include "libavutil/intreadwrite.h"
#include "libavcodec/get_bits.h"
+#include "libavcodec/internal.h"
#include "parser.h"
+#define VP9_SYNCCODE 0x498342
+
+static int read_colorspace_details(AVCodecParserContext *ctx, AVCodecContext *avctx,
+ GetBitContext *gb)
+{
+ static const enum AVColorSpace colorspaces[8] = {
+ AVCOL_SPC_UNSPECIFIED, AVCOL_SPC_BT470BG, AVCOL_SPC_BT709, AVCOL_SPC_SMPTE170M,
+ AVCOL_SPC_SMPTE240M, AVCOL_SPC_BT2020_NCL, AVCOL_SPC_RESERVED, AVCOL_SPC_RGB,
+ };
+ int colorspace, bits = avctx->profile <= 1 ? 0 : 1 + get_bits1(gb); // 0:8, 1:10, 2:12
+
+ colorspace = colorspaces[get_bits(gb, 3)];
+ if (colorspace == AVCOL_SPC_RGB) { // RGB = profile 1
+ static const enum AVPixelFormat pix_fmt_rgb[3] = {
+ AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12
+ };
+ if (avctx->profile & 1) {
+ if (get_bits1(gb)) // reserved bit
+ return AVERROR_INVALIDDATA;
+ } else
+ return AVERROR_INVALIDDATA;
+ ctx->format = pix_fmt_rgb[bits];
+ } else {
+ static const enum AVPixelFormat pix_fmt_for_ss[3][2 /* v */][2 /* h */] = {
+ { { AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV422P },
+ { AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV420P } },
+ { { AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV422P10 },
+ { AV_PIX_FMT_YUV440P10, AV_PIX_FMT_YUV420P10 } },
+ { { AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12 },
+ { AV_PIX_FMT_YUV440P12, AV_PIX_FMT_YUV420P12 } }
+ };
+ if (avctx->profile & 1) {
+ int ss_h, ss_v, format;
+
+ ss_h = get_bits1(gb);
+ ss_v = get_bits1(gb);
+ format = pix_fmt_for_ss[bits][ss_v][ss_h];
+ if (format == AV_PIX_FMT_YUV420P)
+ // YUV 4:2:0 not supported in profiles 1 and 3
+ return AVERROR_INVALIDDATA;
+ else if (get_bits1(gb)) // color details reserved bit
+ return AVERROR_INVALIDDATA;
+ ctx->format = format;
+ } else {
+ ctx->format = pix_fmt_for_ss[bits][1][1];
+ }
+ }
+
+ return 0;
+}
+
static int parse(AVCodecParserContext *ctx,
AVCodecContext *avctx,
const uint8_t **out_data, int *out_size,
const uint8_t *data, int size)
{
GetBitContext gb;
- int res, profile, keyframe;
+ int res, profile, keyframe, invisible, errorres;
*out_data = data;
*out_size = size;
- if ((res = init_get_bits8(&gb, data, size)) < 0)
+ if (!size || (res = init_get_bits8(&gb, data, size)) < 0)
return size; // parsers can't return errors
get_bits(&gb, 2); // frame marker
profile = get_bits1(&gb);
profile |= get_bits1(&gb) << 1;
if (profile == 3) profile += get_bits1(&gb);
+ if (profile > 3)
+ return size;
+ avctx->profile = profile;
if (get_bits1(&gb)) {
keyframe = 0;
+ skip_bits(&gb, 3);
} else {
keyframe = !get_bits1(&gb);
}
+ invisible = !get_bits1(&gb);
+ errorres = get_bits1(&gb);
+
if (!keyframe) {
+ int intraonly = invisible ? get_bits1(&gb) : 0;
+ if (!errorres)
+ skip_bits(&gb, 2);
+ if (intraonly) {
+ if (get_bits_long(&gb, 24) != VP9_SYNCCODE) // synccode
+ return size;
+ if (profile >= 1) {
+ if ((read_colorspace_details(ctx, avctx, &gb)) < 0)
+ return size;
+ } else {
+ ctx->format = AV_PIX_FMT_YUV420P;
+ }
+ }
+
ctx->pict_type = AV_PICTURE_TYPE_P;
ctx->key_frame = 0;
} else {
+ if (get_bits_long(&gb, 24) != VP9_SYNCCODE) // synccode
+ return size;
+ if (read_colorspace_details(ctx, avctx, &gb) < 0)
+ return size;
+
ctx->pict_type = AV_PICTURE_TYPE_I;
ctx->key_frame = 1;
}
--
2.19.0
More information about the ffmpeg-devel
mailing list