int cVideo::setAspectRatio(int aspect, int mode) { static int _mode = -1; static int _aspect = -1; vidDispSize_t dsize = VID_DISPSIZE_UNKNOWN; vidDispMode_t dmode = VID_DISPMODE_NORM; /* 1 = 4:3, 3 = 16:9, 4 = 2.21:1, 0 = unknown */ int v_ar = getAspectRatio(); if (aspect != -1) _aspect = aspect; if (mode != -1) _mode = mode; lt_info("%s(%d, %d)_(%d, %d) v_ar %d\n", __FUNCTION__, aspect, mode, _aspect, _mode, v_ar); /* values are hardcoded in neutrino_menue.cpp, "2" is 14:9 -> not used */ if (_aspect != -1) { switch(_aspect) { case 1: dsize = VID_DISPSIZE_4x3; scartvoltage = 12; break; case 3: dsize = VID_DISPSIZE_16x9; scartvoltage = 6; break; default: break; } } if (_mode != -1) { int zoom = 100 * 16 / 14; /* 16:9 vs 14:9 */ switch(_mode) { case DISPLAY_AR_MODE_NONE: if (v_ar < 3) dsize = VID_DISPSIZE_4x3; else dsize = VID_DISPSIZE_16x9; break; case DISPLAY_AR_MODE_LETTERBOX: dmode = VID_DISPMODE_LETTERBOX; break; case DISPLAY_AR_MODE_PANSCAN: zoom = 100 * 5 / 4; case DISPLAY_AR_MODE_PANSCAN2: if ((v_ar < 3 && _aspect == 3) || (v_ar >= 3 && _aspect == 1)) { /* unfortunately, this partly reimplements the setZoom code... */ dsize = VID_DISPSIZE_UNKNOWN; dmode = VID_DISPMODE_SCALE; SCALEINFO s; memset(&s, 0, sizeof(s)); if (v_ar < 3) { /* 4:3 */ s.src.hori_size = 720; s.src.vert_size = 2 * 576 - 576 * zoom / 100; s.des.hori_size = zoom * 720 * 3/4 / 100; s.des.vert_size = 576; } else { s.src.hori_size = 2 * 720 - 720 * zoom / 100; s.src.vert_size = 576; s.des.hori_size = 720; s.des.vert_size = zoom * 576 * 3/4 / 100; } s.des.vert_off = (576 - s.des.vert_size) / 2; s.des.hori_off = (720 - s.des.hori_size) / 2; lt_debug("PANSCAN2: %d%% src: %d:%d:%d:%d dst: %d:%d:%d:%d\n", zoom, s.src.hori_off,s.src.vert_off,s.src.hori_size,s.src.vert_size, s.des.hori_off,s.des.vert_off,s.des.hori_size,s.des.vert_size); fop(ioctl, MPEG_VID_SCALE_ON); fop(ioctl, MPEG_VID_SET_SCALE_POS, &s); } default: break; } if (dmode != VID_DISPMODE_SCALE) fop(ioctl, MPEG_VID_SCALE_OFF); setCroppingMode(dmode); } const char *ds[] = { "4x3", "16x9", "2.21", "unknown" }; const char *d; if (dsize >=0 && dsize < 4) d = ds[dsize]; else d = "invalid!"; lt_debug("%s dispsize(%d) (%s)\n", __FUNCTION__, dsize, d); fop(ioctl, MPEG_VID_SET_DISPSIZE, dsize); int avsfd = open("/dev/stb/tdsystem", O_RDONLY); if (avsfd < 0) { perror("open tdsystem"); return 0; } if (!noscart && scartvoltage > 0 && video_standby == 0) { lt_info("%s set SCART_PIN_8 to %dV\n", __FUNCTION__, scartvoltage); if (ioctl(avsfd, IOC_AVS_SCART_PIN8_SET, scartvoltage) < 0) perror("IOC_AVS_SCART_PIN8_SET"); } close(avsfd); return 0; }
/* set zoom in percent (100% == 1:1) */ int cVideo::setZoom(int zoom) { if (zoom == -1) // "auto" reset zoom = *zoomvalue; if (zoom > 150 || zoom < 100) return -1; *zoomvalue = zoom; if (zoom == 100) { setCroppingMode(croppingMode); return fop(ioctl, MPEG_VID_SCALE_OFF); } /* the SCALEINFO describes the source and destination of the scaled video. "src" is the part of the source picture that gets scaled, "dst" is the area on the screen where this part is displayed Messing around with MPEG_VID_SET_SCALE_POS disables the automatic letterboxing, which, as I guess, is only a special case of MPEG_VID_SET_SCALE_POS. Therefor we need to care for letterboxing etc here, which is probably not yet totally correct */ SCALEINFO s; memset(&s, 0, sizeof(s)); if (zoom > 100) { /* 1 = 4:3, 3 = 16:9, 4 = 2.21:1, 0 = unknown */ int x = getAspectRatio(); if (x < 3 && croppingMode == VID_DISPMODE_NORM) { s.src.hori_size = 720; s.des.hori_size = 720 * 3/4 * zoom / 100; if (s.des.hori_size > 720) { /* the destination exceeds the screen size. TODO: decrease source size to allow higher zoom factors (is this useful ?) */ s.des.hori_size = 720; zoom = 133; // (720*4*100)/(720*3) *zoomvalue = zoom; } } else { s.src.hori_size = 2 * 720 - 720 * zoom / 100; s.des.hori_size = 720; } s.src.vert_size = 2 * 576 - 576 * zoom / 100; s.des.hori_off = (720 - s.des.hori_size) / 2; s.des.vert_size = 576; } /* not working correctly (wrong formula) and does not make sense IMHO else { s.src.hori_size = 720; s.src.vert_size = 576; s.des.hori_size = 720 * zoom / 100; s.des.vert_size = 576 * zoom / 100; s.des.hori_off = (720 - s.des.hori_size) / 2; s.des.vert_off = (576 - s.des.vert_size) / 2; } */ lt_debug("%s %d%% src: %d:%d:%d:%d dst: %d:%d:%d:%d\n", __FUNCTION__, zoom, s.src.hori_off,s.src.vert_off,s.src.hori_size,s.src.vert_size, s.des.hori_off,s.des.vert_off,s.des.hori_size,s.des.vert_size); fop(ioctl, MPEG_VID_SET_DISPMODE, VID_DISPMODE_SCALE); fop(ioctl, MPEG_VID_SCALE_ON); return fop(ioctl, MPEG_VID_SET_SCALE_POS, &s); }
void CVideo::setVideoFormat(int format) { #if defined HAVE_DREAMBOX_HARDWARE || defined HAVE_DBOX_HARDWARE || defined HAVE_IPBOX_HARDWARE video_displayformat_t videoDisplayFormat; int avsiosfncFormat; int wss; #endif #ifdef HAVE_TRIPLEDRAGON vidDispSize_t dispsize; vidDispMode_t videoDisplayFormat; #endif #if defined HAVE_DREAMBOX_HARDWARE || defined HAVE_DBOX_HARDWARE || defined HAVE_IPBOX_HARDWARE || defined HAVE_TRIPLEDRAGON int _fd; #endif const char *format_string[] = { "auto", "16:9", "4:3(LB)", "4:3(PS)" }; /* 16:9 : fnc 1 4:3 : fnc 2 */ if (format == 0) // automatic switch { DBG("setting VideoFormat to auto"); int activeAspectRatio; if (settings.vcr) activeAspectRatio = settings.aspectRatio_vcr; else activeAspectRatio = settings.aspectRatio_dvb; switch (activeAspectRatio) { case 0: // 4:3 format= 2; break; case 1: // 16:9 case 2: // 21,1:1 format = 1; break; default: format = 2; // damits nicht ausgeht beim starten :) } } printf("[CVideo::%s] output format: ", __FUNCTION__); if (format >= 0 && format <= 3) printf("%s\n", format_string[format]); else printf("unknown (%d)\n", format); #if defined HAVE_DREAMBOX_HARDWARE || defined HAVE_DBOX_HARDWARE || defined HAVE_IPBOX_HARDWARE if ((_fd = open(AVS_DEVICE, O_RDWR)) < 0) perror("[CVideo] " AVS_DEVICE); else { if (format < 0) format = 0; avsiosfncFormat = format; if (settings.boxtype == CControld::TUXBOX_MAKER_PHILIPS) { switch (format) { case 1: avsiosfncFormat = 2; break; case 2: avsiosfncFormat = 3; break; } } if (ioctl(_fd, AVSIOSFNC, &avsiosfncFormat) < 0) perror("[CVideo] AVSIOSFNC"); close(_fd); } switch (format) { // ? case AVS_FNCOUT_INTTV : videoDisplayFormat = VIDEO_PAN_SCAN; case AVS_FNCOUT_EXT169: videoDisplayFormat = VIDEO_CENTER_CUT_OUT; wss = SAA_WSS_169F; break; case AVS_FNCOUT_EXT43: videoDisplayFormat = VIDEO_LETTER_BOX; wss = SAA_WSS_43F; break; case AVS_FNCOUT_EXT43_1: videoDisplayFormat = VIDEO_PAN_SCAN; wss = SAA_WSS_43F; break; default: videoDisplayFormat = VIDEO_LETTER_BOX; wss = SAA_WSS_43F; break; } setCroppingMode(videoDisplayFormat); if ((_fd = open(SAA7126_DEVICE, O_RDWR)) < 0) perror("[CVideo] " SAA7126_DEVICE); else { if (ioctl(_fd, SAAIOSWSS, &wss) < 0) perror("[CVideo] SAAIOSWSS"); close(_fd); } #endif #ifdef HAVE_TRIPLEDRAGON unsigned int volt = 12; switch(format) { case 1: /* 16:9 */ videoDisplayFormat = VID_DISPMODE_NORM; dispsize = VID_DISPSIZE_16x9; volt = 6; break; case 3: /* 4:3 PS */ videoDisplayFormat = VID_DISPMODE_NORM; dispsize = VID_DISPSIZE_4x3; break; default: volt = 0; // fallthrough case 2: /* 4:3 LB */ videoDisplayFormat = VID_DISPMODE_LETTERBOX; dispsize = VID_DISPSIZE_4x3; break; } if (fop(ioctl, MPEG_VID_SET_DISPSIZE, dispsize) < 0) perror("[CVideo] MPEG_VID_SET_DISPSIZE"); if ((_fd = open(AVS_DEVICE, O_RDWR)) < 0) perror("[CVideo] " AVS_DEVICE); else { DBG("setting PIN 8 to %dV", volt); if (ioctl(_fd, IOC_AVS_SCART_PIN8_SET, volt) < 0) WARN("IOC_AVS_SCART_PIN8_SET: %m"); close(_fd); } setCroppingMode(videoDisplayFormat); if (*zoomvalue != 100) setZoom(*zoomvalue); #endif #if 0 /* todo: fix. probably outside of video.cpp. */ static int last_videoformat = AVS_FNCOUT_EXT43; if (format != last_videoformat) { switch (format) { case AVS_FNCOUT_EXT169: { execute_start_file(FORMAT_16_9_FILE); CIRSend irs("16:9"); irs.Send(); last_videoformat = format; break; } case AVS_FNCOUT_EXT43: { execute_start_file(FORMAT_4_3_FILE); CIRSend irs("4:3"); irs.Send(); last_videoformat = format; break; } default: break; } } #endif }