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:
Seungha Yang 2022-07-15 00:13:45 +09:00 committed by GStreamer Marge Bot
parent 89a6ce105b
commit 5227b3c9a6
3 changed files with 678 additions and 0 deletions

View file

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

View file

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

View file

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