mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-18 22:36:33 +00:00
qtdemux: fragmented support; handle moov samples and proper stream duration
This commit is contained in:
parent
4790603d31
commit
b7c27029e5
1 changed files with 45 additions and 18 deletions
|
@ -1664,12 +1664,19 @@ static void
|
||||||
gst_qtdemux_stbl_free (QtDemuxStream * stream)
|
gst_qtdemux_stbl_free (QtDemuxStream * stream)
|
||||||
{
|
{
|
||||||
g_free ((gpointer) stream->stco.data);
|
g_free ((gpointer) stream->stco.data);
|
||||||
|
stream->stco.data = NULL;
|
||||||
g_free ((gpointer) stream->stsz.data);
|
g_free ((gpointer) stream->stsz.data);
|
||||||
|
stream->stsz.data = NULL;
|
||||||
g_free ((gpointer) stream->stsc.data);
|
g_free ((gpointer) stream->stsc.data);
|
||||||
|
stream->stsc.data = NULL;
|
||||||
g_free ((gpointer) stream->stts.data);
|
g_free ((gpointer) stream->stts.data);
|
||||||
|
stream->stts.data = NULL;
|
||||||
g_free ((gpointer) stream->stss.data);
|
g_free ((gpointer) stream->stss.data);
|
||||||
|
stream->stss.data = NULL;
|
||||||
g_free ((gpointer) stream->stps.data);
|
g_free ((gpointer) stream->stps.data);
|
||||||
|
stream->stps.data = NULL;
|
||||||
g_free ((gpointer) stream->ctts.data);
|
g_free ((gpointer) stream->ctts.data);
|
||||||
|
stream->ctts.data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstStateChangeReturn
|
static GstStateChangeReturn
|
||||||
|
@ -4829,6 +4836,8 @@ too_many_streams:
|
||||||
static gboolean
|
static gboolean
|
||||||
qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
|
qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
|
||||||
{
|
{
|
||||||
|
stream->stbl_index = -1; /* no samples have yet been parsed */
|
||||||
|
|
||||||
/* time-to-sample atom */
|
/* time-to-sample atom */
|
||||||
if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
|
if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
|
||||||
goto corrupt_file;
|
goto corrupt_file;
|
||||||
|
@ -4964,8 +4973,15 @@ qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!stream->n_samples) {
|
if (!stream->n_samples) {
|
||||||
|
gst_qtdemux_stbl_free (stream);
|
||||||
|
if (!qtdemux->fragmented) {
|
||||||
|
/* not quite good */
|
||||||
GST_WARNING_OBJECT (qtdemux, "stream has no samples");
|
GST_WARNING_OBJECT (qtdemux, "stream has no samples");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
} else {
|
||||||
|
/* may pick up samples elsewhere */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (qtdemux,
|
GST_DEBUG_OBJECT (qtdemux,
|
||||||
|
@ -5008,8 +5024,6 @@ qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
|
||||||
goto corrupt_file;
|
goto corrupt_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream->stbl_index = -1; /* no samples have yet been parsed */
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
corrupt_file:
|
corrupt_file:
|
||||||
|
@ -5527,6 +5541,10 @@ done:
|
||||||
if (stream->segments == NULL)
|
if (stream->segments == NULL)
|
||||||
stream->segments = g_new (QtDemuxSegment, 1);
|
stream->segments = g_new (QtDemuxSegment, 1);
|
||||||
|
|
||||||
|
/* represent unknown our way */
|
||||||
|
if (stream_duration == 0)
|
||||||
|
stream_duration = -1;
|
||||||
|
|
||||||
stream->segments[0].time = 0;
|
stream->segments[0].time = 0;
|
||||||
stream->segments[0].stop_time = stream_duration;
|
stream->segments[0].stop_time = stream_duration;
|
||||||
stream->segments[0].duration = stream_duration;
|
stream->segments[0].duration = stream_duration;
|
||||||
|
@ -6838,8 +6856,19 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
|
||||||
|
|
||||||
/* collect sample information */
|
/* collect sample information */
|
||||||
if (qtdemux->fragmented) {
|
if (qtdemux->fragmented) {
|
||||||
|
/* first parse basic moov samples if any */
|
||||||
|
if (!qtdemux_stbl_init (qtdemux, stream, stbl))
|
||||||
|
goto samples_failed;
|
||||||
|
if (stream->n_samples &&
|
||||||
|
!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1))
|
||||||
|
goto samples_failed;
|
||||||
|
/* then add fragment samples */
|
||||||
if (!qtdemux_parse_mfra (qtdemux, stream))
|
if (!qtdemux_parse_mfra (qtdemux, stream))
|
||||||
goto samples_failed;
|
goto samples_failed;
|
||||||
|
/* prevent further parse_samples */
|
||||||
|
stream->stbl_index = stream->n_samples;
|
||||||
|
/* movie duration more reliable in this case (e.g. mehd) */
|
||||||
|
stream->duration = qtdemux->segment.duration;
|
||||||
} else {
|
} else {
|
||||||
if (!qtdemux_stbl_init (qtdemux, stream, stbl))
|
if (!qtdemux_stbl_init (qtdemux, stream, stbl))
|
||||||
goto samples_failed;
|
goto samples_failed;
|
||||||
|
@ -8020,24 +8049,14 @@ qtdemux_parse_tree (GstQTDemux * qtdemux)
|
||||||
|
|
||||||
/* check for fragmented file and get some (default) data */
|
/* check for fragmented file and get some (default) data */
|
||||||
mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
|
mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
|
||||||
if (mvex) {
|
|
||||||
/* let track parsing or anyone know weird stuff might happen ... */
|
|
||||||
qtdemux->fragmented = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* parse all traks */
|
|
||||||
trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
|
|
||||||
while (trak) {
|
|
||||||
qtdemux_parse_trak (qtdemux, trak);
|
|
||||||
/* iterate all siblings */
|
|
||||||
trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* compensate for total duration */
|
|
||||||
if (mvex) {
|
if (mvex) {
|
||||||
GNode *mehd;
|
GNode *mehd;
|
||||||
GstByteReader mehd_data;
|
GstByteReader mehd_data;
|
||||||
|
|
||||||
|
/* let track parsing or anyone know weird stuff might happen ... */
|
||||||
|
qtdemux->fragmented = TRUE;
|
||||||
|
|
||||||
|
/* compensate for total duration */
|
||||||
mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
|
mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
|
||||||
if (mehd)
|
if (mehd)
|
||||||
qtdemux_parse_mehd (qtdemux, &mehd_data);
|
qtdemux_parse_mehd (qtdemux, &mehd_data);
|
||||||
|
@ -8048,6 +8067,14 @@ qtdemux_parse_tree (GstQTDemux * qtdemux)
|
||||||
if (duration)
|
if (duration)
|
||||||
gst_segment_set_duration (&qtdemux->segment, GST_FORMAT_TIME, duration);
|
gst_segment_set_duration (&qtdemux->segment, GST_FORMAT_TIME, duration);
|
||||||
|
|
||||||
|
/* parse all traks */
|
||||||
|
trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
|
||||||
|
while (trak) {
|
||||||
|
qtdemux_parse_trak (qtdemux, trak);
|
||||||
|
/* iterate all siblings */
|
||||||
|
trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
|
||||||
|
}
|
||||||
|
|
||||||
gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
|
gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
|
||||||
|
|
||||||
/* find and push tags, we do this after adding the pads so we can push the
|
/* find and push tags, we do this after adding the pads so we can push the
|
||||||
|
|
Loading…
Reference in a new issue