mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-29 19:50:40 +00:00
qtdemux: Handle another kind of redirect trak
Some traks might contain a redirect rtsp uri inside hndl atom (which is a dref atom entry). This commit makes qtdemux post a message when it finds one of these traks and there are no other traks. Fixes #597497
This commit is contained in:
parent
06de494640
commit
92a83e016a
2 changed files with 114 additions and 1 deletions
|
@ -192,6 +192,9 @@ struct _QtDemuxStream
|
|||
GstCaps *caps;
|
||||
guint32 fourcc;
|
||||
|
||||
/* if the stream has a redirect URI in its headers, we store it here */
|
||||
gchar *redirect_uri;
|
||||
|
||||
/* duration/scale */
|
||||
guint64 duration; /* in timescale */
|
||||
guint32 timescale;
|
||||
|
@ -1679,6 +1682,7 @@ gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
|
|||
g_free (stream->segments);
|
||||
if (stream->pending_tags)
|
||||
gst_tag_list_free (stream->pending_tags);
|
||||
g_free (stream->redirect_uri);
|
||||
/* free stbl sub-atoms */
|
||||
gst_qtdemux_stbl_free (stream);
|
||||
g_free (stream);
|
||||
|
@ -4854,6 +4858,98 @@ end:
|
|||
}
|
||||
}
|
||||
|
||||
static gchar *
|
||||
qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
|
||||
{
|
||||
GNode *hndl;
|
||||
GNode *dinf;
|
||||
GstByteReader dref;
|
||||
gchar *uri = NULL;
|
||||
|
||||
/*
|
||||
* Get 'dinf', to get its child 'dref', that might contain a 'hndl'
|
||||
* atom that might contain a 'data' atom with the rtsp uri.
|
||||
* This case was reported in bug #597497, some info about
|
||||
* the hndl atom can be found in TN1195
|
||||
*/
|
||||
dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
|
||||
GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
|
||||
|
||||
if (dinf) {
|
||||
guint32 dref_num_entries;
|
||||
if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
|
||||
gst_byte_reader_skip (&dref, 4) &&
|
||||
gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
|
||||
gint i;
|
||||
hndl = NULL;
|
||||
|
||||
/* search dref entries for hndl atom */
|
||||
for (i = 0; i < dref_num_entries; i++) {
|
||||
guint32 size, type;
|
||||
guint8 string_len;
|
||||
if (gst_byte_reader_get_uint32_be (&dref, &size) &&
|
||||
qt_atom_parser_get_fourcc (&dref, &type)) {
|
||||
if (type == FOURCC_hndl) {
|
||||
GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
|
||||
|
||||
/* skip data reference handle bytes and the
|
||||
* following pascal string and some extra 4
|
||||
* bytes I have no idea what are */
|
||||
if (!gst_byte_reader_skip (&dref, 4) ||
|
||||
!gst_byte_reader_get_uint8 (&dref, &string_len) ||
|
||||
!gst_byte_reader_skip (&dref, string_len + 4)) {
|
||||
GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
|
||||
break;
|
||||
}
|
||||
|
||||
/* iterate over the atoms to find the data atom */
|
||||
while (gst_byte_reader_get_remaining (&dref) >= 8) {
|
||||
guint32 atom_size;
|
||||
guint32 atom_type;
|
||||
|
||||
if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
|
||||
qt_atom_parser_get_fourcc (&dref, &atom_type)) {
|
||||
if (atom_type == FOURCC_data) {
|
||||
const guint8 *uri_aux = NULL;
|
||||
|
||||
/* found the data atom that might contain the rtsp uri */
|
||||
GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
|
||||
"hndl atom, interpreting it as an URI");
|
||||
if (gst_byte_reader_peek_data (&dref, atom_size - 8,
|
||||
&uri_aux)) {
|
||||
if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
|
||||
uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
|
||||
else
|
||||
GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
|
||||
"didn't contain a rtsp address");
|
||||
} else {
|
||||
GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
|
||||
"atom contents");
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* skipping to the next entry */
|
||||
gst_byte_reader_skip (&dref, atom_size - 8);
|
||||
} else {
|
||||
GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
|
||||
"atom header");
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* skip to the next entry */
|
||||
gst_byte_reader_skip (&dref, size - 8);
|
||||
} else {
|
||||
GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
|
||||
}
|
||||
}
|
||||
GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
|
||||
}
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
|
||||
/* parse the traks.
|
||||
* With each track we associate a new QtDemuxStream that contains all the info
|
||||
* about the trak.
|
||||
|
@ -5659,7 +5755,9 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
|
|||
GST_FOURCC_ARGS (fourcc), stream->caps);
|
||||
|
||||
} else if (stream->subtype == FOURCC_strm) {
|
||||
if (fourcc != FOURCC_rtsp) {
|
||||
if (fourcc == FOURCC_rtsp) {
|
||||
stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
|
||||
} else {
|
||||
GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
|
||||
GST_FOURCC_ARGS (fourcc));
|
||||
goto unknown_stream;
|
||||
|
@ -6730,6 +6828,20 @@ qtdemux_parse_tree (GstQTDemux * qtdemux)
|
|||
gst_message_new_tag (GST_OBJECT (qtdemux),
|
||||
gst_tag_list_copy (qtdemux->tag_list)));
|
||||
|
||||
/* check if we should post a redirect in case there is a single trak
|
||||
* and it is a redirecting trak */
|
||||
if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
|
||||
GstMessage *m;
|
||||
GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
|
||||
"a external content");
|
||||
m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
|
||||
gst_structure_new ("redirect",
|
||||
"new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
|
||||
NULL));
|
||||
gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
|
||||
qtdemux->posted_redirect = TRUE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ G_BEGIN_DECLS
|
|||
#define FOURCC_mdia GST_MAKE_FOURCC('m','d','i','a')
|
||||
#define FOURCC_mdhd GST_MAKE_FOURCC('m','d','h','d')
|
||||
#define FOURCC_hdlr GST_MAKE_FOURCC('h','d','l','r')
|
||||
#define FOURCC_hndl GST_MAKE_FOURCC('h','n','d','l')
|
||||
#define FOURCC_minf GST_MAKE_FOURCC('m','i','n','f')
|
||||
#define FOURCC_vmhd GST_MAKE_FOURCC('v','m','h','d')
|
||||
#define FOURCC_smhd GST_MAKE_FOURCC('s','m','h','d')
|
||||
|
|
Loading…
Reference in a new issue