mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-25 19:21:06 +00:00
h264parse, h265parse: Fix timecode parsing
The scaling factor for nFrame part should be "(1 + nuit_field_based_flag) / 2" Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5254>
This commit is contained in:
parent
22c8d1890e
commit
2c4cb82afc
2 changed files with 76 additions and 7 deletions
|
@ -3208,6 +3208,7 @@ gst_h264_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
||||||
GstEvent *event;
|
GstEvent *event;
|
||||||
GstBuffer *parse_buffer = NULL;
|
GstBuffer *parse_buffer = NULL;
|
||||||
gboolean is_interlaced = FALSE;
|
gboolean is_interlaced = FALSE;
|
||||||
|
GstH264SPS *sps;
|
||||||
|
|
||||||
h264parse = GST_H264_PARSE (parse);
|
h264parse = GST_H264_PARSE (parse);
|
||||||
|
|
||||||
|
@ -3369,8 +3370,15 @@ gst_h264_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
||||||
parse_buffer = frame->buffer = gst_buffer_make_writable (frame->buffer);
|
parse_buffer = frame->buffer = gst_buffer_make_writable (frame->buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gst_buffer_get_video_time_code_meta (parse_buffer)) {
|
sps = h264parse->nalparser->last_sps;
|
||||||
|
if (sps && sps->vui_parameters_present_flag &&
|
||||||
|
sps->vui_parameters.timing_info_present_flag &&
|
||||||
|
sps->vui_parameters.time_scale > 0 &&
|
||||||
|
sps->vui_parameters.num_units_in_tick > 0 &&
|
||||||
|
h264parse->parsed_fps_n > 0 && h264parse->parsed_fps_d > 0 &&
|
||||||
|
!gst_buffer_get_video_time_code_meta (parse_buffer)) {
|
||||||
guint i = 0;
|
guint i = 0;
|
||||||
|
GstH264VUIParams *vui = &sps->vui_parameters;
|
||||||
|
|
||||||
for (i = 0; i < 3 && h264parse->num_clock_timestamp; i++) {
|
for (i = 0; i < 3 && h264parse->num_clock_timestamp; i++) {
|
||||||
GstH264ClockTimestamp *tim =
|
GstH264ClockTimestamp *tim =
|
||||||
|
@ -3378,6 +3386,7 @@ gst_h264_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
||||||
gint field_count = -1;
|
gint field_count = -1;
|
||||||
guint n_frames;
|
guint n_frames;
|
||||||
GstVideoTimeCodeFlags flags = 0;
|
GstVideoTimeCodeFlags flags = 0;
|
||||||
|
guint64 scale_n, scale_d;
|
||||||
|
|
||||||
if (!h264parse->pic_timing_sei.clock_timestamp_flag[i])
|
if (!h264parse->pic_timing_sei.clock_timestamp_flag[i])
|
||||||
continue;
|
continue;
|
||||||
|
@ -3424,9 +3433,37 @@ gst_h264_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
||||||
is_interlaced = TRUE;
|
is_interlaced = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
n_frames =
|
/* Equation D-1 (without and tOffset)
|
||||||
gst_util_uint64_scale_int (tim->n_frames, 1,
|
*
|
||||||
2 - tim->nuit_field_based_flag);
|
* clockTimestamp = ( ( hH * 60 + mM ) * 60 + sS ) * time_scale +
|
||||||
|
* nFrames * ( num_units_in_tick * ( 1 + nuit_field_based_flag ) )
|
||||||
|
* => timestamp = clockTimestamp / time_scale
|
||||||
|
*
|
||||||
|
* <taking only frame part>
|
||||||
|
* timestamp = nFrames * ( num_units_in_tick * ( 1 + nuit_field_based_flag ) ) / time_scale
|
||||||
|
*
|
||||||
|
* <timecode's timestamp of frame part>
|
||||||
|
* timecode_timestamp = n_frames * fps_d / fps_n
|
||||||
|
*
|
||||||
|
* <Scaling Equation>
|
||||||
|
* n_frames = nFrames * ( num_units_in_tick * ( 1 + nuit_field_based_flag ) ) / time_scale
|
||||||
|
* * fps_n / fps_d
|
||||||
|
*
|
||||||
|
* fps_n * ( num_units_in_tick * ( 1 + nuit_field_based_flag ) )
|
||||||
|
* = nFrames * --------------------------------------------------------------
|
||||||
|
* fps_d * time_scale
|
||||||
|
*
|
||||||
|
* NOTE: "time_scale / num_units_in_tick" value is expected field rate
|
||||||
|
* (i.e., framerate = time_scale / (2 * num_units_in_tick)), so the above
|
||||||
|
* equation can be simplified if the bitstream is conveying field rate
|
||||||
|
* using time_scale / num_units_in_tick
|
||||||
|
* => "n_frames = nFrames * (1 + nuit_field_based_flag) / 2".
|
||||||
|
*/
|
||||||
|
scale_n = h264parse->parsed_fps_n * vui->num_units_in_tick
|
||||||
|
* (1 + tim->nuit_field_based_flag);
|
||||||
|
scale_d = h264parse->parsed_fps_d * vui->time_scale;
|
||||||
|
|
||||||
|
n_frames = gst_util_uint64_scale (tim->n_frames, scale_n, scale_d);
|
||||||
|
|
||||||
GST_LOG_OBJECT (h264parse,
|
GST_LOG_OBJECT (h264parse,
|
||||||
"Add time code meta %02u:%02u:%02u:%02u",
|
"Add time code meta %02u:%02u:%02u:%02u",
|
||||||
|
|
|
@ -2910,6 +2910,7 @@ gst_h265_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
||||||
GstBuffer *buffer;
|
GstBuffer *buffer;
|
||||||
GstEvent *event;
|
GstEvent *event;
|
||||||
GstBuffer *parse_buffer = NULL;
|
GstBuffer *parse_buffer = NULL;
|
||||||
|
GstH265SPS *sps;
|
||||||
|
|
||||||
h265parse = GST_H265_PARSE (parse);
|
h265parse = GST_H265_PARSE (parse);
|
||||||
|
|
||||||
|
@ -3043,13 +3044,20 @@ gst_h265_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
sps = h265parse->nalparser->last_sps;
|
||||||
|
if (sps && sps->vui_parameters_present_flag &&
|
||||||
|
sps->vui_params.timing_info_present_flag &&
|
||||||
|
sps->vui_params.time_scale > 0 &&
|
||||||
|
sps->vui_params.num_units_in_tick > 0 &&
|
||||||
|
!gst_buffer_get_video_time_code_meta (parse_buffer)) {
|
||||||
guint i = 0;
|
guint i = 0;
|
||||||
|
GstH265VUIParams *vui = &sps->vui_params;
|
||||||
|
|
||||||
for (i = 0; i < h265parse->time_code.num_clock_ts; i++) {
|
for (i = 0; i < h265parse->time_code.num_clock_ts; i++) {
|
||||||
gint field_count = -1;
|
gint field_count = -1;
|
||||||
guint n_frames;
|
guint n_frames;
|
||||||
GstVideoTimeCodeFlags flags = 0;
|
GstVideoTimeCodeFlags flags = 0;
|
||||||
|
guint64 scale_n, scale_d;
|
||||||
|
|
||||||
if (!h265parse->time_code.clock_timestamp_flag[i])
|
if (!h265parse->time_code.clock_timestamp_flag[i])
|
||||||
break;
|
break;
|
||||||
|
@ -3100,9 +3108,33 @@ gst_h265_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
||||||
if (h265parse->sei_pic_struct != GST_H265_SEI_PIC_STRUCT_FRAME)
|
if (h265parse->sei_pic_struct != GST_H265_SEI_PIC_STRUCT_FRAME)
|
||||||
flags |= GST_VIDEO_TIME_CODE_FLAGS_INTERLACED;
|
flags |= GST_VIDEO_TIME_CODE_FLAGS_INTERLACED;
|
||||||
|
|
||||||
|
/* Equation D-26 (without and tOffset)
|
||||||
|
*
|
||||||
|
* clockTimestamp[i] = ( ( hH * 60 + mM ) * 60 + sS ) * vui_time_scale +
|
||||||
|
* nFrames * ( vui_num_units_in_tick * ( 1 + unit_field_based_flag[i] ) )
|
||||||
|
* => timestamp = clockTimestamp / time_scale
|
||||||
|
*
|
||||||
|
* <taking only frame part>
|
||||||
|
* timestamp = nFrames * ( vui_num_units_in_tick * ( 1 + unit_field_based_flag ) ) / vui_time_scale
|
||||||
|
*
|
||||||
|
* <timecode's timestamp of frame part>
|
||||||
|
* timecode_timestamp = n_frames * fps_d / fps_n
|
||||||
|
*
|
||||||
|
* <Scaling Equation>
|
||||||
|
* n_frames = nFrames * ( vui_num_units_in_tick * ( 1 + unit_field_based_flag ) ) / vui_time_scale
|
||||||
|
* * fps_n / fps_d
|
||||||
|
*
|
||||||
|
* fps_n * ( vui_num_units_in_tick * ( 1 + unit_field_based_flag ) )
|
||||||
|
* = nFrames * ------------------------------------------------------------------
|
||||||
|
* fps_d * vui_time_scale
|
||||||
|
*/
|
||||||
|
scale_n = h265parse->parsed_fps_n * vui->num_units_in_tick
|
||||||
|
* (1 + h265parse->time_code.units_field_based_flag[i]);
|
||||||
|
scale_d = h265parse->parsed_fps_d * vui->time_scale;
|
||||||
|
|
||||||
n_frames =
|
n_frames =
|
||||||
gst_util_uint64_scale_int (h265parse->time_code.n_frames[i], 1,
|
gst_util_uint64_scale_int (h265parse->time_code.n_frames[i], scale_n,
|
||||||
2 - h265parse->time_code.units_field_based_flag[i]);
|
scale_d);
|
||||||
|
|
||||||
gst_buffer_add_video_time_code_meta_full (parse_buffer,
|
gst_buffer_add_video_time_code_meta_full (parse_buffer,
|
||||||
h265parse->parsed_fps_n,
|
h265parse->parsed_fps_n,
|
||||||
|
|
Loading…
Reference in a new issue