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