summaryrefslogtreecommitdiffstats
path: root/libhb/decsub.c
diff options
context:
space:
mode:
authorprigaux <[email protected]>2007-02-11 20:00:15 +0000
committerprigaux <[email protected]>2007-02-11 20:00:15 +0000
commita74fd5a1ec37e53fe7008f022639af6ede0e82c9 (patch)
tree0a6a32640a840b72653149aa11efa264674df976 /libhb/decsub.c
parentf45dfeb2afb1b0bf46054959e8ea9494f3b7d14f (diff)
Merge the 0.8.0_mpeg4ip branch into the trunk
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@285 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb/decsub.c')
-rw-r--r--libhb/decsub.c415
1 files changed, 0 insertions, 415 deletions
diff --git a/libhb/decsub.c b/libhb/decsub.c
deleted file mode 100644
index 3666ea3fe..000000000
--- a/libhb/decsub.c
+++ /dev/null
@@ -1,415 +0,0 @@
-/* $Id: decsub.c,v 1.12 2005/04/14 17:37:54 titer Exp $
-
- This file is part of the HandBrake source code.
- Homepage: <http://handbrake.m0k.org/>.
- It may be used under the terms of the GNU General Public License. */
-
-#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 x;
- int y;
- int width;
- int height;
-
- int offsets[2];
- uint8_t lum[4];
- uint8_t alpha[4];
-};
-
-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;
-
- pv->job = job;
- pv->pts = -1;
-
- return 0;
-}
-
-int decsubWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
- hb_buffer_t ** buf_out )
-{
- hb_work_private_t * pv = w->private_data;
- hb_buffer_t * in = *buf_in;
-
- int size_sub, size_rle;
-
- size_sub = ( in->data[0] << 8 ) | in->data[1];
- size_rle = ( in->data[2] << 8 ) | in->data[3];
-
- if( !pv->size_sub )
- {
- /* We are looking for the start of a new subtitle */
- if( size_sub && size_rle && size_sub > size_rle &&
- in->size <= size_sub )
- {
- /* Looks all right so far */
- pv->size_sub = size_sub;
- pv->size_rle = size_rle;
-
- memcpy( pv->buf, in->data, in->size );
- pv->size_got = in->size;
- pv->pts = in->start;
- }
- }
- else
- {
- /* 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 );
- pv->size_got += in->size;
- if( in->start >= 0 )
- {
- pv->pts = in->start;
- }
- }
- }
-
- *buf_out = NULL;
-
- if( pv->size_sub && pv->size_sub == pv->size_got )
- {
- /* We got a complete subtitle, decode it */
- *buf_out = Decode( w );
-
- /* Wait for the next one */
- pv->size_sub = 0;
- pv->size_got = 0;
- pv->size_rle = 0;
- pv->pts = -1;
- }
-
- return HB_WORK_OK;
-}
-
-void decsubClose( hb_work_object_t * w )
-{
- free( w->private_data );
-}
-
-hb_work_object_t hb_decsub =
-{
- WORK_DECSUB,
- "Subtitle decoder",
- decsubInit,
- decsubWork,
- decsubClose
-};
-
-
-/***********************************************************************
- * ParseControls
- ***********************************************************************
- * Get the start and end dates (relative to the PTS from the PES
- * header), the width and height of the subpicture and the colors and
- * alphas used in it
- **********************************************************************/
-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;
-
- int i;
- int command;
- int date, next;
-
- pv->pts_start = 0;
- pv->pts_stop = 0;
-
- 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;
-
- for( ;; )
- {
- command = pv->buf[i++];
-
- if( command == 0xFF )
- {
- break;
- }
-
- switch( command )
- {
- case 0x00:
- break;
-
- case 0x01:
- pv->pts_start = pv->pts + date * 900;
- break;
-
- case 0x02:
- pv->pts_stop = pv->pts + date * 900;
- break;
-
- case 0x03:
- {
- 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;
-
- for( j = 0; j < 4; j++ )
- {
- uint32_t color = title->palette[colors[j]];
- pv->lum[3-j] = (color>>16) & 0xff;
- }
- i += 2;
- break;
- }
- case 0x04:
- {
- 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;
- i += 2;
- break;
- }
- case 0x05:
- {
- 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;
- i += 6;
- break;
- }
- case 0x06:
- {
- 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;
- break;
- }
- }
- }
-
- if( i > next )
- {
- break;
- }
- i = next;
- }
-
- if( !pv->pts_stop )
- {
- /* Show it for 3 seconds */
- pv->pts_stop = pv->pts_start + 3 * 90000;
- }
-}
-
-/***********************************************************************
- * CropSubtitle
- ***********************************************************************
- * Given a raw decoded subtitle, detects transparent borders and
- * returns a cropped subtitle in a hb_buffer_t ready to be used by
- * the renderer, or NULL if the subtitle was completely transparent
- **********************************************************************/
-static int LineIsTransparent( hb_work_object_t * w, uint8_t * p )
-{
- hb_work_private_t * pv = w->private_data;
- int i;
- for( i = 0; i < pv->width; i++ )
- {
- if( p[i] )
- {
- return 0;
- }
- }
- return 1;
-}
-static int ColumnIsTransparent( hb_work_object_t * w, uint8_t * p )
-{
- hb_work_private_t * pv = w->private_data;
- int i;
- for( i = 0; i < pv->height; i++ )
- {
- if( p[i*pv->width] )
- {
- return 0;
- }
- }
- return 1;
-}
-static hb_buffer_t * CropSubtitle( hb_work_object_t * w, uint8_t * raw )
-{
- hb_work_private_t * pv = w->private_data;
- int i;
- int crop[4] = { -1,-1,-1,-1 };
- uint8_t * alpha;
- int realwidth, realheight;
- hb_buffer_t * buf;
- uint8_t * lum_in, * lum_out, * alpha_in, * alpha_out;
-
- alpha = raw + pv->width * pv->height;
-
- /* Top */
- for( i = 0; i < pv->height; i++ )
- {
- if( !LineIsTransparent( w, &alpha[i*pv->width] ) )
- {
- crop[0] = i;
- break;
- }
- }
-
- if( crop[0] < 0 )
- {
- /* Empty subtitle */
- return NULL;
- }
-
- /* Bottom */
- for( i = pv->height - 1; i >= 0; i-- )
- {
- if( !LineIsTransparent( w, &alpha[i*pv->width] ) )
- {
- crop[1] = i;
- break;
- }
- }
-
- /* Left */
- for( i = 0; i < pv->width; i++ )
- {
- if( !ColumnIsTransparent( w, &alpha[i] ) )
- {
- crop[2] = i;
- break;
- }
- }
-
- /* Right */
- for( i = pv->width - 1; i >= 0; i-- )
- {
- if( !ColumnIsTransparent( w, &alpha[i] ) )
- {
- crop[3] = i;
- break;
- }
- }
-
- realwidth = crop[3] - crop[2] + 1;
- realheight = crop[1] - crop[0] + 1;
-
- buf = hb_buffer_init( realwidth * realheight * 2 );
- buf->start = pv->pts_start;
- buf->stop = pv->pts_stop;
- buf->x = pv->x + crop[2];
- buf->y = pv->y + crop[0];
- buf->width = realwidth;
- buf->height = realheight;
-
- lum_in = raw + crop[0] * pv->width + crop[2];
- alpha_in = lum_in + pv->width * pv->height;
- lum_out = buf->data;
- alpha_out = lum_out + realwidth * realheight;
-
- for( i = 0; i < realheight; i++ )
- {
- memcpy( lum_out, lum_in, realwidth );
- memcpy( alpha_out, alpha_in, realwidth );
- lum_in += pv->width;
- alpha_in += pv->width;
- lum_out += realwidth;
- alpha_out += realwidth;
- }
-
- return buf;
-}
-
-static hb_buffer_t * Decode( hb_work_object_t * w )
-{
- hb_work_private_t * pv = w->private_data;
- int code, line, col;
- int offsets[2];
- int * offset;
- hb_buffer_t * buf;
- uint8_t * buf_raw = NULL;
-
- /* Get infos about the subtitle */
- ParseControls( w );
-
- /* Do the actual decoding now */
- buf_raw = malloc( pv->width * pv->height * 2 );
-
-#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;
-
- for( line = 0; line < pv->height; line++ )
- {
- /* Select even or odd field */
- offset = ( line & 1 ) ? &offsets[1] : &offsets[0];
-
- for( col = 0; col < pv->width; col += code >> 2 )
- {
- uint8_t * lum, * alpha;
-
- code = 0;
- GET_NEXT_NIBBLE;
- if( code < 0x4 )
- {
- GET_NEXT_NIBBLE;
- if( code < 0x10 )
- {
- GET_NEXT_NIBBLE;
- if( code < 0x40 )
- {
- GET_NEXT_NIBBLE;
- if( code < 0x100 )
- {
- /* End of line */
- code |= ( pv->width - col ) << 2;
- }
- }
- }
- }
-
- lum = buf_raw;
- alpha = lum + 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 );
- }
-
- /* Byte-align */
- if( *offset & 1 )
- {
- (*offset)++;
- }
- }
-
- /* Crop subtitle (remove transparent borders) */
- buf = CropSubtitle( w, buf_raw );
-
- free( buf_raw );
-
- return buf;
-}