mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 10:11:08 +00:00
h26{4,5}parse: add support for forward predicted trick mode
Also stop assigning TRUE to fields with |=
This commit is contained in:
parent
d6680b35b4
commit
2305bf272c
4 changed files with 83 additions and 21 deletions
|
@ -193,6 +193,8 @@ gst_h264_parse_reset_frame (GstH264Parse * h264parse)
|
|||
h264parse->idr_pos = -1;
|
||||
h264parse->sei_pos = -1;
|
||||
h264parse->keyframe = FALSE;
|
||||
h264parse->predicted = FALSE;
|
||||
h264parse->bidirectional = FALSE;
|
||||
h264parse->header = FALSE;
|
||||
h264parse->frame_start = FALSE;
|
||||
h264parse->aud_insert = TRUE;
|
||||
|
@ -260,6 +262,7 @@ gst_h264_parse_reset (GstH264Parse * h264parse)
|
|||
gst_event_replace (&h264parse->force_key_unit_event, NULL);
|
||||
|
||||
h264parse->discont = FALSE;
|
||||
h264parse->discard_bidirectional = FALSE;
|
||||
|
||||
gst_h264_parse_reset_stream_info (h264parse);
|
||||
}
|
||||
|
@ -855,7 +858,7 @@ gst_h264_parse_process_nal (GstH264Parse * h264parse, GstH264NalUnit * nalu)
|
|||
if (pres != GST_H264_PARSER_OK) {
|
||||
GST_WARNING_OBJECT (h264parse, "failed to parse SPS:");
|
||||
h264parse->state |= GST_H264_PARSE_STATE_GOT_SPS;
|
||||
h264parse->header |= TRUE;
|
||||
h264parse->header = TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -875,7 +878,7 @@ gst_h264_parse_process_nal (GstH264Parse * h264parse, GstH264NalUnit * nalu)
|
|||
gst_h264_parser_store_nal (h264parse, sps.id, nal_type, nalu);
|
||||
gst_h264_sps_clear (&sps);
|
||||
h264parse->state |= GST_H264_PARSE_STATE_GOT_SPS;
|
||||
h264parse->header |= TRUE;
|
||||
h264parse->header = TRUE;
|
||||
break;
|
||||
case GST_H264_NAL_PPS:
|
||||
/* expected state: got-sps */
|
||||
|
@ -910,14 +913,14 @@ gst_h264_parse_process_nal (GstH264Parse * h264parse, GstH264NalUnit * nalu)
|
|||
gst_h264_parser_store_nal (h264parse, pps.id, nal_type, nalu);
|
||||
gst_h264_pps_clear (&pps);
|
||||
h264parse->state |= GST_H264_PARSE_STATE_GOT_PPS;
|
||||
h264parse->header |= TRUE;
|
||||
h264parse->header = TRUE;
|
||||
break;
|
||||
case GST_H264_NAL_SEI:
|
||||
/* expected state: got-sps */
|
||||
if (!GST_H264_PARSE_STATE_VALID (h264parse, GST_H264_PARSE_STATE_GOT_SPS))
|
||||
return FALSE;
|
||||
|
||||
h264parse->header |= TRUE;
|
||||
h264parse->header = TRUE;
|
||||
gst_h264_parse_process_sei (h264parse, nalu);
|
||||
/* mark SEI pos */
|
||||
if (h264parse->sei_pos == -1) {
|
||||
|
@ -962,7 +965,12 @@ gst_h264_parse_process_nal (GstH264Parse * h264parse, GstH264NalUnit * nalu)
|
|||
pres, slice.first_mb_in_slice, slice.type);
|
||||
if (pres == GST_H264_PARSER_OK) {
|
||||
if (GST_H264_IS_I_SLICE (&slice) || GST_H264_IS_SI_SLICE (&slice))
|
||||
h264parse->keyframe |= TRUE;
|
||||
h264parse->keyframe = TRUE;
|
||||
else if (GST_H264_IS_P_SLICE (&slice)
|
||||
|| GST_H264_IS_SP_SLICE (&slice))
|
||||
h264parse->predicted = TRUE;
|
||||
else if (GST_H264_IS_B_SLICE (&slice))
|
||||
h264parse->bidirectional = TRUE;
|
||||
|
||||
h264parse->state |= GST_H264_PARSE_STATE_GOT_SLICE;
|
||||
h264parse->field_pic_flag = slice.field_pic_flag;
|
||||
|
@ -2335,6 +2343,9 @@ gst_h264_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
|||
else
|
||||
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
|
||||
|
||||
if (h264parse->discard_bidirectional && h264parse->bidirectional)
|
||||
goto discard;
|
||||
|
||||
if (h264parse->header)
|
||||
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_HEADER);
|
||||
else
|
||||
|
@ -2356,7 +2367,14 @@ gst_h264_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
|||
gst_buffer_unref (buf);
|
||||
}
|
||||
|
||||
done:
|
||||
return GST_FLOW_OK;
|
||||
|
||||
discard:
|
||||
GST_DEBUG_OBJECT (h264parse, "Discarding bidirectional frame");
|
||||
frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DROP;
|
||||
gst_h264_parse_reset_frame (h264parse);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* sends a codec NAL downstream, decorating and transforming as needed.
|
||||
|
@ -3156,6 +3174,12 @@ gst_h264_parse_event (GstBaseParse * parse, GstEvent * event)
|
|||
|| segment->applied_rate != 1.0))
|
||||
h264parse->do_ts = FALSE;
|
||||
|
||||
if (segment->flags & GST_SEEK_FLAG_TRICKMODE_FORWARD_PREDICTED) {
|
||||
GST_DEBUG_OBJECT (h264parse, "Will discard bidirectional frames");
|
||||
h264parse->discard_bidirectional = TRUE;
|
||||
}
|
||||
|
||||
|
||||
h264parse->last_report = GST_CLOCK_TIME_NONE;
|
||||
|
||||
res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
|
||||
|
|
|
@ -123,6 +123,8 @@ struct _GstH264Parse
|
|||
gboolean update_caps;
|
||||
GstAdapter *frame_out;
|
||||
gboolean keyframe;
|
||||
gboolean predicted;
|
||||
gboolean bidirectional;
|
||||
gboolean header;
|
||||
gboolean frame_start;
|
||||
/* AU state */
|
||||
|
@ -147,6 +149,9 @@ struct _GstH264Parse
|
|||
guint8 closedcaptions[96];
|
||||
guint closedcaptions_size;
|
||||
GstVideoCaptionType closedcaptions_type;
|
||||
|
||||
/* For forward predicted trickmode */
|
||||
gboolean discard_bidirectional;
|
||||
};
|
||||
|
||||
struct _GstH264ParseClass
|
||||
|
|
|
@ -189,6 +189,8 @@ gst_h265_parse_reset_frame (GstH265Parse * h265parse)
|
|||
h265parse->idr_pos = -1;
|
||||
h265parse->sei_pos = -1;
|
||||
h265parse->keyframe = FALSE;
|
||||
h265parse->predicted = FALSE;
|
||||
h265parse->bidirectional = FALSE;
|
||||
h265parse->header = FALSE;
|
||||
h265parse->have_vps_in_frame = FALSE;
|
||||
h265parse->have_sps_in_frame = FALSE;
|
||||
|
@ -255,6 +257,7 @@ gst_h265_parse_reset (GstH265Parse * h265parse)
|
|||
gst_event_replace (&h265parse->force_key_unit_event, NULL);
|
||||
|
||||
h265parse->discont = FALSE;
|
||||
h265parse->discard_bidirectional = FALSE;
|
||||
|
||||
gst_h265_parse_reset_stream_info (h265parse);
|
||||
}
|
||||
|
@ -593,11 +596,11 @@ gst_h265_parse_process_sei (GstH265Parse * h265parse, GstH265NalUnit * nalu)
|
|||
minfo.Wx_n = sei.payload.mastering_display_colour_volume.white_point_x;
|
||||
minfo.Wy_n = sei.payload.mastering_display_colour_volume.white_point_y;
|
||||
minfo.max_luma_n =
|
||||
sei.payload.
|
||||
mastering_display_colour_volume.max_display_mastering_luminance;
|
||||
sei.payload.mastering_display_colour_volume.
|
||||
max_display_mastering_luminance;
|
||||
minfo.min_luma_n =
|
||||
sei.payload.
|
||||
mastering_display_colour_volume.min_display_mastering_luminance;
|
||||
sei.payload.mastering_display_colour_volume.
|
||||
min_display_mastering_luminance;
|
||||
|
||||
minfo.Gx_d = minfo.Gy_d = minfo.Bx_d = minfo.By_d =
|
||||
minfo.Rx_d = minfo.Ry_d = minfo.Wx_d = minfo.Wy_d = chroma_den;
|
||||
|
@ -716,7 +719,7 @@ gst_h265_parse_process_nal (GstH265Parse * h265parse, GstH265NalUnit * nalu)
|
|||
}
|
||||
|
||||
gst_h265_parser_store_nal (h265parse, vps.id, nal_type, nalu);
|
||||
h265parse->header |= TRUE;
|
||||
h265parse->header = TRUE;
|
||||
break;
|
||||
case GST_H265_NAL_SPS:
|
||||
/* reset state, everything else is obsolete */
|
||||
|
@ -732,7 +735,7 @@ gst_h265_parse_process_nal (GstH265Parse * h265parse, GstH265NalUnit * nalu)
|
|||
if (pres != GST_H265_PARSER_OK) {
|
||||
GST_WARNING_OBJECT (h265parse, "failed to parse SPS:");
|
||||
h265parse->state |= GST_H265_PARSE_STATE_GOT_SPS;
|
||||
h265parse->header |= TRUE;
|
||||
h265parse->header = TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
GST_WARNING_OBJECT (h265parse,
|
||||
|
@ -753,7 +756,7 @@ gst_h265_parse_process_nal (GstH265Parse * h265parse, GstH265NalUnit * nalu)
|
|||
}
|
||||
|
||||
gst_h265_parser_store_nal (h265parse, sps.id, nal_type, nalu);
|
||||
h265parse->header |= TRUE;
|
||||
h265parse->header = TRUE;
|
||||
h265parse->state |= GST_H265_PARSE_STATE_GOT_SPS;
|
||||
break;
|
||||
case GST_H265_NAL_PPS:
|
||||
|
@ -789,7 +792,7 @@ gst_h265_parse_process_nal (GstH265Parse * h265parse, GstH265NalUnit * nalu)
|
|||
}
|
||||
|
||||
gst_h265_parser_store_nal (h265parse, pps.id, nal_type, nalu);
|
||||
h265parse->header |= TRUE;
|
||||
h265parse->header = TRUE;
|
||||
h265parse->state |= GST_H265_PARSE_STATE_GOT_PPS;
|
||||
break;
|
||||
case GST_H265_NAL_PREFIX_SEI:
|
||||
|
@ -798,7 +801,7 @@ gst_h265_parse_process_nal (GstH265Parse * h265parse, GstH265NalUnit * nalu)
|
|||
if (!GST_H265_PARSE_STATE_VALID (h265parse, GST_H265_PARSE_STATE_GOT_SPS))
|
||||
return FALSE;
|
||||
|
||||
h265parse->header |= TRUE;
|
||||
h265parse->header = TRUE;
|
||||
|
||||
gst_h265_parse_process_sei (h265parse, nalu);
|
||||
|
||||
|
@ -844,7 +847,11 @@ gst_h265_parse_process_nal (GstH265Parse * h265parse, GstH265NalUnit * nalu)
|
|||
|
||||
if (pres == GST_H265_PARSER_OK) {
|
||||
if (GST_H265_IS_I_SLICE (&slice))
|
||||
h265parse->keyframe |= TRUE;
|
||||
h265parse->keyframe = TRUE;
|
||||
else if (GST_H265_IS_P_SLICE (&slice))
|
||||
h265parse->predicted = TRUE;
|
||||
else if (GST_H265_IS_B_SLICE (&slice))
|
||||
h265parse->bidirectional = TRUE;
|
||||
|
||||
h265parse->state |= GST_H265_PARSE_STATE_GOT_SLICE;
|
||||
}
|
||||
|
@ -2118,6 +2125,10 @@ gst_h265_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
|||
else
|
||||
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
|
||||
|
||||
if (h265parse->discard_bidirectional && h265parse->bidirectional)
|
||||
goto discard;
|
||||
|
||||
|
||||
if (h265parse->header)
|
||||
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_HEADER);
|
||||
else
|
||||
|
@ -2139,7 +2150,15 @@ gst_h265_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
|||
gst_buffer_unref (buf);
|
||||
}
|
||||
|
||||
done:
|
||||
return GST_FLOW_OK;
|
||||
|
||||
discard:
|
||||
GST_DEBUG_OBJECT (h265parse, "Discarding bidirectional frame");
|
||||
frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DROP;
|
||||
gst_h265_parse_reset_frame (h265parse);
|
||||
goto done;
|
||||
|
||||
}
|
||||
|
||||
/* sends a codec NAL downstream, decorating and transforming as needed.
|
||||
|
@ -2551,12 +2570,12 @@ gst_h265_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
|||
h265parse->parsed_fps_d,
|
||||
NULL,
|
||||
flags,
|
||||
h265parse->time_code.hours_flag[i] ? h265parse->
|
||||
time_code.hours_value[i] : 0,
|
||||
h265parse->time_code.minutes_flag[i] ? h265parse->
|
||||
time_code.minutes_value[i] : 0,
|
||||
h265parse->time_code.seconds_flag[i] ? h265parse->
|
||||
time_code.seconds_value[i] : 0, n_frames, field_count);
|
||||
h265parse->time_code.hours_flag[i] ? h265parse->time_code.
|
||||
hours_value[i] : 0,
|
||||
h265parse->time_code.minutes_flag[i] ? h265parse->time_code.
|
||||
minutes_value[i] : 0,
|
||||
h265parse->time_code.seconds_flag[i] ? h265parse->time_code.
|
||||
seconds_value[i] : 0, n_frames, field_count);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2846,8 +2865,17 @@ gst_h265_parse_event (GstBaseParse * parse, GstEvent * event)
|
|||
break;
|
||||
case GST_EVENT_SEGMENT:
|
||||
{
|
||||
const GstSegment *segment = NULL;
|
||||
|
||||
gst_event_parse_segment (event, &segment);
|
||||
|
||||
h265parse->last_report = GST_CLOCK_TIME_NONE;
|
||||
|
||||
if (segment->flags & GST_SEEK_FLAG_TRICKMODE_FORWARD_PREDICTED) {
|
||||
GST_DEBUG_OBJECT (h265parse, "Will discard bidirectional frames");
|
||||
h265parse->discard_bidirectional = TRUE;
|
||||
}
|
||||
|
||||
res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -102,6 +102,8 @@ struct _GstH265Parse
|
|||
gboolean update_caps;
|
||||
GstAdapter *frame_out;
|
||||
gboolean keyframe;
|
||||
gboolean predicted;
|
||||
gboolean bidirectional;
|
||||
gboolean header;
|
||||
/* AU state */
|
||||
gboolean picture_start;
|
||||
|
@ -119,6 +121,9 @@ struct _GstH265Parse
|
|||
|
||||
GstVideoContentLightLevel content_light_level;
|
||||
guint content_light_level_state;
|
||||
|
||||
/* For forward predicted trickmode */
|
||||
gboolean discard_bidirectional;
|
||||
};
|
||||
|
||||
struct _GstH265ParseClass
|
||||
|
|
Loading…
Reference in a new issue