2 Copyright 2004-2005 Chris Tallon
\r
4 This file is part of VOMP.
\r
6 VOMP is free software; you can redistribute it and/or modify
\r
7 it under the terms of the GNU General Public License as published by
\r
8 the Free Software Foundation; either version 2 of the License, or
\r
9 (at your option) any later version.
\r
11 VOMP is distributed in the hope that it will be useful,
\r
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
14 GNU General Public License for more details.
\r
16 You should have received a copy of the GNU General Public License
\r
17 along with VOMP; if not, write to the Free Software
\r
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
\r
21 #include "videomvp.h"
\r
26 VideoMVP::VideoMVP()
\r
28 if (instance) return;
\r
31 VideoMVP::~VideoMVP()
\r
36 int VideoMVP::init(UCHAR tformat)
\r
38 if (initted) return 0;
\r
41 if ((fdVideo = open("/dev/vdec_dev", O_WRONLY)) < 0) return 0;
\r
43 if (!setFormat(tformat)) { shutdown(); return 0; }
\r
44 if (!setConnection(COMPOSITERGB)) { shutdown(); return 0; }
\r
45 if (!setAspectRatio(ASPECT4X3)) { shutdown(); return 0; }
\r
46 if (!setMode(NORMAL)) { shutdown(); return 0; }
\r
47 if (!setSource()) { shutdown(); return 0; }
\r
48 if (!attachFrameBuffer()) { shutdown(); return 0; }
\r
50 setTVsize(ASPECT4X3);
\r
52 if (format == PAL) setLetterboxBorder("38");
\r
53 else setLetterboxBorder("31");
\r
61 void VideoMVP::setLetterboxBorder(char* border)
\r
63 FILE* fdlbox = fopen("/proc/lbox_border", "w");
\r
64 if (!fdlbox) return;
\r
65 fputs(border, fdlbox);
\r
69 int VideoMVP::setTVsize(UCHAR ttvsize)
\r
73 // Override the aspect ratio usage, temporarily use to set the video chip mode
\r
74 if (!setAspectRatio(tvsize)) { shutdown(); return 0; }
\r
76 if ((fdVideo = open("/dev/vdec_dev", O_WRONLY)) < 0) return 0;
\r
77 if (!setSource()) { shutdown(); return 0; }
\r
78 if (!attachFrameBuffer()) { shutdown(); return 0; }
\r
80 // Reopening the fd causes the scart aspect line to go back to 4:3
\r
81 // Set this again to the same as the tv screen size
\r
82 if (!setAspectRatio(tvsize)) { shutdown(); return 0; }
\r
84 // mode == LETTERBOX is invalid if the TV is widescreen
\r
85 if (tvsize == ASPECT16X9) setMode(NORMAL);
\r
90 int VideoMVP::setDefaultAspect()
\r
92 return setAspectRatio(tvsize);
\r
95 int VideoMVP::shutdown()
\r
97 if (!initted) return 0;
\r
103 int VideoMVP::checkSCART()
\r
105 // Returns 3 for SCART Composite out
\r
106 // Returns 3 for SCART S-Video out
\r
107 // Returns 2 for SCART RGB out
\r
108 // Returns 3 for SCART not plugged in
\r
110 // So, as you can have RGB and composite out simultaneously,
\r
111 // and it can't detect S-Video, what is the point of this?
\r
114 if (ioctl(fdVideo, AV_CHK_SCART, &scart) != 0) return -10;
\r
119 int VideoMVP::setFormat(UCHAR tformat)
\r
121 if (!initted) return 0;
\r
122 if ((tformat != PAL) && (tformat != NTSC)) return 0;
\r
125 if (ioctl(fdVideo, AV_SET_VID_DISP_FMT, format) != 0) return 0;
\r
127 if (format == NTSC)
\r
130 screenHeight = 480;
\r
135 screenHeight = 576;
\r
141 int VideoMVP::setConnection(UCHAR tconnection)
\r
143 if (!initted) return 0;
\r
144 if ((tconnection != COMPOSITERGB) && (tconnection != SVIDEO)) return 0;
\r
145 connection = tconnection;
\r
147 if (ioctl(fdVideo, AV_SET_VID_OUTPUT, connection) != 0) return 0;
\r
151 int VideoMVP::setAspectRatio(UCHAR taspectRatio)
\r
153 if (!initted) return 0;
\r
154 if ((taspectRatio != ASPECT4X3) && (taspectRatio != ASPECT16X9)) return 0;
\r
155 aspectRatio = taspectRatio;
\r
157 Log::getInstance()->log("Video", Log::DEBUG, "Setting aspect to %i", aspectRatio);
\r
159 if (ioctl(fdVideo, AV_SET_VID_RATIO, aspectRatio) != 0) return 0;
\r
163 int VideoMVP::setMode(UCHAR tmode)
\r
165 if (!initted) return 0;
\r
167 if ((tmode == LETTERBOX) && (tvsize == ASPECT16X9)) return 0; // invalid mode
\r
169 if ((tmode != NORMAL) && (tmode != LETTERBOX) && (tmode != UNKNOWN2) && (tmode != QUARTER) && (tmode != EIGHTH)
\r
170 && (tmode != ZOOM) && (tmode != UNKNOWN6)) return 0;
\r
173 if (ioctl(fdVideo, AV_SET_VID_MODE, mode) != 0) return 0;
\r
177 int VideoMVP::signalOff()
\r
179 if (ioctl(fdVideo, AV_SET_VID_DENC, 0) != 0) return 0;
\r
183 int VideoMVP::signalOn()
\r
185 if (ioctl(fdVideo, AV_SET_VID_DENC, 1) != 0) return 0;
\r
189 int VideoMVP::setSource()
\r
191 if (!initted) return 0;
\r
193 // What does this do...
\r
194 if (ioctl(fdVideo, AV_SET_VID_SRC, 1) != 0) return 0;
\r
198 int VideoMVP::setPosition(int x, int y)
\r
200 if (!initted) return 0;
\r
202 // vid_pos_regs_t pos_d;
\r
206 vid_pos_regs_t pos_d;
\r
208 memset(&pos_d, 0, sizeof(pos_d));
\r
233 pos_d.y = 100; // Top left X
\r
234 pos_d.x = 50; // Top left Y
\r
242 if (ioctl(fdVideo, AV_SET_VID_POSITION, &pos_d) != 0) return 0;
\r
246 int VideoMVP::sync()
\r
248 if (!initted) return 0;
\r
250 if (ioctl(fdVideo, AV_SET_VID_SYNC, 2) != 0) return 0;
\r
254 int VideoMVP::play()
\r
256 if (!initted) return 0;
\r
258 if (ioctl(fdVideo, AV_SET_VID_PLAY, 0) != 0) return 0;
\r
262 int VideoMVP::stop()
\r
264 if (!initted) return 0;
\r
266 if (ioctl(fdVideo, AV_SET_VID_STOP, 0) != 0) return 0;
\r
270 int VideoMVP::reset()
\r
272 if (!initted) return 0;
\r
274 if (ioctl(fdVideo, AV_SET_VID_RESET, 0x11) != 0) return 0;
\r
278 int VideoMVP::pause()
\r
280 if (!initted) return 0;
\r
282 if (ioctl(fdVideo, AV_SET_VID_PAUSE, 0) != 0) return 0;
\r
286 int VideoMVP::unPause() // FIXME get rid - same as play!!
\r
288 if (!initted) return 0;
\r
289 if (ioctl(fdVideo, AV_SET_VID_PLAY, 0) != 0) return 0;
\r
293 int VideoMVP::fastForward()
\r
295 if (!initted) return 0;
\r
297 if (ioctl(fdVideo, AV_SET_VID_FFWD, 1) != 0) return 0;
\r
301 int VideoMVP::unFastForward()
\r
303 if (!initted) return 0;
\r
305 // if (ioctl(fdVideo, AV_SET_VID_RESET, 0x11) != 0) return 0; // don't need this.
\r
307 if (ioctl(fdVideo, AV_SET_VID_PLAY, 0) != 0) return 0;
\r
311 int VideoMVP::attachFrameBuffer()
\r
313 if (!initted) return 0;
\r
315 if (ioctl(fdVideo, AV_SET_VID_FB, 0) != 0) return 0;
\r
319 int VideoMVP::blank(void)
\r
321 if (ioctl(fdVideo, AV_SET_VID_FB, 1) != 0) return 0;
\r
322 if (ioctl(fdVideo, AV_SET_VID_FB, 0) != 0) return 0;
\r
326 ULLONG VideoMVP::getCurrentTimestamp()
\r
328 sync_data_t timestamps;
\r
329 if (ioctl(fdVideo, AV_GET_VID_TIMESTAMPS, ×tamps) == 0)
\r
331 // FIXME are these the right way around?
\r
333 timestamps.stc = (timestamps.stc >> 31 ) | (timestamps.stc & 1);
\r
334 timestamps.pts = (timestamps.pts >> 31 ) | (timestamps.pts & 1);
\r
336 return timestamps.stc;
\r
344 ULONG VideoMVP::timecodeToFrameNumber(ULLONG timecode)
\r
346 if (format == PAL) return (ULONG)(((double)timecode / (double)90000) * (double)25);
\r
347 else return (ULONG)(((double)timecode / (double)90000) * (double)30);
\r
351 int VideoMVP::test()
\r
356 // return ioctl(fdVideo, AV_SET_VID_STC, &stc);
\r
363 int VideoMVP::test2()
\r
369 void VideoMVP::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos)
\r
371 MediaPacketList::const_iterator iter = mplist.begin();
\r
372 deliver_start = iter->pos_buffer + samplepos;
\r
373 mediapacket_len[0] = deliver_length = iter->length;
\r
375 while (++iter != mplist.end() &&
\r
376 iter->pos_buffer == deliver_start + deliver_length)
\r
378 deliver_length += iter->length;
\r
379 mediapacket_len[deliver_count] = iter->length;
\r
381 if (deliver_length >= WRITE_LENGTH ||
\r
382 deliver_count == WRITE_PACKETS) break;
\r
386 UINT VideoMVP::DeliverMediaSample(UCHAR* buffer, UINT* samplepos)
\r
388 int written = ::write(fdVideo, buffer + deliver_start, deliver_length);
\r
389 if (written == (int)deliver_length) { *samplepos = 0; return deliver_count;}
\r
390 if (written <= 0) return 0;
\r
391 // Handle a partial write. Is this possible? Should we bother?
\r
393 while ((written -= mediapacket_len[i]) >= 0) i++;
\r
394 *samplepos = mediapacket_len[i] + written;
\r
398 void VideoMVP::ResetTimeOffsets()
\r
402 bool VideoMVP::displayIFrame(const UCHAR* buffer, UINT length)
\r
404 write(fdVideo, buffer, length);
\r