X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=libhb%2Fdecvobsub.c;h=3b5177ca381fc08a953fd4eabaeab91cf82f71fa;hb=4f0019f03c2e85e8634150ff0c9a31bee6d35ce5;hp=102d18fe763de5b656d8e827000c8be4652a01cf;hpb=64db42bb1203f530ea328a80d105054ea40c1e84;p=handbrake-jp%2Fhandbrake-jp-git.git diff --git a/libhb/decvobsub.c b/libhb/decvobsub.c index 102d18fe..3b5177ca 100644 --- a/libhb/decvobsub.c +++ b/libhb/decvobsub.c @@ -4,31 +4,51 @@ Homepage: . It may be used under the terms of the GNU General Public License. */ +/* + * Decoder for DVD bitmap subtitles, also known as "VOB subtitles" within the HandBrake source code. + * + * Input format of the subtitle packets is described here: + * http://sam.zoy.org/writings/dvd/subtitles/ + * + * An auxiliary input is the color palette lookup table, in 'subtitle->palette'. + * The demuxer implementation must fill out this table appropriately. + * - In the case of a true DVD input, the palette is read from the IFO file. + * - In the case of an MKV file input, the palette is read from the codec private data of the subtitle track. + * + * Output format of this decoder is PICTURESUB, which is: + * struct PictureSubPacket { + * uint8_t lum[pixelCount]; + * uint8_t alpha[pixelCount]; + * uint8_t chromaU[pixelCount]; + * uint8_t chromaV[pixelCount]; + * } + */ + #include "hb.h" struct hb_work_private_s { - hb_job_t * job; - - uint8_t buf[0xFFFF]; - int size_sub; - int size_got; - int size_rle; - int64_t pts; - int64_t pts_start; - int64_t pts_stop; - int pts_forced; - int x; - int y; - int width; - int height; - int stream_id; - - int offsets[2]; - uint8_t lum[4]; - uint8_t chromaU[4]; - uint8_t chromaV[4]; - uint8_t alpha[4]; + hb_job_t * job; + + hb_buffer_t * buf; + int size_sub; + int size_got; + int size_rle; + int64_t pts; + int64_t pts_start; + int64_t pts_stop; + int pts_forced; + int x; + int y; + int width; + int height; + int stream_id; + + int offsets[2]; + uint8_t lum[4]; + uint8_t chromaU[4]; + uint8_t chromaV[4]; + uint8_t alpha[4]; }; static hb_buffer_t * Decode( hb_work_object_t * ); @@ -42,6 +62,21 @@ int decsubInit( hb_work_object_t * w, hb_job_t * job ) pv->job = job; pv->pts = -1; + + // Warn if the input color palette is empty + int paletteEmpty = 1; + int i; + for (i=0; i<16; i++) + { + if (w->subtitle->palette[i]) + { + paletteEmpty = 0; + break; + } + } + if (paletteEmpty) { + hb_log( "decvobsub: input color palette is empty; not demuxed properly?" ); + } return 0; } @@ -76,7 +111,10 @@ int decsubWork( hb_work_object_t * w, hb_buffer_t ** buf_in, pv->size_sub = size_sub; pv->size_rle = size_rle; - memcpy( pv->buf, in->data, in->size ); + pv->buf = hb_buffer_init( 0xFFFF ); + memcpy( pv->buf->data, in->data, in->size ); + pv->buf->id = in->id; + pv->buf->sequence = in->sequence; pv->size_got = in->size; pv->pts = in->start; } @@ -86,24 +124,38 @@ int decsubWork( hb_work_object_t * w, hb_buffer_t ** buf_in, /* We are waiting for the end of the current subtitle */ if( in->size <= pv->size_sub - pv->size_got ) { - memcpy( pv->buf + pv->size_got, in->data, in->size ); + memcpy( pv->buf->data + pv->size_got, in->data, in->size ); + pv->buf->id = in->id; + pv->buf->sequence = in->sequence; pv->size_got += in->size; if( in->start >= 0 ) { pv->pts = in->start; } } + else + { + // bad size, must have lost sync + // force re-sync + if ( pv->buf != NULL ) + hb_buffer_close( &pv->buf ); + pv->size_sub = 0; + } + } *buf_out = NULL; if( pv->size_sub && pv->size_sub == pv->size_got ) { + pv->buf->size = pv->size_sub; + /* We got a complete subtitle, decode it */ *buf_out = Decode( w ); if( buf_out && *buf_out ) { + (*buf_out)->id = in->id; (*buf_out)->sequence = in->sequence; } @@ -119,12 +171,16 @@ int decsubWork( hb_work_object_t * w, hb_buffer_t ** buf_in, void decsubClose( hb_work_object_t * w ) { + hb_work_private_t * pv = w->private_data; + + if ( pv->buf ) + hb_buffer_close( &pv->buf ); free( w->private_data ); } -hb_work_object_t hb_decsub = +hb_work_object_t hb_decvobsub = { - WORK_DECSUB, + WORK_DECVOBSUB, "VOBSUB decoder", decsubInit, decsubWork, @@ -145,6 +201,7 @@ static void ParseControls( hb_work_object_t * w ) hb_job_t * job = pv->job; hb_title_t * title = job->title; hb_subtitle_t * subtitle; + uint8_t * buf = pv->buf->data; int i, n; int command; @@ -161,12 +218,12 @@ static void ParseControls( hb_work_object_t * w ) for( i = pv->size_rle; ; ) { - date = ( pv->buf[i] << 8 ) | pv->buf[i+1]; i += 2; - next = ( pv->buf[i] << 8 ) | pv->buf[i+1]; i += 2; + date = ( buf[i] << 8 ) | buf[i+1]; i += 2; + next = ( buf[i] << 8 ) | buf[i+1]; i += 2; for( ;; ) { - command = pv->buf[i++]; + command = buf[i++]; /* * There are eight commands available for @@ -224,10 +281,10 @@ static void ParseControls( hb_work_object_t * w ) int colors[4]; int j; - colors[0] = (pv->buf[i+0]>>4)&0x0f; - colors[1] = (pv->buf[i+0])&0x0f; - colors[2] = (pv->buf[i+1]>>4)&0x0f; - colors[3] = (pv->buf[i+1])&0x0f; + colors[0] = (buf[i+0]>>4)&0x0f; + colors[1] = (buf[i+0])&0x0f; + colors[2] = (buf[i+1]>>4)&0x0f; + colors[3] = (buf[i+1])&0x0f; for( j = 0; j < 4; j++ ) { @@ -240,7 +297,7 @@ static void ParseControls( hb_work_object_t * w ) * work, but I get the right colours by doing * no conversion. */ - uint32_t color = title->palette[colors[j]]; + uint32_t color = w->subtitle->palette[colors[j]]; uint8_t Cr, Cb, y; y = (color>>16) & 0xff; Cr = (color>>8) & 0xff; @@ -267,10 +324,10 @@ static void ParseControls( hb_work_object_t * w ) */ uint8_t alpha[4]; - alpha[3] = (pv->buf[i+0]>>4)&0x0f; - alpha[2] = (pv->buf[i+0])&0x0f; - alpha[1] = (pv->buf[i+1]>>4)&0x0f; - alpha[0] = (pv->buf[i+1])&0x0f; + alpha[3] = (buf[i+0]>>4)&0x0f; + alpha[2] = (buf[i+0])&0x0f; + alpha[1] = (buf[i+1]>>4)&0x0f; + alpha[0] = (buf[i+1])&0x0f; int lastAlpha = pv->alpha[3] + pv->alpha[2] + pv->alpha[1] + pv->alpha[0]; @@ -296,17 +353,17 @@ static void ParseControls( hb_work_object_t * w ) } case 0x05: // 0x05 - SET_DAREA - defines the display area { - pv->x = (pv->buf[i+0]<<4) | ((pv->buf[i+1]>>4)&0x0f); - pv->width = (((pv->buf[i+1]&0x0f)<<8)| pv->buf[i+2]) - pv->x + 1; - pv->y = (pv->buf[i+3]<<4)| ((pv->buf[i+4]>>4)&0x0f); - pv->height = (((pv->buf[i+4]&0x0f)<<8)| pv->buf[i+5]) - pv->y + 1; + pv->x = (buf[i+0]<<4) | ((buf[i+1]>>4)&0x0f); + pv->width = (((buf[i+1]&0x0f)<<8)| buf[i+2]) - pv->x + 1; + pv->y = (buf[i+3]<<4)| ((buf[i+4]>>4)&0x0f); + pv->height = (((buf[i+4]&0x0f)<<8)| buf[i+5]) - pv->y + 1; i += 6; break; } case 0x06: // 0x06 - SET_DSPXA - defines the pixel data addresses { - pv->offsets[0] = ( pv->buf[i] << 8 ) | pv->buf[i+1]; i += 2; - pv->offsets[1] = ( pv->buf[i] << 8 ) | pv->buf[i+1]; i += 2; + pv->offsets[0] = ( buf[i] << 8 ) | buf[i+1]; i += 2; + pv->offsets[1] = ( buf[i] << 8 ) | buf[i+1]; i += 2; break; } } @@ -475,7 +532,7 @@ static hb_buffer_t * Decode( hb_work_object_t * w ) /* Get infos about the subtitle */ ParseControls( w ); - if( job->indepth_scan || ( job->subtitle_force && pv->pts_forced == 0 ) ) + if( job->indepth_scan || ( w->subtitle->config.force && pv->pts_forced == 0 ) ) { /* * Don't encode subtitles when doing a scan. @@ -483,14 +540,24 @@ static hb_buffer_t * Decode( hb_work_object_t * w ) * When forcing subtitles, ignore all those that don't * have the forced flag set. */ + hb_buffer_close( &pv->buf ); return NULL; } + if (w->subtitle->config.dest == PASSTHRUSUB) + { + pv->buf->start = pv->pts_start; + pv->buf->stop = pv->pts_stop; + buf = pv->buf; + pv->buf = NULL; + return buf; + } + /* Do the actual decoding now */ buf_raw = malloc( ( pv->width * pv->height ) * 4 ); #define GET_NEXT_NIBBLE code = ( code << 4 ) | ( ( ( *offset & 1 ) ? \ -( pv->buf[((*offset)>>1)] & 0xF ) : ( pv->buf[((*offset)>>1)] >> 4 ) ) ); \ +( pv->buf->data[((*offset)>>1)] & 0xF ) : ( pv->buf->data[((*offset)>>1)] >> 4 ) ) ); \ (*offset)++ offsets[0] = pv->offsets[0] * 2; @@ -547,6 +614,8 @@ static hb_buffer_t * Decode( hb_work_object_t * w ) } } + hb_buffer_close( &pv->buf ); + /* Crop subtitle (remove transparent borders) */ buf = CropSubtitle( w, buf_raw );