Annotation of margi2/video.c, revision 1.1
1.1 ! cvs 1: /*
! 2: video.c
! 3:
! 4: Copyright (C) Christian Wolff for convergence integrated media.
! 5:
! 6: This program is free software; you can redistribute it and/or modify
! 7: it under the terms of the GNU General Public License as published by
! 8: the Free Software Foundation; either version 2 of the License, or
! 9: (at your option) any later version.
! 10:
! 11: This program is distributed in the hope that it will be useful,
! 12: but WITHOUT ANY WARRANTY; without even the implied warranty of
! 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! 14: GNU General Public License for more details.
! 15:
! 16: You should have received a copy of the GNU General Public License
! 17: along with this program; if not, write to the Free Software
! 18: Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
! 19: */
! 20:
! 21: //
! 22: // Video Decoder
! 23: //
! 24: #define __NO_VERSION__
! 25:
! 26: #include "video.h"
! 27: #include "l64021.h"
! 28: #include "dram.h"
! 29:
! 30: // Set the background of the OSD and SPU and it's color
! 31: // mode=0: Video on Black
! 32: // mode=1: Black
! 33: // mode=2: Selected Color
! 34: // mode=3: Video on Selected Color
! 35: void VideoSetBackground(struct cvdv_cards *card, int mode, u8 Y, u8 Cb,
! 36: u8 Cr)
! 37: {
! 38: DecoderWriteByte(card, 0x10A, Y);
! 39: DecoderWriteByte(card, 0x10B, Cb);
! 40: DecoderWriteByte(card, 0x10C, Cr);
! 41: DecoderMaskByte(card, 0x109, 0xC0, mode << 6);
! 42: }
! 43:
! 44:
! 45: int DecoderStartDecode(struct cvdv_cards *card)
! 46: {
! 47: DecoderSetByte(card, 0x0F6, 0x01);
! 48: card->videosync = 1;
! 49: return 0;
! 50: }
! 51:
! 52: int DecoderStopDecode(struct cvdv_cards *card)
! 53: {
! 54: DecoderDelByte(card, 0x0F6, 0x01);
! 55: card->videosync = 0;
! 56: return 0;
! 57: }
! 58:
! 59: // Sets Display Override (Still Image Display) to Frame Buffer at specified addresses,
! 60: // addresses are 16 bit, in 64 byte resolution
! 61: // mode: 0=off, 1=Frame, 2=Field
! 62: // width: width of the still picture in 8 pixel units
! 63: int DecoderStillImageDisplay(struct cvdv_cards *card, int mode, int width,
! 64: u16 LumaAddr, u16 ChromaAddr)
! 65: {
! 66: DecoderStopDecode(card);
! 67: DecoderWriteWord(card, 0x11D, LumaAddr);
! 68: DecoderWriteWord(card, 0x11F, ChromaAddr);
! 69: DecoderWriteByte(card, 0x11B, width & 0x7F);
! 70: DecoderMaskByte(card, 0x109, 0x30, (mode & 3) << 4); // Display Override Mode
! 71: return 0;
! 72: }
! 73:
! 74: // Frees allocated frame buffers
! 75: int DecoderKillFrameBuffers(struct cvdv_cards *card)
! 76: {
! 77: printk(KERN_DEBUG LOGNAME ": -- DecoderKillFrameBuffers\n");
! 78: DecoderStopDecode(card);
! 79: DRAMFree(card, card->FrameStoreLuma1);
! 80: card->FrameStoreLuma1 = BLANK;
! 81: DRAMFree(card, card->FrameStoreChroma1);
! 82: card->FrameStoreChroma1 = BLANK;
! 83: DRAMFree(card, card->FrameStoreLuma2);
! 84: card->FrameStoreLuma2 = BLANK;
! 85: DRAMFree(card, card->FrameStoreChroma2);
! 86: card->FrameStoreChroma2 = BLANK;
! 87: DRAMFree(card, card->FrameStoreLumaB);
! 88: card->FrameStoreLumaB = BLANK;
! 89: DRAMFree(card, card->FrameStoreChromaB);
! 90: card->FrameStoreChromaB = BLANK;
! 91: card->FrameBuffersAllocated = 0;
! 92: // DecoderWriteWord(
! 93: return 0;
! 94: }
! 95:
! 96: int DecoderSetFrameBuffers(struct cvdv_cards *card, int lines, // number of lines of the decoded MPEG
! 97: int TwoFrames, // 1 if no B-Frames are present in the video stream, thus allowing only 2 framestores
! 98: int RMM) // 1 if RMM
! 99: {
! 100: #define SEGMENTS 44 // 40..54 for PAL, 44 recommended
! 101: #define BUFFERSET(buf,adr,align) if (buf>0) {\
! 102: if (buf&((1<<align)-1)) buf=(buf&~((1<<align)-1))+(1<<align);\
! 103: addr=DRAMAlloc(card,buf,1<<align);\
! 104: if (addr==BLANK) return adr;\
! 105: card->buf=addr;\
! 106: addr>>=align;\
! 107: DecoderWriteByte(card,adr,addr&0xFF);\
! 108: DecoderWriteByte(card,adr+1,(addr>>8)&(0x00FF));\
! 109: }
! 110: u32 addr;
! 111: int pixel, byteperline; // visible pixel per video line, same for PAL and NTSC
! 112: int FrameStoreLuma1, FrameStoreChroma1,
! 113: FrameStoreLuma2, FrameStoreChroma2,
! 114: FrameStoreLumaB, FrameStoreChromaB;
! 115: printk(KERN_DEBUG LOGNAME ": -- DecoderSetFrameBuffers\n");
! 116: DecoderStopDecode(card);
! 117: //DecoderStopChannel(card);
! 118: //lines=((CCIR601Lines(card->videomode)==625)?576:480);
! 119: byteperline = (DecoderReadByte(card, 0x116) & 0x7F) * 8; // main 64-bit reads per line
! 120: pixel = byteperline * lines;
! 121: FrameStoreLuma1 = FrameStoreLuma2 = FrameStoreLumaB = pixel >> 1; // 8 bit luma per pixel in words
! 122: FrameStoreChroma1 = FrameStoreChroma2 = FrameStoreChromaB =
! 123: pixel >> 2; // 8+8 bit chroma every 2nd pixel every 2nd line
! 124: if (card->FrameBuffersAllocated)
! 125: DecoderKillFrameBuffers(card);
! 126: BUFFERSET(FrameStoreLuma1, 0x0E0, 5); // Anchor Frame Store 1
! 127: BUFFERSET(FrameStoreChroma1, 0x0E2, 5);
! 128: BUFFERSET(FrameStoreLuma2, 0x0E4, 5); // Anchor Frame Store 2
! 129: BUFFERSET(FrameStoreChroma2, 0x0E6, 5);
! 130: if (TwoFrames) {
! 131: DecoderDelByte(card, 0x0F8, 0x01);
! 132: } else {
! 133: // if (CCIR601Lines(card->videomode)==525) { // Normal Mode, NTSC
! 134: if (!RMM) { // Normal Mode, NTSC
! 135: BUFFERSET(FrameStoreLumaB, 0x0E8, 5); // B Frame Store
! 136: BUFFERSET(FrameStoreChromaB, 0x0EA, 5);
! 137: DecoderDelByte(card, 0x0F8, 0x01);
! 138: } else { // Reduced Memory Mode, PAL
! 139: // 44 segments with 8 lines each (8 bit luma + 4 bit chroma)
! 140: // only display modes 4-8, 10, and 11 are allowed
! 141: FrameStoreLumaB =
! 142: (8 * byteperline * SEGMENTS) >> 1;
! 143: FrameStoreChromaB =
! 144: (4 * byteperline * SEGMENTS) >> 1;
! 145: BUFFERSET(FrameStoreLumaB, 0x0E8, 5); // B Frame Store
! 146: BUFFERSET(FrameStoreChromaB, 0x0EA, 5);
! 147: DecoderWriteByte(card, 0x121, SEGMENTS << 1); // Number of segments
! 148: DecoderSetByte(card, 0x0F8, 0x01);
! 149: }
! 150: }
! 151: card->FrameBuffersAllocated = 1;
! 152: #undef SEGMENTS
! 153: #undef BUFFERSET
! 154: return 0;
! 155: }
! 156:
! 157: // returns size of the Video ES Buffer in bytes or 0=error
! 158: u32 DecoderGetVideoESSize(struct cvdv_cards * card)
! 159: {
! 160: if (!card->ChannelBuffersAllocated)
! 161: return 0; // buffer not initialised
! 162: return (u32) ((DecoderReadWord(card, 0x04A) & 0x3FFF) -
! 163: (DecoderReadWord(card, 0x048) & 0x3FFF)) * 256; // bytes
! 164: }
! 165:
! 166: // returns level of fullness in bytes
! 167: u32 DecoderGetVideoESLevel(struct cvdv_cards * card)
! 168: {
! 169: u32 items;
! 170: items = DecoderReadByte(card, 0x086);
! 171: items |= ((DecoderReadWord(card, 0x087) & 0x07FF) << 8);
! 172: items *= 8; // 64 bit per item
! 173: return items;
! 174: }
! 175:
! 176: // pics=0 --> items=bytes
! 177: // pics=1 --> items=pictures
! 178: void DecoderSetVideoPanic(struct cvdv_cards *card, int pics, int items)
! 179: {
! 180: if (pics < 0) {
! 181: DecoderMaskByte(card, 0x045, 0x18, 0x00 << 3); // disable panic mode
! 182: } else {
! 183: if (pics) {
! 184: DecoderWriteMWord(card, 0x086, items & 0x0003FFFF);
! 185: DecoderMaskByte(card, 0x045, 0x18, 0x02 << 3); // set panic mode to "number of pictures" in VideoES
! 186: } else {
! 187: DecoderWriteMWord(card, 0x086,
! 188: (items / 8) & 0x0003FFFF);
! 189: DecoderMaskByte(card, 0x045, 0x18, 0x01 << 3); // set panic mode to "number of 8-byte-frames" in VideoES
! 190: }
! 191: }
! 192: }
! 193:
! 194: int DecoderClose(struct cvdv_cards *card)
! 195: {
! 196: if (card->DecoderOpen) {
! 197: printk(KERN_DEBUG LOGNAME ": -- DecoderClose\n");
! 198: DecoderStopDecode(card);
! 199: DecoderKillFrameBuffers(card);
! 200: card->DecoderOpen = 0;
! 201: card->lastvattr = 0;
! 202: return 0;
! 203: } else
! 204: return 1;
! 205: }
! 206:
! 207: // returns 0 on success, 1 on "picture size too big", 2 on "out of DRAM memory"
! 208: int DecoderOpen(struct cvdv_cards *card, int x, int y, // size of the decoded MPEG picture
! 209: int aspect, // pixel or picture aspect ratio of the MPEG picture: 1=square pixel 2=3:4 3=9:16 4=1:2.21
! 210: int Field, // 0:Frame (interlaced, MPEG-2) , 1:Field (non-interlaced, MPEG-1) structure
! 211: int Letterbox, // 0:PanScan (4:3), 1:letterbox (16:9, 8:3) picture ratio
! 212: int RMM) // 1:use ReducedMemoryMode
! 213: {
! 214: int mode, // Display Mode
! 215: i, factor, // zoom factor
! 216: top, bottom, left, right, width, height, newwidth, newheight, // screen size
! 217: vaspx, vaspy, // output video pixel aspect ratio
! 218: paspx, paspy, // input picture pixel aspect ratio
! 219: SIF; // 0:Full (480/576 lines, MPEG-2), 1:SIF (half, 240/288 lines, MPEG-1) resolution
! 220:
! 221: printk(KERN_DEBUG LOGNAME
! 222: ": -- DecoderOpen x:%d y:%d asp:%d field:%d lt:%d rmm:%d\n",
! 223: x, y, aspect, Field, Letterbox, RMM);
! 224: if ((x <= 0) || (y <= 0))
! 225: return 4; // picture too small
! 226: //if (card->DecoderOpen) return 3;
! 227: DecoderStopDecode(card);
! 228: DecoderClose(card); // closes only, if already open
! 229: vaspy = 11;
! 230: vaspx = ((CCIR601Lines(card->videomode) == 525) ? 10 : 12); // screen pixel aspect ratio
! 231: // note: this aspect ratio applies to 704 pixel width, but the card's default is 720, wich is not 3:4 picture aspect ratio anymore!?
! 232: i = ((x == 720) ? 704 : x); // 720 wide is overscan of 704 wide
! 233: switch (aspect) { // MPEG data pixel aspect ratio
! 234: case 1:
! 235: paspx = 1;
! 236: paspy = 1;
! 237: break;
! 238: default:
! 239: case 2:
! 240: paspx = 4 * y;
! 241: paspy = 3 * i;
! 242: break;
! 243: case 3:
! 244: paspx = 16 * y;
! 245: paspy = 9 * i;
! 246: break;
! 247: case 4:
! 248: paspx = 221 * y;
! 249: paspy = 100 * i;
! 250: break;
! 251: }
! 252: top =
! 253: DecoderReadByte(card,
! 254: 0x129) | ((DecoderReadByte(card, 0x12B) & 0x07)
! 255: << 8); // current Start- and End Column
! 256: bottom =
! 257: DecoderReadByte(card,
! 258: 0x12A) | ((DecoderReadByte(card, 0x12B) & 0x70)
! 259: << 4);
! 260: height = (bottom - top + 1) * 2; // screen (frame) height
! 261: left =
! 262: DecoderReadByte(card,
! 263: 0x12C) | ((DecoderReadByte(card, 0x12E) & 0x07)
! 264: << 8); // current Start- and End Row
! 265: right =
! 266: DecoderReadByte(card,
! 267: 0x12D) | ((DecoderReadByte(card, 0x12E) & 0x70)
! 268: << 4);
! 269: width = (right - left + 1) / 2; // screen width, 2 clocks = 1 pixel
! 270:
! 271: if (RMM)
! 272: DecoderSetByte(card, 0x0F8, 0x01);
! 273: else
! 274: DecoderDelByte(card, 0x0F8, 0x01);
! 275: //RMM=(DecoderReadByte(card,0x0F8)&0x01);
! 276: DecoderWriteByte(card, 0x0EF, 0x08);
! 277:
! 278: //if (x>width) { // Is the picture too wide for the screen?
! 279: // DecoderSetByte(card,0x112,0x40); // Horiz. 2:1 Filter enable
! 280: // x/=2;
! 281: //} else {
! 282: DecoderDelByte(card, 0x112, 0x40); // Horiz. 2:1 Filter disable
! 283: //}
! 284:
! 285:
! 286:
! 287:
! 288: if (1 /*Letterbox */ ) { // Fit to width, reduce height
! 289: newwidth = (x * vaspy * paspx / (paspy * vaspx)); // width in right aspect ratio
! 290: if (newwidth <= 360) { // less then about half the screen size?
! 291: SIF = 1;
! 292: newwidth *= 2;
! 293: } else {
! 294: SIF = 0;
! 295: }
! 296: if ((newwidth == 704) || (newwidth == 720))
! 297: width = newwidth; // standard sizes?
! 298: newheight =
! 299: (y * vaspx * paspy / (paspx * vaspy)) * width / x;
! 300: factor = newheight * 100 / y;
! 301: printk(KERN_INFO LOGNAME
! 302: ": Decoder Open: Display size %d x %d, Picture size %d x %d, Demanded size: %d x %d, factor %d\n",
! 303: width, height, x, y, newwidth, newheight, factor);
! 304: // 16:9 Letterbox
! 305: if ((aspect == 3)
! 306: || ((aspect == 0)
! 307: && (((factor >= 65) && (factor <= 80))
! 308: || ((factor >= 140) && (factor <= 160))))) {
! 309: if (SIF) { // height * 1.5, SIF Letterbox
! 310: if (RMM)
! 311: return 1; // not supported!
! 312: height = (y * 3) / 2 - 2;
! 313: mode = 3;
! 314: } else { // height * 0.75, 16:9 Letterbox
! 315: height = (y * 3) / 4 - 2;
! 316: mode = 8;
! 317: }
! 318: // 2.21:1 Letterbox
! 319: } else if ((aspect == 4)
! 320: || ((aspect == 0)
! 321: && (((factor >= 45) && (factor <= 60))
! 322: || (SIF && ((factor >= 90)
! 323: && (factor <= 110)))))) {
! 324: if (SIF) { // height * 1
! 325: height = y;
! 326: mode = 5;
! 327: } else { // height / 2
! 328: height = y / 2;
! 329: mode = 11;
! 330: }
! 331: // 3:4 aspect ratio
! 332: } else {
! 333: if (SIF) {
! 334: height = y * 2;
! 335: mode = ((Field && ~RMM) ? 9 : 10);
! 336: } else if (newwidth > 720) { // picture too wide, scale down to 3/4
! 337: height = (y * 3) / 4;
! 338: mode = 8;
! 339: } else {
! 340: height = y;
! 341: mode = ((Field) ? 7 : 5);
! 342: // mode=((Field)?5:7);
! 343: }
! 344: }
! 345: width = (x * vaspy * paspx / (paspy * vaspx)) * height / y;
! 346: if (x < width) { // does the picture needs a horizontal blow-up?
! 347: DecoderWriteByte(card, 0x115,
! 348: ((x * 256 + width - 1) / width) & 0xFF); // Horiz.Filter scale, x/width*256, rounded up
! 349: DecoderSetByte(card, 0x114, 0x02); // Horiz.Filter enable
! 350: } else if (x == width) {
! 351: DecoderWriteByte(card, 0x115, 0); // 1:1 scale
! 352: DecoderDelByte(card, 0x114, 0x02); // Horiz.Filter disable
! 353: } else if (x <= 720) {
! 354: width = x;
! 355: DecoderWriteByte(card, 0x115, 0); // 1:1 scale
! 356: DecoderDelByte(card, 0x114, 0x02); // Horiz.Filter disable
! 357: } else { // picture is more than twice the screen width. sigh.
! 358: return 1;
! 359: }
! 360: } else { // Pan-Scan, fit height to maximum
! 361: DecoderSetByte(card, 0x117, 0x40); // pan-scan from bitstream
! 362: //TODO
! 363: newwidth = (x * vaspy * paspx / (paspy * vaspx)); // width in right aspect ratio
! 364: newheight = y;
! 365: if (newheight <= 288) { // less then about half the screen size?
! 366: SIF = 1;
! 367: newheight *= 2;
! 368: } else {
! 369: SIF = 0;
! 370: }
! 371: if ((newwidth == 704) || (newwidth == 720))
! 372: width = newwidth; // standard sizes?
! 373: //newheight=(y*vaspx*paspy/(paspx*vaspy))*width/x;
! 374: factor = newheight * 100 / y;
! 375: printk(KERN_INFO LOGNAME
! 376: ": Decoder Open: Display size %d x %d, Picture size %d x %d, Demanded size: %d x %d, factor %d\n",
! 377: width, height, x, y, newwidth, newheight, factor);
! 378: if (aspect == 3) { // 16:9 Letterbox
! 379: if (SIF) { // height * 1.5, SIF Letterbox
! 380: if (RMM)
! 381: return 1; // not supported!
! 382: height = (y * 3) / 2;
! 383: mode = 3;
! 384: } else { // height * 0.75, 16:9 Letterbox
! 385: height = (y * 3) / 4;
! 386: mode = 8;
! 387: }
! 388: } else if (aspect == 4) { // 2.21:1 Letterbox
! 389: if (SIF) { // height * 1
! 390: height = y;
! 391: mode = 5;
! 392: } else { // height / 2
! 393: height = y / 2;
! 394: mode = 11;
! 395: }
! 396: } else if (aspect == 2) { // 3:4 aspect ratio
! 397: if (SIF) {
! 398: height = y * 2;
! 399: mode = ((Field && ~RMM) ? 9 : 10);
! 400: } else if (newwidth > 720) { // picture too wide, scale down to 3/4
! 401: height = (y * 3) / 4;
! 402: mode = 8;
! 403: } else {
! 404: height = y;
! 405: mode = ((Field) ? 7 : 5);
! 406: // mode=((Field)?5:7);
! 407: }
! 408: }
! 409: width = (x * vaspy * paspx / (paspy * vaspx)) * height / y;
! 410: if (x < width) { // does the picture needs a horizontal blow-up?
! 411: DecoderWriteByte(card, 0x115,
! 412: ((x * 256 + width - 1) / width) & 0xFF); // Horiz.Filter scale, x/width*256, rounded up
! 413: DecoderSetByte(card, 0x114, 0x02); // Horiz.Filter enable
! 414: } else if (x == width) {
! 415: DecoderWriteByte(card, 0x115, 0); // 1:1 scale
! 416: DecoderDelByte(card, 0x114, 0x02); // Horiz.Filter disable
! 417: } else if (x <= 720) {
! 418: width = x;
! 419: DecoderWriteByte(card, 0x115, 0); // 1:1 scale
! 420: DecoderDelByte(card, 0x114, 0x02); // Horiz.Filter disable
! 421: } else { // picture is more than twice the screen width. sigh.
! 422: return 1;
! 423: }
! 424: }
! 425: printk(KERN_INFO LOGNAME
! 426: ": Decoder Open: Display size %d x %d, Picture size %d x %d Mode: %d\n",
! 427: width, height, x, y, mode);
! 428:
! 429: // calculate new picture start- and end rows and columns
! 430: height /= 2; // convert back to field height
! 431: top += ((bottom - top + 1 - height) / 2);
! 432: if (top < 0)
! 433: top = 0;
! 434: bottom = top + height - 1;
! 435: width *= 2; // convert back to clocks
! 436: left += ((right - left + 1 - width) / 2);
! 437: if (left < 0)
! 438: left = 0;
! 439: right = left + width - 1;
! 440: DecoderWriteByte(card, 0x12C, left & 0xFF); // Start- and End Column
! 441: DecoderWriteByte(card, 0x12D, right & 0xFF);
! 442: DecoderWriteByte(card, 0x12E,
! 443: ((right >> 4) & 0x70) | ((left >> 8) & 0x07));
! 444: DecoderWriteByte(card, 0x129, top & 0xFF); // Start- and End Row
! 445: DecoderWriteByte(card, 0x12A, bottom & 0xFF);
! 446: DecoderWriteByte(card, 0x12b,
! 447: ((bottom >> 4) & 0x70) | ((top >> 8) & 0x07));
! 448:
! 449: DecoderWriteByte(card, 0x116, ((x + 7) / 8) & 0x7F); // Main Reads per Line
! 450:
! 451: // set the new mode
! 452: DecoderMaskByte(card, 0x114, 0x78, (mode & 0x0F) << 3);
! 453:
! 454: //printk(KERN_INFO LOGNAME ": Decoder Open: top/bottom/width / left/right/height / main reads %d/%d/%d / %d/%d/%d / %d\n",top,bottom,width,left,right,height,((x+7)/8)&0x7F);
! 455:
! 456: // set the frame store buffers
! 457: if ((i = DecoderSetFrameBuffers(card, y, 0, RMM))) {
! 458: printk(KERN_ERR LOGNAME
! 459: ": SetFrameBuffers failed for buffer at 0x%03X\n",
! 460: i);
! 461: DecoderKillFrameBuffers(card);
! 462: return 2;
! 463: }
! 464:
! 465: card->lastvattr = 0;
! 466: card->DecoderOpen = 1;
! 467: return 0;
! 468: }
! 469:
! 470: // displays a still image, whose pixel data is in luma and chroma
! 471: int DecoderShowStill(struct cvdv_cards *card, int width, int height,
! 472: u8 * luma, u8 * chroma)
! 473: {
! 474: u16 addr;
! 475: DecoderOpen(card, width, height,
! 476: (((width == 320) || (width == 640) || (width == 384)
! 477: || (width == 768)) ? 1 : 2),
! 478: ((height < 313) ? 1 : 0), 1, 0);
! 479: addr =
! 480: ((DecoderReadWord(card, 0x11D) == DecoderReadWord(card, 0x0E0))
! 481: ? 0x0E4 : 0x0E0); // choose invisible frame
! 482: DRAMWriteByte(card, DecoderReadWord(card, addr) << 5,
! 483: width * height, luma, 1);
! 484: DRAMWriteByte(card, DecoderReadWord(card, addr + 2) << 5,
! 485: width * height / 2, chroma, 1);
! 486: DecoderStillImageDisplay(card, ((height < 313) ? 2 : 1),
! 487: DecoderReadByte(card, 0x116) & 0x7F,
! 488: DecoderReadWord(card, addr),
! 489: DecoderReadWord(card, addr + 2));
! 490: VideoSetBackground(card, 0, 0, 0, 0); // video on black
! 491: return 0;
! 492: }
! 493:
! 494: // TODO: untested, probably won't work (have to use "main reads per line" instead of width on SIF)
! 495: int DecoderGetStill(struct cvdv_cards *card, int *width, int *height,
! 496: u8 * luma, u8 * chroma)
! 497: {
! 498: int framebuffer;
! 499: if (card->DecoderOpen) {
! 500: //*width=((DecoderReadByte(card,0x12D)|((DecoderReadByte(card,0x12E)&0x70)<<4))-(DecoderReadByte(card,0x12C)|((DecoderReadByte(card,0x12E)&0x07)<<8))+1)/2; // screen width, 2 clocks = 1 pixel
! 501: *width = DecoderReadByte(card, 0x116) * 8;
! 502: *height =
! 503: ((DecoderReadByte
! 504: (card,
! 505: 0x12A) | ((DecoderReadByte(card, 0x12B) & 0x70) <<
! 506: 4)) -
! 507: (DecoderReadByte(card, 0x129) |
! 508: ((DecoderReadByte(card, 0x12B) & 0x07) << 8)) + 1) * 2; // screen (frame) height
! 509: if ((luma != NULL) && (chroma != NULL)) {
! 510: framebuffer =
! 511: (((DecoderReadByte(card, 0x0EE) & 0x0C) == 1) ?
! 512: 0x0E4 : 0x0E0);
! 513: DRAMReadByte(card,
! 514: DecoderReadWord(card,
! 515: framebuffer) << 5,
! 516: (*width) * (*height), luma, 1);
! 517: DRAMReadByte(card,
! 518: DecoderReadWord(card,
! 519: framebuffer + 2) << 5,
! 520: (*width) * (*height) / 2, chroma, 1);
! 521: }
! 522: return 0;
! 523: } else
! 524: return 1;
! 525: }
LinuxTV legacy CVS <linuxtv.org/cvs>