OSDN Git Service

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