summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>2009-06-11 15:54:42 +0200
committerMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>2009-06-19 18:13:06 +0200
commite29be2546f1fefc35a78a85efc336810ac2f2c2c (patch)
tree1c5a04c846f3f4227bd53c5e7016fd952a427d16
parent5b672ed441ad9a4b48dd778a2718117c1bd1bcb1 (diff)
qtmux: only use (64-bit) extended (mdat) atom size if needed. Fixes #585319.
-rw-r--r--gst/qtmux/atoms.c3
-rw-r--r--gst/qtmux/gstqtmux.c58
-rw-r--r--gst/qtmux/gstqtmux.h2
3 files changed, 42 insertions, 21 deletions
diff --git a/gst/qtmux/atoms.c b/gst/qtmux/atoms.c
index d223c1292..29859d004 100644
--- a/gst/qtmux/atoms.c
+++ b/gst/qtmux/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/qtmux/gstqtmux.c b/gst/qtmux/gstqtmux.c
index bf8036ee2..8d811f41a 100644
--- a/gst/qtmux/gstqtmux.c
+++ b/gst/qtmux/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/qtmux/gstqtmux.h b/gst/qtmux/gstqtmux.h
index a4701cc1a..567773a03 100644
--- a/gst/qtmux/gstqtmux.h
+++ b/gst/qtmux/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 */