aacparse: Avoid mismatch between src_caps and output_header_type

If our downstream caps didn't intersect, we attempted to convert between
raw and ADTS stream formats, if possible. If the caps still did not
intersect, we then used the modified `src_caps` but left the
`output_header_type` unmodified.

This caused a mismatch between caps and actual stream format.

Avoid this by first copying the `src_caps` to `convcaps` for the
additional intersection tests, replacing `src_caps` if we succeed.

While we're here, clean up the code a bit and remove the `codec_data`
field from outgoing ADTS caps.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2550>
This commit is contained in:
Jan Alexander Steffens (heftig) 2022-06-03 18:35:54 +02:00 committed by GStreamer Marge Bot
parent e5f9bb973f
commit 637406cdb1

View file

@ -210,7 +210,9 @@ gst_aac_parse_set_src_caps (GstAacParse * aacparse, GstCaps * sink_caps)
stream_format = NULL;
}
/* Generate codec data to be able to set profile/level on the caps */
/* Generate codec data to be able to set profile/level on the caps.
* The codec_data data is according to AudioSpecificConfig,
* ISO/IEC 14496-3, 1.6.2.1 */
sample_rate_idx =
gst_codec_utils_aac_get_index_from_sample_rate (aacparse->sample_rate);
if (sample_rate_idx < 0)
@ -231,39 +233,38 @@ gst_aac_parse_set_src_caps (GstAacParse * aacparse, GstCaps * sink_caps)
peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (aacparse), NULL);
if (peercaps && !gst_caps_can_intersect (src_caps, peercaps)) {
GST_DEBUG_OBJECT (GST_BASE_PARSE (aacparse)->srcpad,
"Caps can not intersect");
GstCaps *convcaps = gst_caps_copy (src_caps);
GstStructure *cs = gst_caps_get_structure (convcaps, 0);
GST_DEBUG_OBJECT (aacparse, "Caps do not intersect: parsed %" GST_PTR_FORMAT
" and peer %" GST_PTR_FORMAT, src_caps, peercaps);
if (aacparse->header_type == DSPAAC_HEADER_ADTS) {
GST_DEBUG_OBJECT (GST_BASE_PARSE (aacparse)->srcpad,
"Input is ADTS, trying raw");
gst_caps_set_simple (src_caps, "stream-format", G_TYPE_STRING, "raw",
NULL);
if (gst_caps_can_intersect (src_caps, peercaps)) {
GstBuffer *codec_data_buffer;
GstBuffer *codec_data_buffer = gst_buffer_new_and_alloc (2);
GST_DEBUG_OBJECT (GST_BASE_PARSE (aacparse)->srcpad,
"Caps can intersect, we will drop the ADTS layer");
gst_buffer_fill (codec_data_buffer, 0, codec_data, 2);
gst_structure_set (cs, "stream-format", G_TYPE_STRING, "raw",
"codec_data", GST_TYPE_BUFFER, codec_data_buffer, NULL);
if (gst_caps_can_intersect (convcaps, peercaps)) {
GST_DEBUG_OBJECT (aacparse, "Converting from ADTS to raw");
aacparse->output_header_type = DSPAAC_HEADER_NONE;
/* The codec_data data is according to AudioSpecificConfig,
ISO/IEC 14496-3, 1.6.2.1 */
codec_data_buffer = gst_buffer_new_and_alloc (2);
gst_buffer_fill (codec_data_buffer, 0, codec_data, 2);
gst_caps_set_simple (src_caps, "codec_data", GST_TYPE_BUFFER,
codec_data_buffer, NULL);
gst_buffer_unref (codec_data_buffer);
gst_caps_replace (&src_caps, convcaps);
}
gst_buffer_unref (codec_data_buffer);
} else if (aacparse->header_type == DSPAAC_HEADER_NONE) {
GST_DEBUG_OBJECT (GST_BASE_PARSE (aacparse)->srcpad,
"Input is raw, trying ADTS");
gst_caps_set_simple (src_caps, "stream-format", G_TYPE_STRING, "adts",
NULL);
if (gst_caps_can_intersect (src_caps, peercaps)) {
GST_DEBUG_OBJECT (GST_BASE_PARSE (aacparse)->srcpad,
"Caps can intersect, we will prepend ADTS headers");
gst_structure_set (cs, "stream-format", G_TYPE_STRING, "adts", NULL);
gst_structure_remove_field (cs, "codec_data");
if (gst_caps_can_intersect (convcaps, peercaps)) {
GST_DEBUG_OBJECT (aacparse, "Converting from raw to ADTS");
aacparse->output_header_type = DSPAAC_HEADER_ADTS;
gst_caps_replace (&src_caps, convcaps);
}
}
gst_caps_unref (convcaps);
}
if (peercaps)
gst_caps_unref (peercaps);