mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-22 09:41:07 +00:00
h265parser: Add an API for HEVCDecoderConfigurationRecord parsing
Add a method for HEVC configuration data parsing Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2759>
This commit is contained in:
parent
89a6ce105b
commit
5227b3c9a6
3 changed files with 678 additions and 0 deletions
|
@ -4741,3 +4741,294 @@ gst_h265_get_profile_from_sps (GstH265SPS * sps)
|
|||
/* first profile of the synthetic ptl */
|
||||
return gst_h265_profile_tier_level_get_profile (&tmp_ptl);
|
||||
}
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
static void
|
||||
gst_clear_h265_decoder_config_record_nalu_array (
|
||||
GstH265DecoderConfigRecordNalUnitArray * array)
|
||||
{
|
||||
if (!array)
|
||||
return;
|
||||
|
||||
if (array->nalu)
|
||||
g_array_unref (array->nalu);
|
||||
}
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/**
|
||||
* gst_h265_decoder_config_record_free:
|
||||
* @config: (nullable): a #GstH265DecoderConfigRecord data
|
||||
*
|
||||
* Free @config data
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
void
|
||||
gst_h265_decoder_config_record_free (GstH265DecoderConfigRecord * config)
|
||||
{
|
||||
if (!config)
|
||||
return;
|
||||
|
||||
if (config->nalu_array)
|
||||
g_array_unref (config->nalu_array);
|
||||
|
||||
g_free (config);
|
||||
}
|
||||
|
||||
static GstH265DecoderConfigRecord *
|
||||
gst_h265_decoder_config_record_new (void)
|
||||
{
|
||||
GstH265DecoderConfigRecord *config;
|
||||
|
||||
config = g_new0 (GstH265DecoderConfigRecord, 1);
|
||||
config->nalu_array = g_array_new (FALSE,
|
||||
FALSE, sizeof (GstH265DecoderConfigRecordNalUnitArray));
|
||||
g_array_set_clear_func (config->nalu_array,
|
||||
(GDestroyNotify) gst_clear_h265_decoder_config_record_nalu_array);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_h265_parser_parse_decoder_config_record:
|
||||
* @parser: a #GstH265Parser
|
||||
* @data: the data to parse
|
||||
* @size: the size of @data
|
||||
* @config: (out): parsed #GstH265DecoderConfigRecord data
|
||||
*
|
||||
* Parses HEVCDecoderConfigurationRecord data and fill into @config.
|
||||
* The caller must free @config via gst_h265_decoder_config_record_free()
|
||||
*
|
||||
* This method does not parse VPS, SPS and PPS and therefore the caller needs to
|
||||
* parse each NAL unit via appropriate parsing method.
|
||||
*
|
||||
* Returns: a #GstH265ParserResult
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
GstH265ParserResult
|
||||
gst_h265_parser_parse_decoder_config_record (GstH265Parser * parser,
|
||||
const guint8 * data, gsize size, GstH265DecoderConfigRecord ** config)
|
||||
{
|
||||
GstH265DecoderConfigRecord *ret;
|
||||
GstBitReader br;
|
||||
GstH265ParserResult result = GST_H265_PARSER_OK;
|
||||
guint i;
|
||||
guint8 num_of_arrays;
|
||||
|
||||
g_return_val_if_fail (parser != NULL, GST_H265_PARSER_ERROR);
|
||||
g_return_val_if_fail (data != NULL, GST_H265_PARSER_ERROR);
|
||||
g_return_val_if_fail (config != NULL, GST_H265_PARSER_ERROR);
|
||||
|
||||
#define READ_CONFIG_UINT8(val, nbits) G_STMT_START { \
|
||||
if (!gst_bit_reader_get_bits_uint8 (&br, (guint8 *) &val, nbits)) { \
|
||||
GST_WARNING ("Failed to read " G_STRINGIFY (val)); \
|
||||
result = GST_H265_PARSER_ERROR; \
|
||||
goto error; \
|
||||
} \
|
||||
} G_STMT_END;
|
||||
|
||||
#define READ_CONFIG_UINT16(val, nbits) G_STMT_START { \
|
||||
if (!gst_bit_reader_get_bits_uint16 (&br, &val, nbits)) { \
|
||||
GST_WARNING ("Failed to read " G_STRINGIFY (val)); \
|
||||
result = GST_H265_PARSER_ERROR; \
|
||||
goto error; \
|
||||
} \
|
||||
} G_STMT_END;
|
||||
|
||||
#define SKIP_CONFIG_BITS(nbits) G_STMT_START { \
|
||||
if (!gst_bit_reader_skip (&br, nbits)) { \
|
||||
GST_WARNING ("Failed to skip %d bits", nbits); \
|
||||
result = GST_H265_PARSER_ERROR; \
|
||||
goto error; \
|
||||
} \
|
||||
} G_STMT_END;
|
||||
|
||||
*config = NULL;
|
||||
|
||||
if (size < 23) {
|
||||
GST_WARNING ("Too small size hvcC");
|
||||
return GST_H265_PARSER_ERROR;
|
||||
}
|
||||
|
||||
gst_bit_reader_init (&br, data, size);
|
||||
|
||||
ret = gst_h265_decoder_config_record_new ();
|
||||
|
||||
READ_CONFIG_UINT8 (ret->configuration_version, 8);
|
||||
if (ret->configuration_version != 1) {
|
||||
GST_WARNING ("Wrong configurationVersion %d", ret->configuration_version);
|
||||
/* Must be 1 but allows 0 for backward compatibility.
|
||||
* See commit
|
||||
* https://gitlab.freedesktop.org/gstreamer/gstreamer/-/commit/63fee31a3f95021fa0bb2429c723f5356c9b3c4b */
|
||||
if (ret->configuration_version != 0) {
|
||||
result = GST_H265_PARSER_ERROR;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
READ_CONFIG_UINT8 (ret->general_profile_space, 2);
|
||||
READ_CONFIG_UINT8 (ret->general_tier_flag, 1);
|
||||
READ_CONFIG_UINT8 (ret->general_profile_idc, 5);
|
||||
|
||||
for (i = 0; i < 32; i++)
|
||||
READ_CONFIG_UINT8 (ret->general_profile_compatibility_flags[i], 1);
|
||||
|
||||
/* 7.3.3 Profile, tier and level syntax */
|
||||
READ_CONFIG_UINT8 (ret->general_progressive_source_flag, 1);
|
||||
READ_CONFIG_UINT8 (ret->general_interlaced_source_flag, 1);
|
||||
READ_CONFIG_UINT8 (ret->general_non_packed_constraint_flag, 1);
|
||||
READ_CONFIG_UINT8 (ret->general_frame_only_constraint_flag, 1);
|
||||
|
||||
if (ret->general_profile_idc == 4 ||
|
||||
ret->general_profile_compatibility_flags[4] ||
|
||||
ret->general_profile_idc == 5 ||
|
||||
ret->general_profile_compatibility_flags[5] ||
|
||||
ret->general_profile_idc == 6 ||
|
||||
ret->general_profile_compatibility_flags[6] ||
|
||||
ret->general_profile_idc == 7 ||
|
||||
ret->general_profile_compatibility_flags[7] ||
|
||||
ret->general_profile_idc == 8 ||
|
||||
ret->general_profile_compatibility_flags[8] ||
|
||||
ret->general_profile_idc == 9 ||
|
||||
ret->general_profile_compatibility_flags[9] ||
|
||||
ret->general_profile_idc == 10 ||
|
||||
ret->general_profile_compatibility_flags[10] ||
|
||||
ret->general_profile_idc == 11 ||
|
||||
ret->general_profile_compatibility_flags[11]) {
|
||||
READ_CONFIG_UINT8 (ret->general_max_12bit_constraint_flag, 1);
|
||||
READ_CONFIG_UINT8 (ret->general_max_10bit_constraint_flag, 1);
|
||||
READ_CONFIG_UINT8 (ret->general_max_8bit_constraint_flag, 1);
|
||||
READ_CONFIG_UINT8 (ret->general_max_422chroma_constraint_flag, 1);
|
||||
READ_CONFIG_UINT8 (ret->general_max_420chroma_constraint_flag, 1);
|
||||
READ_CONFIG_UINT8 (ret->general_max_monochrome_constraint_flag, 1);
|
||||
READ_CONFIG_UINT8 (ret->general_intra_constraint_flag, 1);
|
||||
READ_CONFIG_UINT8 (ret->general_one_picture_only_constraint_flag, 1);
|
||||
READ_CONFIG_UINT8 (ret->general_lower_bit_rate_constraint_flag, 1);
|
||||
|
||||
if (ret->general_profile_idc == 5 ||
|
||||
ret->general_profile_compatibility_flags[5] ||
|
||||
ret->general_profile_idc == 9 ||
|
||||
ret->general_profile_compatibility_flags[9] ||
|
||||
ret->general_profile_idc == 10 ||
|
||||
ret->general_profile_compatibility_flags[10] ||
|
||||
ret->general_profile_idc == 11 ||
|
||||
ret->general_profile_compatibility_flags[11]) {
|
||||
READ_CONFIG_UINT8 (ret->general_max_14bit_constraint_flag, 1);
|
||||
SKIP_CONFIG_BITS (33);
|
||||
} else {
|
||||
SKIP_CONFIG_BITS (34);
|
||||
}
|
||||
} else if (ret->general_profile_idc == 2 ||
|
||||
ret->general_profile_compatibility_flags[2]) {
|
||||
SKIP_CONFIG_BITS (7);
|
||||
READ_CONFIG_UINT8 (ret->general_one_picture_only_constraint_flag, 1);
|
||||
|
||||
SKIP_CONFIG_BITS (35);
|
||||
} else {
|
||||
SKIP_CONFIG_BITS (43);
|
||||
}
|
||||
|
||||
if (ret->general_profile_idc == 1 ||
|
||||
ret->general_profile_compatibility_flags[1] ||
|
||||
ret->general_profile_idc == 2 ||
|
||||
ret->general_profile_compatibility_flags[2] ||
|
||||
ret->general_profile_idc == 3 ||
|
||||
ret->general_profile_compatibility_flags[3] ||
|
||||
ret->general_profile_idc == 4 ||
|
||||
ret->general_profile_compatibility_flags[4] ||
|
||||
ret->general_profile_idc == 5 ||
|
||||
ret->general_profile_compatibility_flags[5] ||
|
||||
ret->general_profile_idc == 9 ||
|
||||
ret->general_profile_compatibility_flags[9] ||
|
||||
ret->general_profile_idc == 11 ||
|
||||
ret->general_profile_compatibility_flags[11]) {
|
||||
READ_CONFIG_UINT8 (ret->general_inbld_flag, 1);
|
||||
} else {
|
||||
SKIP_CONFIG_BITS (1);
|
||||
}
|
||||
|
||||
g_assert (gst_bit_reader_get_pos (&br) == 12 * 8);
|
||||
|
||||
READ_CONFIG_UINT8 (ret->general_level_idc, 8);
|
||||
|
||||
SKIP_CONFIG_BITS (4);
|
||||
READ_CONFIG_UINT16 (ret->min_spatial_segmentation_idc, 12);
|
||||
|
||||
SKIP_CONFIG_BITS (6);
|
||||
READ_CONFIG_UINT8 (ret->parallelism_type, 2);
|
||||
|
||||
SKIP_CONFIG_BITS (6);
|
||||
READ_CONFIG_UINT8 (ret->chroma_format_idc, 2);
|
||||
|
||||
SKIP_CONFIG_BITS (5);
|
||||
READ_CONFIG_UINT8 (ret->bit_depth_luma_minus8, 3);
|
||||
|
||||
SKIP_CONFIG_BITS (5);
|
||||
READ_CONFIG_UINT8 (ret->bit_depth_chroma_minus8, 3);
|
||||
|
||||
READ_CONFIG_UINT16 (ret->avg_frame_rate, 16);
|
||||
|
||||
READ_CONFIG_UINT8 (ret->constant_frame_rate, 2);
|
||||
READ_CONFIG_UINT8 (ret->num_temporal_layers, 3);
|
||||
READ_CONFIG_UINT8 (ret->temporal_id_nested, 1);
|
||||
READ_CONFIG_UINT8 (ret->length_size_minus_one, 2);
|
||||
if (ret->length_size_minus_one == 2) {
|
||||
/* "length_size_minus_one + 1" should be 1, 2, or 4 */
|
||||
GST_WARNING ("Wrong nal-length-size");
|
||||
result = GST_H265_PARSER_ERROR;
|
||||
goto error;
|
||||
}
|
||||
|
||||
READ_CONFIG_UINT8 (num_of_arrays, 8);
|
||||
|
||||
g_assert (gst_bit_reader_get_pos (&br) == 23 * 8);
|
||||
for (i = 0; i < num_of_arrays; i++) {
|
||||
GstH265DecoderConfigRecordNalUnitArray array;
|
||||
GstH265NalUnit nalu;
|
||||
guint16 num_nalu, j;
|
||||
guint offset;
|
||||
|
||||
READ_CONFIG_UINT8 (array.array_completeness, 1);
|
||||
SKIP_CONFIG_BITS (1);
|
||||
READ_CONFIG_UINT8 (array.nal_unit_type, 6);
|
||||
|
||||
READ_CONFIG_UINT16 (num_nalu, 16);
|
||||
|
||||
offset = gst_bit_reader_get_pos (&br) / 8;
|
||||
array.nalu = g_array_sized_new (FALSE, FALSE, sizeof (GstH265NalUnit),
|
||||
num_nalu);
|
||||
for (j = 0; j < num_nalu; j++) {
|
||||
result = gst_h265_parser_identify_nalu_hevc (parser, data, offset, size,
|
||||
2, &nalu);
|
||||
if (result != GST_H265_PARSER_OK) {
|
||||
g_array_unref (array.nalu);
|
||||
goto error;
|
||||
}
|
||||
|
||||
g_array_append_val (array.nalu, nalu);
|
||||
offset = nalu.offset + nalu.size;
|
||||
}
|
||||
|
||||
g_array_append_val (ret->nalu_array, array);
|
||||
|
||||
if (i != num_of_arrays - 1 && !gst_bit_reader_set_pos (&br, offset * 8)) {
|
||||
GST_WARNING ("Not enough byte for NAL reading");
|
||||
result = GST_H265_PARSER_ERROR;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
*config = ret;
|
||||
return GST_H265_PARSER_OK;
|
||||
|
||||
error:
|
||||
{
|
||||
gst_h265_decoder_config_record_free (ret);
|
||||
return result;
|
||||
}
|
||||
|
||||
#undef READ_CONFIG_UINT8
|
||||
#undef READ_CONFIG_UINT16
|
||||
#undef SKIP_CONFIG_BITS
|
||||
}
|
||||
|
|
|
@ -452,6 +452,8 @@ typedef struct _GstH265TimeCode GstH265TimeCode;
|
|||
typedef struct _GstH265MasteringDisplayColourVolume GstH265MasteringDisplayColourVolume;
|
||||
typedef struct _GstH265ContentLightLevel GstH265ContentLightLevel;
|
||||
typedef struct _GstH265SEIMessage GstH265SEIMessage;
|
||||
typedef struct _GstH265DecoderConfigRecordNalUnitArray GstH265DecoderConfigRecordNalUnitArray;
|
||||
typedef struct _GstH265DecoderConfigRecord GstH265DecoderConfigRecord;
|
||||
|
||||
/**
|
||||
* GstH265NalUnit:
|
||||
|
@ -1656,6 +1658,303 @@ struct _GstH265SEIMessage
|
|||
} payload;
|
||||
};
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecordNalUnitArray:
|
||||
*
|
||||
* Contains NAL Unit array data as defined in ISO/IEC 14496-15
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
struct _GstH265DecoderConfigRecordNalUnitArray
|
||||
{
|
||||
/**
|
||||
* GstH265DecoderConfigRecordNalUnitArray.array_completeness:
|
||||
*
|
||||
* 1: all NAL units of the given type are in this array and none
|
||||
* are in the stream.
|
||||
* 0: additional NAL units of the indicated type may be in the stream
|
||||
*/
|
||||
guint8 array_completeness;
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecordNalUnitArray.nal_unit_type:
|
||||
*
|
||||
* Indicates the type of the NAL units in the following array.
|
||||
* Shall be VPS, SPS, PPS, prefix SEI or suffix SEI
|
||||
*/
|
||||
GstH265NalUnitType nal_unit_type;
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecordNalUnitArray.nalu:
|
||||
*
|
||||
* Array of identified #GstH265NalUnit
|
||||
*/
|
||||
GArray *nalu;
|
||||
};
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecord:
|
||||
*
|
||||
* Contains HEVCDecoderConfigurationRecord data as defined in ISO/IEC 14496-15
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
struct _GstH265DecoderConfigRecord
|
||||
{
|
||||
/**
|
||||
* GstH265DecoderConfigRecord.configuration_version:
|
||||
*
|
||||
* Indicates configurationVersion, must be 1
|
||||
*/
|
||||
guint8 configuration_version;
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecord.general_profile_space:
|
||||
*
|
||||
* general profile space
|
||||
*/
|
||||
guint8 general_profile_space;
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecord.general_tier_flag:
|
||||
*
|
||||
* general tier flag
|
||||
*/
|
||||
guint8 general_tier_flag;
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecord.general_profile_idc:
|
||||
*
|
||||
* general profile indiction
|
||||
*/
|
||||
guint8 general_profile_idc;
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecord.general_profile_compatibility_flags:
|
||||
*
|
||||
* general profile compatibility flags
|
||||
*/
|
||||
guint8 general_profile_compatibility_flags[32];
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecord.general_progressive_source_flag:
|
||||
*
|
||||
* general_progressive_source_flag parsed from
|
||||
* HEVCDecoderConfigurationRecord.general_constraint_indicator_flags
|
||||
*/
|
||||
guint8 general_progressive_source_flag;
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecord.general_interlaced_source_flag:
|
||||
*
|
||||
* general_interlaced_source_flag parsed from
|
||||
* HEVCDecoderConfigurationRecord.general_constraint_indicator_flags
|
||||
*/
|
||||
guint8 general_interlaced_source_flag;
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecord.general_non_packed_constraint_flag:
|
||||
*
|
||||
* general_non_packed_constraint_flag parsed from
|
||||
* HEVCDecoderConfigurationRecord.general_constraint_indicator_flags
|
||||
*/
|
||||
guint8 general_non_packed_constraint_flag;
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecord.general_frame_only_constraint_flag:
|
||||
*
|
||||
* general_frame_only_constraint_flag parsed from
|
||||
* HEVCDecoderConfigurationRecord.general_constraint_indicator_flags
|
||||
*/
|
||||
guint8 general_frame_only_constraint_flag;
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecord.general_max_12bit_constraint_flag:
|
||||
*
|
||||
* general_max_12bit_constraint_flag parsed from
|
||||
* HEVCDecoderConfigurationRecord.general_constraint_indicator_flags
|
||||
*/
|
||||
guint8 general_max_12bit_constraint_flag;
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecord.general_max_10bit_constraint_flag:
|
||||
*
|
||||
* general_max_10bit_constraint_flag parsed from
|
||||
* HEVCDecoderConfigurationRecord.general_constraint_indicator_flags
|
||||
*/
|
||||
guint8 general_max_10bit_constraint_flag;
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecord.general_max_8bit_constraint_flag:
|
||||
*
|
||||
* general_max_8bit_constraint_flag parsed from
|
||||
* HEVCDecoderConfigurationRecord.general_constraint_indicator_flags
|
||||
*/
|
||||
guint8 general_max_8bit_constraint_flag;
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecord.general_max_422chroma_constraint_flag:
|
||||
*
|
||||
* general_max_422chroma_constraint_flag parsed from
|
||||
* HEVCDecoderConfigurationRecord.general_constraint_indicator_flags
|
||||
*/
|
||||
guint8 general_max_422chroma_constraint_flag;
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecord.general_max_420chroma_constraint_flag:
|
||||
*
|
||||
* general_max_420chroma_constraint_flag parsed from
|
||||
* HEVCDecoderConfigurationRecord.general_constraint_indicator_flags
|
||||
*/
|
||||
guint8 general_max_420chroma_constraint_flag;
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecord.general_max_monochrome_constraint_flag:
|
||||
*
|
||||
* general_max_monochrome_constraint_flag parsed from
|
||||
* HEVCDecoderConfigurationRecord.general_constraint_indicator_flags
|
||||
*/
|
||||
guint8 general_max_monochrome_constraint_flag;
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecord.general_intra_constraint_flag:
|
||||
*
|
||||
* general_intra_constraint_flag parsed from
|
||||
* HEVCDecoderConfigurationRecord.general_constraint_indicator_flags
|
||||
*/
|
||||
guint8 general_intra_constraint_flag;
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecord.general_one_picture_only_constraint_flag:
|
||||
*
|
||||
* general_one_picture_only_constraint_flag parsed from
|
||||
* HEVCDecoderConfigurationRecord.general_constraint_indicator_flags
|
||||
*/
|
||||
guint8 general_one_picture_only_constraint_flag;
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecord.general_lower_bit_rate_constraint_flag:
|
||||
*
|
||||
* general_lower_bit_rate_constraint_flag parsed from
|
||||
* HEVCDecoderConfigurationRecord.general_constraint_indicator_flags
|
||||
*/
|
||||
guint8 general_lower_bit_rate_constraint_flag;
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecord.general_max_14bit_constraint_flag:
|
||||
*
|
||||
* general_max_14bit_constraint_flag parsed from
|
||||
* HEVCDecoderConfigurationRecord.general_constraint_indicator_flags
|
||||
*/
|
||||
guint8 general_max_14bit_constraint_flag;
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecord.general_inbld_flag:
|
||||
*
|
||||
* general_inbld_flag parsed from
|
||||
* HEVCDecoderConfigurationRecord.general_constraint_indicator_flags
|
||||
*/
|
||||
guint8 general_inbld_flag;
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecord.general_level_idc:
|
||||
*
|
||||
* general level indication
|
||||
*/
|
||||
guint8 general_level_idc;
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecord.min_spatial_segmentation_idc:
|
||||
*
|
||||
* min spatial segmentation indication
|
||||
*/
|
||||
guint16 min_spatial_segmentation_idc;
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecord.parallelism_type:
|
||||
*
|
||||
* parallelism type
|
||||
*/
|
||||
guint8 parallelism_type;
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecord.chroma_format_idc:
|
||||
*
|
||||
* chroma format indication
|
||||
*/
|
||||
guint8 chroma_format_idc;
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecord.bit_depth_luma_minus8:
|
||||
*
|
||||
* bit depth luma minus 8
|
||||
*/
|
||||
guint8 bit_depth_luma_minus8;
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecord.bit_depth_chroma_minus8:
|
||||
*
|
||||
* bit depth chroma minus 8
|
||||
*/
|
||||
guint8 bit_depth_chroma_minus8;
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecord.avg_frame_rate:
|
||||
*
|
||||
* average frame rate in units of frames per 256 seconds,
|
||||
* or 0 when unspecified
|
||||
*/
|
||||
guint16 avg_frame_rate;
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecord.constant_frame_rate:
|
||||
*
|
||||
* constant frame rate.
|
||||
* 1: stream to which this configuration record applies is constante frame rate
|
||||
* 2: representation of each temporal layer in the stream is constant frame rate
|
||||
* 0: unspecified
|
||||
*/
|
||||
guint8 constant_frame_rate;
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecord.num_temporal_layers:
|
||||
*
|
||||
* 0: unknown whether the stream is temporally scalable
|
||||
* otherwise: the number of temporal layers
|
||||
*/
|
||||
guint8 num_temporal_layers;
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecord.temporal_id_nested:
|
||||
*
|
||||
* 1: all SPSs that activated when the stream to this configuration record
|
||||
* applies is decoded have sps_temporal_id_nesting_flags equal to 1
|
||||
* and temporal sub-layer up-switching to any higher temporal layer can
|
||||
* be performed at any semple
|
||||
* 0: unknown
|
||||
*/
|
||||
guint8 temporal_id_nested;
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecord.length_size_minus_one:
|
||||
*
|
||||
* indicates the length in bytes of nal unit length field.
|
||||
* This value shall be one of 0, 1, or 3 corresponding to a length
|
||||
* encoded with 1, 2, or 4 bytes, respectively
|
||||
*/
|
||||
guint8 length_size_minus_one;
|
||||
|
||||
/**
|
||||
* GstH265DecoderConfigRecord.nalu_array:
|
||||
*
|
||||
* Array of #GstH265DecoderConfigRecordNalUnitArray
|
||||
*/
|
||||
GArray *nalu_array;
|
||||
|
||||
/*< private >*/
|
||||
gpointer _gst_reserved[GST_PADDING];
|
||||
};
|
||||
|
||||
/**
|
||||
* GstH265Parser:
|
||||
*
|
||||
|
@ -1865,5 +2164,14 @@ GstBuffer * gst_h265_parser_insert_sei_hevc (GstH265Parser * parser,
|
|||
GST_CODEC_PARSERS_API
|
||||
GstH265Profile gst_h265_get_profile_from_sps (GstH265SPS * sps);
|
||||
|
||||
GST_CODEC_PARSERS_API
|
||||
void gst_h265_decoder_config_record_free (GstH265DecoderConfigRecord * config);
|
||||
|
||||
GST_CODEC_PARSERS_API
|
||||
GstH265ParserResult gst_h265_parser_parse_decoder_config_record (GstH265Parser * parser,
|
||||
const guint8 * data,
|
||||
gsize size,
|
||||
GstH265DecoderConfigRecord ** config);
|
||||
|
||||
G_END_DECLS
|
||||
#endif
|
||||
|
|
|
@ -1372,6 +1372,84 @@ GST_START_TEST (test_h265_split_hevc)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
/* Captured from Apple's HLS test stream
|
||||
* http://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_adv_example_hevc/v14/prog_index.m3u8
|
||||
*/
|
||||
static const guint8 h265_codec_data[] = {
|
||||
0x01, 0x02, 0x00, 0x00, 0x00, 0x04, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x7b, 0xf0, 0x00, 0xfc, 0xfd, 0xfa, 0xfa, 0x00, 0x00, 0x0f, 0x03, 0xa0,
|
||||
0x00, 0x01, 0x00, 0x18, 0x40, 0x01, 0x0c, 0x01, 0xff, 0xff, 0x02, 0x20,
|
||||
0x00, 0x00, 0x03, 0x00, 0xb0, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00,
|
||||
0x7b, 0x18, 0xb0, 0x24, 0xa1, 0x00, 0x01, 0x00, 0x3c, 0x42, 0x01, 0x01,
|
||||
0x02, 0x20, 0x00, 0x00, 0x03, 0x00, 0xb0, 0x00, 0x00, 0x03, 0x00, 0x00,
|
||||
0x03, 0x00, 0x7b, 0xa0, 0x07, 0x82, 0x00, 0x88, 0x7d, 0xb6, 0x71, 0x8b,
|
||||
0x92, 0x44, 0x80, 0x53, 0x88, 0x88, 0x92, 0xcf, 0x24, 0xa6, 0x92, 0x72,
|
||||
0xc9, 0x12, 0x49, 0x22, 0xdc, 0x91, 0xaa, 0x48, 0xfc, 0xa2, 0x23, 0xff,
|
||||
0x00, 0x01, 0x00, 0x01, 0x6a, 0x02, 0x02, 0x02, 0x01, 0xa2, 0x00, 0x01,
|
||||
0x00, 0x08, 0x44, 0x01, 0xc0, 0x25, 0x2f, 0x05, 0x32, 0x40
|
||||
};
|
||||
|
||||
GST_START_TEST (test_h265_decoder_config_record)
|
||||
{
|
||||
GstH265Parser *parser;
|
||||
GstH265ParserResult ret;
|
||||
GstH265DecoderConfigRecord *config = NULL;
|
||||
GstH265VPS vps;
|
||||
GstH265SPS sps;
|
||||
GstH265PPS pps;
|
||||
GstH265DecoderConfigRecordNalUnitArray *nalu_array;
|
||||
GstH265NalUnit *nalu;
|
||||
|
||||
parser = gst_h265_parser_new ();
|
||||
|
||||
ret = gst_h265_parser_parse_decoder_config_record (parser,
|
||||
h265_codec_data, sizeof (h265_codec_data), &config);
|
||||
assert_equals_int (ret, GST_H265_PARSER_OK);
|
||||
fail_unless (config != NULL);
|
||||
|
||||
assert_equals_int (config->length_size_minus_one, 3);
|
||||
fail_unless (config->nalu_array != NULL);
|
||||
assert_equals_int (config->nalu_array->len, 3);
|
||||
|
||||
/* VPS */
|
||||
nalu_array = &g_array_index (config->nalu_array,
|
||||
GstH265DecoderConfigRecordNalUnitArray, 0);
|
||||
fail_unless (nalu_array->nalu != NULL);
|
||||
assert_equals_int (nalu_array->nalu->len, 1);
|
||||
|
||||
nalu = &g_array_index (nalu_array->nalu, GstH265NalUnit, 0);
|
||||
assert_equals_int (nalu->type, GST_H265_NAL_VPS);
|
||||
ret = gst_h265_parser_parse_vps (parser, nalu, &vps);
|
||||
assert_equals_int (ret, GST_H265_PARSER_OK);
|
||||
|
||||
/* SPS */
|
||||
nalu_array = &g_array_index (config->nalu_array,
|
||||
GstH265DecoderConfigRecordNalUnitArray, 1);
|
||||
fail_unless (nalu_array->nalu != NULL);
|
||||
assert_equals_int (nalu_array->nalu->len, 1);
|
||||
|
||||
nalu = &g_array_index (nalu_array->nalu, GstH265NalUnit, 0);
|
||||
assert_equals_int (nalu->type, GST_H265_NAL_SPS);
|
||||
ret = gst_h265_parser_parse_sps (parser, nalu, &sps, TRUE);
|
||||
assert_equals_int (ret, GST_H265_PARSER_OK);
|
||||
|
||||
/* PPS */
|
||||
nalu_array = &g_array_index (config->nalu_array,
|
||||
GstH265DecoderConfigRecordNalUnitArray, 2);
|
||||
fail_unless (nalu_array->nalu != NULL);
|
||||
assert_equals_int (nalu_array->nalu->len, 1);
|
||||
|
||||
nalu = &g_array_index (nalu_array->nalu, GstH265NalUnit, 0);
|
||||
assert_equals_int (nalu->type, GST_H265_NAL_PPS);
|
||||
ret = gst_h265_parser_parse_pps (parser, nalu, &pps);
|
||||
assert_equals_int (ret, GST_H265_PARSER_OK);
|
||||
|
||||
gst_h265_decoder_config_record_free (config);
|
||||
gst_h265_parser_free (parser);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static Suite *
|
||||
h265parser_suite (void)
|
||||
{
|
||||
|
@ -1395,6 +1473,7 @@ h265parser_suite (void)
|
|||
tcase_add_test (tc_chain, test_h265_sei_registered_user_data);
|
||||
tcase_add_test (tc_chain, test_h265_create_sei);
|
||||
tcase_add_test (tc_chain, test_h265_split_hevc);
|
||||
tcase_add_test (tc_chain, test_h265_decoder_config_record);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue