本帖最后由 shane007 于 2021-1-2 13:56 编辑
: n5 O: g# H- F% D A9 k
; W2 v$ M% b/ [ B4 R6 s) q最近找到了一些和幽魂系列Phantasmagoria 有关的资料,
2 {4 p% J/ n6 ]6 O也许将来可以用于汉化。
5 t! U/ ]6 G' D1 k& W
4 P7 [* N6 `8 b: ]+ W和日文版有关的信息/ G: {6 F4 d, q( k9 M' }
http://anthonylarme.tripod.com/phantas/phintgtp.html
S: j$ m2 k1 w; u0 F$ R. S' b% _( T2 _* ]; |
相关工具
! Y# N- Q' @% z# ]" Hhttp://anthonylarme.tripod.com/phantas/phcheats.html
& q' ^, B- R" G' x) b5 j) P9 x) I-----------------------------------------------------------------------/ B7 V5 x1 G" j5 l n! Y/ z
2012/1/2 更新
' V- g0 [1 g" t3 E8 B0 s4 s0 R关于幽魂游戏的字幕2 V& G3 L# ?: E! w4 ~
Phantasmagoria subtitles function discovered - ScummVM :: Forums: R8 F E) U" t" w
5 \; p7 y8 W2 S/ d5 b% E* [
VMD文件: [7 v u9 {& [1 {( b( Y" y
Subtitling Sierra VMD Files | Breaking Eggs And Making Omelettes (multimedia.cx)VMD - MultimediaWiki6 Z* C h1 \, k; p0 g! S7 e
/ d( o2 A4 p0 O* f$ L* }字幕
' A/ e+ k+ f5 CSubtitling Sierra RBT Files | Breaking Eggs And Making Omelettes (multimedia.cx)7 i6 G* B; ?/ }( k3 {
/ T2 T- j, n& W- B+ T; h: {& e4 TFFmpeg/subtitle-rbt.c at feature/VMD_encoder · multimediamike/FFmpeg · GitHub) r. ^0 Z. O' A* I
- /*' u+ z4 P: f; a' k# |3 g( Y! c
- * subtitle-rbt.c$ l$ v) B! l: W* X- K- H+ U
- * by Mike Melanson (mike -at- multimedia.cx)' k+ q* x0 T: w+ @
- *
' C: S$ Q+ c: V - * build with this command:
9 i5 w/ a, I' _' O1 H7 Y( Q( a - * gcc -g -Wall subtitle-rbt.c -o subtitle-rbt -lm -lass% D* k" [$ ~# s
- */; a( b: H' H F- J8 q8 |% y7 `' k4 j- a
- ' _, ~ @5 D/ `0 |
- #include <inttypes.h>; D# d* |7 v1 [# M
- #include <math.h>
* x& K7 b, n5 l. \ - #include <stdio.h>
4 m; b8 `3 m5 | - #include <stdlib.h>1 Q" Z& C$ B; \- k% Q/ X
- #include <string.h>; |" {4 F: T" W
6 `/ M9 T9 D$ C9 s3 J8 y- #include <ass/ass.h>
& _- t6 E2 y( _% O - % R6 C4 |& n" K; u# Q% [
- #define LE_16(x) ((((uint8_t*)(x))[1] << 8) | ((uint8_t*)(x))[0])+ x. Z; a1 H6 W o I, p
m& k' d" ~- S( @# G5 n# v( ~. N6 ?- #define LE_32(x) (((uint32_t)(((uint8_t*)(x))[3]) << 24) | \
; Y* h j" q( v! R - (((uint8_t*)(x))[2] << 16) | \/ V& X3 z7 N) w/ z0 R5 n$ M
- (((uint8_t*)(x))[1] << 8) | \
1 M, z, k; v! S# N. _ - ((uint8_t*)(x))[0])- n7 {9 B; ^" G( _% T) F4 v' \/ t2 U9 R
- : K- ?" |3 W' t* ?
- /*********************************************************************/$ _# Y7 H# f+ [; n; R8 v
( o" ]) j: e# ^3 J$ z1 E% _- /* Bit reader stuff */3 i+ j7 s5 x4 x2 i; Q1 H3 e
- z$ D! ]3 E$ w1 R- b
- typedef struct
) m# l* G- s C& D5 r( N - { X3 \ m2 x5 i% l9 E5 |) p0 b
- uint8_t *bytestream;
\# E0 p* T6 L; H* |9 J2 b - int bytestream_size;
4 o) F7 T+ b( b0 v8 k+ l- s2 X - int index;2 ?# H& Z" W- H6 O0 j
- uint32_t bits;$ R5 X2 W( d* }2 p$ t6 w
- int bits_in_buffer;
% P( G9 \, |/ f - } get_bits_context;
2 K' n" d+ `9 l3 S$ n - 5 k6 W0 D* g* T/ D8 z. A+ [
- static inline void reload_bits(get_bits_context *gb)5 Y% ?7 ]! r$ B
- {
1 I# F: T' A, _# T: O$ \ - while (gb->bits_in_buffer <= 24); w6 `" d2 B. V
- {% _$ {( z* J1 }/ I1 F1 Z, h
- if (gb->index < gb->bytestream_size)
5 m0 K$ Z; Q- ?" G" @) `& x - gb->bits |= (gb->bytestream[gb->index++] << (24 - gb->bits_in_buffer));
! Q- ?$ }1 z9 t" N& f" X* ~ - gb->bits_in_buffer += 8;
9 F6 u! X" F" \ - }
9 g3 Z s4 p8 {2 C0 m2 y0 E - }
, L" C9 d% A. k. l6 f* A; n
4 o5 ` m. X9 u& {9 n7 `- static void init_get_bits(get_bits_context *gb, uint8_t *bytestream, int size)
% S% n8 l. M9 D/ a# i4 j - {
4 [- e% h* P+ r! D0 D - gb->bytestream = malloc(size);" y+ j# A5 R5 {' h( K- {
- memcpy(gb->bytestream, bytestream, size);
4 m, l# a9 |- P4 R8 L- e& ` - gb->bytestream_size = size;' X6 t2 q" U2 b/ ?* I. \9 u+ @/ o5 Y
- gb->index = 0;
9 z' Q M& p8 O# O: s - gb->bits = 0;+ o7 b- ]7 S0 W% I& [$ O+ O
- gb->bits_in_buffer = 0;
- F9 R9 q2 V( b" G& _5 @. Z
+ l2 M: Q, }- c" n/ Z# N- x* b- reload_bits(gb);
+ W3 N" d4 Y( q- I7 G* @ - }
. x; D8 ^* Z6 Q, a) H - - Q2 Q! c) E/ W% n
- /* read bits without consuming them from the stream */
! |& S: p9 Z# ?6 x0 R - static int view_bits(get_bits_context *gb, int count), a* t. C) ?2 X: m
- {
; n8 e6 z% ?) d8 }6 T - if (count >= 24)( O' {0 ~- z+ k
- return -1;
! m0 y" D- ]4 }2 h7 x; [- i - if (gb->bits_in_buffer < count) M: V7 n) y4 V( ~1 k
- reload_bits(gb);3 @: b% I0 h- f# V, z, [5 d! O( F
- return (gb->bits >> (32 - count));
7 W! A5 _0 H7 r; y5 J k - }0 _7 h& B- h V) Z& w5 D
- 8 v& N& C4 ?- f& P6 A8 y& i: Z
- /* read and consume bits from the stream */+ {1 _ Q! ]! e
- static int read_bits(get_bits_context *gb, int count)' K) i; w# M T2 k. p" N Q
- {- B8 f3 I+ \1 L2 {% K# w. F& z, Y: I
- int value;3 d! x) E& s `0 `, w, p d/ O c1 ~
- : L. s$ |! ^, z/ h! E: F- Z
- if (count >= 24)- G5 A5 ~& e; V6 O. y" v9 H
- return -1;
# V6 x& _7 J& K4 |+ P! \ - * W& u B) u: o* E% |2 _; X
- value = view_bits(gb, count);
: q+ S1 [! z/ O - gb->bits <<= count;
2 K) L" q" R$ ~/ E - gb->bits_in_buffer -= count;
/ T' Q5 _3 u9 n" w+ f# l1 k
# x, X: [( S6 D5 C; R0 \+ S3 R- return value;% I& _ b( ]! ?, e8 F
- }
% H: ~- I3 n G; j9 W - 8 ~( d* J+ P: ]; }/ L
- static void delete_get_bits(get_bits_context *gb)
: T9 X2 ]* e- k, r& \ - {1 x, ?. R/ v- i. x2 P+ R" G! `& I
- free(gb->bytestream);
3 L- ~) Y3 v8 ~3 z - }
3 T, l6 A$ R$ h% B# u" b - 8 W0 c6 {7 g/ R! u/ H
- /*********************************************************************/
% C- Y( g2 J* T
. t! S V7 {4 X J6 X- /* Bit writer stuff */
- }, U5 Z8 Z5 C* }) [/ V! R
8 m5 H+ C0 ?1 s! l& }- #define MAX_PUT_BITS_BYTES 63000
% f0 g) T1 b) `" h; I# Y - typedef struct
! @/ h3 ]- L1 r2 D - {' Q8 I+ h* j. ~- x6 Q
- uint8_t bytes[MAX_PUT_BITS_BYTES];. a2 `: w" z2 M ?3 [, n
- int byte_index;
3 a# J! a/ u8 `/ n2 Q" x: | - uint32_t bit_buffer;
# g+ ]) p. r4 B% u: @' t, ^# Y3 g - int bits_buffered;" p% o g1 v, H' \* e
- } put_bits_context;* r6 r, a8 c0 s# J1 W. _& ^
- $ w2 |( O: N) F8 P+ L' P9 X
- static void reset_put_bits(put_bits_context *pb). b$ `6 S4 D4 j
- {/ r8 G- c8 n* P# S7 [6 B
- memset(pb->bytes, 0, MAX_PUT_BITS_BYTES);
( k) s, G+ @+ E7 F6 J- n - pb->byte_index = 0;
& N5 K0 J% s: V3 Z, a4 J2 p" v- }! C - pb->bit_buffer = 0;
0 G$ w: E; ^6 x/ I+ Z' U& b - pb->bits_buffered = 0;
/ D' b1 g- T. x/ Y t2 M. _* j - }
# j- j3 R* A$ B7 c. [1 y7 F6 g
0 ^8 T8 |, s& c9 O0 Q; u0 l" {7 F- static put_bits_context *init_put_bits()
! Q# [: S+ _# D - {6 j/ \/ L5 o" C8 f
- put_bits_context *pb;
p3 s( t2 C# A9 ]6 F1 v - 4 M& O" `+ f: \
- pb = malloc(sizeof(put_bits_context));
$ {2 J& s. Y" B- s2 | - reset_put_bits(pb);
3 `$ O; }, }) f7 F8 ]
7 }$ D9 S6 z( J' s- return pb;) ]+ y; a1 I' I9 |9 Y3 }, o
- }+ s! E% W- [7 z. Z- P4 ?7 X* L0 }
- # x! z" z! N% y! Z- v3 M
- static void put_bits(put_bits_context *pb, int bits, int count)( y! V, u; U8 n, c2 w
- {
/ z& G% k/ g+ {* X. d! ~9 i. J - pb->bit_buffer <<= count;
- ]6 ^6 C0 Q. H$ n4 @* X - pb->bit_buffer |= (bits & (~(0xFFFFFFFF << count)));+ Z. o" s; l. t% r
- pb->bits_buffered += count;0 \# g- d8 P2 v
! j: X: o+ q. o! V; }" l, H- while (pb->bits_buffered >= 8)- l. |( @. \ O) t
- {% _& D7 U( w" E
- pb->bytes[pb->byte_index++] = pb->bit_buffer >> (pb->bits_buffered - 8);$ P8 b' I+ d. g# g0 W5 a
- pb->bit_buffer &= (~(0xFFFFFFFF << (pb->bits_buffered - 8)));8 Z$ o; i3 H" J* {* o0 t' T; O
- pb->bits_buffered -= 8;7 i/ F3 ^! s& s. t/ T
- }+ Y( @) P' J/ S+ w0 h% U
' X) g1 u* v" \& ~9 f% \- if (pb->byte_index >= MAX_PUT_BITS_BYTES)
3 y; s8 y8 R! R _3 T - {
0 Z, A3 [% I; ]7 N, ? - printf("HELP! Bit overflow\n");' } s* H X7 Z6 {8 q; a
- exit(1);
5 Y. }# C, n y% ^ - }
- p6 s) X" f! D* S3 d - }& q& [6 r! q5 J$ V) ?$ U u. C( [
- , f' j+ p7 k5 b7 R
- static void put_bits_flush(put_bits_context *pb)
' Q! D$ L, _( ?1 r) d0 M - {: M: }6 z% F1 \' U
- if (pb->bits_buffered > 0)1 x- ?; b. y/ Y5 s! u( u& v
- pb->bytes[pb->byte_index++] = pb->bit_buffer << (8 - pb->bits_buffered);
) H& h. ~! D9 p: { - }
( z" [, G$ Y3 | - 4 O1 B0 d& q7 q
- static void delete_put_bits(put_bits_context *pb)
$ k+ j/ n% A! V ?' v - {
+ {% X5 @+ k4 R7 ]3 V4 r8 g - free(pb->bytes);6 _8 f# L% ]7 m7 E+ D n; w
- }5 x; }' m+ M- E# @- U8 z
; E7 \+ W! E0 }- /*********************************************************************/
- _( X% ?, X, B - * O% _ B3 z6 E) N. h
- /* RBT functions */+ [! x* \! d6 s" }3 Y6 h
- ' _/ j# f+ H/ u. T
- #define PALETTE_COUNT 2564 g/ @; o( m; i* `
- #define RBT_HEADER_SIZE 60
' C Y8 @3 F+ G5 |( k - #define UNKNOWN_TABLE_SIZE (1024+512)
# E+ Q! g" k/ P r" v( S - #define SUBTITLE_THRESHOLD 0x70; e4 k1 o3 Z4 b7 C4 P
- #define MILLISECONDS_PER_FRAME 100* M0 s1 \3 H/ r# U4 s( `, E/ ]
- \3 N+ d/ m& H& E0 n, Q- {- /* VLC table */6 j( E! N/ s, W3 W: _! _0 r) ]: O" ~, `
- #define VLC_SIZE 49 N( z% Z$ {1 P5 ^ n1 X. u. O
- static struct
) ]# n& Y8 W* h. E) H - {
0 U, |. ^/ D- G6 I - int count;2 y' V2 s, S% F8 r3 R* E, j
- int value;
# E8 G8 y. P$ T- v" Y8 ~6 U - } lzs_vlc_table[] =: r: h. F3 f5 |& F( H: Q
- {* c9 T% k, l0 T4 `, G
- /* code length = 2 bits; value = 2 */
- \- s% T0 Z+ }0 R+ t6 N - /* 0000 */ { 2, 2 },
8 k% W+ R8 y4 d& [6 }* A& m9 L - /* 0001 */ { 2, 2 },1 r/ `% C! Y' `; t9 A4 L$ {
- /* 0010 */ { 2, 2 },
5 O* R7 g! S; h - /* 0011 */ { 2, 2 },
0 J1 }) L( x$ B3 |7 Z - " A C: g* A2 e* `; v! o4 B
- /* code length = 2 bits; value = 3 */
( i. e1 N5 z. w; p0 o2 ?; g5 ]# W- B - /* 0100 */ { 2, 3 },; K; t6 O+ I* r6 z7 r8 V5 `# c
- /* 0101 */ { 2, 3 },
2 f% y: g$ u) P1 S1 \/ j O - /* 0110 */ { 2, 3 },3 T! Z/ \& p; }8 {" N+ _) h! U2 F
- /* 0111 */ { 2, 3 },9 q5 I6 E+ {; L1 f9 o
- . ]" X! x+ I( A, L! _5 u
- /* code length = 2 bits; value = 4 */
! S( j* \! \0 ?, z2 Q6 l) r& f - /* 1000 */ { 2, 4 },% y" q5 g, s4 a1 X8 q9 }) y
- /* 1001 */ { 2, 4 },. L c; K5 b( O: S) i) @- ~; N" P
- /* 1010 */ { 2, 4 }," R+ B4 q2 c3 E$ U/ f' S
- /* 1011 */ { 2, 4 },
0 B3 s% i! d. n3 G. Q
1 R6 H: ^* I! O9 I: R- /* code length = 4 bits; value = 5 */0 D- w3 A; V) u
- /* 1100 */ { 4, 5 },
/ t) p) h) c4 W/ s( k$ R* P4 \$ s, h
* \ Z* t, k5 T. n6 P& H# \- /* code length = 4 bits; value = 6 */
5 F/ U% e* B1 A: q% A0 O - /* 1101 */ { 4, 6 },
1 x" T# O+ a, B0 S2 h- [. `* q3 |
5 H' Y! m1 E$ ~& w( m+ ^- /* code length = 4 bits; value = 7 */* |$ c/ O0 i9 H# z. m
- /* 1110 */ { 4, 7 },; w7 a0 d8 i/ Q/ @0 k
; `% b- z2 y- |- /* special case */
7 \4 L6 W2 X: O1 w6 \" M5 J/ E - /* 1111 */ { 4, 8 }+ |( J( }3 D: Q! G
- };" e3 t1 N& P4 j9 M) `' A7 t) x
- 6 w* D7 n- a9 A
- typedef struct& g- T! C% Z' e7 e
- {
3 l7 u7 Z4 q( H6 C) h% D - int version;
5 X2 Z! _" d& }; n1 {3 W - int width;
, b$ H2 ]( S; w! @0 D8 R- u - int height;1 m! a* ?/ o8 D5 V' Z
- int frame_count;
8 y9 z: J. m% O) e - int audio_chunk_size;
1 w- `9 l' B- `" [ - uint8_t palette[PALETTE_COUNT * 3];
- C$ j/ X% C9 Z: I" {% d+ O - off_t video_frame_size_table_offset;5 P; F8 `: G. I b7 I
- uint8_t *video_frame_size_table;
$ m1 O6 j+ ]. D1 a w. C* d - off_t frame_size_table_offset;2 e1 R6 F: G" w! L; J
- uint8_t *frame_size_table;
( q$ Q) @' U5 j0 f& B - uint8_t *frame_load_buffer;
4 n3 v) ?: j W, r9 s - int dump_frames;
# M! g1 H% I s( L$ @
c( E+ J3 r) q" g1 K0 B: k9 `" i- /* subtitle library */) F5 E! T2 K- ]/ m
- ASS_Library *ass_lib;9 B) i! C: o. Q! c2 U( S
- ASS_Renderer *ass_renderer;" d+ v8 n& q# g8 l, a" H
- ASS_Track *ass_track;
! E3 j% O0 U) @" O7 o' Q - } rbt_dec_context;
8 W1 n/ u6 l. S7 P- V4 u5 [ - 3 ^; t0 n% [( x2 [! B1 \
- static void dump_pnm_file(char *filename, rbt_dec_context *rbt,+ D S' U9 @: U+ h- S% G
- uint8_t *image, int width, int height)
3 @) [9 S# G0 m7 Q' ?4 w9 M - {
" J3 w5 u9 \- B% J# Z - FILE *outfile;4 f8 ~( `/ [9 o( _. S/ O
- uint8_t bytes[3];
7 M- O$ ~* A3 } - int p; x8 ?; [& ]" V5 ~
- uint8_t pixel;! h9 v) z& s% j0 Q8 I1 p; A1 P
- 4 N" ]+ a+ l* h% R* o' p" i8 ^. Z6 ~
- outfile = fopen(filename, "wb");
% R5 |3 f0 w0 _' m - fprintf(outfile, "P6\n%d %d\n255\n", width, height);# c' s8 } p0 O# r O/ e' M8 Y, Z3 p2 C+ |5 T
- for (p = 0; p < width * height; p++)5 Z, P- w+ o* Q1 s' b- N W
- {
" @- t8 s* }' S% U2 ` - pixel = image[p];- S4 R: y, t; k; O! E
- bytes[0] = rbt->palette[pixel*3+0];
' r- e+ O+ Q: }7 D4 t! v, _" l - bytes[1] = rbt->palette[pixel*3+1];
- j: T% D0 o6 K9 Y) u( i - bytes[2] = rbt->palette[pixel*3+2];
/ t& @" \/ |7 u9 p - fwrite(bytes, 3, 1, outfile);+ U) B7 G- d# K8 O: Q
- }. U$ G, l( P; D& M3 ]. C; d
- fclose(outfile);8 z( O6 @: {. n4 N3 ~% s0 U# J- A3 \
- }
5 [4 x2 o2 E/ O; b+ h: G8 F0 I- U - + L3 U, b. c& H% l1 O1 {3 D4 a1 I
- static int load_and_copy_rbt_header(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file)
- I( v6 Z9 y7 q" o; J - {
, l6 H/ l- h; j" D9 q9 S - uint8_t header[RBT_HEADER_SIZE];
) x- |3 G: D7 @& Z" C - int palette_data_size;
7 O. s2 l% I, x4 V+ T/ c5 F8 _( n8 F - uint8_t *palette_chunk;
" ~2 f4 M, S+ i6 A9 ?; `% z2 [ - int unknown_chunk_size;
! u0 n& n. a9 E( C - uint8_t *unknown_chunk;+ ~/ S; v" r9 X5 w0 w$ p8 S7 w a4 ^
- uint8_t unknown_table[UNKNOWN_TABLE_SIZE];
, _. W* k4 {/ R [3 o - off_t padding_size;
4 `, w" M1 n% d# n* D/ L - uint8_t *padding;2 d# j7 j7 i4 m( `5 B
- int i;7 `; y* {& X4 o' P
- int frame_size;
h& ^* B, M0 j( k& q/ R - int max_frame_size;
/ W7 d2 x& n- s. r+ o1 w" i6 _: a - int first_palette_index;
- m- r7 Y: `$ N8 U/ S1 _ - int palette_count;: \/ I5 M o5 Y$ G% ]# V* W
- int palette_type;: W0 F" b/ l# M) b* W; f
- int palette_index;
! k& O! u2 X5 a5 V
7 `7 D3 u! \2 Z) @( T6 l- fseek(inrbt_file, 0, SEEK_SET);
) C! |4 L+ W* T1 @) T - fseek(outrbt_file, 0, SEEK_SET);
+ r9 q: G6 s4 T8 k+ _2 K - 1 U( y% N" I; j# H4 K7 |
- /* load the header */
, ?' _! m, C+ y: n - if (fread(header, RBT_HEADER_SIZE, 1, inrbt_file) != 1)
4 A: i4 }4 K1 ]& P9 `2 t - {' P7 x7 K ^# {: T @- d
- printf("problem reading initial RBT header\n");
9 x0 d* a0 Z4 t0 w/ x - return 0;
& m$ A' e ^. _4 k+ v3 o% I - }
h7 Z7 R [3 j1 D/ D2 \ - ( {. {# v* B, O2 {$ V: q
- /* copy header to the output */1 U) v' ?4 v4 v# C1 J8 u; a
- if (fwrite(header, RBT_HEADER_SIZE, 1, outrbt_file) != 1)1 }: B2 y7 u! |5 `% j# N
- {
. q! Q! A: C. n( U, J9 x6 D - printf("problem writing initial RBT header\n");8 H2 L: y6 a+ e0 M4 x" W
- return 0;/ O" F. Q2 S1 H
- }
# m" |, {7 R8 D6 L5 R8 A - [- H& G" E6 p: K4 O0 E
- rbt->version = LE_16(&header[6]);
9 \' ^* a A- _% F- } - rbt->audio_chunk_size = LE_16(&header[8]);+ U! ~9 j2 D3 u. y. k/ a
- rbt->frame_count = LE_16(&header[14]);
& H0 j/ _9 j ^4 s - 6 {% x/ k$ r- A& U% e
- /* transfer the unknown data, if it's there */1 f+ \# p" q3 g9 K
- unknown_chunk_size = LE_16(&header[18]);
' E8 d+ x: \. Q, L0 M - if (unknown_chunk_size > 0)
4 P S% ^- z% K+ i/ E! j$ R( r - {
# z: K- W4 m( x2 m - unknown_chunk = malloc(unknown_chunk_size);
2 j' [# U, I# X - if (fread(unknown_chunk, unknown_chunk_size, 1, inrbt_file) != 1)
& V# [& d9 y) O e7 s - {3 Y$ U* m0 [3 P0 D5 `; Z
- printf("problem reading unknown data\n");+ L* Z. X f2 c$ s8 C. u
- return 0;1 C$ U( T0 H9 y B- @
- }
& m8 ? k9 }. e% ^* w - if (fwrite(unknown_chunk, unknown_chunk_size, 1, outrbt_file) != 1)" z9 p) h* W3 W: A% N
- {$ I- L( ? n) ?6 J/ U4 j& A* G& N' r% ]
- printf("problem writing unknown data\n");; c9 t6 R. g9 i! U4 |7 z0 Z
- return 0;
! I" E( u& [2 c3 t" _ - }
" ?, [4 D% t$ W' I/ ? - free(unknown_chunk);4 r: p0 b% N3 l% C; ]
- }) C. K& E; E* a- V
- 6 Z+ X6 _1 ^, o( o
- /* transfer the palette chunk */3 h+ h( T/ k3 X) ]
- palette_data_size = LE_16(&header[16]);7 j5 X, Q' [5 |! b6 A( c
- palette_chunk = malloc(palette_data_size);
$ l4 Z: o! Z* D( Y! E9 ? - if (fread(palette_chunk, palette_data_size, 1, inrbt_file) != 1)
3 y; t( S7 J$ n4 `1 m: l+ f - {
' |- \7 U4 S9 w. r1 q& n5 A - printf("problem reading palette\n");7 T8 }% L Z* ^$ @
- return 0;( X/ t! O" J! O4 i7 c% L: \$ F
- }
6 w% r8 Q' e9 B1 K* ~' j - if (fwrite(palette_chunk, palette_data_size, 1, outrbt_file) != 1)
% Z5 P! T! T! X4 B% o4 f0 e& X - {( x# K9 i, {* r, H
- printf("problem writing palette\n");
6 b6 [( z# [( p0 w% ^8 _. j - return 0;* r* ^ H7 P3 }' I# @; ~
- }& P. z& E7 T/ e- z0 V
- /* load the palette into the internal context */; G N8 _5 E4 D ]5 i& ?
- memset(rbt->palette, 0, PALETTE_COUNT * 3);
' t+ U/ T5 ]: u - first_palette_index = palette_chunk[25];
" c W6 W5 ]3 P- L, n - palette_count = LE_16(&palette_chunk[29]);" L' p9 o/ ?0 X
- palette_type = palette_chunk[32];
. }/ P! | w# V4 v. _- A - palette_index = (palette_type == 0) ? 38 : 37;
, h& P3 R/ I: d* H! B; _8 U - for (i = first_palette_index; i < first_palette_index + palette_count; i++)
( }( S& U( d$ Z - {$ r9 p7 @- S2 W6 b$ T1 y3 K
- rbt->palette[i*3+0] = palette_chunk[palette_index++];6 l# J( \* n! H/ B6 w5 a
- rbt->palette[i*3+1] = palette_chunk[palette_index++];4 p, K, c) z h% g4 A' p
- rbt->palette[i*3+2] = palette_chunk[palette_index++];
8 e" j1 k: B! C1 S9 W3 Q5 r0 `" i* I+ z - }
- Y( t# h9 M* M, Y5 X - free(palette_chunk);
3 f7 n1 u- a3 o" E5 Y
h2 m! l0 R6 x$ v- /* copy the video frame size table (2 bytes per frame), as a placeholder */
; d/ d1 p7 w+ K3 k3 V, H" @4 I- Y - rbt->video_frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));' |( z. g Z& @. q/ v# e
- if (fread(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)
3 @0 q5 G% {: d" C/ a" @; K$ H5 l - {/ @7 i4 j2 \* P+ x) A
- printf("problem reading frame table\n");
) P# ^+ q$ x$ f: E2 F - return 0;# p0 t5 D: }. }; @, M1 ?7 |
- } c' l/ Z6 \2 O: R$ m, \
- rbt->video_frame_size_table_offset = ftell(outrbt_file);
- e' G& B$ C3 }9 w. n' _5 q( l - if (fwrite(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)3 P: ]; R# q, B/ T4 w- k( N# a
- {
) q+ ?8 d6 t+ T; b' P4 Q1 Z0 w - printf("problem writing frame table\n");4 d' V( O/ S2 W! d
- return 0;6 r3 n# I5 y5 T7 y% R! F+ x7 k
- }
" S4 H, h3 e7 U/ x
6 M0 `* Q5 k Q z* N- /* copy the frame size table (2 bytes per frame), as a placeholder */
! S+ G+ O9 ~5 x7 _2 y - rbt->frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));* g& k8 s4 H0 j
- if (fread(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)# u5 q- g: i2 D$ q
- {9 L% a1 S s3 ]$ Y0 n
- printf("problem reading frame table\n");
/ e0 S# T" Y+ r# F, U/ o6 g1 K" L6 I - return 0;& I) z; z$ x1 l! w
- }) F( h" u& ^0 p* ?/ K
- rbt->frame_size_table_offset = ftell(outrbt_file);; ?6 b3 } n' q X
- if (fwrite(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)
. T- P+ ]+ ~; T' F+ E" N - {
' u2 ?9 n0 B& o2 ` - printf("problem writing frame table\n");) P, L; e e$ V. ~& Z
- return 0;: D N+ a/ i! R+ J0 N
- }. _) z0 o& v: u, r; n( j
0 y8 Q' x; [8 f- /* find the max frame size */' A- J$ } T6 X" I0 F% N; B o7 w
- max_frame_size = 0;
% N- J' E" U V" U5 m6 Z3 _: b - for (i = 0; i < rbt->frame_count; i++). V2 n8 I% x9 ]2 g, k" T( }
- {
( ~# _* |6 M% P - frame_size = LE_16(&rbt->frame_size_table[i*2]);
1 H$ ~+ ^% x; y8 D7 U4 |( X - if (frame_size > max_frame_size)# [, D1 x7 r# e8 K/ i9 r+ ]
- max_frame_size = frame_size;; _- W: j+ b# e& g2 G, w' \
- }6 X# W8 X6 g+ w6 P& ^/ n
- rbt->frame_load_buffer = malloc(max_frame_size);
; O+ ?" b6 t: N5 R7 k f7 \
) W9 _- O. l6 _1 @- I& ]; M; u4 @# d' E- /* transfer the unknown table(s) */
) s5 @# x* t4 Z, D" D - if (fread(unknown_table, UNKNOWN_TABLE_SIZE, 1, inrbt_file) != 1)9 r+ \) V0 @6 t6 L" }5 [
- {) B& Z4 j# U: ^9 `3 E/ Z
- printf("problem reading unknown table\n");; Z9 a9 M2 J+ {6 x4 F
- return 0;
/ K# j6 A9 J/ X; R z# p9 @ - }
" }& `: [4 b, q' p9 N2 ?; T3 a, ^7 I( Q - if (fwrite(unknown_table, UNKNOWN_TABLE_SIZE, 1, outrbt_file) != 1)
6 _4 D, z! X% a. R* I/ a) n% c - {. E, }( V: L" }* e7 f3 e
- printf("problem writing unknown table\n");
- k8 P5 q# e' r, V G7 l0 h/ o - return 0;
# k7 r1 X- h0 u2 ?7 R/ L$ { - }7 q& D: Q) A U) C* X' v+ K
- Q& ]% P4 s8 i6 i- /* copy over padding */
6 i1 k( |2 @8 Z - padding_size = 0x800 - (ftell(inrbt_file) & 0x7FF);
& y2 f* L; J( e) M q - if (padding_size)# O' ?$ B4 x: r: `
- {; k4 z% G3 m: y. V d
- padding = malloc(padding_size);* Z# {( q, C2 S' ]5 E8 m' w
- if (fread(padding, padding_size, 1, inrbt_file) != 1)3 d1 B+ e, H' J
- {
# S# o/ \' l$ N- F* Z" U - printf("problem reading padding\n");
8 s! U! G: n, F( E$ ^ - return 0;5 g$ G2 Z7 j4 j# ]! U
- }4 P' E8 l$ N( b3 U! }
- if (fwrite(padding, padding_size, 1, outrbt_file) != 1)
2 x& A# v" G; @# ]& ~ - {
( X1 T, @2 U% }( u6 V - printf("problem writing padding\n");
; k0 |8 k; z! S, B - return 0;
1 C5 t) w" O0 D" r - }
# o! U% [- i" ?& q( B - free(padding);1 u- h* v; T' }
- }1 g; Y& p- E9 w$ m8 G' F) v' n. q' `
& o% z( n) a" \# C- return 1;! [7 Z1 ^2 ?0 Z5 m( j( Q
- }
5 Q$ @+ |7 z; F( j' D8 G. m
+ J ^$ y% f1 }8 R# O- static int get_lzs_back_ref_length(get_bits_context *gb)& y/ S7 v& G# I& R
- {: v l; K9 e' V8 w4 P- V6 d# B- [
- int vlc;$ U; X8 o5 \; q% b: b* U7 a K& U+ u0 ~
- int count;
7 ^; W7 j9 J/ V+ a - int value;
5 k! I& T: u( [) y) a7 q
; ?4 d! Y- N7 s. x- vlc = view_bits(gb, VLC_SIZE);
- }$ {6 R0 M9 R5 K - count = lzs_vlc_table[vlc].count;
5 k5 Z1 ^2 p) p- B l7 i2 I2 z3 } - value = lzs_vlc_table[vlc].value;
2 f1 P0 Z* H" Z4 Y: q0 F
, R3 Z% n D4 I+ z) M- read_bits(gb, count);
& H8 b# b/ O/ [! |' V- M# a8 C6 Q - if (value == 8)( f' o8 n9 s/ o
- {/ ~; z( e( A" ~7 M: v
- do% l5 \+ I3 [/ }% h1 u
- {2 }; a' g7 H4 l& X
- vlc = read_bits(gb, VLC_SIZE);# j! I% Z' m3 b4 A! x% e0 t
- value += vlc;
6 O# t ^' F$ C% Z6 a* u# b: z1 j - }( g3 d' T3 v) L# Q7 A
- while (vlc == 0xF);
4 \- i4 a- {( G; f l - }
5 b% C" V M6 ?$ l% j
/ t; m! S$ C2 K5 l0 }, D1 b' O- return value;0 s! t( X& I8 M- U: ?
- }1 x4 ^1 b; [9 r
, j8 j1 @1 W! @: h- static void compress_window(put_bits_context *pb, uint8_t *full_window,* t5 f E( b8 v6 @
- int full_window_stride,0 o5 W6 O% I. H$ e& ^: U5 u
- int window_top, int window_bottom, int window_left, int window_right)6 G5 `8 `! l% N3 }
- {7 D3 d, R) m. _4 q
- int last_pixel;
: q" @. p% ~' x( A5 K( Q# j - int run_size; u/ H* U" ^+ _0 v/ q7 @# t
- int x;; Q' e3 P$ C! d9 v, u
- int y;
) u6 ]/ U2 @/ g; u- Q0 O1 W% o - int start_index;/ D6 }# P' z) u; L r* }
- int end_index;$ p4 M4 {2 k+ {2 U# F
- int encode_last_run;
7 f( c2 B1 M4 C! a2 N - 0 g& M, y/ k2 p+ {8 X: C T9 p
- last_pixel = full_window[0];; g6 {, \: W7 j1 \. I3 K( |
- run_size = 1;! O {6 H( a& d. R/ p5 v
- for (y = window_top; y <= window_bottom; y++)
# }# d5 v0 _$ [. y- b6 S1 t2 m - {
5 b8 \7 W% q! V. C) L - start_index = y * full_window_stride + window_left;' r9 n/ H8 z2 \! p5 T
- if (y == window_top)+ W0 J& L- v) X5 N, \
- start_index += 1;
0 \: U' _! r' Z( Z - end_index = y * full_window_stride + window_right;6 O2 T2 ^* ^5 F# P1 U
- if (y == window_bottom)$ G0 h+ {, v0 d4 y" I$ ~) ~) a# n
- encode_last_run = 1;. L5 H: n, w5 h! q$ B& z3 ?
- else6 | ~ t$ z3 @9 q; q9 R
- encode_last_run = 0;
& @9 O0 C& M% x2 j% {' E2 U - for (x = start_index; x < end_index; x++)
5 G) `6 Y, z/ ]" \ - {4 D; }+ \$ p, |! L" o
- if (!encode_last_run && full_window[x] == last_pixel)! K' F! C) Y5 V) E8 I$ v
- run_size++;# ]: q) A* q; e3 Y
- else
4 |/ d A5 A" m2 I" e+ b - {5 O) Z% t8 m2 d' q: M: ], c( U
- if (run_size == 1)# O9 t+ b* |3 U7 s, }3 }' c
- {
" F5 f+ B9 o/ X! y7 p - /* encode a 0 bit followed by raw pixel byte */
/ {% z7 }9 `; k- ? - put_bits(pb, 0, 1);6 Y. M6 ]5 q, w* \9 W8 p. x7 Z& Z
- put_bits(pb, last_pixel, 8);
# T( y. q9 u% |' Q8 }1 D8 S - }
0 \! I4 u* h* T7 ]9 K$ Y - else if (run_size == 2)
0 m; ~3 _4 b6 F' m3 d5 s - {& y5 S" _' `/ N
- /* encode a 0 bit followed by raw pixel byte */' ^% Z- S7 d1 v6 C
- put_bits(pb, 0, 1);
# b1 L2 F7 x' k9 F - put_bits(pb, last_pixel, 8);: X" H: G; ^7 a4 w" f
- put_bits(pb, 0, 1);* H/ p& r1 o4 ?. p7 ~
- put_bits(pb, last_pixel, 8);, a0 n" l% R% u$ S; Z/ b7 x8 u6 g8 x
- }
9 F# Q; [: v1 U/ e. Z g: c+ U - else3 q4 }: M2 b; k3 w8 k4 H
- {
- @$ a- ?6 }% W+ I3 ^ - /* encode a 0 bit followed by raw pixel byte */
& p6 O( {' f4 i5 L% H/ C/ \ - put_bits(pb, 0, 1);) g6 T) V( Q. t" L% h+ l
- put_bits(pb, last_pixel, 8);1 c7 ^! H6 y: F1 v$ N. O3 T+ h7 Z
- run_size--;
: p) X5 Q1 G/ T4 D% F8 u - /* encode a run: a 1 bit, followed by a back reference5 \; Q! t! d, n6 n$ U9 b
- * offset (-1), followed by a length */4 d* j- t; a8 R5 U( S
- put_bits(pb, 1, 1);6 L' P( Q# f% s8 g8 t' U
- put_bits(pb, 1, 1); /* 1 = 7-bit offset */
5 T4 T0 o3 C2 U, @" ^/ y( w - put_bits(pb, 1, 7);6 }; T V% M. o P$ A5 @6 O
- if (run_size <= 4)3 \+ h; V# G8 {5 ]
- {
: \6 L2 A- h3 s4 t3 L! p; D& t - /* lengths 2, 3, and 4 are 2 bits */% v2 n% \: z" f1 g# ^9 Z
- put_bits(pb, run_size - 2, 2);
( }( ^5 w" Q* R0 g6 q; o3 S! \5 U - }1 T8 z G0 p- A2 m$ r
- else if (run_size <= 7): z0 s, x" w& J' b. `" G
- {
7 U4 n/ D* y( C+ p) x: I - /* lengths 5, 6, and 7 are 4 bits */0 j4 D% @6 g$ s- ?
- put_bits(pb, run_size + 7, 4);
2 g; }5 o' Z8 ^6 u/ _8 q - }
: l) ~8 J: k( \# j - else
4 A* ]" I4 m: a - {
+ A8 z- Q, [) y2 p8 B1 E+ {/ y) r6 | - /* arbitrary length; start by encoding 0xF which
7 u% {5 q/ D& S! _/ o6 Z% l - * stands in for an initial version of 8 */5 q% _3 l" [; m$ o" l8 p
- put_bits(pb, 0xF, 4);
, H, ?1 s% W# d- a' H8 u. k - run_size -= 8;$ E4 i! g" T+ T( {" m3 u5 ^' M
- ' ^+ l; j- C9 F+ ^* Y
- /* encode blocks of 4 bits until run_size is 0 */
( T# b$ G0 }6 b0 ~' F6 V - while (run_size >= 0). Y3 m/ |! J e$ p1 \
- {
7 ^1 {( u: g% c5 p - if (run_size >= 15)4 D0 P: u6 Z: P* {6 W/ b% a
- {2 j9 V2 O- P$ C" K2 h9 T. T6 t
- put_bits(pb, 0xF, 4);" t9 P1 q4 ?2 t( o5 q
- run_size -= 0xF;
- `, x/ S, `* \- i# E$ m9 b/ h - }- o1 J4 U' T: p& `- i: ^# g
- else( d4 F4 K9 `8 D8 z" f6 B5 n; u9 J
- {/ V1 b0 E( i$ p5 d2 p, {
- put_bits(pb, run_size, 4);
: R5 W9 t6 |! N - run_size = -1;: j' P& m' g, h$ e5 O5 x
- }
- }8 x: P, }5 ~- C9 g - }
+ {3 O7 v( v/ I4 t - }
: C9 q; ?3 Z+ n3 h/ W - }
8 b8 R, p; P1 p. J6 T" L* W F
: N( _8 |& R7 y- last_pixel = full_window[x];
v3 W( N, a/ H! ^6 {4 H0 A - run_size = 1;
3 ^2 x4 g m$ Q5 w+ U - / y- |. a# I3 Q
- /* this single x iteration was only here to close the final run */: d9 N( u6 u, ?' g& E
- if (y == window_bottom)8 s: o- F9 r+ E& A: g7 q# m0 K4 o
- break;- ~- j. ?+ N6 i8 R2 d" I
- }
4 E7 T& _. k/ G4 K) v3 {" | - }
6 `: L4 `/ j3 Q1 b; T: u3 l9 \ - }$ I0 F% ]. ]+ Z7 b6 c' ]
, v4 E# j: }5 A- /* close the bitstream by encoding a back reference with length 0 */1 O2 I5 \ w# [: H- t4 v
- put_bits(pb, 1, 1); /* back reference run */1 ^9 D3 \: }4 T
- put_bits(pb, 1, 1); /* 1 = 7-bit offset */
' U1 b% S, T m. N! g5 u - put_bits(pb, 0, 7); /* length 0 */9 ^& p7 h+ t; }
- % r' d/ W: H6 U6 _
- put_bits_flush(pb);
/ [0 C5 A0 T% [* w0 f& f - }
4 [% u* w0 _7 ?4 X - d( r; ^. g. s) t7 W9 R) V
- /* compute Euclidean distance between an RGB color and the desired target */: t( [+ Y! x# F5 y$ ^) T
- static int compute_rgb_distance(int r1, int r2, int g1, int g2, int b1, int b2)8 l- p6 z2 r" p4 F
- {' O5 ]; m7 v1 Z- s! A& _$ ~
- return sqrt((r1 - r2) * (r1 - r2) +
) V0 P* {/ _" c - (g1 - g2) * (g1 - g2) +
3 V0 I+ g( h" k0 |$ K& L) E - (b1 - b2) * (b1 - b2));9 G4 S. P; k8 g& ^: j& G# o/ P7 ^
- }4 H" c% q/ m# V
- 4 z3 a c3 ?9 y( x9 G8 Z% E
- static uint8_t find_nearest_color(rbt_dec_context *rbt, int r, int g, int b); R/ @; @' z) Y \. C @' Q6 r
- {; W/ c3 k2 R* C
- int i;; U3 z, d" A4 _2 V+ [" ?8 A( j
- int nearest_distance;
8 P; r; S9 l* d z, I! P2 h - int distance;, i; d: w. u7 }0 U; C
- int rp;& }8 i7 j0 R' S5 l4 X4 Q" W
- int gp;/ ~" I3 z5 V* j' _3 {1 E
- int bp;
0 C, P3 K w6 g - uint8_t palette_index;
8 s. O' a+ ^5 ?9 Q8 t - & C2 c$ D' L ~3 f- T4 y
- nearest_distance = 999999999;
9 k) S2 [/ I5 l) f - palette_index = 0;
6 {0 N" {8 }/ G - for (i = 0; i < 256; i++)
: `% b: F5 R8 w" L1 E) \- P* J - {
+ B. B$ } L0 g/ S - rp = rbt->palette[i * 3 + 0];
# X7 ]% {$ D/ ]- U$ w/ u$ ^* H2 w7 l - gp = rbt->palette[i * 3 + 1];
; ^) I+ ~, k' o' V - bp = rbt->palette[i * 3 + 2];
4 ^# j7 y0 U$ S9 D - distance = compute_rgb_distance(r, rp, g, gp, b, bp);5 H8 Z3 u7 Y! J
- if (distance < nearest_distance), [& ^- D; n- I
- {: d# k* h) U- g2 ~6 x5 V! D
- nearest_distance = distance;
$ k4 o. i H+ R - palette_index = i;% ], z/ W0 J4 V% u9 k' q
- }
3 u, H$ m% }- f+ | - /* can't get closer than 0; break early */
* L2 {% n0 \- N( M% Y - if (distance == 0)- ?( w# T. c; A
- break;
4 C2 m) P0 `* j0 { - }4 F; W5 g$ u( W7 Y+ {
1 w, l9 Z) v& w0 F- b& S- return palette_index;' Z( v4 U! t f! F* J( X. s. v; C
- }
6 p3 L: c5 G+ }) r8 N2 { - " m: ~! `9 `8 j3 }
- static void subtitle_frame(rbt_dec_context *rbt, uint8_t *frame, f; x% g) h; V7 G2 t! |% F
- int width, int height, int timestamp)
. I% o9 Q+ Y7 O) X) V - {1 f' o5 x. z" m I! R
- ASS_Image *subtitles;
' m8 N0 \8 Z3 Q - int detect_change;2 Z6 S5 `) ]5 Y5 v% ?5 } {" P2 s
- uint8_t subtitle_pixel;! A ]; z' O- @
- int x, y;% p, I5 s+ x; @
- uint8_t *frame_ptr;
% T1 v0 }5 x. y" k2 { - uint8_t *subtitle_ptr;% s" e2 f' y; B8 o, O/ Q
# E- c& w& x% i! r3 `* Z- /* ask library for the subtitle for this timestamp */
; {+ J5 u" l8 @: U; E4 Z. ` - subtitles = ass_render_frame(rbt->ass_renderer, rbt->ass_track,
- n m r. i# s: C% `* M; R- A# M - timestamp, &detect_change);2 @* n: z9 ^1 ]8 ^
5 _0 [9 i1 u! O- /* render the list of subtitles onto the decoded frame */3 e$ U5 o. ~1 I0 x8 N- v; Z
- while (subtitles)
. c7 X5 U, I0 p2 i - {, C2 D/ Z' C- W8 {
- /* palette components are only 6 bits, so shift an extra 2
/ ~3 `$ S: c7 Q1 |" [ - * bits off each component */& V4 n) {- C$ c$ L3 E; P
- subtitle_pixel = find_nearest_color(rbt,
2 t) g( r0 ]- `; c. K P. w9 Q7 K - (subtitles->color >> 10) & 0xFF,
) J. t& e3 Q: C1 l - (subtitles->color >> 18) & 0xFF,0 ]# w) \) Y; l0 v2 J/ j- q. Z5 O. u
- (subtitles->color >> 26) & 0xFF);; U2 y* p. m4 J9 c9 a/ H) H
- for (y = 0; y < subtitles->h; y++)3 g* J9 G$ N$ w/ \: \' s2 L
- {3 [# ^! m* l" u
- subtitle_ptr = &subtitles->bitmap[y * subtitles->stride];
6 U' H0 u% x2 a - frame_ptr = &frame[(subtitles->dst_y + y) * width + subtitles->dst_x];
# p$ b- \4 H* M4 W6 o - for (x = 0; x < subtitles->w; x++, frame_ptr++, subtitle_ptr++)
$ @8 W) K0 E4 }3 }$ S - {- v ^& }0 A+ p4 u: p0 g8 |5 z/ k) }
- if (*subtitle_ptr >= SUBTITLE_THRESHOLD)$ W; U3 m3 @9 M5 ]
- *frame_ptr = subtitle_pixel;
" I6 G2 D6 I8 {3 g0 i - }
1 @3 v. k* J5 L6 C# W - }
: `) u5 y* a* v7 r6 B! c - subtitles = subtitles->next;
7 y7 h0 o! ~( w7 v - }
0 E' m2 g- z2 Y; h - }
6 n h( @3 [/ @1 t/ W( {
+ z7 a& {. a/ E5 ^" E8 ~$ ]" C! t- static int copy_frames(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file,7 j/ E- j4 n9 ~* k
- int origin_x, int origin_y, int window_width, int window_height)
9 [; n- ?# R/ q0 [- H - {0 y& Z4 c5 p& f' Y
- int i;( |9 p' u* W2 B+ _0 Q! l
- int j;
) r2 w3 C! ^# I) e7 F7 b - int scale;' d4 j+ B: Q( k% b j+ h- R! K
- int width;- u4 ?# m0 L4 e' Y8 m+ g6 x0 }
- int height;" E7 O" z: j+ [2 D- E# S' O3 F/ U, Y
- int max_width;
/ J& C) s0 o! \+ ~' G - int max_height;% P9 p) u$ z4 N: t$ Q
- int frame_x;
# Y3 K% g0 k) A1 E - int frame_y;9 a4 D& V2 c' e/ n9 E; V7 }
- int fragment_count;9 |3 f9 ~! Z; e- Q! N' x( d6 i5 B
- int decoded_size;) Q; p4 \8 N0 J' }5 R2 o9 t
- uint8_t *decoded_frame; F! D$ y3 F" d9 h, V, s
- int fragment;6 G. _5 ^5 a4 `/ r; I
- int fragment_compressed_size;" W* w7 {: a* K& U7 W: t: Z
- int fragment_decompressed_size;
; S* b& K& i' W - int compression_type;
: i p* r1 Q6 p0 V7 J- q' a - int index;9 X" s6 b/ N9 l) K- [
- int out_index;
+ _/ v& ` e9 W% W5 b. [* Z8 j - get_bits_context gb;
/ j B' F F; D! ~& d8 u - int frame_size;
) s0 r4 R4 b' P3 y8 C - int video_frame_size;
! M0 Y5 S1 S& w! A1 Q i - int audio_frame_size;/ Y( E: J( I: j
- 7 Z* p- i( Z5 C: f: H" {4 P* g
- int back_ref_offset_type;- t6 i2 h$ t" ~$ |$ w! Q
- int back_ref_offset;# G5 n' A( `0 U/ Y# l8 p, r
- int back_ref_length;
) O! J& ~) q/ g! y" e% W - int back_ref_start;9 z; K: w3 D' z8 s) f
- int back_ref_end;- D! J7 L8 s( Z
- Q, e5 ^( c _3 X5 E7 e; x- uint8_t *full_window;; r) R+ T) t- t% c7 s
- int full_window_size;
: e3 l7 N5 i0 H4 g" ]( ~ - int y;
: J3 o/ p4 e$ F' V/ s% k - int window_top;$ Z+ s/ X% P. @' i$ S
- int window_bottom;
7 Q( P5 z* N# x6 y B# k - int window_left;
5 C8 ]- a" h3 r2 D, j: V/ ~ - int window_right;
5 f R0 }! \3 p9 i) B$ w' { - int window_size;
7 B5 F4 h j, W
9 Q( k8 h( m0 B- char filename[30];8 p) h0 C- ^! j, O7 n4 P
- % e6 g. m* d; {/ L# }8 k
- put_bits_context *pb;& v9 q7 K. L! }9 V- D
* a/ l0 j5 L& L% L7 j$ H8 P0 q- full_window_size = window_width * window_height;
* z8 E, C5 u. t6 z! C. v2 F - full_window = malloc(full_window_size);. P# Y( {" g" s* M# i S
- pb = init_put_bits();9 [+ t2 l% x( l3 ?0 R
+ \# ^, z, K* H! y4 {1 ~- max_width = 0;* @% n/ S5 f! `' S# z
- max_height = 0;2 r4 T: q* O" r& ]% ?7 I$ e
- ) ?4 j: W# [- y8 z
- for (i = 0; i < rbt->frame_count; i++)
) [ R( x* i' e - {
) k% d1 W( V1 p) u) `# p3 m" I - /* read the entire frame (includes audio and video) */
4 H7 u$ y; ^" O' P+ C7 C/ L5 c0 ] - frame_size = LE_16(&rbt->frame_size_table[i*2]);
8 Z8 Y6 a+ ]- t* i - video_frame_size = LE_16(&rbt->video_frame_size_table[i*2]);
\% S$ s5 W, D, ^+ p; s. r - audio_frame_size = frame_size - video_frame_size;2 f R2 z$ Q2 u3 L, p& J
- if (fread(rbt->frame_load_buffer, frame_size, 1, inrbt_file) != 1)
/ L( O; o+ L# @8 p; i8 r7 ?* K - {
+ K- P5 q# I( R8 N! R X1 B - printf("problem reading frame %d\n", i);! a* D6 g) [/ k% S7 ]
- return 0;
9 F* [$ T9 x a% P7 ~ - }( K# {& e+ _7 j5 w
- 5 p. N7 L$ d- g9 O
- scale = rbt->frame_load_buffer[3];
# m1 r( j- c3 t8 v+ f, b2 v+ V; m - width = LE_16(&rbt->frame_load_buffer[4]);3 b6 z8 h) v) x0 i7 Q( C
- if (max_width < width)6 G2 P% m; U- _3 J
- max_width = width;
' S& `3 O I5 m, Y& b6 ]. {) } - if (max_height < height)
, G0 o: \ y/ c S9 k+ m G: g5 w - max_height = height;
- d% F9 s0 ~! Y3 Q0 X - height = LE_16(&rbt->frame_load_buffer[6]);9 X/ F$ s- C) T0 x
- frame_x = LE_16(&rbt->frame_load_buffer[12]);8 e. T7 k% w7 b, U$ u
- frame_y = LE_16(&rbt->frame_load_buffer[14]);$ n' Q0 `; B: e1 C
- fragment_count = LE_16(&rbt->frame_load_buffer[18]);3 [, |5 g3 N/ b+ U3 ~- N
- decoded_size = width * height;9 G: e0 O, p) f/ @: d0 s: x
- / u, }/ N# ~6 d2 i7 _
- printf("processing frame %d: %d%%, %dx%d, origin @ (%d, %d), %d fragments\n", i, scale, width, height, frame_x, frame_y, fragment_count);
& P9 r+ q% t' x5 s2 j" M8 T0 d+ g - ( [: d* [. W3 D+ ~! N
- /* decode the frame */
+ ~- A9 S! X' Y3 L2 ^6 k' L+ w; v - decoded_frame = malloc(decoded_size);' Z! L9 Q: o9 Y; O- _
- index = 24;! {" N: _3 o, i3 Y# f! m# V
- out_index = 0;. d8 i, u% f( A! O/ Z
- for (fragment = 0; fragment < fragment_count; fragment++)0 k: D& l+ J+ P9 {8 P2 G
- {
) F: _; ?, e* G( ?7 D! c! A - fragment_compressed_size = LE_32(&rbt->frame_load_buffer[index]);
3 X* o( `7 C( a$ G6 J - index += 4;+ W1 Z! }& T. @/ `' Y; o3 w
- fragment_decompressed_size = LE_32(&rbt->frame_load_buffer[index]);
7 M7 L$ ^/ o7 [% w6 F" L& y9 x - index += 4;4 W& J* J( i1 O3 \& v9 s w1 M' O; k
- compression_type = LE_16(&rbt->frame_load_buffer[index]);
( Z! \% O" o) _ - index += 2;9 u# c( z) m1 r: ^1 }2 w
& O6 y: c4 |% g* w$ H$ K- if (compression_type == 0)
1 T6 a9 `; H5 V6 }1 Y& a7 ~$ i - {* a% s% F4 y' R) ~
- init_get_bits(&gb, &rbt->frame_load_buffer[index],+ ?2 X& R$ N; t4 S0 C
- fragment_compressed_size);
6 k3 v4 ]( U8 {0 u9 d
2 k; X, c; a2 A% j+ `4 K$ J* U- while (out_index < fragment_decompressed_size)
, M1 b( o1 x9 b7 }: F5 U# c - {
8 c4 v! j; k& e: I - if (read_bits(&gb, 1))
8 b+ T7 v$ z9 T" g5 i+ s - {# J% V- H2 N6 H+ W
- /* decode back reference offset type */( ~: g- t8 T2 m
- back_ref_offset_type = read_bits(&gb, 1);# d) X. n$ x/ K. Q
- + ~( B6 c, ~% I+ I! V
- /* back reference offset is 7 or 11 bits */
5 `0 |7 ^6 Y4 V6 w. g5 R' B - back_ref_offset = read_bits(&gb,
$ v% e( c) A' `; _' J5 W - (back_ref_offset_type) ? 7 : 11);8 h/ T7 ^/ @" s
# o4 L+ C6 H. Z5 n. Y9 G- /* get the length of the back reference */
2 m8 l6 {+ [* v; m4 t - back_ref_length = get_lzs_back_ref_length(&gb);$ t3 q* N" t5 a
- back_ref_start = out_index - back_ref_offset;
' y. ~* m+ n- r$ n+ M# x) ^ - back_ref_end = back_ref_start + back_ref_length;
4 R( {- V4 H8 Z8 Y! U
9 B& y U0 w+ t" H; U. T- /* copy the back reference, byte by byte */
9 ?& E9 c1 a9 ^6 S$ e% T& d - for (j = back_ref_start; j < back_ref_end; j++)2 t+ q% i: v8 g ~
- decoded_frame[out_index++] = decoded_frame[j];, R3 J. [/ Y2 x- x& S
- }
0 L V" N J" H$ w& h1 o9 u) ? - else7 T4 Q( d4 j m: _
- {/ Q$ t+ \9 j, i+ l4 T2 Q7 a
- /* read raw pixel byte */1 c+ l) ?' a1 i7 ~
- decoded_frame[out_index++] = read_bits(&gb, 8) & 0xFF;9 S* a, B, O% W
- }
) `, u, L/ v5 Z6 c% L* b - }) g; p* D! I; i7 \ |% S5 P& D4 ]
- * b: b: s9 o" I6 \9 l# ^
- delete_get_bits(&gb);
' [7 P9 [+ C( w% S; Z1 o. Q; o - }2 `+ ^4 a7 x" f9 t# e1 P8 `
3 S% g8 ~9 d% X4 d5 R- /* next fragment */
1 F! Y- d" d& E: G. w( J& `$ v; W - index += fragment_compressed_size;$ O w, W& x/ t* u. k& {
- }
, u1 L/ g; [$ e1 [& m& P+ }0 E - : o U/ Y- m- s' {, u5 @: Z( X
- if (rbt->dump_frames)% b5 T9 R; j; x( Y
- {
. j1 w$ d; Y4 l" r- m0 r - /* dump the original frame */# N* f9 [& |+ c; v3 m+ |
- sprintf(filename, "original-frame-%03d.pnm", i);
, l f: u6 H9 ^# [9 z# B7 e+ D* E - dump_pnm_file(filename, rbt, decoded_frame, width, height);- {6 B$ h, R2 p7 l
- }
1 b; T% [; z k1 W3 d9 K# v - : i, g7 ~( \: U5 X/ m! Y
- /* transfer the image onto the frame window */
' Y' f' X: o# s4 G6 p - memset(full_window, 0xFF, full_window_size);3 h) q/ w S4 T; j2 s5 q
- index = 0;
, r- k' X( Q* j4 C, ?: X1 I# b - for (y = 0; y < height; y++)
" f9 x1 K9 e, y$ P3 V0 [, I - {; a* i8 S# c: v8 i! e- L
- out_index = window_width * (frame_y + y) + frame_x;
8 @$ I# w0 F8 A, o - memcpy(&full_window[out_index], &decoded_frame[index], width);
* X( K; G& C3 j9 c - index += width;
9 n( O& [( m7 B1 G: U1 | - }: r3 f! v: l- g& A1 @; P# _- u+ j
3 r5 }, M9 R+ R7 W( `- /* write the subtitle */
) ?+ @# `0 s: x% K" h2 ? - subtitle_frame(rbt, full_window, window_width, window_height,, o8 f0 E9 M$ \% e9 O( l( \
- i * MILLISECONDS_PER_FRAME);( v' M1 a/ r- o, O$ d$ T
- & ] h7 j7 k; k" v$ m) x! g
- /* figure out the smallest change window */
. v2 F% d' |9 Q. ~1 r - window_top = frame_y;
" u' f+ y- x: i - window_bottom = window_height;5 N# Y) V4 H& g' |5 |8 X
- window_left = 0;
1 y. y6 [; c5 F - window_right = window_width;; v- u/ k1 M1 m- H) r
- window_size = (window_right - window_left) * (window_bottom - window_top);
+ i% L \8 _' ^
2 L; g+ J& T8 k/ M$ _- /* compress the frame */
, a$ y) ?3 @; L& u _* H4 o# J% g* H - reset_put_bits(pb);, N. b8 R& b$ Y! v8 t
- compress_window(pb, full_window, window_width, window_top,
' Z; p+ m% [0 K( A" P - window_bottom, window_left, window_right);, |# `$ Y/ u1 p' C9 l
- ) A! }4 R) k A2 t5 S0 j
- if (rbt->dump_frames): k2 v$ J, A8 B/ _( W3 Y
- {
! ?( R9 e5 k E& ]5 G - /* dump the frame plotted onto the full window prior to encoding,; u6 q* @9 O2 B2 S; I) _5 ~
- * with subtitle */
8 D2 |" e( y( Q9 O- t% t - sprintf(filename, "pre-encoding-frame-%03d.pnm", i);, y+ j# F* u) S* i$ c
- dump_pnm_file(filename, rbt, full_window, window_width, window_height);: d: Z# S% f. `3 `. A6 n9 k1 N
- }
. _% C5 G4 V, f M5 W6 c - 2 }8 w* m3 m: |2 E
- free(decoded_frame);1 h7 x9 {9 t8 ~
- & Q2 j5 v' p4 X- l$ w: C6 O4 p
- /* update the frame header */
& x) E! x7 `) Q7 i, x8 P; x - /* width */
2 }( l) u3 r) R1 e - rbt->frame_load_buffer[4] = (window_right - window_left) & 0xFF;& F( \( a8 {1 n! t- Z- i! A
- rbt->frame_load_buffer[5] = (window_right - window_left) >> 8;
! |1 ~1 P/ Q2 L$ v - /* height */( G# P, ~6 o) o9 B3 e
- rbt->frame_load_buffer[6] = (window_bottom - window_top) & 0xFF;
& j4 E3 [" `6 H) v) H2 n; M - rbt->frame_load_buffer[7] = (window_bottom - window_top) >> 8;7 l. ]# H0 A/ J1 B( p
- /* origin X */
) O( g$ Z# t& ]4 c& d; e6 h) K1 z - rbt->frame_load_buffer[12] = window_left & 0xFF;
+ ?2 S* C* N6 e, j$ \ - rbt->frame_load_buffer[13] = window_left >> 8;
3 Y6 s0 X! I2 m9 g3 U1 k( c' o - /* origin Y */
# C0 a$ v f8 q7 y0 r7 _* E - rbt->frame_load_buffer[14] = window_top & 0xFF;
/ }# X- X' D5 S - rbt->frame_load_buffer[15] = window_top >> 8; x" C8 M0 [. Q: p
- /* fragment payload size */+ L& t8 d; ~% U+ [
- rbt->frame_load_buffer[16] = (pb->byte_index + 10) & 0xFF;
% f2 e7 I6 t+ D% y6 Z) r0 i7 l - rbt->frame_load_buffer[17] = (pb->byte_index + 10) >> 8;
4 U. X H: i' l8 t7 a - /* fragment count (1) */# U; m# p8 x7 B1 C, g9 D' }9 W, }
- rbt->frame_load_buffer[18] = 1;
+ r% x) V! l6 l w! _4 S1 h! ]: G. \ - rbt->frame_load_buffer[19] = 0;* Z6 M6 \8 Y% ?; s6 d7 H
- 2 L' o6 i [" k( f& i. T6 K& i
- /* update the fragment header */6 A6 d& a# B- q
- /* compressed size */
6 ~1 l, _4 h0 q( ]1 R; v - rbt->frame_load_buffer[24 + 0] = (pb->byte_index >> 0) & 0xFF;5 t+ s" W$ `- B4 \7 o
- rbt->frame_load_buffer[24 + 1] = (pb->byte_index >> 8) & 0xFF;
& D( J, F" ~* a; A# t; F - rbt->frame_load_buffer[24 + 2] = (pb->byte_index >> 16) & 0xFF;- V/ W4 D" z' E+ Y& h) D
- rbt->frame_load_buffer[24 + 3] = (pb->byte_index >> 24) & 0xFF;& `3 ^! e" c) [( V
- /* decompressed size */
9 Y A" m! g2 u - rbt->frame_load_buffer[24 + 4] = (window_size >> 0) & 0xFF;
' G; z: w. a+ X8 c8 { - rbt->frame_load_buffer[24 + 5] = (window_size >> 8) & 0xFF;, ?# N) ?/ a' W, P N
- rbt->frame_load_buffer[24 + 6] = (window_size >> 16) & 0xFF;8 @* Y( }- q* j" M# \/ ]
- rbt->frame_load_buffer[24 + 7] = (window_size >> 24) & 0xFF;
9 ]9 u5 Z% }& ^% d# a - /* compression format 0 */
3 v, f9 W3 K( @ - rbt->frame_load_buffer[24 + 8] = 0;
2 p+ C7 z, H) b4 M( H5 x+ R' E. i - rbt->frame_load_buffer[24 + 9] = 0;* S6 z& D8 v2 i9 H' M
- 5 H* I9 a- \: \4 P; J
- /* write the 24-byte frame header and the 10-byte fragment header */
3 O4 L! T# K9 k! [, u8 t2 G9 ?- U! E2 v - if (fwrite(rbt->frame_load_buffer, 24 + 10, 1, outrbt_file) != 1)
& b7 c# q- {# h' F' T( d7 ~ - {: Z8 h% G1 w% {1 }4 [# W
- printf("problem writing frame %d\n", i);
. P8 z- Y* \2 j% E6 Z1 ^. @, H5 T" ~ - return 0;0 |' t" b) C6 d0 q
- }6 Y5 j+ `" `' f# A) Y
- + G" Y% p- R* J E
- /* write the new compressed frame data */
9 Z6 R7 m+ @0 |. ~7 X3 X/ x8 n1 g - if (fwrite(pb->bytes, pb->byte_index, 1, outrbt_file) != 1)
! R7 | o, M/ c& F1 W" a8 k - {
* e6 Z. K" ? z - printf("problem writing frame %d\n", i);
( J [" o( R1 b5 u- \/ d# J- B - return 0;
+ r3 T* [# K, e8 P" U; ] - }
; ~3 q" Y8 m; `5 I - 2 ^, Z& m- T+ H0 K- B+ U0 q
- /* write the audio data *// A' i: V4 B, Q1 w3 r& S
- if (fwrite(&rbt->frame_load_buffer[video_frame_size], frame_size - video_frame_size, 1, outrbt_file) != 1)
J& R' D/ \: D& m. r - {1 U1 V! P" t H2 ]7 S
- printf("problem writing frame %d\n", i);" [! E& L# D+ X& y) i/ m
- return 0;
. w3 P: B: ^' R7 z% g ? - }+ a. L# V6 ~- T& X3 e' Q
* ~& H4 W2 l+ L- n+ E- /* update the table entries */8 g! M; C, E- {
- video_frame_size = pb->byte_index + 24 + 10;% ~ o5 _0 s4 o& A, H5 T
- frame_size = video_frame_size + audio_frame_size;" j! I# V0 N ^4 }
- rbt->frame_size_table[i*2+0] = frame_size & 0xFF;
: k1 z9 T2 c8 L+ ?8 f' I5 d e - rbt->frame_size_table[i*2+1] = frame_size >> 8;5 Q8 T/ O$ M0 w* Z/ _2 k7 @9 V
- rbt->video_frame_size_table[i*2+0] = video_frame_size & 0xFF;; Z% D+ y6 A, Z: v; H; L
- rbt->video_frame_size_table[i*2+1] = video_frame_size >> 8;3 @, I5 y1 [9 x* s8 O/ F
- }
2 l9 D% v0 M9 f, G$ J
0 @8 O' G9 @) a5 B6 ]0 ~" F4 E- printf("maximum dimensions seen are %dx%d\n", max_width, max_height);
' p9 [' M; c" _% g8 X - 1 l% {8 p+ t" z+ S6 I. x B
- delete_put_bits(pb);7 P0 }4 W0 V2 C6 n; g, r
- free(full_window);8 W J, k, O8 k0 }! ~! M. t) R
5 D5 g' g( N; n) j9 M- return 1;) D/ v9 n) Z4 ` t' g
- }
5 h8 k) ?, m" P6 B3 T, P
, L, U/ |+ w3 L- int main(int argc, char *argv[])/ I) K" Y9 \% |% ^0 a8 G5 @
- {
9 C$ ]7 L9 r% @1 W. z2 _( @ - char *subtitle_filename;& e6 L( P$ e8 r6 B a
- FILE *subtitle_file;
, V5 M9 B$ |4 d, }- M% n8 p - char *inrbt_filename;* b8 } h+ D* L) d$ ^6 B) J
- FILE *inrbt_file;7 u2 _1 B$ @: P9 r( y& v- M
- char *outrbt_filename;
4 I p% g! ~# K - FILE *outrbt_file;
0 o7 b7 v0 J7 s6 u& R - rbt_dec_context rbt;
# y& T# t! R9 p4 k) B7 i% c5 u - int origin_x;4 }# D% D: R8 o( V) T c8 {
- int origin_y;
$ ^& n, k, F# t( b - int window_width;2 u! p$ b) B B. C
- int window_height;
8 A* L% d: C- u7 Y6 |" \4 I! i
- ]1 `6 M7 d- W+ P/ S- /* testing the bit functions */" v4 g3 a& P2 K7 p
- #if 0
9 W6 Z$ ~( c& v9 _6 @+ K - int i;7 E$ ]3 n- q5 L8 X( P( A$ D
- uint8_t bytestream[] = { 0x55, 0xAA, 0x00, 0xAA, 0x55, 0x77, 0xFF, 0x1B, 0x70, 0x8F }; ^: V3 i* I7 B1 o3 c" T0 [
- int bytestream_size = 10;
; |- {. g+ K3 c - get_bits_context gb;
/ D/ F8 r4 U& @+ G# j- A- i - put_bits_context *pb;6 d8 q8 y; k' T1 U' r. G6 k1 Y, I. n
- int bits;/ v6 z7 `; Z D! s- t! d9 [0 D: ^
: c7 q( l. Y; H& e5 Y* z- init_get_bits(&gb, bytestream, bytestream_size);
5 f+ S9 S. p3 ?* ~$ n$ h6 s3 L - pb = init_put_bits();- p |( {% E) p& ~
0 c9 Z1 S# q. y4 n% Z( w- for (i = 1; i <= 12; i++)7 E; G! O$ t$ a
- {
* ?( b1 n+ L% Z7 Z - bits = view_bits(&gb, i);. M# x0 w5 C0 Z
- printf("view %d bits: %d\n", i, bits);* n+ P( A- A2 r9 P! H& Z" O9 ^5 G
- printf("read %d bits: %d\n", i, read_bits(&gb, i));
9 [8 U% ~4 L, }- I+ Q - put_bits(pb, bits, i);
3 X& s+ H k' S6 V+ `5 e4 z6 F - }
s1 K5 y! s2 P# p# E( v% N - put_bits_flush(pb);3 r# W' [4 y' c/ B1 j
/ c2 \9 s3 ~( M" N! g% H0 V( m* H- printf("original bytestream:\n");8 {0 B; [, f8 y& Z' J
- for (i = 0; i < bytestream_size; i++)/ R/ a2 T0 z3 F8 P% ^ a7 `) d- z
- printf(" %02X", bytestream[i]);$ z" r- l- ? ~* P
- printf("\nnewbytestream:\n");4 W# `$ U' d6 G- N
- for (i = 0; i < pb->byte_index; i++)
, T" [( O. T$ o* \' ? _5 \ - printf(" %02X", pb->bytes[i]); H. I: S4 [; I3 s
- printf("\n");7 V+ w- p! h( C0 h
- + d! K$ e& G I0 a; S/ e
- delete_get_bits(&gb);% U2 J5 B0 k4 j- J3 f' S" y
- free(pb);
1 }, _$ h% Q; Y - #endif- R7 k3 d+ C" ]+ l! u. D0 q; i
- 2 x7 v3 U J# V0 w4 I& x j0 e" ?' ?
- /* validate the number of arguments */8 B, G0 L$ M8 R: i- W
- if (argc != 8 && argc != 9)% p0 k/ Z1 F- G/ z7 ?) F* S8 z
- {' d7 r" C: {) }' z z+ H
- printf("USAGE: subtitle-rbt <subtitles.ass> <in.rbt> <out.rbt> <origin X> <origin Y> <width> <height> [dump_frames]\n");7 @2 j3 H% V: G( h% R* u
- return 1;
% k, @) u' |1 m7 N1 u8 q - }7 m. Q9 ?' O' P X3 I0 Q% L
- subtitle_filename = argv[1];
' y; }9 X: l6 w" r* `- s; `1 f - inrbt_filename = argv[2];
; P5 F6 q) @2 b# Z' Z: s - outrbt_filename = argv[3];, {# d1 }/ O& O, r* ~ o& d2 j
- origin_x = atoi(argv[4]);* I" v0 y4 d9 n& s; Z7 p1 d/ E$ Z
- origin_y = atoi(argv[5]);% ]; j( @1 O3 d9 n
- window_width = atoi(argv[6]);
' h8 x" y6 T) j - window_height = atoi(argv[7]);8 T7 x! Y7 b$ G0 R
- rbt.dump_frames = 0; q# c' \ C: d4 e5 n0 i% f
- if (argc == 9)
, \3 |' L& u- J# s- E8 W& a - rbt.dump_frames = 1;5 U' g1 u0 e* s7 s6 f+ c+ f8 Z( Y
- 0 K9 a6 t' K; O
- /* verify that the specified input files are valid */
) Q7 `' ? Q1 T' c% G - subtitle_file = fopen(subtitle_filename, "r"); a* X& P8 u- K) s4 L* ?
- if (!subtitle_file)3 @) Y6 q) e c
- {' f# u) ~ |. v4 D+ a* z+ \. J9 w/ l
- perror(subtitle_filename);* d6 \; x* \( Y' {. Z1 F
- return 1;
3 q6 X4 `; _2 x N" A, h - }7 ?7 J, r3 S3 p" V
- fclose(subtitle_file);7 R: [6 Y' d7 X4 |0 u k
- inrbt_file = fopen(inrbt_filename, "rb");0 R2 V5 S5 T: I# A
- if (!inrbt_file)5 m1 |$ V5 r) Y2 E% M! v3 S0 }) s
- {6 t8 v9 p0 }9 e+ k% I& V
- perror(inrbt_filename);2 b9 Z3 s5 V& r5 U: d
- return 1;) \$ r+ ~, G# j- F/ H
- }
+ A3 ~8 \ n7 v0 J
T7 x, D/ w: y8 ?6 g- /* initialize the subtitle support */' j7 R* [; d1 T! U/ K1 r7 T8 o
- rbt.ass_lib = ass_library_init();+ D% D. Y( g2 q- Z; f
- rbt.ass_renderer = ass_renderer_init(rbt.ass_lib);
0 B/ [2 a E. {) Y0 v - rbt.ass_track = ass_read_file(rbt.ass_lib, subtitle_filename, "UTF-8");+ |+ F9 L* N2 a* _2 X' e9 H: P
- ass_set_frame_size(rbt.ass_renderer, window_width, window_height);
1 B4 g4 ~ Y* E6 o; I4 q5 q/ b - ass_set_fonts(rbt.ass_renderer, NULL, NULL, 1, NULL, 1);7 P4 R1 W% k, Y+ p- u1 m. M& }
5 K2 ?5 @/ h/ C3 I' L9 s- /* open the output file */3 X4 H% N( l9 S. ]8 B
- outrbt_file = fopen(outrbt_filename, "wb");! e# o( O P9 \' H- d3 y: q
- if (!outrbt_file)
b8 N; n2 d+ _, { - {
1 g0 g8 v) N0 ^ u& O" ~. O5 s ` - perror(outrbt_filename);
& N( {7 i: N, x3 M2 D! x* |% ?9 P7 u; c - return 1;; _, J# s/ G* Z* i7 t D& J' g# z
- }
, j1 Y! I) Z$ v8 y$ [# v& p; W' x - / j$ n7 {& Y& Z4 B! K
- /* transfer header from input to output *// q) J: K1 E" h
- if (!load_and_copy_rbt_header(&rbt, inrbt_file, outrbt_file)), ~+ p0 a+ |: {0 K: k+ F) e
- return 1;
. ?9 t; M- O: ?. E! a- ~- ~
% o1 ]3 ^ ^, r6 o6 ~- /* rewrite the frames */
! c ^$ w$ r& U: |1 ~ - if (!copy_frames(&rbt, inrbt_file, outrbt_file, origin_x, origin_y,+ J0 s8 v0 {2 W _7 }( H
- window_width, window_height))
6 Z, s& d4 l' S9 H T - return 1;" K6 j( ?7 P" H4 Q0 t; T
- 1 c* i; F- ?5 t$ a" w: l O2 r/ f
- /* write the modified frame size tables back to the file */$ X6 q0 e1 Q! I) P3 q) e! |9 J
- fseek(outrbt_file, rbt.video_frame_size_table_offset, SEEK_SET);4 K$ @4 |) Z& t: M& p( o
- fwrite(rbt.video_frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);6 u4 J6 D' H ^2 l8 `2 ^& ?. x
- fseek(outrbt_file, rbt.frame_size_table_offset, SEEK_SET);4 M/ Q7 r7 u& T: q k$ Z) P5 L O6 D
- fwrite(rbt.frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);( p/ v- q6 R' ?- H
3 Q9 z4 x, P, \ X/ ^- r# p' ]- /* finished with files */
% m! r( L; \2 T' K& T - fclose(inrbt_file);
D# R. w7 { N/ K3 ?8 g8 Z - fclose(outrbt_file);) @5 v# Y5 I3 u" Q1 g
- " Y" M) F- g$ X9 r w7 `
- /* clean up subtitle library */
& q- e; S3 B6 j |6 o - ass_free_track(rbt.ass_track);9 z% F% b( H, `: b! U
- ass_renderer_done(rbt.ass_renderer);' b% B5 g. s# l
- ass_library_done(rbt.ass_lib);
: Q3 ~( {, k0 M+ Q+ X - 6 x) n; \! M5 V6 ?6 W
- /* clean up *// F# L; d' |% V- `% ], v; N
- free(rbt.frame_load_buffer);# M+ \% l: t, ], }/ `
- free(rbt.video_frame_size_table);( u$ V3 e d% R7 I# ^5 h
- free(rbt.frame_size_table);
9 J* E0 P6 K$ p( F
) n0 V- E& b+ S, J! H {- return 0;
) ^/ q$ r; z7 ]3 |/ r - }
复制代码 ! C) B/ e- E; Q- Z8 O, a
& p' a+ x7 i1 R8 z# q& I. G* K# X
# F$ T+ t z0 b" s
: Q1 U' k- W! h1 K Z/ q
|