Mercurial > mplayer.hg
view sub_cc.c @ 13568:1cb0e1833515
Currently vbeGetProtModeInfo call the 0x4f0a function of int 10h the get
a simple 32 bits protected mode interface to some VESA functions. This
protected mode interface is interesting because it's quicker than the
raw int 10h interface.
Unfortunatly, begining with VBE 3.0, the 0x4f0a function is optional,
and some video cards don't implement it (3dfx, intel 845/855/865...).
This protected mode interface is then only used in vbeSetWindow and
vbeSetDisplayStart :
?- vbeSetWindow already implement an alternative methode if protected
mode interface is not available.
?- vbeSetDisplayStart also contain an alternative implementation, but
this one is disabled with a #if 0. I don't exactly know why because
it works well !
So currently, cards which don't have the 0x4f0a function are not
supported. This patch correct this.
?- vbeGetProtModeInfo failure is not fatal.
?- vbeSetDisplayStart has it's alternative implementation reenabled.
? ?it's used only with cards which don't have the 0x4f0a function
? ?so this won't make any difference for cards which were already
? ?working.
This patch also make the failure of vbeGetModeInfo not fatal. The
VBE 3.0 standard state that GetModeInfo can fail with some mode
which are listed as supported if the mode can't be used in the
current situation (not enough video memory for example). So a
failure of vbeGetModeInfo don't mean that other modes won't work
and should really not be fatal.
patch by Aurelien Jacobs <aurel@gnuage.org>
author | faust3 |
---|---|
date | Wed, 06 Oct 2004 08:42:13 +0000 |
parents | 9fc45fe0d444 |
children | f580a7755ac5 |
line wrap: on
line source
/* * sub_cc.c - Decoder for Closed Captions * * This decoder relies on MPlayer's OSD to display subtitles. * Be warned that the decoding is somewhat preliminary, though it basically works. * * Most notably, only the text information is decoded as of now, discarding color, * background and position info (see source below). * * by Matteo Giani * * uses source from the xine closed captions decoder */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "sub_cc.h" #include "subreader.h" #include "libvo/video_out.h" #include "libvo/sub.h" #define CC_INPUTBUFFER_SIZE 256 #define CC_MAX_LINE_LENGTH 64 static char chartbl[128]; static subtitle buf1,buf2; static subtitle *fb,*bb; static unsigned int cursor_pos=0; static int inited=0; static unsigned char inputbuffer[CC_INPUTBUFFER_SIZE]; static unsigned int inputlength; static void build_char_table(void) { int i; /* first the normal ASCII codes */ for (i = 0; i < 128; i++) chartbl[i] = (char) i; /* now the special codes */ chartbl[0x2a] = 'á'; chartbl[0x5c] = 'é'; chartbl[0x5e] = 'í'; chartbl[0x5f] = 'ó'; chartbl[0x60] = 'ú'; chartbl[0x7b] = 'ç'; chartbl[0x7c] = '÷'; chartbl[0x7d] = 'Ñ'; chartbl[0x7e] = 'ñ'; chartbl[0x7f] = '¤'; /* FIXME: this should be a solid block */ } static void clear_buffer(subtitle *buf) { int i; buf->lines=0; for(i=0;i<SUB_MAX_TEXT;i++) if(buf->text[i]) {free(buf->text[i]);buf->text[i]=NULL;} } void subcc_init() { int i; //printf("subcc_init(): initing...\n"); build_char_table(); for(i=0;i<SUB_MAX_TEXT;i++) {buf1.text[i]=buf2.text[i]=NULL;} buf1.lines=buf2.lines=0; fb=&buf1; bb=&buf2; inited=1; } static void append_char(char c) { if(!bb->lines) {bb->lines++; cursor_pos=0;} if(bb->text[bb->lines - 1]==NULL) { bb->text[bb->lines - 1]=malloc(CC_MAX_LINE_LENGTH); memset(bb->text[bb->lines - 1],0,CC_MAX_LINE_LENGTH); cursor_pos=0; } if(c=='\n') { if(cursor_pos>0) bb->lines++;cursor_pos=0; } else { if(cursor_pos==CC_MAX_LINE_LENGTH-1) { printf("sub_cc.c: append_char() reached CC_MAX_LINE_LENGTH!\n"); return; } bb->text[bb->lines - 1][cursor_pos++]=c; } } static void swap_buffers() { subtitle *foo; foo=fb; fb=bb; bb=foo; } static void display_buffer(subtitle * buf) { vo_sub=buf; vo_osd_changed(OSDTYPE_SUBTITLE); } static void cc_decode_EIA608(unsigned short int data) { static unsigned short int lastcode=0x0000; unsigned char c1 = data & 0x7f; unsigned char c2 = (data >> 8) & 0x7f; if (c1 & 0x60) { /* normal character, 0x20 <= c1 <= 0x7f */ append_char(chartbl[c1]); if(c2 & 0x60) /*c2 might not be a normal char even if c1 is*/ append_char(chartbl[c2]); } else if (c1 & 0x10) // control code / special char { // int channel= (c1 & 0x08) >> 3; c1&=~0x08; if(data!=lastcode) { if(c2 & 0x40) { /*PAC, Preamble Address Code */ append_char('\n'); /*FIXME properly interpret PACs*/ } else switch(c1) { case 0x10: break; // ext attribute case 0x11: if((c2 & 0x30)==0x30) { //printf("[debug]:Special char (ignored)\n"); /*cc_decode_special_char()*/; } else if (c2 & 0x20) { //printf("[debug]: midrow_attr (ignored)\n"); /*cc_decode_midrow_attr()*/; } break; case 0x14: switch(c2) { case 0x2C: display_buffer(NULL); //EDM clear_buffer(fb); break; case 0x2d: append_char('\n'); //carriage return break; case 0x2e: clear_buffer(bb); //ENM break; case 0x2f: swap_buffers(); //Swap buffers display_buffer(fb); clear_buffer(bb); break; } break; case 0x17: if( c2>=0x21 && c2<=0x23) //TAB { break; } } } } lastcode=data; } static void subcc_decode() { /* The first number may denote a channel number. I don't have the * EIA-708 standard, so it is hard to say. * From what I could figure out so far, the general format seems to be: * * repeat * * 0xfe starts 2 byte sequence of unknown purpose. It might denote * field #2 in line 21 of the VBI. We'll ignore it for the * time being. * * 0xff starts 2 byte EIA-608 sequence, field #1 in line 21 of the VBI. * Followed by a 3-code triplet that starts either with 0xff or * 0xfe. In either case, the following triplet needs to be ignored * for line 21, field 1. * * 0x00 is padding, followed by 2 more 0x00. * * 0x01 always seems to appear at the beginning, always seems to * be followed by 0xf8, 8-bit number. * The lower 7 bits of this 8-bit number seem to denote the * number of code triplets that follow. * The most significant bit denotes whether the Line 21 field 1 * captioning information is at odd or even triplet offsets from this * beginning triplet. 1 denotes odd offsets, 0 denotes even offsets. * * Most captions are encoded with odd offsets, so this is what we * will assume. * * until end of packet */ unsigned char *current = inputbuffer; unsigned int curbytes = 0; unsigned char data1, data2; unsigned char cc_code; int odd_offset = 1; while (curbytes < inputlength) { int skip = 2; cc_code = *(current); if (inputlength - curbytes < 2) { #ifdef LOG_DEBUG fprintf(stderr, "Not enough data for 2-byte CC encoding\n"); #endif break; } data1 = *(current+1); data2 = *(current + 2); current++; curbytes++; switch (cc_code) { case 0xfe: /* expect 2 byte encoding (perhaps CC3, CC4?) */ /* ignore for time being */ skip = 2; break; case 0xff: /* expect EIA-608 CC1/CC2 encoding */ // FIXME check parity! // Parity check omitted assuming we are reading from a DVD and therefore // we should encounter no "transmission errors". cc_decode_EIA608(data1 | (data2 << 8)); skip = 5; break; case 0x00: /* This seems to be just padding */ skip = 2; break; case 0x01: odd_offset = data2 & 0x80; if (odd_offset) skip = 2; else skip = 5; break; default: //#ifdef LOG_DEBUG fprintf(stderr, "Unknown CC encoding: %x\n", cc_code); //#endif skip = 2; break; } current += skip; curbytes += skip; } } void subcc_process_data(unsigned char *inputdata,unsigned int len) { if(!subcc_enabled) return; if(!inited) subcc_init(); memcpy(inputbuffer,inputdata,len); inputlength=len; subcc_decode(); }