mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-03 17:22:29 +00:00
av1parse: Properly transfer TU timestamp
When transforming from unknown alignment to frame or obu, the TU timestamp was not properly transferred. Fix this by saving the TU DTS as the first DTS seen within the the TU data, and the PTS as the last PTS seen in that TU data. Finally, reset the TU timestamp after each TU have completed. Fixes #1496 Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6895>
This commit is contained in:
parent
5b1bc0f19f
commit
79312357a6
1 changed files with 32 additions and 26 deletions
|
@ -1130,6 +1130,7 @@ gst_av1_parse_push_data (GstAV1Parse * self, GstBaseParseFrame * frame,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
/* Aligning to TUs which must contain a display frame. */
|
||||||
GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DECODE_ONLY);
|
GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DECODE_ONLY);
|
||||||
if (frame_finished) {
|
if (frame_finished) {
|
||||||
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_MARKER);
|
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_MARKER);
|
||||||
|
@ -1504,6 +1505,7 @@ new_tu:
|
||||||
"Start a new temporal unit with incompleted frame.");
|
"Start a new temporal unit with incompleted frame.");
|
||||||
|
|
||||||
gst_av1_parse_reset_obu_data_state (self);
|
gst_av1_parse_reset_obu_data_state (self);
|
||||||
|
gst_av1_parse_reset_tu_timestamp (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1587,6 +1589,7 @@ gst_av1_parse_handle_one_obu (GstAV1Parse * self, GstAV1OBU * obu,
|
||||||
start a TU. We only check TD here. */
|
start a TU. We only check TD here. */
|
||||||
if (obu->obu_type == GST_AV1_OBU_TEMPORAL_DELIMITER) {
|
if (obu->obu_type == GST_AV1_OBU_TEMPORAL_DELIMITER) {
|
||||||
gst_av1_parse_reset_obu_data_state (self);
|
gst_av1_parse_reset_obu_data_state (self);
|
||||||
|
gst_av1_parse_reset_tu_timestamp (self);
|
||||||
|
|
||||||
if (check_new_tu) {
|
if (check_new_tu) {
|
||||||
*check_new_tu = TRUE;
|
*check_new_tu = TRUE;
|
||||||
|
@ -1609,11 +1612,13 @@ gst_av1_parse_handle_one_obu (GstAV1Parse * self, GstAV1OBU * obu,
|
||||||
self->show_frame = fh->show_frame || fh->show_existing_frame;
|
self->show_frame = fh->show_frame || fh->show_existing_frame;
|
||||||
if (self->show_frame) {
|
if (self->show_frame) {
|
||||||
/* Check whether a new temporal starts, and return early. */
|
/* Check whether a new temporal starts, and return early. */
|
||||||
if (check_new_tu && obu->obu_type != GST_AV1_OBU_REDUNDANT_FRAME_HEADER
|
if (obu->obu_type != GST_AV1_OBU_REDUNDANT_FRAME_HEADER
|
||||||
&& gst_av1_parse_frame_start_new_temporal_unit (self, obu)) {
|
&& gst_av1_parse_frame_start_new_temporal_unit (self, obu)) {
|
||||||
*check_new_tu = TRUE;
|
if (check_new_tu) {
|
||||||
res = GST_AV1_PARSER_OK;
|
*check_new_tu = TRUE;
|
||||||
goto out;
|
res = GST_AV1_PARSER_OK;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self->last_shown_frame_temporal_id = obu->header.obu_temporal_id;
|
self->last_shown_frame_temporal_id = obu->header.obu_temporal_id;
|
||||||
|
@ -1941,6 +1946,10 @@ again:
|
||||||
if (res != GST_AV1_PARSER_OK)
|
if (res != GST_AV1_PARSER_OK)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* Take the DTS from the first OBU of the TU */
|
||||||
|
if (!GST_CLOCK_TIME_IS_VALID (self->buffer_dts))
|
||||||
|
self->buffer_dts = GST_BUFFER_DTS (buffer);
|
||||||
|
|
||||||
check_new_tu = FALSE;
|
check_new_tu = FALSE;
|
||||||
if (self->align == GST_AV1_PARSE_ALIGN_TEMPORAL_UNIT
|
if (self->align == GST_AV1_PARSE_ALIGN_TEMPORAL_UNIT
|
||||||
|| self->align == GST_AV1_PARSE_ALIGN_TEMPORAL_UNIT_ANNEX_B) {
|
|| self->align == GST_AV1_PARSE_ALIGN_TEMPORAL_UNIT_ANNEX_B) {
|
||||||
|
@ -1981,13 +1990,16 @@ again:
|
||||||
if (complete || GST_BASE_PARSE_DRAINING (parse)) {
|
if (complete || GST_BASE_PARSE_DRAINING (parse)) {
|
||||||
*skipsize = 0;
|
*skipsize = 0;
|
||||||
|
|
||||||
|
/* Save the oldest valid PTS as the TU PTS */
|
||||||
|
if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_PTS (buffer)))
|
||||||
|
self->buffer_pts = GST_BUFFER_PTS (buffer);
|
||||||
|
|
||||||
/* push the left anyway if no error */
|
/* push the left anyway if no error */
|
||||||
if (res == GST_AV1_PARSER_OK)
|
if (res == GST_AV1_PARSER_OK)
|
||||||
ret = gst_av1_parse_push_data (self, frame,
|
ret = gst_av1_parse_push_data (self, frame,
|
||||||
self->last_parsed_offset, TRUE);
|
self->last_parsed_offset, TRUE);
|
||||||
|
|
||||||
self->last_parsed_offset = 0;
|
self->last_parsed_offset = 0;
|
||||||
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2155,8 +2167,10 @@ gst_av1_parse_handle_frame (GstBaseParse * parse,
|
||||||
if (GST_BUFFER_FLAG_IS_SET (frame->buffer, GST_BUFFER_FLAG_DISCONT)) {
|
if (GST_BUFFER_FLAG_IS_SET (frame->buffer, GST_BUFFER_FLAG_DISCONT)) {
|
||||||
self->discont = TRUE;
|
self->discont = TRUE;
|
||||||
|
|
||||||
if (frame->flags & GST_BASE_PARSE_FRAME_FLAG_NEW_FRAME)
|
if (frame->flags & GST_BASE_PARSE_FRAME_FLAG_NEW_FRAME) {
|
||||||
gst_av1_parse_reset_obu_data_state (self);
|
gst_av1_parse_reset_obu_data_state (self);
|
||||||
|
gst_av1_parse_reset_tu_timestamp (self);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
self->discont = FALSE;
|
self->discont = FALSE;
|
||||||
}
|
}
|
||||||
|
@ -2273,28 +2287,20 @@ gst_av1_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
|
|
||||||
if (self->align == GST_AV1_PARSE_ALIGN_FRAME) {
|
if (self->align == GST_AV1_PARSE_ALIGN_FRAME) {
|
||||||
/* When the input align to TU, it may may contain more than one frames
|
/* Input buffers may may contain more than one frames inside its buffer.
|
||||||
inside its buffer. When splitting a TU into frames, the base parse
|
When splitting a TU into frames, the base parse class only assign the
|
||||||
class only assign the PTS to the first frame and leave the others'
|
PTS to the first frame and leave the others PTS invalid. But in fact,
|
||||||
PTS invalid. But in fact, all decode only frames should have invalid
|
all decode only frames should have invalid PTS while showable frames
|
||||||
PTS while showable frames should have correct PTS setting. */
|
should have correct PTS setting. */
|
||||||
if (self->in_align == GST_AV1_PARSE_ALIGN_TEMPORAL_UNIT
|
if (GST_BUFFER_FLAG_IS_SET (frame->buffer, GST_BUFFER_FLAG_DECODE_ONLY)) {
|
||||||
|| self->in_align == GST_AV1_PARSE_ALIGN_TEMPORAL_UNIT_ANNEX_B) {
|
GST_BUFFER_PTS (frame->buffer) = GST_CLOCK_TIME_NONE;
|
||||||
if (GST_BUFFER_FLAG_IS_SET (frame->buffer, GST_BUFFER_FLAG_DECODE_ONLY)) {
|
GST_BUFFER_DURATION (frame->buffer) = GST_CLOCK_TIME_NONE;
|
||||||
GST_BUFFER_PTS (frame->buffer) = GST_CLOCK_TIME_NONE;
|
|
||||||
GST_BUFFER_DURATION (frame->buffer) = GST_CLOCK_TIME_NONE;
|
|
||||||
} else {
|
|
||||||
GST_BUFFER_PTS (frame->buffer) = self->buffer_pts;
|
|
||||||
GST_BUFFER_DURATION (frame->buffer) = self->buffer_duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_BUFFER_DTS (frame->buffer) = self->buffer_dts;
|
|
||||||
} else {
|
} else {
|
||||||
if (GST_BUFFER_FLAG_IS_SET (frame->buffer, GST_BUFFER_FLAG_DECODE_ONLY)) {
|
GST_BUFFER_PTS (frame->buffer) = self->buffer_pts;
|
||||||
GST_BUFFER_PTS (frame->buffer) = GST_CLOCK_TIME_NONE;
|
GST_BUFFER_DURATION (frame->buffer) = self->buffer_duration;
|
||||||
GST_BUFFER_DURATION (frame->buffer) = GST_CLOCK_TIME_NONE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GST_BUFFER_DTS (frame->buffer) = self->buffer_dts;
|
||||||
} else if (self->align == GST_AV1_PARSE_ALIGN_OBU) {
|
} else if (self->align == GST_AV1_PARSE_ALIGN_OBU) {
|
||||||
/* When we split a big frame or TU into OBUs, all OBUs should have the
|
/* When we split a big frame or TU into OBUs, all OBUs should have the
|
||||||
same PTS and DTS of the input buffer, and should not have duration. */
|
same PTS and DTS of the input buffer, and should not have duration. */
|
||||||
|
|
Loading…
Reference in a new issue