Annotation of margi2/video.c, revision 1.4

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

LinuxTV legacy CVS <linuxtv.org/cvs>