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.m0k.org/>.
5 It may be used under the terms of the GNU General Public License. */
9 struct hb_work_private_s
34 static hb_buffer_t
* Decode( hb_work_object_t
* );
36 int decsubInit( hb_work_object_t
* w
, hb_job_t
* job
)
38 hb_work_private_t
* pv
;
40 pv
= calloc( 1, sizeof( hb_work_private_t
) );
49 int decsubWork( hb_work_object_t
* w
, hb_buffer_t
** buf_in
,
50 hb_buffer_t
** buf_out
)
52 hb_work_private_t
* pv
= w
->private_data
;
53 hb_buffer_t
* in
= *buf_in
;
55 int size_sub
, size_rle
;
57 pv
->stream_id
= in
->id
;
59 size_sub
= ( in
->data
[0] << 8 ) | in
->data
[1];
60 size_rle
= ( in
->data
[2] << 8 ) | in
->data
[3];
64 /* We are looking for the start of a new subtitle */
65 if( size_sub
&& size_rle
&& size_sub
> size_rle
&&
66 in
->size
<= size_sub
)
68 /* Looks all right so far */
69 pv
->size_sub
= size_sub
;
70 pv
->size_rle
= size_rle
;
72 memcpy( pv
->buf
, in
->data
, in
->size
);
73 pv
->size_got
= in
->size
;
79 /* We are waiting for the end of the current subtitle */
80 if( in
->size
<= pv
->size_sub
- pv
->size_got
)
82 memcpy( pv
->buf
+ pv
->size_got
, in
->data
, in
->size
);
83 pv
->size_got
+= in
->size
;
93 if( pv
->size_sub
&& pv
->size_sub
== pv
->size_got
)
95 /* We got a complete subtitle, decode it */
96 *buf_out
= Decode( w
);
98 if( buf_out
&& *buf_out
)
100 (*buf_out
)->sequence
= in
->sequence
;
103 /* Wait for the next one */
113 void decsubClose( hb_work_object_t
* w
)
115 free( w
->private_data
);
118 hb_work_object_t hb_decsub
=
128 /***********************************************************************
130 ***********************************************************************
131 * Get the start and end dates (relative to the PTS from the PES
132 * header), the width and height of the subpicture and the colors and
134 **********************************************************************/
135 static void ParseControls( hb_work_object_t
* w
)
137 hb_work_private_t
* pv
= w
->private_data
;
138 hb_job_t
* job
= pv
->job
;
139 hb_title_t
* title
= job
->title
;
140 hb_subtitle_t
* subtitle
;
155 for( i
= pv
->size_rle
; ; )
157 date
= ( pv
->buf
[i
] << 8 ) | pv
->buf
[i
+1]; i
+= 2;
158 next
= ( pv
->buf
[i
] << 8 ) | pv
->buf
[i
+1]; i
+= 2;
162 command
= pv
->buf
[i
++];
165 * There are eight commands available for
166 * Sub-Pictures. The first SP_DCSQ should contain, as a
167 * minimum, SET_COLOR, SET_CONTR, SET_DAREA, and
171 if( command
== 0xFF ) // 0xFF - CMD_END - ends one SP_DCSQ
178 case 0x00: // 0x00 - FSTA_DSP - Forced Start Display, no arguments
179 pv
->pts_start
= pv
->pts
+ date
* 900;
183 * If we are doing a subtitle scan then note down
185 if( job
->indepth_scan
)
187 for( n
=0; n
< hb_list_count(title
->list_subtitle
); n
++ )
189 subtitle
= hb_list_item( title
->list_subtitle
, n
);
190 if( pv
->stream_id
== subtitle
->id
) {
194 subtitle
->forced_hits
++;
200 case 0x01: // 0x01 - STA_DSP - Start Display, no arguments
201 pv
->pts_start
= pv
->pts
+ date
* 900;
205 case 0x02: // 0x02 - STP_DSP - Stop Display, no arguments
207 pv
->pts_stop
= pv
->pts
+ date
* 900;
210 case 0x03: // 0x03 - SET_COLOR - Set Colour indices
213 * SET_COLOR - provides four indices into the CLUT
214 * for the current PGC to associate with the four
220 colors
[0] = (pv
->buf
[i
+0]>>4)&0x0f;
221 colors
[1] = (pv
->buf
[i
+0])&0x0f;
222 colors
[2] = (pv
->buf
[i
+1]>>4)&0x0f;
223 colors
[3] = (pv
->buf
[i
+1])&0x0f;
225 for( j
= 0; j
< 4; j
++ )
228 * Not sure what is happening here, in theory
229 * the palette is in YCbCr. And we want YUV.
231 * However it looks more like YCrCb (according
232 * to pgcedit). And the scalers for YCrCb don't
233 * work, but I get the right colours by doing
236 uint32_t color
= title
->palette
[colors
[j
]];
238 y
= (color
>>16) & 0xff;
239 Cr
= (color
>>8) & 0xff;
242 pv
->chromaU
[3-j
] = Cb
;
243 pv
->chromaV
[3-j
] = Cr
;
244 /* hb_log("color[%d] y = %d, u = %d, v = %d",
254 case 0x04: // 0x04 - SET_CONTR - Set Contrast
257 * SET_CONTR - directly provides the four contrast
258 * (alpha blend) values to associate with the four
263 alpha
[3] = (pv
->buf
[i
+0]>>4)&0x0f;
264 alpha
[2] = (pv
->buf
[i
+0])&0x0f;
265 alpha
[1] = (pv
->buf
[i
+1]>>4)&0x0f;
266 alpha
[0] = (pv
->buf
[i
+1])&0x0f;
269 int lastAlpha
= pv
->alpha
[3] + pv
->alpha
[2] + pv
->alpha
[1] + pv
->alpha
[0];
270 int currAlpha
= alpha
[3] + alpha
[2] + alpha
[1] + alpha
[0];
272 // fading-in, save the highest alpha value
273 if( currAlpha
> lastAlpha
)
275 pv
->alpha
[3] = alpha
[3];
276 pv
->alpha
[2] = alpha
[2];
277 pv
->alpha
[1] = alpha
[1];
278 pv
->alpha
[0] = alpha
[0];
282 if( currAlpha
< lastAlpha
&& !pv
->pts_stop
)
284 pv
->pts_stop
= pv
->pts
+ date
* 900;
290 case 0x05: // 0x05 - SET_DAREA - defines the display area
292 pv
->x
= (pv
->buf
[i
+0]<<4) | ((pv
->buf
[i
+1]>>4)&0x0f);
293 pv
->width
= (((pv
->buf
[i
+1]&0x0f)<<8)| pv
->buf
[i
+2]) - pv
->x
+ 1;
294 pv
->y
= (pv
->buf
[i
+3]<<4)| ((pv
->buf
[i
+4]>>4)&0x0f);
295 pv
->height
= (((pv
->buf
[i
+4]&0x0f)<<8)| pv
->buf
[i
+5]) - pv
->y
+ 1;
299 case 0x06: // 0x06 - SET_DSPXA - defines the pixel data addresses
301 pv
->offsets
[0] = ( pv
->buf
[i
] << 8 ) | pv
->buf
[i
+1]; i
+= 2;
302 pv
->offsets
[1] = ( pv
->buf
[i
] << 8 ) | pv
->buf
[i
+1]; i
+= 2;
319 /* Show it for 3 seconds */
320 pv
->pts_stop
= pv
->pts_start
+ 3 * 90000;
324 /***********************************************************************
326 ***********************************************************************
327 * Given a raw decoded subtitle, detects transparent borders and
328 * returns a cropped subtitle in a hb_buffer_t ready to be used by
329 * the renderer, or NULL if the subtitle was completely transparent
330 **********************************************************************/
331 static int LineIsTransparent( hb_work_object_t
* w
, uint8_t * p
)
333 hb_work_private_t
* pv
= w
->private_data
;
335 for( i
= 0; i
< pv
->width
; i
++ )
344 static int ColumnIsTransparent( hb_work_object_t
* w
, uint8_t * p
)
346 hb_work_private_t
* pv
= w
->private_data
;
348 for( i
= 0; i
< pv
->height
; i
++ )
357 static hb_buffer_t
* CropSubtitle( hb_work_object_t
* w
, uint8_t * raw
)
359 hb_work_private_t
* pv
= w
->private_data
;
361 int crop
[4] = { -1,-1,-1,-1 };
363 int realwidth
, realheight
;
365 uint8_t * lum_in
, * lum_out
, * alpha_in
, * alpha_out
;
366 uint8_t * u_in
, * u_out
, * v_in
, * v_out
;
368 alpha
= raw
+ pv
->width
* pv
->height
;
371 for( i
= 0; i
< pv
->height
; i
++ )
373 if( !LineIsTransparent( w
, &alpha
[i
*pv
->width
] ) )
387 for( i
= pv
->height
- 1; i
>= 0; i
-- )
389 if( !LineIsTransparent( w
, &alpha
[i
*pv
->width
] ) )
397 for( i
= 0; i
< pv
->width
; i
++ )
399 if( !ColumnIsTransparent( w
, &alpha
[i
] ) )
407 for( i
= pv
->width
- 1; i
>= 0; i
-- )
409 if( !ColumnIsTransparent( w
, &alpha
[i
] ) )
416 realwidth
= crop
[3] - crop
[2] + 1;
417 realheight
= crop
[1] - crop
[0] + 1;
419 buf
= hb_buffer_init( realwidth
* realheight
* 4 );
420 buf
->start
= pv
->pts_start
;
421 buf
->stop
= pv
->pts_stop
;
422 buf
->x
= pv
->x
+ crop
[2];
423 buf
->y
= pv
->y
+ crop
[0];
424 buf
->width
= realwidth
;
425 buf
->height
= realheight
;
427 lum_in
= raw
+ crop
[0] * pv
->width
+ crop
[2];
428 alpha_in
= lum_in
+ pv
->width
* pv
->height
;
429 u_in
= alpha_in
+ pv
->width
* pv
->height
;
430 v_in
= u_in
+ pv
->width
* pv
->height
;
433 alpha_out
= lum_out
+ realwidth
* realheight
;
434 u_out
= alpha_out
+ realwidth
* realheight
;
435 v_out
= u_out
+ realwidth
* realheight
;
437 for( i
= 0; i
< realheight
; i
++ )
439 memcpy( lum_out
, lum_in
, realwidth
);
440 memcpy( alpha_out
, alpha_in
, realwidth
);
441 memcpy( u_out
, u_in
, realwidth
);
442 memcpy( v_out
, v_in
, realwidth
);
445 alpha_in
+= pv
->width
;
449 lum_out
+= realwidth
;
450 alpha_out
+= realwidth
;
458 static hb_buffer_t
* Decode( hb_work_object_t
* w
)
460 hb_work_private_t
* pv
= w
->private_data
;
465 uint8_t * buf_raw
= NULL
;
466 hb_job_t
* job
= pv
->job
;
468 /* Get infos about the subtitle */
471 if( job
->indepth_scan
|| ( job
->subtitle_force
&& pv
->pts_forced
== 0 ) )
474 * Don't encode subtitles when doing a scan.
476 * When forcing subtitles, ignore all those that don't
477 * have the forced flag set.
482 /* Do the actual decoding now */
483 buf_raw
= malloc( ( pv
->width
* pv
->height
) * 4 );
485 #define GET_NEXT_NIBBLE code = ( code << 4 ) | ( ( ( *offset & 1 ) ? \
486 ( pv->buf[((*offset)>>1)] & 0xF ) : ( pv->buf[((*offset)>>1)] >> 4 ) ) ); \
489 offsets
[0] = pv
->offsets
[0] * 2;
490 offsets
[1] = pv
->offsets
[1] * 2;
492 for( line
= 0; line
< pv
->height
; line
++ )
494 /* Select even or odd field */
495 offset
= ( line
& 1 ) ? &offsets
[1] : &offsets
[0];
497 for( col
= 0; col
< pv
->width
; col
+= code
>> 2 )
499 uint8_t * lum
, * alpha
, * chromaU
, * chromaV
;
515 code
|= ( pv
->width
- col
) << 2;
522 alpha
= lum
+ pv
->width
* pv
->height
;
523 chromaU
= alpha
+ pv
->width
* pv
->height
;
524 chromaV
= chromaU
+ pv
->width
* pv
->height
;
526 memset( lum
+ line
* pv
->width
+ col
,
527 pv
->lum
[code
& 3], code
>> 2 );
528 memset( alpha
+ line
* pv
->width
+ col
,
529 pv
->alpha
[code
& 3], code
>> 2 );
530 memset( chromaU
+ line
* pv
->width
+ col
,
531 pv
->chromaU
[code
& 3], code
>> 2 );
532 memset( chromaV
+ line
* pv
->width
+ col
,
533 pv
->chromaV
[code
& 3], code
>> 2 );
543 /* Crop subtitle (remove transparent borders) */
544 buf
= CropSubtitle( w
, buf_raw
);