diff options
author | Sebastian Dröge <sebastian@centricular.com> | 2015-03-24 12:46:19 +0100 |
---|---|---|
committer | Sebastian Dröge <sebastian@centricular.com> | 2015-03-24 16:15:04 +0100 |
commit | c9b42951fefaeb4afbad2f84ff845375424f8bcb (patch) | |
tree | 079358beff43287eb841dff76165c7925f650dee | |
parent | 5e88b532122bab23227a010b1ca9790c595fd780 (diff) |
flvdemux: Don't create AAC/H264 caps without codec_data
Instead delay creating the caps until we read the codec_data from the stream,
or fail if we get normal data before the codec_data.
AAC raw caps and H264 avc caps always need codec_data, setting caps on the pad
without them is going to make negotiation fail most of the time. Even if we
later set new caps with the codec_data, that's usually going to be too late.
https://bugzilla.gnome.org/show_bug.cgi?id=746682
-rw-r--r-- | gst/flv/gstflvdemux.c | 115 |
1 files changed, 74 insertions, 41 deletions
diff --git a/gst/flv/gstflvdemux.c b/gst/flv/gstflvdemux.c index 175d07e5e..43ac53dd4 100644 --- a/gst/flv/gstflvdemux.c +++ b/gst/flv/gstflvdemux.c @@ -704,29 +704,32 @@ gst_flv_demux_audio_negotiate (GstFlvDemux * demux, guint32 codec_tag, break; case 10: { - if (demux->audio_codec_data) { - GstMapInfo map; + GstMapInfo map; + if (!demux->audio_codec_data) { + GST_DEBUG_OBJECT (demux, "don't have AAC codec data yet"); + ret = TRUE; + goto done; + } - gst_buffer_map (demux->audio_codec_data, &map, GST_MAP_READ); + gst_buffer_map (demux->audio_codec_data, &map, GST_MAP_READ); - /* use codec-data to extract and verify samplerate */ - if (map.size >= 2) { - gint freq_index; + /* use codec-data to extract and verify samplerate */ + if (map.size >= 2) { + gint freq_index; - freq_index = GST_READ_UINT16_BE (map.data); - freq_index = (freq_index & 0x0780) >> 7; - adjusted_rate = - gst_codec_utils_aac_get_sample_rate_from_index (freq_index); + freq_index = GST_READ_UINT16_BE (map.data); + freq_index = (freq_index & 0x0780) >> 7; + adjusted_rate = + gst_codec_utils_aac_get_sample_rate_from_index (freq_index); - if (adjusted_rate && (rate != adjusted_rate)) { - GST_LOG_OBJECT (demux, "Ajusting AAC sample rate %d -> %d", rate, - adjusted_rate); - } else { - adjusted_rate = rate; - } + if (adjusted_rate && (rate != adjusted_rate)) { + GST_LOG_OBJECT (demux, "Ajusting AAC sample rate %d -> %d", rate, + adjusted_rate); + } else { + adjusted_rate = rate; } - gst_buffer_unmap (demux->audio_codec_data, &map); } + gst_buffer_unmap (demux->audio_codec_data, &map); caps = gst_caps_new_simple ("audio/mpeg", "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE, @@ -823,6 +826,7 @@ gst_flv_demux_audio_negotiate (GstFlvDemux * demux, guint32 codec_tag, ret = gst_pad_set_caps (demux->audio_pad, caps); +done: if (G_LIKELY (ret)) { /* Store the caps we got from tags */ demux->audio_codec_tag = codec_tag; @@ -830,24 +834,29 @@ gst_flv_demux_audio_negotiate (GstFlvDemux * demux, guint32 codec_tag, demux->channels = channels; demux->width = width; - codec_name = gst_pb_utils_get_codec_description (caps); + if (caps) { + codec_name = gst_pb_utils_get_codec_description (caps); - if (codec_name) { - if (demux->taglist == NULL) - demux->taglist = gst_tag_list_new_empty (); - gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE, - GST_TAG_AUDIO_CODEC, codec_name, NULL); - g_free (codec_name); - } + if (codec_name) { + if (demux->taglist == NULL) + demux->taglist = gst_tag_list_new_empty (); + gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE, + GST_TAG_AUDIO_CODEC, codec_name, NULL); + g_free (codec_name); + } - GST_DEBUG_OBJECT (demux->audio_pad, "successfully negotiated caps %" - GST_PTR_FORMAT, caps); + GST_DEBUG_OBJECT (demux->audio_pad, "successfully negotiated caps %" + GST_PTR_FORMAT, caps); + } else { + GST_DEBUG_OBJECT (demux->audio_pad, "delayed setting caps"); + } } else { GST_WARNING_OBJECT (demux->audio_pad, "failed negotiating caps %" GST_PTR_FORMAT, caps); } - gst_caps_unref (caps); + if (caps) + gst_caps_unref (caps); beach: return ret; @@ -1068,6 +1077,8 @@ gst_flv_demux_parse_tag_audio (GstFlvDemux * demux, GstBuffer * buffer) codec_tag != demux->audio_codec_tag || width != demux->width)) { GST_DEBUG_OBJECT (demux, "audio settings have changed, changing caps"); + gst_buffer_replace (&demux->audio_codec_data, NULL); + /* Negotiate caps */ if (!gst_flv_demux_audio_negotiate (demux, codec_tag, rate, channels, width)) { @@ -1107,6 +1118,12 @@ gst_flv_demux_parse_tag_audio (GstFlvDemux * demux, GstBuffer * buffer) goto beach; } case 1: + if (!demux->audio_codec_data) { + GST_ERROR_OBJECT (demux, "got AAC audio packet before codec data"); + ret = GST_FLOW_OK; + gst_buffer_unref (outbuf); + goto beach; + } /* AAC raw packet */ GST_LOG_OBJECT (demux, "got a raw AAC audio packet"); break; @@ -1239,6 +1256,11 @@ gst_flv_demux_video_negotiate (GstFlvDemux * demux, guint32 codec_tag) caps = gst_caps_new_empty_simple ("video/x-vp6-alpha"); break; case 7: + if (!demux->video_codec_data) { + GST_DEBUG_OBJECT (demux, "don't have h264 codec data yet"); + ret = TRUE; + goto done; + } caps = gst_caps_new_simple ("video/x-h264", "stream-format", G_TYPE_STRING, "avc", NULL); @@ -1290,28 +1312,34 @@ gst_flv_demux_video_negotiate (GstFlvDemux * demux, guint32 codec_tag) gst_pad_push_event (demux->video_pad, event); ret = gst_pad_set_caps (demux->video_pad, caps); +done: if (G_LIKELY (ret)) { /* Store the caps we have set */ demux->video_codec_tag = codec_tag; - codec_name = gst_pb_utils_get_codec_description (caps); + if (caps) { + codec_name = gst_pb_utils_get_codec_description (caps); - if (codec_name) { - if (demux->taglist == NULL) - demux->taglist = gst_tag_list_new_empty (); - gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE, - GST_TAG_VIDEO_CODEC, codec_name, NULL); - g_free (codec_name); - } + if (codec_name) { + if (demux->taglist == NULL) + demux->taglist = gst_tag_list_new_empty (); + gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE, + GST_TAG_VIDEO_CODEC, codec_name, NULL); + g_free (codec_name); + } - GST_DEBUG_OBJECT (demux->video_pad, "successfully negotiated caps %" - GST_PTR_FORMAT, caps); + GST_DEBUG_OBJECT (demux->video_pad, "successfully negotiated caps %" + GST_PTR_FORMAT, caps); + } else { + GST_DEBUG_OBJECT (demux->video_pad, "delayed setting caps"); + } } else { GST_WARNING_OBJECT (demux->video_pad, "failed negotiating caps %" GST_PTR_FORMAT, caps); } - gst_caps_unref (caps); + if (caps) + gst_caps_unref (caps); beach: return ret; @@ -1452,8 +1480,8 @@ gst_flv_demux_parse_tag_video (GstFlvDemux * demux, GstBuffer * buffer) /* Check if caps have changed */ if (G_UNLIKELY (codec_tag != demux->video_codec_tag || demux->got_par)) { - GST_DEBUG_OBJECT (demux, "video settings have changed, changing caps"); + gst_buffer_replace (&demux->video_codec_data, NULL); if (!gst_flv_demux_video_negotiate (demux, codec_tag)) { ret = GST_FLOW_ERROR; @@ -1497,6 +1525,12 @@ gst_flv_demux_parse_tag_video (GstFlvDemux * demux, GstBuffer * buffer) } case 1: /* H.264 NALU packet */ + if (!demux->video_codec_data) { + GST_ERROR_OBJECT (demux, "got H.264 video packet before codec data"); + ret = GST_FLOW_OK; + gst_buffer_unref (outbuf); + goto beach; + } GST_LOG_OBJECT (demux, "got a H.264 NALU video packet"); break; default: @@ -2357,7 +2391,6 @@ gst_flv_demux_seek_to_prev_keyframe (GstFlvDemux * demux) gst_object_unref (index); } - done: return ret; } |