]> git.vomp.tv Git - vompclient.git/blob - videomvp.cc
Fix text corruption in channel number display on live tv
[vompclient.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,12,11))    { 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,parx,pary))       { 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,parx,pary))       { 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,parx,pary);
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, int tparx,int tpary)
152 {
153   if (!initted) return 0;
154   parx=tparx;
155   pary=tpary;
156   if ((taspectRatio != ASPECT4X3) && (taspectRatio != ASPECT16X9)) return 0;
157   aspectRatio = taspectRatio;
158
159   Log::getInstance()->log("Video", Log::DEBUG, "Setting aspect to %i", aspectRatio);
160
161   if (ioctl(fdVideo, AV_SET_VID_RATIO, aspectRatio) != 0) return 0;
162   return 1;
163 }
164
165 int VideoMVP::setMode(UCHAR tmode)
166 {
167   if (!initted) return 0;
168
169   if ((tmode == LETTERBOX) && (tvsize == ASPECT16X9)) return 0; // invalid mode
170
171   if ((tmode != NORMAL) && (tmode != LETTERBOX) && (tmode != UNKNOWN2) && (tmode != QUARTER) && (tmode != EIGHTH)
172       && (tmode != ZOOM) && (tmode != UNKNOWN6)) return 0;
173   if (tmode==NORMAL || tmode == LETTERBOX || tmode == QUARTER) mode = tmode;
174   if (ioctl(fdVideo, AV_SET_VID_MODE, mode) != 0) return 0;
175   return 1;
176 }
177
178 int VideoMVP::signalOff()
179 {
180   if (ioctl(fdVideo, AV_SET_VID_DENC, 0) != 0) return 0;
181   return 1;
182 }
183
184 int VideoMVP::signalOn()
185 {
186   if (ioctl(fdVideo, AV_SET_VID_DENC, 1) != 0) return 0;
187   return 1;
188 }
189
190 int VideoMVP::setSource()
191 {
192   if (!initted) return 0;
193
194   // What does this do...
195   if (ioctl(fdVideo, AV_SET_VID_SRC, 1) != 0) return 0;
196   return 1;
197 }
198
199 int VideoMVP::setPosition(int x, int y)
200 {
201   if (!initted) return 0;
202
203 //  vid_pos_regs_t pos_d;
204 //  pos_d.x = x;
205 //  pos_d.y = y;
206
207   vid_pos_regs_t pos_d;
208
209   memset(&pos_d, 0, sizeof(pos_d));
210
211   pos_d.dest.y = y;
212   pos_d.dest.x = x;
213 /*
214 typedef struct {
215   int w;
216   int h;
217   int scale;
218   int x1;
219   int y;
220   int x;
221   int y2;
222   int x3;
223   int y3;
224   int x4;
225   int y4;
226 } vid_pos_regs_t;
227 */
228
229 /*
230   pos_d.w = 100;
231   pos_d.h = 30;
232   pos_d.scale = 2;
233   pos_d.x1 = 0;
234   pos_d.y = 100;            // Top left X
235   pos_d.x = 50;            // Top left Y
236   pos_d.y2 = 30;
237   pos_d.x3 = 60;
238   pos_d.y3 = 90;
239   pos_d.x4 = 120;
240   pos_d.y4 = 150;
241 */
242
243   if (ioctl(fdVideo, AV_SET_VID_POSITION, &pos_d) != 0) return 0;
244   return 1;
245 }
246
247 int VideoMVP::sync()
248 {
249   if (!initted) return 0;
250
251   if (ioctl(fdVideo, AV_SET_VID_SYNC, 2) != 0) return 0;
252   return 1;
253 }
254
255 int VideoMVP::play()
256 {
257   if (!initted) return 0;
258
259   if (ioctl(fdVideo, AV_SET_VID_PLAY, 0) != 0) return 0;
260   return 1;
261 }
262
263 int VideoMVP::stop()
264 {
265   if (!initted) return 0;
266
267   if (ioctl(fdVideo, AV_SET_VID_STOP, 0) != 0) return 0;
268   return 1;
269 }
270
271 int VideoMVP::reset()
272 {
273   if (!initted) return 0;
274
275   if (ioctl(fdVideo, AV_SET_VID_RESET, 0x11) != 0) return 0;
276   return 1;
277 }
278
279 int VideoMVP::pause()
280 {
281   if (!initted) return 0;
282
283   if (ioctl(fdVideo, AV_SET_VID_PAUSE, 0) != 0) return 0;
284   return 1;
285 }
286
287 int VideoMVP::unPause() // FIXME get rid - same as play!!
288 {
289   if (!initted) return 0;
290   if (ioctl(fdVideo, AV_SET_VID_PLAY, 0) != 0) return 0;
291   return 1;
292 }
293
294 int VideoMVP::fastForward()
295 {
296   if (!initted) return 0;
297
298   if (ioctl(fdVideo, AV_SET_VID_FFWD, 1) != 0) return 0;
299   return 1;
300 }
301
302 int VideoMVP::unFastForward()
303 {
304   if (!initted) return 0;
305
306 //  if (ioctl(fdVideo, AV_SET_VID_RESET, 0x11) != 0) return 0; // don't need this.
307
308   if (ioctl(fdVideo, AV_SET_VID_PLAY, 0) != 0) return 0;
309   return 1;
310 }
311
312 int VideoMVP::attachFrameBuffer()
313 {
314   if (!initted) return 0;
315
316   if (ioctl(fdVideo, AV_SET_VID_FB, 0) != 0) return 0;
317   return 1;
318 }
319
320 int VideoMVP::blank(void)
321 {
322   if (ioctl(fdVideo, AV_SET_VID_FB, 1) != 0) return 0;
323   if (ioctl(fdVideo, AV_SET_VID_FB, 0) != 0) return 0;
324   return 1;
325 }
326
327 ULLONG VideoMVP::getCurrentTimestamp()
328 {
329   sync_data_t timestamps;
330   if (ioctl(fdVideo, AV_GET_VID_TIMESTAMPS, &timestamps) == 0)
331   {
332     // FIXME are these the right way around?
333
334     timestamps.stc = (timestamps.stc >> 31 ) | (timestamps.stc & 1);
335     timestamps.pts = (timestamps.pts >> 31 ) | (timestamps.pts & 1);
336
337     return timestamps.stc;
338   }
339   else
340   {
341     return 0;
342   }
343 }
344
345 ULONG VideoMVP::timecodeToFrameNumber(ULLONG timecode)
346 {
347   if (format == PAL) return (ULONG)(((double)timecode / (double)90000) * (double)25);
348   else               return (ULONG)(((double)timecode / (double)90000) * (double)30);
349 }
350
351 #ifdef DEV
352 int VideoMVP::test()
353 {
354   return 0;
355
356 //  ULLONG stc = 0;
357 //  return ioctl(fdVideo, AV_SET_VID_STC, &stc);
358 /*
359  // reset();
360   return 1;
361 */
362 }
363
364 int VideoMVP::test2()
365 {
366   return 0;
367 }
368 #endif
369
370 void VideoMVP::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos)
371 {
372   MediaPacketList::const_iterator iter = mplist.begin();
373   deliver_start = iter->pos_buffer + samplepos;
374   mediapacket_len[0] = deliver_length = iter->length;
375   deliver_count = 1;
376   while (++iter != mplist.end() &&
377            iter->pos_buffer == deliver_start + deliver_length)
378   {
379     deliver_length += iter->length;
380     mediapacket_len[deliver_count] = iter->length;
381     ++deliver_count;
382     if (deliver_length >= WRITE_LENGTH ||
383         deliver_count == WRITE_PACKETS) break;
384   }
385 }
386
387 UINT VideoMVP::DeliverMediaSample(UCHAR* buffer, UINT* samplepos)
388 {
389   int written = ::write(fdVideo, buffer + deliver_start, deliver_length);
390   if (written == (int)deliver_length) { *samplepos = 0; return deliver_count;}
391   if (written <= 0) return 0;
392   // Handle a partial write. Is this possible? Should we bother?
393   UINT i = 0;
394   while ((written -= mediapacket_len[i]) >= 0) i++;
395   *samplepos = mediapacket_len[i] + written;
396   return i;
397 }
398
399 void VideoMVP::ResetTimeOffsets()
400 {
401 }
402
403 bool VideoMVP::displayIFrame(const UCHAR* buffer, UINT length)
404 {
405   write(fdVideo, buffer, length);
406   return true;
407 }