X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=libhb%2Fdecsub.c;h=98ffa1a0d7ad9008a951aa84604d9883431dcd7c;hb=27f82628e116613e7e333a52d75b7aebca7e7fb8;hp=3666ea3fe3ec56f311e791736ac1baf57edfa99e;hpb=52d45181a7d1df6016d32c1842622660224538e0;p=handbrake-jp%2Fhandbrake-jp-git.git diff --git a/libhb/decsub.c b/libhb/decsub.c index 3666ea3f..98ffa1a0 100644 --- a/libhb/decsub.c +++ b/libhb/decsub.c @@ -1,7 +1,7 @@ /* $Id: decsub.c,v 1.12 2005/04/14 17:37:54 titer Exp $ This file is part of the HandBrake source code. - Homepage: . + Homepage: . It may be used under the terms of the GNU General Public License. */ #include "hb.h" @@ -17,13 +17,17 @@ struct hb_work_private_s 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]; }; @@ -32,7 +36,7 @@ static hb_buffer_t * Decode( hb_work_object_t * ); int decsubInit( hb_work_object_t * w, hb_job_t * job ) { hb_work_private_t * pv; - + pv = calloc( 1, sizeof( hb_work_private_t ) ); w->private_data = pv; @@ -47,9 +51,18 @@ int decsubWork( hb_work_object_t * w, hb_buffer_t ** buf_in, { hb_work_private_t * pv = w->private_data; hb_buffer_t * in = *buf_in; - int size_sub, size_rle; + if ( in->size <= 0 ) + { + /* EOF on input stream - send it downstream & say that we're done */ + *buf_out = in; + *buf_in = NULL; + return HB_WORK_DONE; + } + + pv->stream_id = in->id; + size_sub = ( in->data[0] << 8 ) | in->data[1]; size_rle = ( in->data[2] << 8 ) | in->data[3]; @@ -89,6 +102,11 @@ int decsubWork( hb_work_object_t * w, hb_buffer_t ** buf_in, /* We got a complete subtitle, decode it */ *buf_out = Decode( w ); + if( buf_out && *buf_out ) + { + (*buf_out)->sequence = in->sequence; + } + /* Wait for the next one */ pv->size_sub = 0; pv->size_got = 0; @@ -126,13 +144,20 @@ static void ParseControls( hb_work_object_t * w ) hb_work_private_t * pv = w->private_data; hb_job_t * job = pv->job; hb_title_t * title = job->title; + hb_subtitle_t * subtitle; - int i; + int i, n; int command; int date, next; pv->pts_start = 0; pv->pts_stop = 0; + pv->pts_forced = 0; + + pv->alpha[3] = 0; + pv->alpha[2] = 0; + pv->alpha[1] = 0; + pv->alpha[0] = 0; for( i = pv->size_rle; ; ) { @@ -143,26 +168,59 @@ static void ParseControls( hb_work_object_t * w ) { command = pv->buf[i++]; - if( command == 0xFF ) + /* + * There are eight commands available for + * Sub-Pictures. The first SP_DCSQ should contain, as a + * minimum, SET_COLOR, SET_CONTR, SET_DAREA, and + * SET_DSPXA + */ + + if( command == 0xFF ) // 0xFF - CMD_END - ends one SP_DCSQ { break; } switch( command ) { - case 0x00: + case 0x00: // 0x00 - FSTA_DSP - Forced Start Display, no arguments + pv->pts_start = pv->pts + date * 900; + pv->pts_forced = 1; + + /* + * If we are doing a subtitle scan then note down + */ + if( job->indepth_scan ) + { + for( n=0; n < hb_list_count(title->list_subtitle); n++ ) + { + subtitle = hb_list_item( title->list_subtitle, n); + if( pv->stream_id == subtitle->id ) { + /* + * A hit, count it. + */ + subtitle->forced_hits++; + } + } + } break; - case 0x01: + case 0x01: // 0x01 - STA_DSP - Start Display, no arguments pv->pts_start = pv->pts + date * 900; + pv->pts_forced = 0; break; - case 0x02: - pv->pts_stop = pv->pts + date * 900; + case 0x02: // 0x02 - STP_DSP - Stop Display, no arguments + if(!pv->pts_stop) + pv->pts_stop = pv->pts + date * 900; break; - case 0x03: + case 0x03: // 0x03 - SET_COLOR - Set Colour indices { + /* + * SET_COLOR - provides four indices into the CLUT + * for the current PGC to associate with the four + * pixel values + */ int colors[4]; int j; @@ -173,22 +231,70 @@ static void ParseControls( hb_work_object_t * w ) for( j = 0; j < 4; j++ ) { + /* + * Not sure what is happening here, in theory + * the palette is in YCbCr. And we want YUV. + * + * However it looks more like YCrCb (according + * to pgcedit). And the scalers for YCrCb don't + * work, but I get the right colours by doing + * no conversion. + */ uint32_t color = title->palette[colors[j]]; - pv->lum[3-j] = (color>>16) & 0xff; + uint8_t Cr, Cb, y; + y = (color>>16) & 0xff; + Cr = (color>>8) & 0xff; + Cb = (color) & 0xff; + pv->lum[3-j] = y; + pv->chromaU[3-j] = Cb; + pv->chromaV[3-j] = Cr; + /* hb_log("color[%d] y = %d, u = %d, v = %d", + 3-j, + pv->lum[3-j], + pv->chromaU[3-j], + pv->chromaV[3-j]); + */ } i += 2; break; } - case 0x04: + case 0x04: // 0x04 - SET_CONTR - Set Contrast { - pv->alpha[3] = (pv->buf[i+0]>>4)&0x0f; - pv->alpha[2] = (pv->buf[i+0])&0x0f; - pv->alpha[1] = (pv->buf[i+1]>>4)&0x0f; - pv->alpha[0] = (pv->buf[i+1])&0x0f; + /* + * SET_CONTR - directly provides the four contrast + * (alpha blend) values to associate with the four + * pixel values + */ + 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; + + + int lastAlpha = pv->alpha[3] + pv->alpha[2] + pv->alpha[1] + pv->alpha[0]; + int currAlpha = alpha[3] + alpha[2] + alpha[1] + alpha[0]; + + // fading-in, save the highest alpha value + if( currAlpha > lastAlpha ) + { + pv->alpha[3] = alpha[3]; + pv->alpha[2] = alpha[2]; + pv->alpha[1] = alpha[1]; + pv->alpha[0] = alpha[0]; + } + + // fading-out + if( currAlpha < lastAlpha && !pv->pts_stop ) + { + pv->pts_stop = pv->pts + date * 900; + } + i += 2; break; } - case 0x05: + 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; @@ -197,7 +303,7 @@ static void ParseControls( hb_work_object_t * w ) i += 6; break; } - case 0x06: + 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; @@ -206,6 +312,8 @@ static void ParseControls( hb_work_object_t * w ) } } + + if( i > next ) { break; @@ -262,6 +370,7 @@ static hb_buffer_t * CropSubtitle( hb_work_object_t * w, uint8_t * raw ) int realwidth, realheight; hb_buffer_t * buf; uint8_t * lum_in, * lum_out, * alpha_in, * alpha_out; + uint8_t * u_in, * u_out, * v_in, * v_out; alpha = raw + pv->width * pv->height; @@ -314,7 +423,7 @@ static hb_buffer_t * CropSubtitle( hb_work_object_t * w, uint8_t * raw ) realwidth = crop[3] - crop[2] + 1; realheight = crop[1] - crop[0] + 1; - buf = hb_buffer_init( realwidth * realheight * 2 ); + buf = hb_buffer_init( realwidth * realheight * 4 ); buf->start = pv->pts_start; buf->stop = pv->pts_stop; buf->x = pv->x + crop[2]; @@ -324,17 +433,30 @@ static hb_buffer_t * CropSubtitle( hb_work_object_t * w, uint8_t * raw ) lum_in = raw + crop[0] * pv->width + crop[2]; alpha_in = lum_in + pv->width * pv->height; + u_in = alpha_in + pv->width * pv->height; + v_in = u_in + pv->width * pv->height; + lum_out = buf->data; alpha_out = lum_out + realwidth * realheight; + u_out = alpha_out + realwidth * realheight; + v_out = u_out + realwidth * realheight; for( i = 0; i < realheight; i++ ) { memcpy( lum_out, lum_in, realwidth ); memcpy( alpha_out, alpha_in, realwidth ); + memcpy( u_out, u_in, realwidth ); + memcpy( v_out, v_in, realwidth ); + lum_in += pv->width; alpha_in += pv->width; + u_in += pv->width; + v_in += pv->width; + lum_out += realwidth; alpha_out += realwidth; + u_out += realwidth; + v_out += realwidth; } return buf; @@ -348,17 +470,29 @@ static hb_buffer_t * Decode( hb_work_object_t * w ) int * offset; hb_buffer_t * buf; uint8_t * buf_raw = NULL; + hb_job_t * job = pv->job; /* Get infos about the subtitle */ ParseControls( w ); + if( job->indepth_scan || ( job->subtitle_force && pv->pts_forced == 0 ) ) + { + /* + * Don't encode subtitles when doing a scan. + * + * When forcing subtitles, ignore all those that don't + * have the forced flag set. + */ + return NULL; + } + /* Do the actual decoding now */ - buf_raw = malloc( pv->width * pv->height * 2 ); + 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 ) ) ); \ (*offset)++ - + offsets[0] = pv->offsets[0] * 2; offsets[1] = pv->offsets[1] * 2; @@ -369,7 +503,7 @@ static hb_buffer_t * Decode( hb_work_object_t * w ) for( col = 0; col < pv->width; col += code >> 2 ) { - uint8_t * lum, * alpha; + uint8_t * lum, * alpha, * chromaU, * chromaV; code = 0; GET_NEXT_NIBBLE; @@ -393,10 +527,17 @@ static hb_buffer_t * Decode( hb_work_object_t * w ) lum = buf_raw; alpha = lum + pv->width * pv->height; + chromaU = alpha + pv->width * pv->height; + chromaV = chromaU + pv->width * pv->height; + memset( lum + line * pv->width + col, pv->lum[code & 3], code >> 2 ); memset( alpha + line * pv->width + col, pv->alpha[code & 3], code >> 2 ); + memset( chromaU + line * pv->width + col, + pv->chromaU[code & 3], code >> 2 ); + memset( chromaV + line * pv->width + col, + pv->chromaV[code & 3], code >> 2 ); } /* Byte-align */