[FFmpeg-devel,7/7] lavf/flacenc: generate timestamps internally

Submitted by Rodger Combs on Aug. 2, 2017, 6:30 a.m.

Details

Message ID 1501655445-18976-7-git-send-email-rodger.combs@gmail.com
State New
Headers show

Commit Message

Rodger Combs Aug. 2, 2017, 6:30 a.m.
---
 libavformat/flacenc.c            | 87 ++++++++++++++++++++++++++++++++++++++--
 tests/ref/acodec/flac            |  4 +-
 tests/ref/acodec/flac-exact-rice |  4 +-
 tests/ref/seek/acodec-flac       | 36 ++++++++---------
 4 files changed, 106 insertions(+), 25 deletions(-)

Patch hide | download patch | download mbox

diff --git a/libavformat/flacenc.c b/libavformat/flacenc.c
index 1906aee..39e5e2c 100644
--- a/libavformat/flacenc.c
+++ b/libavformat/flacenc.c
@@ -30,6 +30,7 @@ 
 #include "internal.h"
 #include "vorbiscomment.h"
 #include "libavcodec/bytestream.h"
+#include "libavutil/crc.h"
 
 
 typedef struct FlacMuxerContext {
@@ -46,6 +47,8 @@  typedef struct FlacMuxerContext {
     uint8_t *streaminfo;
 
     unsigned attached_types;
+
+    uint64_t samples;
 } FlacMuxerContext;
 
 static int flac_write_block_padding(AVIOContext *pb, unsigned int n_padding_bytes,
@@ -263,11 +266,17 @@  static int flac_write_header(struct AVFormatContext *s)
     return ret;
 }
 
+static const int32_t blocksize_table[16] = {
+     0,    192, 576<<0, 576<<1, 576<<2, 576<<3,      0,      0,
+256<<0, 256<<1, 256<<2, 256<<3, 256<<4, 256<<5, 256<<6, 256<<7
+};
+
 static int flac_write_audio_packet(struct AVFormatContext *s, AVPacket *pkt)
 {
     FlacMuxerContext *c = s->priv_data;
     uint8_t *streaminfo;
     int streaminfo_size;
+    char header[16];
 
     /* check for updated streaminfo */
     streaminfo = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA,
@@ -281,8 +290,77 @@  static int flac_write_audio_packet(struct AVFormatContext *s, AVPacket *pkt)
         memcpy(c->streaminfo, streaminfo, FLAC_STREAMINFO_SIZE);
     }
 
-    if (pkt->size)
-        avio_write(s->pb, pkt->data, pkt->size);
+    if (pkt->size) {
+        uint8_t tmp;
+        uint64_t pts = c->samples;
+        int offset = 5;
+        int headerlen = 4;
+        int bscode, bs;
+        int crc;
+        if (pkt->size < FLAC_MIN_FRAME_SIZE)
+            return AVERROR_INVALIDDATA;
+        memcpy(header, pkt->data, 4);
+        if (pkt->pts == AV_NOPTS_VALUE)
+            pts = 0;
+        if ((pkt->data[4] & 0xC0) == 0xC0)
+            offset += ff_clz((unsigned char)~pkt->data[4]) - 25;
+        else if (pkt->data[4] & 0x80)
+            return AVERROR_INVALIDDATA;
+        if (pkt->size <= offset + 1)
+            return AVERROR_INVALIDDATA;
+
+        // Forcing use of sample counts instead of block counts to avoid bs
+        // mismatch issues
+        header[1] |= 1;
+
+        bscode = (unsigned char)header[2] >> 4;
+        bs = blocksize_table[bscode];
+        if (bscode == 0)
+            return AVERROR_INVALIDDATA;
+        if (bscode == 6) {
+            if (pkt->size <= offset + 1)
+                return AVERROR_INVALIDDATA;
+            bs = pkt->data[offset] + 1;
+        } else if (bscode == 7) {
+            if (pkt->size <= offset + 2)
+                return AVERROR_INVALIDDATA;
+            bs = AV_RB16(&pkt->data[offset]) + 1;
+        }
+
+        c->samples += bs;
+
+        PUT_UTF8(pts, tmp, header[headerlen++] = tmp;)
+        if (headerlen > 11)
+            return AVERROR_INVALIDDATA;
+        if ((bscode & 0xE) == 0x6)
+            header[headerlen++] = pkt->data[offset++];
+        if (pkt->size <= offset + 1)
+            return AVERROR_INVALIDDATA;
+        if (bscode == 0x7)
+            header[headerlen++] = pkt->data[offset++];
+        if (pkt->size <= offset + 1)
+            return AVERROR_INVALIDDATA;
+        if ((header[2] & 0xC) == 0xC) {
+            header[headerlen++] = pkt->data[offset++];
+            if (pkt->size <= offset + 1)
+                return AVERROR_INVALIDDATA;
+            if ((header[2] & 0x3) == 0x3)
+                return AVERROR_INVALIDDATA;
+            else if (header[2] & 0x3) {
+                header[headerlen++] = pkt->data[offset++];
+                if (pkt->size <= offset + 1)
+                    return AVERROR_INVALIDDATA;
+            }
+        }
+        header[headerlen] = av_crc(av_crc_get_table(AV_CRC_8_ATM), 0, header, headerlen);
+        headerlen++; offset++;
+        crc = av_crc(av_crc_get_table(AV_CRC_16_ANSI), 0, header, headerlen);
+        if (pkt->size < offset + 3)
+            return AVERROR_INVALIDDATA;
+        avio_write(s->pb, header, headerlen);
+        avio_write(s->pb, pkt->data + offset, pkt->size - offset - 2);
+        avio_wl16(s->pb, av_crc(av_crc_get_table(AV_CRC_16_ANSI), crc, pkt->data + offset, pkt->size - offset - 2));
+    }
     return 0;
 }
 
@@ -326,7 +404,10 @@  static int flac_write_trailer(struct AVFormatContext *s)
         /* rewrite the STREAMINFO header block data */
         file_size = avio_tell(pb);
         avio_seek(pb, 8, SEEK_SET);
-        avio_write(pb, streaminfo, FLAC_STREAMINFO_SIZE);
+        avio_write(pb, streaminfo, 13);
+        avio_w8(pb, (streaminfo[13] & 0xF0) | ((c->samples >> 32) & 0xF));
+        avio_wb32(pb, c->samples);
+        avio_write(pb, streaminfo + 18, FLAC_STREAMINFO_SIZE - 18);
         avio_seek(pb, file_size, SEEK_SET);
         avio_flush(pb);
     } else {
diff --git a/tests/ref/acodec/flac b/tests/ref/acodec/flac
index c2e7f20..ccd6568 100644
--- a/tests/ref/acodec/flac
+++ b/tests/ref/acodec/flac
@@ -1,4 +1,4 @@ 
-151eef9097f944726968bec48649f00a *tests/data/fate/acodec-flac.flac
-361582 tests/data/fate/acodec-flac.flac
+6c8b80b229c3212e6f62e0eb1e75e4b8 *tests/data/fate/acodec-flac.flac
+362110 tests/data/fate/acodec-flac.flac
 95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-flac.out.wav
 stddev:    0.00 PSNR:999.99 MAXDIFF:    0 bytes:  1058400/  1058400
diff --git a/tests/ref/acodec/flac-exact-rice b/tests/ref/acodec/flac-exact-rice
index 6f6d274..03b6971 100644
--- a/tests/ref/acodec/flac-exact-rice
+++ b/tests/ref/acodec/flac-exact-rice
@@ -1,4 +1,4 @@ 
-aab144de213ae684ca008a3e0afe5e28 *tests/data/fate/acodec-flac-exact-rice.flac
-360454 tests/data/fate/acodec-flac-exact-rice.flac
+3b019c7c003ea02c82b4608a16181faf *tests/data/fate/acodec-flac-exact-rice.flac
+360982 tests/data/fate/acodec-flac-exact-rice.flac
 95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-flac-exact-rice.out.wav
 stddev:    0.00 PSNR:999.99 MAXDIFF:    0 bytes:  1058400/  1058400
diff --git a/tests/ref/seek/acodec-flac b/tests/ref/seek/acodec-flac
index f6add9a..0b2c60f 100644
--- a/tests/ref/seek/acodec-flac
+++ b/tests/ref/seek/acodec-flac
@@ -2,52 +2,52 @@  ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:   8256 size:   614
 ret: 0         st:-1 flags:0  ts:-1.000000
 ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:   8256 size:   614
 ret: 0         st:-1 flags:1  ts: 1.894167
-ret: 0         st: 0 flags:1 dts: 1.880816 pts: 1.880816 pos:  86742 size:  2191
+ret: 0         st: 0 flags:1 dts: 1.880816 pts: 1.880816 pos:  86898 size:  2194
 ret: 0         st: 0 flags:0  ts: 0.788345
-ret: 0         st: 0 flags:1 dts: 0.809796 pts: 0.809796 pos:  27366 size:   615
+ret: 0         st: 0 flags:1 dts: 0.809796 pts: 0.809796 pos:  27425 size:   617
 ret: 0         st: 0 flags:1  ts:-0.317506
 ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:   8256 size:   614
 ret: 0         st:-1 flags:0  ts: 2.576668
-ret: 0         st: 0 flags:1 dts: 2.586122 pts: 2.586122 pos: 145606 size:  2384
+ret: 0         st: 0 flags:1 dts: 2.586122 pts: 2.586122 pos: 145843 size:  2387
 ret: 0         st:-1 flags:1  ts: 1.470835
-ret: 0         st: 0 flags:1 dts: 1.462857 pts: 1.462857 pos:  53388 size:  1851
+ret: 0         st: 0 flags:1 dts: 1.462857 pts: 1.462857 pos:  53497 size:  1853
 ret: 0         st: 0 flags:0  ts: 0.365011
-ret: 0         st: 0 flags:1 dts: 0.365714 pts: 0.365714 pos:  16890 size:   614
+ret: 0         st: 0 flags:1 dts: 0.365714 pts: 0.365714 pos:  16915 size:   616
 ret: 0         st: 0 flags:1  ts:-0.740839
 ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:   8256 size:   614
 ret: 0         st:-1 flags:0  ts: 2.153336
-ret: 0         st: 0 flags:1 dts: 2.168163 pts: 2.168163 pos: 110531 size:  2143
+ret: 0         st: 0 flags:1 dts: 2.168163 pts: 2.168163 pos: 110720 size:  2146
 ret: 0         st:-1 flags:1  ts: 1.047503
-ret: 0         st: 0 flags:1 dts: 1.044898 pts: 1.044898 pos:  32880 size:   579
+ret: 0         st: 0 flags:1 dts: 1.044898 pts: 1.044898 pos:  32957 size:   581
 ret: 0         st: 0 flags:0  ts:-0.058322
 ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:   8256 size:   614
 ret: 0         st: 0 flags:1  ts: 2.835828
-ret: 0         st: 0 flags:1 dts: 2.821224 pts: 2.821224 pos: 167112 size:  2391
+ret: 0         st: 0 flags:1 dts: 2.821224 pts: 2.821224 pos: 167376 size:  2394
 ret: 0         st:-1 flags:0  ts: 1.730004
-ret: 0         st: 0 flags:1 dts: 1.750204 pts: 1.750204 pos:  75788 size:  2191
+ret: 0         st: 0 flags:1 dts: 1.750204 pts: 1.750204 pos:  75929 size:  2194
 ret: 0         st:-1 flags:1  ts: 0.624171
-ret: 0         st: 0 flags:1 dts: 0.600816 pts: 0.600816 pos:  22446 size:   616
+ret: 0         st: 0 flags:1 dts: 0.600816 pts: 0.600816 pos:  22489 size:   618
 ret: 0         st: 0 flags:0  ts:-0.481655
 ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:   8256 size:   614
 ret: 0         st: 0 flags:1  ts: 2.412494
-ret: 0         st: 0 flags:1 dts: 2.403265 pts: 2.403265 pos: 129793 size:  2138
+ret: 0         st: 0 flags:1 dts: 2.403265 pts: 2.403265 pos: 130009 size:  2141
 ret: 0         st:-1 flags:0  ts: 1.306672
-ret: 0         st: 0 flags:1 dts: 1.332245 pts: 1.332245 pos:  44812 size:  1609
+ret: 0         st: 0 flags:1 dts: 1.332245 pts: 1.332245 pos:  44911 size:  1611
 ret: 0         st:-1 flags:1  ts: 0.200839
-ret: 0         st: 0 flags:1 dts: 0.182857 pts: 0.182857 pos:  12572 size:   628
+ret: 0         st: 0 flags:1 dts: 0.182857 pts: 0.182857 pos:  12583 size:   630
 ret: 0         st: 0 flags:0  ts:-0.904989
 ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:   8256 size:   614
 ret: 0         st: 0 flags:1  ts: 1.989184
-ret: 0         st: 0 flags:1 dts: 1.985306 pts: 1.985306 pos:  95508 size:  2169
+ret: 0         st: 0 flags:1 dts: 1.985306 pts: 1.985306 pos:  95676 size:  2172
 ret: 0         st:-1 flags:0  ts: 0.883340
-ret: 0         st: 0 flags:1 dts: 0.888163 pts: 0.888163 pos:  29211 size:   620
+ret: 0         st: 0 flags:1 dts: 0.888163 pts: 0.888163 pos:  29276 size:   622
 ret: 0         st:-1 flags:1  ts:-0.222493
 ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:   8256 size:   614
 ret: 0         st: 0 flags:0  ts: 2.671678
-ret: 0         st: 0 flags:1 dts: 2.690612 pts: 2.690612 pos: 155154 size:  2394
+ret: 0         st: 0 flags:1 dts: 2.690612 pts: 2.690612 pos: 155403 size:  2397
 ret: 0         st: 0 flags:1  ts: 1.565850
-ret: 0         st: 0 flags:1 dts: 1.541224 pts: 1.541224 pos:  59082 size:  1974
+ret: 0         st: 0 flags:1 dts: 1.541224 pts: 1.541224 pos:  59199 size:  1977
 ret: 0         st:-1 flags:0  ts: 0.460008
-ret: 0         st: 0 flags:1 dts: 0.470204 pts: 0.470204 pos:  19353 size:   608
+ret: 0         st: 0 flags:1 dts: 0.470204 pts: 0.470204 pos:  19386 size:   610
 ret: 0         st:-1 flags:1  ts:-0.645825
 ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:   8256 size:   614