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.
This commit is contained in:
Yeongjin Jeong 2020-02-28 03:06:47 +09:00
parent 09367da35c
commit 454147d269
2 changed files with 106 additions and 0 deletions

View file

@ -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;
}

View file

@ -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);