av1parse: Output each OBU when output is aligned to obu.

The current behaviour for obu aligned output is not very precise.
Several OBUs will be output together within one gst buffer. We
should output each gst buffer just containing one OBU. This is
the same way as the h264/h265 parse do when NAL aligned.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1979>
This commit is contained in:
He Junyan 2021-01-23 19:05:57 +08:00 committed by Víctor Manuel Jáquez Leal
parent ee1f6017ac
commit d83f253258

View file

@ -514,6 +514,9 @@ gst_av1_parse_update_src_caps (GstAV1Parse * self, GstCaps * caps)
gint fps_n = 0, fps_d = 0; gint fps_n = 0, fps_d = 0;
const gchar *profile = NULL; const gchar *profile = NULL;
if (G_UNLIKELY (!gst_pad_has_current_caps (GST_BASE_PARSE_SRC_PAD (self))))
self->update_caps = TRUE;
if (!self->update_caps) if (!self->update_caps)
return; return;
@ -1213,7 +1216,7 @@ gst_av1_parse_handle_obu_to_obu (GstBaseParse * parse,
GstFlowReturn ret = GST_FLOW_OK; GstFlowReturn ret = GST_FLOW_OK;
GstAV1ParserResult res; GstAV1ParserResult res;
GstBuffer *buffer = gst_buffer_ref (frame->buffer); GstBuffer *buffer = gst_buffer_ref (frame->buffer);
guint32 consumed, total_consumed; guint32 consumed;
gboolean frame_complete; gboolean frame_complete;
if (!gst_buffer_map (buffer, &map_info, GST_MAP_READ)) { if (!gst_buffer_map (buffer, &map_info, GST_MAP_READ)) {
@ -1222,42 +1225,14 @@ gst_av1_parse_handle_obu_to_obu (GstBaseParse * parse,
return GST_FLOW_ERROR; return GST_FLOW_ERROR;
} }
total_consumed = 0; consumed = 0;
again: frame_complete = FALSE;
while (total_consumed < map_info.size) { res = gst_av1_parser_identify_one_obu (self->parser, map_info.data,
frame_complete = FALSE; map_info.size, &obu, &consumed);
res = gst_av1_parser_identify_one_obu (self->parser, if (res == GST_AV1_PARSER_OK)
map_info.data + total_consumed, map_info.size - total_consumed, res = gst_av1_parse_handle_one_obu (self, &obu, &frame_complete);
&obu, &consumed);
if (res == GST_AV1_PARSER_OK)
res = gst_av1_parse_handle_one_obu (self, &obu, &frame_complete);
if (res != GST_AV1_PARSER_OK)
break;
total_consumed += consumed; g_assert (consumed <= map_info.size);
}
g_assert (total_consumed <= map_info.size);
if (total_consumed) {
/* If we get something, always output it even already met some error.
Next handle_frame loop will handle that error. */
gst_av1_parse_update_src_caps (self, NULL);
if (self->discont) {
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
self->discont = FALSE;
}
if (self->header) {
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_HEADER);
self->header = FALSE;
}
/* happen to be a frame boundary */
if (frame_complete)
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_MARKER);
ret = gst_base_parse_finish_frame (parse, frame, total_consumed);
*skipsize = 0;
goto out;
}
if (res == GST_AV1_PARSER_BITSTREAM_ERROR) { if (res == GST_AV1_PARSER_BITSTREAM_ERROR) {
if (consumed) { if (consumed) {
@ -1267,6 +1242,7 @@ again:
} }
GST_WARNING_OBJECT (parse, "Parse obu error, discard %d.", *skipsize); GST_WARNING_OBJECT (parse, "Parse obu error, discard %d.", *skipsize);
ret = GST_FLOW_OK; ret = GST_FLOW_OK;
goto out;
} else if (res == GST_AV1_PARSER_NO_MORE_DATA) { } else if (res == GST_AV1_PARSER_NO_MORE_DATA) {
*skipsize = 0; *skipsize = 0;
@ -1281,17 +1257,38 @@ again:
*skipsize); *skipsize);
} }
ret = GST_FLOW_OK; ret = GST_FLOW_OK;
goto out;
} else if (res == GST_AV1_PARSER_DROP) { } else if (res == GST_AV1_PARSER_DROP) {
GST_DEBUG_OBJECT (parse, "Drop %d data", consumed); GST_DEBUG_OBJECT (parse, "Drop %d data", consumed);
total_consumed += consumed; *skipsize = consumed;
res = GST_AV1_PARSER_OK; ret = GST_FLOW_OK;
goto again; goto out;
} else if (res != GST_AV1_PARSER_OK) { } else if (res != GST_AV1_PARSER_OK) {
GST_ERROR_OBJECT (parse, "Parse obu get unexpect error %d", res); GST_ERROR_OBJECT (parse, "Parse obu get unexpect error %d", res);
*skipsize = 0; *skipsize = 0;
ret = GST_FLOW_ERROR; ret = GST_FLOW_ERROR;
goto out;
} }
g_assert (consumed);
gst_av1_parse_update_src_caps (self, NULL);
if (self->discont) {
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
self->discont = FALSE;
}
if (self->header) {
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_HEADER);
self->header = FALSE;
}
/* happen to be a frame boundary */
if (frame_complete)
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_MARKER);
GST_LOG_OBJECT (self, "Output one buffer with size %d", consumed);
ret = gst_base_parse_finish_frame (parse, frame, consumed);
*skipsize = 0;
out: out:
gst_buffer_unmap (buffer, &map_info); gst_buffer_unmap (buffer, &map_info);
gst_buffer_unref (buffer); gst_buffer_unref (buffer);
@ -1341,10 +1338,12 @@ again:
total_consumed += consumed; total_consumed += consumed;
if (self->align == GST_AV1_PARSE_ALIGN_OBU)
break;
if (self->align == GST_AV1_PARSE_ALIGN_FRAME && frame_complete) if (self->align == GST_AV1_PARSE_ALIGN_FRAME && frame_complete)
break; break;
} }
g_assert (total_consumed <= map_info.size);
if (res == GST_AV1_PARSER_BITSTREAM_ERROR) { if (res == GST_AV1_PARSER_BITSTREAM_ERROR) {
/* Discard the whole frame */ /* Discard the whole frame */
@ -1375,7 +1374,9 @@ again:
goto out; goto out;
} }
g_assert (total_consumed >= map_info.size || frame_complete); g_assert (total_consumed >= map_info.size || frame_complete
|| self->align == GST_AV1_PARSE_ALIGN_OBU);
if (total_consumed >= map_info.size && !frame_complete if (total_consumed >= map_info.size && !frame_complete
&& self->align == GST_AV1_PARSE_ALIGN_FRAME) { && self->align == GST_AV1_PARSE_ALIGN_FRAME) {
/* Warning and still consider this frame as complete */ /* Warning and still consider this frame as complete */