📄 demux_ty_osd.c
字号:
// Most of this was written by mbm@linux.com and released on the GPL2 License.//// Modifications and SEVERE cleanup of the code was done by // Christopher Wingert // Copyright 2003// // Released under GPL2 License.#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <time.h>#include <stdarg.h>#include <string.h>#include "config.h"#include "mp_msg.h"#include "help_mp.h"//#include "stream.h"//#include "demuxer.h"//#include "parse_es.h"//#include "stheader.h"//#include "mp3_hdr.h"//#include "../subreader.h"#include "../sub_cc.h"#include "../libvo/sub.h"//#include "dvdauth.h"extern int sub_justify;#define TY_TEXT_MODE ( 1 << 0 )#define TY_OSD_MODE ( 1 << 1 )static int TY_OSD_flags = TY_TEXT_MODE | TY_OSD_MODE;static int TY_OSD_debug = 0;// ===========================================================================// Closed Caption Decoding and OSD Presentation// ===========================================================================#define TY_CCNONE ( -3 )#define TY_CCTEXTMODE ( -2 )#define TY_CCPOPUPNB ( -1 )#define TY_CCPOPUP ( 0 )#define TY_CCPAINTON ( 1 )#define TY_CC_MAX_X ( 45 )static int TY_CC_CUR_X;static int TY_CC_CUR_Y;static int TY_CC_stat = TY_CCNONE;static char TY_CC_buf[ 255 ];static char *TY_CC_ptr = TY_CC_buf;static unsigned TY_CC_lastcap = 0;static int TY_CC_TextItalic;static int TY_CC_Y_Offset;static subtitle ty_OSD1;static subtitle ty_OSD2;static subtitle *ty_pOSD1;static subtitle *ty_pOSD2;static int tyOSDInited = 0;static int tyOSDUpdate = 0;static void ty_DrawOSD(){ // printf( "Calling ty_DrawOSD()\n" ); tyOSDUpdate = 1;}void ty_ClearOSD( int start ){ int index; // printf( "Calling ty_ClearOSD()\n" ); for ( index = start ; index < SUB_MAX_TEXT ; index++ ) { memset( ty_OSD1.text[ index ], ' ', TY_CC_MAX_X - 1 ); ty_OSD1.text[ index ][ TY_CC_MAX_X - 1 ] = 0; memset( ty_OSD2.text[ index ], ' ', TY_CC_MAX_X - 1 ); ty_OSD2.text[ index ][ TY_CC_MAX_X - 1 ] = 0; }}static void ty_DrawChar( int *x, int *y, char disChar, int fgColor, int bgColor ){ int index; int cx; int cy; cx = *x; cy = *y; if ( *x >= ( TY_CC_MAX_X - 1 ) ) { cx = 0; } if ( ( *y + TY_CC_Y_Offset ) > SUB_MAX_TEXT ) { cy = SUB_MAX_TEXT - TY_CC_Y_Offset - 1; } // printf( "Calling ty_DrawChar() x:%d y:%d %c fg:%d bg:%d\n", // cx, cy, disChar, fgColor, bgColor ); ty_OSD1.text[ TY_CC_Y_Offset + cy ][ cx ] = disChar; memset( &( ty_OSD1.text[ TY_CC_Y_Offset + cy ][ cx + 1 ] ), ' ', TY_CC_MAX_X - cx - 2 ); ( *x )++;}static void ty_RollupBuf( int dest, int source, int numLines ){ int index; // printf( "Calling ty_RollupBuf() dest:%d source %d, numLines %d\n", // dest, source, numLines ); // if ( ( source + TY_CC_Y_Offset + numLines ) > SUB_MAX_TEXT ) { ty_ClearOSD( 1 ); return; } if ( ( source + TY_CC_Y_Offset + numLines ) < 0 ) { ty_ClearOSD( 1 ); return; } if ( numLines > SUB_MAX_TEXT ) { ty_ClearOSD( 1 ); return; } for ( index = 0 ; index < numLines ; index++ ) { strcpy( ty_OSD1.text[ TY_CC_Y_Offset + dest ], ty_OSD1.text[ TY_CC_Y_Offset + source ] ); dest++; source++; } memset( ty_OSD1.text[ TY_CC_Y_Offset + source - 1 ], ' ', TY_CC_MAX_X - 1 ); ty_OSD1.text[ TY_CC_Y_Offset + source - 1 ][ TY_CC_MAX_X - 1 ] = 0;}static void ty_drawchar( char c ){ if ( c < 2 ) return; if ( TY_OSD_flags & TY_OSD_MODE && TY_CC_stat != TY_CCNONE && TY_CC_CUR_Y != -1 ) ty_DrawChar( &TY_CC_CUR_X, &TY_CC_CUR_Y, c, 4, 13 ); if ( TY_CC_ptr - TY_CC_buf > sizeof( TY_CC_buf ) - 1 ) { // buffer overflow TY_CC_ptr = TY_CC_buf; memset( TY_CC_buf, 0, sizeof( TY_CC_buf ) ); } *( TY_CC_ptr++ ) = ( c == 14 ) ? '/' : c; // swap a '/' for musical note}static void ty_draw(){ if ( TY_CC_ptr != TY_CC_buf && TY_OSD_flags & TY_TEXT_MODE ) { if ( *( TY_CC_ptr - 1 ) == '\n' ) *( TY_CC_ptr - 1 ) = 0; mp_msg( MSGT_DEMUX, MSGL_V, "CC: %s\n", TY_CC_buf ); } TY_CC_lastcap = time( NULL ); TY_CC_ptr = TY_CC_buf; memset( TY_CC_buf, 0, sizeof( TY_CC_buf) ); if ( TY_OSD_flags & TY_OSD_MODE ) ty_DrawOSD(); if ( TY_CC_TextItalic ) TY_CC_TextItalic = 0;}static int CC_last = 0;static char CC_mode = 0;static int CC_row[] = { 11, -1, 1, 2, 3, 4, 12, 13, 14, 15, 5, 6, 7, 8, 9, 10 };// char specialchar[] = { '®', '°', '½', '¿', '*', '¢', '£', 14, 'à', ' ', 'è', 'â', 'ê', 'î', 'ô', 'û' };static int ty_CCdecode( char b1, char b2 ){ int x; int data = ( b2 << 8 ) + b1; if ( b1 & 0x60 ) // text { if ( !TY_OSD_debug && TY_CC_stat == TY_CCNONE ) return 0; if ( TY_OSD_debug > 3 ) { mp_msg( MSGT_DEMUX, MSGL_DBG3, "%c %c", b1, b2 ); } ty_drawchar( b1 ); ty_drawchar( b2 ); if ( TY_CC_stat > 0 && TY_OSD_flags & TY_OSD_MODE ) ty_DrawOSD(); } else if ( ( b1 & 0x10 ) && ( b2 > 0x1F ) && ( data != CC_last ) ) { #define CURRENT ( ( b1 & 0x08 ) >> 3 ) if ( CC_mode != CURRENT && TY_CC_stat != TY_CCNONE ) { if ( TY_OSD_debug && TY_CC_ptr != TY_CC_buf ) ty_draw(); TY_CC_stat = TY_CCNONE; return 0; } if ( TY_CC_stat == TY_CCNONE || TY_CC_CUR_Y == -1 ) { if ( TY_CC_ptr != TY_CC_buf ) { if ( TY_OSD_debug ) mp_msg( MSGT_DEMUX, MSGL_DBG3, "(TY_OSD_debug) %s\n", TY_CC_buf ); TY_CC_ptr = TY_CC_buf; memset(TY_CC_buf, 0, sizeof(TY_CC_buf)); } if ( CC_mode != CURRENT ) return 0; } // preamble address code (row & indent) if ( b2 & 0x40 ) { TY_CC_CUR_Y = CC_row[ ( ( b1 << 1 ) & 14 ) | ( ( b2 >> 5 ) & 1 ) ]; // Offset into MPlayer's Buffer if ( ( TY_CC_CUR_Y >= 1 ) && ( TY_CC_CUR_Y <= 4 ) ) { TY_CC_Y_Offset = SUB_MAX_TEXT - 5 - 1; } if ( ( TY_CC_CUR_Y >= 5 ) && ( TY_CC_CUR_Y <= 10 ) ) { TY_CC_Y_Offset = SUB_MAX_TEXT - 5 - 5; } if ( ( TY_CC_CUR_Y >= 12 ) && ( TY_CC_CUR_Y <= 15 ) ) { TY_CC_Y_Offset = SUB_MAX_TEXT - 5 - 12; } if ( TY_OSD_debug > 3 ) mp_msg( MSGT_DEMUX, MSGL_DBG3, "<< preamble %d >>\n", TY_CC_CUR_Y ); // we still have something in the text buffer if (TY_CC_ptr != TY_CC_buf) { *(TY_CC_ptr++) = '\n'; if ( TY_CC_TextItalic ) { TY_CC_TextItalic = 0; } } TY_CC_CUR_X = 1; // row contains indent flag if ( b2 & 0x10 ) { for ( x = 0 ; x < ( ( b2 & 0x0F ) << 1 ) ; x++ ) { TY_CC_CUR_X++; *(TY_CC_ptr++) = ' '; } } } else // !(b2 & 0x40) { if ( TY_OSD_debug > 3 ) mp_msg( MSGT_DEMUX, MSGL_DBG3, "<< %02x >>\n", b1 & 0x7 ); switch (b1 & 0x07) { case 0x00: // attribute { if ( TY_OSD_debug > 1 ) mp_msg( MSGT_DEMUX, MSGL_DBG3, "<<A: %d>>\n", b2 ); break; } case 0x01: // midrow or char { switch (b2 & 0x70) { case 0x20: // midrow attribute change { switch (b2 & 0x0e) { case 0x00: // italics off { TY_CC_TextItalic = 0; *(TY_CC_ptr++) = ' '; break; } case 0x0e: // italics on { ty_drawchar(' '); TY_CC_TextItalic = 1; break; } default: { if ( TY_OSD_debug > 1 ) mp_msg( MSGT_DEMUX, MSGL_DBG3, "<<D: %d>>\n", b2 & 0x0e ); } } if ( b2 & 0x01 ) { // TextUnderline = 1; } else { // TextUnderline = 0; } break; } case 0x30: // special character.. { // transparent space if ( ( b2 & 0x0f ) == 9 ) { TY_CC_CUR_X++; *(TY_CC_ptr++) = ' '; } else { // ty_drawchar(specialchar[ b2 & 0x0f ] ); ty_drawchar( ' ' ); } break; } } break; } case 0x04: // misc case 0x05: // misc + F { if ( TY_OSD_debug > 3 ) mp_msg( MSGT_DEMUX, MSGL_DBG3, "<< misc %02x >>\n", b2 ); switch ( b2 ) { case 0x20: // resume caption (new caption) { if ( TY_OSD_flags & TY_OSD_MODE && TY_CC_stat != TY_CCPOPUP ) ty_ClearOSD( 1 ); TY_CC_stat = TY_CCPOPUP; break; } case 0x21: // backspace { TY_CC_CUR_X--; break; } case 0x25 ... 0x27: // 2-4 row captions { if ( TY_CC_stat == TY_CCPOPUP ) ty_ClearOSD( 1 ); TY_CC_stat = b2 - 0x23; if ( TY_CC_CUR_Y < TY_CC_stat ) TY_CC_CUR_Y = TY_CC_stat; break; } case 0x29: // resume direct caption { TY_CC_stat = TY_CCPAINTON; break; } case 0x2A: // text restart { ty_draw(); /* FALL */ } case 0x2B: // resume text display { TY_CC_stat = TY_CCTEXTMODE; break; } case 0x2C: // erase displayed memory { TY_CC_lastcap = 0; if ( TY_OSD_flags & TY_OSD_MODE ) { if ( TY_CC_stat > TY_CCPOPUP || TY_CC_ptr == TY_CC_buf ) { ty_ClearOSD( 1 ); ty_draw(); } else { ty_ClearOSD( 1 ); // CRW - // new buffer // Used to be a buffer swap here, dunno why } } break; } case 0x2D: // carriage return { ty_draw(); TY_CC_CUR_X = 1; if ( TY_OSD_flags & TY_OSD_MODE ) { if ( TY_CC_stat > TY_CCPAINTON ) ty_RollupBuf ( TY_CC_CUR_Y - TY_CC_stat + 1 , TY_CC_CUR_Y - TY_CC_stat + 2, TY_CC_stat - 1 ); else TY_CC_CUR_Y++; } break; } case 0x2F: // end caption + swap memory { ty_draw(); /* FALL THROUGH TO 0x2E */ } case 0x2E: // erase non-displayed memory { if ( TY_OSD_debug && TY_CC_ptr != TY_CC_buf ) mp_msg( MSGT_DEMUX, MSGL_DBG3, "(TY_OSD_debug) %s\n", TY_CC_buf ); if ( TY_OSD_flags & TY_OSD_MODE ) ty_ClearOSD( 1 ); TY_CC_CUR_X = 1; TY_CC_CUR_Y = -1; TY_CC_ptr = TY_CC_buf; memset( TY_CC_buf, 0, sizeof( TY_CC_buf ) ); } } break; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -