WinGui: Fix another instance of the Caliburn vs Json.net sillyness where objects...
[HandBrake.git] / libhb / decvobsub.c
blobfa247ab28bf058e768f97c3d2e899ec64ef64435
1 /* decvobsub.c
3 Copyright (c) 2003-2015 HandBrake Team
4 This file is part of the HandBrake source code
5 Homepage: <http://handbrake.fr/>.
6 It may be used under the terms of the GNU General Public License v2.
7 For full terms see the file COPYING file or visit http://www.gnu.org/licenses/gpl-2.0.html
8 */
11 * Decoder for DVD bitmap subtitles, also known as "VOB subtitles" within the HandBrake source code.
13 * Input format of the subtitle packets is described here:
14 * http://sam.zoy.org/writings/dvd/subtitles/
16 * An auxiliary input is the color palette lookup table, in 'subtitle->palette'.
17 * The demuxer implementation must fill out this table appropriately.
18 * - In the case of a true DVD input, the palette is read from the IFO file.
19 * - In the case of an MKV file input, the palette is read from the codec private data of the subtitle track.
21 * Output format of this decoder is PICTURESUB, which is:
22 * struct PictureSubPacket {
23 * uint8_t lum[pixelCount]; // Y
24 * uint8_t alpha[pixelCount]; // alpha (max = 16)
25 * uint8_t chromaU[pixelCount]; // Cb
26 * uint8_t chromaV[pixelCount]; // Cr
27 * }
30 #include "hb.h"
32 struct hb_work_private_s
34 hb_job_t * job;
36 hb_buffer_t * buf;
37 int size_sub;
38 int size_got;
39 int size_rle;
40 int64_t pts;
41 int64_t pts_start;
42 int64_t pts_stop;
43 int pts_forced;
44 int x;
45 int y;
46 int width;
47 int height;
48 int stream_id;
50 int offsets[2];
51 uint8_t lum[4];
52 uint8_t chromaU[4];
53 uint8_t chromaV[4];
54 uint8_t alpha[4];
55 uint8_t palette_set;
58 static hb_buffer_t * Decode( hb_work_object_t * );
60 int decsubInit( hb_work_object_t * w, hb_job_t * job )
62 hb_work_private_t * pv;
64 pv = calloc( 1, sizeof( hb_work_private_t ) );
65 w->private_data = pv;
67 pv->job = job;
68 pv->pts = 0;
70 // Warn if the input color palette is empty
71 pv->palette_set = w->subtitle->palette_set;
72 if ( pv->palette_set )
74 // Make sure the entries in the palette are not all 0
75 pv->palette_set = 0;
76 int i;
77 for (i=0; i<16; i++)
79 if (w->subtitle->palette[i])
81 pv->palette_set = 1;
82 break;
86 if (!pv->palette_set) {
87 hb_log( "decvobsub: input color palette is empty!" );
90 return 0;
93 int decsubWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
94 hb_buffer_t ** buf_out )
96 hb_work_private_t * pv = w->private_data;
97 hb_buffer_t * in = *buf_in;
98 int size_sub, size_rle;
100 if (in->s.flags & HB_BUF_FLAG_EOF)
102 /* EOF on input stream - send it downstream & say that we're done */
103 *buf_out = in;
104 *buf_in = NULL;
105 return HB_WORK_DONE;
108 pv->stream_id = in->s.id;
110 size_sub = ( in->data[0] << 8 ) | in->data[1];
111 size_rle = ( in->data[2] << 8 ) | in->data[3];
113 if( !pv->size_sub )
115 /* We are looking for the start of a new subtitle */
116 if( size_sub && size_rle && size_sub > size_rle &&
117 in->size <= size_sub )
119 /* Looks all right so far */
120 pv->size_sub = size_sub;
121 pv->size_rle = size_rle;
123 pv->buf = hb_buffer_init( 0xFFFF );
124 memcpy( pv->buf->data, in->data, in->size );
125 pv->buf->s.id = in->s.id;
126 pv->buf->s.frametype = HB_FRAME_SUBTITLE;
127 pv->buf->sequence = in->sequence;
128 pv->size_got = in->size;
129 if( in->s.start >= 0 )
131 pv->pts = in->s.start;
135 else
137 /* We are waiting for the end of the current subtitle */
138 if( in->size <= pv->size_sub - pv->size_got )
140 memcpy( pv->buf->data + pv->size_got, in->data, in->size );
141 pv->buf->s.id = in->s.id;
142 pv->buf->sequence = in->sequence;
143 pv->size_got += in->size;
144 if( in->s.start >= 0 )
146 pv->pts = in->s.start;
149 else
151 // bad size, must have lost sync
152 // force re-sync
153 if ( pv->buf != NULL )
154 hb_buffer_close( &pv->buf );
155 pv->size_sub = 0;
160 *buf_out = NULL;
162 if( pv->size_sub && pv->size_sub == pv->size_got )
164 pv->buf->size = pv->size_sub;
166 /* We got a complete subtitle, decode it */
167 *buf_out = Decode( w );
169 if( buf_out && *buf_out )
171 (*buf_out)->s.id = in->s.id;
172 (*buf_out)->sequence = in->sequence;
175 /* Wait for the next one */
176 pv->size_sub = 0;
177 pv->size_got = 0;
178 pv->size_rle = 0;
180 if ( pv->pts_stop != AV_NOPTS_VALUE )
182 // If we don't get a valid next timestamp, use the stop time
183 // of the current sub as the start of the next.
184 // This can happen if reader invalidates timestamps while
185 // waiting for an audio to update the SCR.
186 pv->pts = pv->pts_stop;
190 return HB_WORK_OK;
193 void decsubClose( hb_work_object_t * w )
195 hb_work_private_t * pv = w->private_data;
197 if ( pv->buf )
198 hb_buffer_close( &pv->buf );
199 free( w->private_data );
202 hb_work_object_t hb_decvobsub =
204 WORK_DECVOBSUB,
205 "VOBSUB decoder",
206 decsubInit,
207 decsubWork,
208 decsubClose
212 /***********************************************************************
213 * ParseControls
214 ***********************************************************************
215 * Get the start and end dates (relative to the PTS from the PES
216 * header), the width and height of the subpicture and the colors and
217 * alphas used in it
218 **********************************************************************/
219 static void ParseControls( hb_work_object_t * w )
221 hb_work_private_t * pv = w->private_data;
222 uint8_t * buf = pv->buf->data;
224 int i;
225 int command;
226 int date, next;
228 pv->pts_start = AV_NOPTS_VALUE;
229 pv->pts_stop = AV_NOPTS_VALUE;
230 pv->pts_forced = 0;
232 pv->alpha[3] = 0;
233 pv->alpha[2] = 0;
234 pv->alpha[1] = 0;
235 pv->alpha[0] = 0;
237 for( i = pv->size_rle; ; )
239 date = ( buf[i] << 8 ) | buf[i+1]; i += 2;
240 next = ( buf[i] << 8 ) | buf[i+1]; i += 2;
242 for( ;; )
244 command = buf[i++];
247 * There are eight commands available for
248 * Sub-Pictures. The first SP_DCSQ should contain, as a
249 * minimum, SET_COLOR, SET_CONTR, SET_DAREA, and
250 * SET_DSPXA
253 if( command == 0xFF ) // 0xFF - CMD_END - ends one SP_DCSQ
255 break;
258 switch( command )
260 case 0x00: // 0x00 - FSTA_DSP - Forced Start Display, no arguments
261 pv->pts_start = pv->pts + date * 1024;
262 pv->pts_forced = 1;
263 w->subtitle->hits++;
264 w->subtitle->forced_hits++;
265 break;
267 case 0x01: // 0x01 - STA_DSP - Start Display, no arguments
268 pv->pts_start = pv->pts + date * 1024;
269 pv->pts_forced = 0;
270 w->subtitle->hits++;
271 break;
273 case 0x02: // 0x02 - STP_DSP - Stop Display, no arguments
274 if(pv->pts_stop == AV_NOPTS_VALUE)
275 pv->pts_stop = pv->pts + date * 1024;
276 break;
278 case 0x03: // 0x03 - SET_COLOR - Set Colour indices
281 * SET_COLOR - provides four indices into the CLUT
282 * for the current PGC to associate with the four
283 * pixel values
285 int colors[4];
286 int j;
288 colors[0] = (buf[i+0]>>4)&0x0f;
289 colors[1] = (buf[i+0])&0x0f;
290 colors[2] = (buf[i+1]>>4)&0x0f;
291 colors[3] = (buf[i+1])&0x0f;
293 for( j = 0; j < 4; j++ )
296 * Not sure what is happening here, in theory
297 * the palette is in YCbCr. And we want YUV.
299 * However it looks more like YCrCb (according
300 * to pgcedit). And the scalers for YCrCb don't
301 * work, but I get the right colours by doing
302 * no conversion.
304 uint32_t color = w->subtitle->palette[colors[j]];
305 uint8_t Cr, Cb, y;
306 y = (color>>16) & 0xff;
307 Cr = (color>>8) & 0xff;
308 Cb = (color) & 0xff;
309 pv->lum[3-j] = y;
310 pv->chromaU[3-j] = Cb;
311 pv->chromaV[3-j] = Cr;
312 /* hb_log("color[%d] y = %d, u = %d, v = %d",
313 3-j,
314 pv->lum[3-j],
315 pv->chromaU[3-j],
316 pv->chromaV[3-j]);
319 i += 2;
320 break;
322 case 0x04: // 0x04 - SET_CONTR - Set Contrast
325 * SET_CONTR - directly provides the four contrast
326 * (alpha blend) values to associate with the four
327 * pixel values
329 uint8_t alpha[4];
331 alpha[3] = ((buf[i+0] >> 4) & 0x0f) << 4;
332 alpha[2] = ((buf[i+0] ) & 0x0f) << 4;
333 alpha[1] = ((buf[i+1] >> 4) & 0x0f) << 4;
334 alpha[0] = ((buf[i+1] ) & 0x0f) << 4;
337 int lastAlpha = pv->alpha[3] + pv->alpha[2] + pv->alpha[1] + pv->alpha[0];
338 int currAlpha = alpha[3] + alpha[2] + alpha[1] + alpha[0];
340 // fading-in, save the highest alpha value
341 if( currAlpha > lastAlpha )
343 pv->alpha[3] = alpha[3];
344 pv->alpha[2] = alpha[2];
345 pv->alpha[1] = alpha[1];
346 pv->alpha[0] = alpha[0];
349 // fading-out
350 if (currAlpha < lastAlpha && pv->pts_stop == AV_NOPTS_VALUE)
352 pv->pts_stop = pv->pts + date * 1024;
355 i += 2;
356 break;
358 case 0x05: // 0x05 - SET_DAREA - defines the display area
360 pv->x = (buf[i+0]<<4) | ((buf[i+1]>>4)&0x0f);
361 pv->width = (((buf[i+1]&0x0f)<<8)| buf[i+2]) - pv->x + 1;
362 pv->y = (buf[i+3]<<4)| ((buf[i+4]>>4)&0x0f);
363 pv->height = (((buf[i+4]&0x0f)<<8)| buf[i+5]) - pv->y + 1;
364 i += 6;
365 break;
367 case 0x06: // 0x06 - SET_DSPXA - defines the pixel data addresses
369 pv->offsets[0] = ( buf[i] << 8 ) | buf[i+1]; i += 2;
370 pv->offsets[1] = ( buf[i] << 8 ) | buf[i+1]; i += 2;
371 break;
378 if( i > next )
380 break;
382 i = next;
384 // Generate timestamps if they are not set
385 if( pv->pts_start == AV_NOPTS_VALUE )
387 // Set pts to end of last sub if the start time is unknown.
388 pv->pts_start = pv->pts;
392 /***********************************************************************
393 * CropSubtitle
394 ***********************************************************************
395 * Given a raw decoded subtitle, detects transparent borders and
396 * returns a cropped subtitle in a hb_buffer_t ready to be used by
397 * the renderer, or NULL if the subtitle was completely transparent
398 **********************************************************************/
399 static int LineIsTransparent( hb_work_object_t * w, uint8_t * p )
401 hb_work_private_t * pv = w->private_data;
402 int i;
403 for( i = 0; i < pv->width; i++ )
405 if( p[i] )
407 return 0;
410 return 1;
413 static int ColumnIsTransparent( hb_work_object_t * w, uint8_t * p )
415 hb_work_private_t * pv = w->private_data;
416 int i;
417 for( i = 0; i < pv->height; i++ )
419 if( p[i*pv->width] )
421 return 0;
424 return 1;
427 // Brain dead resampler. This should really use swscale...
428 // Uses Bresenham algo to pick source samples for averaging
429 static void resample( uint8_t * dst, uint8_t * src, int dst_w, int src_w )
431 int dst_x, src_x, err, cnt, sum, val;
433 if( dst_w < src_w )
435 // sample down
436 err = 0;
437 sum = 0;
438 val = 0;
439 cnt = 0;
440 err = src_w / 2;
441 dst_x = 0;
442 for( src_x = 0; src_x < src_w; src_x++ )
444 sum += src[src_x];
445 cnt++;
446 err -= dst_w;
447 if( err < 0 )
449 val = sum / cnt;
450 dst[dst_x++] = val;
451 sum = cnt = 0;
452 err += src_w;
455 for( ; dst_x < dst_w; dst_x++ )
457 dst[dst_x] = val;
460 else
462 // sample up
463 err = 0;
464 err = dst_w / 2;
465 src_x = 0;
466 for( dst_x = 0; dst_x < dst_w; dst_x++ )
468 dst[dst_x] = src[src_x];
469 err -= src_w;
470 if( err < 0 )
472 src_x++;
473 err += dst_w;
479 static hb_buffer_t * CropSubtitle( hb_work_object_t * w, uint8_t * raw )
481 hb_work_private_t * pv = w->private_data;
482 int i;
483 int crop[4] = { -1,-1,-1,-1 };
484 uint8_t * alpha;
485 int realwidth, realheight;
486 hb_buffer_t * buf;
487 uint8_t * lum_in, * alpha_in, * u_in, * v_in;
489 alpha = raw + pv->width * pv->height;
491 /* Top */
492 for( i = 0; i < pv->height; i++ )
494 if( !LineIsTransparent( w, &alpha[i*pv->width] ) )
496 crop[0] = i;
497 break;
501 if( crop[0] < 0 )
503 /* Empty subtitle */
504 return NULL;
507 /* Bottom */
508 for( i = pv->height - 1; i >= 0; i-- )
510 if( !LineIsTransparent( w, &alpha[i*pv->width] ) )
512 crop[1] = i;
513 break;
517 /* Left */
518 for( i = 0; i < pv->width; i++ )
520 if( !ColumnIsTransparent( w, &alpha[i] ) )
522 crop[2] = i;
523 break;
527 /* Right */
528 for( i = pv->width - 1; i >= 0; i-- )
530 if( !ColumnIsTransparent( w, &alpha[i] ) )
532 crop[3] = i;
533 break;
537 realwidth = crop[3] - crop[2] + 1;
538 realheight = crop[1] - crop[0] + 1;
540 buf = hb_frame_buffer_init( AV_PIX_FMT_YUVA420P, realwidth, realheight );
541 buf->s.frametype = HB_FRAME_SUBTITLE;
542 buf->s.start = pv->pts_start;
543 buf->s.stop = pv->pts_stop;
544 buf->s.type = SUBTITLE_BUF;
546 buf->f.x = pv->x + crop[2];
547 buf->f.y = pv->y + crop[0];
549 lum_in = raw + crop[0] * pv->width + crop[2];
550 alpha_in = lum_in + pv->width * pv->height;
551 u_in = alpha_in + pv->width * pv->height;
552 v_in = u_in + pv->width * pv->height;
554 uint8_t *dst;
555 for( i = 0; i < realheight; i++ )
557 // Luma
558 dst = buf->plane[0].data + buf->plane[0].stride * i;
559 memcpy( dst, lum_in, realwidth );
561 if( ( i & 1 ) == 0 )
563 // chroma U (resample to YUV420)
564 dst = buf->plane[1].data + buf->plane[1].stride * ( i >> 1 );
565 resample( dst, u_in, buf->plane[1].width, realwidth );
567 // chroma V (resample to YUV420)
568 dst = buf->plane[2].data + buf->plane[2].stride * ( i >> 1 );
569 resample( dst, v_in, buf->plane[2].width, realwidth );
571 // Alpha
572 dst = buf->plane[3].data + buf->plane[3].stride * i;
573 memcpy( dst, alpha_in, realwidth );
575 lum_in += pv->width;
576 alpha_in += pv->width;
577 u_in += pv->width;
578 v_in += pv->width;
581 return buf;
584 static hb_buffer_t * Decode( hb_work_object_t * w )
586 hb_work_private_t * pv = w->private_data;
587 int code, line, col;
588 int offsets[2];
589 int * offset;
590 hb_buffer_t * buf;
591 uint8_t * buf_raw = NULL;
592 hb_job_t * job = pv->job;
594 /* Get infos about the subtitle */
595 ParseControls( w );
597 if( job->indepth_scan || ( w->subtitle->config.force && pv->pts_forced == 0 ) )
600 * Don't encode subtitles when doing a scan.
602 * When forcing subtitles, ignore all those that don't
603 * have the forced flag set.
605 hb_buffer_close( &pv->buf );
606 return NULL;
609 if (w->subtitle->config.dest == PASSTHRUSUB)
611 pv->buf->s.start = pv->pts_start;
612 pv->buf->s.stop = pv->pts_stop;
613 buf = pv->buf;
614 pv->buf = NULL;
615 return buf;
618 /* Do the actual decoding now */
619 buf_raw = malloc( ( pv->width * pv->height ) * 4 );
621 #define GET_NEXT_NIBBLE code = ( code << 4 ) | ( ( ( *offset & 1 ) ? \
622 ( pv->buf->data[((*offset)>>1)] & 0xF ) : ( pv->buf->data[((*offset)>>1)] >> 4 ) ) ); \
623 (*offset)++
625 offsets[0] = pv->offsets[0] * 2;
626 offsets[1] = pv->offsets[1] * 2;
628 for( line = 0; line < pv->height; line++ )
630 /* Select even or odd field */
631 offset = ( line & 1 ) ? &offsets[1] : &offsets[0];
633 for( col = 0; col < pv->width; col += code >> 2 )
635 uint8_t * lum, * alpha, * chromaU, * chromaV;
637 code = 0;
638 GET_NEXT_NIBBLE;
639 if( code < 0x4 )
641 GET_NEXT_NIBBLE;
642 if( code < 0x10 )
644 GET_NEXT_NIBBLE;
645 if( code < 0x40 )
647 GET_NEXT_NIBBLE;
648 if( code < 0x100 )
650 /* End of line */
651 code |= ( pv->width - col ) << 2;
657 lum = buf_raw;
658 alpha = lum + pv->width * pv->height;
659 chromaU = alpha + pv->width * pv->height;
660 chromaV = chromaU + pv->width * pv->height;
662 memset( lum + line * pv->width + col,
663 pv->lum[code & 3], code >> 2 );
664 memset( alpha + line * pv->width + col,
665 pv->alpha[code & 3], code >> 2 );
666 memset( chromaU + line * pv->width + col,
667 pv->chromaU[code & 3], code >> 2 );
668 memset( chromaV + line * pv->width + col,
669 pv->chromaV[code & 3], code >> 2 );
672 /* Byte-align */
673 if( *offset & 1 )
675 (*offset)++;
679 hb_buffer_close( &pv->buf );
681 /* Crop subtitle (remove transparent borders) */
682 buf = CropSubtitle( w, buf_raw );
684 free( buf_raw );
686 return buf;