shithub: mcfs

Download patch

ref: a6d7e91e617d0dc39ab440a40e21e2986e099dbd
parent: 1774df63c4e8b3b3c063ec2acfda6cfc33382573
author: Sigrid Haflínudóttir <ftrvxmtrx@gmail.com>
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;
+}