~ft/treason

ref: c1156352ba4eceae2ec875fd06fc94c38c92271f treason/stream_sub.c -rw-r--r-- 1.9 KiB
c1156352 — Sigrid Solveig Haflínudóttir info: mixed up dispdelay and yuv→rgb, fix it 1 year, 1 month ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <ctype.h>
#include "misc.h"
#include "stream.h"

extern Streamops subops;

int
subopenfd(int fd, Stream *s, int *failed)
{
	if(fd < 0)
		return -1;

	s->type = Ssubtitles;
	s->timebase.denum = 1;
	s->timebase.num = 1;
	s->b = Bfdopen(fd, OREAD);
	memmove(&s->ops, &subops, sizeof(subops));
	*failed = 0;

	return 0;
}

Stream *
subopen(char *path, int *num, int *failed)
{
	Stream *s;

	if((s = calloc(1, sizeof(*s))) == nil){
		*failed = 1;
		return nil;
	}

	*num = 1;
	if(subopenfd(open(path, OREAD), s, failed) != 0){
		free(s);
		s = nil;
	}

	return s;
}

static int
subts2ns(char *s, char **e, uvlong *ns)
{
	if(strlen(s) < 9){
		werrstr("timestamp too short");
		goto err;
	}
	*ns = 0;
	s--;
	do{
		s++;
		*ns *= 60;
		*ns += strtod(s, &s)*1000000000.0;
		if(*s == ','){
			*ns += strtod(s+1, &s)*1000000.0;
			break;
		}
	}while(*s == ':');

	*e = s;

	return 0;
err:
	werrstr("subts2ns: %r");
	return -1;
}

static int
subread(Stream *s, Streamframe *f)
{
	uvlong end;
	char *x;
	int i, n;

	Brdline(s->b, '\n'); /* index */
	if((x = Brdline(s->b, '\n')) == nil){ /* timestamp */
		f->sz = 0;
		return 0;
	}
	if((n = Blinelen(s->b)) < 1){
		werrstr("unexpected empty line");
		goto err;
	}
	x[n-1] = 0;
	if(subts2ns(x, &x, &f->timestamp) != 0)
		goto err;
	while(isspace(*x))
		x++;
	if(strncmp(x, "-->", 3) != 0){
		werrstr("no timestamp delimeter: %s", x);
		goto err;
	}
	x += 3;
	if(subts2ns(x, &x, &end) != 0)
		goto err;
	f->dt = end - f->timestamp;

	for(i = 0; i < nelem(f->lines); i++){
		if((x = Brdstr(s->b, '\n', 1)) == nil || *x == 0){
			free(x);
			break;
		}
		f->lines[i] = x;
	}
	f->nlines = i;

	s->timestamp = f->timestamp;

	return 0;
err:
	werrstr("subread: %r");
	return -1;
}

static void
subclose(Stream *s)
{
	Bterm(s->b);
	free(s->buf);
}

Streamops subops = {
	.open = subopen,
	.read = subread,
	.close = subclose,
};