[FFmpeg-devel] [PATCH 7/7] lavf/flacenc: generate timestamps internally
Rodger Combs
rodger.combs at gmail.com
Tue Aug 1 09:33:54 EEST 2017
---
libavformat/flacenc.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 85 insertions(+), 3 deletions(-)
diff --git a/libavformat/flacenc.c b/libavformat/flacenc.c
index 1906aee..f569c14 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,9 @@ typedef struct FlacMuxerContext {
uint8_t *streaminfo;
unsigned attached_types;
+
+ uint64_t samples;
+ unsigned last_bs;
} FlacMuxerContext;
static int flac_write_block_padding(AVIOContext *pb, unsigned int n_padding_bytes,
@@ -263,11 +267,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 +291,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;
+
+ 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;
+ }
+ if ((header[1] & 1) == 0)
+ pts /= c->last_bs ? c->last_bs : bs;
+
+ c->last_bs = bs;
+
+ 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 +405,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 {
--
2.6.4
More information about the ffmpeg-devel
mailing list