av1parse: Continue when we fail to detect the alignment.

Some streams may have problematic OBUs at the beginning, which causes
the parse fail to detect the alignment and return error. For example,
there may be verbose OBUs before a valid sequence, which should be
discarded until we meet a valid sequence. We should let the parse
continue when we meet such cases, rather than just return error.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1634>
This commit is contained in:
He Junyan 2022-02-04 11:40:18 +08:00
parent 32633a9a14
commit 348658dd0a

View file

@ -1654,7 +1654,7 @@ out:
/* Try to recognize whether the input is annex-b format. */ /* Try to recognize whether the input is annex-b format. */
static GstFlowReturn static GstFlowReturn
gst_av1_parse_detect_alignment (GstBaseParse * parse, gst_av1_parse_detect_alignment (GstBaseParse * parse,
GstBaseParseFrame * frame, gint * skipsize) GstBaseParseFrame * frame, gint * skipsize, guint32 * total_consumed)
{ {
GstAV1Parse *self = GST_AV1_PARSE (parse); GstAV1Parse *self = GST_AV1_PARSE (parse);
GstMapInfo map_info; GstMapInfo map_info;
@ -1663,7 +1663,7 @@ gst_av1_parse_detect_alignment (GstBaseParse * parse,
GstBuffer *buffer = gst_buffer_ref (frame->buffer); GstBuffer *buffer = gst_buffer_ref (frame->buffer);
gboolean got_seq, got_frame; gboolean got_seq, got_frame;
gboolean frame_complete; gboolean frame_complete;
guint32 consumed, total_consumed; guint32 consumed;
guint32 frame_sz; guint32 frame_sz;
GstFlowReturn ret = GST_FLOW_OK; GstFlowReturn ret = GST_FLOW_OK;
@ -1678,19 +1678,20 @@ gst_av1_parse_detect_alignment (GstBaseParse * parse,
/* Detect the alignment obu first */ /* Detect the alignment obu first */
got_seq = FALSE; got_seq = FALSE;
got_frame = FALSE; got_frame = FALSE;
total_consumed = 0; *total_consumed = 0;
again: again:
while (total_consumed < map_info.size) { while (*total_consumed < map_info.size) {
res = gst_av1_parser_identify_one_obu (self->parser, res = gst_av1_parser_identify_one_obu (self->parser,
map_info.data + total_consumed, map_info.size - total_consumed, map_info.data + *total_consumed, map_info.size - *total_consumed,
&obu, &consumed); &obu, &consumed);
if (res == GST_AV1_PARSER_OK) if (res == GST_AV1_PARSER_OK) {
*total_consumed += consumed;
res = gst_av1_parse_handle_one_obu (self, &obu, &frame_complete); res = gst_av1_parse_handle_one_obu (self, &obu, &frame_complete);
}
if (res != GST_AV1_PARSER_OK) if (res != GST_AV1_PARSER_OK)
break; break;
total_consumed += consumed;
if (obu.obu_type == GST_AV1_OBU_SEQUENCE_HEADER) if (obu.obu_type == GST_AV1_OBU_SEQUENCE_HEADER)
got_seq = TRUE; got_seq = TRUE;
if (obu.obu_type == GST_AV1_OBU_REDUNDANT_FRAME_HEADER || if (obu.obu_type == GST_AV1_OBU_REDUNDANT_FRAME_HEADER ||
@ -1715,7 +1716,7 @@ again:
ret = GST_FLOW_OK; ret = GST_FLOW_OK;
goto out; goto out;
} else if (res == GST_AV1_PARSER_DROP) { } else if (res == GST_AV1_PARSER_DROP) {
total_consumed += consumed; *total_consumed += consumed;
res = GST_AV1_PARSER_OK; res = GST_AV1_PARSER_OK;
goto again; goto again;
} }
@ -1812,17 +1813,20 @@ gst_av1_parse_handle_frame (GstBaseParse * parse,
} }
if (self->in_align == GST_AV1_PARSE_ALIGN_NONE) { if (self->in_align == GST_AV1_PARSE_ALIGN_NONE) {
guint32 consumed = 0;
/* Only happend at the first time of handle_frame, and the /* Only happend at the first time of handle_frame, and the
alignment in the sink caps is unset. Try the default and alignment in the sink caps is unset. Try the default and
if error, try the annex B. */ if error, try the annex B. */
ret = gst_av1_parse_detect_alignment (parse, frame, skipsize); ret = gst_av1_parse_detect_alignment (parse, frame, skipsize, &consumed);
if (ret == GST_FLOW_OK && self->in_align != GST_AV1_PARSE_ALIGN_NONE) if (ret == GST_FLOW_OK && self->in_align != GST_AV1_PARSE_ALIGN_NONE) {
GST_INFO_OBJECT (self, "Detect the input alignment %d", self->in_align); GST_INFO_OBJECT (self, "Detect the input alignment %d", self->in_align);
} } else {
*skipsize = consumed > 0 ? consumed : gst_buffer_get_size (frame->buffer);
if (self->in_align == GST_AV1_PARSE_ALIGN_NONE) { GST_WARNING_OBJECT (self, "Fail to detect the alignment, skip %d",
GST_ERROR_OBJECT (self, "Input alignment is unknown"); *skipsize);
return GST_FLOW_ERROR; return GST_FLOW_OK;
}
} }
/* We may in pull mode and no caps is set */ /* We may in pull mode and no caps is set */