isomp4: Implement robust muxing using ping-pong strategy
Implement a robust recording mode, where the output
file is always in a playable state, seeking and rewriting
the moov header at a configurable interval. Rewriting
moov is done using reserved space at the start of
the file, and a ping-pong strategy where the moov
is replaced atomically so it's never invalid.
Track when tags have actually changed, and don't write them into
the moov unless they've changed. Clear any existing tags when
re-writing them, so we can do progressive moov updating in robust
recording mode.
Write placeholder mdat as a free atom plus a 32-bit mdat
with '0' size, which means "rest of the file" in the spec.
Re-write it later to a full 64-bit extended size atom if needed.
diff --git a/gst/isomp4/atoms.c b/gst/isomp4/atoms.c
index 4ac7670..c300e67 100644
--- a/gst/isomp4/atoms.c
+++ b/gst/isomp4/atoms.c
@@ -1132,6 +1132,20 @@
atom_info_list_free (udta->entries);
}
+/* Clear added tags, but keep the context/flavor the same */
+void
+atom_udta_clear_tags (AtomUDTA * udta)
+{
+ if (udta->entries) {
+ atom_info_list_free (udta->entries);
+ udta->entries = NULL;
+ }
+ if (udta->meta && udta->meta->ilst->entries) {
+ atom_info_list_free (udta->meta->ilst->entries);
+ udta->meta->ilst->entries = NULL;
+ }
+}
+
static void
atom_tag_data_init (AtomTagData * data)
{
@@ -1980,12 +1994,13 @@
prop_copy_ensure_buffer (buffer, size, offset,
8 * atom_array_get_len (&stco64->entries));
for (i = 0; i < atom_array_get_len (&stco64->entries); i++) {
- guint64 *value = &atom_array_index (&stco64->entries, i);
+ guint64 value =
+ atom_array_index (&stco64->entries, i) + stco64->chunk_offset;
if (trunc_to_32) {
- prop_copy_uint32 ((guint32) * value, buffer, size, offset);
+ prop_copy_uint32 ((guint32) value, buffer, size, offset);
} else {
- prop_copy_uint64 (*value, buffer, size, offset);
+ prop_copy_uint64 (value, buffer, size, offset);
}
}
@@ -2749,6 +2764,12 @@
atom_moov_add_trex (moov, atom_trex_new (trak));
}
+guint
+atom_moov_get_trak_count (AtomMOOV * moov)
+{
+ return g_list_length (moov->traks);
+}
+
static guint64
atom_trak_get_duration (AtomTRAK * trak)
{
@@ -2821,28 +2842,27 @@
}
void
-atom_stco64_chunks_add_offset (AtomSTCO64 * stco64, guint32 offset)
+atom_stco64_chunks_set_offset (AtomSTCO64 * stco64, guint32 offset)
{
- guint i;
-
- for (i = 0; i < atom_array_get_len (&stco64->entries); i++) {
- guint64 *value = &atom_array_index (&stco64->entries, i);
-
- *value += offset;
- }
+ stco64->chunk_offset = offset;
}
void
-atom_moov_chunks_add_offset (AtomMOOV * moov, guint32 offset)
+atom_moov_chunks_set_offset (AtomMOOV * moov, guint32 offset)
{
GList *traks = moov->traks;
+ if (offset == moov->chunks_offset)
+ return; /* Nothing to do */
+
while (traks) {
AtomTRAK *trak = (AtomTRAK *) traks->data;
- atom_stco64_chunks_add_offset (&trak->mdia.minf.stbl.stco64, offset);
+ atom_stco64_chunks_set_offset (&trak->mdia.minf.stbl.stco64, offset);
traks = g_list_next (traks);
}
+
+ moov->chunks_offset = offset;
}
void