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