From 454147d2692930b9eef8e8a766da32a27cf2fc08 Mon Sep 17 00:00:00 2001 From: Yeongjin Jeong Date: Fri, 28 Feb 2020 03:06:47 +0900 Subject: [PATCH] vp9parser: Add new API for parsing superframe info Some elements are using their own implementations for superframe parsing. To reduce redundant code, we need to add API to the parser. --- gst-libs/gst/codecparsers/gstvp9parser.c | 81 ++++++++++++++++++++++++ gst-libs/gst/codecparsers/gstvp9parser.h | 25 ++++++++ 2 files changed, 106 insertions(+) diff --git a/gst-libs/gst/codecparsers/gstvp9parser.c b/gst-libs/gst/codecparsers/gstvp9parser.c index 59d60ee612..33e1f0ebd4 100644 --- a/gst-libs/gst/codecparsers/gstvp9parser.c +++ b/gst-libs/gst/codecparsers/gstvp9parser.c @@ -103,6 +103,12 @@ verify_sync_code (GstBitReader * const br) return (gst_vp9_read_bits (br, 24) == GST_VP9_SYNC_CODE); } +static gboolean +verify_superframe_marker (GstBitReader * br) +{ + return gst_vp9_read_bits (br, 3) == GST_VP9_SUPERFRAME_MARKER; +} + static gboolean parse_bitdepth_colorspace_sampling (GstVp9Parser * parser, GstBitReader * const br, GstVp9FrameHdr * frame_hdr) @@ -814,3 +820,78 @@ gst_vp9_parser_parse_frame_header (GstVp9Parser * parser, error: return GST_VP9_PARSER_ERROR; } + +/** + * gst_vp9_parser_parse_superframe_info: + * @parser: The #GstVp9Parser + * @superframe_info: The #GstVp9SuperframeInfo to fill + * @data: The data to parse + * @size: The size of the @data to parse + * + * Parses the VP9 bitstream contained in @data, and fills in @superframe_info + * with the information. The @size argument represent the whole superframe size. + * If @data is not superframe but normal frame, the parser returns + * GST_VP9_PARSER_OK, frame_size[0] is set to @size and frames_in_superframe is + * set to 1. Also this method does not validate vp9frame header and verifying + * the frame header is caller's responsibility. + * + * Returns: a #GstVp9ParserResult + * + * Since: 1.18 + */ +GstVp9ParserResult +gst_vp9_parser_parse_superframe_info (GstVp9Parser * parser, + GstVp9SuperframeInfo * superframe_info, const guint8 * data, gsize size) +{ + GstBitReader header_bit_reader, index_bit_reader; + GstBitReader *hbr = &header_bit_reader, *ibr = &index_bit_reader; + guint i, j; + + g_return_val_if_fail (parser != NULL, GST_VP9_PARSER_ERROR); + g_return_val_if_fail (superframe_info != NULL, GST_VP9_PARSER_ERROR); + g_return_val_if_fail (data != NULL, GST_VP9_PARSER_ERROR); + g_return_val_if_fail (size > 0, GST_VP9_PARSER_ERROR); + + gst_bit_reader_init (hbr, data + size - 1, 1); + memset (superframe_info, 0, sizeof (GstVp9SuperframeInfo)); + + /* Parsing Superframe Data Chunk */ + + if (!verify_superframe_marker (hbr)) { + superframe_info->frame_sizes[0] = size; + superframe_info->frames_in_superframe = 1; + return GST_VP9_PARSER_OK; + } + + GST_DEBUG ("Parsing VP9 superframe, size %" G_GSIZE_FORMAT, size); + + superframe_info->bytes_per_framesize = gst_vp9_read_bits (hbr, 2) + 1; + superframe_info->frames_in_superframe = gst_vp9_read_bits (hbr, 3) + 1; + + if (superframe_info->frames_in_superframe > GST_VP9_MAX_FRAMES_IN_SUPERFRAME) + goto error; + + superframe_info->superframe_index_size = + 2 + + superframe_info->frames_in_superframe * + superframe_info->bytes_per_framesize; + + gst_bit_reader_init (ibr, + data + size - superframe_info->superframe_index_size, + superframe_info->superframe_index_size); + + /* Checking that the first byte of the superframe_index matches the final byte */ + if (gst_vp9_read_bits (ibr, 8) != data[size - 1]) + goto error; + + for (i = 0; i < superframe_info->frames_in_superframe; i++) { + for (j = 0; j < superframe_info->bytes_per_framesize; j++) + superframe_info->frame_sizes[i] |= gst_vp9_read_bits (ibr, 8) << (j * 8); + } + + return GST_VP9_PARSER_OK; + +error: + GST_ERROR ("Failed to parse superframe"); + return GST_VP9_PARSER_ERROR; +} diff --git a/gst-libs/gst/codecparsers/gstvp9parser.h b/gst-libs/gst/codecparsers/gstvp9parser.h index a437f48499..20417d9c63 100644 --- a/gst-libs/gst/codecparsers/gstvp9parser.h +++ b/gst-libs/gst/codecparsers/gstvp9parser.h @@ -37,6 +37,7 @@ G_BEGIN_DECLS #define GST_VP9_FRAME_MARKER 0x02 #define GST_VP9_SYNC_CODE 0x498342 +#define GST_VP9_SUPERFRAME_MARKER 0x06 #define GST_VP9_MAX_LOOP_FILTER 63 #define GST_VP9_MAX_PROB 255 @@ -61,6 +62,8 @@ G_BEGIN_DECLS #define GST_VP9_PREDICTION_PROBS 3 +#define GST_VP9_MAX_FRAMES_IN_SUPERFRAME 8 + typedef struct _GstVp9Parser GstVp9Parser; typedef struct _GstVp9FrameHdr GstVp9FrameHdr; typedef struct _GstVp9LoopFilter GstVp9LoopFilter; @@ -68,6 +71,7 @@ typedef struct _GstVp9QuantIndices GstVp9QuantIndices; typedef struct _GstVp9Segmentation GstVp9Segmentation; typedef struct _GstVp9SegmentationInfo GstVp9SegmentationInfo; typedef struct _GstVp9SegmentationInfoData GstVp9SegmentationInfoData; +typedef struct _GstVp9SuperframeInfo GstVp9SuperframeInfo; /** * GstVp9ParseResult: @@ -421,6 +425,24 @@ struct _GstVp9FrameHdr guint32 frame_header_length_in_bytes; }; +/** + * GstVp9SuperframeInfo: + * @bytes_per_framesize: indicates the number of bytes needed to code each frame size + * @frames_in_superframe: indicates the number of frames within this superframe + * @frame_sizes: specifies the size in bytes of frame number i (zero indexed) within this superframe + * @superframe_index_size: indicates the total size of the superframe_index + * + * Superframe info + * + * Since: 1.18 + */ +struct _GstVp9SuperframeInfo { + guint32 bytes_per_framesize; + guint32 frames_in_superframe; + guint32 frame_sizes[GST_VP9_MAX_FRAMES_IN_SUPERFRAME]; + guint32 superframe_index_size; +}; + /** * GstVp9Segmentation: * @filter_level: loop filter level @@ -489,6 +511,9 @@ GstVp9Parser * gst_vp9_parser_new (void); GST_CODEC_PARSERS_API GstVp9ParserResult gst_vp9_parser_parse_frame_header (GstVp9Parser* parser, GstVp9FrameHdr * frame_hdr, const guint8 * data, gsize size); +GST_CODEC_PARSERS_API +GstVp9ParserResult gst_vp9_parser_parse_superframe_info (GstVp9Parser* parser, GstVp9SuperframeInfo * superframe_info, const guint8 * data, gsize size); + GST_CODEC_PARSERS_API void gst_vp9_parser_free (GstVp9Parser * parser);