Skip to content

Commit 32f73b4

Browse files
authored
cubicibo/MR/timegrid: Rewrite time handling to sample on frame grid
The time unit is now the frame count and FPS rather than the integer ms frame duration.
2 parents 3982081 + 8d1f7c0 commit 32f73b4

File tree

3 files changed

+89
-36
lines changed

3 files changed

+89
-36
lines changed

ass2bdnxml.c

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,13 @@
2323

2424
#include "common.h"
2525

26-
typedef struct frate_s {
27-
char *name;
28-
int rate;
29-
double frame_dur;
30-
} frate_t;
31-
3226
frate_t frates[] = {
33-
{"23.976", 24, 1000.0 / (24000.0 / 1001.0)},
34-
{"24", 24, 1000.0 / (24.0 / 1.0)},
35-
{"25", 25, 1000.0 / (25.0 / 1.0)},
36-
{"29.97", 30, 1000.0 / (30000.0 / 1001.0)},
37-
{"50", 50, 1000.0 / (50.0 / 1.0)},
38-
{"59.94", 60, 1000.0 / (60000.0 / 1001.0)},
27+
{"23.976",24, 1000.0 / (24000.0 / 1001.0), 24000, 1001},
28+
{"24", 24, 1000.0 / (24.0 / 1.0), 24, 1},
29+
{"25", 25, 1000.0 / (25.0 / 1.0), 25, 1},
30+
{"29.97", 30, 1000.0 / (30000.0 / 1001.0), 30000, 1001},
31+
{"50", 50, 1000.0 / (50.0 / 1.0), 50, 1},
32+
{"59.94", 60, 1000.0 / (60000.0 / 1001.0), 60000, 1001},
3933
{NULL, 0, 0}
4034
};
4135

@@ -88,6 +82,24 @@ void mktc(int tc, int fps, char *buf)
8882
}
8983
}
9084

85+
static void frame_to_tc(uint64_t frames, frate_t *fps, char *buf)
86+
{
87+
frames--;
88+
uint8_t frame = frames % fps->rate;
89+
uint64_t ts = frames/fps->rate;
90+
uint8_t sec = ts % 60;
91+
ts /= 60;
92+
uint8_t m = ts % 60;
93+
ts /= 60;
94+
if (ts > 99) {
95+
fprintf(stderr, "timestamp overflow (more than 99 hours).\n");
96+
exit(1);
97+
} else if (snprintf(buf, 12, "%02d:%02d:%02d:%02d", (uint8_t)ts, m, sec, frame) != 11) {
98+
fprintf(stderr, "Timecode lead to invalid format: %s\n", buf);
99+
exit(1);
100+
}
101+
}
102+
91103
void write_xml(eventlist_t *evlist, vfmt_t *vfmt, frate_t *frate,
92104
char *track_name, char *language, opts_t *args)
93105
{
@@ -103,9 +115,10 @@ void write_xml(eventlist_t *evlist, vfmt_t *vfmt, frate_t *frate,
103115
exit(1);
104116
}
105117

106-
mktc(evlist->events[0]->in / frate->frame_dur, frate->rate, buf_in);
107-
mktc(evlist->events[evlist->nmemb - 1]->out / frate->frame_dur,
108-
frate->rate, buf_out);
118+
//mktc(evlist->events[0]->in / frate->frame_dur, frate->rate, buf_in);
119+
//mktc(evlist->events[evlist->nmemb - 1]->out / frate->frame_dur, frate->rate, buf_out);
120+
frame_to_tc(evlist->events[0]->in, frate, buf_in);
121+
frame_to_tc(evlist->events[evlist->nmemb - 1]->out, frate, buf_out);
109122

110123
fprintf(of, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
111124
"<BDN Version=\"0.93\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"BD-03-006-0093b BDN File Format.xsd\">\n"
@@ -116,15 +129,19 @@ void write_xml(eventlist_t *evlist, vfmt_t *vfmt, frate_t *frate,
116129
" <Events LastEventOutTC=\"%s\" FirstEventInTC=\"%s\" ",
117130
track_name, language, vfmt->name, frate->name, buf_out, buf_in);
118131

119-
mktc(0, frate->rate, buf_in);
132+
//mktc(0, frate->rate, buf_in);
133+
frame_to_tc(1, frate, buf_in);
134+
120135
fprintf(of, "ContentInTC=\"%s\" ContentOutTC=\"%s\" NumberofEvents=\"%d\" Type=\"Graphic\"/>\n"
121136
" </Description>\n"
122137
" <Events>\n", buf_in, buf_out, evlist->nmemb);
123138

124139
for (i = 0; i < evlist->nmemb; i++) {
125140
image_t *img = evlist->events[i];
126-
mktc(img->in / frate->frame_dur, frate->rate, buf_in);
127-
mktc(img->out / frate->frame_dur, frate->rate, buf_out);
141+
frame_to_tc(img->in, frate, buf_in);
142+
frame_to_tc(img->out, frate, buf_out);
143+
//mktc(img->in / frate->frame_dur, frate->rate, buf_in);
144+
//mktc(img->out / frate->frame_dur, frate->rate, buf_out);
128145

129146
fprintf(of, " <Event Forced=\"False\" InTC=\"%s\" OutTC=\"%s\">\n",
130147
buf_in, buf_out);
@@ -313,9 +330,7 @@ int main(int argc, char *argv[])
313330
}
314331
}
315332

316-
args.fps = frate->rate;
317-
318-
evlist = render_subs(subfile, rint(frate->frame_dur), &args);
333+
evlist = render_subs(subfile, frate, &args);
319334

320335
write_xml(evlist, vfmt, frate, track_name, language, &args);
321336

common.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,24 @@
1+
#include <stdint.h>
2+
13
typedef struct BoundingBox_s {
24
int x1;
35
int x2;
46
int y1;
57
int y2;
68
} BoundingBox_t;
79

10+
typedef struct frate_s {
11+
char *name;
12+
int rate;
13+
double frame_dur;
14+
uint64_t num;
15+
uint64_t denom;
16+
} frate_t;
17+
818
typedef struct image_s {
919
int width, height, stride, dvd_mode;
1020
int subx1, suby1, subx2, suby2;
11-
long long in, out;
21+
uint64_t in, out;
1222
BoundingBox_t crops[2];
1323
uint8_t *buffer;
1424
} image_t;
@@ -20,7 +30,6 @@ typedef struct eventlist_s {
2030

2131
typedef struct opts_s {
2232
double par;
23-
int fps;
2433
int frame_w;
2534
int frame_h;
2635
int render_w;
@@ -33,4 +42,4 @@ typedef struct opts_s {
3342
const char *fontdir;
3443
} opts_t;
3544

36-
eventlist_t *render_subs(char *subfile, int frame_d, opts_t *args);
45+
eventlist_t *render_subs(char *subfile, frate_t *frate, opts_t *args);

render.c

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@
1010
#define MIN(a,b) ((a) > (b) ? (b) : (a))
1111
#define BOX_AREA(box) ((box.x2-box.x1)*(box.y2-box.y1))
1212

13+
typedef enum SamplingFlag_s {
14+
SAMPLE_TC_IN = 0,
15+
SAMPLE_TC_OUT,
16+
SAMPLE_TC_MID,
17+
INVALID_SAMPLING
18+
} SamplingFlag_t;
19+
1320
ASS_Library *ass_library;
1421
ASS_Renderer *ass_renderer;
1522

@@ -357,35 +364,52 @@ static int find_split(image_t *frame)
357364
return best_score < (uint32_t)(-1);
358365
}
359366

360-
static int get_frame(ASS_Renderer *renderer, ASS_Track *track, image_t *frame,
361-
long long time, int frame_d)
367+
static uint64_t frame_to_realtime_ms(uint64_t frame_cnt, frate_t *frate, SamplingFlag_t flag)
368+
{
369+
if (flag == SAMPLE_TC_OUT) {
370+
return (uint64_t)floor((1000 * frame_cnt * frate->denom)/(double)frate->num);
371+
} else if (flag == SAMPLE_TC_IN) {
372+
return (uint64_t)ceil((1000*(frame_cnt - 1) * frate->denom)/(double)frate->num);
373+
} else if (flag == SAMPLE_TC_MID) {
374+
return (uint64_t)round(((1000*frame_cnt * frate->denom)/frate->num) - (500*frate->denom)/frate->num);
375+
}
376+
fprintf(stderr, "Invalid sampling flag.\n");
377+
exit(1);
378+
}
379+
380+
static int get_frame(ASS_Renderer *renderer, ASS_Track *track,
381+
image_t *frame, uint64_t frame_cnt, frate_t *frate)
362382
{
363383
int changed;
364-
ASS_Image *img = ass_render_frame(renderer, track, time, &changed);
384+
385+
uint64_t ms = frame_to_realtime_ms(frame_cnt, frate, SAMPLE_TC_MID);
386+
ASS_Image *img = ass_render_frame(renderer, track, ms, &changed);
365387

366388
if (changed && img) {
367-
frame->out = time + frame_d;
389+
frame->out = frame_cnt + 1;
368390
blend(frame, img);
369-
frame->in = time;
391+
frame->in = frame_cnt;
370392

371393
if (frame->subx1 == -1 || frame->suby1 == -1)
372394
return 2;
373395

374396
return 3;
375397
} else if (!changed && img) {
376-
frame->out = time + frame_d;
398+
++frame->out;
377399
return 1;
378400
} else {
379401
return 0;
380402
}
381403
}
382404

383-
eventlist_t *render_subs(char *subfile, int frame_d, opts_t *args)
405+
eventlist_t *render_subs(char *subfile, frate_t *frate, opts_t *args)
384406
{
385407
long long tm = 0;
386408
int count = 0, fres = 0;
387409
int img_cnt;
388410

411+
uint64_t frame_cnt = 1;
412+
389413
eventlist_t *evlist = calloc(1, sizeof(eventlist_t));
390414

391415
init(args);
@@ -403,7 +427,7 @@ eventlist_t *render_subs(char *subfile, int frame_d, opts_t *args)
403427
eventlist_set(evlist, frame, count - 1);
404428
}
405429

406-
fres = get_frame(ass_renderer, track, frame, tm, frame_d);
430+
fres = get_frame(ass_renderer, track, frame, frame_cnt, frate);
407431

408432
switch (fres) {
409433
case 3:
@@ -429,16 +453,21 @@ eventlist_t *render_subs(char *subfile, int frame_d, opts_t *args)
429453
/* fall through */
430454
case 2:
431455
case 1:
432-
tm += frame_d;
456+
++frame_cnt;
433457
break;
434458
case 0:
435459
{
436-
long long offset = ass_step_sub(track, tm, 1);
460+
tm = (uint64_t)ass_step_sub(track, frame_to_realtime_ms(frame_cnt, frate, SAMPLE_TC_MID), 1);
461+
uint64_t offset = (tm*frate->rate)/1000;
437462

438-
if (tm && !offset)
463+
if (!tm && frame_cnt > 1)
439464
goto finish;
440465

441-
tm += offset;
466+
if (offset == 0) {
467+
offset = 1; //avoid deadlocks
468+
}
469+
470+
frame_cnt += offset;
442471
break;
443472
}
444473
}

0 commit comments

Comments
 (0)