Commit 401a3172 authored by Francois Cartegnie's avatar Francois Cartegnie

codec: cc: return caption on screen flip

parent f54301b6
...@@ -112,6 +112,15 @@ struct eia608_screen // A CC buffer ...@@ -112,6 +112,15 @@ struct eia608_screen // A CC buffer
}; };
typedef struct eia608_screen eia608_screen; typedef struct eia608_screen eia608_screen;
typedef enum
{
EIA608_STATUS_DEFAULT = 0x00,
EIA608_STATUS_CHANGED = 0x01, /* current screen has been altered */
EIA608_STATUS_CAPTION_ENDED = 0x02, /* screen flip */
EIA608_STATUS_CAPTION_CLEARED = 0x04, /* active screen erased */
EIA608_STATUS_DISPLAY = EIA608_STATUS_CAPTION_CLEARED | EIA608_STATUS_CAPTION_ENDED,
} eia608_status_t;
typedef struct typedef struct
{ {
/* Current channel (used to reject packet without channel information) */ /* Current channel (used to reject packet without channel information) */
...@@ -142,7 +151,7 @@ typedef struct ...@@ -142,7 +151,7 @@ typedef struct
} eia608_t; } eia608_t;
static void Eia608Init( eia608_t * ); static void Eia608Init( eia608_t * );
static bool Eia608Parse( eia608_t *h, int i_channel_selected, const uint8_t data[2] ); static eia608_status_t Eia608Parse( eia608_t *h, int i_channel_selected, const uint8_t data[2] );
static text_segment_t *Eia608Text( eia608_t *h ); static text_segment_t *Eia608Text( eia608_t *h );
/* It will be enough up to 63 B frames, which is far too high for /* It will be enough up to 63 B frames, which is far too high for
...@@ -152,6 +161,7 @@ struct decoder_sys_t ...@@ -152,6 +161,7 @@ struct decoder_sys_t
{ {
int i_block; int i_block;
block_t *pp_block[CC_MAX_REORDER_SIZE]; block_t *pp_block[CC_MAX_REORDER_SIZE];
block_t *p_block; /* currently processed block (if incomplely) */
int i_field; int i_field;
int i_channel; int i_channel;
...@@ -221,10 +231,12 @@ static int Open( vlc_object_t *p_this ) ...@@ -221,10 +231,12 @@ static int Open( vlc_object_t *p_this )
****************************************************************************/ ****************************************************************************/
static void Push( decoder_t *, block_t * ); static void Push( decoder_t *, block_t * );
static block_t *Pop( decoder_t * ); static block_t *Pop( decoder_t * );
static subpicture_t *Convert( decoder_t *, block_t * ); static subpicture_t *Convert( decoder_t *, block_t ** );
static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block ) static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
{ {
decoder_sys_t *p_sys = p_dec->p_sys;
if( pp_block && *pp_block ) if( pp_block && *pp_block )
{ {
Push( p_dec, *pp_block ); Push( p_dec, *pp_block );
...@@ -233,11 +245,13 @@ static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block ) ...@@ -233,11 +245,13 @@ static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
for( ;; ) for( ;; )
{ {
block_t *p_block = Pop( p_dec ); if( !p_sys->p_block )
if( !p_block ) p_sys->p_block = Pop( p_dec );
if( !p_sys->p_block )
break; break;
subpicture_t *p_spu = Convert( p_dec, p_block ); subpicture_t *p_spu = Convert( p_dec, &p_sys->p_block );
if( p_spu ) if( p_spu )
return p_spu; return p_spu;
} }
...@@ -344,27 +358,38 @@ static subpicture_t *Subtitle( decoder_t *p_dec, text_segment_t *p_segments, mti ...@@ -344,27 +358,38 @@ static subpicture_t *Subtitle( decoder_t *p_dec, text_segment_t *p_segments, mti
return p_spu; return p_spu;
} }
static subpicture_t *Convert( decoder_t *p_dec, block_t *p_block ) static subpicture_t *Convert( decoder_t *p_dec, block_t **pp_block )
{ {
assert( p_block ); assert( pp_block && *pp_block );
block_t *p_block = *pp_block;
decoder_sys_t *p_sys = p_dec->p_sys; decoder_sys_t *p_sys = p_dec->p_sys;
const int64_t i_pts = p_block->i_pts; const int64_t i_pts = p_block->i_pts;
bool b_changed = false; eia608_status_t i_status = EIA608_STATUS_DEFAULT;
/* TODO do the real decoding here */ /* TODO do the real decoding here */
while( p_block->i_buffer >= 3 ) while( p_block->i_buffer >= 3 && !(i_status & EIA608_STATUS_DISPLAY) )
{ {
if( p_block->p_buffer[0] == p_sys->i_field ) if( p_block->p_buffer[0] == p_sys->i_field )
b_changed |= Eia608Parse( &p_sys->eia608, p_sys->i_channel, &p_block->p_buffer[1] ); i_status = Eia608Parse( &p_sys->eia608, p_sys->i_channel, &p_block->p_buffer[1] );
p_block->i_buffer -= 3; p_block->i_buffer -= 3;
p_block->p_buffer += 3; p_block->p_buffer += 3;
} }
if( p_block ) if( p_block->i_buffer < 3 )
{
block_Release( p_block ); block_Release( p_block );
*pp_block = NULL;
}
if( b_changed ) /* a caption is ready or removed, process its screen */
/*
* In case of rollup/painton with 1 packet/frame, we need to update on Changed status.
* Batch decoding might be incorrect if those in large number of commands (mp4, ...) then.
* see CEAv1.2zero.trp tests
*/
if( i_status & (EIA608_STATUS_DISPLAY | EIA608_STATUS_CHANGED) )
{ {
text_segment_t *p_segments = Eia608Text( &p_sys->eia608 ); text_segment_t *p_segments = Eia608Text( &p_sys->eia608 );
return Subtitle( p_dec, p_segments, i_pts ); return Subtitle( p_dec, p_segments, i_pts );
...@@ -596,7 +621,7 @@ static void Eia608ParseChannel( eia608_t *h, const uint8_t d[2] ) ...@@ -596,7 +621,7 @@ static void Eia608ParseChannel( eia608_t *h, const uint8_t d[2] )
else if( d1 < 0x10 ) else if( d1 < 0x10 )
h->i_channel = 3; h->i_channel = 3;
} }
static bool Eia608ParseTextAttribute( eia608_t *h, uint8_t d2 ) static eia608_status_t Eia608ParseTextAttribute( eia608_t *h, uint8_t d2 )
{ {
const int i_index = d2 - 0x20; const int i_index = d2 - 0x20;
assert( d2 >= 0x20 && d2 <= 0x2f ); assert( d2 >= 0x20 && d2 <= 0x2f );
...@@ -605,21 +630,21 @@ static bool Eia608ParseTextAttribute( eia608_t *h, uint8_t d2 ) ...@@ -605,21 +630,21 @@ static bool Eia608ParseTextAttribute( eia608_t *h, uint8_t d2 )
h->font = pac2_attribs[i_index].i_font; h->font = pac2_attribs[i_index].i_font;
Eia608Cursor( h, 1 ); Eia608Cursor( h, 1 );
return false; return EIA608_STATUS_DEFAULT;
} }
static bool Eia608ParseSingle( eia608_t *h, const uint8_t dx ) static eia608_status_t Eia608ParseSingle( eia608_t *h, const uint8_t dx )
{ {
assert( dx >= 0x20 ); assert( dx >= 0x20 );
Eia608Write( h, dx ); Eia608Write( h, dx );
return true; return EIA608_STATUS_CHANGED;
} }
static bool Eia608ParseDouble( eia608_t *h, uint8_t d2 ) static eia608_status_t Eia608ParseDouble( eia608_t *h, uint8_t d2 )
{ {
assert( d2 >= 0x30 && d2 <= 0x3f ); assert( d2 >= 0x30 && d2 <= 0x3f );
Eia608Write( h, d2 + 0x50 ); /* We use charaters 0x80...0x8f */ Eia608Write( h, d2 + 0x50 ); /* We use charaters 0x80...0x8f */
return true; return EIA608_STATUS_CHANGED;
} }
static bool Eia608ParseExtended( eia608_t *h, uint8_t d1, uint8_t d2 ) static eia608_status_t Eia608ParseExtended( eia608_t *h, uint8_t d1, uint8_t d2 )
{ {
assert( d2 >= 0x20 && d2 <= 0x3f ); assert( d2 >= 0x20 && d2 <= 0x3f );
assert( d1 == 0x12 || d1 == 0x13 ); assert( d1 == 0x12 || d1 == 0x13 );
...@@ -632,11 +657,11 @@ static bool Eia608ParseExtended( eia608_t *h, uint8_t d1, uint8_t d2 ) ...@@ -632,11 +657,11 @@ static bool Eia608ParseExtended( eia608_t *h, uint8_t d1, uint8_t d2 )
* advanced one */ * advanced one */
Eia608Cursor( h, -1 ); Eia608Cursor( h, -1 );
Eia608Write( h, d2 ); Eia608Write( h, d2 );
return true; return EIA608_STATUS_CHANGED;
} }
static bool Eia608ParseCommand0x14( eia608_t *h, uint8_t d2 ) static eia608_status_t Eia608ParseCommand0x14( eia608_t *h, uint8_t d2 )
{ {
bool b_changed = false; eia608_status_t i_status = EIA608_STATUS_DEFAULT;
switch( d2 ) switch( d2 )
{ {
...@@ -645,7 +670,7 @@ static bool Eia608ParseCommand0x14( eia608_t *h, uint8_t d2 ) ...@@ -645,7 +670,7 @@ static bool Eia608ParseCommand0x14( eia608_t *h, uint8_t d2 )
break; break;
case 0x21: /* Backspace */ case 0x21: /* Backspace */
Eia608Erase( h ); Eia608Erase( h );
b_changed = true; i_status = EIA608_STATUS_CHANGED;
break; break;
case 0x22: /* Reserved */ case 0x22: /* Reserved */
case 0x23: case 0x23:
...@@ -660,7 +685,7 @@ static bool Eia608ParseCommand0x14( eia608_t *h, uint8_t d2 ) ...@@ -660,7 +685,7 @@ static bool Eia608ParseCommand0x14( eia608_t *h, uint8_t d2 )
{ {
Eia608EraseScreen( h, true ); Eia608EraseScreen( h, true );
Eia608EraseScreen( h, false ); Eia608EraseScreen( h, false );
b_changed = true; i_status = EIA608_STATUS_CHANGED | EIA608_STATUS_CAPTION_CLEARED;
} }
if( d2 == 0x25 ) if( d2 == 0x25 )
...@@ -689,11 +714,11 @@ static bool Eia608ParseCommand0x14( eia608_t *h, uint8_t d2 ) ...@@ -689,11 +714,11 @@ static bool Eia608ParseCommand0x14( eia608_t *h, uint8_t d2 )
case 0x2c: /* Erase displayed memory */ case 0x2c: /* Erase displayed memory */
Eia608EraseScreen( h, true ); Eia608EraseScreen( h, true );
b_changed = true; i_status = EIA608_STATUS_CHANGED | EIA608_STATUS_CAPTION_CLEARED;
break; break;
case 0x2d: /* Carriage return */ case 0x2d: /* Carriage return */
Eia608RollUp(h); Eia608RollUp(h);
b_changed = true; i_status = EIA608_STATUS_CHANGED;
break; break;
case 0x2e: /* Erase non displayed memory */ case 0x2e: /* Erase non displayed memory */
Eia608EraseScreen( h, false ); Eia608EraseScreen( h, false );
...@@ -706,10 +731,10 @@ static bool Eia608ParseCommand0x14( eia608_t *h, uint8_t d2 ) ...@@ -706,10 +731,10 @@ static bool Eia608ParseCommand0x14( eia608_t *h, uint8_t d2 )
h->cursor.i_row = 0; h->cursor.i_row = 0;
h->color = EIA608_COLOR_DEFAULT; h->color = EIA608_COLOR_DEFAULT;
h->font = EIA608_FONT_REGULAR; h->font = EIA608_FONT_REGULAR;
b_changed = true; i_status = EIA608_STATUS_CHANGED | EIA608_STATUS_CAPTION_ENDED;
break; break;
} }
return b_changed; return i_status;
} }
static bool Eia608ParseCommand0x17( eia608_t *h, uint8_t d2 ) static bool Eia608ParseCommand0x17( eia608_t *h, uint8_t d2 )
{ {
...@@ -755,14 +780,14 @@ static bool Eia608ParsePac( eia608_t *h, uint8_t d1, uint8_t d2 ) ...@@ -755,14 +780,14 @@ static bool Eia608ParsePac( eia608_t *h, uint8_t d1, uint8_t d2 )
return false; return false;
} }
static bool Eia608ParseData( eia608_t *h, uint8_t d1, uint8_t d2 ) static eia608_status_t Eia608ParseData( eia608_t *h, uint8_t d1, uint8_t d2 )
{ {
bool b_changed = false; eia608_status_t i_status = EIA608_STATUS_DEFAULT;
if( d1 >= 0x18 && d1 <= 0x1f ) if( d1 >= 0x18 && d1 <= 0x1f )
d1 -= 8; d1 -= 8;
#define ON( d2min, d2max, cmd ) do { if( d2 >= d2min && d2 <= d2max ) b_changed = cmd; } while(0) #define ON( d2min, d2max, cmd ) do { if( d2 >= d2min && d2 <= d2max ) i_status = cmd; } while(0)
switch( d1 ) switch( d1 )
{ {
case 0x11: case 0x11:
...@@ -787,11 +812,11 @@ static bool Eia608ParseData( eia608_t *h, uint8_t d1, uint8_t d2 ) ...@@ -787,11 +812,11 @@ static bool Eia608ParseData( eia608_t *h, uint8_t d1, uint8_t d2 )
#undef ON #undef ON
if( d1 >= 0x20 ) if( d1 >= 0x20 )
{ {
b_changed = Eia608ParseSingle( h, d1 ); i_status = Eia608ParseSingle( h, d1 );
if( d2 >= 0x20 ) if( d2 >= 0x20 )
b_changed |= Eia608ParseSingle( h, d2 ); i_status |= Eia608ParseSingle( h, d2 );
} }
return b_changed; return i_status;
} }
static void Eia608TextUtf8( char *psz_utf8, uint8_t c ) // Returns number of bytes used static void Eia608TextUtf8( char *psz_utf8, uint8_t c ) // Returns number of bytes used
...@@ -1066,14 +1091,14 @@ static void Eia608Init( eia608_t *h ) ...@@ -1066,14 +1091,14 @@ static void Eia608Init( eia608_t *h )
h->font = EIA608_FONT_REGULAR; h->font = EIA608_FONT_REGULAR;
h->i_row_rollup = EIA608_SCREEN_ROWS-1; h->i_row_rollup = EIA608_SCREEN_ROWS-1;
} }
static bool Eia608Parse( eia608_t *h, int i_channel_selected, const uint8_t data[2] ) static eia608_status_t Eia608Parse( eia608_t *h, int i_channel_selected, const uint8_t data[2] )
{ {
const uint8_t d1 = data[0] & 0x7f; /* Removed parity bit */ const uint8_t d1 = data[0] & 0x7f; /* Removed parity bit */
const uint8_t d2 = data[1] & 0x7f; const uint8_t d2 = data[1] & 0x7f;
bool b_screen_changed = false; eia608_status_t i_screen_status = EIA608_STATUS_DEFAULT;
if( d1 == 0 && d2 == 0 ) if( d1 == 0 && d2 == 0 )
return false; /* Ignore padding (parity check are sometimes invalid on them) */ return EIA608_STATUS_DEFAULT; /* Ignore padding (parity check are sometimes invalid on them) */
Eia608ParseChannel( h, data ); Eia608ParseChannel( h, data );
if( h->i_channel != i_channel_selected ) if( h->i_channel != i_channel_selected )
...@@ -1084,7 +1109,7 @@ static bool Eia608Parse( eia608_t *h, int i_channel_selected, const uint8_t data ...@@ -1084,7 +1109,7 @@ static bool Eia608Parse( eia608_t *h, int i_channel_selected, const uint8_t data
{ {
if( d1 >= 0x20 || if( d1 >= 0x20 ||
d1 != h->last.d1 || d2 != h->last.d2 ) /* Command codes can be repeated */ d1 != h->last.d1 || d2 != h->last.d2 ) /* Command codes can be repeated */
b_screen_changed = Eia608ParseData( h, d1,d2 ); i_screen_status = Eia608ParseData( h, d1,d2 );
h->last.d1 = d1; h->last.d1 = d1;
h->last.d2 = d2; h->last.d2 = d2;
...@@ -1093,7 +1118,7 @@ static bool Eia608Parse( eia608_t *h, int i_channel_selected, const uint8_t data ...@@ -1093,7 +1118,7 @@ static bool Eia608Parse( eia608_t *h, int i_channel_selected, const uint8_t data
{ {
/* XDS block / End of XDS block */ /* XDS block / End of XDS block */
} }
return b_screen_changed; return i_screen_status;
} }
static text_segment_t *Eia608Text( eia608_t *h ) static text_segment_t *Eia608Text( eia608_t *h )
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment