qtdemux: fragmented support for push mode

This commit is contained in:
Mark Nauwelaerts 2010-11-04 14:07:56 +01:00
parent d66a3db6b8
commit dfa54ed8cb
2 changed files with 63 additions and 13 deletions

View file

@ -1385,7 +1385,8 @@ gst_qtdemux_handle_src_event (GstPad * pad, GstEvent * event)
}
if (qtdemux->pullbased) {
res = gst_qtdemux_do_seek (qtdemux, pad, event);
} else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams) {
} else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams &&
!qtdemux->fragmented) {
res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
} else {
GST_DEBUG_OBJECT (qtdemux,
@ -3159,7 +3160,8 @@ gst_qtdemux_sync_streams (GstQTDemux * demux)
continue;
} else {
/* push mode is byte position based */
if (stream->samples[stream->n_samples - 1].offset >= demux->offset)
if (stream->n_samples &&
stream->samples[stream->n_samples - 1].offset >= demux->offset)
continue;
}
@ -3836,13 +3838,6 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
guint32 fourcc;
guint64 size;
/* prepare newsegment to send when streaming actually starts */
if (!demux->pending_newsegment) {
demux->pending_newsegment =
gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
0, GST_CLOCK_TIME_NONE, 0);
}
data = gst_adapter_peek (demux->adapter, demux->neededbytes);
/* get fourcc/length, set neededbytes */
@ -3862,6 +3857,7 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
/* we have the headers, start playback */
demux->state = QTDEMUX_STATE_MOVIE;
demux->neededbytes = next_entry_size (demux);
demux->mdatleft = size;
/* Only post, event on pads is done after newsegment */
qtdemux_post_global_tags (demux);
@ -3942,6 +3938,13 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
demux->got_moov = TRUE;
/* prepare newsegment to send when streaming actually starts */
if (!demux->pending_newsegment) {
demux->pending_newsegment =
gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
0, GST_CLOCK_TIME_NONE, 0);
}
qtdemux_parse_moov (demux, data, demux->neededbytes);
qtdemux_node_dump (demux, demux->moov_node);
qtdemux_parse_tree (demux);
@ -3950,6 +3953,15 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
g_node_destroy (demux->moov_node);
demux->moov_node = NULL;
GST_DEBUG_OBJECT (demux, "Finished parsing the header");
} else if (fourcc == FOURCC_moof) {
if (demux->got_moov && demux->fragmented) {
GST_DEBUG_OBJECT (demux, "Parsing [moof]");
if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
demux->offset, NULL))
return GST_FLOW_ERROR;
} else {
GST_DEBUG_OBJECT (demux, "Discarding [moof]");
}
} else if (fourcc == FOURCC_ftyp) {
GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
qtdemux_parse_ftyp (demux, data, demux->neededbytes);
@ -3975,12 +3987,11 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
buf = gst_adapter_take_buffer (demux->adapter,
gst_adapter_available (demux->adapter));
gst_adapter_clear (demux->adapter);
gst_adapter_push (demux->adapter, demux->mdatbuffer);
gst_adapter_push (demux->adapter, buf);
demux->mdatbuffer = NULL;
demux->offset = demux->mdatoffset;
demux->neededbytes = next_entry_size (demux);
demux->state = QTDEMUX_STATE_MOVIE;
demux->mdatleft = gst_adapter_available (demux->adapter);
/* Only post, event on pads is done after newsegment */
qtdemux_post_global_tags (demux);
@ -4038,6 +4049,33 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
GST_DEBUG_OBJECT (demux,
"BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
if (demux->fragmented) {
GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
demux->mdatleft);
if (G_LIKELY (demux->todrop < demux->mdatleft)) {
/* if needed data starts within this atom,
* then it should not exceed this atom */
if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
(_("This file is invalid and cannot be played.")),
("sample data crosses atom boundary"));
ret = GST_FLOW_ERROR;
break;
}
demux->mdatleft -= demux->neededbytes;
} else {
GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
/* so we are dropping more than left in this atom */
demux->todrop -= demux->mdatleft;
demux->neededbytes -= demux->mdatleft;
demux->mdatleft = 0;
/* need to resume atom parsing so we do not miss any other pieces */
demux->state = QTDEMUX_STATE_INITIAL;
demux->neededbytes = 16;
break;
}
}
if (demux->todrop) {
GST_LOG_OBJECT (demux, "Dropping %d bytes", demux->todrop);
gst_adapter_flush (demux->adapter, demux->todrop);
@ -4104,8 +4142,16 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
demux->offset);
if ((demux->neededbytes = next_entry_size (demux)) == -1)
if ((demux->neededbytes = next_entry_size (demux)) == -1) {
if (demux->fragmented) {
GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
/* there may be more to follow, only finish this atom */
demux->todrop = demux->mdatleft;
demux->neededbytes = demux->todrop;
break;
}
goto eos;
}
break;
}
default:
@ -7155,7 +7201,10 @@ qtdemux_expose_streams (GstQTDemux * qtdemux)
qtdemux->moof_offset = 0;
}
if (G_UNLIKELY (!stream->n_samples)) {
/* in pull mode, we should have parsed some sample info by now;
* and quite some code will not handle no samples.
* in push mode, we'll just have to deal with it */
if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
gst_qtdemux_stream_free (qtdemux, stream);
memmove (&(qtdemux->streams[i]), &(qtdemux->streams[i + 1]),

View file

@ -87,6 +87,7 @@ struct _GstQTDemux {
guint todrop;
GstAdapter *adapter;
GstBuffer *mdatbuffer;
guint64 mdatleft;
/* offset of the media data (i.e.: Size of header) */
guint64 offset;