h26xparse: Handle state change on IDR first slice

As the H265/H264 bitstream can support multiple slices,
mastering_display_info_state and content_light_level_state
should be changed only on first slice segment.

Fix #1152
This commit is contained in:
Stéphane Cerveau 2019-12-17 12:08:34 +01:00 committed by Guillaume Desmottes
parent d414e90eff
commit 4b8c47ee37
2 changed files with 34 additions and 31 deletions

View File

@ -879,6 +879,7 @@ gst_h264_parse_process_nal (GstH264Parse * h264parse, GstH264NalUnit * nalu)
GstH264SPS sps = { 0, }; GstH264SPS sps = { 0, };
GstH264NalParser *nalparser = h264parse->nalparser; GstH264NalParser *nalparser = h264parse->nalparser;
GstH264ParserResult pres; GstH264ParserResult pres;
GstH264SliceHdr slice;
/* nothing to do for broken input */ /* nothing to do for broken input */
if (G_UNLIKELY (nalu->size < 2)) { if (G_UNLIKELY (nalu->size < 2)) {
@ -1006,8 +1007,6 @@ gst_h264_parse_process_nal (GstH264Parse * h264parse, GstH264NalUnit * nalu)
GST_DEBUG_OBJECT (h264parse, "frame start: %i", h264parse->frame_start); GST_DEBUG_OBJECT (h264parse, "frame start: %i", h264parse->frame_start);
if (nal_type == GST_H264_NAL_SLICE_EXT && !GST_H264_IS_MVC_NALU (nalu)) if (nal_type == GST_H264_NAL_SLICE_EXT && !GST_H264_IS_MVC_NALU (nalu))
break; break;
{
GstH264SliceHdr slice;
pres = gst_h264_parser_parse_slice_hdr (nalparser, nalu, &slice, pres = gst_h264_parser_parse_slice_hdr (nalparser, nalu, &slice,
FALSE, FALSE); FALSE, FALSE);
@ -1026,10 +1025,11 @@ gst_h264_parse_process_nal (GstH264Parse * h264parse, GstH264NalUnit * nalu)
h264parse->state |= GST_H264_PARSE_STATE_GOT_SLICE; h264parse->state |= GST_H264_PARSE_STATE_GOT_SLICE;
h264parse->field_pic_flag = slice.field_pic_flag; h264parse->field_pic_flag = slice.field_pic_flag;
} }
}
if (G_LIKELY (nal_type != GST_H264_NAL_SLICE_IDR && if (G_LIKELY (nal_type != GST_H264_NAL_SLICE_IDR &&
!h264parse->push_codec)) !h264parse->push_codec))
break; break;
/* if we need to sneak codec NALs into the stream, /* if we need to sneak codec NALs into the stream,
* this is a good place, so fake it as IDR * this is a good place, so fake it as IDR
* (which should be at start anyway) */ * (which should be at start anyway) */
@ -1049,8 +1049,10 @@ gst_h264_parse_process_nal (GstH264Parse * h264parse, GstH264NalUnit * nalu)
GST_DEBUG_OBJECT (h264parse, "moved IDR mark to SEI position %d", GST_DEBUG_OBJECT (h264parse, "moved IDR mark to SEI position %d",
h264parse->idr_pos); h264parse->idr_pos);
} }
/* Reset state only on first IDR slice of CVS D.2.29 */
if (h264parse->mastering_display_info_state == GST_H264_PARSE_SEI_PARSED) if (slice.first_mb_in_slice == 0) {
if (h264parse->mastering_display_info_state ==
GST_H264_PARSE_SEI_PARSED)
h264parse->mastering_display_info_state = GST_H264_PARSE_SEI_ACTIVE; h264parse->mastering_display_info_state = GST_H264_PARSE_SEI_ACTIVE;
else if (h264parse->mastering_display_info_state == else if (h264parse->mastering_display_info_state ==
GST_H264_PARSE_SEI_ACTIVE) GST_H264_PARSE_SEI_ACTIVE)
@ -1061,7 +1063,7 @@ gst_h264_parse_process_nal (GstH264Parse * h264parse, GstH264NalUnit * nalu)
else if (h264parse->content_light_level_state == else if (h264parse->content_light_level_state ==
GST_H264_PARSE_SEI_ACTIVE) GST_H264_PARSE_SEI_ACTIVE)
h264parse->content_light_level_state = GST_H264_PARSE_SEI_EXPIRED; h264parse->content_light_level_state = GST_H264_PARSE_SEI_EXPIRED;
}
break; break;
case GST_H264_NAL_AU_DELIMITER: case GST_H264_NAL_AU_DELIMITER:
/* Just accumulate AU Delimiter, whether it's before SPS or not */ /* Just accumulate AU Delimiter, whether it's before SPS or not */

View File

@ -921,7 +921,8 @@ gst_h265_parse_process_nal (GstH265Parse * h265parse, GstH265NalUnit * nalu)
is_irap = ((nal_type >= GST_H265_NAL_SLICE_BLA_W_LP) is_irap = ((nal_type >= GST_H265_NAL_SLICE_BLA_W_LP)
&& (nal_type <= GST_H265_NAL_SLICE_CRA_NUT)) ? TRUE : FALSE; && (nal_type <= GST_H265_NAL_SLICE_CRA_NUT)) ? TRUE : FALSE;
if (no_rasl_output_flag && is_irap) { if (no_rasl_output_flag && is_irap
&& slice.first_slice_segment_in_pic_flag == 1) {
if (h265parse->mastering_display_info_state == if (h265parse->mastering_display_info_state ==
GST_H265_PARSE_SEI_PARSED) GST_H265_PARSE_SEI_PARSED)
h265parse->mastering_display_info_state = GST_H265_PARSE_SEI_ACTIVE; h265parse->mastering_display_info_state = GST_H265_PARSE_SEI_ACTIVE;