]> git.vomp.tv Git - vompclient-marten.git/blob - videomvp.cc
Live radio prebuffering display - code upgrades for connection lost handling
[vompclient-marten.git] / videomvp.cc
1 /*
2     Copyright 2004-2005 Chris Tallon
3
4     This file is part of VOMP.
5
6     VOMP 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     VOMP 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 VOMP; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19 */
20
21 #include "videomvp.h"
22
23 // temp
24 #include "log.h"
25
26 VideoMVP::VideoMVP()
27 {
28   if (instance) return;
29 }
30
31 VideoMVP::~VideoMVP()
32 {
33   instance = NULL;
34 }
35
36 int VideoMVP::init(UCHAR tformat)
37 {
38   if (initted) return 0;
39   initted = 1;
40
41   if ((fdVideo = open("/dev/vdec_dev", O_WRONLY)) < 0) return 0;
42
43   if (!setFormat(tformat))           { shutdown(); return 0; }
44   if (!setConnection(COMPOSITERGB))  { shutdown(); return 0; }
45   if (!setAspectRatio(ASPECT4X3))    { shutdown(); return 0; }
46   if (!setMode(NORMAL))              { shutdown(); return 0; }
47   if (!setSource())                  { shutdown(); return 0; }
48   if (!attachFrameBuffer())          { shutdown(); return 0; }
49
50   setTVsize(ASPECT4X3);
51
52   if (format == PAL) setLetterboxBorder("38");
53   else setLetterboxBorder("31");
54
55   stop();
56
57
58   return 1;
59 }
60
61 void VideoMVP::setLetterboxBorder(char* border)
62 {
63   FILE* fdlbox = fopen("/proc/lbox_border", "w");
64   if (!fdlbox) return;
65   fputs(border, fdlbox);
66   fclose(fdlbox);
67 }
68
69 int VideoMVP::setTVsize(UCHAR ttvsize)
70 {
71   tvsize = ttvsize;
72
73   // Override the aspect ratio usage, temporarily use to set the video chip mode
74   if (!setAspectRatio(tvsize))       { shutdown(); return 0; }
75   close(fdVideo);
76   if ((fdVideo = open("/dev/vdec_dev", O_WRONLY)) < 0) return 0;
77   if (!setSource())                  { shutdown(); return 0; }
78   if (!attachFrameBuffer())          { shutdown(); return 0; }
79
80   // Reopening the fd causes the scart aspect line to go back to 4:3
81   // Set this again to the same as the tv screen size
82   if (!setAspectRatio(tvsize))       { shutdown(); return 0; }
83
84   // mode == LETTERBOX is invalid if the TV is widescreen
85   if (tvsize == ASPECT16X9) setMode(NORMAL);
86
87   return 1;
88 }
89
90 int VideoMVP::setDefaultAspect()
91 {
92   return setAspectRatio(tvsize);
93 }
94
95 int VideoMVP::shutdown()
96 {
97   if (!initted) return 0;
98   initted = 0;
99   close(fdVideo);
100   return 1;
101 }
102
103 int VideoMVP::checkSCART()
104 {
105   // Returns 3 for SCART Composite out
106   // Returns 3 for SCART S-Video out
107   // Returns 2 for SCART RGB out
108   // Returns 3 for SCART not plugged in
109
110   // So, as you can have RGB and composite out simultaneously,
111   // and it can't detect S-Video, what is the point of this?
112
113   int scart;
114   if (ioctl(fdVideo, AV_CHK_SCART, &scart) != 0) return -10;
115
116   return scart;
117 }
118
119 int VideoMVP::setFormat(UCHAR tformat)
120 {
121   if (!initted) return 0;
122   if ((tformat != PAL) && (tformat != NTSC)) return 0;
123   format = tformat;
124
125   if (ioctl(fdVideo, AV_SET_VID_DISP_FMT, format) != 0) return 0;
126
127   if (format == NTSC)
128   {
129     screenWidth = 720;
130     screenHeight = 480;
131   }
132   if (format == PAL)
133   {
134     screenWidth = 720;
135     screenHeight = 576;
136   }
137
138   return 1;
139 }
140
141 int VideoMVP::setConnection(UCHAR tconnection)
142 {
143   if (!initted) return 0;
144   if ((tconnection != COMPOSITERGB) && (tconnection != SVIDEO)) return 0;
145   connection = tconnection;
146
147   if (ioctl(fdVideo, AV_SET_VID_OUTPUT, connection) != 0) return 0;
148   return 1;
149 }
150
151 int VideoMVP::setAspectRatio(UCHAR taspectRatio)
152 {
153   if (!initted) return 0;
154   if ((taspectRatio != ASPECT4X3) && (taspectRatio != ASPECT16X9)) return 0;
155   aspectRatio = taspectRatio;
156
157   Log::getInstance()->log("Video", Log::DEBUG, "Setting aspect to %i", aspectRatio);
158
159   if (ioctl(fdVideo, AV_SET_VID_RATIO, aspectRatio) != 0) return 0;
160   return 1;
161 }
162
163 int VideoMVP::setMode(UCHAR tmode)
164 {
165   if (!initted) return 0;
166
167   if ((tmode == LETTERBOX) && (tvsize == ASPECT16X9)) return 0; // invalid mode
168
169   if ((tmode != NORMAL) && (tmode != LETTERBOX) && (tmode != UNKNOWN2) && (tmode != QUARTER) && (tmode != EIGHTH)
170       && (tmode != ZOOM) && (tmode != UNKNOWN6)) return 0;
171   mode = tmode;
172
173   if (ioctl(fdVideo, AV_SET_VID_MODE, mode) != 0) return 0;
174   return 1;
175 }
176
177 int VideoMVP::signalOff()
178 {
179   if (ioctl(fdVideo, AV_SET_VID_DENC, 0) != 0) return 0;
180   return 1;
181 }
182
183 int VideoMVP::signalOn()
184 {
185   if (ioctl(fdVideo, AV_SET_VID_DENC, 1) != 0) return 0;
186   return 1;
187 }
188
189 int VideoMVP::setSource()
190 {
191   if (!initted) return 0;
192
193   // What does this do...
194   if (ioctl(fdVideo, AV_SET_VID_SRC, 1) != 0) return 0;
195   return 1;
196 }
197
198 int VideoMVP::setPosition(int x, int y)
199 {
200   if (!initted) return 0;
201
202 //  vid_pos_regs_t pos_d;
203 //  pos_d.x = x;
204 //  pos_d.y = y;
205
206   vid_pos_regs_t pos_d;
207
208   memset(&pos_d, 0, sizeof(pos_d));
209
210   pos_d.dest.y = y;
211   pos_d.dest.x = x;
212 /*
213 typedef struct {
214   int w;
215   int h;
216   int scale;
217   int x1;
218   int y;
219   int x;
220   int y2;
221   int x3;
222   int y3;
223   int x4;
224   int y4;
225 } vid_pos_regs_t;
226 */
227
228 /*
229   pos_d.w = 100;
230   pos_d.h = 30;
231   pos_d.scale = 2;
232   pos_d.x1 = 0;
233   pos_d.y = 100;            // Top left X
234   pos_d.x = 50;            // Top left Y
235   pos_d.y2 = 30;
236   pos_d.x3 = 60;
237   pos_d.y3 = 90;
238   pos_d.x4 = 120;
239   pos_d.y4 = 150;
240 */
241
242   if (ioctl(fdVideo, AV_SET_VID_POSITION, &pos_d) != 0) return 0;
243   return 1;
244 }
245
246 int VideoMVP::sync()
247 {
248   if (!initted) return 0;
249
250   if (ioctl(fdVideo, AV_SET_VID_SYNC, 2) != 0) return 0;
251   return 1;
252 }
253
254 int VideoMVP::play()
255 {
256   if (!initted) return 0;
257
258   if (ioctl(fdVideo, AV_SET_VID_PLAY, 0) != 0) return 0;
259   return 1;
260 }
261
262 int VideoMVP::stop()
263 {
264   if (!initted) return 0;
265
266   if (ioctl(fdVideo, AV_SET_VID_STOP, 0) != 0) return 0;
267   return 1;
268 }
269
270 int VideoMVP::reset()
271 {
272   if (!initted) return 0;
273
274   if (ioctl(fdVideo, AV_SET_VID_RESET, 0x11) != 0) return 0;
275   return 1;
276 }
277
278 int VideoMVP::pause()
279 {
280   if (!initted) return 0;
281
282   if (ioctl(fdVideo, AV_SET_VID_PAUSE, 0) != 0) return 0;
283   return 1;
284 }
285
286 int VideoMVP::unPause() // FIXME get rid - same as play!!
287 {
288   if (!initted) return 0;
289   if (ioctl(fdVideo, AV_SET_VID_PLAY, 0) != 0) return 0;
290   return 1;
291 }
292
293 int VideoMVP::fastForward()
294 {
295   if (!initted) return 0;
296
297   if (ioctl(fdVideo, AV_SET_VID_FFWD, 1) != 0) return 0;
298   return 1;
299 }
300
301 int VideoMVP::unFastForward()
302 {
303   if (!initted) return 0;
304
305 //  if (ioctl(fdVideo, AV_SET_VID_RESET, 0x11) != 0) return 0; // don't need this.
306
307   if (ioctl(fdVideo, AV_SET_VID_PLAY, 0) != 0) return 0;
308   return 1;
309 }
310
311 int VideoMVP::attachFrameBuffer()
312 {
313   if (!initted) return 0;
314
315   if (ioctl(fdVideo, AV_SET_VID_FB, 0) != 0) return 0;
316   return 1;
317 }
318
319 int VideoMVP::blank(void)
320 {
321   if (ioctl(fdVideo, AV_SET_VID_FB, 1) != 0) return 0;
322   if (ioctl(fdVideo, AV_SET_VID_FB, 0) != 0) return 0;
323   return 1;
324 }
325
326 ULLONG VideoMVP::getCurrentTimestamp()
327 {
328   sync_data_t timestamps;
329   if (ioctl(fdVideo, AV_GET_VID_TIMESTAMPS, &timestamps) == 0)
330   {
331     // FIXME are these the right way around?
332
333     timestamps.stc = (timestamps.stc >> 31 ) | (timestamps.stc & 1);
334     timestamps.pts = (timestamps.pts >> 31 ) | (timestamps.pts & 1);
335
336     return timestamps.stc;
337   }
338   else
339   {
340     return 0;
341   }
342 }
343
344 ULONG VideoMVP::timecodeToFrameNumber(ULLONG timecode)
345 {
346   if (format == PAL) return (ULONG)(((double)timecode / (double)90000) * (double)25);
347   else               return (ULONG)(((double)timecode / (double)90000) * (double)30);
348 }
349
350 #ifdef DEV
351 int VideoMVP::test()
352 {
353   return 0;
354
355 //  ULLONG stc = 0;
356 //  return ioctl(fdVideo, AV_SET_VID_STC, &stc);
357 /*
358  // reset();
359   return 1;
360 */
361 }
362
363 int VideoMVP::test2()
364 {
365   return 0;
366 }
367 #endif
368
369 void VideoMVP::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos)
370 {
371   MediaPacketList::const_iterator iter = mplist.begin();
372   deliver_start = iter->pos_buffer + samplepos;
373   mediapacket_len[0] = deliver_length = iter->length;
374   deliver_count = 1;
375   while (++iter != mplist.end() &&
376            iter->pos_buffer == deliver_start + deliver_length)
377   {
378     deliver_length += iter->length;
379     mediapacket_len[deliver_count] = iter->length;
380     ++deliver_count;
381     if (deliver_length >= WRITE_LENGTH ||
382         deliver_count == WRITE_PACKETS) break;
383   }
384 }
385
386 UINT VideoMVP::DeliverMediaSample(const UCHAR* buffer, UINT* samplepos)
387 {
388   int written = ::write(fdVideo, buffer + deliver_start, deliver_length);
389   if (written == (int)deliver_length) { *samplepos = 0; return deliver_count;}
390   if (written <= 0) return 0;
391   // Handle a partial write. Is this possible? Should we bother?
392   UINT i = 0;
393   while ((written -= mediapacket_len[i]) >= 0) i++;
394   *samplepos = mediapacket_len[i] + written;
395   return i;
396 }
397
398 void VideoMVP::ResetTimeOffsets()
399 {
400 }
401
402 void VideoMVP::displayIFrame(const UCHAR* buffer, UINT length)
403 {
404   write(fdVideo, buffer, length);
405 }