📄 cc.c
字号:
bool b_changed = false; /* TODO do the real decoding here */ while( p_block->i_buffer >= 3 ) { 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] ); p_block->i_buffer -= 3; p_block->p_buffer += 3; } if( p_block ) block_Release( p_block ); if( b_changed ) { char *psz_subtitle = Eia608Text( &p_sys->eia608, false ); char *psz_html = NULL;//Eia608Text( &p_sys->eia608, true ); return Subtitle( p_dec, psz_subtitle, psz_html, i_pts ); } return NULL;}/***************************************************************************** * *****************************************************************************/static const struct { eia608_color_t i_color; eia608_font_t i_font; int i_column;} pac2_attribs[]= { { EIA608_COLOR_WHITE, EIA608_FONT_REGULAR, 0 }, { EIA608_COLOR_WHITE, EIA608_FONT_UNDERLINE, 0 }, { EIA608_COLOR_GREEN, EIA608_FONT_REGULAR, 0 }, { EIA608_COLOR_GREEN, EIA608_FONT_UNDERLINE, 0 }, { EIA608_COLOR_BLUE, EIA608_FONT_REGULAR, 0 }, { EIA608_COLOR_BLUE, EIA608_FONT_UNDERLINE, 0 }, { EIA608_COLOR_CYAN, EIA608_FONT_REGULAR, 0 }, { EIA608_COLOR_CYAN, EIA608_FONT_UNDERLINE, 0 }, { EIA608_COLOR_RED, EIA608_FONT_REGULAR, 0 }, { EIA608_COLOR_RED, EIA608_FONT_UNDERLINE, 0 }, { EIA608_COLOR_YELLOW, EIA608_FONT_REGULAR, 0 }, { EIA608_COLOR_YELLOW, EIA608_FONT_UNDERLINE, 0 }, { EIA608_COLOR_MAGENTA, EIA608_FONT_REGULAR, 0 }, { EIA608_COLOR_MAGENTA, EIA608_FONT_UNDERLINE, 0 }, { EIA608_COLOR_WHITE, EIA608_FONT_ITALICS, 0 }, { EIA608_COLOR_WHITE, EIA608_FONT_UNDERLINE_ITALICS, 0 }, { EIA608_COLOR_WHITE, EIA608_FONT_REGULAR, 0 }, { EIA608_COLOR_WHITE, EIA608_FONT_UNDERLINE, 0 }, { EIA608_COLOR_WHITE, EIA608_FONT_REGULAR, 4 }, { EIA608_COLOR_WHITE, EIA608_FONT_UNDERLINE, 4 }, { EIA608_COLOR_WHITE, EIA608_FONT_REGULAR, 8 }, { EIA608_COLOR_WHITE, EIA608_FONT_UNDERLINE, 8 }, { EIA608_COLOR_WHITE, EIA608_FONT_REGULAR, 12 }, { EIA608_COLOR_WHITE, EIA608_FONT_UNDERLINE, 12 }, { EIA608_COLOR_WHITE, EIA608_FONT_REGULAR, 16 }, { EIA608_COLOR_WHITE, EIA608_FONT_UNDERLINE, 16 }, { EIA608_COLOR_WHITE, EIA608_FONT_REGULAR, 20 }, { EIA608_COLOR_WHITE, EIA608_FONT_UNDERLINE, 20 }, { EIA608_COLOR_WHITE, EIA608_FONT_REGULAR, 24 }, { EIA608_COLOR_WHITE, EIA608_FONT_UNDERLINE, 24 }, { EIA608_COLOR_WHITE, EIA608_FONT_REGULAR, 28 }, { EIA608_COLOR_WHITE, EIA608_FONT_UNDERLINE, 28 } ,};#define EIA608_COLOR_DEFAULT EIA608_COLOR_WHITEstatic void Eia608Cursor( eia608_t *h, int dx ){ h->cursor.i_column += dx; if( h->cursor.i_column < 0 ) h->cursor.i_column = 0; else if( h->cursor.i_column > EIA608_SCREEN_COLUMNS-1 ) h->cursor.i_column = EIA608_SCREEN_COLUMNS-1;}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 ) { screen->row_used[i_row] = false; } else { screen->row_used[i_row] = false; for( i = 0; i < x; i++ ) { if( screen->characters[i_row][i] != ' ' || screen->colors[i_row][i] != EIA608_COLOR_DEFAULT || screen->fonts[i_row][i] != EIA608_FONT_REGULAR ) { screen->row_used[i_row] = true; break; } } } for( ; x < EIA608_SCREEN_COLUMNS+1; x++ ) { screen->characters[i_row][x] = x < EIA608_SCREEN_COLUMNS ? ' ' : '\0'; screen->colors[i_row][x] = EIA608_COLOR_DEFAULT; screen->fonts[i_row][x] = EIA608_FONT_REGULAR; }}static void Eia608ClearScreenRow( eia608_t *h, int i_screen, int i_row ){ Eia608ClearScreenRowX( h, i_screen, i_row, 0 );}static void Eia608ClearScreen( eia608_t *h, int i_screen ){ int i; for( i = 0; i < EIA608_SCREEN_ROWS; i++ ) Eia608ClearScreenRow( h, i_screen, i );}static int Eia608GetWritingScreenIndex( eia608_t *h ){ switch( h->mode ) { case EIA608_MODE_POPUP: // Non displayed screen return 1 - h->i_screen; case EIA608_MODE_ROLLUP_2: // Displayed screen case EIA608_MODE_ROLLUP_3: case EIA608_MODE_ROLLUP_4: case EIA608_MODE_PAINTON: return h->i_screen; default: /* It cannot happen, else it is a bug */ assert( 0 ); return 0; }}static void Eia608EraseScreen( eia608_t *h, bool b_displayed ){ Eia608ClearScreen( h, b_displayed ? h->i_screen : (1-h->i_screen) );}static void Eia608Write( eia608_t *h, const uint8_t c ){ const int i_row = h->cursor.i_row; const int i_column = h->cursor.i_column; eia608_screen *screen; if( h->mode == EIA608_MODE_TEXT ) return; screen = &h->screen[Eia608GetWritingScreenIndex( h )]; screen->characters[i_row][i_column] = c; screen->colors[i_row][i_column] = h->color; screen->fonts[i_row][i_column] = h->font; screen->row_used[i_row] = true; Eia608Cursor( h, 1 );}static void Eia608Erase( eia608_t *h ){ const int i_row = h->cursor.i_row; const int i_column = h->cursor.i_column - 1; eia608_screen *screen; if( h->mode == EIA608_MODE_TEXT ) return; if( i_column < 0 ) return; screen = &h->screen[Eia608GetWritingScreenIndex( h )]; /* FIXME do we need to reset row_used/colors/font ? */ screen->characters[i_row][i_column] = ' '; Eia608Cursor( h, -1 );}static void Eia608EraseToEndOfRow( eia608_t *h ){ if( h->mode == EIA608_MODE_TEXT ) return; Eia608ClearScreenRowX( h, Eia608GetWritingScreenIndex( h ), h->cursor.i_row, h->cursor.i_column );}static void Eia608RollUp( eia608_t *h ){ 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 ) keep_lines = 2; else if( h->mode == EIA608_MODE_ROLLUP_3 ) keep_lines = 3; else if( h->mode == EIA608_MODE_ROLLUP_4 ) keep_lines = 4; else return; /* Reset the cursor */ h->cursor.i_column = 0; /* Erase lines above our window */ for( 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++ ) { const int i_row = h->cursor.i_row - keep_lines + i + 1; if( i_row < 0 ) continue; assert( i_row+1 < EIA608_SCREEN_ROWS ); memcpy( screen->characters[i_row], screen->characters[i_row+1], sizeof(*screen->characters) ); memcpy( screen->colors[i_row], screen->colors[i_row+1], sizeof(*screen->colors) ); memcpy( screen->fonts[i_row], screen->fonts[i_row+1], sizeof(*screen->fonts) ); screen->row_used[i_row] = screen->row_used[i_row+1]; } /* Reset current row */ Eia608ClearScreenRow( h, i_screen, h->cursor.i_row );}static void Eia608ParseChannel( eia608_t *h, uint8_t d1 ){ if( d1 == 0x14 ) h->i_channel = 1; else if( d1 == 0x1c ) h->i_channel = 2; else if( ( d1 >= 0x01 && d1 <= 0x0f ) || d1 == 0x15 ) h->i_channel = 3; else if( d1 == 0x1d ) h->i_channel = 4;}static bool Eia608ParseTextAttribute( eia608_t *h, uint8_t d2 ){ const int i_index = d2 - 0x20; assert( d2 >= 0x20 && d2 <= 0x2f ); h->color = pac2_attribs[i_index].i_color; h->font = pac2_attribs[i_index].i_font; Eia608Cursor( h, 1 ); return false;}static bool Eia608ParseSingle( eia608_t *h, const uint8_t dx ){ assert( dx >= 0x20 ); Eia608Write( h, dx ); return true;}static bool Eia608ParseDouble( eia608_t *h, uint8_t d2 ){ assert( d2 >= 0x30 && d2 <= 0x3f ); Eia608Write( h, d2 + 0x50 ); /* We use charaters 0x80...0x8f */ return true;}static bool Eia608ParseExtended( eia608_t *h, uint8_t d1, uint8_t d2 ){ assert( d2 >= 0x20 && d2 <= 0x3f ); assert( d1 == 0x12 || d1 == 0x13 ); if( d1 == 0x12 ) d2 += 0x70; /* We use charaters 0x90-0xaf */ else d2 += 0x90; /* We use charaters 0xb0-0xcf */ /* The extended characters replace the previous one with a more * advanced one */ Eia608Cursor( h, -1 ); Eia608Write( h, d2 ); return true;}static bool Eia608ParseCommand0x14( eia608_t *h, uint8_t d2 ){ bool b_changed = false; switch( d2 ) { case 0x20: /* Resume caption loading */ h->mode = EIA608_MODE_POPUP; break; case 0x21: /* Backspace */ Eia608Erase( h ); b_changed = true; break; case 0x22: /* Reserved */ case 0x23: break; case 0x24: /* Delete to end of row */ Eia608EraseToEndOfRow( h ); break; case 0x25: /* Rollup 2 */ case 0x26: /* Rollup 3 */ case 0x27: /* Rollup 4 */ if( h->mode == EIA608_MODE_POPUP || h->mode == EIA608_MODE_PAINTON ) { Eia608EraseScreen( h, true ); Eia608EraseScreen( h, false ); b_changed = true; } if( d2 == 0x25 ) h->mode = EIA608_MODE_ROLLUP_2; else if( d2 == 0x26 ) h->mode = EIA608_MODE_ROLLUP_3; else h->mode = EIA608_MODE_ROLLUP_4; h->cursor.i_column = 0; h->cursor.i_row = h->i_row_rollup; break; case 0x28: /* Flash on */ /* TODO */ break; case 0x29: /* Resume direct captionning */ h->mode = EIA608_MODE_PAINTON; break; case 0x2a: /* Text restart */ /* TODO */ break; case 0x2b: /* Resume text display */ h->mode = EIA608_MODE_TEXT; break; case 0x2c: /* Erase displayed memory */ Eia608EraseScreen( h, true ); b_changed = true; break; case 0x2d: /* Carriage return */ Eia608RollUp(h); b_changed = true; break; case 0x2e: /* Erase non displayed memory */ Eia608EraseScreen( h, false ); break; case 0x2f: /* End of caption (flip screen if not paint on) */ if( h->mode != EIA608_MODE_PAINTON ) h->i_screen = 1 - h->i_screen; h->mode = EIA608_MODE_POPUP; h->cursor.i_column = 0; h->cursor.i_row = 0; h->color = EIA608_COLOR_DEFAULT; h->font = EIA608_FONT_REGULAR; b_changed = true; break; } return b_changed;}static bool Eia608ParseCommand0x17( eia608_t *h, uint8_t d2 ){ switch( d2 ) { case 0x21: /* Tab offset 1 */ Eia608Cursor( h, 1 ); break; case 0x22: /* Tab offset 2 */ Eia608Cursor( h, 2 ); break; case 0x23: /* Tab offset 3 */ Eia608Cursor( h, 3 ); break; } return false;}static bool Eia608ParsePac( eia608_t *h, uint8_t d1, uint8_t d2 ){ static const int pi_row[] = { 11, -1, 1, 2, 3, 4, 12, 13, 14, 15, 5, 6, 7, 8, 9, 10 }; const int i_row_index = ( (d1<<1) & 0x0e) | ( (d2>>5) & 0x01 ); assert( d2 >= 0x40 && d2 <= 0x7f ); if( pi_row[i_row_index] <= 0 )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -