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