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