diff --git a/libtriple/video_td.cpp b/libtriple/video_td.cpp new file mode 100644 index 0000000..a5a9038 --- /dev/null +++ b/libtriple/video_td.cpp @@ -0,0 +1,545 @@ +/* + * $Id$ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include + +#include +#include + +//#include +#include +//#include + +#include +#include +#include "video_td.h" +#include +#define VIDEO_DEVICE "/dev/" DEVICE_NAME_VIDEO + +cVideo * videoDecoder = NULL; +int system_rev = 0; + +extern struct Ssettings settings; + +cVideo::cVideo(int, void *, void *) +{ + if ((fd = open(VIDEO_DEVICE, O_RDWR)) < 0) + ERROR(VIDEO_DEVICE); + + playstate = VIDEO_STOPPED; + croppingMode = VID_DISPMODE_NORM; + outputformat = VID_OUTFMT_RGBC_SVIDEO; + scartvoltage = -1; + z[0] = 100; + z[1] = 100; + zoomvalue = &z[0]; + const char *blanknames[2] = { "/share/tuxbox/blank_576.mpg", "/share/tuxbox/blank_480.mpg" }; + int blankfd; + struct stat st; + + for (int i = 0; i < 2; i++) + { + blank_data[i] = NULL; /* initialize */ + blank_size[i] = 0; + blankfd = open(blanknames[i], O_RDONLY); + if (blankfd < 0) + { + WARN("cannot open %s: %m", blanknames[i]); + continue; + } + if (fstat(blankfd, &st) != -1 && st.st_size > 0) + { + blank_size[i] = st.st_size; + blank_data[i] = malloc(blank_size[i]); + if (! blank_data[i]) + ERROR("cannot malloc memory"); + else if (read(blankfd, blank_data[i], blank_size[i]) != blank_size[i]) + { + ERROR("short read"); + free(blank_data[i]); /* don't leak... */ + blank_data[i] = NULL; + } + } + close(blankfd); + } +} + +cVideo::~cVideo(void) +{ + playstate = VIDEO_STOPPED; + for (int i = 0; i < 2; i++) + { + if (blank_data[i]) + free(blank_data[i]); + blank_data[i] = NULL; + } + /* disable DACs and SCART voltage */ + Standby(true); + if (fd >= 0) + close(fd); +} + +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; + fprintf(stderr, "cVideo::setAspectRatio(%d, %d)_(%d, %d) v_ar %d\n", 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) + { + switch(_mode) + { + case DISPLAY_AR_MODE_PANSCAN: + if (v_ar < 3) + dsize = VID_DISPSIZE_4x3; + break; + case DISPLAY_AR_MODE_LETTERBOX: + dmode = VID_DISPMODE_LETTERBOX; + break; + case DISPLAY_AR_MODE_PANSCAN2: + if ((v_ar < 3 && _aspect == 3) || (v_ar >= 3 && _aspect == 1)) + { + /* unfortunately, this partly reimplements the setZoom code... */ + int zoom = 100 * 16 / 14; /* 16:9 vs 14:9 */ + 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; + } + 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("cVideo::setAspectRatio:dispsize(%d) (%s)\n", 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; + } + lt_debug("cVideo::setAspectRatio: setting SCART_PIN_8 to %dV\n", scartvoltage); + if (scartvoltage > 0 && ioctl(avsfd, IOC_AVS_SCART_PIN8_SET, scartvoltage) < 0) + perror("IOC_AVS_SCART_PIN8_SET"); + close(avsfd); + return 0; +} + +int cVideo::getAspectRatio(void) +{ + VIDEOINFO v; + /* this memset silences *TONS* of valgrind warnings */ + memset(&v, 0, sizeof(v)); + quiet_fop(ioctl, MPEG_VID_GET_V_INFO, &v); + if (v.pel_aspect_ratio < VID_DISPSIZE_4x3 || v.pel_aspect_ratio > VID_DISPSIZE_UNKNOWN) + { + WARN("invalid value %d, returning 0 for 'unknown' fd: %d", v.pel_aspect_ratio, fd); + return 0; + } + /* convert to Coolstream api values. Taken from streaminfo2.cpp */ + switch (v.pel_aspect_ratio) + { + case VID_DISPSIZE_4x3: + return 1; + case VID_DISPSIZE_16x9: + return 3; + case VID_DISPSIZE_221x100: + return 4; + default: + return 0; + } +} + +int cVideo::setCroppingMode(vidDispMode_t format) +{ + croppingMode = format; + const char *format_string[] = { "norm", "letterbox", "unknown", "mode_1_2", "mode_1_4", "mode_2x", "scale", "disexp" }; + const char *f; + if (format >= VID_DISPMODE_NORM && format <= VID_DISPMODE_DISEXP) + f = format_string[format]; + else + f = "ILLEGAL format!"; + lt_debug("cVideo::setCroppingMode(%d) => %s\n", format, f); + return fop(ioctl, MPEG_VID_SET_DISPMODE, format); +} + +int cVideo::Start(void * /*PcrChannel*/, unsigned short /*PcrPid*/, unsigned short /*VideoPid*/, void * /*hChannel*/) +{ + if (playstate == VIDEO_PLAYING) + return 0; + if (playstate == VIDEO_FREEZED) /* in theory better, but not in practice :-) */ + fop(ioctl, MPEG_VID_CONTINUE); + playstate = VIDEO_PLAYING; + fop(ioctl, MPEG_VID_PLAY); + return fop(ioctl, MPEG_VID_SYNC_ON, VID_SYNC_AUD); +} + +int cVideo::Stop(bool blank) +{ + //fprintf(stderr, "cVideo::Stop %d\n", blank); + if (blank) + { + playstate = VIDEO_STOPPED; + fop(ioctl, MPEG_VID_STOP); + return setBlank(1); + } + playstate = VIDEO_FREEZED; + return fop(ioctl, MPEG_VID_FREEZE); +} + +int cVideo::setBlank(int) +{ + /* The TripleDragon has no VIDEO_SET_BLANK ioctl. + instead, you write a black still-MPEG Iframe into the decoder. + The original software uses different files for 4:3 and 16:9 and + for PAL and NTSC. I optimized that a little bit + */ + int index = 0; /* default PAL */ + VIDEOINFO v; + BUFINFO buf; + memset(&v, 0, sizeof(v)); + quiet_fop(ioctl, MPEG_VID_GET_V_INFO, &v); + + if ((v.v_size % 240) == 0) /* NTSC */ + { + INFO("NTSC format detected"); + index = 1; + } + + if (blank_data[index] == NULL) /* no MPEG found */ + return -1; + + /* hack: this might work only on those two still-MPEG files! + I diff'ed the 4:3 and the 16:9 still mpeg from the original + soft and spotted the single bit difference, so there is no + need to keep two different MPEGs in memory + If we would read them from disk all the time it would be + slower and it might wake up the drive occasionally */ + if (v.pel_aspect_ratio == VID_DISPSIZE_4x3) + ((char *)blank_data[index])[7] &= ~0x10; // clear the bit + else + ((char *)blank_data[index])[7] |= 0x10; // set the bit + + //WARN("blank[7] == 0x%02x", ((char *)blank_data[index])[7]); + + buf.ulLen = blank_size[index]; + buf.ulStartAdrOff = (int)blank_data[index]; + fop(ioctl, MPEG_VID_STILLP_WRITE, &buf); + return fop(ioctl, MPEG_VID_SELECT_SOURCE, VID_SOURCE_DEMUX); +} + +int cVideo::SetVideoSystem(int video_system, bool remember) +{ + fprintf(stderr, "cVideo::setVideoSystem(%d, %d)\n", video_system, remember); + if (video_system > VID_DISPFMT_SECAM || video_system < 0) + video_system = VID_DISPFMT_PAL; + return fop(ioctl, MPEG_VID_SET_DISPFMT, video_system); +} + +int cVideo::getPlayState(void) +{ + return playstate; +} + +void cVideo::SetVideoMode(analog_mode_t mode) +{ + lt_debug("cVideo::setVideoMode(%d)\n", mode); + switch(mode) + { + case ANALOG_SD_YPRPB_SCART: + outputformat = VID_OUTFMT_YBR_SVIDEO; + break; + case ANALOG_SD_RGB_SCART: + outputformat = VID_OUTFMT_RGBC_SVIDEO; + break; + default: + fprintf(stderr, "cVideo::setVideoMode: unknown mode %d\n", mode); + return; + } + fop(ioctl, MPEG_VID_SET_OUTFMT, outputformat); +} + +void cVideo::ShowPicture(const char * fname) +{ + fprintf(stderr, "cVideo::ShowPicture: %s\n", fname); +} + +void cVideo::StopPicture() +{ + lt_debug("cVideo::StopPicture()\n"); + fop(ioctl, MPEG_VID_SELECT_SOURCE, VID_SOURCE_DEMUX); +} + +void cVideo::Standby(unsigned int bOn) +{ + lt_debug("cVideo::Standby: %d\n", bOn); + if (bOn) + { + setBlank(1); + fop(ioctl, MPEG_VID_SET_OUTFMT, VID_OUTFMT_DISABLE_DACS); + } else + fop(ioctl, MPEG_VID_SET_OUTFMT, outputformat); + routeVideo(bOn); +} + +int cVideo::getBlank(void) +{ + fprintf(stderr, "cVideo::getBlank\n"); + 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) + { + vidDispSize_t x = (vidDispSize_t)getAspectRatio(); + if (x == VID_DISPSIZE_4x3 && 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; + } + */ + DBG("setZoom: %d%% src: %d:%d:%d:%d dst: %d:%d:%d:%d", 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); +} + +#if 0 +int cVideo::getZoom(void) +{ + return *zoomvalue; +} + +void cVideo::setZoomAspect(int index) +{ + if (index < 0 || index > 1) + WARN("index out of range"); + else + zoomvalue = &z[index]; +} +#endif + +void cVideo::Pig(int x, int y, int w, int h, int /*osd_w*/, int /*osd_h*/) +{ + /* x = y = w = h = -1 -> reset / "hide" PIG */ + if (x == -1 && y == -1 && w == -1 && h == -1) + { + setZoom(-1); + return; + } + SCALEINFO s; + memset(&s, 0, sizeof(s)); + s.src.hori_size = 720; + s.src.vert_size = 576; + s.des.hori_off = x; + s.des.vert_off = y; + s.des.hori_size = w; + s.des.vert_size = h; + DBG("setPig src: %d:%d:%d:%d dst: %d:%d:%d:%d", + 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); + fop(ioctl, MPEG_VID_SET_SCALE_POS, &s); +} + +void cVideo::getPictureInfo(int &width, int &height, int &rate) +{ + VIDEOINFO v; + /* this memset silences *TONS* of valgrind warnings */ + memset(&v, 0, sizeof(v)); + quiet_fop(ioctl, MPEG_VID_GET_V_INFO, &v); + /* convert to Coolstream API */ + rate = (int)v.frame_rate - 1; + width = (int)v.h_size; + height = (int)v.v_size; +} + +void cVideo::SetSyncMode(AVSYNC_TYPE /*Mode*/) +{ + fprintf(stderr, "cVideo::%s\n", __FUNCTION__); +}; + +int cVideo::SetStreamType(VIDEO_FORMAT type) +{ + static const char *VF[] = { + "VIDEO_FORMAT_MPEG2", + "VIDEO_FORMAT_MPEG4", + "VIDEO_FORMAT_VC1", + "VIDEO_FORMAT_JPEG", + "VIDEO_FORMAT_GIF", + "VIDEO_FORMAT_PNG" + }; + + lt_debug("cVideo::SetStreamType - type=%s\n", VF[type]); + return 0; +} + +void cVideo::routeVideo(int standby) +{ + lt_debug("cVideo::routeVideo(%d)\n", standby); + + int avsfd = open("/dev/stb/tdsystem", O_RDONLY); + if (avsfd < 0) + { + perror("open tdsystem"); + return; + } + + /* in standby, we always route VCR scart to the TV. Once there is a UI + to configure this, we can think more about this... */ + if (standby) + { + printf("[routeVideo] setting FASTBLANK to follow VCR SCART\n"); + if (ioctl(avsfd, IOC_AVS_FASTBLANK_SET, (unsigned char)3) < 0) + perror("IOC_AVS_FASTBLANK_SET, 3"); + /* TODO: should probably depend on aspect ratio setting */ + printf("[routeVideo] setting SCART_PIN_8 to follow VCR SCART\n"); + if (ioctl(avsfd, IOC_AVS_SCART_PIN8_FOLLOW_VCR) < 0) + perror("IOC_AVS_SCART_PIN8_FOLLOW_VCR"); + printf("[routeVideo] routing VCR to TV SCART\n"); + if (ioctl(avsfd, IOC_AVS_ROUTE_VCR2TV) < 0) + perror("IOC_AVS_ROUTE_VCR2TV"); + return; + } + unsigned char fblk = 1; + printf("[routeVideo] setting FASTBLANK to %d\n", fblk); + if (ioctl(avsfd, IOC_AVS_FASTBLANK_SET, fblk) < 0) + perror("IOC_AVS_FASTBLANK_SET, fblk"); + printf("[routeVideo] setting SCART_PIN_8 to %dV\n", scartvoltage); + if (ioctl(avsfd, IOC_AVS_SCART_PIN8_SET, scartvoltage) < 0) + perror("IOC_AVS_SCART_PIN8_SET"); + printf("[routeVideo] routing TV encoder to TV SCART\n"); + if (ioctl(avsfd, IOC_AVS_ROUTE_ENC2TV) < 0) + perror("IOC_AVS_ROUTE_ENC2TV"); + close(avsfd); +} diff --git a/libtriple/video_td.h b/libtriple/video_td.h new file mode 100644 index 0000000..49778b1 --- /dev/null +++ b/libtriple/video_td.h @@ -0,0 +1,189 @@ +#ifndef _VIDEO_TD_H +#define _VIDEO_TD_H + +#include +#define video_format_t vidDispSize_t +//#define video_displayformat_t vidDispMode_t + + +typedef enum { + ANALOG_SD_RGB_SCART = 0x00, + ANALOG_SD_YPRPB_SCART, + ANALOG_HD_RGB_SCART, + ANALOG_HD_YPRPB_SCART, + ANALOG_SD_RGB_CINCH = 0x80, + ANALOG_SD_YPRPB_CINCH, + ANALOG_HD_RGB_CINCH, + ANALOG_HD_YPRPB_CINCH, +} analog_mode_t; + +typedef enum { + VIDEO_FORMAT_MPEG2 = 0, + VIDEO_FORMAT_MPEG4, + VIDEO_FORMAT_VC1, + VIDEO_FORMAT_JPEG, + VIDEO_FORMAT_GIF, + VIDEO_FORMAT_PNG +} VIDEO_FORMAT; + +typedef enum { + VIDEO_SD = 0, + VIDEO_HD, + VIDEO_120x60i, + VIDEO_320x240i, + VIDEO_1440x800i, + VIDEO_360x288i +} VIDEO_DEFINITION; + +typedef enum { + VIDEO_FRAME_RATE_23_976 = 0, + VIDEO_FRAME_RATE_24, + VIDEO_FRAME_RATE_25, + VIDEO_FRAME_RATE_29_97, + VIDEO_FRAME_RATE_30, + VIDEO_FRAME_RATE_50, + VIDEO_FRAME_RATE_59_94, + VIDEO_FRAME_RATE_60 +} VIDEO_FRAME_RATE; + +typedef enum { + DISPLAY_AR_1_1, + DISPLAY_AR_4_3, + DISPLAY_AR_14_9, + DISPLAY_AR_16_9, + DISPLAY_AR_20_9, + DISPLAY_AR_RAW, +} DISPLAY_AR; + +typedef enum { + DISPLAY_AR_MODE_PANSCAN = 0, + DISPLAY_AR_MODE_LETTERBOX, + DISPLAY_AR_MODE_NONE, + DISPLAY_AR_MODE_PANSCAN2 +} DISPLAY_AR_MODE; + +typedef enum { + VIDEO_DB_DR_NEITHER = 0, + VIDEO_DB_ON, + VIDEO_DB_DR_BOTH +} VIDEO_DB_DR; + +typedef enum { + VIDEO_PLAY_STILL = 0, + VIDEO_PLAY_CLIP, + VIDEO_PLAY_TRICK, + VIDEO_PLAY_MOTION, + VIDEO_PLAY_MOTION_NO_SYNC +} VIDEO_PLAY_MODE; + +typedef enum { + VIDEO_STD_NTSC = VID_DISPFMT_NTSC, /* 0 */ + VIDEO_STD_PAL = VID_DISPFMT_PAL, /* 1 */ + VIDEO_STD_SECAM = VID_DISPFMT_SECAM, /* 4 */ + VIDEO_STD_1080I50 = VIDEO_STD_PAL, /* hack, this is used in neutrino settings default */ + VIDEO_STD_MAX = VIDEO_STD_SECAM +} VIDEO_STD; + +typedef enum { + VIDEO_STOPPED, /* Video is stopped */ + VIDEO_PLAYING, /* Video is currently playing */ + VIDEO_FREEZED /* Video is freezed */ +} video_play_state_t; + +/* not used, for dummy functions */ +typedef enum { + VIDEO_HDMI_CEC_MODE_OFF = 0, + VIDEO_HDMI_CEC_MODE_TUNER, + VIDEO_HDMI_CEC_MODE_RECORDER +} VIDEO_HDMI_CEC_MODE; + +typedef enum +{ + VIDEO_CONTROL_BRIGHTNESS = 0, + VIDEO_CONTROL_CONTRAST, + VIDEO_CONTROL_SATURATION, + VIDEO_CONTROL_HUE, + VIDEO_CONTROL_SHARPNESS, + VIDEO_CONTROL_MAX = VIDEO_CONTROL_SHARPNESS +} VIDEO_CONTROL; + + +class cVideo +{ + private: + /* video device */ + int fd; + /* apparently we cannot query the driver's state + => remember it */ + video_play_state_t playstate; + vidDispMode_t croppingMode; + vidOutFmt_t outputformat; + int scartvoltage; + int z[2]; /* zoomvalue for 4:3 (0) and 16:9 (1) in percent */ + int *zoomvalue; + void *blank_data[2]; /* we store two blank MPEGs (PAL/NTSC) in there */ + int blank_size[2]; + + VIDEO_FORMAT StreamType; + VIDEO_DEFINITION VideoDefinition; + DISPLAY_AR DisplayAR; + VIDEO_PLAY_MODE SyncMode; + DISPLAY_AR_MODE ARMode; + VIDEO_DB_DR eDbDr; + DISPLAY_AR PictureAR; + VIDEO_FRAME_RATE FrameRate; + void routeVideo(int standby); + public: + /* constructor & destructor */ + cVideo(int mode, void *, void *); + ~cVideo(void); + + void * GetTVEnc() { return NULL; }; + void * GetTVEncSD() { return NULL; }; + + /* aspect ratio */ + int getAspectRatio(void); + void getPictureInfo(int &width, int &height, int &rate); + int setAspectRatio(int aspect, int mode); + + /* cropping mode */ + int setCroppingMode(vidDispMode_t x = VID_DISPMODE_NORM); + + /* get play state */ + int getPlayState(void); + + /* blank on freeze */ + int getBlank(void); + int setBlank(int enable); + + /* change video play state. Parameters are all unused. */ + int Start(void *PcrChannel = NULL, unsigned short PcrPid = 0, unsigned short VideoPid = 0, void *x = NULL); + int Stop(bool blank = true); + bool Pause(void); + + /* set video_system */ + int SetVideoSystem(int video_system, bool remember = true); + int SetStreamType(VIDEO_FORMAT type); +#define AVSYNC_TYPE int + void SetSyncMode(AVSYNC_TYPE mode); + bool SetCECMode(VIDEO_HDMI_CEC_MODE) { return true; }; + void SetCECAutoView(bool) { return; }; + void SetCECAutoStandby(bool) { return; }; + void ShowPicture(const char * fname); + void StopPicture(); + void Standby(unsigned int bOn); + void Pig(int x, int y, int w, int h, int osd_w = 1064, int osd_h = 600); + void SetControl(int, int) { return; }; + int setZoom(int); + void setContrast(int val); + void SetVideoMode(analog_mode_t mode); + void SetDBDR(int) { return; }; + void SetAudioHandle(void *) { return; }; + void SetAutoModes(int [VIDEO_STD_MAX]) { return; }; + int OpenVBI(int) { return 0; }; + int CloseVBI(void) { return 0; }; + int StartVBI(unsigned short) { return 0; }; + int StopVBI(void) { return 0; }; +}; + +#endif