movenc: write AAC pre-roll sample group info

Message ID 20170219215703.14895-1-stebbins@jetheaddev.com
State New
Headers show

Commit Message

John Stebbins Feb. 19, 2017, 9:57 p.m.
This recordes the number of AAC frames that must be decoded before valid
audio is decoded.

It also signals to Apple tools that the encoder delay is explicitly set
in the edit list.  If the roll sample group is omitted, Apply tools will
apply an implicit rule to remove encoder delay which would result in
removing the delay twice.
---
 libavformat/movenc.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)

Patch

diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index 840190d..689291d 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -136,6 +136,54 @@  static int mov_write_stco_tag(AVIOContext *pb, MOVTrack *track)
     return update_size(pb, pos);
 }
 
+static int mov_write_sgpd_tag(AVIOContext *pb, int16_t roll)
+{
+    int64_t pos = avio_tell(pb);
+    avio_wb32(pb, 0); /* size */
+
+    ffio_wfourcc(pb, "sgpd");
+    avio_w8(pb, 1); /* version */
+    avio_w8(pb, 0); /* flags (1) */
+    avio_wb16(pb, 0); /* flags (2) */
+    ffio_wfourcc(pb, "roll"); /* grouping type */
+    avio_wb32(pb, 2); /* table entry length */
+    avio_wb32(pb, 1); /* table entry count */
+
+    /* table data, roll distance
+     * i.e. number of audio frames to pre-roll after a seek */
+    avio_wb16(pb, roll);
+
+    return update_size(pb, pos);
+}
+
+static int mov_write_sbgp_tag(AVIOContext *pb, MOVTrack *track)
+{
+    int count = 0;
+    int i;
+    int64_t pos;
+
+    for (i = 0; i < track->entry; i++)
+    {
+        count += track->cluster[i].entries;
+    }
+
+    pos = avio_tell(pb);
+    avio_wb32(pb, 0); /* size */
+
+    ffio_wfourcc(pb, "sbgp"); /* atom name */
+    avio_wb32(pb, 0); /* version & flags */
+    ffio_wfourcc(pb, "roll"); /* grouping type */
+    avio_wb32(pb, 1); /* table entry count */
+
+    /* table data */
+    avio_wb32(pb, count);
+    /* sgpd table index, index values are 1 based
+     * we write 'roll' sample group at index 1 */
+    avio_wb32(pb, 1);
+
+    return update_size(pb, pos);
+}
+
 /* Sample size atom */
 static int mov_write_stsz_tag(AVIOContext *pb, MOVTrack *track)
 {
@@ -1277,6 +1325,19 @@  static int mov_write_stbl_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra
     mov_write_stsc_tag(pb, track);
     mov_write_stsz_tag(pb, track);
     mov_write_stco_tag(pb, track);
+
+    if (track->par->codec_id == AV_CODEC_ID_AAC)
+    {
+        /* Add sgpd and sbgp tags for AAC tracks.
+         * Apple documentation says they use this as a flag to indicate
+         * that AAC encoder delay is explicitely set in the edit list.
+         * If this is omitted, Apple tools will apply an implicit
+         * rule to remove encoder delay samples, which results in
+         * removal of 2 * delay and A/V desync. */
+        mov_write_sgpd_tag(pb, -1);
+        mov_write_sbgp_tag(pb, track);
+    }
+
     return update_size(pb, pos);
 }