X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fcodec%2Fcc.c;h=c85e4d62784d9b0270e960795f69ec1018766064;hb=a294d6af04da83c1ba542448f2cd9cc5271b27c9;hp=59614a161707ed0fc6e4d332035efa9f63329242;hpb=ad77d955a5dc051976d94d6e08ee0f717ec3a938;p=vlc diff --git a/modules/codec/cc.c b/modules/codec/cc.c index 59614a1617..c85e4d6278 100644 --- a/modules/codec/cc.c +++ b/modules/codec/cc.c @@ -1,8 +1,7 @@ /***************************************************************************** - * cc608.c : CC 608/708 subtitles decoder + * cc.c : CC 608/708 subtitles decoder ***************************************************************************** - * Copyright (C) 2007 Laurent Aimar - * $Id$ + * Copyright © 2007-2010 Laurent Aimar, 2011 VLC authors and VideoLAN * * Authors: Laurent Aimar < fenrir # via.ecp.fr> * @@ -37,21 +36,14 @@ # include "config.h" #endif +#include + #include #include #include -#include - -#include -#include -#include #include -#include -#include -#include -#include -#include +#include "substext.h" /***************************************************************************** * Module descriptor. @@ -143,15 +135,12 @@ typedef struct static void Eia608Init( eia608_t * ); static bool Eia608Parse( eia608_t *h, int i_channel_selected, const uint8_t data[2] ); static char *Eia608Text( eia608_t *h, bool b_html ); -static void Eia608Exit( eia608_t * ); /* It will be enough up to 63 B frames, which is far too high for * broadcast environment */ #define CC_MAX_REORDER_SIZE (64) struct decoder_sys_t { - int i; - int i_block; block_t *pp_block[CC_MAX_REORDER_SIZE]; @@ -251,11 +240,9 @@ static void Close( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t *)p_this; decoder_sys_t *p_sys = p_dec->p_sys; - int i; - for( i = 0; i < p_sys->i_block; i++ ) + for( int i = 0; i < p_sys->i_block; i++ ) block_Release( p_sys->pp_block[i] ); - Eia608Exit( &p_sys->eia608 ); free( p_sys ); } @@ -279,7 +266,6 @@ static block_t *Pop( decoder_t *p_dec ) decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_block; int i_index; - int i; /* XXX Cc captions data are OUT OF ORDER (because we receive them in the bitstream * order (ie ordered by video picture dts) instead of the display order. * We will simulate a simple IPB buffer scheme @@ -294,11 +280,11 @@ static block_t *Pop( decoder_t *p_dec ) return NULL; p_block = p_sys->pp_block[i_index = 0]; - if( p_block->i_pts > 0 ) + if( p_block->i_pts > VLC_TS_INVALID ) { - for( i = 1; i < p_sys->i_block-1; i++ ) + for( int i = 1; i < p_sys->i_block-1; i++ ) { - if( p_sys->pp_block[i]->i_pts > 0 && p_block->i_pts > 0 && + if( p_sys->pp_block[i]->i_pts > VLC_TS_INVALID && p_block->i_pts > VLC_TS_INVALID && p_sys->pp_block[i]->i_pts < p_block->i_pts ) p_block = p_sys->pp_block[i_index = i]; } @@ -314,10 +300,9 @@ static subpicture_t *Subtitle( decoder_t *p_dec, char *psz_subtitle, char *psz_h { //decoder_sys_t *p_sys = p_dec->p_sys; subpicture_t *p_spu = NULL; - video_format_t fmt; /* We cannot display a subpicture with no date */ - if( i_pts == 0 ) + if( i_pts <= VLC_TS_INVALID ) { msg_Warn( p_dec, "subtitle without a date" ); return NULL; @@ -328,44 +313,23 @@ static subpicture_t *Subtitle( decoder_t *p_dec, char *psz_subtitle, char *psz_h EnsureUTF8( psz_html ); /* Create the subpicture unit */ - p_spu = decoder_NewSubpicture( p_dec ); + p_spu = decoder_NewSubpictureText( p_dec ); if( !p_spu ) { - msg_Warn( p_dec, "can't get spu buffer" ); - free( psz_subtitle ); - free( psz_html ); - return NULL; - } - - /* Create a new subpicture region */ - memset( &fmt, 0, sizeof(video_format_t) ); - fmt.i_chroma = VLC_CODEC_TEXT; - fmt.i_aspect = 0; - fmt.i_width = fmt.i_height = 0; - fmt.i_x_offset = fmt.i_y_offset = 0; - p_spu->p_region = subpicture_region_New( &fmt ); - if( !p_spu->p_region ) - { - msg_Err( p_dec, "cannot allocate SPU region" ); free( psz_subtitle ); free( psz_html ); - decoder_DeleteSubpicture( p_dec, p_spu ); return NULL; } + p_spu->i_start = i_pts; + p_spu->i_stop = i_pts + 10000000; /* 10s max */ + p_spu->b_ephemer = true; + p_spu->b_absolute = false; - /* Decode and format the subpicture unit */ - /* Normal text subs, easy markup */ - p_spu->p_region->i_align = SUBPICTURE_ALIGN_BOTTOM;// | SUBPICTURE_ALIGN_LEFT;// | p_sys->i_align; - p_spu->p_region->i_x = 0; //p_sys->i_align ? 20 : 0; - p_spu->p_region->i_y = 10; - - p_spu->p_region->psz_text = psz_subtitle; - p_spu->p_region->psz_html = psz_html; + subpicture_updater_sys_t *p_spu_sys = p_spu->updater.p_sys; - p_spu->i_start = i_pts; - p_spu->i_stop = i_pts + 10000000; /* 10s max */ - p_spu->b_ephemer = true; - p_spu->b_absolute = false; + p_spu_sys->align = SUBPICTURE_ALIGN_BOTTOM; + p_spu_sys->text = psz_subtitle; + p_spu_sys->html = psz_html; return p_spu; } @@ -456,7 +420,6 @@ static void Eia608Cursor( eia608_t *h, int dx ) static void Eia608ClearScreenRowX( eia608_t *h, int i_screen, int i_row, int x ) { eia608_screen *screen = &h->screen[i_screen]; - int i; if( x == 0 ) { @@ -465,7 +428,7 @@ static void Eia608ClearScreenRowX( eia608_t *h, int i_screen, int i_row, int x ) else { screen->row_used[i_row] = false; - for( i = 0; i < x; i++ ) + for( int i = 0; i < x; i++ ) { if( screen->characters[i_row][i] != ' ' || screen->colors[i_row][i] != EIA608_COLOR_DEFAULT || @@ -492,8 +455,7 @@ static void Eia608ClearScreenRow( eia608_t *h, int i_screen, int i_row ) static void Eia608ClearScreen( eia608_t *h, int i_screen ) { - int i; - for( i = 0; i < EIA608_SCREEN_ROWS; i++ ) + for( int i = 0; i < EIA608_SCREEN_ROWS; i++ ) Eia608ClearScreenRow( h, i_screen, i ); } @@ -565,11 +527,13 @@ static void Eia608EraseToEndOfRow( eia608_t *h ) static void Eia608RollUp( eia608_t *h ) { + if( h->mode == EIA608_MODE_TEXT ) + return; + const int i_screen = Eia608GetWritingScreenIndex( h ); eia608_screen *screen = &h->screen[i_screen]; int keep_lines; - int i; /* Window size */ if( h->mode == EIA608_MODE_ROLLUP_2 ) @@ -585,11 +549,11 @@ static void Eia608RollUp( eia608_t *h ) h->cursor.i_column = 0; /* Erase lines above our window */ - for( i = 0; i < h->cursor.i_row - keep_lines; i++ ) + for( int i = 0; i < h->cursor.i_row - keep_lines; i++ ) Eia608ClearScreenRow( h, i_screen, i ); /* Move up */ - for( i = 0; i < keep_lines-1; i++ ) + for( int i = 0; i < keep_lines-1; i++ ) { const int i_row = h->cursor.i_row - keep_lines + i + 1; if( i_row < 0 ) @@ -603,7 +567,7 @@ static void Eia608RollUp( eia608_t *h ) /* Reset current row */ Eia608ClearScreenRow( h, i_screen, h->cursor.i_row ); } -static void Eia608ParseChannel( eia608_t *h, uint8_t d[2] ) +static void Eia608ParseChannel( eia608_t *h, const uint8_t d[2] ) { /* Check odd parity */ static const int p4[16] = { @@ -618,15 +582,10 @@ static void Eia608ParseChannel( eia608_t *h, uint8_t d[2] ) /* */ const int d1 = d[0] & 0x7f; - const int d2 = d[1] & 0x7f; - if( d1 == 0x14 ) - h->i_channel = 1; - else if( d1 == 0x1c ) - h->i_channel = 2; - else if( d1 == 0x15 ) + if( d1 >= 0x10 && d1 <= 0x1f ) + h->i_channel = 1 + ((d1 & 0x08) != 0); + else if( d1 < 0x10 ) h->i_channel = 3; - else if( d1 == 0x1d ) - h->i_channel = 4; } static bool Eia608ParseTextAttribute( eia608_t *h, uint8_t d2 ) { @@ -781,6 +740,9 @@ static bool Eia608ParsePac( eia608_t *h, uint8_t d1, uint8_t d2 ) else if( d2 >= 0x40 ) d2 -= 0x40; h->cursor.i_column = pac2_attribs[d2].i_column; + h->color = pac2_attribs[d2].i_color; + h->font = pac2_attribs[d2].i_font; + return false; } @@ -853,7 +815,7 @@ static void Eia608TextUtf8( char *psz_utf8, uint8_t c ) // Returns number of byt E2( 0x86, 0xc2,0xa3), // Pounds sterling E3( 0x87, 0xe2,0x99,0xaa), // Music note E2( 0x88, 0xc3,0xa0), // lowercase a, grave accent - E1( 0x89, 0x20), // transparent space, we make it regular + E2( 0x89, 0xc2,0xa0), // transparent space E2( 0x8a, 0xc3,0xa8), // lowercase e, grave accent E2( 0x8b, 0xc3,0xa2), // lowercase a, circumflex accent E2( 0x8c, 0xc3,0xaa), // lowercase e, circumflex accent @@ -869,15 +831,15 @@ static void Eia608TextUtf8( char *psz_utf8, uint8_t c ) // Returns number of byt E2( 0x94, 0xc3,0x9c), // capital letter U with diaresis E2( 0x95, 0xc3,0xbc), // lowercase letter U with diaeresis E1( 0x96, 0x27), // apostrophe - E2( 0x97, 0xc1,0xa1), // inverted exclamation mark + E2( 0x97, 0xc2,0xa1), // inverted exclamation mark E1( 0x98, 0x2a), // asterisk E1( 0x99, 0x27), // apostrophe (yes, duped). See CCADI source code. E1( 0x9a, 0x2d), // hyphen-minus E2( 0x9b, 0xc2,0xa9), // copyright sign E3( 0x9c, 0xe2,0x84,0xa0), // Service mark E1( 0x9d, 0x2e), // Full stop (.) - E1( 0x9e, 0x22), // Quoatation mark - E1( 0x9f, 0x22), // Quoatation mark + E3( 0x9e, 0xe2,0x80,0x9c), // Quotation mark + E3( 0x9f, 0xe2,0x80,0x9d), // Quotation mark E2( 0xa0, 0xc3,0x80), // uppercase A, grave accent E2( 0xa1, 0xc3,0x82), // uppercase A, circumflex E2( 0xa2, 0xc3,0x87), // uppercase C with cedilla @@ -935,23 +897,14 @@ static void Eia608TextUtf8( char *psz_utf8, uint8_t c ) // Returns number of byt #undef E2 #undef E1 - static const int i_c2utf8 = sizeof(c2utf8)/sizeof(*c2utf8); - int i; + for( size_t i = 0; i < ARRAY_SIZE(c2utf8) ; i++ ) + if( c2utf8[i].c == c ) { + strcpy( psz_utf8, c2utf8[i].utf8 ); + return; + } - for( i = 0; i < i_c2utf8; i++ ) - { - if( c2utf8[i].c == c ) - break; - } - if( i >= i_c2utf8 ) - { - psz_utf8[0] = c < 0x80 ? c : '?'; /* Normal : Unsupported */ - psz_utf8[1] = '\0'; - } - else - { - strcpy( psz_utf8, c2utf8[i].utf8 ); - } + psz_utf8[0] = c < 0x80 ? c : '?'; /* Normal : Unsupported */ + psz_utf8[1] = '\0'; } static void Eia608Strlcat( char *d, const char *s, int i_max ) @@ -1005,7 +958,7 @@ static void Eia608TextLine( struct eia608_screen *screen, char *psz_text, int i_ /* Be sure to create valid html */ b_close_italics |= b_last_italics && b_close_color; - b_close_underline = b_last_underline && ( b_close_italics || b_close_color ); + b_close_underline |= b_last_underline && ( b_close_italics || b_close_color ); if( b_close_underline ) CAT( "" ); @@ -1116,7 +1069,6 @@ static char *Eia608Text( eia608_t *h, bool b_html ) struct eia608_screen *screen = &h->screen[h->i_screen]; bool b_first = true; char *psz; - int i; /* We allocate a buffer big enough for normal case */ psz = malloc( i_size ); @@ -1125,7 +1077,7 @@ static char *Eia608Text( eia608_t *h, bool b_html ) *psz = '\0'; if( b_html ) Eia608Strlcat( psz, "", i_size ); - for( i = 0; i < EIA608_SCREEN_ROWS; i++ ) + for( int i = 0; i < EIA608_SCREEN_ROWS; i++ ) { if( !screen->row_used[i] ) continue; @@ -1140,8 +1092,3 @@ static char *Eia608Text( eia608_t *h, bool b_html ) Eia608Strlcat( psz, "", i_size ); return psz; } - -static void Eia608Exit( eia608_t *h ) -{ -} -