1 /* $Id: decsub.c,v 1.12 2005/04/14 17:37:54 titer Exp $
3 This file is part of the HandBrake source code.
4 Homepage: <http://handbrake.fr/>.
5 It may be used under the terms of the GNU General Public License. */
8 * Decoder for DVD bitmap subtitles, also known as "VOB subtitles" within the HandBrake source code.
10 * Input format of the subtitle packets is described here:
11 * http://sam.zoy.org/writings/dvd/subtitles/
13 * An auxiliary input is the color palette lookup table, in 'subtitle->palette'.
14 * The demuxer implementation must fill out this table appropriately.
15 * - In the case of a true DVD input, the palette is read from the IFO file.
16 * - In the case of an MKV file input, the palette is read from the codec private data of the subtitle track.
18 * Output format of this decoder is PICTURESUB, which is:
19 * struct PictureSubPacket {
20 * uint8_t lum[pixelCount]; // Y
21 * uint8_t alpha[pixelCount]; // alpha (max = 16)
22 * uint8_t chromaU[pixelCount]; // Cb
23 * uint8_t chromaV[pixelCount]; // Cr
29 struct hb_work_private_s
54 static hb_buffer_t * Decode( hb_work_object_t * );
56 int decsubInit( hb_work_object_t * w, hb_job_t * job )
58 hb_work_private_t * pv;
60 pv = calloc( 1, sizeof( hb_work_private_t ) );
66 // Warn if the input color palette is empty
71 if (w->subtitle->palette[i])
78 hb_log( "decvobsub: input color palette is empty; not demuxed properly?" );
84 int decsubWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
85 hb_buffer_t ** buf_out )
87 hb_work_private_t * pv = w->private_data;
88 hb_buffer_t * in = *buf_in;
89 int size_sub, size_rle;
93 /* EOF on input stream - send it downstream & say that we're done */
99 pv->stream_id = in->id;
101 size_sub = ( in->data[0] << 8 ) | in->data[1];
102 size_rle = ( in->data[2] << 8 ) | in->data[3];
106 /* We are looking for the start of a new subtitle */
107 if( size_sub && size_rle && size_sub > size_rle &&
108 in->size <= size_sub )
110 /* Looks all right so far */
111 pv->size_sub = size_sub;
112 pv->size_rle = size_rle;
114 pv->buf = hb_buffer_init( 0xFFFF );
115 memcpy( pv->buf->data, in->data, in->size );
116 pv->buf->id = in->id;
117 pv->buf->sequence = in->sequence;
118 pv->size_got = in->size;
124 /* We are waiting for the end of the current subtitle */
125 if( in->size <= pv->size_sub - pv->size_got )
127 memcpy( pv->buf->data + pv->size_got, in->data, in->size );
128 pv->buf->id = in->id;
129 pv->buf->sequence = in->sequence;
130 pv->size_got += in->size;
138 // bad size, must have lost sync
140 if ( pv->buf != NULL )
141 hb_buffer_close( &pv->buf );
149 if( pv->size_sub && pv->size_sub == pv->size_got )
151 pv->buf->size = pv->size_sub;
153 /* We got a complete subtitle, decode it */
154 *buf_out = Decode( w );
156 if( buf_out && *buf_out )
158 (*buf_out)->id = in->id;
159 (*buf_out)->sequence = in->sequence;
162 /* Wait for the next one */
172 void decsubClose( hb_work_object_t * w )
174 hb_work_private_t * pv = w->private_data;
177 hb_buffer_close( &pv->buf );
178 free( w->private_data );
181 hb_work_object_t hb_decvobsub =
191 /***********************************************************************
193 ***********************************************************************
194 * Get the start and end dates (relative to the PTS from the PES
195 * header), the width and height of the subpicture and the colors and
197 **********************************************************************/
198 static void ParseControls( hb_work_object_t * w )
200 hb_work_private_t * pv = w->private_data;
201 hb_job_t * job = pv->job;
202 hb_title_t * title = job->title;
203 hb_subtitle_t * subtitle;
204 uint8_t * buf = pv->buf->data;
219 for( i = pv->size_rle; ; )
221 date = ( buf[i] << 8 ) | buf[i+1]; i += 2;
222 next = ( buf[i] << 8 ) | buf[i+1]; i += 2;
229 * There are eight commands available for
230 * Sub-Pictures. The first SP_DCSQ should contain, as a
231 * minimum, SET_COLOR, SET_CONTR, SET_DAREA, and
235 if( command == 0xFF ) // 0xFF - CMD_END - ends one SP_DCSQ
242 case 0x00: // 0x00 - FSTA_DSP - Forced Start Display, no arguments
243 pv->pts_start = pv->pts + date * 900;
247 * If we are doing a subtitle scan then note down
249 if( job->indepth_scan )
251 for( n=0; n < hb_list_count(title->list_subtitle); n++ )
253 subtitle = hb_list_item( title->list_subtitle, n);
254 if( pv->stream_id == subtitle->id ) {
258 subtitle->forced_hits++;
264 case 0x01: // 0x01 - STA_DSP - Start Display, no arguments
265 pv->pts_start = pv->pts + date * 900;
269 case 0x02: // 0x02 - STP_DSP - Stop Display, no arguments
271 pv->pts_stop = pv->pts + date * 900;
274 case 0x03: // 0x03 - SET_COLOR - Set Colour indices
277 * SET_COLOR - provides four indices into the CLUT
278 * for the current PGC to associate with the four
284 colors[0] = (buf[i+0]>>4)&0x0f;
285 colors[1] = (buf[i+0])&0x0f;
286 colors[2] = (buf[i+1]>>4)&0x0f;
287 colors[3] = (buf[i+1])&0x0f;
289 for( j = 0; j < 4; j++ )
292 * Not sure what is happening here, in theory
293 * the palette is in YCbCr. And we want YUV.
295 * However it looks more like YCrCb (according
296 * to pgcedit). And the scalers for YCrCb don't
297 * work, but I get the right colours by doing
300 uint32_t color = w->subtitle->palette[colors[j]];
302 y = (color>>16) & 0xff;
303 Cr = (color>>8) & 0xff;
306 pv->chromaU[3-j] = Cb;
307 pv->chromaV[3-j] = Cr;
308 /* hb_log("color[%d] y = %d, u = %d, v = %d",
318 case 0x04: // 0x04 - SET_CONTR - Set Contrast
321 * SET_CONTR - directly provides the four contrast
322 * (alpha blend) values to associate with the four
327 alpha[3] = (buf[i+0]>>4)&0x0f;
328 alpha[2] = (buf[i+0])&0x0f;
329 alpha[1] = (buf[i+1]>>4)&0x0f;
330 alpha[0] = (buf[i+1])&0x0f;
333 int lastAlpha = pv->alpha[3] + pv->alpha[2] + pv->alpha[1] + pv->alpha[0];
334 int currAlpha = alpha[3] + alpha[2] + alpha[1] + alpha[0];
336 // fading-in, save the highest alpha value
337 if( currAlpha > lastAlpha )
339 pv->alpha[3] = alpha[3];
340 pv->alpha[2] = alpha[2];
341 pv->alpha[1] = alpha[1];
342 pv->alpha[0] = alpha[0];
346 if( currAlpha < lastAlpha && !pv->pts_stop )
348 pv->pts_stop = pv->pts + date * 900;
354 case 0x05: // 0x05 - SET_DAREA - defines the display area
356 pv->x = (buf[i+0]<<4) | ((buf[i+1]>>4)&0x0f);
357 pv->width = (((buf[i+1]&0x0f)<<8)| buf[i+2]) - pv->x + 1;
358 pv->y = (buf[i+3]<<4)| ((buf[i+4]>>4)&0x0f);
359 pv->height = (((buf[i+4]&0x0f)<<8)| buf[i+5]) - pv->y + 1;
363 case 0x06: // 0x06 - SET_DSPXA - defines the pixel data addresses
365 pv->offsets[0] = ( buf[i] << 8 ) | buf[i+1]; i += 2;
366 pv->offsets[1] = ( buf[i] << 8 ) | buf[i+1]; i += 2;
383 /* Show it for 3 seconds */
384 pv->pts_stop = pv->pts_start + 3 * 90000;
388 /***********************************************************************
390 ***********************************************************************
391 * Given a raw decoded subtitle, detects transparent borders and
392 * returns a cropped subtitle in a hb_buffer_t ready to be used by
393 * the renderer, or NULL if the subtitle was completely transparent
394 **********************************************************************/
395 static int LineIsTransparent( hb_work_object_t * w, uint8_t * p )
397 hb_work_private_t * pv = w->private_data;
399 for( i = 0; i < pv->width; i++ )
408 static int ColumnIsTransparent( hb_work_object_t * w, uint8_t * p )
410 hb_work_private_t * pv = w->private_data;
412 for( i = 0; i < pv->height; i++ )
421 static hb_buffer_t * CropSubtitle( hb_work_object_t * w, uint8_t * raw )
423 hb_work_private_t * pv = w->private_data;
425 int crop[4] = { -1,-1,-1,-1 };
427 int realwidth, realheight;
429 uint8_t * lum_in, * lum_out, * alpha_in, * alpha_out;
430 uint8_t * u_in, * u_out, * v_in, * v_out;
432 alpha = raw + pv->width * pv->height;
435 for( i = 0; i < pv->height; i++ )
437 if( !LineIsTransparent( w, &alpha[i*pv->width] ) )
451 for( i = pv->height - 1; i >= 0; i-- )
453 if( !LineIsTransparent( w, &alpha[i*pv->width] ) )
461 for( i = 0; i < pv->width; i++ )
463 if( !ColumnIsTransparent( w, &alpha[i] ) )
471 for( i = pv->width - 1; i >= 0; i-- )
473 if( !ColumnIsTransparent( w, &alpha[i] ) )
480 realwidth = crop[3] - crop[2] + 1;
481 realheight = crop[1] - crop[0] + 1;
483 buf = hb_buffer_init( realwidth * realheight * 4 );
484 buf->start = pv->pts_start;
485 buf->stop = pv->pts_stop;
486 buf->x = pv->x + crop[2];
487 buf->y = pv->y + crop[0];
488 buf->width = realwidth;
489 buf->height = realheight;
491 lum_in = raw + crop[0] * pv->width + crop[2];
492 alpha_in = lum_in + pv->width * pv->height;
493 u_in = alpha_in + pv->width * pv->height;
494 v_in = u_in + pv->width * pv->height;
497 alpha_out = lum_out + realwidth * realheight;
498 u_out = alpha_out + realwidth * realheight;
499 v_out = u_out + realwidth * realheight;
501 for( i = 0; i < realheight; i++ )
503 memcpy( lum_out, lum_in, realwidth );
504 memcpy( alpha_out, alpha_in, realwidth );
505 memcpy( u_out, u_in, realwidth );
506 memcpy( v_out, v_in, realwidth );
509 alpha_in += pv->width;
513 lum_out += realwidth;
514 alpha_out += realwidth;
522 static hb_buffer_t * Decode( hb_work_object_t * w )
524 hb_work_private_t * pv = w->private_data;
529 uint8_t * buf_raw = NULL;
530 hb_job_t * job = pv->job;
532 /* Get infos about the subtitle */
535 if( job->indepth_scan || ( w->subtitle->config.force && pv->pts_forced == 0 ) )
538 * Don't encode subtitles when doing a scan.
540 * When forcing subtitles, ignore all those that don't
541 * have the forced flag set.
543 hb_buffer_close( &pv->buf );
547 if (w->subtitle->config.dest == PASSTHRUSUB)
549 pv->buf->start = pv->pts_start;
550 pv->buf->stop = pv->pts_stop;
556 /* Do the actual decoding now */
557 buf_raw = malloc( ( pv->width * pv->height ) * 4 );
559 #define GET_NEXT_NIBBLE code = ( code << 4 ) | ( ( ( *offset & 1 ) ? \
560 ( pv->buf->data[((*offset)>>1)] & 0xF ) : ( pv->buf->data[((*offset)>>1)] >> 4 ) ) ); \
563 offsets[0] = pv->offsets[0] * 2;
564 offsets[1] = pv->offsets[1] * 2;
566 for( line = 0; line < pv->height; line++ )
568 /* Select even or odd field */
569 offset = ( line & 1 ) ? &offsets[1] : &offsets[0];
571 for( col = 0; col < pv->width; col += code >> 2 )
573 uint8_t * lum, * alpha, * chromaU, * chromaV;
589 code |= ( pv->width - col ) << 2;
596 alpha = lum + pv->width * pv->height;
597 chromaU = alpha + pv->width * pv->height;
598 chromaV = chromaU + pv->width * pv->height;
600 memset( lum + line * pv->width + col,
601 pv->lum[code & 3], code >> 2 );
602 memset( alpha + line * pv->width + col,
603 pv->alpha[code & 3], code >> 2 );
604 memset( chromaU + line * pv->width + col,
605 pv->chromaU[code & 3], code >> 2 );
606 memset( chromaV + line * pv->width + col,
607 pv->chromaV[code & 3], code >> 2 );
617 hb_buffer_close( &pv->buf );
619 /* Crop subtitle (remove transparent borders) */
620 buf = CropSubtitle( w, buf_raw );