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 */
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;

View file

@ -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);

View file

@ -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 */