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