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