ref: a6d7e91e617d0dc39ab440a40e21e2986e099dbd
parent: 1774df63c4e8b3b3c063ec2acfda6cfc33382573
author: Sigrid Haflínudóttir <[email protected]>
date: Mon Sep 21 15:20:15 EDT 2020
extract SRT (subtitles)
--- a/common.h
+++ b/common.h
@@ -10,8 +10,9 @@
FmtVp08 = 0x76703038u,
FmtVp09 = 0x76703039u,
- /* a fake one, not supposed to show up in a mp4 */
+ /* fake ones, not supposed to show up in a mp4 */
FmtVorbis = 0x766f7262u,
+ FmtSrt = 0x00737274u, /* srt subtitles */
};
typedef struct Ebml Ebml;
@@ -29,6 +30,7 @@
uvlong duration;
uvlong seekpreroll;
vlong discardpad;
+ vlong blockdur;
struct {
char name[16];
vlong delay;
@@ -76,6 +78,9 @@
#pragma varargck type "T" u32int
int isotypefmt(Fmt *f);
+#pragma varargck type "P" uvlong
+int srttsfmt(Fmt *f);
+
int isorun(Biobuf *f);
int ebmlrun(Biobuf *f);
@@ -82,6 +87,7 @@
u32int crc32(u32int init, u8int *d, ulong len);
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 ebmlint(Biobuf *f, vlong *out, int isid);
vlong ebmlel(Biobuf *f, vlong sz, vlong *id, vlong *esz);
vlong ebmlrawint(Biobuf *f, vlong sz, vlong *dst);
--- a/ebml.c
+++ b/ebml.c
@@ -161,8 +161,7 @@
goto err;
e->fpacket = ivfpacket;
return 0;
- }
- if(e->tracktype == 2){
+ }else if(e->tracktype == 2){
if(strcmp(c, "vorbis") == 0){
e->fmt = FmtVorbis;
e->fpacket = oggpacket;
@@ -173,6 +172,12 @@
e->fpacket = oggpacket;
return 0;
}
+ }else if(e->tracktype == 17){
+ if(strcmp(e->codec.name, "S_TEXT/UTF8") == 0){
+ e->fmt = FmtSrt;
+ e->fpacket = srtpacket;
+ return 0;
+ }
}
err:
@@ -231,7 +236,7 @@
else if(e->tracktype == 2)
Bprint(o, "%s\t%d\t%d", codec(e->codec.name), e->audio.channels, (int)e->audio.samplerate);
else if(e->tracktype == 17)
- Bprint(o, ""); /* FIXME */
+ Bprint(o, "%s", e->codec.name); /* FIXME */
else
Bprint(o, "???");
Bprint(o, "\n");
@@ -258,6 +263,8 @@
e.tracknum = -1;
duration = 0;
for(isebml = 0; left != 0;){
+ if(id == 0x9b)
+ te.blockdur *= timestampscale;
if(endtracks > 0 && left < endtracks && trackdump == Nodump){
/* early exit */
left = 0;
@@ -455,8 +462,8 @@
ebmlgetnumber(0x73c5, e.trackuid)
else
ebmlgetnumber(0x75a2, te.discardpad)
- //else
- // ebmlgetnumber(0x9b, blockdur)
+ else
+ ebmlgetnumber(0x9b, te.blockdur)
}
if(Bseek(f, sz, 1) < 0)
--- a/main.c
+++ b/main.c
@@ -52,6 +52,7 @@
fmtinstall('H', encodefmt);
fmtinstall('T', isotypefmt);
+ fmtinstall('P', srttsfmt);
Binit(&out, 1, OWRITE);
Binit(&stderr, 2, OWRITE);
--- a/mkfile
+++ b/mkfile
@@ -12,6 +12,7 @@
ivf.$O\
main.$O\
ogg.$O\
+ srt.$O\
HFILES=\
common.h\
--- /dev/null
+++ b/srt.c
@@ -1,0 +1,55 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "common.h"
+
+enum {
+ Timedenum = 1000ULL,
+};
+
+int
+srttsfmt(Fmt *f)
+{
+ char *s, *e, tmp[64];
+ uvlong nsec, sec, msec;
+
+ s = tmp;
+ e = tmp + sizeof(tmp);
+ nsec = va_arg(f->args, uvlong);
+ sec = nsec / 1000000000ULL;
+ msec = nsec/1000000ULL - sec*1000ULL;
+ if(sec >= 3600){
+ s = seprint(s, e, "%02zd:", sec/3600);
+ sec %= 3600;
+ }
+ s = seprint(s, e, "%02zd:", sec/60);
+ sec %= 60;
+ seprint(s, e, "%02zd,%03zd", sec, msec);
+
+ return fmtstrcpy(f, tmp);
+}
+
+int
+srtpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts)
+{
+ int i, n;
+ uchar *s, *o;
+
+ for(i = 0; i < np; i++, p++){
+ for(s = o = p->data, n = 0; n < p->sz; n++){
+ if(*s == '\r'){
+ if(n+1 >= p->sz || s[1] != '\n')
+ *s = '\n';
+ else{
+ s++;
+ n++;
+ }
+ }
+ *o++ = *s++;
+ }
+ Bprint(out, "%zd\n%P --> %P\n", ++ctx->frid, ts, ts+ctx->blockdur);
+ Bprint(out, "%.*s\n\n", p->sz, (char*)p->data);
+ }
+
+ return 0;
+}