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