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