00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <vlc/vlc.h>
00037 #include <vlc/vout.h>
00038 #include <vlc/decoder.h>
00039 #include <vlc/sout.h>
00040
00041 #include "vlc_bits.h"
00042
00043
00044
00045 #define POSX_TEXT N_("X coordinate of the subpicture")
00046 #define POSX_LONGTEXT N_("You can reposition the subpicture by providing another value here." )
00047
00048 #define POSY_TEXT N_("Y coordinate of the subpicture")
00049 #define POSY_LONGTEXT N_("You can reposition the subpicture by providing another value here." )
00050
00051 #define POS_TEXT N_("Subpicture position")
00052 #define POS_LONGTEXT N_( \
00053 "You can enforce the subpicture position on the video " \
00054 "(0=center, 1=left, 2=right, 4=top, 8=bottom, you can " \
00055 "also use combinations of these values).")
00056
00057 #define ENC_POSX_TEXT N_("X coordinate of the encoded subpicture")
00058 #define ENC_POSX_LONGTEXT N_("You can reposition the subpicture by providing another value here." )
00059
00060 #define ENC_POSY_TEXT N_("Y coordinate of encoded the subpicture")
00061 #define ENC_POSY_LONGTEXT N_("You can reposition the subpicture by providing another value here." )
00062
00063 #define TIMEOUT_TEXT N_("Timeout of subpictures")
00064 #define TIMEOUT_LONGTEXT N_( \
00065 "Subpictures get a default timeout of 15 seconds added to their remaining time." \
00066 "This will ensure that they are at least the specified time visible.")
00067
00068 static int pi_pos_values[] = { 0, 1, 2, 4, 8, 5, 6, 9, 10 };
00069 static char *ppsz_pos_descriptions[] =
00070 { N_("Center"), N_("Left"), N_("Right"), N_("Top"), N_("Bottom"),
00071 N_("Top-Left"), N_("Top-Right"), N_("Bottom-Left"), N_("Bottom-Right") };
00072
00073
00074
00075
00076 static int Open ( vlc_object_t * );
00077 static void Close( vlc_object_t * );
00078 static subpicture_t *Decode( decoder_t *, block_t ** );
00079
00080 static int OpenEncoder ( vlc_object_t * );
00081 static void CloseEncoder( vlc_object_t * );
00082 static block_t *Encode ( encoder_t *, subpicture_t * );
00083
00084 vlc_module_begin();
00085 # define DVBSUB_CFG_PREFIX "dvbsub-"
00086 set_description( _("DVB subtitles decoder") );
00087 set_capability( "decoder", 50 );
00088 set_category( CAT_INPUT );
00089 set_subcategory( SUBCAT_INPUT_SCODEC );
00090 set_callbacks( Open, Close );
00091
00092 add_integer( DVBSUB_CFG_PREFIX "position", 8, NULL, POS_TEXT, POS_LONGTEXT, VLC_TRUE );
00093 change_integer_list( pi_pos_values, ppsz_pos_descriptions, 0 );
00094 add_integer( DVBSUB_CFG_PREFIX "x", -1, NULL, POSX_TEXT, POSX_LONGTEXT, VLC_FALSE );
00095 add_integer( DVBSUB_CFG_PREFIX "y", -1, NULL, POSY_TEXT, POSY_LONGTEXT, VLC_FALSE );
00096
00097 # define ENC_CFG_PREFIX "sout-dvbsub-"
00098 add_submodule();
00099 set_description( _("DVB subtitles encoder") );
00100 set_capability( "encoder", 100 );
00101 set_callbacks( OpenEncoder, CloseEncoder );
00102
00103 add_integer( ENC_CFG_PREFIX "x", -1, NULL, ENC_POSX_TEXT, ENC_POSX_LONGTEXT, VLC_FALSE );
00104 add_integer( ENC_CFG_PREFIX "y", -1, NULL, ENC_POSY_TEXT, ENC_POSY_LONGTEXT, VLC_FALSE );
00105 add_integer( ENC_CFG_PREFIX "timeout", 15, NULL, TIMEOUT_TEXT, TIMEOUT_LONGTEXT, VLC_FALSE );
00106 vlc_module_end();
00107
00108 static const char *ppsz_enc_options[] = { NULL };
00109
00110
00111
00112
00113
00114
00115
00116
00117 typedef struct dvbsub_objectdef_s
00118 {
00119 int i_id;
00120 int i_type;
00121 int i_x;
00122 int i_y;
00123 int i_fg_pc;
00124 int i_bg_pc;
00125 char *psz_text;
00126
00127 } dvbsub_objectdef_t;
00128
00129
00130 typedef struct
00131 {
00132 uint8_t Y;
00133 uint8_t Cr;
00134 uint8_t Cb;
00135 uint8_t T;
00136
00137 } dvbsub_color_t;
00138
00139
00140 typedef struct dvbsub_clut_s
00141 {
00142 uint8_t i_id;
00143 uint8_t i_version;
00144 dvbsub_color_t c_2b[4];
00145 dvbsub_color_t c_4b[16];
00146 dvbsub_color_t c_8b[256];
00147
00148 struct dvbsub_clut_s *p_next;
00149
00150 } dvbsub_clut_t;
00151
00152
00153
00154 typedef struct dvbsub_region_s
00155 {
00156 int i_id;
00157 int i_version;
00158 int i_x;
00159 int i_y;
00160 int i_width;
00161 int i_height;
00162 int i_level_comp;
00163 int i_depth;
00164 int i_clut;
00165
00166 uint8_t *p_pixbuf;
00167
00168 int i_object_defs;
00169 dvbsub_objectdef_t *p_object_defs;
00170
00171 struct dvbsub_region_s *p_next;
00172
00173 } dvbsub_region_t;
00174
00175
00176 typedef struct dvbsub_regiondef_s
00177 {
00178 int i_id;
00179 int i_x;
00180 int i_y;
00181
00182 } dvbsub_regiondef_t;
00183
00184
00185 typedef struct
00186 {
00187 int i_id;
00188 int i_timeout;
00189 int i_state;
00190 int i_version;
00191
00192 int i_region_defs;
00193 dvbsub_regiondef_t *p_region_defs;
00194
00195 } dvbsub_page_t;
00196
00197 struct decoder_sys_t
00198 {
00199 bs_t bs;
00200
00201
00202 int i_id;
00203 int i_ancillary_id;
00204 mtime_t i_pts;
00205
00206 vlc_bool_t b_absolute;
00207 int i_spu_position;
00208 int i_spu_x;
00209 int i_spu_y;
00210
00211 vlc_bool_t b_page;
00212 dvbsub_page_t *p_page;
00213 dvbsub_region_t *p_regions;
00214 dvbsub_clut_t *p_cluts;
00215 dvbsub_clut_t default_clut;
00216 };
00217
00218
00219
00220
00221 #define DVBSUB_ST_PAGE_COMPOSITION 0x10
00222 #define DVBSUB_ST_REGION_COMPOSITION 0x11
00223 #define DVBSUB_ST_CLUT_DEFINITION 0x12
00224 #define DVBSUB_ST_OBJECT_DATA 0x13
00225 #define DVBSUB_ST_ENDOFDISPLAY 0x80
00226 #define DVBSUB_ST_STUFFING 0xff
00227
00228
00229 #define DVBSUB_OT_BASIC_BITMAP 0x00
00230 #define DVBSUB_OT_BASIC_CHAR 0x01
00231 #define DVBSUB_OT_COMPOSITE_STRING 0x02
00232
00233
00234 #define DVBSUB_DT_2BP_CODE_STRING 0x10
00235 #define DVBSUB_DT_4BP_CODE_STRING 0x11
00236 #define DVBSUB_DT_8BP_CODE_STRING 0x12
00237 #define DVBSUB_DT_24_TABLE_DATA 0x20
00238 #define DVBSUB_DT_28_TABLE_DATA 0x21
00239 #define DVBSUB_DT_48_TABLE_DATA 0x22
00240 #define DVBSUB_DT_END_LINE 0xf0
00241
00242
00243 #define DVBSUB_PCS_STATE_ACQUISITION 0x01
00244 #define DVBSUB_PCS_STATE_CHANGE 0x10
00245
00246
00247
00248
00249 static void decode_segment( decoder_t *, bs_t * );
00250 static void decode_page_composition( decoder_t *, bs_t * );
00251 static void decode_region_composition( decoder_t *, bs_t * );
00252 static void decode_object( decoder_t *, bs_t * );
00253 static void decode_clut( decoder_t *, bs_t * );
00254 static void free_all( decoder_t * );
00255
00256 static void default_clut_init( decoder_t * );
00257
00258 static subpicture_t *render( decoder_t * );
00259
00260
00261
00262
00263
00264
00265
00266 static int Open( vlc_object_t *p_this )
00267 {
00268 decoder_t *p_dec = (decoder_t *) p_this;
00269 decoder_sys_t *p_sys;
00270 vlc_value_t val;
00271 int i_posx, i_posy;
00272
00273 if( p_dec->fmt_in.i_codec != VLC_FOURCC('d','v','b','s') )
00274 {
00275 return VLC_EGENERIC;
00276 }
00277
00278 p_dec->pf_decode_sub = Decode;
00279 p_sys = p_dec->p_sys = malloc( sizeof(decoder_sys_t) );
00280 memset( p_sys, 0, sizeof(decoder_sys_t) );
00281
00282 p_sys->i_pts = (mtime_t) 0;
00283 p_sys->i_id = p_dec->fmt_in.subs.dvb.i_id & 0xFFFF;
00284 p_sys->i_ancillary_id = p_dec->fmt_in.subs.dvb.i_id >> 16;
00285
00286 p_sys->p_regions = NULL;
00287 p_sys->p_cluts = NULL;
00288 p_sys->p_page = NULL;
00289
00290 var_Create( p_this, DVBSUB_CFG_PREFIX "position",
00291 VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
00292 var_Get( p_this, DVBSUB_CFG_PREFIX "position", &val );
00293 p_sys->i_spu_position = val.i_int;
00294 var_Create( p_this, DVBSUB_CFG_PREFIX "x",
00295 VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
00296 var_Get( p_this, DVBSUB_CFG_PREFIX "x", &val );
00297 i_posx = val.i_int;
00298 var_Create( p_this, DVBSUB_CFG_PREFIX "y",
00299 VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
00300 var_Get( p_this, DVBSUB_CFG_PREFIX "y", &val );
00301 i_posy = val.i_int;
00302
00303
00304 p_sys->b_absolute = VLC_TRUE;
00305 p_sys->i_spu_x = p_sys->i_spu_y = 0;
00306
00307 if( i_posx >= 0 && i_posy >= 0 )
00308 {
00309 p_sys->b_absolute = VLC_FALSE;
00310 p_sys->i_spu_x = i_posx;
00311 p_sys->i_spu_y = i_posy;
00312 }
00313
00314 es_format_Init( &p_dec->fmt_out, SPU_ES, VLC_FOURCC( 'd','v','b','s' ) );
00315
00316 default_clut_init( p_dec );
00317
00318 return VLC_SUCCESS;
00319 }
00320
00321
00322
00323
00324 static void Close( vlc_object_t *p_this )
00325 {
00326 decoder_t *p_dec = (decoder_t*) p_this;
00327 decoder_sys_t *p_sys = p_dec->p_sys;
00328
00329 var_Destroy( p_this, DVBSUB_CFG_PREFIX "x" );
00330 var_Destroy( p_this, DVBSUB_CFG_PREFIX "y" );
00331 var_Destroy( p_this, DVBSUB_CFG_PREFIX "position" );
00332
00333 free_all( p_dec );
00334 free( p_sys );
00335 }
00336
00337
00338
00339
00340 static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
00341 {
00342 decoder_sys_t *p_sys = p_dec->p_sys;
00343 block_t *p_block;
00344 subpicture_t *p_spu = NULL;
00345
00346 if( pp_block == NULL || *pp_block == NULL ) return NULL;
00347 p_block = *pp_block;
00348 *pp_block = NULL;
00349
00350 p_sys->i_pts = p_block->i_pts;
00351 if( p_sys->i_pts <= 0 )
00352 {
00353 #ifdef DEBUG_DVBSUB
00354
00355
00356 msg_Warn( p_dec, "non dated subtitle" );
00357 #endif
00358 block_Release( p_block );
00359 return NULL;
00360 }
00361
00362 bs_init( &p_sys->bs, p_block->p_buffer, p_block->i_buffer );
00363
00364 if( bs_read( &p_sys->bs, 8 ) != 0x20 )
00365 {
00366 msg_Dbg( p_dec, "invalid data identifier" );
00367 block_Release( p_block );
00368 return NULL;
00369 }
00370
00371 if( bs_read( &p_sys->bs, 8 ) )
00372 {
00373 msg_Dbg( p_dec, "invalid subtitle stream id" );
00374 block_Release( p_block );
00375 return NULL;
00376 }
00377
00378 #ifdef DEBUG_DVBSUB
00379 msg_Dbg( p_dec, "subtitle packet received: "I64Fd, p_sys->i_pts );
00380 #endif
00381
00382 p_sys->b_page = VLC_FALSE;
00383 while( bs_show( &p_sys->bs, 8 ) == 0x0f )
00384 {
00385 decode_segment( p_dec, &p_sys->bs );
00386 }
00387
00388 if( bs_read( &p_sys->bs, 8 ) != 0xff )
00389 {
00390 msg_Warn( p_dec, "end marker not found (corrupted subtitle ?)" );
00391 block_Release( p_block );
00392 return NULL;
00393 }
00394
00395
00396 if( p_sys->p_page && p_sys->b_page ) p_spu = render( p_dec );
00397
00398 block_Release( p_block );
00399
00400 return p_spu;
00401 }
00402
00403
00404
00405
00406
00407
00408 static void default_clut_init( decoder_t *p_dec )
00409 {
00410 decoder_sys_t *p_sys = p_dec->p_sys;
00411 uint8_t i;
00412
00413 #define RGB_TO_Y(r, g, b) ((int16_t) 77 * r + 150 * g + 29 * b) / 256;
00414 #define RGB_TO_U(r, g, b) ((int16_t) -44 * r - 87 * g + 131 * b) / 256;
00415 #define RGB_TO_V(r, g, b) ((int16_t) 131 * r - 110 * g - 21 * b) / 256;
00416
00417
00418 for( i = 0; i < 4; i++ )
00419 {
00420 uint8_t R = 0, G = 0, B = 0, T = 0;
00421
00422 if( !(i & 0x2) && !(i & 0x1) ) T = 0xFF;
00423 else if( !(i & 0x2) && (i & 0x1) ) R = G = B = 0xFF;
00424 else if( (i & 0x2) && !(i & 0x1) ) R = G = B = 0;
00425 else R = G = B = 0x7F;
00426
00427 p_sys->default_clut.c_2b[i].Y = RGB_TO_Y(R,G,B);
00428 p_sys->default_clut.c_2b[i].Cr = RGB_TO_U(R,G,B);
00429 p_sys->default_clut.c_2b[i].Cb = RGB_TO_V(R,G,B);
00430 p_sys->default_clut.c_2b[i].T = T;
00431 }
00432
00433
00434 for( i = 0; i < 16; i++ )
00435 {
00436 uint8_t R = 0, G = 0, B = 0, T = 0;
00437
00438 if( !(i & 0x8) )
00439 {
00440 if( !(i & 0x4) && !(i & 0x2) && !(i & 0x1) )
00441 {
00442 T = 0xFF;
00443 }
00444 else
00445 {
00446 R = (i & 0x1) ? 0xFF : 0;
00447 G = (i & 0x2) ? 0xFF : 0;
00448 B = (i & 0x4) ? 0xFF : 0;
00449 }
00450 }
00451 else
00452 {
00453 R = (i & 0x1) ? 0x7F : 0;
00454 G = (i & 0x2) ? 0x7F : 0;
00455 B = (i & 0x4) ? 0x7F : 0;
00456 }
00457
00458 p_sys->default_clut.c_4b[i].Y = RGB_TO_Y(R,G,B);
00459 p_sys->default_clut.c_4b[i].Cr = RGB_TO_U(R,G,B);
00460 p_sys->default_clut.c_4b[i].Cb = RGB_TO_V(R,G,B);
00461 p_sys->default_clut.c_4b[i].T = T;
00462 }
00463
00464
00465 memset( p_sys->default_clut.c_8b, 0xFF, 256 * sizeof(dvbsub_color_t) );
00466 }
00467
00468 static void decode_segment( decoder_t *p_dec, bs_t *s )
00469 {
00470 decoder_sys_t *p_sys = p_dec->p_sys;
00471 int i_type;
00472 int i_page_id;
00473 int i_size;
00474
00475
00476 bs_skip( s, 8 );
00477
00478
00479 i_type = bs_read( s, 8 );
00480
00481
00482 i_page_id = bs_read( s, 16 );
00483
00484
00485 i_size = bs_show( s, 16 );
00486
00487 if( i_page_id != p_sys->i_id && i_page_id != p_sys->i_ancillary_id )
00488 {
00489 #ifdef DEBUG_DVBSUB
00490 msg_Dbg( p_dec, "subtitle skipped (page id: %i, %i)",
00491 i_page_id, p_sys->i_id );
00492 #endif
00493 bs_skip( s, 8 * ( 2 + i_size ) );
00494 return;
00495 }
00496
00497 if( p_sys->i_ancillary_id != p_sys->i_id &&
00498 i_type == DVBSUB_ST_PAGE_COMPOSITION &&
00499 i_page_id == p_sys->i_ancillary_id )
00500 {
00501 #ifdef DEBUG_DVBSUB
00502 msg_Dbg( p_dec, "skipped invalid ancillary subtitle packet" );
00503 #endif
00504 bs_skip( s, 8 * ( 2 + i_size ) );
00505 return;
00506 }
00507
00508 #ifdef DEBUG_DVBSUB
00509 if( i_page_id == p_sys->i_id )
00510 msg_Dbg( p_dec, "segment (id: %i)", i_page_id );
00511 else
00512 msg_Dbg( p_dec, "ancillary segment (id: %i)", i_page_id );
00513 #endif
00514
00515 switch( i_type )
00516 {
00517 case DVBSUB_ST_PAGE_COMPOSITION:
00518 #ifdef DEBUG_DVBSUB
00519 msg_Dbg( p_dec, "decode_page_composition" );
00520 #endif
00521 decode_page_composition( p_dec, s );
00522 break;
00523
00524 case DVBSUB_ST_REGION_COMPOSITION:
00525 #ifdef DEBUG_DVBSUB
00526 msg_Dbg( p_dec, "decode_region_composition" );
00527 #endif
00528 decode_region_composition( p_dec, s );
00529 break;
00530
00531 case DVBSUB_ST_CLUT_DEFINITION:
00532 #ifdef DEBUG_DVBSUB
00533 msg_Dbg( p_dec, "decode_clut" );
00534 #endif
00535 decode_clut( p_dec, s );
00536 break;
00537
00538 case DVBSUB_ST_OBJECT_DATA:
00539 #ifdef DEBUG_DVBSUB
00540 msg_Dbg( p_dec, "decode_object" );
00541 #endif
00542 decode_object( p_dec, s );
00543 break;
00544
00545 case DVBSUB_ST_ENDOFDISPLAY:
00546 #ifdef DEBUG_DVBSUB
00547 msg_Dbg( p_dec, "end of display" );
00548 #endif
00549 bs_skip( s, 8 * ( 2 + i_size ) );
00550 break;
00551
00552 case DVBSUB_ST_STUFFING:
00553 #ifdef DEBUG_DVBSUB
00554 msg_Dbg( p_dec, "skip stuffing" );
00555 #endif
00556 bs_skip( s, 8 * ( 2 + i_size ) );
00557 break;
00558
00559 default:
00560 msg_Warn( p_dec, "unsupported segment type: (%04x)", i_type );
00561 bs_skip( s, 8 * ( 2 + i_size ) );
00562 break;
00563 }
00564 }
00565
00566 static void decode_clut( decoder_t *p_dec, bs_t *s )
00567 {
00568 decoder_sys_t *p_sys = p_dec->p_sys;
00569 uint16_t i_segment_length;
00570 uint16_t i_processed_length;
00571 dvbsub_clut_t *p_clut, *p_next;
00572 int i_id, i_version;
00573
00574 i_segment_length = bs_read( s, 16 );
00575 i_id = bs_read( s, 8 );
00576 i_version = bs_read( s, 4 );
00577
00578
00579 for( p_clut = p_sys->p_cluts; p_clut != NULL; p_clut = p_clut->p_next )
00580 {
00581 if( p_clut->i_id == i_id ) break;
00582 }
00583
00584
00585 if( p_clut && p_clut->i_version == i_version )
00586 {
00587
00588 bs_skip( s, 8 * i_segment_length - 12 );
00589 return;
00590 }
00591
00592 if( !p_clut )
00593 {
00594 #ifdef DEBUG_DVBSUB
00595 msg_Dbg( p_dec, "new clut: %i", i_id );
00596 #endif
00597 p_clut = malloc( sizeof(dvbsub_clut_t) );
00598 p_clut->p_next = p_sys->p_cluts;
00599 p_sys->p_cluts = p_clut;
00600 }
00601
00602
00603 p_next = p_clut->p_next;
00604 *p_clut = p_sys->default_clut;
00605 p_clut->p_next = p_next;
00606
00607
00608 p_clut->i_version = i_version;
00609 p_clut->i_id = i_id;
00610 bs_skip( s, 4 );
00611 i_processed_length = 2;
00612 while( i_processed_length < i_segment_length )
00613 {
00614 uint8_t y, cb, cr, t;
00615 uint8_t i_id;
00616 uint8_t i_type;
00617
00618 i_id = bs_read( s, 8 );
00619 i_type = bs_read( s, 3 );
00620
00621 bs_skip( s, 4 );
00622
00623 if( bs_read( s, 1 ) )
00624 {
00625 y = bs_read( s, 8 );
00626 cr = bs_read( s, 8 );
00627 cb = bs_read( s, 8 );
00628 t = bs_read( s, 8 );
00629 i_processed_length += 6;
00630 }
00631 else
00632 {
00633 y = bs_read( s, 6 ) << 2;
00634 cr = bs_read( s, 4 ) << 4;
00635 cb = bs_read( s, 4 ) << 4;
00636 t = bs_read( s, 2 ) << 6;
00637 i_processed_length += 4;
00638 }
00639
00640
00641
00642
00643 if( y == 0 )
00644 {
00645 cr = cb = 0;
00646 t = 0xff;
00647 }
00648
00649
00650
00651
00652 if( i_type & 0x04 && i_id < 4 )
00653 {
00654 p_clut->c_2b[i_id].Y = y;
00655 p_clut->c_2b[i_id].Cr = cr;
00656 p_clut->c_2b[i_id].Cb = cb;
00657 p_clut->c_2b[i_id].T = t;
00658 }
00659 if( i_type & 0x02 && i_id < 16 )
00660 {
00661 p_clut->c_4b[i_id].Y = y;
00662 p_clut->c_4b[i_id].Cr = cr;
00663 p_clut->c_4b[i_id].Cb = cb;
00664 p_clut->c_4b[i_id].T = t;
00665 }
00666 if( i_type & 0x01 )
00667 {
00668 p_clut->c_8b[i_id].Y = y;
00669 p_clut->c_8b[i_id].Cr = cr;
00670 p_clut->c_8b[i_id].Cb = cb;
00671 p_clut->c_8b[i_id].T = t;
00672 }
00673 }
00674 }
00675
00676 static void decode_page_composition( decoder_t *p_dec, bs_t *s )
00677 {
00678 decoder_sys_t *p_sys = p_dec->p_sys;
00679 int i_version, i_state, i_segment_length, i_timeout, i;
00680
00681
00682 i_segment_length = bs_read( s, 16 );
00683 i_timeout = bs_read( s, 8 );
00684 i_version = bs_read( s, 4 );
00685 i_state = bs_read( s, 2 );
00686 bs_skip( s, 2 );
00687
00688 if( i_state == DVBSUB_PCS_STATE_CHANGE )
00689 {
00690
00691 #ifdef DEBUG_DVBSUB
00692 msg_Dbg( p_dec, "page composition mode change" );
00693 #endif
00694 free_all( p_dec );
00695 }
00696 else if( !p_sys->p_page && i_state != DVBSUB_PCS_STATE_ACQUISITION &&
00697 i_state != DVBSUB_PCS_STATE_CHANGE )
00698 {
00699
00700 msg_Dbg( p_dec, "didn't receive an acquisition page yet" );
00701
00702 #if 0
00703
00704 bs_skip( s, 8 * (i_segment_length - 2) );
00705 return;
00706 #endif
00707 }
00708
00709 #ifdef DEBUG_DVBSUB
00710 if( i_state == DVBSUB_PCS_STATE_ACQUISITION )
00711 msg_Dbg( p_dec, "acquisition page composition" );
00712 #endif
00713
00714
00715 if( p_sys->p_page && p_sys->p_page->i_version == i_version )
00716 {
00717 bs_skip( s, 8 * (i_segment_length - 2) );
00718 return;
00719 }
00720 else if( p_sys->p_page )
00721 {
00722 if( p_sys->p_page->i_region_defs )
00723 free( p_sys->p_page->p_region_defs );
00724 p_sys->p_page->i_region_defs = 0;
00725 }
00726
00727 if( !p_sys->p_page )
00728 {
00729 #ifdef DEBUG_DVBSUB
00730 msg_Dbg( p_dec, "new page" );
00731 #endif
00732
00733 p_sys->p_page = malloc( sizeof(dvbsub_page_t) );
00734 }
00735
00736 p_sys->p_page->i_version = i_version;
00737 p_sys->p_page->i_timeout = i_timeout;
00738 p_sys->b_page = VLC_TRUE;
00739
00740
00741 p_sys->p_page->i_region_defs = (i_segment_length - 2) / 6;
00742
00743 if( p_sys->p_page->i_region_defs == 0 ) return;
00744
00745 p_sys->p_page->p_region_defs =
00746 malloc( p_sys->p_page->i_region_defs * sizeof(dvbsub_region_t) );
00747 for( i = 0; i < p_sys->p_page->i_region_defs; i++ )
00748 {
00749 p_sys->p_page->p_region_defs[i].i_id = bs_read( s, 8 );
00750 bs_skip( s, 8 );
00751 p_sys->p_page->p_region_defs[i].i_x = bs_read( s, 16 );
00752 p_sys->p_page->p_region_defs[i].i_y = bs_read( s, 16 );
00753
00754 #ifdef DEBUG_DVBSUB
00755 msg_Dbg( p_dec, "page_composition, region %i (%i,%i)",
00756 i, p_sys->p_page->p_region_defs[i].i_x,
00757 p_sys->p_page->p_region_defs[i].i_y );
00758 #endif
00759 }
00760 }
00761
00762 static void decode_region_composition( decoder_t *p_dec, bs_t *s )
00763 {
00764 decoder_sys_t *p_sys = p_dec->p_sys;
00765 dvbsub_region_t *p_region, **pp_region = &p_sys->p_regions;
00766 int i_segment_length, i_processed_length, i_id, i_version;
00767 int i_width, i_height, i_level_comp, i_depth, i_clut;
00768 int i_8_bg, i_4_bg, i_2_bg;
00769 vlc_bool_t b_fill;
00770
00771 i_segment_length = bs_read( s, 16 );
00772 i_id = bs_read( s, 8 );
00773 i_version = bs_read( s, 4 );
00774
00775
00776 for( p_region = p_sys->p_regions; p_region != NULL;
00777 p_region = p_region->p_next )
00778 {
00779 pp_region = &p_region->p_next;
00780 if( p_region->i_id == i_id ) break;
00781 }
00782
00783
00784 if( p_region && p_region->i_version == i_version )
00785 {
00786 bs_skip( s, 8 * (i_segment_length - 1) - 4 );
00787 return;
00788 }
00789
00790 if( !p_region )
00791 {
00792 #ifdef DEBUG_DVBSUB
00793 msg_Dbg( p_dec, "new region: %i", i_id );
00794 #endif
00795 p_region = *pp_region = malloc( sizeof(dvbsub_region_t) );
00796 memset( p_region, 0, sizeof(dvbsub_region_t) );
00797 p_region->p_object_defs = NULL;
00798 p_region->p_pixbuf = NULL;
00799 p_region->p_next = NULL;
00800 }
00801
00802
00803 p_region->i_id = i_id;
00804 p_region->i_version = i_version;
00805 b_fill = bs_read( s, 1 );
00806 bs_skip( s, 3 );
00807
00808 i_width = bs_read( s, 16 );
00809 i_height = bs_read( s, 16 );
00810 #ifdef DEBUG_DVBSUB
00811 msg_Dbg( p_dec, " width=%d height=%d", i_width, i_height );
00812 #endif
00813 i_level_comp = bs_read( s, 3 );
00814 i_depth = bs_read( s, 3 );
00815 bs_skip( s, 2 );
00816 i_clut = bs_read( s, 8 );
00817
00818 i_8_bg = bs_read( s, 8 );
00819 i_4_bg = bs_read( s, 4 );
00820 i_2_bg = bs_read( s, 2 );
00821 bs_skip( s, 2 );
00822
00823
00824 while( p_region->i_object_defs )
00825 {
00826 int i = p_region->i_object_defs - 1;
00827 if( p_region->p_object_defs[i].psz_text )
00828 free( p_region->p_object_defs[i].psz_text );
00829 if( !i ) free( p_region->p_object_defs );
00830
00831 p_region->i_object_defs--;
00832 }
00833 p_region->p_object_defs = NULL;
00834
00835
00836 if( p_region->i_width != i_width || p_region->i_height != i_height )
00837 {
00838 if( p_region->p_pixbuf )
00839 {
00840 msg_Dbg( p_dec, "region size changed (not allowed)" );
00841 free( p_region->p_pixbuf );
00842 }
00843
00844 p_region->p_pixbuf = malloc( i_height * i_width );
00845 p_region->i_depth = 0;
00846 b_fill = VLC_TRUE;
00847 }
00848 if( p_region->i_depth && (p_region->i_depth != i_depth ||
00849 p_region->i_level_comp != i_level_comp || p_region->i_clut != i_clut) )
00850 {
00851 msg_Dbg( p_dec, "region parameters changed (not allowed)" );
00852 }
00853
00854
00855 if( b_fill )
00856 {
00857 int i_background = (p_region->i_depth == 1) ? i_2_bg :
00858 (p_region->i_depth == 2) ? i_4_bg : i_8_bg;
00859 memset( p_region->p_pixbuf, i_background, i_width * i_height );
00860 }
00861
00862 p_region->i_width = i_width;
00863 p_region->i_height = i_height;
00864 p_region->i_level_comp = i_level_comp;
00865 p_region->i_depth = i_depth;
00866 p_region->i_clut = i_clut;
00867
00868
00869 i_processed_length = 10;
00870 while( i_processed_length < i_segment_length )
00871 {
00872 dvbsub_objectdef_t *p_obj;
00873
00874
00875 p_region->i_object_defs++;
00876 p_region->p_object_defs =
00877 realloc( p_region->p_object_defs,
00878 sizeof(dvbsub_objectdef_t) * p_region->i_object_defs );
00879
00880
00881 p_obj = &p_region->p_object_defs[p_region->i_object_defs - 1];
00882 p_obj->i_id = bs_read( s, 16 );
00883 p_obj->i_type = bs_read( s, 2 );
00884 bs_skip( s, 2 );
00885 p_obj->i_x = bs_read( s, 12 );
00886 bs_skip( s, 4 );
00887 p_obj->i_y = bs_read( s, 12 );
00888 p_obj->psz_text = 0;
00889
00890 i_processed_length += 6;
00891
00892 if( p_obj->i_type == DVBSUB_OT_BASIC_CHAR ||
00893 p_obj->i_type == DVBSUB_OT_COMPOSITE_STRING )
00894 {
00895 p_obj->i_fg_pc = bs_read( s, 8 );
00896 p_obj->i_bg_pc = bs_read( s, 8 );
00897 i_processed_length += 2;
00898 }
00899 }
00900 }
00901
00902 static void dvbsub_render_pdata( decoder_t *, dvbsub_region_t *, int, int,
00903 uint8_t *, int );
00904 static void dvbsub_pdata2bpp( bs_t *, uint8_t *, int, int * );
00905 static void dvbsub_pdata4bpp( bs_t *, uint8_t *, int, int * );
00906 static void dvbsub_pdata8bpp( bs_t *, uint8_t *, int, int * );
00907
00908 static void decode_object( decoder_t *p_dec, bs_t *s )
00909 {
00910 decoder_sys_t *p_sys = p_dec->p_sys;
00911 dvbsub_region_t *p_region;
00912 int i_segment_length, i_coding_method, i_version, i_id, i;
00913 vlc_bool_t b_non_modify_color;
00914
00915
00916
00917
00918 i_segment_length = bs_read( s, 16 );
00919 i_id = bs_read( s, 16 );
00920 i_version = bs_read( s, 4 );
00921 i_coding_method = bs_read( s, 2 );
00922
00923 if( i_coding_method > 1 )
00924 {
00925 msg_Dbg( p_dec, "Unknown DVB subtitling coding %d is not handled!", i_coding_method );
00926 bs_skip( s, 8 * (i_segment_length - 2) - 6 );
00927 return;
00928 }
00929
00930
00931
00932 for( p_region = p_sys->p_regions; p_region != NULL;
00933 p_region = p_region->p_next )
00934 {
00935 for( i = 0; i < p_region->i_object_defs; i++ )
00936 if( p_region->p_object_defs[i].i_id == i_id ) break;
00937
00938 if( i != p_region->i_object_defs ) break;
00939 }
00940 if( !p_region )
00941 {
00942 bs_skip( s, 8 * (i_segment_length - 2) - 6 );
00943 return;
00944 }
00945
00946 #ifdef DEBUG_DVBSUB
00947 msg_Dbg( p_dec, "new object: %i", i_id );
00948 #endif
00949
00950 b_non_modify_color = bs_read( s, 1 );
00951 bs_skip( s, 1 );
00952
00953 if( i_coding_method == 0x00 )
00954 {
00955 int i_topfield, i_bottomfield;
00956 uint8_t *p_topfield, *p_bottomfield;
00957
00958 i_topfield = bs_read( s, 16 );
00959 i_bottomfield = bs_read( s, 16 );
00960 p_topfield = s->p_start + bs_pos( s ) / 8;
00961 p_bottomfield = p_topfield + i_topfield;
00962
00963 bs_skip( s, 8 * (i_segment_length - 7) );
00964
00965
00966 if( i_segment_length < i_topfield + i_bottomfield + 7 ||
00967 p_topfield + i_topfield + i_bottomfield > s->p_end )
00968 {
00969 msg_Dbg( p_dec, "corrupted object data" );
00970 return;
00971 }
00972
00973 for( p_region = p_sys->p_regions; p_region != NULL;
00974 p_region = p_region->p_next )
00975 {
00976 for( i = 0; i < p_region->i_object_defs; i++ )
00977 {
00978 if( p_region->p_object_defs[i].i_id != i_id ) continue;
00979
00980 dvbsub_render_pdata( p_dec, p_region,
00981 p_region->p_object_defs[i].i_x,
00982 p_region->p_object_defs[i].i_y,
00983 p_topfield, i_topfield );
00984
00985 if( i_bottomfield )
00986 {
00987 dvbsub_render_pdata( p_dec, p_region,
00988 p_region->p_object_defs[i].i_x,
00989 p_region->p_object_defs[i].i_y + 1,
00990 p_bottomfield, i_bottomfield );
00991 }
00992 else
00993 {
00994
00995 dvbsub_render_pdata( p_dec, p_region,
00996 p_region->p_object_defs[i].i_x,
00997 p_region->p_object_defs[i].i_y + 1,
00998 p_topfield, i_topfield );
00999 }
01000 }
01001 }
01002 }
01003 else
01004 {
01005
01006 int i_number_of_codes = bs_read( s, 8 );
01007 uint8_t* p_start = s->p_start + bs_pos( s ) / 8;
01008
01009
01010 if( i_segment_length < i_number_of_codes*2 + 4 ||
01011 p_start + i_number_of_codes*2 > s->p_end )
01012 {
01013 msg_Dbg( p_dec, "corrupted object data" );
01014 return;
01015 }
01016
01017 for( p_region = p_sys->p_regions; p_region != NULL;
01018 p_region = p_region->p_next )
01019 {
01020 for( i = 0; i < p_region->i_object_defs; i++ )
01021 {
01022 int j;
01023
01024 if( p_region->p_object_defs[i].i_id != i_id ) continue;
01025
01026 p_region->p_object_defs[i].psz_text =
01027 realloc( p_region->p_object_defs[i].psz_text,
01028 i_number_of_codes + 1 );
01029
01030 for( j = 0; j < i_number_of_codes; j++ )
01031 {
01032 p_region->p_object_defs[i].psz_text[j] = bs_read( s, 16 );
01033 }
01034 p_region->p_object_defs[i].psz_text[j] = 0;
01035 }
01036 }
01037 }
01038
01039 #ifdef DEBUG_DVBSUB
01040 msg_Dbg( p_dec, "end object: %i", i_id );
01041 #endif
01042 }
01043
01044 static void dvbsub_render_pdata( decoder_t *p_dec, dvbsub_region_t *p_region,
01045 int i_x, int i_y,
01046 uint8_t *p_field, int i_field )
01047 {
01048 uint8_t *p_pixbuf;
01049 int i_offset = 0;
01050 bs_t bs;
01051
01052
01053 if( !p_region->p_pixbuf )
01054 {
01055 msg_Err( p_dec, "region %i has no pixel buffer!", p_region->i_id );
01056 return;
01057 }
01058 if( i_y < 0 || i_x < 0 || i_y >= p_region->i_height ||
01059 i_x >= p_region->i_width )
01060 {
01061 msg_Dbg( p_dec, "invalid offset (%i,%i)", i_x, i_y );
01062 return;
01063 }
01064
01065 p_pixbuf = p_region->p_pixbuf + i_y * p_region->i_width;
01066 bs_init( &bs, p_field, i_field );
01067
01068 while( !bs_eof( &bs ) )
01069 {
01070
01071 if( i_y >= p_region->i_height ) return;
01072
01073 switch( bs_read( &bs, 8 ) )
01074 {
01075 case 0x10:
01076 dvbsub_pdata2bpp( &bs, p_pixbuf + i_x, p_region->i_width - i_x,
01077 &i_offset );
01078 break;
01079
01080 case 0x11:
01081 dvbsub_pdata4bpp( &bs, p_pixbuf + i_x, p_region->i_width - i_x,
01082 &i_offset );
01083 break;
01084
01085 case 0x12:
01086 dvbsub_pdata8bpp( &bs, p_pixbuf + i_x, p_region->i_width - i_x,
01087 &i_offset );
01088 break;
01089
01090 case 0x20:
01091 case 0x21:
01092 case 0x22:
01093
01094 break;
01095
01096 case 0xf0:
01097 p_pixbuf += 2*p_region->i_width;
01098 i_offset = 0; i_y += 2;
01099 break;
01100 }
01101 }
01102 }
01103
01104 static void dvbsub_pdata2bpp( bs_t *s, uint8_t *p, int i_width, int *pi_off )
01105 {
01106 vlc_bool_t b_stop = 0;
01107
01108 while( !b_stop && !bs_eof( s ) )
01109 {
01110 int i_count = 0, i_color = 0;
01111
01112 if( (i_color = bs_read( s, 2 )) != 0x00 )
01113 {
01114 i_count = 1;
01115 }
01116 else
01117 {
01118 if( bs_read( s, 1 ) == 0x01 )
01119 {
01120 i_count = 3 + bs_read( s, 3 );
01121 i_color = bs_read( s, 2 );
01122 }
01123 else
01124 {
01125 if( bs_read( s, 1 ) == 0x00 )
01126 {
01127 switch( bs_read( s, 2 ) )
01128 {
01129 case 0x00:
01130 b_stop = 1;
01131 break;
01132 case 0x01:
01133 i_count = 2;
01134 break;
01135 case 0x02:
01136 i_count = 12 + bs_read( s, 4 );
01137 i_color = bs_read( s, 2 );
01138 break;
01139 case 0x03:
01140 i_count = 29 + bs_read( s, 8 );
01141 i_color = bs_read( s, 2 );
01142 break;
01143 default:
01144 break;
01145 }
01146 }
01147 else
01148 {
01149
01150 i_count = 1;
01151 }
01152 }
01153 }
01154
01155 if( !i_count ) continue;
01156
01157
01158 if( i_count + *pi_off > i_width ) break;
01159
01160 if( i_count == 1 ) p[*pi_off] = i_color;
01161 else memset( p + *pi_off, i_color, i_count );
01162
01163 (*pi_off) += i_count;
01164 }
01165
01166 bs_align( s );
01167 }
01168
01169 static void dvbsub_pdata4bpp( bs_t *s, uint8_t *p, int i_width, int *pi_off )
01170 {
01171 vlc_bool_t b_stop = 0;
01172
01173 while( !b_stop && !bs_eof( s ) )
01174 {
01175 int i_count = 0, i_color = 0;
01176
01177 if( (i_color = bs_read( s, 4 )) != 0x00 )
01178 {
01179
01180 i_count = 1;
01181 }
01182 else
01183 {
01184 if( bs_read( s, 1 ) == 0x00 )
01185 {
01186 if( bs_show( s, 3 ) != 0x00 )
01187 {
01188 i_count = 2 + bs_read( s, 3 );
01189 }
01190 else
01191 {
01192 bs_skip( s, 3 );
01193 b_stop = 1;
01194 }
01195 }
01196 else
01197 {
01198 if( bs_read( s, 1 ) == 0x00)
01199 {
01200 i_count = 4 + bs_read( s, 2 );
01201 i_color = bs_read( s, 4 );
01202 }
01203 else
01204 {
01205 switch ( bs_read( s, 2 ) )
01206 {
01207 case 0x0:
01208 i_count = 1;
01209 break;
01210 case 0x1:
01211 i_count = 2;
01212 break;
01213 case 0x2:
01214 i_count = 9 + bs_read( s, 4 );
01215 i_color = bs_read( s, 4 );
01216 break;
01217 case 0x3:
01218 i_count= 25 + bs_read( s, 8 );
01219 i_color = bs_read( s, 4 );
01220 break;
01221 }
01222 }
01223 }
01224 }
01225
01226 if( !i_count ) continue;
01227
01228
01229 if( i_count + *pi_off > i_width ) break;
01230
01231 if( i_count == 1 ) p[*pi_off] = i_color;
01232 else memset( p + *pi_off, i_color, i_count );
01233
01234 (*pi_off) += i_count;
01235 }
01236
01237 bs_align( s );
01238 }
01239
01240 static void dvbsub_pdata8bpp( bs_t *s, uint8_t *p, int i_width, int *pi_off )
01241 {
01242 vlc_bool_t b_stop = 0;
01243
01244 while( !b_stop && !bs_eof( s ) )
01245 {
01246 int i_count = 0, i_color = 0;
01247
01248 if( (i_color = bs_read( s, 8 )) != 0x00 )
01249 {
01250
01251 i_count = 1;
01252 }
01253 else
01254 {
01255 if( bs_read( s, 1 ) == 0x00 )
01256 {
01257 if( bs_show( s, 7 ) != 0x00 )
01258 {
01259 i_count = bs_read( s, 7 );
01260 }
01261 else
01262 {
01263 bs_skip( s, 7 );
01264 b_stop = 1;
01265 }
01266 }
01267 else
01268 {
01269 i_count = bs_read( s, 7 );
01270 i_color = bs_read( s, 8 );
01271 }
01272 }
01273
01274 if( !i_count ) continue;
01275
01276
01277 if( i_count + *pi_off > i_width ) break;
01278
01279 if( i_count == 1 ) p[*pi_off] = i_color;
01280 else memset( p + *pi_off, i_color, i_count );
01281
01282 (*pi_off) += i_count;
01283 }
01284
01285 bs_align( s );
01286 }
01287
01288 static void free_all( decoder_t *p_dec )
01289 {
01290 decoder_sys_t *p_sys = p_dec->p_sys;
01291 dvbsub_region_t *p_reg, *p_reg_next;
01292 dvbsub_clut_t *p_clut, *p_clut_next;
01293
01294 for( p_clut = p_sys->p_cluts; p_clut != NULL; p_clut = p_clut_next )
01295 {
01296 p_clut_next = p_clut->p_next;
01297 free( p_clut );
01298 }
01299 p_sys->p_cluts = NULL;
01300
01301 for( p_reg = p_sys->p_regions; p_reg != NULL; p_reg = p_reg_next )
01302 {
01303 int i;
01304
01305 p_reg_next = p_reg->p_next;
01306 for( i = 0; i < p_reg->i_object_defs; i++ )
01307 if( p_reg->p_object_defs[i].psz_text )
01308 free( p_reg->p_object_defs[i].psz_text );
01309 if( p_reg->i_object_defs ) free( p_reg->p_object_defs );
01310 if( p_reg->p_pixbuf ) free( p_reg->p_pixbuf );
01311 free( p_reg );
01312 }
01313 p_sys->p_regions = NULL;
01314
01315 if( p_sys->p_page )
01316 {
01317 if( p_sys->p_page->i_region_defs )
01318 free( p_sys->p_page->p_region_defs );
01319 free( p_sys->p_page );
01320 }
01321 p_sys->p_page = NULL;
01322 }
01323
01324 static subpicture_t *render( decoder_t *p_dec )
01325 {
01326 decoder_sys_t *p_sys = p_dec->p_sys;
01327 subpicture_t *p_spu;
01328 subpicture_region_t **pp_spu_region;
01329 int i, j, i_timeout = 0;
01330
01331
01332 p_spu = p_dec->pf_spu_buffer_new( p_dec );
01333 if( !p_spu ) return NULL;
01334
01335 pp_spu_region = &p_spu->p_region;
01336
01337
01338 #ifdef DEBUG_DVBSUB
01339 if( p_sys->p_page )
01340 msg_Dbg( p_dec, "rendering %i regions", p_sys->p_page->i_region_defs );
01341 #endif
01342
01343 for( i = 0; p_sys->p_page && i < p_sys->p_page->i_region_defs; i++ )
01344 {
01345 dvbsub_region_t *p_region;
01346 dvbsub_regiondef_t *p_regiondef;
01347 dvbsub_clut_t *p_clut;
01348 dvbsub_color_t *p_color;
01349 subpicture_region_t *p_spu_region;
01350 uint8_t *p_src, *p_dst;
01351 video_format_t fmt;
01352 int i_pitch;
01353
01354 i_timeout = p_sys->p_page->i_timeout;
01355
01356 p_regiondef = &p_sys->p_page->p_region_defs[i];
01357
01358 #ifdef DEBUG_DVBSUB
01359 msg_Dbg( p_dec, "rendering region %i (%i,%i)", i,
01360 p_regiondef->i_x, p_regiondef->i_y );
01361 #endif
01362
01363
01364 for( p_region = p_sys->p_regions; p_region != NULL;
01365 p_region = p_region->p_next )
01366 {
01367 if( p_regiondef->i_id == p_region->i_id ) break;
01368 }
01369
01370 if( !p_region )
01371 {
01372 msg_Dbg( p_dec, "region %i not found", p_regiondef->i_id );
01373 continue;
01374 }
01375
01376
01377 for( p_clut = p_sys->p_cluts; p_clut != NULL; p_clut = p_clut->p_next )
01378 {
01379 if( p_region->i_clut == p_clut->i_id ) break;
01380 }
01381 if( !p_clut )
01382 {
01383 msg_Dbg( p_dec, "clut %i not found", p_region->i_clut );
01384 continue;
01385 }
01386
01387
01388 memset( &fmt, 0, sizeof(video_format_t) );
01389 fmt.i_chroma = VLC_FOURCC('Y','U','V','P');
01390 fmt.i_aspect = 0;
01391 fmt.i_width = fmt.i_visible_width = p_region->i_width;
01392 fmt.i_height = fmt.i_visible_height = p_region->i_height;
01393 fmt.i_x_offset = fmt.i_y_offset = 0;
01394 p_spu_region = p_spu->pf_create_region( VLC_OBJECT(p_dec), &fmt );
01395 if( !p_spu_region )
01396 {
01397 msg_Err( p_dec, "cannot allocate SPU region" );
01398 continue;
01399 }
01400 p_spu_region->i_x = p_regiondef->i_x;
01401 p_spu_region->i_y = p_regiondef->i_y;
01402 *pp_spu_region = p_spu_region;
01403 pp_spu_region = &p_spu_region->p_next;
01404
01405
01406 fmt.p_palette->i_entries = p_region->i_depth == 1 ? 4 :
01407 p_region->i_depth == 2 ? 16 : 256;
01408 p_color = (p_region->i_depth == 1) ? p_clut->c_2b :
01409 (p_region->i_depth == 2) ? p_clut->c_4b : p_clut->c_8b;
01410 for( j = 0; j < fmt.p_palette->i_entries; j++ )
01411 {
01412 fmt.p_palette->palette[j][0] = p_color[j].Y;
01413 fmt.p_palette->palette[j][1] = p_color[j].Cr;
01414 fmt.p_palette->palette[j][2] = p_color[j].Cb;
01415 fmt.p_palette->palette[j][3] = 0xff - p_color[j].T;
01416 }
01417
01418 p_src = p_region->p_pixbuf;
01419 p_dst = p_spu_region->picture.Y_PIXELS;
01420 i_pitch = p_spu_region->picture.Y_PITCH;
01421
01422
01423 for( j = 0; j < p_region->i_height; j++ )
01424 {
01425 memcpy( p_dst, p_src, p_region->i_width );
01426 p_src += p_region->i_width;
01427 p_dst += i_pitch;
01428 }
01429
01430
01431
01432 for( j = 0; j < p_region->i_object_defs; j++ )
01433 {
01434 dvbsub_objectdef_t *p_object_def = &p_region->p_object_defs[j];
01435
01436 if( p_object_def->i_type != 1 || !p_object_def->psz_text )
01437 continue;
01438
01439
01440 memset( &fmt, 0, sizeof(video_format_t) );
01441 fmt.i_chroma = VLC_FOURCC('T','E','X','T');
01442 fmt.i_aspect = VOUT_ASPECT_FACTOR;
01443 fmt.i_width = fmt.i_visible_width = p_region->i_width;
01444 fmt.i_height = fmt.i_visible_height = p_region->i_height;
01445 fmt.i_x_offset = fmt.i_y_offset = 0;
01446 p_spu_region = p_spu->pf_create_region( VLC_OBJECT(p_dec), &fmt );
01447 if( !p_region )
01448 {
01449 msg_Err( p_dec, "cannot allocate SPU region" );
01450 continue;
01451 }
01452
01453 p_spu_region->psz_text = strdup( p_object_def->psz_text );
01454 p_spu_region->i_x = p_regiondef->i_x + p_object_def->i_x;
01455 p_spu_region->i_y = p_regiondef->i_y + p_object_def->i_y;
01456 *pp_spu_region = p_spu_region;
01457 pp_spu_region = &p_spu_region->p_next;
01458 }
01459 }
01460
01461
01462 p_spu->i_start = p_sys->i_pts;
01463 p_spu->i_stop = p_spu->i_start + (mtime_t) (i_timeout * 1000000);
01464 p_spu->b_ephemer = VLC_TRUE;
01465 p_spu->b_fade = VLC_TRUE;
01466
01467
01468 p_spu->b_absolute = p_sys->b_absolute;
01469 p_spu->i_flags = p_sys->i_spu_position;
01470 p_spu->i_x = p_sys->i_spu_x;
01471 p_spu->i_y = p_sys->i_spu_y;
01472
01473 return p_spu;
01474 }
01475
01476
01477
01478
01479 typedef struct encoder_region_t
01480 {
01481 int i_width;
01482 int i_height;
01483
01484 } encoder_region_t;
01485
01486 struct encoder_sys_t
01487 {
01488 unsigned int i_page_ver;
01489 unsigned int i_region_ver;
01490 unsigned int i_clut_ver;
01491
01492 int i_regions;
01493 encoder_region_t *p_regions;
01494
01495 mtime_t i_pts;
01496
01497
01498 int i_offset_x;
01499 int i_offset_y;
01500 int i_timeout_delay;
01501 };
01502
01503 static void encode_page_composition( encoder_t *, bs_t *, subpicture_t * );
01504 static void encode_clut( encoder_t *, bs_t *, subpicture_t * );
01505 static void encode_region_composition( encoder_t *, bs_t *, subpicture_t * );
01506 static void encode_object( encoder_t *, bs_t *, subpicture_t * );
01507
01508
01509
01510
01511 static int OpenEncoder( vlc_object_t *p_this )
01512 {
01513 encoder_t *p_enc = (encoder_t *)p_this;
01514 encoder_sys_t *p_sys;
01515 vlc_value_t val;
01516
01517 if( p_enc->fmt_out.i_codec != VLC_FOURCC('d','v','b','s') &&
01518 !p_enc->b_force )
01519 {
01520 return VLC_EGENERIC;
01521 }
01522
01523
01524 if( ( p_sys = (encoder_sys_t *)malloc(sizeof(encoder_sys_t)) ) == NULL )
01525 {
01526 msg_Err( p_enc, "out of memory" );
01527 return VLC_ENOMEM;
01528 }
01529 p_enc->p_sys = p_sys;
01530
01531 p_enc->pf_encode_sub = Encode;
01532 p_enc->fmt_out.i_codec = VLC_FOURCC('d','v','b','s');
01533 p_enc->fmt_out.subs.dvb.i_id = 1 << 16 | 1;
01534
01535 sout_CfgParse( p_enc, ENC_CFG_PREFIX, ppsz_enc_options, p_enc->p_cfg );
01536
01537 p_sys->i_page_ver = 0;
01538 p_sys->i_region_ver = 0;
01539 p_sys->i_clut_ver = 0;
01540 p_sys->i_regions = 0;
01541 p_sys->p_regions = 0;
01542
01543 var_Create( p_this, ENC_CFG_PREFIX "x", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
01544 var_Get( p_this, ENC_CFG_PREFIX "x", &val );
01545 p_sys->i_offset_x = val.i_int;
01546 var_Create( p_this, ENC_CFG_PREFIX "y", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
01547 var_Get( p_this, ENC_CFG_PREFIX "y", &val );
01548 p_sys->i_offset_y = val.i_int;
01549 var_Create( p_this, ENC_CFG_PREFIX "timeout", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
01550 var_Get( p_this, ENC_CFG_PREFIX "timeout", &val );
01551 p_sys->i_timeout_delay = val.i_int;
01552
01553 return VLC_SUCCESS;
01554 }
01555
01556
01557
01558
01559 static subpicture_t *YuvaYuvp( encoder_t *p_enc, subpicture_t *p_subpic )
01560 {
01561 subpicture_region_t *p_region = NULL;
01562
01563 if( !p_subpic ) return NULL;
01564
01565 for( p_region = p_subpic->p_region; p_region; p_region = p_region->p_next )
01566 {
01567 video_format_t *p_fmt = &p_region->fmt;
01568 int i = 0, j = 0, n = 0, p = 0;
01569 int i_max_entries = 256;
01570
01571 #ifdef RANDOM_DITHERING
01572 int i_seed = 0xdeadbeef;
01573 #else
01574 int *pi_delta;
01575 #endif
01576 int i_pixels = p_region->picture.p[0].i_visible_lines
01577 * p_region->picture.p[0].i_pitch;
01578 int i_iterator = p_region->picture.p[0].i_visible_lines * 3 / 4
01579 * p_region->picture.p[0].i_pitch
01580 + p_region->picture.p[0].i_pitch * 1 / 3;
01581 int i_tolerance = 0;
01582
01583 #if DEBUG_DVBSUB
01584 msg_Dbg( p_enc, "YuvaYuvp: i_pixels=%d, i_iterator=%d", i_pixels, i_iterator );
01585 #endif
01586 p_fmt->i_chroma = VLC_FOURCC('Y','U','V','P');
01587 p_fmt->p_palette = (video_palette_t *) malloc( sizeof( video_palette_t ) );
01588 if( !p_fmt->p_palette ) break;
01589 p_fmt->p_palette->i_entries = 0;
01590
01591
01592 for( ; i_iterator > 1 ; i_iterator-- )
01593 {
01594 int a = i_pixels;
01595 int b = i_iterator;
01596 int c;
01597
01598 while( b )
01599 {
01600 c = a % b;
01601 a = b;
01602 b = c;
01603 }
01604
01605 if( a == 1 )
01606 {
01607 break;
01608 }
01609 }
01610
01611
01612 for( i_tolerance = 0; i_tolerance < 128; i_tolerance++ )
01613 {
01614 vlc_bool_t b_success = VLC_TRUE;
01615 p_fmt->p_palette->i_entries = 0;
01616
01617 for( i = 0; i < i_pixels ; )
01618 {
01619 uint8_t y, u, v, a;
01620 y = p_region->picture.p[0].p_pixels[i];
01621 u = p_region->picture.p[1].p_pixels[i];
01622 v = p_region->picture.p[2].p_pixels[i];
01623 a = p_region->picture.p[3].p_pixels[i];
01624 for( j = 0; j < p_fmt->p_palette->i_entries; j++ )
01625 {
01626 if( abs((int)p_fmt->p_palette->palette[j][0] - (int)y) <= i_tolerance &&
01627 abs((int)p_fmt->p_palette->palette[j][1] - (int)u) <= i_tolerance &&
01628 abs((int)p_fmt->p_palette->palette[j][2] - (int)v) <= i_tolerance &&
01629 abs((int)p_fmt->p_palette->palette[j][3] - (int)a) <= i_tolerance / 2 )
01630 {
01631 break;
01632 }
01633 }
01634 if( j == p_fmt->p_palette->i_entries )
01635 {
01636 p_fmt->p_palette->palette[j][0] = y;
01637 p_fmt->p_palette->palette[j][1] = u;
01638 p_fmt->p_palette->palette[j][2] = v;
01639 p_fmt->p_palette->palette[j][3] = a;
01640 p_fmt->p_palette->i_entries++;
01641 }
01642 if( p_fmt->p_palette->i_entries >= i_max_entries )
01643 {
01644 b_success = VLC_FALSE;
01645 break;
01646 }
01647 i += i_iterator;
01648 if( i > i_pixels )
01649 {
01650 i -= i_pixels;
01651 }
01652 }
01653
01654 if( b_success )
01655 {
01656 break;
01657 }
01658 }
01659
01660 #if DEBUG_DVBSUB
01661 msg_Dbg( p_enc, "best palette has %d colors", p_fmt->p_palette->i_entries );
01662 #endif
01663
01664 #ifndef RANDOM_DITHERING
01665 pi_delta = malloc( ( p_region->picture.p[0].i_pitch + 1 )
01666 * sizeof(int) * 4 );
01667 for( i = 0; i < (p_region->picture.p[0].i_pitch + 1) * 4 ; i++ )
01668 {
01669 pi_delta[ i ] = 0;
01670 }
01671 #endif
01672
01673
01674 for( p = 0; p < p_region->picture.p[0].i_visible_lines ; p++ )
01675 {
01676 int i_ydelta = 0, i_udelta = 0, i_vdelta = 0, i_adelta = 0;
01677
01678 for( n = 0; n < p_region->picture.p[0].i_pitch ; n++ )
01679 {
01680 int i_offset = p * p_region->picture.p[0].i_pitch + n;
01681 int y, u, v, a;
01682 int i_mindist, i_best;
01683
01684 y = (int)p_region->picture.p[0].p_pixels[i_offset];
01685 u = (int)p_region->picture.p[1].p_pixels[i_offset];
01686 v = (int)p_region->picture.p[2].p_pixels[i_offset];
01687 a = (int)p_region->picture.p[3].p_pixels[i_offset];
01688
01689
01690 #ifdef RANDOM_DITHERING
01691 y += ((i_seed & 0xff) - 0x80) * i_tolerance / 0x80;
01692 u += (((i_seed >> 8) & 0xff) - 0x80) * i_tolerance / 0x80;
01693 v += (((i_seed >> 16) & 0xff) - 0x80) * i_tolerance / 0x80;
01694 a += (((i_seed >> 24) & 0xff) - 0x80) * i_tolerance / 0x80;
01695 #else
01696 y += i_ydelta + pi_delta[ n * 4 ];
01697 u += i_udelta + pi_delta[ n * 4 + 1 ];
01698 v += i_vdelta + pi_delta[ n * 4 + 2 ];
01699 a += i_adelta + pi_delta[ n * 4 + 3 ];
01700 #endif
01701
01702
01703 for( i_mindist = 99999999, i_best = 0, j = 0; j < p_fmt->p_palette->i_entries; j++ )
01704 {
01705 int i_dist = 0;
01706
01707 i_dist += abs((int)p_fmt->p_palette->palette[j][0] - y);
01708 i_dist += abs((int)p_fmt->p_palette->palette[j][1] - u);
01709 i_dist += abs((int)p_fmt->p_palette->palette[j][2] - v);
01710 i_dist += 2 * abs((int)p_fmt->p_palette->palette[j][3] - a);
01711
01712 if( i_dist < i_mindist )
01713 {
01714 i_mindist = i_dist;
01715 i_best = j;
01716 }
01717 }
01718
01719
01720 p_region->picture.p[0].p_pixels[i_offset] = i_best;
01721
01722
01723 #ifdef RANDOM_DITHERING
01724 i_seed = (i_seed * 0x1283837) ^ 0x789479 ^ (i_seed >> 13);
01725 #else
01726 i_ydelta = y - (int)p_fmt->p_palette->palette[i_best][0];
01727 i_udelta = u - (int)p_fmt->p_palette->palette[i_best][1];
01728 i_vdelta = v - (int)p_fmt->p_palette->palette[i_best][2];
01729 i_adelta = a - (int)p_fmt->p_palette->palette[i_best][3];
01730 pi_delta[ n * 4 ] = i_ydelta * 3 / 8;
01731 pi_delta[ n * 4 + 1 ] = i_udelta * 3 / 8;
01732 pi_delta[ n * 4 + 2 ] = i_vdelta * 3 / 8;
01733 pi_delta[ n * 4 + 3 ] = i_adelta * 3 / 8;
01734 i_ydelta = i_ydelta * 5 / 8;
01735 i_udelta = i_udelta * 5 / 8;
01736 i_vdelta = i_vdelta * 5 / 8;
01737 i_adelta = i_adelta * 5 / 8;
01738 #endif
01739 }
01740 }
01741 #ifndef RANDOM_DITHERING
01742 free( pi_delta );
01743 #endif
01744
01745
01746 for( i = p_fmt->p_palette->i_entries; i < i_max_entries; i++ )
01747 {
01748 p_fmt->p_palette->palette[i][0] = 0;
01749 p_fmt->p_palette->palette[i][1] = 0;
01750 p_fmt->p_palette->palette[i][2] = 0;
01751 p_fmt->p_palette->palette[i][3] = 0;
01752 }
01753 p_fmt->p_palette->i_entries = i_max_entries;
01754 #if DEBUG_DVBSUB
01755 msg_Dbg( p_enc, "best palette has %d colors", p_fmt->p_palette->i_entries );
01756 #endif
01757 }
01758 return p_subpic;
01759 }
01760
01761
01762
01763
01764 static block_t *Encode( encoder_t *p_enc, subpicture_t *p_subpic )
01765 {
01766 subpicture_t *p_temp = NULL;
01767 subpicture_region_t *p_region = NULL;
01768 bs_t bits, *s = &bits;
01769 block_t *p_block;
01770
01771 if( !p_subpic || !p_subpic->p_region ) return NULL;
01772
01773
01774
01775
01776 p_region = p_subpic->p_region;
01777 if( p_region->fmt.i_chroma == VLC_FOURCC('Y','U','V','A') )
01778 {
01779 p_temp = YuvaYuvp( p_enc, p_subpic );
01780 if( !p_temp )
01781 {
01782 msg_Err( p_enc, "no picture in subpicture" );
01783 return NULL;
01784 }
01785 p_region = p_subpic->p_region;
01786 }
01787
01788
01789 if( !p_region ) return NULL;
01790
01791 if( p_region->fmt.i_chroma != VLC_FOURCC('T','E','X','T') &&
01792 p_region->fmt.i_chroma != VLC_FOURCC('Y','U','V','P') ) return NULL;
01793
01794 if( p_region->fmt.p_palette )
01795 {
01796 switch( p_region->fmt.p_palette->i_entries )
01797 {
01798 case 0:
01799 case 4:
01800 case 16:
01801 case 256:
01802 break;
01803 default:
01804 msg_Err( p_enc, "subpicture palette (%d) not handled",
01805 p_region->fmt.p_palette->i_entries );
01806 return NULL;
01807 }
01808 }
01809
01810
01811 #if DEBUG_DVBSUB
01812 msg_Dbg( p_enc, "encoding subpicture" );
01813 #endif
01814 p_block = block_New( p_enc, 64000 );
01815 bs_init( s, p_block->p_buffer, p_block->i_buffer );
01816
01817 bs_write( s, 8, 0x20 );
01818 bs_write( s, 8, 0x0 );
01819
01820 encode_page_composition( p_enc, s, p_subpic );
01821 encode_region_composition( p_enc, s, p_subpic );
01822 encode_clut( p_enc, s, p_subpic );
01823 encode_object( p_enc, s, p_subpic );
01824
01825
01826 bs_write( s, 8, 0x0f );
01827 bs_write( s, 8, DVBSUB_ST_ENDOFDISPLAY );
01828 bs_write( s, 16, 1 );
01829 bs_write( s, 16, 0 );
01830
01831 bs_write( s, 8, 0xff );
01832 p_block->i_buffer = bs_pos( s ) / 8;
01833 p_block->i_pts = p_block->i_dts = p_subpic->i_start;
01834 if( !p_subpic->b_ephemer && p_subpic->i_stop > p_subpic->i_start )
01835 {
01836 block_t *p_block_stop;
01837
01838 p_block->i_length = p_subpic->i_stop - p_subpic->i_start;
01839
01840
01841 p_block_stop = block_New( p_enc, 64000 );
01842 bs_init( s, p_block_stop->p_buffer, p_block_stop->i_buffer );
01843 bs_write( s, 8, 0x20 );
01844 bs_write( s, 8, 0x0 );
01845 encode_page_composition( p_enc, s, 0 );
01846 bs_write( s, 8, 0x0f );
01847 bs_write( s, 8, DVBSUB_ST_ENDOFDISPLAY );
01848 bs_write( s, 16, 1 );
01849 bs_write( s, 16, 0 );
01850 bs_write( s, 8, 0xff );
01851 p_block_stop->i_buffer = bs_pos( s ) / 8;
01852 p_block_stop->i_pts = p_block_stop->i_dts = p_subpic->i_stop;
01853 block_ChainAppend( &p_block, p_block_stop );
01854 p_block_stop->i_length = 100000;
01855 }
01856 #ifdef DEBUG_DVBSUB
01857 msg_Dbg( p_enc, "subpicture encoded properly" );
01858 #endif
01859 return p_block;
01860 }
01861
01862
01863
01864
01865 static void CloseEncoder( vlc_object_t *p_this )
01866 {
01867 encoder_t *p_enc = (encoder_t *)p_this;
01868 encoder_sys_t *p_sys = p_enc->p_sys;
01869
01870 var_Destroy( p_this , ENC_CFG_PREFIX "x" );
01871 var_Destroy( p_this , ENC_CFG_PREFIX "y" );
01872 var_Destroy( p_this , ENC_CFG_PREFIX "timeout" );
01873
01874 if( p_sys->i_regions ) free( p_sys->p_regions );
01875 free( p_sys );
01876 }
01877
01878 static void encode_page_composition( encoder_t *p_enc, bs_t *s,
01879 subpicture_t *p_subpic )
01880 {
01881 encoder_sys_t *p_sys = p_enc->p_sys;
01882 subpicture_region_t *p_region;
01883 vlc_bool_t b_mode_change = VLC_FALSE;
01884 int i_regions, i_timeout;
01885
01886 bs_write( s, 8, 0x0f );
01887 bs_write( s, 8, DVBSUB_ST_PAGE_COMPOSITION );
01888 bs_write( s, 16, 1 );
01889
01890 for( i_regions = 0, p_region = p_subpic ? p_subpic->p_region : 0;
01891 p_region; p_region = p_region->p_next, i_regions++ )
01892 {
01893 if( i_regions >= p_sys->i_regions )
01894 {
01895 encoder_region_t region;
01896 region.i_width = region.i_height = 0;
01897 p_sys->p_regions =
01898 realloc( p_sys->p_regions, sizeof(encoder_region_t) *
01899 (p_sys->i_regions + 1) );
01900 p_sys->p_regions[p_sys->i_regions++] = region;
01901 }
01902
01903 if( ( p_sys->p_regions[i_regions].i_width <
01904 (int)p_region->fmt.i_visible_width ) ||
01905 ( p_sys->p_regions[i_regions].i_width >
01906 (int)p_region->fmt.i_visible_width ) )
01907 {
01908 b_mode_change = VLC_TRUE;
01909 msg_Dbg( p_enc, "region %i width change: %i -> %i",
01910 i_regions, p_sys->p_regions[i_regions].i_width,
01911 p_region->fmt.i_visible_width );
01912 p_sys->p_regions[i_regions].i_width =
01913 p_region->fmt.i_visible_width;
01914 }
01915 if( ( p_sys->p_regions[i_regions].i_height <
01916 (int)p_region->fmt.i_visible_height ) ||
01917 ( p_sys->p_regions[i_regions].i_height >
01918 (int)p_region->fmt.i_visible_height ) )
01919 {
01920 b_mode_change = VLC_TRUE;
01921 msg_Dbg( p_enc, "region %i height change: %i -> %i",
01922 i_regions, p_sys->p_regions[i_regions].i_height,
01923 p_region->fmt.i_visible_height );
01924 p_sys->p_regions[i_regions].i_height =
01925 p_region->fmt.i_visible_height;
01926 }
01927 }
01928
01929 bs_write( s, 16, i_regions * 6 + 2 );
01930
01931 i_timeout = 0;
01932 if( p_subpic && !p_subpic->b_ephemer &&
01933 p_subpic->i_stop > p_subpic->i_start )
01934 {
01935 i_timeout = (p_subpic->i_stop - p_subpic->i_start) / 1000000;
01936 }
01937
01938 bs_write( s, 8, i_timeout + p_sys->i_timeout_delay );
01939 bs_write( s, 4, p_sys->i_page_ver++ );
01940 bs_write( s, 2, b_mode_change ?
01941 DVBSUB_PCS_STATE_CHANGE : DVBSUB_PCS_STATE_ACQUISITION );
01942 bs_write( s, 2, 0 );
01943
01944 for( i_regions = 0, p_region = p_subpic ? p_subpic->p_region : 0;
01945 p_region; p_region = p_region->p_next, i_regions++ )
01946 {
01947 bs_write( s, 8, i_regions );
01948 bs_write( s, 8, 0 );
01949 if( (p_sys->i_offset_x > 0) && (p_sys->i_offset_y > 0) )
01950 {
01951 bs_write( s, 16, p_sys->i_offset_x );
01952 bs_write( s, 16, p_sys->i_offset_y );
01953 }
01954 else
01955 {
01956 bs_write( s, 16, p_region->i_x );
01957 bs_write( s, 16, p_region->i_y );
01958 }
01959 }
01960 }
01961
01962 static void encode_clut( encoder_t *p_enc, bs_t *s, subpicture_t *p_subpic )
01963 {
01964 encoder_sys_t *p_sys = p_enc->p_sys;
01965 subpicture_region_t *p_region = p_subpic->p_region;
01966 video_palette_t *p_pal, pal;
01967 int i;
01968
01969
01970 if( !p_region ) return;
01971
01972 if( p_region->fmt.i_chroma == VLC_FOURCC('Y','U','V','P') )
01973 {
01974 p_pal = p_region->fmt.p_palette;
01975 }
01976 else
01977 {
01978 pal.i_entries = 4;
01979 for( i = 0; i < 4; i++ )
01980 {
01981 pal.palette[i][0] = 0;
01982 pal.palette[i][1] = 0;
01983 pal.palette[i][2] = 0;
01984 pal.palette[i][3] = 0;
01985 }
01986 p_pal = &pal;
01987 }
01988
01989 bs_write( s, 8, 0x0f );
01990 bs_write( s, 8, DVBSUB_ST_CLUT_DEFINITION );
01991 bs_write( s, 16, 1 );
01992
01993 bs_write( s, 16, p_pal->i_entries * 6 + 2 );
01994 bs_write( s, 8, 1 );
01995 bs_write( s, 4, p_sys->i_clut_ver++ );
01996 bs_write( s, 4, 0 );
01997
01998 for( i = 0; i < p_pal->i_entries; i++ )
01999 {
02000 bs_write( s, 8, i );
02001 bs_write( s, 1, p_pal->i_entries == 4 );
02002 bs_write( s, 1, p_pal->i_entries == 16 );
02003 bs_write( s, 1, p_pal->i_entries == 256 );
02004 bs_write( s, 4, 0 );
02005 bs_write( s, 1, 1 );
02006 bs_write( s, 8, p_pal->palette[i][3] ?
02007 (p_pal->palette[i][0] ? p_pal->palette[i][0] : 16) : 0 );
02008 bs_write( s, 8, p_pal->palette[i][1] );
02009 bs_write( s, 8, p_pal->palette[i][2] );
02010 bs_write( s, 8, 0xff - p_pal->palette[i][3] );
02011 }
02012 }
02013
02014 static void encode_region_composition( encoder_t *p_enc, bs_t *s,
02015 subpicture_t *p_subpic )
02016 {
02017 encoder_sys_t *p_sys = p_enc->p_sys;
02018 subpicture_region_t *p_region;
02019 int i_region;
02020
02021 for( i_region = 0, p_region = p_subpic->p_region; p_region;
02022 p_region = p_region->p_next, i_region++ )
02023 {
02024 int i_entries = 4, i_depth = 0x1, i_bg = 0;
02025 vlc_bool_t b_text =
02026 p_region->fmt.i_chroma == VLC_FOURCC('T','E','X','T');
02027
02028 if( !b_text )
02029 {
02030 video_palette_t *p_pal = p_region->fmt.p_palette;
02031
02032 if( !p_pal )
02033 {
02034 msg_Err( p_enc, "subpicture has no palette - ignoring it" );
02035 break;
02036 }
02037
02038 i_entries = p_pal->i_entries;
02039 i_depth = i_entries == 4 ? 0x1 : i_entries == 16 ? 0x2 : 0x3;
02040
02041 for( i_bg = 0; i_bg < p_pal->i_entries; i_bg++ )
02042 {
02043 if( !p_pal->palette[i_bg][3] ) break;
02044 }
02045 }
02046
02047 bs_write( s, 8, 0x0f );
02048 bs_write( s, 8, DVBSUB_ST_REGION_COMPOSITION );
02049 bs_write( s, 16, 1 );
02050
02051 bs_write( s, 16, 10 + 6 + (b_text ? 2 : 0) );
02052 bs_write( s, 8, i_region );
02053 bs_write( s, 4, p_sys->i_region_ver++ );
02054
02055
02056 bs_write( s, 1, i_bg < i_entries );
02057 bs_write( s, 3, 0 );
02058 bs_write( s, 16, p_sys->p_regions[i_region].i_width );
02059 bs_write( s, 16, p_sys->p_regions[i_region].i_height );
02060 bs_write( s, 3, i_depth );
02061 bs_write( s, 3, i_depth );
02062 bs_write( s, 2, 0 );
02063 bs_write( s, 8, 1 );
02064 bs_write( s, 8, i_bg );
02065 bs_write( s, 4, i_bg );
02066 bs_write( s, 2, i_bg );
02067 bs_write( s, 2, 0 );
02068
02069
02070 bs_write( s, 16, i_region );
02071 bs_write( s, 2, b_text ? DVBSUB_OT_BASIC_CHAR:DVBSUB_OT_BASIC_BITMAP );
02072 bs_write( s, 2, 0 );
02073 bs_write( s, 12, 0 );
02074 bs_write( s, 4, 0 );
02075 bs_write( s, 12, 0 );
02076
02077 if( b_text )
02078 {
02079 bs_write( s, 8, 1 );
02080 bs_write( s, 8, 0 );
02081 }
02082 }
02083 }
02084
02085 static void encode_pixel_data( encoder_t *p_enc, bs_t *s,
02086 subpicture_region_t *p_region,
02087 vlc_bool_t b_top );
02088
02089 static void encode_object( encoder_t *p_enc, bs_t *s, subpicture_t *p_subpic )
02090 {
02091 encoder_sys_t *p_sys = p_enc->p_sys;
02092 subpicture_region_t *p_region;
02093 int i_region;
02094
02095 int i_length_pos, i_update_pos, i_pixel_data_pos;
02096
02097 for( i_region = 0, p_region = p_subpic->p_region; p_region;
02098 p_region = p_region->p_next, i_region++ )
02099 {
02100 bs_write( s, 8, 0x0f );
02101 bs_write( s, 8, DVBSUB_ST_OBJECT_DATA );
02102 bs_write( s, 16, 1 );
02103
02104 i_length_pos = bs_pos( s );
02105 bs_write( s, 16, 0 );
02106 bs_write( s, 16, i_region );
02107 bs_write( s, 4, p_sys->i_region_ver++ );
02108
02109
02110 switch( p_region->fmt.i_chroma )
02111 {
02112 case VLC_FOURCC( 'Y','U','V','P' ):
02113 bs_write( s, 2, 0 );
02114 break;
02115 case VLC_FOURCC( 'T','E','X','T' ):
02116 bs_write( s, 2, 1 );
02117 break;
02118 default:
02119 msg_Err( p_enc, "FOURCC %d not supported by encoder.", p_region->fmt.i_chroma );
02120 continue;
02121 }
02122
02123 bs_write( s, 1, 0 );
02124 bs_write( s, 1, 0 );
02125
02126 if( p_region->fmt.i_chroma == VLC_FOURCC( 'T','E','X','T' ) )
02127 {
02128 int i_size, i;
02129
02130 if( !p_region->psz_text ) continue;
02131
02132 i_size = __MIN( strlen( p_region->psz_text ), 256 );
02133
02134 bs_write( s, 8, i_size );
02135 for( i = 0; i < i_size; i++ )
02136 {
02137 bs_write( s, 16, p_region->psz_text[i] );
02138 }
02139
02140
02141 SetWBE( &s->p_start[i_length_pos/8],
02142 (bs_pos(s) - i_length_pos)/8 -2 );
02143 continue;
02144 }
02145
02146
02147 i_update_pos = bs_pos( s );
02148 bs_write( s, 16, 0 );
02149 bs_write( s, 16, 0 );
02150
02151
02152 i_pixel_data_pos = bs_pos( s );
02153 encode_pixel_data( p_enc, s, p_region, VLC_TRUE );
02154 i_pixel_data_pos = ( bs_pos( s ) - i_pixel_data_pos ) / 8;
02155 SetWBE( &s->p_start[i_update_pos/8], i_pixel_data_pos );
02156
02157
02158 i_pixel_data_pos = bs_pos( s );
02159 encode_pixel_data( p_enc, s, p_region, VLC_FALSE );
02160 i_pixel_data_pos = ( bs_pos( s ) - i_pixel_data_pos ) / 8;
02161 SetWBE( &s->p_start[i_update_pos/8+2], i_pixel_data_pos );
02162
02163
02164 bs_align_0( s );
02165 if( bs_pos( s ) % 16 ) bs_write( s, 8, 0 );
02166
02167
02168 SetWBE( &s->p_start[i_length_pos/8], (bs_pos(s) - i_length_pos)/8 -2 );
02169 }
02170 }
02171
02172 static void encode_pixel_line_2bp( encoder_t *p_enc, bs_t *s,
02173 subpicture_region_t *p_region,
02174 int i_line );
02175 static void encode_pixel_line_4bp( encoder_t *p_enc, bs_t *s,
02176 subpicture_region_t *p_region,
02177 int i_line );
02178 static void encode_pixel_line_8bp( encoder_t *p_enc, bs_t *s,
02179 subpicture_region_t *p_region,
02180 int i_line );
02181 static void encode_pixel_data( encoder_t *p_enc, bs_t *s,
02182 subpicture_region_t *p_region,
02183 vlc_bool_t b_top )
02184 {
02185 unsigned int i_line;
02186
02187
02188 if( p_region->fmt.i_chroma != VLC_FOURCC('Y','U','V','P') ) return;
02189
02190
02191 for( i_line = !b_top; i_line < p_region->fmt.i_visible_height;
02192 i_line += 2 )
02193 {
02194 switch( p_region->fmt.p_palette->i_entries )
02195 {
02196 case 0:
02197 break;
02198
02199 case 4:
02200 bs_write( s, 8, 0x10 );
02201 encode_pixel_line_2bp( p_enc, s, p_region, i_line );
02202 break;
02203
02204 case 16:
02205 bs_write( s, 8, 0x11 );
02206 encode_pixel_line_4bp( p_enc, s, p_region, i_line );
02207 break;
02208
02209 case 256:
02210 bs_write( s, 8, 0x12 );
02211 encode_pixel_line_8bp( p_enc, s, p_region, i_line );
02212 break;
02213
02214 default:
02215 msg_Err( p_enc, "subpicture palette (%i) not handled",
02216 p_region->fmt.p_palette->i_entries );
02217 break;
02218 }
02219
02220 bs_write( s, 8, 0xf0 );
02221 }
02222 }
02223
02224 static void encode_pixel_line_2bp( encoder_t *p_enc, bs_t *s,
02225 subpicture_region_t *p_region,
02226 int i_line )
02227 {
02228 unsigned int i, i_length = 0;
02229 int i_pitch = p_region->picture.p->i_pitch;
02230 uint8_t *p_data = &p_region->picture.p->p_pixels[ i_pitch * i_line ];
02231 int i_last_pixel = p_data[0];
02232
02233 for( i = 0; i <= p_region->fmt.i_visible_width; i++ )
02234 {
02235 if( i != p_region->fmt.i_visible_width &&
02236 p_data[i] == i_last_pixel && i_length != 284 )
02237 {
02238 i_length++;
02239 continue;
02240 }
02241
02242 if( i_length == 1 || i_length == 11 || i_length == 28 )
02243 {
02244
02245 if( i_last_pixel ) bs_write( s, 2, i_last_pixel );
02246 else
02247 {
02248 bs_write( s, 2, 0 );
02249 bs_write( s, 1, 0 );
02250 bs_write( s, 1, 1 );
02251 }
02252 i_length--;
02253 }
02254
02255 if( i_length == 2 )
02256 {
02257 if( i_last_pixel )
02258 {
02259 bs_write( s, 2, i_last_pixel );
02260 bs_write( s, 2, i_last_pixel );
02261 }
02262 else
02263 {
02264 bs_write( s, 2, 0 );
02265 bs_write( s, 1, 0 );
02266 bs_write( s, 1, 0 );
02267 bs_write( s, 2, 1 );
02268 }
02269 }
02270 else if( i_length > 2 )
02271 {
02272 bs_write( s, 2, 0 );
02273 if( i_length <= 10 )
02274 {
02275 bs_write( s, 1, 1 );
02276 bs_write( s, 3, i_length - 3 );
02277 bs_write( s, 2, i_last_pixel );
02278 }
02279 else
02280 {
02281 bs_write( s, 1, 0 );
02282 bs_write( s, 1, 0 );
02283
02284 if( i_length <= 27 )
02285 {
02286 bs_write( s, 2, 2 );
02287 bs_write( s, 4, i_length - 12 );
02288 bs_write( s, 2, i_last_pixel );
02289 }
02290 else
02291 {
02292 bs_write( s, 2, 3 );
02293 bs_write( s, 8, i_length - 29 );
02294 bs_write( s, 2, i_last_pixel );
02295 }
02296 }
02297 }
02298
02299 if( i == p_region->fmt.i_visible_width ) break;
02300
02301 i_last_pixel = p_data[i];
02302 i_length = 1;
02303 }
02304
02305
02306 bs_write( s, 2, 0 );
02307 bs_write( s, 1, 0 );
02308 bs_write( s, 1, 0 );
02309 bs_write( s, 2, 0 );
02310
02311
02312 bs_align_0( s );
02313 }
02314
02315 static void encode_pixel_line_4bp( encoder_t *p_enc, bs_t *s,
02316 subpicture_region_t *p_region,
02317 int i_line )
02318 {
02319 unsigned int i, i_length = 0;
02320 int i_pitch = p_region->picture.p->i_pitch;
02321 uint8_t *p_data = &p_region->picture.p->p_pixels[ i_pitch * i_line ];
02322 int i_last_pixel = p_data[0];
02323
02324 for( i = 0; i <= p_region->fmt.i_visible_width; i++ )
02325 {
02326 if( i != p_region->fmt.i_visible_width &&
02327 p_data[i] == i_last_pixel && i_length != 280 )
02328 {
02329 i_length++;
02330 continue;
02331 }
02332
02333 if( i_length == 1 || (i_length == 3 && i_last_pixel) || i_length == 8 )
02334 {
02335
02336 if( i_last_pixel ) bs_write( s, 4, i_last_pixel );
02337 else
02338 {
02339 bs_write( s, 4, 0 );
02340 bs_write( s, 1, 1 );
02341 bs_write( s, 1, 1 );
02342 bs_write( s, 2, 0 );
02343 }
02344 i_length--;
02345 }
02346
02347 if( i_length == 2 )
02348 {
02349 if( i_last_pixel )
02350 {
02351 bs_write( s, 4, i_last_pixel );
02352 bs_write( s, 4, i_last_pixel );
02353 }
02354 else
02355 {
02356 bs_write( s, 4, 0 );
02357 bs_write( s, 1, 1 );
02358 bs_write( s, 1, 1 );
02359 bs_write( s, 2, 1 );
02360 }
02361 }
02362 else if( !i_last_pixel && i_length >= 3 && i_length <= 9 )
02363 {
02364 bs_write( s, 4, 0 );
02365 bs_write( s, 1, 0 );
02366 bs_write( s, 3, i_length - 2 );
02367 }
02368 else if( i_length > 2 )
02369 {
02370 bs_write( s, 4, 0 );
02371 bs_write( s, 1, 1 );
02372
02373 if( i_length <= 7 )
02374 {
02375 bs_write( s, 1, 0 );
02376 bs_write( s, 2, i_length - 4 );
02377 bs_write( s, 4, i_last_pixel );
02378 }
02379 else
02380 {
02381 bs_write( s, 1, 1 );
02382
02383 if( i_length <= 24 )
02384 {
02385 bs_write( s, 2, 2 );
02386 bs_write( s, 4, i_length - 9 );
02387 bs_write( s, 4, i_last_pixel );
02388 }
02389 else
02390 {
02391 bs_write( s, 2, 3 );
02392 bs_write( s, 8, i_length - 25 );
02393 bs_write( s, 4, i_last_pixel );
02394 }
02395 }
02396 }
02397
02398 if( i == p_region->fmt.i_visible_width ) break;
02399
02400 i_last_pixel = p_data[i];
02401 i_length = 1;
02402 }
02403
02404
02405 bs_write( s, 8, 0 );
02406
02407
02408 bs_align_0( s );
02409 }
02410
02411 static void encode_pixel_line_8bp( encoder_t *p_enc, bs_t *s,
02412 subpicture_region_t *p_region,
02413 int i_line )
02414 {
02415 unsigned int i, i_length = 0;
02416 int i_pitch = p_region->picture.p->i_pitch;
02417 uint8_t *p_data = &p_region->picture.p->p_pixels[ i_pitch * i_line ];
02418 int i_last_pixel = p_data[0];
02419
02420 for( i = 0; i <= p_region->fmt.i_visible_width; i++ )
02421 {
02422 if( i != p_region->fmt.i_visible_width &&
02423 p_data[i] == i_last_pixel && i_length != 127 )
02424 {
02425 i_length++;
02426 continue;
02427 }
02428
02429 if( i_length == 1 && i_last_pixel )
02430 {
02431
02432 bs_write( s, 8, i_last_pixel );
02433 }
02434 else if( i_length == 2 && i_last_pixel )
02435 {
02436
02437 bs_write( s, 8, i_last_pixel );
02438 bs_write( s, 8, i_last_pixel );
02439 }
02440 else if( i_length <= 127 )
02441 {
02442 bs_write( s, 8, 0 );
02443
02444 if( !i_last_pixel )
02445 {
02446 bs_write( s, 1, 0 );
02447 bs_write( s, 7, i_length );
02448 }
02449 else
02450 {
02451 bs_write( s, 1, 1 );
02452 bs_write( s, 7, i_length );
02453 bs_write( s, 8, i_last_pixel );
02454 }
02455 }
02456
02457 if( i == p_region->fmt.i_visible_width ) break;
02458
02459 i_last_pixel = p_data[i];
02460 i_length = 1;
02461 }
02462
02463
02464 bs_write( s, 8, 0 );
02465 bs_write( s, 8, 0 );
02466
02467
02468 bs_align_0( s );
02469 }