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/vout.h>
00032 #include <vlc/decoder.h>
00033
00034 #include "vlc_bits.h"
00035
00036 #define DEBUG_CVDSUB 1
00037
00038
00039
00040
00041 static int DecoderOpen ( vlc_object_t * );
00042 static int PacketizerOpen( vlc_object_t * );
00043 static void DecoderClose ( vlc_object_t * );
00044
00045 vlc_module_begin();
00046 set_description( _("CVD subtitle decoder") );
00047 set_capability( "decoder", 50 );
00048 set_callbacks( DecoderOpen, DecoderClose );
00049
00050 add_submodule();
00051 set_description( _("Chaoji VCD subtitle packetizer") );
00052 set_capability( "packetizer", 50 );
00053 set_callbacks( PacketizerOpen, DecoderClose );
00054 vlc_module_end();
00055
00056
00057
00058
00059 static subpicture_t *Decode( decoder_t *, block_t ** );
00060 static block_t *Packetize ( decoder_t *, block_t ** );
00061 static block_t *Reassemble ( decoder_t *, block_t * );
00062 static void ParseMetaInfo ( decoder_t *, block_t * );
00063 static void ParseHeader ( decoder_t *, block_t * );
00064 static subpicture_t *DecodePacket( decoder_t *, block_t * );
00065 static void RenderImage( decoder_t *, block_t *, subpicture_region_t * );
00066
00067 #define SUBTITLE_BLOCK_EMPTY 0
00068 #define SUBTITLE_BLOCK_PARTIAL 1
00069 #define SUBTITLE_BLOCK_COMPLETE 2
00070
00071 struct decoder_sys_t
00072 {
00073 int b_packetizer;
00074
00075 int i_state;
00076
00077 block_t *p_spu;
00078
00079 int i_spu_size;
00080
00081
00082 uint16_t i_image_offset;
00083
00084 int i_image_length;
00085 int first_field_offset;
00086 int second_field_offset;
00087 int metadata_offset;
00088 int metadata_length;
00089
00090 mtime_t i_duration;
00091
00092
00093 uint16_t i_x_start, i_y_start;
00094
00095 uint16_t i_width, i_height;
00096
00097 uint8_t p_palette[4][4];
00098 uint8_t p_palette_highlight[4][4];
00099 };
00100
00101
00102
00103
00104 static int DecoderOpen( vlc_object_t *p_this )
00105 {
00106 decoder_t *p_dec = (decoder_t*)p_this;
00107 decoder_sys_t *p_sys;
00108
00109 if( p_dec->fmt_in.i_codec != VLC_FOURCC( 'c','v','d',' ' ) )
00110 {
00111 return VLC_EGENERIC;
00112 }
00113
00114 p_dec->p_sys = p_sys = malloc( sizeof( decoder_sys_t ) );
00115
00116 p_sys->b_packetizer = VLC_FALSE;
00117
00118 p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
00119 p_sys->p_spu = NULL;
00120
00121 es_format_Init( &p_dec->fmt_out, SPU_ES, VLC_FOURCC( 'c','v','d',' ' ) );
00122
00123 p_dec->pf_decode_sub = Decode;
00124 p_dec->pf_packetize = Packetize;
00125
00126 return VLC_SUCCESS;
00127 }
00128
00129
00130
00131
00132 static int PacketizerOpen( vlc_object_t *p_this )
00133 {
00134 decoder_t *p_dec = (decoder_t*)p_this;
00135
00136 if( DecoderOpen( p_this ) != VLC_SUCCESS ) return VLC_EGENERIC;
00137
00138 p_dec->p_sys->b_packetizer = VLC_TRUE;
00139
00140 return VLC_SUCCESS;
00141 }
00142
00143
00144
00145
00146 void DecoderClose( vlc_object_t *p_this )
00147 {
00148 decoder_t *p_dec = (decoder_t*)p_this;
00149 decoder_sys_t *p_sys = p_dec->p_sys;
00150
00151 if( p_sys->p_spu ) block_ChainRelease( p_sys->p_spu );
00152 free( p_sys );
00153 }
00154
00155
00156
00157
00158 static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
00159 {
00160 block_t *p_block, *p_spu;
00161
00162 if( pp_block == NULL || *pp_block == NULL ) return NULL;
00163
00164 p_block = *pp_block;
00165 *pp_block = NULL;
00166
00167 if( !(p_spu = Reassemble( p_dec, p_block )) ) return NULL;
00168
00169
00170 return DecodePacket( p_dec, p_spu );
00171 }
00172
00173
00174
00175
00176 static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
00177 {
00178 block_t *p_block, *p_spu;
00179
00180 if( pp_block == NULL || *pp_block == NULL ) return NULL;
00181
00182 p_block = *pp_block;
00183 *pp_block = NULL;
00184
00185 if( !(p_spu = Reassemble( p_dec, p_block )) ) return NULL;
00186
00187 p_spu->i_dts = p_spu->i_pts;
00188 p_spu->i_length = 0;
00189
00190 return p_spu;
00191 }
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207 #define SPU_HEADER_LEN 1
00208
00209 static block_t *Reassemble( decoder_t *p_dec, block_t *p_block )
00210 {
00211 decoder_sys_t *p_sys = p_dec->p_sys;
00212 uint8_t *p_buffer;
00213
00214 if( p_block->i_buffer < SPU_HEADER_LEN )
00215 {
00216 msg_Dbg( p_dec, "invalid packet header (size %d < %d)" ,
00217 p_block->i_buffer, SPU_HEADER_LEN );
00218 block_Release( p_block );
00219 return NULL;
00220 }
00221
00222 p_buffer = p_block->p_buffer;
00223
00224
00225
00226
00227
00228 if( p_sys->i_state == SUBTITLE_BLOCK_EMPTY && p_block->i_pts == 0 )
00229 {
00230 msg_Warn( p_dec, "first packet expected but no PTS present");
00231 return NULL;
00232 }
00233
00234 p_block->p_buffer += SPU_HEADER_LEN;
00235 p_block->i_buffer -= SPU_HEADER_LEN;
00236
00237
00238 if( p_sys->i_state == SUBTITLE_BLOCK_EMPTY ) ParseHeader( p_dec, p_block );
00239
00240 block_ChainAppend( &p_sys->p_spu, p_block );
00241 p_sys->p_spu = block_ChainGather( p_sys->p_spu );
00242
00243 if( p_sys->p_spu->i_buffer >= p_sys->i_spu_size )
00244 {
00245 block_t *p_spu = p_sys->p_spu;
00246
00247 if( p_spu->i_buffer != p_sys->i_spu_size )
00248 {
00249 msg_Warn( p_dec, "SPU packets size=%d should be %d",
00250 p_spu->i_buffer, p_sys->i_spu_size );
00251 }
00252
00253 msg_Dbg( p_dec, "subtitle packet complete, size=%d", p_spu->i_buffer);
00254
00255 ParseMetaInfo( p_dec, p_spu );
00256
00257 p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
00258 p_sys->p_spu = 0;
00259 return p_spu;
00260 }
00261 else
00262 {
00263
00264 p_sys->i_state = SUBTITLE_BLOCK_PARTIAL;
00265 }
00266
00267 return NULL;
00268 }
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296 static void ParseHeader( decoder_t *p_dec, block_t *p_block )
00297 {
00298 decoder_sys_t *p_sys = p_dec->p_sys;
00299 uint8_t *p = p_block->p_buffer;
00300
00301 p_sys->i_spu_size = (p[0] << 8) + p[1] + 4; p += 2;
00302
00303
00304 p_sys->metadata_offset = (p[0] << 8) + p[1]; p +=2;
00305 p_sys->metadata_length = p_sys->i_spu_size - p_sys->metadata_offset;
00306
00307 p_sys->i_image_offset = 4;
00308 p_sys->i_image_length = p_sys->metadata_offset - p_sys->i_image_offset;
00309
00310 #ifdef DEBUG_CVDSUB
00311 msg_Dbg( p_dec, "total size: %d image size: %d",
00312 p_sys->i_spu_size, p_sys->i_image_length );
00313 #endif
00314
00315 }
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326 #define ExtractXY(x, y) x = ((p[1]&0x0f)<<6) + (p[2]>>2); \
00327 y = ((p[2]&0x03)<<8) + p[3];
00328
00329 static void ParseMetaInfo( decoder_t *p_dec, block_t *p_spu )
00330 {
00331
00332
00333 decoder_sys_t *p_sys = p_dec->p_sys;
00334 uint8_t *p = p_spu->p_buffer + p_sys->metadata_offset;
00335 uint8_t *p_end = p + p_sys->metadata_length;
00336
00337 for( ; p < p_end; p += 4 )
00338 {
00339 switch( p[0] )
00340 {
00341 case 0x04:
00342 p_sys->i_duration = (p[1]<<16) + (p[2]<<8) + p[3];
00343
00344 #ifdef DEBUG_CVDSUB
00345 msg_Dbg( p_dec, "subtitle display duration %lu secs",
00346 (long unsigned int)(p_sys->i_duration / 90000) );
00347 #endif
00348 p_sys->i_duration *= 100 / 9;
00349 break;
00350
00351 case 0x0c:
00352 #ifdef DEBUG_CVDSUB
00353 msg_Dbg( p_dec, "subtitle command unknown 0x%0x 0x%0x 0x%0x 0x%0x",
00354 (int)p[0], (int)p[1], (int)p[2], (int)p[3] );
00355 #endif
00356 break;
00357
00358 case 0x17:
00359 ExtractXY(p_sys->i_x_start, p_sys->i_y_start);
00360
00361 #ifdef DEBUG_CVDSUB
00362 msg_Dbg( p_dec, "start position (%d,%d)",
00363 p_sys->i_x_start, p_sys->i_y_start );
00364 #endif
00365 break;
00366
00367 case 0x1f:
00368 {
00369 int lastx;
00370 int lasty;
00371 ExtractXY(lastx, lasty);
00372 p_sys->i_width = lastx - p_sys->i_x_start + 1;
00373 p_sys->i_height = lasty - p_sys->i_y_start + 1;
00374
00375 #ifdef DEBUG_CVDSUB
00376 msg_Dbg( p_dec, "end position (%d,%d), w x h: %dx%d",
00377 lastx, lasty, p_sys->i_width, p_sys->i_height );
00378 #endif
00379 break;
00380 }
00381
00382 case 0x24:
00383 case 0x25:
00384 case 0x26:
00385 case 0x27:
00386 {
00387 uint8_t v = p[0] - 0x24;
00388
00389 #ifdef DEBUG_CVDSUB
00390
00391 msg_Dbg( p_dec, "primary palette %d (y,u,v): (0x%0x,0x%0x,0x%0x)",
00392 (int)v, (int)p[1], (int)p[2], (int)p[3] );
00393 #endif
00394
00395 p_sys->p_palette[v][0] = p[1];
00396 p_sys->p_palette[v][1] = p[3];
00397 p_sys->p_palette[v][2] = p[2];
00398 break;
00399 }
00400
00401 case 0x2c:
00402 case 0x2d:
00403 case 0x2e:
00404 case 0x2f:
00405 {
00406 uint8_t v = p[0] - 0x2c;
00407
00408 #ifdef DEBUG_CVDSUB
00409 msg_Dbg( p_dec,"highlight palette %d (y,u,v): (0x%0x,0x%0x,0x%0x)",
00410 (int)v, (int)p[1], (int)p[2], (int)p[3] );
00411 #endif
00412
00413
00414 p_sys->p_palette_highlight[v][0] = p[1];
00415 p_sys->p_palette_highlight[v][1] = p[3];
00416 p_sys->p_palette_highlight[v][2] = p[2];
00417 break;
00418 }
00419
00420 case 0x37:
00421
00422 p_sys->p_palette[0][3] = (p[3] & 0x0f) << 4;
00423 p_sys->p_palette[1][3] = (p[3] >> 4) << 4;
00424 p_sys->p_palette[2][3] = (p[2] & 0x0f) << 4;
00425 p_sys->p_palette[3][3] = (p[2] >> 4) << 4;
00426
00427 #ifdef DEBUG_CVDSUB
00428 msg_Dbg( p_dec, "transparency for primary palette 0..3: "
00429 "0x%0x 0x%0x 0x%0x 0x%0x",
00430 (int)p_sys->p_palette[0][3], (int)p_sys->p_palette[1][3],
00431 (int)p_sys->p_palette[2][3], (int)p_sys->p_palette[3][3]);
00432 #endif
00433 break;
00434
00435 case 0x3f:
00436
00437 p_sys->p_palette_highlight[0][3] = (p[2] & 0x0f) << 4;
00438 p_sys->p_palette_highlight[1][3] = (p[2] >> 4) << 4;
00439 p_sys->p_palette_highlight[2][3] = (p[1] & 0x0f) << 4;
00440 p_sys->p_palette_highlight[3][3] = (p[1] >> 4) << 4;
00441
00442 #ifdef DEBUG_CVDSUB
00443 msg_Dbg( p_dec, "transparency for highlight palette 0..3: "
00444 "0x%0x 0x%0x 0x%0x 0x%0x",
00445 (int)p_sys->p_palette_highlight[0][3],
00446 (int)p_sys->p_palette_highlight[1][3],
00447 (int)p_sys->p_palette_highlight[2][3],
00448 (int)p_sys->p_palette_highlight[3][3] );
00449 #endif
00450 break;
00451
00452 case 0x47:
00453
00454
00455 p_sys->first_field_offset =
00456 (p[2] << 8) + p[3] - p_sys->i_image_offset;
00457 #ifdef DEBUG_CVDSUB
00458 msg_Dbg( p_dec, "1st_field_offset %d", p_sys->first_field_offset );
00459 #endif
00460 break;
00461
00462 case 0x4f:
00463
00464
00465 p_sys->second_field_offset =
00466 (p[2] << 8) + p[3] - p_sys->i_image_offset;
00467 #ifdef DEBUG_CVDSUB
00468 msg_Dbg( p_dec, "2nd_field_offset %d", p_sys->second_field_offset);
00469 #endif
00470 break;
00471
00472 default:
00473 #ifdef DEBUG_CVDSUB
00474 msg_Warn( p_dec, "unknown sequence in control header "
00475 "0x%0x 0x%0x 0x%0x 0x%0x", p[0], p[1], p[2], p[3]);
00476 #endif
00477 }
00478 }
00479 }
00480
00481
00482
00483
00484
00485
00486
00487 static subpicture_t *DecodePacket( decoder_t *p_dec, block_t *p_data )
00488 {
00489 decoder_sys_t *p_sys = p_dec->p_sys;
00490 subpicture_t *p_spu;
00491 subpicture_region_t *p_region;
00492 video_format_t fmt;
00493 int i;
00494
00495
00496 p_spu = p_dec->pf_spu_buffer_new( p_dec );
00497 if( !p_spu ) return NULL;
00498
00499 p_spu->i_x = p_sys->i_x_start;
00500 p_spu->i_x = p_spu->i_x * 3 / 4;
00501 p_spu->i_y = p_sys->i_y_start;
00502 p_spu->i_start = p_data->i_pts;
00503 p_spu->i_stop = p_data->i_pts + p_sys->i_duration;
00504 p_spu->b_ephemer = VLC_TRUE;
00505
00506
00507 memset( &fmt, 0, sizeof(video_format_t) );
00508 fmt.i_chroma = VLC_FOURCC('Y','U','V','P');
00509 fmt.i_aspect = VOUT_ASPECT_FACTOR;
00510 fmt.i_width = fmt.i_visible_width = p_sys->i_width;
00511 fmt.i_height = fmt.i_visible_height = p_sys->i_height;
00512 fmt.i_x_offset = fmt.i_y_offset = 0;
00513 p_region = p_spu->pf_create_region( VLC_OBJECT(p_dec), &fmt );
00514 if( !p_region )
00515 {
00516 msg_Err( p_dec, "cannot allocate SPU region" );
00517
00518 }
00519
00520 p_spu->p_region = p_region;
00521 p_region->i_x = p_region->i_y = 0;
00522
00523
00524 fmt.p_palette->i_entries = 4;
00525 for( i = 0; i < fmt.p_palette->i_entries; i++ )
00526 {
00527 fmt.p_palette->palette[i][0] = p_sys->p_palette[i][0];
00528 fmt.p_palette->palette[i][1] = p_sys->p_palette[i][1];
00529 fmt.p_palette->palette[i][2] = p_sys->p_palette[i][2];
00530 fmt.p_palette->palette[i][3] = p_sys->p_palette[i][3];
00531 }
00532
00533 RenderImage( p_dec, p_data, p_region );
00534
00535 return p_spu;
00536 }
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561 static void RenderImage( decoder_t *p_dec, block_t *p_data,
00562 subpicture_region_t *p_region )
00563 {
00564 decoder_sys_t *p_sys = p_dec->p_sys;
00565 uint8_t *p_dest = p_region->picture.Y_PIXELS;
00566 int i_field;
00567 int i_row, i_column;
00568 uint8_t i_color, i_count;
00569 bs_t bs;
00570
00571 bs_init( &bs, p_data->p_buffer + p_sys->i_image_offset,
00572 p_data->i_buffer - p_sys->i_image_offset );
00573
00574 for( i_field = 0; i_field < 2; i_field++ )
00575 {
00576 for( i_row = i_field; i_row < p_sys->i_height; i_row += 2 )
00577 {
00578 for( i_column = 0; i_column < p_sys->i_width; i_column++ )
00579 {
00580 uint8_t i_val = bs_read( &bs, 4 );
00581
00582 if( i_val == 0 )
00583 {
00584
00585 i_color = bs_read( &bs, 4 );
00586
00587 memset( &p_dest[i_row * p_region->picture.Y_PITCH +
00588 i_column], i_color,
00589 p_sys->i_width - i_column );
00590 i_column = p_sys->i_width;
00591 continue;
00592 }
00593 else
00594 {
00595
00596 i_count = (i_val >> 2);
00597 i_color = i_val & 0x3;
00598
00599 i_count = __MIN( i_count, p_sys->i_width - i_column );
00600
00601 memset( &p_dest[i_row * p_region->picture.Y_PITCH +
00602 i_column], i_color, i_count );
00603 i_column += i_count - 1;
00604 continue;
00605 }
00606 }
00607
00608 bs_align( &bs );
00609 }
00610 }
00611 }