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 #include <vlc/vlc.h>
00031 #include <vlc/decoder.h>
00032
00033 #include "vlc_bits.h"
00034
00035
00036
00037
00038 static int DecoderOpen ( vlc_object_t * );
00039 static int PacketizerOpen( vlc_object_t * );
00040 static void DecoderClose ( vlc_object_t * );
00041
00042 #define DEBUG_TEXT \
00043 "If nonzero, this gives additional debug information." \
00044
00045 #define DEBUG_LONGTEXT \
00046 "This integer when viewed in binary is a debugging mask\n" \
00047 "calls 1\n" \
00048 "packet assembly info 2\n"
00049
00050 vlc_module_begin();
00051 set_description( _("Philips OGT (SVCD subtitle) decoder") );
00052 set_shortname( N_("SVCD subtitles"));
00053 set_category( CAT_INPUT );
00054 set_subcategory( SUBCAT_INPUT_SCODEC );
00055 set_capability( "decoder", 50 );
00056 set_callbacks( DecoderOpen, DecoderClose );
00057
00058 add_integer ( MODULE_STRING "-debug", 0, NULL,
00059 DEBUG_TEXT, DEBUG_LONGTEXT, VLC_TRUE );
00060
00061 add_submodule();
00062 set_description( _("Philips OGT (SVCD subtitle) packetizer") );
00063 set_capability( "packetizer", 50 );
00064 set_callbacks( PacketizerOpen, DecoderClose );
00065 vlc_module_end();
00066
00067
00068
00069
00070 static subpicture_t *Decode( decoder_t *, block_t ** );
00071 static block_t *Packetize ( decoder_t *, block_t ** );
00072 static block_t *Reassemble ( decoder_t *, block_t * );
00073 static void ParseHeader( decoder_t *, block_t * );
00074 static subpicture_t *DecodePacket( decoder_t *, block_t * );
00075 static void SVCDSubRenderImage( decoder_t *, block_t *, subpicture_region_t * );
00076
00077 #define DECODE_DBG_CALL 1
00078 #define DECODE_DBG_PACKET 2
00079
00080 #define GETINT16(p) ( (p[0] << 8) + p[1] ) ; p +=2;
00081
00082 #define GETINT32(p) ( (p[0] << 24) + (p[1] << 16) + \
00083 (p[2] << 8) + (p[3]) ) ; p += 4;
00084
00085 typedef enum {
00086 SUBTITLE_BLOCK_EMPTY = 0,
00087 SUBTITLE_BLOCK_PARTIAL = 1,
00088 SUBTITLE_BLOCK_COMPLETE = 2
00089 } packet_state_t;
00090
00091 #ifndef DECODE_DEBUG
00092 #define DECODE_DEBUG 1
00093 #endif
00094 #if DECODE_DEBUG
00095 #define dbg_print(mask, s, args...) \
00096 if (p_sys && p_sys->i_debug & mask) \
00097 msg_Dbg(p_dec, "%s: "s, __func__ , ##args)
00098 #else
00099 #define dbg_print(mask, s, args...)
00100 #endif
00101
00102 struct decoder_sys_t
00103 {
00104 int i_debug;
00105
00106 packet_state_t i_state;
00107
00108 block_t *p_spu;
00109
00110 uint16_t i_image;
00111 uint8_t i_packet;
00112
00113 int i_spu_size;
00114
00115
00116 uint16_t i_image_offset;
00117
00118 int i_image_length;
00119 int second_field_offset;
00120 int metadata_offset;
00121 int metadata_length;
00122
00123 mtime_t i_duration;
00124
00125
00126 uint16_t i_x_start, i_y_start;
00127
00128 uint16_t i_width, i_height;
00129
00130 uint8_t p_palette[4][4];
00131 };
00132
00133
00134
00135
00136 static int DecoderOpen( vlc_object_t *p_this )
00137 {
00138 decoder_t *p_dec = (decoder_t*)p_this;
00139 decoder_sys_t *p_sys;
00140
00141 if( p_dec->fmt_in.i_codec != VLC_FOURCC( 'o','g','t',' ' ) )
00142 {
00143 return VLC_EGENERIC;
00144 }
00145
00146 p_dec->p_sys = p_sys = calloc( 1, sizeof( decoder_sys_t ) );
00147 p_sys->i_debug = config_GetInt( p_this, MODULE_STRING "-debug" );
00148
00149 p_sys->i_image = -1;
00150
00151 p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
00152 p_sys->p_spu = NULL;
00153
00154 es_format_Init( &p_dec->fmt_out, SPU_ES, VLC_FOURCC( 'o','g','t',' ' ) );
00155
00156 p_dec->pf_decode_sub = Decode;
00157 p_dec->pf_packetize = Packetize;
00158
00159 dbg_print( (DECODE_DBG_CALL) , "");
00160 return VLC_SUCCESS;
00161 }
00162
00163
00164
00165
00166 static int PacketizerOpen( vlc_object_t *p_this )
00167 {
00168 if( DecoderOpen( p_this ) != VLC_SUCCESS ) return VLC_EGENERIC;
00169
00170 return VLC_SUCCESS;
00171 }
00172
00173
00174
00175
00176 void DecoderClose( vlc_object_t *p_this )
00177 {
00178 decoder_t *p_dec = (decoder_t*)p_this;
00179 decoder_sys_t *p_sys = p_dec->p_sys;
00180
00181 if( p_sys->p_spu ) block_ChainRelease( p_sys->p_spu );
00182 free( p_sys );
00183 }
00184
00185
00186
00187
00188 static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
00189 {
00190 block_t *p_block, *p_spu;
00191 decoder_sys_t *p_sys = p_dec->p_sys;
00192
00193 dbg_print( (DECODE_DBG_CALL) , "");
00194
00195 if( pp_block == NULL || *pp_block == NULL ) return NULL;
00196
00197 p_block = *pp_block;
00198 *pp_block = NULL;
00199
00200 if( !(p_spu = Reassemble( p_dec, p_block )) ) return NULL;
00201
00202
00203 return DecodePacket( p_dec, p_spu );
00204 }
00205
00206
00207
00208
00209 static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
00210 {
00211 block_t *p_block, *p_spu;
00212
00213 if( pp_block == NULL || *pp_block == NULL ) return NULL;
00214
00215 p_block = *pp_block;
00216 *pp_block = NULL;
00217
00218 if( !(p_spu = Reassemble( p_dec, p_block )) ) return NULL;
00219
00220 p_spu->i_dts = p_spu->i_pts;
00221 p_spu->i_length = 0;
00222
00223 return p_spu;
00224 }
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 #define SPU_HEADER_LEN 5
00250
00251 static block_t *Reassemble( decoder_t *p_dec, block_t *p_block )
00252 {
00253 decoder_sys_t *p_sys = p_dec->p_sys;
00254 uint8_t *p_buffer;
00255 uint16_t i_expected_image;
00256 uint8_t i_packet, i_expected_packet;
00257
00258 if( p_block->i_buffer < SPU_HEADER_LEN )
00259 {
00260 msg_Dbg( p_dec, "invalid packet header (size %d < %d)" ,
00261 p_block->i_buffer, SPU_HEADER_LEN );
00262 block_Release( p_block );
00263 return NULL;
00264 }
00265
00266 p_buffer = p_block->p_buffer;
00267
00268
00269 {
00270 vlc_object_t * p_input;
00271 vlc_value_t val;
00272
00273 p_input = vlc_object_find( p_dec, VLC_OBJECT_INPUT, FIND_PARENT );
00274
00275 if( !p_input ) return NULL;
00276
00277 if( var_Get( p_input, "sub-track", &val ) )
00278 {
00279 vlc_object_release( p_input );
00280 return NULL;
00281 }
00282
00283 vlc_object_release( p_input );
00284 dbg_print( (DECODE_DBG_PACKET),
00285 "val.i_int %x p_buffer[i] %x", val.i_int, p_buffer[1]);
00286
00287
00288
00289 if( val.i_int == -1 || (val.i_int & 0x03) != p_buffer[1] )
00290 {
00291 dbg_print( DECODE_DBG_PACKET, "subtitle not for us.\n");
00292 return NULL;
00293 }
00294 }
00295
00296 if( p_sys->i_state == SUBTITLE_BLOCK_EMPTY )
00297 {
00298 i_expected_image = p_sys->i_image + 1;
00299 i_expected_packet = 0;
00300 }
00301 else
00302 {
00303 i_expected_image = p_sys->i_image;
00304 i_expected_packet = p_sys->i_packet + 1;
00305 }
00306
00307 p_buffer += 2;
00308
00309 if( *p_buffer & 0x80 )
00310 {
00311 p_sys->i_state = SUBTITLE_BLOCK_COMPLETE;
00312 i_packet = *p_buffer++ & 0x7F;
00313 }
00314 else
00315 {
00316 p_sys->i_state = SUBTITLE_BLOCK_PARTIAL;
00317 i_packet = *p_buffer++;
00318 }
00319
00320 p_sys->i_image = GETINT16(p_buffer);
00321
00322 if( p_sys->i_image != i_expected_image )
00323 {
00324 msg_Warn( p_dec, "expected subtitle image %u but found %u",
00325 i_expected_image, p_sys->i_image );
00326 }
00327
00328 if( i_packet != i_expected_packet )
00329 {
00330 msg_Warn( p_dec, "expected subtitle image packet %u but found %u",
00331 i_expected_packet, i_packet );
00332 }
00333
00334 p_block->p_buffer += SPU_HEADER_LEN;
00335 p_block->i_buffer -= SPU_HEADER_LEN;
00336
00337 p_sys->i_packet = i_packet;
00338
00339 if( !p_sys->i_packet ) ParseHeader( p_dec, p_block );
00340
00341 block_ChainAppend( &p_sys->p_spu, p_block );
00342
00343 if( p_sys->i_state == SUBTITLE_BLOCK_COMPLETE )
00344 {
00345 block_t *p_spu = block_ChainGather( p_sys->p_spu );
00346
00347 if( p_spu->i_buffer != p_sys->i_spu_size )
00348 {
00349 msg_Warn( p_dec, "subtitle packets size=%d should be %d",
00350 p_spu->i_buffer, p_sys->i_spu_size );
00351 }
00352
00353 dbg_print( (DECODE_DBG_PACKET),
00354 "subtitle packet complete, size=%d", p_spu->i_buffer );
00355
00356 p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
00357 p_sys->p_spu = 0;
00358 return p_spu;
00359 }
00360
00361 return NULL;
00362 }
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 static void ParseHeader( decoder_t *p_dec, block_t *p_block )
00395 {
00396 decoder_sys_t *p_sys = p_dec->p_sys;
00397 uint8_t *p = p_block->p_buffer;
00398 uint8_t i_options, i_options2, i_cmd, i_cmd_arg;
00399 int i;
00400
00401 p_sys->i_spu_size = GETINT16(p);
00402 i_options = *p++;
00403 i_options2 = *p++;
00404
00405 if( i_options & 0x08 ) { p_sys->i_duration = GETINT32(p); }
00406 else p_sys->i_duration = 0;
00407 p_sys->i_duration *= 100 / 9;
00408
00409 p_sys->i_x_start = GETINT16(p);
00410 p_sys->i_y_start = GETINT16(p);
00411 p_sys->i_width = GETINT16(p);
00412 p_sys->i_height = GETINT16(p);
00413
00414 for( i = 0; i < 4; i++ )
00415 {
00416 p_sys->p_palette[i][0] = *p++;
00417 p_sys->p_palette[i][2] = *p++;
00418 p_sys->p_palette[i][1] = *p++;
00419 p_sys->p_palette[i][3] = *p++;
00420 }
00421
00422 i_cmd = *p++;
00423
00424 if( i_cmd ) {i_cmd_arg = GETINT32(p);}
00425
00426
00427
00428 p_sys->second_field_offset = GETINT16(p);
00429 p_sys->i_image_offset = p - p_block->p_buffer;
00430 p_sys->i_image_length = p_sys->i_spu_size - p_sys->i_image_offset;
00431 p_sys->metadata_length = p_sys->i_image_offset;
00432
00433 if (p_sys && p_sys->i_debug & DECODE_DBG_PACKET)
00434 {
00435 msg_Dbg( p_dec, "x-start: %d, y-start: %d, width: %d, height %d, "
00436 "spu size: %d, duration: %lu (d:%d p:%d)",
00437 p_sys->i_x_start, p_sys->i_y_start,
00438 p_sys->i_width, p_sys->i_height,
00439 p_sys->i_spu_size, (long unsigned int) p_sys->i_duration,
00440 p_sys->i_image_length, p_sys->i_image_offset);
00441
00442 for( i = 0; i < 4; i++ )
00443 {
00444 msg_Dbg( p_dec, "palette[%d]= T: %2x, Y: %2x, u: %2x, v: %2x", i,
00445 p_sys->p_palette[i][3], p_sys->p_palette[i][0],
00446 p_sys->p_palette[i][1], p_sys->p_palette[i][2] );
00447 }
00448 }
00449 }
00450
00451
00452
00453
00454
00455
00456
00457 static subpicture_t *DecodePacket( decoder_t *p_dec, block_t *p_data )
00458 {
00459 decoder_sys_t *p_sys = p_dec->p_sys;
00460 subpicture_t *p_spu;
00461 subpicture_region_t *p_region;
00462 video_format_t fmt;
00463 int i;
00464
00465
00466 p_spu = p_dec->pf_spu_buffer_new( p_dec );
00467 if( !p_spu ) return NULL;
00468
00469 p_spu->i_x = p_sys->i_x_start;
00470 p_spu->i_y = p_sys->i_y_start;
00471 p_spu->i_start = p_data->i_pts;
00472 p_spu->i_stop = p_data->i_pts + p_sys->i_duration;
00473 p_spu->b_ephemer = VLC_TRUE;
00474
00475
00476 memset( &fmt, 0, sizeof(video_format_t) );
00477 fmt.i_chroma = VLC_FOURCC('Y','U','V','P');
00478
00487 fmt.i_aspect = VOUT_ASPECT_FACTOR;
00488
00489 fmt.i_width = fmt.i_visible_width = p_sys->i_width;
00490 fmt.i_height = fmt.i_visible_height = p_sys->i_height;
00491 fmt.i_x_offset = fmt.i_y_offset = 0;
00492 p_region = p_spu->pf_create_region( VLC_OBJECT(p_dec), &fmt );
00493 if( !p_region )
00494 {
00495 msg_Err( p_dec, "cannot allocate SVCD subtitle region" );
00496
00497 }
00498
00499 p_region->fmt.i_aspect = VOUT_ASPECT_FACTOR;
00500
00501 p_spu->p_region = p_region;
00502 p_region->i_x = p_region->i_y = 0;
00503
00504
00505 fmt.p_palette->i_entries = 4;
00506 for( i = 0; i < fmt.p_palette->i_entries; i++ )
00507 {
00508 fmt.p_palette->palette[i][0] = p_sys->p_palette[i][0];
00509 fmt.p_palette->palette[i][1] = p_sys->p_palette[i][1];
00510 fmt.p_palette->palette[i][2] = p_sys->p_palette[i][2];
00511 fmt.p_palette->palette[i][3] = p_sys->p_palette[i][3];
00512 }
00513
00514 SVCDSubRenderImage( p_dec, p_data, p_region );
00515
00516 return p_spu;
00517 }
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537 static void SVCDSubRenderImage( decoder_t *p_dec, block_t *p_data,
00538 subpicture_region_t *p_region )
00539 {
00540 decoder_sys_t *p_sys = p_dec->p_sys;
00541 uint8_t *p_dest = p_region->picture.Y_PIXELS;
00542 int i_field;
00543 int i_row, i_column;
00544 uint8_t i_color, i_count;
00545 bs_t bs;
00546
00547 bs_init( &bs, p_data->p_buffer + p_sys->i_image_offset,
00548 p_data->i_buffer - p_sys->i_image_offset );
00549
00550 for( i_field = 0; i_field < 2; i_field++ )
00551 {
00552 for( i_row = i_field; i_row < p_sys->i_height; i_row += 2 )
00553 {
00554 for( i_column = 0; i_column < p_sys->i_width; i_column++ )
00555 {
00556 i_color = bs_read( &bs, 2 );
00557 if( i_color == 0 && (i_count = bs_read( &bs, 2 )) )
00558 {
00559 i_count = __MIN( i_count, p_sys->i_width - i_column );
00560 memset( &p_dest[i_row * p_region->picture.Y_PITCH +
00561 i_column], 0, i_count + 1 );
00562 i_column += i_count;
00563 continue;
00564 }
00565
00566 p_dest[i_row * p_region->picture.Y_PITCH + i_column] = i_color;
00567 }
00568
00569 bs_align( &bs );
00570 }
00571
00572
00573 bs_init( &bs, p_data->p_buffer + p_sys->i_image_offset +
00574 p_sys->second_field_offset,
00575 p_data->i_buffer - p_sys->i_image_offset -
00576 p_sys->second_field_offset );
00577 }
00578 }