Annotation of margi2/video.c, revision 1.3

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

LinuxTV legacy CVS <linuxtv.org/cvs>