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