mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-25 10:04:19 +00:00
isomp4: fsync after sending updates in robust mode
Use the new GstBuffer SYNC_AFTER flag to trigger an fsync after updating the moov or mdat atom, and after updating the free atom to make it visible.
This commit is contained in:
parent
3e17cd8acb
commit
23d610140d
1 changed files with 43 additions and 22 deletions
|
@ -1543,7 +1543,7 @@ fail:
|
||||||
*/
|
*/
|
||||||
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)
|
gboolean extended, gboolean fsync_after)
|
||||||
{
|
{
|
||||||
GstBuffer *buf;
|
GstBuffer *buf;
|
||||||
GstMapInfo map;
|
GstMapInfo map;
|
||||||
|
@ -1587,6 +1587,9 @@ gst_qt_mux_send_mdat_header (GstQTMux * qtmux, guint64 * off, guint64 size,
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_LOG_OBJECT (qtmux, "Pushing mdat header");
|
GST_LOG_OBJECT (qtmux, "Pushing mdat header");
|
||||||
|
if (fsync_after)
|
||||||
|
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_SYNC_AFTER);
|
||||||
|
|
||||||
return gst_qt_mux_send_buffer (qtmux, buf, off, FALSE);
|
return gst_qt_mux_send_buffer (qtmux, buf, off, FALSE);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1597,7 +1600,7 @@ gst_qt_mux_send_mdat_header (GstQTMux * qtmux, guint64 * off, guint64 size,
|
||||||
*/
|
*/
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_qt_mux_update_mdat_size (GstQTMux * qtmux, guint64 mdat_pos,
|
gst_qt_mux_update_mdat_size (GstQTMux * qtmux, guint64 mdat_pos,
|
||||||
guint64 mdat_size, guint64 * offset)
|
guint64 mdat_size, guint64 * offset, gboolean fsync_after)
|
||||||
{
|
{
|
||||||
GstSegment segment;
|
GstSegment segment;
|
||||||
|
|
||||||
|
@ -1609,7 +1612,8 @@ gst_qt_mux_update_mdat_size (GstQTMux * qtmux, guint64 mdat_pos,
|
||||||
segment.start = mdat_pos;
|
segment.start = mdat_pos;
|
||||||
gst_pad_push_event (qtmux->srcpad, gst_event_new_segment (&segment));
|
gst_pad_push_event (qtmux->srcpad, gst_event_new_segment (&segment));
|
||||||
|
|
||||||
return gst_qt_mux_send_mdat_header (qtmux, offset, mdat_size, TRUE);
|
return gst_qt_mux_send_mdat_header (qtmux, offset, mdat_size, TRUE,
|
||||||
|
fsync_after);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
|
@ -1721,7 +1725,8 @@ gst_qt_mux_set_header_on_caps (GstQTMux * mux, GstBuffer * buf)
|
||||||
* size, but a smaller buffer is sent
|
* size, but a smaller buffer is sent
|
||||||
*/
|
*/
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_qt_mux_send_free_atom (GstQTMux * qtmux, guint64 * off, guint32 size)
|
gst_qt_mux_send_free_atom (GstQTMux * qtmux, guint64 * off, guint32 size,
|
||||||
|
gboolean fsync_after)
|
||||||
{
|
{
|
||||||
Atom *node_header;
|
Atom *node_header;
|
||||||
GstBuffer *buf;
|
GstBuffer *buf;
|
||||||
|
@ -1746,6 +1751,9 @@ gst_qt_mux_send_free_atom (GstQTMux * qtmux, guint64 * off, guint32 size)
|
||||||
buf = _gst_buffer_new_take_data (data, offset);
|
buf = _gst_buffer_new_take_data (data, offset);
|
||||||
g_free (node_header);
|
g_free (node_header);
|
||||||
|
|
||||||
|
if (fsync_after)
|
||||||
|
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_SYNC_AFTER);
|
||||||
|
|
||||||
GST_LOG_OBJECT (qtmux, "Pushing free atom");
|
GST_LOG_OBJECT (qtmux, "Pushing free atom");
|
||||||
ret = gst_qt_mux_send_buffer (qtmux, buf, off, FALSE);
|
ret = gst_qt_mux_send_buffer (qtmux, buf, off, FALSE);
|
||||||
|
|
||||||
|
@ -1804,7 +1812,7 @@ gst_qt_mux_configure_moov (GstQTMux * qtmux)
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_qt_mux_send_moov (GstQTMux * qtmux, guint64 * _offset,
|
gst_qt_mux_send_moov (GstQTMux * qtmux, guint64 * _offset,
|
||||||
guint64 padded_moov_size, gboolean mind_fast)
|
guint64 padded_moov_size, gboolean mind_fast, gboolean fsync_after)
|
||||||
{
|
{
|
||||||
guint64 offset = 0, size = 0;
|
guint64 offset = 0, size = 0;
|
||||||
guint8 *data;
|
guint8 *data;
|
||||||
|
@ -1829,13 +1837,18 @@ gst_qt_mux_send_moov (GstQTMux * qtmux, guint64 * _offset,
|
||||||
* (apparently used by a flumotion util) */
|
* (apparently used by a flumotion util) */
|
||||||
if (qtmux->state == GST_QT_MUX_STATE_EOS)
|
if (qtmux->state == GST_QT_MUX_STATE_EOS)
|
||||||
gst_qt_mux_set_header_on_caps (qtmux, buf);
|
gst_qt_mux_set_header_on_caps (qtmux, buf);
|
||||||
|
|
||||||
|
if (fsync_after)
|
||||||
|
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_SYNC_AFTER);
|
||||||
ret = gst_qt_mux_send_buffer (qtmux, buf, _offset, mind_fast);
|
ret = gst_qt_mux_send_buffer (qtmux, buf, _offset, mind_fast);
|
||||||
|
|
||||||
/* Write out a free atom if needed */
|
/* Write out a free atom if needed */
|
||||||
if (ret == GST_FLOW_OK && offset < padded_moov_size) {
|
if (ret == GST_FLOW_OK && offset < padded_moov_size) {
|
||||||
GST_LOG_OBJECT (qtmux, "Writing out free atom of size %u",
|
GST_LOG_OBJECT (qtmux, "Writing out free atom of size %u",
|
||||||
(guint32) (padded_moov_size - offset));
|
(guint32) (padded_moov_size - offset));
|
||||||
ret = gst_qt_mux_send_free_atom (qtmux, _offset, padded_moov_size - offset);
|
ret =
|
||||||
|
gst_qt_mux_send_free_atom (qtmux, _offset, padded_moov_size - offset,
|
||||||
|
fsync_after);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -2077,7 +2090,9 @@ gst_qt_mux_start_file (GstQTMux * qtmux)
|
||||||
qtmux->mdat_pos = qtmux->header_size;
|
qtmux->mdat_pos = qtmux->header_size;
|
||||||
/* extended atom in case we go over 4GB while writing and need
|
/* extended atom in case we go over 4GB while writing and need
|
||||||
* the full 64-bit atom */
|
* the full 64-bit atom */
|
||||||
ret = gst_qt_mux_send_mdat_header (qtmux, &qtmux->header_size, 0, TRUE);
|
ret =
|
||||||
|
gst_qt_mux_send_mdat_header (qtmux, &qtmux->header_size, 0, TRUE,
|
||||||
|
FALSE);
|
||||||
break;
|
break;
|
||||||
case GST_QT_MUX_MODE_ROBUST_RECORDING:
|
case GST_QT_MUX_MODE_ROBUST_RECORDING:
|
||||||
|
|
||||||
|
@ -2094,7 +2109,9 @@ gst_qt_mux_start_file (GstQTMux * qtmux)
|
||||||
/* Extra 8 bytes for the padding free atom header */
|
/* Extra 8 bytes for the padding free atom header */
|
||||||
guint padding = (guint) (16 - (qtmux->header_size % 8));
|
guint padding = (guint) (16 - (qtmux->header_size % 8));
|
||||||
GST_LOG_OBJECT (qtmux, "Rounding ftyp by %u bytes", padding);
|
GST_LOG_OBJECT (qtmux, "Rounding ftyp by %u bytes", padding);
|
||||||
ret = gst_qt_mux_send_free_atom (qtmux, &qtmux->header_size, padding);
|
ret =
|
||||||
|
gst_qt_mux_send_free_atom (qtmux, &qtmux->header_size, padding,
|
||||||
|
FALSE);
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -2109,11 +2126,11 @@ gst_qt_mux_start_file (GstQTMux * qtmux)
|
||||||
gst_qt_mux_configure_moov (qtmux);
|
gst_qt_mux_configure_moov (qtmux);
|
||||||
gst_qt_mux_setup_metadata (qtmux);
|
gst_qt_mux_setup_metadata (qtmux);
|
||||||
/* Empty free atom to begin, starting on an 8-byte boundary */
|
/* Empty free atom to begin, starting on an 8-byte boundary */
|
||||||
ret = gst_qt_mux_send_free_atom (qtmux, &qtmux->header_size, 8);
|
ret = gst_qt_mux_send_free_atom (qtmux, &qtmux->header_size, 8, FALSE);
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
return ret;
|
return ret;
|
||||||
/* Moov header, not padded yet */
|
/* Moov header, not padded yet */
|
||||||
ret = gst_qt_mux_send_moov (qtmux, &qtmux->header_size, 0, FALSE);
|
ret = gst_qt_mux_send_moov (qtmux, &qtmux->header_size, 0, FALSE, FALSE);
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
return ret;
|
return ret;
|
||||||
/* The moov we just sent contains the 'base' size of the moov, before
|
/* The moov we just sent contains the 'base' size of the moov, before
|
||||||
|
@ -2148,14 +2165,14 @@ gst_qt_mux_start_file (GstQTMux * qtmux)
|
||||||
/* Now that we know how much reserved space is targetted,
|
/* Now that we know how much reserved space is targetted,
|
||||||
* output a free atom to fill the extra reserved */
|
* output a free atom to fill the extra reserved */
|
||||||
ret = gst_qt_mux_send_free_atom (qtmux, &qtmux->header_size,
|
ret = gst_qt_mux_send_free_atom (qtmux, &qtmux->header_size,
|
||||||
qtmux->reserved_moov_size - qtmux->base_moov_size);
|
qtmux->reserved_moov_size - qtmux->base_moov_size, FALSE);
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Then a free atom containing 'pong' buffer, with an
|
/* Then a free atom containing 'pong' buffer, with an
|
||||||
* extra 8 bytes to account for the free atom header itself */
|
* extra 8 bytes to account for the free atom header itself */
|
||||||
ret = gst_qt_mux_send_free_atom (qtmux, &qtmux->header_size,
|
ret = gst_qt_mux_send_free_atom (qtmux, &qtmux->header_size,
|
||||||
qtmux->reserved_moov_size + 8);
|
qtmux->reserved_moov_size + 8, FALSE);
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -2168,7 +2185,9 @@ gst_qt_mux_start_file (GstQTMux * qtmux)
|
||||||
qtmux->mdat_pos = qtmux->header_size;
|
qtmux->mdat_pos = qtmux->header_size;
|
||||||
/* extended atom in case we go over 4GB while writing and need
|
/* extended atom in case we go over 4GB while writing and need
|
||||||
* the full 64-bit atom */
|
* the full 64-bit atom */
|
||||||
ret = gst_qt_mux_send_mdat_header (qtmux, &qtmux->header_size, 0, TRUE);
|
ret =
|
||||||
|
gst_qt_mux_send_mdat_header (qtmux, &qtmux->header_size, 0, TRUE,
|
||||||
|
FALSE);
|
||||||
break;
|
break;
|
||||||
case GST_QT_MUX_MODE_FAST_START:
|
case GST_QT_MUX_MODE_FAST_START:
|
||||||
GST_OBJECT_LOCK (qtmux);
|
GST_OBJECT_LOCK (qtmux);
|
||||||
|
@ -2195,7 +2214,7 @@ gst_qt_mux_start_file (GstQTMux * qtmux)
|
||||||
/* prepare moov and/or tags */
|
/* prepare moov and/or tags */
|
||||||
gst_qt_mux_configure_moov (qtmux);
|
gst_qt_mux_configure_moov (qtmux);
|
||||||
gst_qt_mux_setup_metadata (qtmux);
|
gst_qt_mux_setup_metadata (qtmux);
|
||||||
ret = gst_qt_mux_send_moov (qtmux, &qtmux->header_size, 0, FALSE);
|
ret = gst_qt_mux_send_moov (qtmux, &qtmux->header_size, 0, FALSE, FALSE);
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
return ret;
|
return ret;
|
||||||
/* extra atoms */
|
/* extra atoms */
|
||||||
|
@ -2432,7 +2451,7 @@ gst_qt_mux_stop_file (GstQTMux * qtmux)
|
||||||
segment.start = qtmux->moov_pos;
|
segment.start = qtmux->moov_pos;
|
||||||
gst_pad_push_event (qtmux->srcpad, gst_event_new_segment (&segment));
|
gst_pad_push_event (qtmux->srcpad, gst_event_new_segment (&segment));
|
||||||
/* no need to seek back */
|
/* no need to seek back */
|
||||||
return gst_qt_mux_send_moov (qtmux, NULL, 0, FALSE);
|
return gst_qt_mux_send_moov (qtmux, NULL, 0, FALSE, FALSE);
|
||||||
}
|
}
|
||||||
case GST_QT_MUX_MODE_ROBUST_RECORDING:{
|
case GST_QT_MUX_MODE_ROBUST_RECORDING:{
|
||||||
ret = gst_qt_mux_robust_recording_rewrite_moov (qtmux);
|
ret = gst_qt_mux_robust_recording_rewrite_moov (qtmux);
|
||||||
|
@ -2442,7 +2461,7 @@ gst_qt_mux_stop_file (GstQTMux * qtmux)
|
||||||
* it's been 0, which means 'rest of the file'
|
* it's been 0, which means 'rest of the file'
|
||||||
* No need to seek back after this, we won't write any more */
|
* No need to seek back after this, we won't write any more */
|
||||||
return gst_qt_mux_update_mdat_size (qtmux, qtmux->mdat_pos,
|
return gst_qt_mux_update_mdat_size (qtmux, qtmux->mdat_pos,
|
||||||
qtmux->mdat_size, NULL);
|
qtmux->mdat_size, NULL, TRUE);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -2494,7 +2513,7 @@ gst_qt_mux_stop_file (GstQTMux * qtmux)
|
||||||
/* write out moov and extra atoms */
|
/* write out moov and extra atoms */
|
||||||
/* note: as of this point, we no longer care about tracking written data size,
|
/* note: as of this point, we no longer care about tracking written data size,
|
||||||
* since there is no more use for it anyway */
|
* since there is no more use for it anyway */
|
||||||
ret = gst_qt_mux_send_moov (qtmux, NULL, 0, FALSE);
|
ret = gst_qt_mux_send_moov (qtmux, NULL, 0, FALSE, FALSE);
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -2509,7 +2528,7 @@ gst_qt_mux_stop_file (GstQTMux * qtmux)
|
||||||
/* mdat needs update iff not using faststart */
|
/* mdat needs update iff not using faststart */
|
||||||
GST_DEBUG_OBJECT (qtmux, "updating mdat size");
|
GST_DEBUG_OBJECT (qtmux, "updating mdat size");
|
||||||
ret = gst_qt_mux_update_mdat_size (qtmux, qtmux->mdat_pos,
|
ret = gst_qt_mux_update_mdat_size (qtmux, qtmux->mdat_pos,
|
||||||
qtmux->mdat_size, NULL);
|
qtmux->mdat_size, NULL, FALSE);
|
||||||
/* note; no seeking back to the end of file is done,
|
/* note; no seeking back to the end of file is done,
|
||||||
* since we no longer write anything anyway */
|
* since we no longer write anything anyway */
|
||||||
break;
|
break;
|
||||||
|
@ -2519,7 +2538,7 @@ gst_qt_mux_stop_file (GstQTMux * qtmux)
|
||||||
/* send mdat atom and move buffered data into it */
|
/* send mdat atom and move buffered data into it */
|
||||||
/* mdat_size = accumulated (buffered data) */
|
/* mdat_size = accumulated (buffered data) */
|
||||||
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);
|
large_file, FALSE);
|
||||||
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);
|
||||||
|
@ -2594,7 +2613,7 @@ flush:
|
||||||
atom_array_get_len (&pad->fragment_buffers), total_size);
|
atom_array_get_len (&pad->fragment_buffers), total_size);
|
||||||
if (ret == GST_FLOW_OK)
|
if (ret == GST_FLOW_OK)
|
||||||
ret = gst_qt_mux_send_mdat_header (qtmux, &qtmux->header_size, total_size,
|
ret = gst_qt_mux_send_mdat_header (qtmux, &qtmux->header_size, total_size,
|
||||||
FALSE);
|
FALSE, FALSE);
|
||||||
for (i = 0; i < atom_array_get_len (&pad->fragment_buffers); i++) {
|
for (i = 0; i < atom_array_get_len (&pad->fragment_buffers); i++) {
|
||||||
if (G_LIKELY (ret == GST_FLOW_OK))
|
if (G_LIKELY (ret == GST_FLOW_OK))
|
||||||
ret = gst_qt_mux_send_buffer (qtmux,
|
ret = gst_qt_mux_send_buffer (qtmux,
|
||||||
|
@ -2709,7 +2728,9 @@ gst_qt_mux_robust_recording_rewrite_moov (GstQTMux * qtmux)
|
||||||
segment.start = new_moov_offset;
|
segment.start = new_moov_offset;
|
||||||
gst_pad_push_event (qtmux->srcpad, gst_event_new_segment (&segment));
|
gst_pad_push_event (qtmux->srcpad, gst_event_new_segment (&segment));
|
||||||
|
|
||||||
ret = gst_qt_mux_send_moov (qtmux, NULL, qtmux->reserved_moov_size, FALSE);
|
ret =
|
||||||
|
gst_qt_mux_send_moov (qtmux, NULL, qtmux->reserved_moov_size, FALSE,
|
||||||
|
TRUE);
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -2753,7 +2774,7 @@ gst_qt_mux_robust_recording_rewrite_moov (GstQTMux * qtmux)
|
||||||
segment.start = freeA_offset;
|
segment.start = freeA_offset;
|
||||||
gst_pad_push_event (qtmux->srcpad, gst_event_new_segment (&segment));
|
gst_pad_push_event (qtmux->srcpad, gst_event_new_segment (&segment));
|
||||||
|
|
||||||
ret = gst_qt_mux_send_free_atom (qtmux, NULL, new_freeA_size);
|
ret = gst_qt_mux_send_free_atom (qtmux, NULL, new_freeA_size, TRUE);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue