OSDN Git Service

MacGui: Allow up to 320 kbps bitrate for stereo and 768 kbps for 6 channel discrete...
[handbrake-jp/handbrake-jp-git.git] / libhb / decvobsub.c
1 /* $Id: decsub.c,v 1.12 2005/04/14 17:37:54 titer Exp $
2
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. */
6
7 #include "hb.h"
8
9 struct hb_work_private_s
10 {
11     hb_job_t    * job;
12
13     hb_buffer_t * buf;
14     int           size_sub;
15     int           size_got;
16     int           size_rle;
17     int64_t       pts;
18     int64_t       pts_start;
19     int64_t       pts_stop;
20     int           pts_forced;
21     int           x;
22     int           y;
23     int           width;
24     int           height;
25     int           stream_id;
26
27     int           offsets[2];
28     uint8_t       lum[4];
29     uint8_t       chromaU[4];
30     uint8_t       chromaV[4];
31     uint8_t       alpha[4];
32 };
33
34 static hb_buffer_t * Decode( hb_work_object_t * );
35
36 int decsubInit( hb_work_object_t * w, hb_job_t * job )
37 {
38     hb_work_private_t * pv;
39
40     pv              = calloc( 1, sizeof( hb_work_private_t ) );
41     w->private_data = pv;
42
43     pv->job = job;
44     pv->pts = -1;
45
46     return 0;
47 }
48
49 int decsubWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
50                 hb_buffer_t ** buf_out )
51 {
52     hb_work_private_t * pv = w->private_data;
53     hb_buffer_t * in = *buf_in;
54     int size_sub, size_rle;
55
56     if ( in->size <= 0 )
57     {
58         /* EOF on input stream - send it downstream & say that we're done */
59         *buf_out = in;
60         *buf_in = NULL;
61         return HB_WORK_DONE;
62     }
63
64     pv->stream_id = in->id;
65
66     size_sub = ( in->data[0] << 8 ) | in->data[1];
67     size_rle = ( in->data[2] << 8 ) | in->data[3];
68
69     if( !pv->size_sub )
70     {
71         /* We are looking for the start of a new subtitle */
72         if( size_sub && size_rle && size_sub > size_rle &&
73             in->size <= size_sub )
74         {
75             /* Looks all right so far */
76             pv->size_sub = size_sub;
77             pv->size_rle = size_rle;
78
79             pv->buf      = hb_buffer_init( 0xFFFF );
80             memcpy( pv->buf->data, in->data, in->size );
81             pv->buf->id = in->id;
82             pv->buf->sequence = in->sequence;
83             pv->size_got = in->size;
84             pv->pts      = in->start;
85         }
86     }
87     else
88     {
89         /* We are waiting for the end of the current subtitle */
90         if( in->size <= pv->size_sub - pv->size_got )
91         {
92             memcpy( pv->buf->data + pv->size_got, in->data, in->size );
93             pv->buf->id = in->id;
94             pv->buf->sequence = in->sequence;
95             pv->size_got += in->size;
96             if( in->start >= 0 )
97             {
98                 pv->pts = in->start;
99             }
100         }
101         else
102         {
103             // bad size, must have lost sync
104             // force re-sync
105             if ( pv->buf != NULL )
106                 hb_buffer_close( &pv->buf );
107             pv->size_sub = 0;
108         }
109
110     }
111
112     *buf_out = NULL;
113
114     if( pv->size_sub && pv->size_sub == pv->size_got )
115     {
116         pv->buf->size = pv->size_sub;
117
118         /* We got a complete subtitle, decode it */
119         *buf_out = Decode( w );
120
121         if( buf_out && *buf_out )
122         {
123             (*buf_out)->id = in->id;
124             (*buf_out)->sequence = in->sequence;
125         }
126
127         /* Wait for the next one */
128         pv->size_sub = 0;
129         pv->size_got = 0;
130         pv->size_rle = 0;
131         pv->pts      = -1;
132     }
133
134     return HB_WORK_OK;
135 }
136
137 void decsubClose( hb_work_object_t * w )
138 {
139     hb_work_private_t * pv = w->private_data;
140
141     if ( pv->buf )
142         hb_buffer_close( &pv->buf );
143     free( w->private_data );
144 }
145
146 hb_work_object_t hb_decvobsub =
147 {
148     WORK_DECVOBSUB,
149     "VOBSUB decoder",
150     decsubInit,
151     decsubWork,
152     decsubClose
153 };
154
155
156 /***********************************************************************
157  * ParseControls
158  ***********************************************************************
159  * Get the start and end dates (relative to the PTS from the PES
160  * header), the width and height of the subpicture and the colors and
161  * alphas used in it
162  **********************************************************************/
163 static void ParseControls( hb_work_object_t * w )
164 {
165     hb_work_private_t * pv = w->private_data;
166     hb_job_t * job = pv->job;
167     hb_title_t * title = job->title;
168     hb_subtitle_t * subtitle;
169     uint8_t * buf = pv->buf->data;
170
171     int i, n;
172     int command;
173     int date, next;
174
175     pv->pts_start = 0;
176     pv->pts_stop  = 0;
177     pv->pts_forced  = 0;
178
179     pv->alpha[3] = 0;
180     pv->alpha[2] = 0;
181     pv->alpha[1] = 0;
182     pv->alpha[0] = 0;
183
184     for( i = pv->size_rle; ; )
185     {
186         date = ( buf[i] << 8 ) | buf[i+1]; i += 2;
187         next = ( buf[i] << 8 ) | buf[i+1]; i += 2;
188
189         for( ;; )
190         {
191             command = buf[i++];
192
193             /*
194              * There are eight commands available for
195              * Sub-Pictures. The first SP_DCSQ should contain, as a
196              * minimum, SET_COLOR, SET_CONTR, SET_DAREA, and
197              * SET_DSPXA
198              */
199
200             if( command == 0xFF ) // 0xFF - CMD_END - ends one SP_DCSQ
201             {
202                 break;
203             }
204
205             switch( command )
206             {
207                 case 0x00: // 0x00 - FSTA_DSP - Forced Start Display, no arguments
208                     pv->pts_start = pv->pts + date * 900;
209                     pv->pts_forced = 1;
210
211                     /*
212                      * If we are doing a subtitle scan then note down
213                      */
214                     if( job->indepth_scan )
215                     {
216                         for( n=0; n < hb_list_count(title->list_subtitle); n++ )
217                         {
218                             subtitle = hb_list_item( title->list_subtitle, n);
219                             if( pv->stream_id == subtitle->id ) {
220                                 /*
221                                  * A hit, count it.
222                                  */
223                                 subtitle->forced_hits++;
224                             }
225                         }
226                     }
227                     break;
228
229                 case 0x01: // 0x01 - STA_DSP - Start Display, no arguments
230                     pv->pts_start = pv->pts + date * 900;
231                     pv->pts_forced  = 0;
232                     break;
233
234                 case 0x02: // 0x02 - STP_DSP - Stop Display, no arguments
235                     if(!pv->pts_stop)
236                         pv->pts_stop = pv->pts + date * 900;
237                     break;
238
239                 case 0x03: // 0x03 - SET_COLOR - Set Colour indices
240                 {
241                     /*
242                      * SET_COLOR - provides four indices into the CLUT
243                      * for the current PGC to associate with the four
244                      * pixel values
245                      */
246                     int colors[4];
247                     int j;
248
249                     colors[0] = (buf[i+0]>>4)&0x0f;
250                     colors[1] = (buf[i+0])&0x0f;
251                     colors[2] = (buf[i+1]>>4)&0x0f;
252                     colors[3] = (buf[i+1])&0x0f;
253
254                     for( j = 0; j < 4; j++ )
255                     {
256                         /*
257                          * Not sure what is happening here, in theory
258                          * the palette is in YCbCr. And we want YUV.
259                          *
260                          * However it looks more like YCrCb (according
261                          * to pgcedit). And the scalers for YCrCb don't
262                          * work, but I get the right colours by doing
263                          * no conversion.
264                          */
265                         uint32_t color = title->palette[colors[j]];
266                         uint8_t Cr, Cb, y;
267                         y = (color>>16) & 0xff;
268                         Cr = (color>>8) & 0xff;
269                         Cb = (color) & 0xff;
270                         pv->lum[3-j] = y;
271                         pv->chromaU[3-j] = Cb;
272                         pv->chromaV[3-j] = Cr;
273                         /* hb_log("color[%d] y = %d, u = %d, v = %d",
274                                3-j,
275                                pv->lum[3-j],
276                                pv->chromaU[3-j],
277                                pv->chromaV[3-j]);
278                         */
279                     }
280                     i += 2;
281                     break;
282                 }
283                 case 0x04: // 0x04 - SET_CONTR - Set Contrast
284                 {
285                     /*
286                      * SET_CONTR - directly provides the four contrast
287                      * (alpha blend) values to associate with the four
288                      * pixel values
289                      */
290                     uint8_t    alpha[4];
291
292                     alpha[3] = (buf[i+0]>>4)&0x0f;
293                     alpha[2] = (buf[i+0])&0x0f;
294                     alpha[1] = (buf[i+1]>>4)&0x0f;
295                     alpha[0] = (buf[i+1])&0x0f;
296
297
298                     int lastAlpha = pv->alpha[3] + pv->alpha[2] + pv->alpha[1] + pv->alpha[0];
299                     int currAlpha = alpha[3] + alpha[2] + alpha[1] + alpha[0];
300
301                     // fading-in, save the highest alpha value
302                     if( currAlpha > lastAlpha )
303                     {
304                         pv->alpha[3] = alpha[3];
305                         pv->alpha[2] = alpha[2];
306                         pv->alpha[1] = alpha[1];
307                         pv->alpha[0] = alpha[0];
308                     }
309
310                     // fading-out
311                     if( currAlpha < lastAlpha && !pv->pts_stop )
312                     {
313                         pv->pts_stop = pv->pts + date * 900;
314                     }
315
316                     i += 2;
317                     break;
318                 }
319                 case 0x05: // 0x05 - SET_DAREA - defines the display area
320                 {
321                     pv->x     = (buf[i+0]<<4) | ((buf[i+1]>>4)&0x0f);
322                     pv->width = (((buf[i+1]&0x0f)<<8)| buf[i+2]) - pv->x + 1;
323                     pv->y     = (buf[i+3]<<4)| ((buf[i+4]>>4)&0x0f);
324                     pv->height = (((buf[i+4]&0x0f)<<8)| buf[i+5]) - pv->y + 1;
325                     i += 6;
326                     break;
327                 }
328                 case 0x06: // 0x06 - SET_DSPXA - defines the pixel data addresses
329                 {
330                     pv->offsets[0] = ( buf[i] << 8 ) | buf[i+1]; i += 2;
331                     pv->offsets[1] = ( buf[i] << 8 ) | buf[i+1]; i += 2;
332                     break;
333                 }
334             }
335         }
336
337
338
339         if( i > next )
340         {
341             break;
342         }
343         i = next;
344     }
345
346     if( !pv->pts_stop )
347     {
348         /* Show it for 3 seconds */
349         pv->pts_stop = pv->pts_start + 3 * 90000;
350     }
351 }
352
353 /***********************************************************************
354  * CropSubtitle
355  ***********************************************************************
356  * Given a raw decoded subtitle, detects transparent borders and
357  * returns a cropped subtitle in a hb_buffer_t ready to be used by
358  * the renderer, or NULL if the subtitle was completely transparent
359  **********************************************************************/
360 static int LineIsTransparent( hb_work_object_t * w, uint8_t * p )
361 {
362     hb_work_private_t * pv = w->private_data;
363     int i;
364     for( i = 0; i < pv->width; i++ )
365     {
366         if( p[i] )
367         {
368             return 0;
369         }
370     }
371     return 1;
372 }
373 static int ColumnIsTransparent( hb_work_object_t * w, uint8_t * p )
374 {
375     hb_work_private_t * pv = w->private_data;
376     int i;
377     for( i = 0; i < pv->height; i++ )
378     {
379         if( p[i*pv->width] )
380         {
381             return 0;
382         }
383     }
384     return 1;
385 }
386 static hb_buffer_t * CropSubtitle( hb_work_object_t * w, uint8_t * raw )
387 {
388     hb_work_private_t * pv = w->private_data;
389     int i;
390     int crop[4] = { -1,-1,-1,-1 };
391     uint8_t * alpha;
392     int realwidth, realheight;
393     hb_buffer_t * buf;
394     uint8_t * lum_in, * lum_out, * alpha_in, * alpha_out;
395     uint8_t * u_in, * u_out, * v_in, * v_out;
396
397     alpha = raw + pv->width * pv->height;
398
399     /* Top */
400     for( i = 0; i < pv->height; i++ )
401     {
402         if( !LineIsTransparent( w, &alpha[i*pv->width] ) )
403         {
404             crop[0] = i;
405             break;
406         }
407     }
408
409     if( crop[0] < 0 )
410     {
411         /* Empty subtitle */
412         return NULL;
413     }
414
415     /* Bottom */
416     for( i = pv->height - 1; i >= 0; i-- )
417     {
418         if( !LineIsTransparent( w, &alpha[i*pv->width] ) )
419         {
420             crop[1] = i;
421             break;
422         }
423     }
424
425     /* Left */
426     for( i = 0; i < pv->width; i++ )
427     {
428         if( !ColumnIsTransparent( w, &alpha[i] ) )
429         {
430             crop[2] = i;
431             break;
432         }
433     }
434
435     /* Right */
436     for( i = pv->width - 1; i >= 0; i-- )
437     {
438         if( !ColumnIsTransparent( w, &alpha[i] ) )
439         {
440             crop[3] = i;
441             break;
442         }
443     }
444
445     realwidth  = crop[3] - crop[2] + 1;
446     realheight = crop[1] - crop[0] + 1;
447
448     buf         = hb_buffer_init( realwidth * realheight * 4 );
449     buf->start  = pv->pts_start;
450     buf->stop   = pv->pts_stop;
451     buf->x      = pv->x + crop[2];
452     buf->y      = pv->y + crop[0];
453     buf->width  = realwidth;
454     buf->height = realheight;
455
456     lum_in    = raw + crop[0] * pv->width + crop[2];
457     alpha_in  = lum_in + pv->width * pv->height;
458     u_in      = alpha_in + pv->width * pv->height;
459     v_in      = u_in + pv->width * pv->height;
460
461     lum_out   = buf->data;
462     alpha_out = lum_out + realwidth * realheight;
463     u_out     = alpha_out + realwidth * realheight;
464     v_out     = u_out + realwidth * realheight;
465
466     for( i = 0; i < realheight; i++ )
467     {
468         memcpy( lum_out, lum_in, realwidth );
469         memcpy( alpha_out, alpha_in, realwidth );
470         memcpy( u_out, u_in, realwidth );
471         memcpy( v_out, v_in, realwidth );
472
473         lum_in    += pv->width;
474         alpha_in  += pv->width;
475         u_in      += pv->width;
476         v_in      += pv->width;
477
478         lum_out   += realwidth;
479         alpha_out += realwidth;
480         u_out     += realwidth;
481         v_out     += realwidth;
482     }
483
484     return buf;
485 }
486
487 static hb_buffer_t * Decode( hb_work_object_t * w )
488 {
489     hb_work_private_t * pv = w->private_data;
490     int code, line, col;
491     int offsets[2];
492     int * offset;
493     hb_buffer_t * buf;
494     uint8_t * buf_raw = NULL;
495     hb_job_t * job = pv->job;
496
497     /* Get infos about the subtitle */
498     ParseControls( w );
499
500     if( job->indepth_scan || ( w->subtitle->config.force && pv->pts_forced == 0 ) )
501     {
502         /*
503          * Don't encode subtitles when doing a scan.
504          *
505          * When forcing subtitles, ignore all those that don't
506          * have the forced flag set.
507          */
508         hb_buffer_close( &pv->buf );
509         return NULL;
510     }
511
512     if (w->subtitle->config.dest == PASSTHRUSUB)
513     {
514         pv->buf->start  = pv->pts_start;
515         pv->buf->stop   = pv->pts_stop;
516         buf = pv->buf;
517         pv->buf = NULL;
518         return buf;
519     }
520
521     /* Do the actual decoding now */
522     buf_raw = malloc( ( pv->width * pv->height ) * 4 );
523
524 #define GET_NEXT_NIBBLE code = ( code << 4 ) | ( ( ( *offset & 1 ) ? \
525 ( pv->buf->data[((*offset)>>1)] & 0xF ) : ( pv->buf->data[((*offset)>>1)] >> 4 ) ) ); \
526 (*offset)++
527
528     offsets[0] = pv->offsets[0] * 2;
529     offsets[1] = pv->offsets[1] * 2;
530
531     for( line = 0; line < pv->height; line++ )
532     {
533         /* Select even or odd field */
534         offset = ( line & 1 ) ? &offsets[1] : &offsets[0];
535
536         for( col = 0; col < pv->width; col += code >> 2 )
537         {
538             uint8_t * lum, * alpha,  * chromaU, * chromaV;
539
540             code = 0;
541             GET_NEXT_NIBBLE;
542             if( code < 0x4 )
543             {
544                 GET_NEXT_NIBBLE;
545                 if( code < 0x10 )
546                 {
547                     GET_NEXT_NIBBLE;
548                     if( code < 0x40 )
549                     {
550                         GET_NEXT_NIBBLE;
551                         if( code < 0x100 )
552                         {
553                             /* End of line */
554                             code |= ( pv->width - col ) << 2;
555                         }
556                     }
557                 }
558             }
559
560             lum   = buf_raw;
561             alpha = lum + pv->width * pv->height;
562             chromaU = alpha + pv->width * pv->height;
563             chromaV = chromaU + pv->width * pv->height;
564
565             memset( lum + line * pv->width + col,
566                     pv->lum[code & 3], code >> 2 );
567             memset( alpha + line * pv->width + col,
568                     pv->alpha[code & 3], code >> 2 );
569             memset( chromaU + line * pv->width + col,
570                     pv->chromaU[code & 3], code >> 2 );
571             memset( chromaV + line * pv->width + col,
572                     pv->chromaV[code & 3], code >> 2 );
573         }
574
575         /* Byte-align */
576         if( *offset & 1 )
577         {
578             (*offset)++;
579         }
580     }
581
582     hb_buffer_close( &pv->buf );
583
584     /* Crop subtitle (remove transparent borders) */
585     buf = CropSubtitle( w, buf_raw );
586
587     free( buf_raw );
588
589     return buf;
590 }