From patchwork Tue Mar 19 00:18:20 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Mark Thompson X-Patchwork-Id: 12348 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 05A4544786A for ; Tue, 19 Mar 2019 02:18:35 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id CD073689CF3; Tue, 19 Mar 2019 02:18:34 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wr1-f52.google.com (mail-wr1-f52.google.com [209.85.221.52]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 0A79068971C for ; Tue, 19 Mar 2019 02:18:29 +0200 (EET) Received: by mail-wr1-f52.google.com with SMTP id d17so19034720wre.10 for ; Mon, 18 Mar 2019 17:18:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=jkqxz-net.20150623.gappssmtp.com; s=20150623; h=from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=pFS1cJxXVjplczJHBWy/78rt7KaFjaFhYsQBuyIi+9I=; b=uYei9gBnw+GltA+b21q5K6LzRDDb9H9Np5elRZWbX4Fs2IVJVIv5/o6th4vaL2bY15 Bl+g/Y1vSRSGY+fcCkIbkvGBdMsRnjVaO+lSVuXNt97zmXKOmzJc5uOe6yhZFymY5j/8 TBEK34I2H0z2z+U7x1zm68Q3B0kKXA2hr0CXiiQYuari8diwnSVeRijSMKQG3ARA7jAh bVW16qq331sr9FjWMwWW2Z9qjBU8FfivKHXv4kr1Rfy0hO+wpIkG+iql+UaB1fllfUmv UhGRsHWOh4NYiSaHZU6LjA94pC2KIhFUp2MWSC9IM9rep9xjeG53pAfAK9FJdPGAvJOL UxXA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=pFS1cJxXVjplczJHBWy/78rt7KaFjaFhYsQBuyIi+9I=; b=RZxUds7Oo8uBEYJDN7RvRvVr2oLzO96N+EP5gRSyqnlem1PH0Is7A/aVAYtO+Gc7BE wXR1IlN8BRbSGOEv9PdfkKoMaQ8ePOB36AaXYqn9dlB1cI+D2uBDAovbbe7xsAte5TGH kJV42EE6UPfJPaGCK8+m/0iW10yuT2olBipBWvqmWUbgEMRr5dq1psnQdriF/Lp/xyMH vZtwWLOaKRU/LSYr3/4PSkGahLqwP1Xb1llYqhLUaeHT5UyesJKpTm/D8DEZToRg9kr2 sD2BtSoifSyPNnCdBVcMk84cfVSt5VW8TpdDASholMNMLJE5HN1XcM6223dG+hKwWmI3 7KtQ== X-Gm-Message-State: APjAAAVuH6YMrXIqgWVmleks7NwEWgXUB2DbuelQh0WPl6eceEXCRvHR UXpSFn9OQkhxrlnXuoUWpDkZZ8ipMRo= X-Google-Smtp-Source: APXvYqy/M4jrMLE1zl9o1LbFF7CcFJJal/bpmGr7SI8yRFFuiSJegxaiiC/GdODBv9ebw4N/ktav0w== X-Received: by 2002:adf:f088:: with SMTP id n8mr12086703wro.112.1552954708079; Mon, 18 Mar 2019 17:18:28 -0700 (PDT) Received: from rywe.jkqxz.net (cpc91242-cmbg18-2-0-cust650.5-4.cable.virginm.net. [82.8.130.139]) by smtp.gmail.com with ESMTPSA id j3sm44822046wrg.54.2019.03.18.17.18.26 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 18 Mar 2019 17:18:27 -0700 (PDT) From: Mark Thompson To: ffmpeg-devel@ffmpeg.org Date: Tue, 19 Mar 2019 00:18:20 +0000 Message-Id: <20190319001822.5476-1-sw@jkqxz.net> X-Mailer: git-send-email 2.19.2 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 1/3] vp9_parser: Return stream properties X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Rewrites the parser entirely, using CBS for header parsing. A new entrypoint to the CBS code is added to avoid any copy overhead. --- On 18/03/2019 03:22, Li, Zhong wrote: > If you think that case can be resolved for VP9 parser, could you please provide more details? Since all the infrastructure is already available it seemed easier to just do it than to try to explain it all needs to fit together. - Mark libavcodec/cbs_vp9.c | 62 ++++++++++++++++++++++ libavcodec/cbs_vp9.h | 12 +++++ libavcodec/vp9_parser.c | 113 +++++++++++++++++++++++++++------------- 3 files changed, 152 insertions(+), 35 deletions(-) diff --git a/libavcodec/cbs_vp9.c b/libavcodec/cbs_vp9.c index 0b5f137ed8..237416a06f 100644 --- a/libavcodec/cbs_vp9.c +++ b/libavcodec/cbs_vp9.c @@ -690,3 +690,65 @@ const CodedBitstreamType ff_cbs_type_vp9 = { .close = &cbs_vp9_close, }; + +int ff_cbs_vp9_parse_headers(CodedBitstreamContext *ctx, + VP9RawFrameHeader *header, + const uint8_t *data, size_t data_size) +{ + GetBitContext gbc; + uint8_t superframe_header; + int err; + + if (data_size < 1) + return AVERROR_INVALIDDATA; + + superframe_header = data[data_size - 1]; + if ((superframe_header & 0xe0) == 0xc0) { + VP9RawSuperframeIndex sfi; + size_t index_size, pos; + int i; + + index_size = 2 + (((superframe_header & 0x18) >> 3) + 1) * + ((superframe_header & 0x07) + 1); + if (index_size > data_size) + return AVERROR_INVALIDDATA; + + err = init_get_bits(&gbc, data + data_size - index_size, + 8 * index_size); + if (err < 0) + return err; + + err = cbs_vp9_read_superframe_index(ctx, &gbc, &sfi); + if (err < 0) + return err; + + pos = 0; + for (i = 0; i <= sfi.frames_in_superframe_minus_1; i++) { + if (pos + sfi.frame_sizes[i] + index_size > data_size) + return AVERROR_INVALIDDATA; + + err = init_get_bits(&gbc, data + pos, + 8 * sfi.frame_sizes[i]); + if (err < 0) + return err; + + memset(header, 0, sizeof(*header)); + err = cbs_vp9_read_uncompressed_header(ctx, &gbc, header); + if (err < 0) + return err; + + pos += sfi.frame_sizes[i]; + } + + } else { + err = init_get_bits(&gbc, data, 8 * data_size); + if (err < 0) + return err; + + err = cbs_vp9_read_uncompressed_header(ctx, &gbc, header); + if (err < 0) + return err; + } + + return 0; +} diff --git a/libavcodec/cbs_vp9.h b/libavcodec/cbs_vp9.h index 4c9b2f880d..0b7e8dd71b 100644 --- a/libavcodec/cbs_vp9.h +++ b/libavcodec/cbs_vp9.h @@ -214,4 +214,16 @@ typedef struct CodedBitstreamVP9Context { } CodedBitstreamVP9Context; +/** + * Entrypoint for VP9 parser. + * + * Parses headers only in a VP9 frame, and does not require refcounting. + * + * The data may contain multiple frames in a superframe; all will be parsed + * but the returned information will be for the final frame. + */ +int ff_cbs_vp9_parse_headers(CodedBitstreamContext *ctx, + VP9RawFrameHeader *header, + const uint8_t *data, size_t data_size); + #endif /* AVCODEC_CBS_VP9_H */ diff --git a/libavcodec/vp9_parser.c b/libavcodec/vp9_parser.c index c957a75667..5dd4d8d434 100644 --- a/libavcodec/vp9_parser.c +++ b/libavcodec/vp9_parser.c @@ -1,8 +1,5 @@ /* - * VP9 compatible video decoder - * - * Copyright (C) 2013 Ronald S. Bultje - * Copyright (C) 2013 Clément Bœsch + * VP9 parser * * This file is part of FFmpeg. * @@ -21,50 +18,96 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/intreadwrite.h" -#include "libavcodec/get_bits.h" +#include "libavutil/avassert.h" +#include "cbs.h" +#include "cbs_vp9.h" #include "parser.h" -static int parse(AVCodecParserContext *ctx, - AVCodecContext *avctx, - const uint8_t **out_data, int *out_size, - const uint8_t *data, int size) +typedef struct VP9ParserContext { + CodedBitstreamContext *cbc; + VP9RawFrameHeader frame_header; +} VP9ParserContext; + +static const enum AVPixelFormat vp9_pix_fmts[3][2][2] = { + { // 8-bit. + { AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV440P }, + { AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P }, + }, + { // 10-bit. + { AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV440P10 }, + { AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV420P10 }, + }, + { // 12-bit. + { AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV440P12 }, + { AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12 }, + }, +}; + +static int vp9_parser_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; + VP9ParserContext *s = ctx->priv_data; + const CodedBitstreamVP9Context *vp9 = s->cbc->priv_data; + const VP9RawFrameHeader *fh; + int err; *out_data = data; *out_size = size; - 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; - } else { - keyframe = !get_bits1(&gb); - } + if (!size) + return 0; - if (!keyframe) { - ctx->pict_type = AV_PICTURE_TYPE_P; - ctx->key_frame = 0; - } else { - ctx->pict_type = AV_PICTURE_TYPE_I; - ctx->key_frame = 1; + s->cbc->log_ctx = avctx; + + err = ff_cbs_vp9_parse_headers(s->cbc, &s->frame_header, data, size); + if (err < 0) { + av_log(avctx, AV_LOG_WARNING, "Failed to parse VP9 frame headers.\n"); + goto end; } + fh = &s->frame_header; + + avctx->profile = vp9->profile; + avctx->level = FF_LEVEL_UNKNOWN; + + ctx->width = ctx->coded_width = vp9->frame_width; + ctx->height = ctx->coded_height = vp9->frame_height; + + ctx->pict_type = fh->intra_only ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; + ctx->key_frame = !fh->frame_type; + + ctx->picture_structure = AV_PICTURE_STRUCTURE_FRAME; + + av_assert0(vp9->bit_depth == 8 || + vp9->bit_depth == 10 || + vp9->bit_depth == 12); + + ctx->format = vp9_pix_fmts[(vp9->bit_depth - 8) / 2] + [vp9->subsampling_x][vp9->subsampling_y]; + +end: + s->cbc->log_ctx = NULL; return size; } +static av_cold int vp9_parser_init(AVCodecParserContext *ctx) +{ + VP9ParserContext *s = ctx->priv_data; + return ff_cbs_init(&s->cbc, AV_CODEC_ID_VP9, NULL); +} + +static av_cold void vp9_parser_close(AVCodecParserContext *ctx) +{ + VP9ParserContext *s = ctx->priv_data; + ff_cbs_close(&s->cbc); +} + AVCodecParser ff_vp9_parser = { .codec_ids = { AV_CODEC_ID_VP9 }, - .parser_parse = parse, + .priv_data_size = sizeof(VP9ParserContext), + .parser_init = vp9_parser_init, + .parser_close = vp9_parser_close, + .parser_parse = vp9_parser_parse, };