Commit d7e1dcce authored by Seungha Yang's avatar Seungha Yang

qtdemux: Handle initial header state using flags

Depending on specification, qtdemux can be initialized via
* moov atom - most common case
* upstaream caps - mss use case
* meta atom - HEIF specificaton (not implemented yet)
parent f554369e
......@@ -752,7 +752,8 @@ gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
/* Sanity check: catch bogus sizes (fuzzed/broken files) */
if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
if (qtdemux->state != QTDEMUX_STATE_MOVIE &&
qtdemux->header_state != QTDEMUX_HEADER_NONE) {
/* we're pulling header but already got most interesting bits,
* so never mind the rest (e.g. tags) (that much) */
GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
......@@ -2092,6 +2093,7 @@ gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
}
}
gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
demux->header_state |= QTDEMUX_HEADER_INIT;
} else {
demux->mss_mode = FALSE;
}
......@@ -2186,7 +2188,7 @@ gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
qtdemux->mss_mode = FALSE;
gst_caps_replace (&qtdemux->media_caps, NULL);
qtdemux->timescale = 0;
qtdemux->got_moov = FALSE;
qtdemux->header_state = QTDEMUX_HEADER_NONE;
qtdemux->cenc_aux_info_offset = 0;
qtdemux->cenc_aux_info_sizes = NULL;
qtdemux->cenc_aux_sample_count = 0;
......@@ -4569,7 +4571,7 @@ gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
} else {
qtdemux->offset += length; /* skip moof and keep going */
}
if (qtdemux->got_moov) {
if ((qtdemux->header_state & QTDEMUX_HEADER_MOOV) == QTDEMUX_HEADER_MOOV) {
GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
ret = GST_FLOW_EOS;
goto beach;
......@@ -4592,7 +4594,7 @@ gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
{
GstBuffer *moov = NULL;
if (qtdemux->got_moov) {
if ((qtdemux->header_state & QTDEMUX_HEADER_MOOV) == QTDEMUX_HEADER_MOOV) {
GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
qtdemux->offset = add_offset (qtdemux->offset, length);
goto beach;
......@@ -4654,7 +4656,7 @@ gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
qtdemux->moov_node = NULL;
gst_buffer_unmap (moov, &map);
gst_buffer_unref (moov);
qtdemux->got_moov = TRUE;
qtdemux->header_state |= QTDEMUX_HEADER_MOOV;
break;
}
......@@ -4722,7 +4724,7 @@ gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
}
beach:
if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
if (ret == GST_FLOW_EOS && qtdemux->header_state != QTDEMUX_HEADER_NONE) {
/* digested all data, show what we have */
qtdemux_prepare_streams (qtdemux);
QTDEMUX_EXPOSE_LOCK (qtdemux);
......@@ -7099,7 +7101,8 @@ gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
if (fourcc == FOURCC_moov) {
/* in usual fragmented setup we could try to scan for more
* and end up at the the moov (after mdat) again */
if (demux->got_moov && QTDEMUX_N_STREAMS (demux) > 0 &&
if ((demux->header_state & QTDEMUX_HEADER_MOOV) == QTDEMUX_HEADER_MOOV
&& QTDEMUX_N_STREAMS (demux) > 0 &&
(!demux->fragmented
|| demux->last_moov_offset == demux->offset)) {
GST_DEBUG_OBJECT (demux,
......@@ -7107,7 +7110,8 @@ gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
} else {
GST_DEBUG_OBJECT (demux, "Parsing [moov]");
if (demux->got_moov && demux->fragmented) {
if ((demux->header_state & QTDEMUX_HEADER_MOOV) ==
QTDEMUX_HEADER_MOOV && demux->fragmented) {
GST_DEBUG_OBJECT (demux,
"Got a second moov, clean up data from old one");
if (demux->moov_node_compressed) {
......@@ -7135,7 +7139,7 @@ gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
qtdemux_expose_streams (demux);
QTDEMUX_EXPOSE_UNLOCK (demux);
demux->got_moov = TRUE;
demux->header_state |= QTDEMUX_HEADER_MOOV;
gst_qtdemux_check_send_pending_segment (demux);
......@@ -7149,7 +7153,7 @@ gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
GST_DEBUG_OBJECT (demux, "Finished parsing the header");
}
} else if (fourcc == FOURCC_moof) {
if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
if (demux->header_state != QTDEMUX_HEADER_NONE && demux->fragmented) {
guint64 dist = 0;
GstClockTime prev_pts;
guint64 prev_offset;
......@@ -7300,8 +7304,8 @@ gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
gst_adapter_flush (demux->adapter, demux->neededbytes);
/* only go back to the mdat if there are samples to play */
if (demux->got_moov && demux->first_mdat != -1
&& has_next_entry (demux)) {
if ((demux->header_state & QTDEMUX_HEADER_MOOV) == QTDEMUX_HEADER_MOOV
&& demux->first_mdat != -1 && has_next_entry (demux)) {
gboolean res;
/* we need to seek back */
......
......@@ -57,6 +57,13 @@ enum QtDemuxState
QTDEMUX_STATE_BUFFER_MDAT /* Buffering the mdat atom */
};
enum QtDemuxHeaderState
{
QTDEMUX_HEADER_NONE, /* Initial state (haven't got moov or initial meta yet) */
QTDEMUX_HEADER_MOOV, /* Got moov and it's parsed */
QTDEMUX_HEADER_INIT /* Got init. data via caps or 'meta' atom */
};
struct _GstQTDemux {
GstElement element;
......@@ -100,8 +107,9 @@ struct _GstQTDemux {
/* FIXME : This is never freed. It is only assigned once. memleak ? */
GNode *moov_node_compressed;
/* Set to TRUE when the [moov] header has been fully parsed */
gboolean got_moov;
/* Currrent initial header state. Depending on specification, qtdemux can
* be initialized via moov, caps, or some other way */
enum QtDemuxHeaderState header_state;
/* Global timescale for the incoming stream. Use the QTTIME macros
* to convert values to/from GstClockTime */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment