ref: c5d4cd0d1a217b849ecbe219d11145c872941d2b
parent: 7996b424b3ec858adcf6507c424bc5e06773e3fa
author: Sigrid Solveig Haflínudóttir <ftrvxmtrx@gmail.com>
date: Mon Feb 22 10:53:36 EST 2021
prepare matroska remuxer to handle key frames in special ways
--- a/aac.c
+++ b/aac.c
@@ -24,13 +24,13 @@
};
int
-aacpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts)
+aacpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts, int key)
{
int i, chanc, ratei, objt, sz;
u16int x;
char *c;
- USED(ts);
+ USED(ts, key);
if(ctx->frid == 0){ /* set up ADTS */
ctx->adts[0] = 0xff; /* syncword */
ctx->adts[1] = 0xf1; /* syncword, mpeg4, no crc */
--- a/matroska.c
+++ b/matroska.c
@@ -102,7 +102,7 @@
}
static int
-asispacket(Biobuf *out, Packetctx *, Packet *p, int np, uvlong)
+asispacket(Biobuf *out, Packetctx *, Packet *p, int np, uvlong, int)
{
int i;
@@ -187,11 +187,17 @@
Bprint(o, "\n");
}
+static void
+flush(Ebml *e, int refblock)
+{
+ USED(e); USED(refblock);
+}
+
int
matroskarun(Biobuf *f)
{
- vlong left, n, sz, nsz, bufsz, track, off, packetsz, x, endtracks;
- int isebml, npackets, i, skipdata, lacing;
+ vlong left, n, sz, nsz, bufsz, track, off, packetsz, x, endtracks, bgend;
+ int isebml, npackets, i, skipdata, lacing, refblock, key;
uvlong ts, timestamp, timestampscale;
double duration;
s16int timecode;
@@ -212,6 +218,8 @@
duration = 0;
skipdata = trackdump == Nodump;
el.id = 0;
+ refblock = 0;
+ bgend = 0;
for(isebml = 0; left != 0;){
if(el.id == EBlockDuration)
te.blockdur *= timestampscale;
@@ -234,6 +242,10 @@
break;
}
left -= n;
+ if(off >= bgend && !skipdata){
+ flush(&te, refblock);
+ refblock = 0;
+ }
if(el.id == EEBML){ /* EBML comes first */
if(isebml != 0){
@@ -282,6 +294,8 @@
}else if(el.id == EContentEncodings || el.id == EContentEncoding || el.id == EContentCompression){
continue;
}else if(el.id == EBlockGroup && !skipdata){
+ refblock = 0;
+ bgend = off+sz;
continue;
}else if((el.id == ESimpleBlock || el.id == EBlock) && !skipdata){
if(te.tracknum == -1)
@@ -315,6 +329,7 @@
sz -= 3;
timecode = buf[0]<<8 | buf[1];
lacing = (buf[2] >> 1) & 3;
+ key = buf[2] & 0x80;
npackets = buf[3]+1;
if(te.comp.algo == 3){ /* header stripping, need to put bytes back */
@@ -415,55 +430,56 @@
/* ns timestamp */
ts = (timestamp + timecode) * timestampscale - te.codec.delay;
- if(te.fpacket(&out, &te, packets, npackets, ts) != 0)
+ if(te.fpacket(&out, &te, packets, npackets, ts, key) != 0)
goto err;
continue;
}
- }else{
- getnumber(ETimestampScale, timestampscale)
- else
- getfloat(ESamplingFrequency, e.audio.samplerate)
- else
- getfloat(EOutputSamplingFrequency, e.audio.outsamplerate)
- else
- getnumber(EChannels, e.audio.channels)
- else
- getnumber(EBitDepth, e.audio.bps)
- else
- getnumber(ETrackNumber, e.tracknum)
- else
- getnumber(ETrackType, e.tracktype)
- else
- getstring(ECodecID, e.codec.name)
- else
- getbytes(ECodecPrivate, e.codec.priv)
- else
- getnumber(ECodecDelay, e.codec.delay)
- else
- getnumber(EContentCompAlgo, e.comp.algo)
- else
- getbytes(EContentCompSettings, e.comp)
- else
- getnumber(EPixelWidth, e.video.width)
- else
- getnumber(EPixelHeight, e.video.height)
- else
- getnumber(ETimestamp, timestamp)
- else
- getnumber(EDefaultDuration, e.perframe)
- else
- getnumber(ESeekPreRoll, e.seekpreroll)
- else
- getfloat(EDuration, duration)
- else
- getnumber(ETrackUID, e.trackuid)
- else
- getsigned(EDiscardPadding, te.discardpad)
- else
- getnumber(EBlockDuration, te.blockdur)
- else
- getstring(ELanguage, e.lang)
- }
+ }else
+ getnumber(EReferenceBlock, refblock)
+ else
+ getnumber(ETimestampScale, timestampscale)
+ else
+ getfloat(ESamplingFrequency, e.audio.samplerate)
+ else
+ getfloat(EOutputSamplingFrequency, e.audio.outsamplerate)
+ else
+ getnumber(EChannels, e.audio.channels)
+ else
+ getnumber(EBitDepth, e.audio.bps)
+ else
+ getnumber(ETrackNumber, e.tracknum)
+ else
+ getnumber(ETrackType, e.tracktype)
+ else
+ getstring(ECodecID, e.codec.name)
+ else
+ getbytes(ECodecPrivate, e.codec.priv)
+ else
+ getnumber(ECodecDelay, e.codec.delay)
+ else
+ getnumber(EContentCompAlgo, e.comp.algo)
+ else
+ getbytes(EContentCompSettings, e.comp)
+ else
+ getnumber(EPixelWidth, e.video.width)
+ else
+ getnumber(EPixelHeight, e.video.height)
+ else
+ getnumber(ETimestamp, timestamp)
+ else
+ getnumber(EDefaultDuration, e.perframe)
+ else
+ getnumber(ESeekPreRoll, e.seekpreroll)
+ else
+ getfloat(EDuration, duration)
+ else
+ getnumber(ETrackUID, e.trackuid)
+ else
+ getsigned(EDiscardPadding, te.discardpad)
+ else
+ getnumber(EBlockDuration, te.blockdur)
+ else
+ getstring(ELanguage, e.lang)
if(sz > 0){
if(Bseek(f, sz, 1) < 0)
--- a/ogg.c
+++ b/ogg.c
@@ -71,7 +71,7 @@
}
int
-oggpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts)
+oggpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts, int key)
{
/* magic vendor len list len */
u8int opuscomment[] = {'O','p','u','s','T','a','g','s', 0,0,0,0, 0,0,0,0};
@@ -81,8 +81,8 @@
int sgszs[4];
Packet onep;
+ USED(key);
ts += ctx->seekpreroll - ctx->discardpad;
- gr = (ts * 48) / 1000000;
if(ctx->frid == 0){ /* first packet? */
d = ctx->codec.priv.data;
@@ -128,6 +128,12 @@
if(packet(out, ctx, 0, &onep, 1, 0) != 0)
goto err;
}
+ }
+
+ if(ctx->fmt == FmtTheora){
+ gr = 0;
+ }else{
+ gr = (ts * 48) / 1000000;
}
if(np > 0 && packet(out, ctx, ctx->discardpad ? 4 : 0, p, np, gr) != 0)
--- a/packet.h
+++ b/packet.h
@@ -1,7 +1,7 @@
typedef struct Packet Packet;
typedef struct Packetctx Packetctx;
-typedef int (*packet_f)(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts);
+typedef int (*packet_f)(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts, int key);
struct Packet {
uchar *data;
@@ -30,6 +30,8 @@
u32int trackuid;
u32int fmt;
+ int key;
+
struct {
int width;
int height;
@@ -40,10 +42,17 @@
int channels;
int bps;
}audio;
+
+ /* private stuff for packet_f functions */
uchar adts[7];
+ struct {
+ uchar *p;
+ int n;
+ }ps[16];
+ int nps;
};
-int aacpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts);
-int ivfpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts);
-int oggpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts);
-int srtpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts);
+int aacpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts, int key);
+int ivfpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts, int key);
+int oggpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts, int key);
+int srtpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts, int key);
--- a/srt.c
+++ b/srt.c
@@ -31,11 +31,12 @@
}
int
-srtpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts)
+srtpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts, int key)
{
int i, n;
uchar *s, *o;
+ USED(key);
for(i = 0; i < np; i++, p++){
for(s = o = p->data, n = 0; n < p->sz;){
if(*s == '\r'){
--
⑨