qtmux: only use (64-bit) extended (mdat) atom size if needed. Fixes #585319.

This commit is contained in:
Mark Nauwelaerts 2009-06-11 15:54:42 +02:00
parent 5b672ed441
commit e29be2546f
3 changed files with 42 additions and 21 deletions

View File

@ -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 */ * would be a problem for size (re)write code, not to mention memory */
g_return_val_if_fail (atom->type == FOURCC_mdat, 0); g_return_val_if_fail (atom->type == FOURCC_mdat, 0);
prop_copy_uint64 (atom->extended_size, buffer, size, offset); 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; return *offset - original_offset;

View File

@ -111,7 +111,9 @@ enum
PROP_FAST_START_TEMP_FILE 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_LARGE_FILE FALSE
#define DEFAULT_MOVIE_TIMESCALE 1000 #define DEFAULT_MOVIE_TIMESCALE 1000
#define DEFAULT_DO_CTTS FALSE #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); res = gst_pad_push (qtmux->srcpad, buf);
} }
if (offset) if (G_LIKELY (offset))
*offset += size; *offset += size;
return res; return res;
@ -905,7 +907,8 @@ seek_failed:
* seek back to it later and update when the streams have finished. * seek back to it later and update when the streams have finished.
*/ */
static GstFlowReturn 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; Atom *node_header;
GstBuffer *buf; 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 = g_malloc0 (sizeof (Atom));
node_header->type = FOURCC_mdat; node_header->type = FOURCC_mdat;
/* use extended size */ if (extended) {
node_header->size = 1; /* use extended size */
node_header->extended_size = 0; node_header->size = 1;
if (size) node_header->extended_size = 0;
node_header->extended_size = size; if (size)
node_header->extended_size = size + 16;
} else {
node_header->size = size + 8;
}
size = offset = 0; size = offset = 0;
if (atom_copy_data (node_header, &data, &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; GstEvent *event;
GstBuffer *buf; GstBuffer *buf;
gboolean large_file;
large_file = (mdat_size > MDAT_LARGE_FILE_LIMIT);
if (large_file)
mdat_pos += 8;
/* seek and rewrite the header */ /* seek and rewrite the header */
event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES,
mdat_pos, GST_CLOCK_TIME_NONE, 0); mdat_pos, GST_CLOCK_TIME_NONE, 0);
gst_pad_push_event (qtmux->srcpad, event); gst_pad_push_event (qtmux->srcpad, event);
buf = gst_buffer_new_and_alloc (sizeof (guint64)); if (large_file) {
GST_WRITE_UINT64_BE (GST_BUFFER_DATA (buf), mdat_size); 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); 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 */ /* tags into file metadata */
gst_qt_mux_setup_metadata (qtmux); 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 /* if faststart, update the offset of the atoms in the movie with the offset
* that the movie headers before mdat will cause */ * that the movie headers before mdat will cause */
if (qtmux->fast_start_file) { if (qtmux->fast_start_file) {
@ -1022,7 +1047,7 @@ gst_qt_mux_stop_file (GstQTMux * qtmux)
goto serialize_error; goto serialize_error;
GST_DEBUG_OBJECT (qtmux, "calculated moov atom size %" G_GUINT64_FORMAT, GST_DEBUG_OBJECT (qtmux, "calculated moov atom size %" G_GUINT64_FORMAT,
size); size);
offset += qtmux->header_size + MDAT_ATOM_HEADER_SIZE; offset += qtmux->header_size + (large_file ? 16 : 8);
} else } else
offset = qtmux->header_size; offset = qtmux->header_size;
atom_moov_chunks_add_offset (qtmux->moov, offset); 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_DEBUG_OBJECT (qtmux, "Pushing movie atoms");
gst_qt_mux_send_buffer (qtmux, buffer, NULL, FALSE); 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 needed, send mdat atom and move buffered data into it */
if (qtmux->fast_start_file) { if (qtmux->fast_start_file) {
/* mdat size = accumulated (buffered data) + mdat atom header */ /* 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) if (ret != GST_FLOW_OK)
return ret; return ret;
ret = gst_qt_mux_send_buffered_data (qtmux, NULL); 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) if (!qtmux->fast_start_file)
goto open_failed; goto open_failed;
} else { } else {
ret = gst_qt_mux_send_mdat_header (qtmux, &qtmux->header_size, 0); /* extended to ensure some spare space */
/* mdat size position = current header pos - extended header size */ qtmux->mdat_pos = qtmux->header_size;
qtmux->mdat_pos = qtmux->header_size - sizeof (guint64); ret = gst_qt_mux_send_mdat_header (qtmux, &qtmux->header_size, 0, TRUE);
} }
GST_OBJECT_UNLOCK (qtmux); GST_OBJECT_UNLOCK (qtmux);

View File

@ -109,7 +109,7 @@ struct _GstQTMux
guint64 header_size; guint64 header_size;
/* accumulated size of raw media data (a priori not including mdat header) */ /* accumulated size of raw media data (a priori not including mdat header) */
guint64 mdat_size; guint64 mdat_size;
/* position of mdat extended size field (for later updating) */ /* position of mdat atom (for later updating) */
guint64 mdat_pos; guint64 mdat_pos;
/* atom helper objects */ /* atom helper objects */