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
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
32 struct hb_work_private_s
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
) );
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
79 if (w
->subtitle
->palette
[i
])
86 if (!pv
->palette_set
) {
87 hb_log( "decvobsub: input color palette is empty!" );
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 */
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];
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
;
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
;
151 // bad size, must have lost sync
153 if ( pv
->buf
!= NULL
)
154 hb_buffer_close( &pv
->buf
);
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 */
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
;
193 void decsubClose( hb_work_object_t
* w
)
195 hb_work_private_t
* pv
= w
->private_data
;
198 hb_buffer_close( &pv
->buf
);
199 free( w
->private_data
);
202 hb_work_object_t hb_decvobsub
=
212 /***********************************************************************
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
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
;
228 pv
->pts_start
= AV_NOPTS_VALUE
;
229 pv
->pts_stop
= AV_NOPTS_VALUE
;
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;
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
253 if( command
== 0xFF ) // 0xFF - CMD_END - ends one SP_DCSQ
260 case 0x00: // 0x00 - FSTA_DSP - Forced Start Display, no arguments
261 pv
->pts_start
= pv
->pts
+ date
* 1024;
264 w
->subtitle
->forced_hits
++;
267 case 0x01: // 0x01 - STA_DSP - Start Display, no arguments
268 pv
->pts_start
= pv
->pts
+ date
* 1024;
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;
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
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
304 uint32_t color
= w
->subtitle
->palette
[colors
[j
]];
306 y
= (color
>>16) & 0xff;
307 Cr
= (color
>>8) & 0xff;
310 pv
->chromaU
[3-j
] = Cb
;
311 pv
->chromaV
[3-j
] = Cr
;
312 /* hb_log("color[%d] y = %d, u = %d, v = %d",
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
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];
350 if (currAlpha
< lastAlpha
&& pv
->pts_stop
== AV_NOPTS_VALUE
)
352 pv
->pts_stop
= pv
->pts
+ date
* 1024;
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;
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;
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 /***********************************************************************
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
;
403 for( i
= 0; i
< pv
->width
; i
++ )
413 static int ColumnIsTransparent( hb_work_object_t
* w
, uint8_t * p
)
415 hb_work_private_t
* pv
= w
->private_data
;
417 for( i
= 0; i
< pv
->height
; i
++ )
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
;
442 for( src_x
= 0; src_x
< src_w
; src_x
++ )
455 for( ; dst_x
< dst_w
; dst_x
++ )
466 for( dst_x
= 0; dst_x
< dst_w
; dst_x
++ )
468 dst
[dst_x
] = src
[src_x
];
479 static hb_buffer_t
* CropSubtitle( hb_work_object_t
* w
, uint8_t * raw
)
481 hb_work_private_t
* pv
= w
->private_data
;
483 int crop
[4] = { -1,-1,-1,-1 };
485 int realwidth
, realheight
;
487 uint8_t * lum_in
, * alpha_in
, * u_in
, * v_in
;
489 alpha
= raw
+ pv
->width
* pv
->height
;
492 for( i
= 0; i
< pv
->height
; i
++ )
494 if( !LineIsTransparent( w
, &alpha
[i
*pv
->width
] ) )
508 for( i
= pv
->height
- 1; i
>= 0; i
-- )
510 if( !LineIsTransparent( w
, &alpha
[i
*pv
->width
] ) )
518 for( i
= 0; i
< pv
->width
; i
++ )
520 if( !ColumnIsTransparent( w
, &alpha
[i
] ) )
528 for( i
= pv
->width
- 1; i
>= 0; i
-- )
530 if( !ColumnIsTransparent( w
, &alpha
[i
] ) )
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
;
555 for( i
= 0; i
< realheight
; i
++ )
558 dst
= buf
->plane
[0].data
+ buf
->plane
[0].stride
* i
;
559 memcpy( dst
, lum_in
, realwidth
);
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
);
572 dst
= buf
->plane
[3].data
+ buf
->plane
[3].stride
* i
;
573 memcpy( dst
, alpha_in
, realwidth
);
576 alpha_in
+= pv
->width
;
584 static hb_buffer_t
* Decode( hb_work_object_t
* w
)
586 hb_work_private_t
* pv
= w
->private_data
;
591 uint8_t * buf_raw
= NULL
;
592 hb_job_t
* job
= pv
->job
;
594 /* Get infos about the subtitle */
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
);
609 if (w
->subtitle
->config
.dest
== PASSTHRUSUB
)
611 pv
->buf
->s
.start
= pv
->pts_start
;
612 pv
->buf
->s
.stop
= pv
->pts_stop
;
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 ) ) ); \
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
;
651 code
|= ( pv
->width
- col
) << 2;
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 );
679 hb_buffer_close( &pv
->buf
);
681 /* Crop subtitle (remove transparent borders) */
682 buf
= CropSubtitle( w
, buf_raw
);