gst/qtdemux/qtdemux.*: Make push-based work if mdat atom is before moov atom.

Original commit message from CVS:
* gst/qtdemux/qtdemux.c: (gst_qtdemux_init),
(gst_qtdemux_handle_src_query), (gst_qtdemux_change_state),
(next_entry_size), (gst_qtdemux_chain):
* gst/qtdemux/qtdemux.h:
Make push-based work if mdat atom is before moov atom.
Don't answer duration query. This should be transformed into replying
FALSE to seek events.
This commit is contained in:
Edward Hervey 2006-02-14 18:50:13 +00:00
parent fed4575aef
commit 45dd1af710
2 changed files with 58 additions and 17 deletions

View file

@ -104,6 +104,7 @@ enum QtDemuxState
QTDEMUX_STATE_INITIAL, /* Initial state (haven't got the header yet) */ QTDEMUX_STATE_INITIAL, /* Initial state (haven't got the header yet) */
QTDEMUX_STATE_HEADER, /* Parsing the header */ QTDEMUX_STATE_HEADER, /* Parsing the header */
QTDEMUX_STATE_MOVIE, /* Parsing/Playing the media data */ QTDEMUX_STATE_MOVIE, /* Parsing/Playing the media data */
QTDEMUX_STATE_BUFFER_MDAT, /* Buffering the mdat atom */
}; };
static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc); static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
@ -242,6 +243,9 @@ gst_qtdemux_init (GstQTDemux * qtdemux)
qtdemux->neededbytes = 16; qtdemux->neededbytes = 16;
qtdemux->todrop = 0; qtdemux->todrop = 0;
qtdemux->adapter = gst_adapter_new (); qtdemux->adapter = gst_adapter_new ();
qtdemux->offset = 0;
qtdemux->mdatoffset = GST_CLOCK_TIME_NONE;
qtdemux->mdatbuffer = NULL;
} }
#if 0 #if 0
@ -324,7 +328,8 @@ gst_qtdemux_handle_src_query (GstPad * pad, GstQuery * query)
} }
break; break;
case GST_QUERY_DURATION: case GST_QUERY_DURATION:
if (qtdemux->duration != 0 && qtdemux->timescale != 0) { if (qtdemux->pullbased && qtdemux->duration != 0
&& qtdemux->timescale != 0) {
gint64 duration; gint64 duration;
duration = gst_util_uint64_scale_int (qtdemux->duration, duration = gst_util_uint64_scale_int (qtdemux->duration,
@ -498,6 +503,10 @@ gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
qtdemux->todrop = 0; qtdemux->todrop = 0;
qtdemux->pullbased = FALSE; qtdemux->pullbased = FALSE;
qtdemux->offset = 0; qtdemux->offset = 0;
qtdemux->mdatoffset = GST_CLOCK_TIME_NONE;
if (qtdemux->mdatbuffer)
gst_buffer_unref (qtdemux->mdatbuffer);
qtdemux->mdatbuffer = NULL;
gst_adapter_clear (qtdemux->adapter); gst_adapter_clear (qtdemux->adapter);
for (n = 0; n < qtdemux->n_streams; n++) { for (n = 0; n < qtdemux->n_streams; n++) {
gst_element_remove_pad (element, qtdemux->streams[n]->pad); gst_element_remove_pad (element, qtdemux->streams[n]->pad);
@ -775,8 +784,9 @@ next_entry_size (GstQTDemux * demux)
stream->samples[stream->sample_index].size, stream->samples[stream->sample_index].size,
stream->samples[stream->sample_index].chunk); stream->samples[stream->sample_index].chunk);
if ((smalloffs == -1) if (((smalloffs == -1)
|| (stream->samples[stream->sample_index].offset < smalloffs)) { || (stream->samples[stream->sample_index].offset < smalloffs))
&& (stream->samples[stream->sample_index].size)) {
smallidx = i; smallidx = i;
smalloffs = stream->samples[stream->sample_index].offset; smalloffs = stream->samples[stream->sample_index].offset;
} }
@ -812,7 +822,7 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
inbuf, demux->neededbytes, gst_adapter_available (demux->adapter)); inbuf, demux->neededbytes, gst_adapter_available (demux->adapter));
while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) && while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
ret == GST_FLOW_OK) { (ret == GST_FLOW_OK)) {
GST_DEBUG_OBJECT (demux, GST_DEBUG_OBJECT (demux,
"state:%d , demux->neededbytes:%d, demux->offset:%lld", demux->state, "state:%d , demux->neededbytes:%d, demux->offset:%lld", demux->state,
@ -832,16 +842,14 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
"Peeking found [%" GST_FOURCC_FORMAT "] size:%ld", "Peeking found [%" GST_FOURCC_FORMAT "] size:%ld",
GST_FOURCC_ARGS (fourcc), size); GST_FOURCC_ARGS (fourcc), size);
if ((fourcc == GST_MAKE_FOURCC ('m', 'd', 'a', 't'))) { if ((fourcc == GST_MAKE_FOURCC ('m', 'd', 'a', 't'))) {
if (demux->n_streams <= 0) { if (demux->n_streams > 0) {
GST_ELEMENT_ERROR (demux, STREAM, FAILED, demux->state = QTDEMUX_STATE_MOVIE;
(NULL), demux->neededbytes = next_entry_size (demux);
("Can't handled files with header after data in push-mode!")); } else {
ret = GST_FLOW_ERROR; demux->state = QTDEMUX_STATE_BUFFER_MDAT;
demux->neededbytes = size;
demux->mdatoffset = demux->offset;
} }
demux->state = QTDEMUX_STATE_MOVIE;
demux->offset += 24;
gst_adapter_flush (demux->adapter, 24);
demux->neededbytes = next_entry_size (demux);
} else { } else {
demux->neededbytes = size; demux->neededbytes = size;
demux->state = QTDEMUX_STATE_HEADER; demux->state = QTDEMUX_STATE_HEADER;
@ -862,7 +870,6 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
if (fourcc == GST_MAKE_FOURCC ('m', 'o', 'o', 'v')) { if (fourcc == GST_MAKE_FOURCC ('m', 'o', 'o', 'v')) {
GST_DEBUG_OBJECT (demux, "Parsing [moov]"); GST_DEBUG_OBJECT (demux, "Parsing [moov]");
demux->offset += demux->neededbytes;
qtdemux_parse_moov (demux, data, demux->neededbytes); qtdemux_parse_moov (demux, data, demux->neededbytes);
qtdemux_node_dump (demux, demux->moov_node); qtdemux_node_dump (demux, demux->moov_node);
qtdemux_parse_tree (demux); qtdemux_parse_tree (demux);
@ -870,14 +877,28 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
g_node_destroy (demux->moov_node); g_node_destroy (demux->moov_node);
g_free (data); g_free (data);
demux->moov_node = NULL; demux->moov_node = NULL;
demux->neededbytes = 16;
demux->state = QTDEMUX_STATE_INITIAL;
} else { } else {
GST_WARNING_OBJECT (demux, GST_WARNING_OBJECT (demux,
"Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT, "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
GST_FOURCC_ARGS (fourcc)); GST_FOURCC_ARGS (fourcc));
/* Let's jump that one and go back to initial state */ /* Let's jump that one and go back to initial state */
}
GST_DEBUG_OBJECT (demux, "Finished parsing the header");
if (demux->mdatbuffer && demux->n_streams) {
/* the mdat was before the header */
GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
demux->n_streams, demux->mdatbuffer);
gst_adapter_clear (demux->adapter);
GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
GST_FOURCC_ARGS (GST_READ_UINT32_BE (demux->mdatbuffer)));
gst_adapter_push (demux->adapter, demux->mdatbuffer);
demux->mdatbuffer = NULL;
demux->offset = demux->mdatoffset;
demux->neededbytes = next_entry_size (demux);
demux->state = QTDEMUX_STATE_MOVIE;
} else {
GST_DEBUG_OBJECT (demux, "Carrying on normally");
demux->offset += demux->neededbytes; demux->offset += demux->neededbytes;
demux->neededbytes = 16; demux->neededbytes = 16;
demux->state = QTDEMUX_STATE_INITIAL; demux->state = QTDEMUX_STATE_INITIAL;
@ -885,6 +906,23 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
} }
break; break;
case QTDEMUX_STATE_BUFFER_MDAT:{
GST_DEBUG_OBJECT (demux, "Got our buffer at offset %lld",
demux->mdatoffset);
if (demux->mdatbuffer)
gst_buffer_unref (demux->mdatbuffer);
demux->mdatbuffer = gst_buffer_new ();
gst_buffer_set_data (demux->mdatbuffer,
gst_adapter_take (demux->adapter, demux->neededbytes),
demux->neededbytes);
GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
GST_FOURCC_ARGS (GST_READ_UINT32_BE (demux->mdatbuffer)));
demux->offset += demux->neededbytes;
demux->neededbytes = 16;
demux->state = QTDEMUX_STATE_INITIAL;
}
break;
case QTDEMUX_STATE_MOVIE:{ case QTDEMUX_STATE_MOVIE:{
guint8 *data; guint8 *data;
GstBuffer *outbuf; GstBuffer *outbuf;

View file

@ -68,9 +68,12 @@ struct _GstQTDemux {
guint neededbytes; guint neededbytes;
guint todrop; guint todrop;
GstAdapter *adapter; GstAdapter *adapter;
GstBuffer *mdatbuffer;
/* offset of the media data (i.e.: Size of header) */ /* offset of the media data (i.e.: Size of header) */
guint64 offset; guint64 offset;
/* offset of the mdat atom */
guint64 mdatoffset;
GstTagList *tag_list; GstTagList *tag_list;