From c3f462d9b2b2bd893128d43bb3a28eeac7cf9bee Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Thu, 11 Jun 2009 15:54:42 +0200 Subject: [PATCH] qtmux: only use (64-bit) extended (mdat) atom size if needed. Fixes #585319. --- gst/quicktime/atoms.c | 3 --- gst/quicktime/gstqtmux.c | 58 ++++++++++++++++++++++++++++++++++-------------- gst/quicktime/gstqtmux.h | 2 +- 3 files changed, 42 insertions(+), 21 deletions(-) diff --git a/gst/quicktime/atoms.c b/gst/quicktime/atoms.c index d223c12..29859d0 100644 --- a/gst/quicktime/atoms.c +++ b/gst/quicktime/atoms.c @@ -1243,9 +1243,6 @@ atom_copy_data (Atom * atom, guint8 ** buffer, guint64 * size, guint64 * offset) * would be a problem for size (re)write code, not to mention memory */ g_return_val_if_fail (atom->type == FOURCC_mdat, 0); prop_copy_uint64 (atom->extended_size, buffer, size, offset); - } else { - /* just in case some trivially derived atom does not do so */ - atom_write_size (buffer, size, offset, original_offset); } return *offset - original_offset; diff --git a/gst/quicktime/gstqtmux.c b/gst/quicktime/gstqtmux.c index bf8036e..8d811f4 100644 --- a/gst/quicktime/gstqtmux.c +++ b/gst/quicktime/gstqtmux.c @@ -111,7 +111,9 @@ enum PROP_FAST_START_TEMP_FILE }; -#define MDAT_ATOM_HEADER_SIZE 16 +/* some spare for header size as well */ +#define MDAT_LARGE_FILE_LIMIT ((guint64) 1024 * 1024 * 1024 * 2) + #define DEFAULT_LARGE_FILE FALSE #define DEFAULT_MOVIE_TIMESCALE 1000 #define DEFAULT_DO_CTTS FALSE @@ -815,7 +817,7 @@ gst_qt_mux_send_buffer (GstQTMux * qtmux, GstBuffer * buf, guint64 * offset, res = gst_pad_push (qtmux->srcpad, buf); } - if (offset) + if (G_LIKELY (offset)) *offset += size; return res; @@ -905,7 +907,8 @@ seek_failed: * seek back to it later and update when the streams have finished. */ static GstFlowReturn -gst_qt_mux_send_mdat_header (GstQTMux * qtmux, guint64 * off, guint64 size) +gst_qt_mux_send_mdat_header (GstQTMux * qtmux, guint64 * off, guint64 size, + gboolean extended) { Atom *node_header; GstBuffer *buf; @@ -917,11 +920,15 @@ gst_qt_mux_send_mdat_header (GstQTMux * qtmux, guint64 * off, guint64 size) node_header = g_malloc0 (sizeof (Atom)); node_header->type = FOURCC_mdat; - /* use extended size */ - node_header->size = 1; - node_header->extended_size = 0; - if (size) - node_header->extended_size = size; + if (extended) { + /* use extended size */ + node_header->size = 1; + node_header->extended_size = 0; + if (size) + node_header->extended_size = size + 16; + } else { + node_header->size = size + 8; + } size = offset = 0; if (atom_copy_data (node_header, &data, &size, &offset) == 0) @@ -955,14 +962,31 @@ gst_qt_mux_update_mdat_size (GstQTMux * qtmux, guint64 mdat_pos, { GstEvent *event; GstBuffer *buf; + gboolean large_file; + + large_file = (mdat_size > MDAT_LARGE_FILE_LIMIT); + + if (large_file) + mdat_pos += 8; /* seek and rewrite the header */ event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, mdat_pos, GST_CLOCK_TIME_NONE, 0); gst_pad_push_event (qtmux->srcpad, event); - buf = gst_buffer_new_and_alloc (sizeof (guint64)); - GST_WRITE_UINT64_BE (GST_BUFFER_DATA (buf), mdat_size); + if (large_file) { + buf = gst_buffer_new_and_alloc (sizeof (guint64)); + GST_WRITE_UINT64_BE (GST_BUFFER_DATA (buf), mdat_size + 16); + } else { + guint8 *data; + + buf = gst_buffer_new_and_alloc (16); + data = GST_BUFFER_DATA (buf); + GST_WRITE_UINT32_BE (data, 8); + GST_WRITE_UINT32_LE (data + 4, FOURCC_free); + GST_WRITE_UINT32_BE (data + 8, mdat_size + 8); + GST_WRITE_UINT32_LE (data + 12, FOURCC_mdat); + } return gst_qt_mux_send_buffer (qtmux, buf, offset, FALSE); } @@ -1013,6 +1037,7 @@ gst_qt_mux_stop_file (GstQTMux * qtmux) /* tags into file metadata */ gst_qt_mux_setup_metadata (qtmux); + large_file = (qtmux->mdat_size > MDAT_LARGE_FILE_LIMIT); /* if faststart, update the offset of the atoms in the movie with the offset * that the movie headers before mdat will cause */ if (qtmux->fast_start_file) { @@ -1022,7 +1047,7 @@ gst_qt_mux_stop_file (GstQTMux * qtmux) goto serialize_error; GST_DEBUG_OBJECT (qtmux, "calculated moov atom size %" G_GUINT64_FORMAT, size); - offset += qtmux->header_size + MDAT_ATOM_HEADER_SIZE; + offset += qtmux->header_size + (large_file ? 16 : 8); } else offset = qtmux->header_size; atom_moov_chunks_add_offset (qtmux->moov, offset); @@ -1043,12 +1068,11 @@ gst_qt_mux_stop_file (GstQTMux * qtmux) GST_DEBUG_OBJECT (qtmux, "Pushing movie atoms"); gst_qt_mux_send_buffer (qtmux, buffer, NULL, FALSE); - /* total mdat size as of now also includes the atom header */ - qtmux->mdat_size += MDAT_ATOM_HEADER_SIZE; /* if needed, send mdat atom and move buffered data into it */ if (qtmux->fast_start_file) { /* mdat size = accumulated (buffered data) + mdat atom header */ - ret = gst_qt_mux_send_mdat_header (qtmux, NULL, qtmux->mdat_size); + ret = gst_qt_mux_send_mdat_header (qtmux, NULL, qtmux->mdat_size, + large_file); if (ret != GST_FLOW_OK) return ret; ret = gst_qt_mux_send_buffered_data (qtmux, NULL); @@ -1142,9 +1166,9 @@ gst_qt_mux_start_file (GstQTMux * qtmux) if (!qtmux->fast_start_file) goto open_failed; } else { - ret = gst_qt_mux_send_mdat_header (qtmux, &qtmux->header_size, 0); - /* mdat size position = current header pos - extended header size */ - qtmux->mdat_pos = qtmux->header_size - sizeof (guint64); + /* extended to ensure some spare space */ + qtmux->mdat_pos = qtmux->header_size; + ret = gst_qt_mux_send_mdat_header (qtmux, &qtmux->header_size, 0, TRUE); } GST_OBJECT_UNLOCK (qtmux); diff --git a/gst/quicktime/gstqtmux.h b/gst/quicktime/gstqtmux.h index a4701cc..567773a 100644 --- a/gst/quicktime/gstqtmux.h +++ b/gst/quicktime/gstqtmux.h @@ -109,7 +109,7 @@ struct _GstQTMux guint64 header_size; /* accumulated size of raw media data (a priori not including mdat header) */ guint64 mdat_size; - /* position of mdat extended size field (for later updating) */ + /* position of mdat atom (for later updating) */ guint64 mdat_pos; /* atom helper objects */ -- 2.7.4