2 Copyright 2004-2005 Chris Tallon
4 This file is part of VOMP.
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.
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.
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
21 #include "playervideo.h"
23 PlayerVideo::PlayerVideo(MessageQueue* messageQueue, UCHAR tIsRecording)
24 : vfeed(this), afeed(this)
26 commandMessageQueue = messageQueue;
28 logger = Log::getInstance();
34 feedMode = MODE_NORMAL;
35 isRecording = tIsRecording;
40 PlayerVideo::~PlayerVideo()
42 if (initted) shutdown();
45 int PlayerVideo::init()
47 if (initted) return 0;
49 video = Video::getInstance();
51 if (!demuxer.init(this))
53 logger->log("Player", Log::ERR, "Demuxer failed to init");
58 vfeed.init(video->getFD());
59 afeed.init(audio->getFD());
70 int PlayerVideo::shutdown()
72 if (!initted) return 0;
75 logger->log("Player", Log::DEBUG, "Player shutdown...");
91 logger->log("Player", Log::DEBUG, "Player shutdown done");
96 int PlayerVideo::play()
98 if (!initted) return 0;
100 // If we are just paused, unpause!
107 // If we are fast forwarding, set to normal
114 // If we are fast backwarding, set to normal
117 toggleFastBackward();
121 // If we are already playing, bail // FIXME - resync?
124 logger->log("Player", Log::DEBUG, "DOING RESYNC");
155 // Standard play start
162 // ------------------------ This one works, but doesn't allow any pre-buffering.
172 usleep(500000); // SYNC
177 // ------------------------ This one doesn't work, but it should, and would allow for prebuffering.
184 // struct timespec delay;
186 // delay.tv_nsec = 500000000;
187 // nanosleep(&delay, NULL);
196 // ------------------------------------------------------------------------------------------------
202 void PlayerVideo::stop()
204 if (!initted) return;
205 if (!playing) return;
212 video->unFastForward();
213 audio->systemMuteOff();
214 feedMode = MODE_NORMAL;
220 logger->log("PlayerVideo", Log::DEBUG, "Temp 1");
222 logger->log("PlayerVideo", Log::DEBUG, "Temp 2");
224 logger->log("PlayerVideo", Log::DEBUG, "Temp 3");
226 logger->log("PlayerVideo", Log::DEBUG, "Temp 4");
228 logger->log("PlayerVideo", Log::DEBUG, "Temp 5");
230 logger->log("PlayerVideo", Log::DEBUG, "Temp 6");
232 logger->log("PlayerVideo", Log::DEBUG, "Temp 7");
234 logger->log("PlayerVideo", Log::DEBUG, "Temp 8");
236 logger->log("PlayerVideo", Log::DEBUG, "Temp 9");
238 logger->log("PlayerVideo", Log::DEBUG, "Temp 10");
243 void PlayerVideo::togglePause()
245 if (!initted) return;
246 if (!playing) return;
248 if (ffwd) toggleFastForward();
249 if (fbwd) toggleFastBackward();
265 void PlayerVideo::setPosition(ULLONG position)
267 feedPosition = position;
270 void PlayerVideo::setLength(ULLONG length)
272 lastRescan = time(NULL);
273 streamLength = length;
274 logger->log("PlayerVideo", Log::DEBUG, "Player has received length of %llu", streamLength);
277 void PlayerVideo::skipForward(int seconds)
279 // skip forward 1 minute
280 logger->log("Player", Log::DEBUG, "SKIP FORWARD %i SECONDS", seconds);
282 if (paused) togglePause();
284 ULLONG moveBy = seconds * 500000;
292 audio->doMuting(); // ???
294 feedPosition += moveBy;
296 // printf("Audio test %i\n", audio->test());
307 usleep(500000); // SYNC
314 void PlayerVideo::skipBackward(int seconds)
316 // skip forward 1 minute
317 logger->log("Player", Log::DEBUG, "SKIP BACKWARD %i SECONDS", seconds);
319 if (paused) togglePause();
321 ULLONG moveBy = seconds * 500000;
330 audio->doMuting(); // ???
332 if (feedPosition > moveBy) feedPosition -= moveBy;
342 usleep(500000); // SYNC
349 void PlayerVideo::toggleFastForward()
351 if (!initted) return;
352 if (!playing) return;
354 if (paused) togglePause();
355 if (fbwd) toggleFastBackward();
360 // video->unFastForward();
381 audio->systemMuteOff();
384 usleep(500000); // SYNC
390 demuxer.flushAudio();
398 audio->systemMuteOff();
405 audio->systemMuteOn();
406 video->fastForward();
410 void PlayerVideo::toggleFastBackward()
412 if (!initted) return;
413 if (!playing) return;
415 if (paused) togglePause();
416 if (ffwd) toggleFastForward();
422 audio->systemMuteOff();
425 feedMode = MODE_NORMAL;
432 audio->systemMuteOn();
435 feedMode = MODE_BACKWARDS;
443 void PlayerVideo::jumpToPercent(int percent)
454 feedPosition = streamLength * percent / 100;
464 usleep(500000); // SYNC
471 void PlayerVideo::call(void* caller)
473 if (caller == &demuxer)
475 logger->log("Player", Log::DEBUG, "Callback from demuxer");
477 if (video->getTVsize() == Video::ASPECT4X3)
479 logger->log("Player", Log::DEBUG, "TV is 4:3, ignoring aspect switching");
483 int dxCurrentAspect = demuxer.getAspectRatio();
484 if (dxCurrentAspect == Demuxer::ASPECT_4_3)
486 logger->log("Player", Log::DEBUG, "Demuxer said video is 4:3 aspect, switching TV");
487 video->setAspectRatio(Video::ASPECT4X3);
489 else if (dxCurrentAspect == Demuxer::ASPECT_16_9)
491 logger->log("Player", Log::DEBUG, "Demuxer said video is 16:9 aspect, switching TV");
492 video->setAspectRatio(Video::ASPECT16X9);
496 logger->log("Player", Log::DEBUG, "Demuxer said video is something else... ignoring");
502 threadSignalNoLock();
508 void PlayerVideo::threadMethod()
514 VDR* vdr = VDR::getInstance();
525 // If we havn't rescanned for a while..
526 if (isRecording && ((lastRescan + 60) < time(NULL)))
528 streamLength = vdr->rescanRecording();
529 Log::getInstance()->log("PlayerVideo", Log::DEBUG, "Rescanned and reset length: %llu", streamLength);
530 lastRescan = time(NULL);
533 if (streamLength) // is playing a recording
535 if (feedPosition >= streamLength) break; // finished playback
539 if (startupBlockSize > streamLength)
540 askFor = streamLength; // is a very small recording!
542 askFor = startupBlockSize; // normal, but a startup sized block to detect all the audio streams
546 if ((feedPosition + blockSize) > streamLength) // last block of recording
547 askFor = streamLength - feedPosition;
552 else // is playing live
555 askFor = startupBlockSize; // find audio streams sized block
557 askFor = blockSize; // normal
560 threadBuffer = vdr->getBlock(feedPosition, askFor, &thisRead);
561 if (!threadBuffer) break;
565 int a_stream = demuxer.scan(threadBuffer, thisRead);
566 demuxer.setAudioStream(a_stream);
567 Log::getInstance()->log("Player", Log::DEBUG, "Startup Audio stream chosen %x", a_stream);
571 if (feedMode == MODE_NORMAL)
573 feedPosition += thisRead;
575 else if (feedMode == MODE_BACKWARDS)
577 if (feedPosition >= blockSize)
579 feedPosition -= blockSize;
584 // got to the start of the recording.. revert to play mode? how?
585 feedPosition += thisRead;
591 while(writeLength < thisRead)
593 thisWrite = demuxer.put(threadBuffer + writeLength, thisRead - writeLength);
594 writeLength += thisWrite;
598 // Log::getInstance()->log("Player", Log::DEBUG, "DEMUXER FULL!!!");
599 // demuxer is full and cant take anymore
600 threadWaitForSignal();
601 // Log::getInstance()->log("Player", Log::DEBUG, "BACK FROM WAIT");
613 Log::getInstance()->log("Player", Log::DEBUG, "Recording playback ends");
614 Message* m = new Message();
615 if (streamLength) m->message = Message::STOP_PLAYBACK; // recording
616 else m->message = Message::STREAM_END; // live
617 Log::getInstance()->log("Player", Log::DEBUG, "Posting message to %p...", commandMessageQueue);
618 commandMessageQueue->postMessage(m);
619 Log::getInstance()->log("Player", Log::DEBUG, "Message posted...");
622 void PlayerVideo::threadPostStopCleanup()
624 Log::getInstance()->log("Player", Log::DEBUG, "Post stop cleanup 1");
627 Log::getInstance()->log("Player", Log::DEBUG, "Post stop cleanup 2");
634 void PlayerVideo::test1()
636 Log::getInstance()->log("Player", Log::DEBUG, "PLAYER TEST 1");
639 void PlayerVideo::test2()
641 Log::getInstance()->log("Player", Log::DEBUG, "PLAYER TEST 2");