]> git.vomp.tv Git - vompclient-marten.git/blob - player.cc
New player, ffwd/fbwd, iframe navigation stuff
[vompclient-marten.git] / player.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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 #include "player.h"
22
23 // ----------------------------------- Called from outside, one offs or info funcs
24
25 Player::Player(MessageQueue* messageQueue, bool tIsRecording, bool tIsRadio)
26 : vfeed(this), afeed(this)
27 {
28   commandMessageQueue = messageQueue;
29   audio = Audio::getInstance();
30   video = Video::getInstance();
31   logger = Log::getInstance();
32   vdr = VDR::getInstance();
33   initted = false;
34   lengthBytes = 0;
35   lengthFrames = 0;
36   currentFrameNumber = 0;
37   state = S_STOP;
38
39   videoStartup = false;
40   preBuffering = false;
41   isRecording = tIsRecording;
42   isRadio = tIsRadio;
43
44   threadBuffer = NULL;
45
46   if (isRadio)
47   {
48     blockSize = 20000;
49     startupBlockSize = 60000;
50     video->turnVideoOff();
51   }
52   else
53   {
54     blockSize = 100000;
55     startupBlockSize = 250000;
56     video->turnVideoOn();
57   }
58 }
59
60 Player::~Player()
61 {
62   if (initted) shutdown();
63 }
64
65 int Player::init()
66 {
67   if (initted) return 0;
68 #ifndef WIN32
69   pthread_mutex_init(&mutex, NULL);
70 #else
71   mutex=CreateMutex(NULL,FALSE,NULL);
72 #endif
73
74   demuxer = new DemuxerVDR();
75   if (!demuxer) return 0;
76
77   if (!demuxer->init(this, audio, video))
78   {
79     logger->log("Player", Log::ERR, "Demuxer failed to init");
80     shutdown();
81     return 0;
82   }
83
84   vfeed.init();
85   afeed.init();
86
87   video->stop();
88   video->blank();
89   audio->stop();
90
91   initted = true;
92   return 1;
93 }
94
95 int Player::shutdown()
96 {
97   if (!initted) return 0;
98   switchState(S_STOP);
99   initted = false;
100
101   delete demuxer;
102   demuxer = NULL;
103
104 #ifdef WIN32
105   CloseHandle(mutex);
106 #endif
107
108   return 1;
109 }
110
111 void Player::setStartFrame(ULONG startFrame)
112 {
113   currentFrameNumber = startFrame;
114 }
115
116 void Player::setLengthBytes(ULLONG length)
117 {
118   lengthBytes = length;
119   logger->log("Player", Log::DEBUG, "Player has received length bytes of %llu", lengthBytes);
120 }
121
122 void Player::setLengthFrames(ULONG length)
123 {
124   lengthFrames = length;
125   logger->log("Player", Log::DEBUG, "Player has received length frames of %lu", lengthFrames);
126 }
127
128 ULONG Player::getLengthFrames()
129 {
130   return lengthFrames;
131 }
132
133 ULONG Player::getCurrentFrameNum()
134 {
135   if (startup) return 0;
136   return demuxer->getFrameNumFromPTS(video->getCurrentTimestamp());
137 }
138
139 // ----------------------------------- Externally called events
140
141 void Player::play()
142 {
143   if (!initted) return;
144   if (state == S_PLAY) return;
145   lock();
146   bool doUnlock = false;
147   if (state == S_PAUSE) doUnlock = true;
148   switchState(S_PLAY);
149   if (doUnlock) unLock();
150 }
151
152 void Player::stop()
153 {
154   if (!initted) return;
155   if (state == S_STOP) return;
156   lock();
157   logger->log("Player", Log::DEBUG, "Stop called lock");
158   switchState(S_STOP);
159   unLock();
160 }
161
162 void Player::togglePause()
163 {
164   if (!initted) return;
165   lock();
166   if (state == S_PAUSE) switchState(S_PLAY);
167   else switchState(S_PAUSE);
168   unLock();
169 }
170
171 void Player::toggleFastForward()
172 {
173   if (!initted) return;
174   lock();
175   if (state == S_FFWD) switchState(S_PLAY);
176   else switchState(S_FFWD);
177   unLock();
178 }
179
180 void Player::toggleFastBackward()
181 {
182   if (!initted) return;
183   lock();
184   if (state == S_FBWD) switchState(S_PLAY);
185   else switchState(S_FBWD);
186   unLock();
187 }
188
189 void Player::jumpToPercent(int percent)
190 {
191   lock();
192   logger->log("Player", Log::DEBUG, "JUMP TO %i%%", percent);
193   ULONG newFrame = percent * lengthFrames / 100;
194   switchState(S_JUMP, newFrame);
195 //  unLock(); - let thread unlock this
196 }
197
198 void Player::skipForward(int seconds)
199 {
200   lock();
201   logger->log("Player", Log::DEBUG, "SKIP FORWARD %i SECONDS", seconds);
202   ULONG newFrame = getCurrentFrameNum() + (seconds * video->getFPS());
203   if (newFrame > lengthFrames) { switchState(S_PLAY); unLock(); }
204   else switchState(S_JUMP, newFrame);
205 //  unLock(); - let thread unlock this
206 }
207
208 void Player::skipBackward(int seconds)
209 {
210   lock();
211   logger->log("Player", Log::DEBUG, "SKIP BACKWARD %i SECONDS", seconds);
212   long newFrameNum = getCurrentFrameNum() - (seconds * video->getFPS());
213   if (newFrameNum < 0) newFrameNum = 0;
214   switchState(S_JUMP, newFrameNum);
215 //  unLock(); - let thread unlock this
216 }
217
218 // ----------------------------------- Implementations called events
219
220 void Player::switchState(UCHAR toState, ULONG jumpFrame)
221 {
222   if (!initted) return;
223
224   logger->log("Player", Log::DEBUG, "Switch state from %u to %u", state, toState);
225
226   switch(state) // current state selector
227   {
228     case S_PLAY: // from S_PLAY -----------------------------------
229     {
230       switch(toState)
231       {
232         case S_PLAY: // to S_PLAY
233         {
234           return;
235         }
236         case S_PAUSE: // to S_PAUSE
237         {
238           video->pause();
239           audio->pause();
240           state = S_PAUSE;
241           return;
242         }
243         case S_FFWD: // to S_FFWD
244         {
245           currentFrameNumber = getCurrentFrameNum();
246           audio->systemMuteOn();
247           threadStop();
248           vfeed.stop();
249           afeed.stop();
250           demuxer->flush();
251           state = S_FFWD;
252           threadStart();
253           return;
254         }
255         case S_FBWD: // to S_FBWD
256         {
257           currentFrameNumber = getCurrentFrameNum();
258           audio->systemMuteOn();
259           threadStop();
260           vfeed.stop();
261           afeed.stop();
262           demuxer->flush();
263           state = S_FBWD;
264           threadStart();
265           return;
266         }
267         case S_STOP: // to S_STOP
268         {
269           vfeed.stop();
270           afeed.stop();
271           threadStop();
272           video->stop();
273           video->blank();
274           audio->stop();
275           audio->unPause();
276           video->reset();
277           demuxer->reset();
278           state = S_STOP;
279           return;
280         }
281         case S_JUMP: // to S_JUMP
282         {
283           restartAtFrame(jumpFrame);
284           return;
285         }
286       }
287     }
288     case S_PAUSE: // from S_PAUSE -----------------------------------
289     {
290       switch(toState)
291       {
292         case S_PLAY: // to S_PLAY
293         {
294           if (threadIsActive())
295           {
296             video->unPause();
297             audio->unPause();
298             state = S_PLAY;
299           }
300           else
301           {
302             state = S_PLAY;
303             restartAtFrame(currentFrameNumber);
304           }
305
306           return;
307         }
308         case S_PAUSE: // to S_PAUSE
309         {
310           return;
311         }
312         case S_FFWD: // to S_FFWD
313         {
314           currentFrameNumber = getCurrentFrameNum();
315           audio->systemMuteOn();
316           vfeed.stop();
317           afeed.stop();
318           if (threadIsActive()) threadStop();
319           video->unPause();
320           audio->unPause();
321           state = S_FFWD;
322           threadStart();
323           return;
324         }
325         case S_FBWD: // to S_FBWD
326         {
327           currentFrameNumber = getCurrentFrameNum();
328           audio->systemMuteOn();
329           vfeed.stop();
330           afeed.stop();
331           if (threadIsActive()) threadStop();
332           video->unPause();
333           audio->unPause();
334           state = S_FBWD;
335           threadStart();
336           return;
337         }
338         case S_STOP: // to S_STOP
339         {
340           vfeed.stop();
341           afeed.stop();
342           if (threadIsActive()) threadStop();
343           video->stop();
344           video->blank();
345           audio->stop();
346           video->reset();
347           audio->unPause();
348           demuxer->reset();
349           audio->systemMuteOff();
350           state = S_FFWD;
351           return;
352         }
353         case S_JUMP: // to S_JUMP
354         {
355           state = S_PLAY;
356           audio->unPause();
357           restartAtFrame(jumpFrame);
358           return;
359         }
360       }
361     }
362     case S_FFWD: // from S_FFWD -----------------------------------
363     {
364       switch(toState)
365       {
366         case S_PLAY: // to S_PLAY
367         {
368           state = S_PLAY;
369           restartAtFrame(currentFrameNumber);
370           return;
371         }
372         case S_PAUSE: // to S_PAUSE
373         {
374           threadStop();
375           state = S_PAUSE;
376           return;
377         }
378         case S_FFWD: // to S_FFWD
379         {
380           return;
381         }
382         case S_FBWD: // to S_FBWD
383         {
384           threadStop();
385           state = S_FBWD;
386           threadStart();
387           return;
388         }
389         case S_STOP: // to S_STOP
390         {
391           threadStop();
392           video->stop();
393           video->blank();
394           audio->stop();
395           video->reset();
396           demuxer->reset();
397           state = S_STOP;
398           return;
399         }
400         case S_JUMP: // to S_JUMP
401         {
402           state = S_PLAY;
403           restartAtFrame(jumpFrame);
404           return;
405         }
406       }
407     }
408     case S_FBWD: // from S_FBWD -----------------------------------
409     {
410       switch(toState)
411       {
412         case S_PLAY: // to S_PLAY
413         {
414           state = S_PLAY;
415           restartAtFrame(currentFrameNumber);
416           return;
417         }
418         case S_PAUSE: // to S_PAUSE
419         {
420           threadStop();
421           state = S_PAUSE;
422           return;
423         }
424         case S_FFWD: // to S_FFWD
425         {
426           threadStop();
427           state = S_FFWD;
428           threadStart();
429           return;
430         }
431         case S_FBWD: // to S_FBWD
432         {
433           return;
434         }
435         case S_STOP: // to S_STOP
436         {
437           threadStop();
438           video->stop();
439           video->blank();
440           audio->stop();
441           video->reset();
442           demuxer->reset();
443           state = S_STOP;
444           return;
445         }
446         case S_JUMP: // to S_JUMP
447         {
448           state = S_PLAY;
449           restartAtFrame(jumpFrame);
450           return;
451         }
452       }
453     }
454     case S_STOP: // from S_STOP -----------------------------------
455     {
456       switch(toState)
457       {
458         case S_PLAY: // to S_PLAY
459         {
460           startup = true;
461
462           audio->reset();
463           audio->systemMuteOff();
464           video->reset();
465           demuxer->reset();
466           if (isRecording)
467           {
468             // FIXME use restartAtFrame here?
469             if (currentFrameNumber > lengthFrames) currentFrameNumber = 0;
470             demuxer->setFrameNum(currentFrameNumber);
471           }
472           if (!isRadio) demuxer->seek();
473
474           videoStartup = true;
475           state = S_PLAY;
476           threadStart();
477
478           if (isRecording)
479           {
480             logger->log("Player", Log::DEBUG, "Immediate play");
481             afeed.start();
482             vfeed.start();
483             video->sync();
484             audio->sync();
485             audio->play();
486             video->pause();
487           }
488           else // do prebuffering
489           {
490             logger->log("Player", Log::DEBUG, "Prebuffering...");
491             preBuffering = true;
492           }
493           return;
494         }
495         case S_PAUSE: // to S_PAUSE
496         {
497           return;
498         }
499         case S_FFWD: // to S_FFWD
500         {
501           return;
502         }
503         case S_FBWD: // to S_FBWD
504         {
505           return;
506         }
507         case S_STOP: // to S_STOP
508         {
509           return;
510         }
511         case S_JUMP: // to S_JUMP
512         {
513           return;
514         }
515       }
516     }
517     // case S_JUMP cannot be selected as a start state because it auto flips to play
518   }
519 }
520
521 // ----------------------------------- Internal functions
522
523 void Player::lock()
524 {
525 #ifndef WIN32
526   pthread_mutex_lock(&mutex);
527   logger->log("Player", Log::DEBUG, "LOCKED");
528
529 #else
530    WaitForSingleObject(mutex, INFINITE );
531 #endif
532 }
533
534 void Player::unLock()
535 {
536 #ifndef WIN32
537   logger->log("Player", Log::DEBUG, "UNLOCKING");
538   pthread_mutex_unlock(&mutex);
539 #else
540    ReleaseMutex(mutex);
541 #endif
542 }
543
544 void Player::restartAtFrame(ULONG newFrame)
545 {
546   vfeed.stop();
547   afeed.stop();
548   threadStop();
549   video->stop();
550   video->reset();
551   audio->reset();
552   demuxer->flush();
553   if (!isRadio) demuxer->seek();
554   currentFrameNumber = newFrame;
555   demuxer->setFrameNum(newFrame);
556   videoStartup = true;
557   afeed.start();
558   vfeed.start();
559   threadStart();
560   audio->play();
561   video->sync();
562   audio->sync();
563   audio->systemMuteOff();
564   audio->doMuting();
565 }
566
567 void Player::doConnectionLost()
568 {
569   Message* m = new Message();
570   m->message = Message::CONNECTION_LOST;
571   m->to = this;
572   commandMessageQueue->postMessage(m);
573 }
574
575 // ----------------------------------- Callback
576
577 void Player::call(void* caller)
578 {
579   if (caller == demuxer)
580   {
581     logger->log("Player", Log::DEBUG, "Callback from demuxer");
582
583     if (video->getTVsize() == Video::ASPECT4X3)
584     {
585       logger->log("Player", Log::DEBUG, "TV is 4:3, ignoring aspect switching");
586       return;
587     }
588
589     int dxCurrentAspect = demuxer->getAspectRatio();
590     if (dxCurrentAspect == Demuxer::ASPECT_4_3)
591     {
592       logger->log("Player", Log::DEBUG, "Demuxer said video is 4:3 aspect, switching TV");
593       video->setAspectRatio(Video::ASPECT4X3);
594     }
595     else if (dxCurrentAspect == Demuxer::ASPECT_16_9)
596     {
597       logger->log("Player", Log::DEBUG, "Demuxer said video is 16:9 aspect, switching TV");
598       video->setAspectRatio(Video::ASPECT16X9);
599     }
600     else
601     {
602       logger->log("Player", Log::DEBUG, "Demuxer said video is something else... ignoring");
603     }
604
605   }
606   else
607   {
608     if (videoStartup)
609     {
610       videoStartup = false;
611       video->reset();
612       video->play();
613       video->sync();
614       vfeed.release();
615       unLock();
616       logger->log("Player", Log::DEBUG, "BANG BANG BANG BANG BANG BANG BANG BANG BANG BANG BANG");
617     }
618
619     threadSignalNoLock();
620   }
621 }
622
623 // ----------------------------------- Feed thread
624
625 void Player::threadMethod()
626 {
627   // this method used to be simple, the only thing it does
628   // is farm out to threadFeed Live/Play/Scan
629   // All the guff is to support scan hitting one end
630
631   if (isRecording)
632   {
633     if ((state == S_FFWD) || (state == S_FBWD))
634     {
635       threadFeedScan();
636       // if this returns then scan hit one end
637       if (state == S_FFWD) // scan hit the end. stop
638       {
639         threadCheckExit();
640         Message* m = new Message(); // Must be done after this thread finishes, and must break into master mutex
641         m->message = Message::STOP_PLAYBACK;
642         logger->log("Player", Log::DEBUG, "Posting message to %p...", commandMessageQueue);
643         commandMessageQueue->postMessage(m);
644         logger->log("Player", Log::DEBUG, "Message posted...");
645         return;
646       }
647       // if execution gets to here, threadFeedScan hit the start, go to play mode
648       state = S_PLAY;
649       audio->reset();
650       demuxer->flush();
651       if (!isRadio) demuxer->seek();
652       demuxer->setFrameNum(currentFrameNumber);
653       videoStartup = true;
654       afeed.start();
655       vfeed.start();
656       audio->play();
657       audio->sync();
658       audio->systemMuteOff();
659       audio->doMuting();
660     }
661
662     if (state == S_PLAY) threadFeedPlay();
663   }
664   else
665   {
666     threadFeedLive();
667   }
668 }
669
670 void Player::threadFeedLive()
671 {
672   UINT thisRead;
673   UINT writeLength;
674   UINT thisWrite;
675   UINT preBufferTotal = 0;
676
677   UINT askFor;
678   while(1)
679   {
680     thisRead = 0;
681     writeLength = 0;
682     thisWrite = 0;
683
684     threadCheckExit();
685
686     if (startup)
687       askFor = startupBlockSize; // find audio streams sized block
688     else
689       askFor = blockSize; // normal
690
691     threadBuffer = vdr->getBlock(0, askFor, &thisRead);
692
693     if (!vdr->isConnected())
694     {
695       doConnectionLost();
696       return;
697     }
698
699     if (!threadBuffer) break;
700
701     if (startup)
702     {
703       int a_stream = demuxer->scan(threadBuffer, thisRead);
704       demuxer->setAudioStream(a_stream);
705       logger->log("Player", Log::DEBUG, "Startup Audio stream chosen %x", a_stream);
706       startup = false;
707     }
708
709     if (preBuffering)
710     {
711       preBufferTotal += thisRead;
712       if (preBufferTotal > 500000)
713       {
714         logger->log("Player", Log::DEBUG, "Got >500K, prebuffering complete");
715
716         preBuffering = false;
717         preBufferTotal = 0;
718
719         audio->sync();
720         audio->play();
721         video->sync();
722         video->pause();
723         afeed.start();
724         vfeed.start();
725 //        unLock(); // thread will be locked by play until here
726         // FIXME - see if this can segfault because it is starting threads out of the master mutex
727       }
728     }
729
730     threadCheckExit();
731
732     while(writeLength < thisRead)
733     {
734       thisWrite = demuxer->put(threadBuffer + writeLength, thisRead - writeLength);
735       writeLength += thisWrite;
736
737       if (!thisWrite)
738       {
739         // demuxer is full and can't take anymore
740         threadLock();
741         threadWaitForSignal();
742         threadUnlock();
743       }
744
745       threadCheckExit();
746     }
747
748     free(threadBuffer);
749     threadBuffer = NULL;
750
751   }
752
753   logger->log("Player", Log::DEBUG, "Live play failed to start or interrupted");
754
755   if (videoStartup) // oh woe. there never was a stream, I was conned!
756   {
757     videoStartup = false;
758     unLock();
759     MILLISLEEP(500); // I think this will solve a race
760   }
761
762   threadCheckExit();
763
764   Message* m = new Message(); // Must be done after this thread finishes, and must break into master mutex
765   m->message = Message::STREAM_END;
766   logger->log("Player", Log::DEBUG, "Posting message to %p...", commandMessageQueue);
767   commandMessageQueue->postMessage(m);
768   logger->log("Player", Log::DEBUG, "Message posted...");
769 }
770
771 void Player::threadFeedPlay()
772 {
773   ULLONG feedPosition;
774   UINT thisRead, writeLength, thisWrite, askFor;
775   time_t lastRescan = time(NULL);
776
777   feedPosition = vdr->positionFromFrameNumber(currentFrameNumber);
778   if (!vdr->isConnected()) { doConnectionLost(); return; }
779   logger->log("Player", Log::DEBUG, "startFeedPlay: wantedframe %i goto %llu", currentFrameNumber, feedPosition);
780
781
782   while(1)
783   {
784     thisRead = 0;
785     writeLength = 0;
786     thisWrite = 0;
787
788     threadCheckExit();
789
790     // If we havn't rescanned for a while..
791     if ((lastRescan + 60) < time(NULL))
792     {
793       lengthBytes = vdr->rescanRecording(&lengthFrames);
794       if (!vdr->isConnected()) { doConnectionLost(); return; }
795       logger->log("Player", Log::DEBUG, "Rescanned and reset length: %llu", lengthBytes);
796       lastRescan = time(NULL);
797     }
798
799     if (feedPosition >= lengthBytes) break;  // finished playback
800
801     if (startup)
802     {
803       if (startupBlockSize > lengthBytes)
804         askFor = lengthBytes; // is a very small recording!
805       else
806         askFor = startupBlockSize; // normal, but a startup sized block to detect all the audio streams
807     }
808     else
809     {
810       if ((feedPosition + blockSize) > lengthBytes) // last block of recording
811         askFor = lengthBytes - feedPosition;
812       else // normal
813         askFor = blockSize;
814     }
815
816     threadBuffer = vdr->getBlock(feedPosition, askFor, &thisRead);
817     feedPosition += thisRead;
818
819     if (!vdr->isConnected())
820     {
821       doConnectionLost();
822       return;
823     }
824
825     if (!threadBuffer) break;
826
827     if (startup)
828     {
829       int a_stream = demuxer->scan(threadBuffer, thisRead);
830       demuxer->setAudioStream(a_stream);
831       logger->log("Player", Log::DEBUG, "Startup Audio stream chosen %x", a_stream);
832       startup = false;
833     }
834
835     threadCheckExit();
836
837     while(writeLength < thisRead)
838     {
839       thisWrite = demuxer->put(threadBuffer + writeLength, thisRead - writeLength);
840       writeLength += thisWrite;
841
842       if (!thisWrite)
843       {
844         // demuxer is full and can't take anymore
845         threadLock();
846         threadWaitForSignal();
847         threadUnlock();
848       }
849
850       threadCheckExit();
851     }
852
853     free(threadBuffer);
854     threadBuffer = NULL;
855
856   }
857
858   // end of recording
859   logger->log("Player", Log::DEBUG, "Recording playback ends");
860
861   if (videoStartup) // oh woe. there never was a stream, I was conned!
862   {
863     videoStartup = false;
864     unLock();
865     MILLISLEEP(500); // I think this will solve a race
866   }
867
868   threadCheckExit();
869
870   Message* m = new Message(); // Must be done after this thread finishes, and must break into master mutex
871   m->message = Message::STOP_PLAYBACK;  // recording
872   logger->log("Player", Log::DEBUG, "Posting message to %p...", commandMessageQueue);
873   commandMessageQueue->postMessage(m);
874   logger->log("Player", Log::DEBUG, "Message posted...");
875 }
876
877 void Player::threadFeedScan()
878 {
879   ULONG direction = 0;
880   ULONG iframeNumber = 0;
881   ULONG iframeLength = 0;
882   ULLONG filePos;
883   UINT amountReceived;
884   UINT videoLength;
885
886   if (state == S_FFWD) direction = 1; // and 0 for backward
887
888   while(1)
889   {
890     if (!vdr->getNextIFrame(currentFrameNumber, direction, &filePos, &iframeNumber, &iframeLength)) break;
891     threadBuffer = vdr->getBlock(filePos, iframeLength, &amountReceived);
892     videoLength = demuxer->stripAudio(threadBuffer, amountReceived);
893     video->displayIFrame(threadBuffer, videoLength);
894     currentFrameNumber = iframeNumber;
895     free(threadBuffer);
896     threadBuffer = NULL;
897     threadCheckExit();
898     MILLISLEEP(100);
899   }
900   // scan has hit one end
901 }
902
903 void Player::threadPostStopCleanup()
904 {
905   if (threadBuffer)
906   {
907     free(threadBuffer);
908     threadBuffer = NULL;
909   }
910 }
911
912 // ----------------------------------- Dev
913
914 #ifdef DEV
915 void Player::test1()
916 {
917   logger->log("Player", Log::DEBUG, "PLAYER TEST 1");
918   video->play();
919 //  video->setAspectRatio(Video::ASPECT4X3);
920 }
921
922 void Player::test2()
923 {
924   logger->log("Player", Log::DEBUG, "PLAYER TEST 2");
925   video->setAspectRatio(Video::ASPECT16X9);
926 }
927 #endif