2 Copyright 2007 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 "playerlivetv.h"
26 #include "demuxerts.h"
28 #include "messagequeue.h"
33 // ----------------------------------- Called from outside, one offs or info funcs
35 PlayerLiveTV::PlayerLiveTV(MessageQueue* tmessageQueue, void* tmessageReceiver, ChannelList* tchanList)
36 : vfeed(this), afeed(this)
38 messageQueue = tmessageQueue;
39 messageReceiver = tmessageReceiver;
42 audio = Audio::getInstance();
43 video = Video::getInstance();
44 logger = Log::getInstance();
45 vdr = VDR::getInstance();
48 // videoStartup = false;
49 // preBuffering = false;
57 PlayerLiveTV::~PlayerLiveTV()
59 if (initted) shutdown();
62 int PlayerLiveTV::init()
64 if (initted) return 0;
66 demuxer = new DemuxerTS();
67 if (!demuxer) return 0;
69 if (!demuxer->init(this, audio, video, 2097152, 524288))
71 logger->log("PlayerLiveTV", Log::ERR, "Demuxer failed to init");
87 int PlayerLiveTV::shutdown()
89 if (!initted) return 0;
102 bool* PlayerLiveTV::getDemuxerMpegAudioChannels()
104 return demuxer->getmpAudioChannels();
107 bool* PlayerLiveTV::getDemuxerAc3AudioChannels()
109 return demuxer->getac3AudioChannels();
112 int PlayerLiveTV::getCurrentAudioChannel()
114 return demuxer->getAID();
117 void PlayerLiveTV::setAudioChannel(int newChannel)
119 return demuxer->setAID(newChannel);
122 // ----------------------------------- Externally called events
124 void PlayerLiveTV::go(ULONG index)
126 struct PLTVInstruction i;
128 i.channelIndex = index;
129 instructions.push(i);
134 void PlayerLiveTV::setChannel(ULONG index)
136 // demuxer->setVID(Vpid);
137 // demuxer->setAID(Apid);
139 logger->log("PlayerLiveTV", Log::DEBUG, "setChannel");
141 struct PLTVInstruction i;
143 i.channelIndex = index;
144 instructions.push(i);
146 threadSignalNoLock();
149 void PlayerLiveTV::stop()
151 logger->log("PlayerLiveTV", Log::DEBUG, "stop");
153 struct PLTVInstruction i;
155 instructions.push(i);
157 logger->log("PlayerLiveTV", Log::DEBUG, "Pushed instruction");
161 logger->log("PlayerLiveTV", Log::DEBUG, "Signal sent");
165 logger->log("PlayerLiveTV", Log::DEBUG, "Stop returning");
168 // ----------------------------------- Callback
170 void PlayerLiveTV::call(void* caller)
172 if (caller == demuxer)
174 logger->log("PlayerLiveTV", Log::DEBUG, "Callback from demuxer");
176 if (video->getTVsize() == Video::ASPECT4X3)
178 logger->log("PlayerLiveTV", Log::DEBUG, "TV is 4:3, ignoring aspect switching");
182 int dxCurrentAspect = demuxer->getAspectRatio();
183 if (dxCurrentAspect == Demuxer::ASPECT_4_3)
185 logger->log("PlayerLiveTV", Log::DEBUG, "Demuxer said video is 4:3 aspect, switching TV");
186 video->setAspectRatio(Video::ASPECT4X3);
188 Message* m = new Message();
190 m->to = messageReceiver;
191 m->message = Message::PLAYER_EVENT;
192 m->parameter = PlayerLiveTV::ASPECT43;
193 messageQueue->postMessageFromOuterSpace(m);
195 else if (dxCurrentAspect == Demuxer::ASPECT_16_9)
197 logger->log("PlayerLiveTV", Log::DEBUG, "Demuxer said video is 16:9 aspect, switching TV");
198 video->setAspectRatio(Video::ASPECT16X9);
200 Message* m = new Message();
202 m->to = messageReceiver;
203 m->message = Message::PLAYER_EVENT;
204 m->parameter = PlayerLiveTV::ASPECT169;
205 messageQueue->postMessageFromOuterSpace(m);
209 logger->log("PlayerLiveTV", Log::DEBUG, "Demuxer said video is something else... ignoring");
217 logger->log("PlayerLiveTV", Log::DEBUG, "Video startup");
218 videoStartup = false;
225 threadSignalNoLock();
229 // -----------------------------------
231 void PlayerLiveTV::streamReceive(void* data, ULONG len)
233 logger->log("PlayerLiveTV", Log::DEBUG, "Got data, %p, %lu", data, len);
236 if (streamChunks.size() < 11)
241 streamChunks.push(s);
242 threadSignalNoLock();
247 // Too many chunks in streamChunks, drop this chunk
249 logger->log("PlayerLiveTV", Log::DEBUG, "Dropped chunk");
253 void PlayerLiveTV::clearStreamChunks()
255 while(streamChunks.size())
257 logger->log("PlayerLiveTV", Log::DEBUG, "Dropping chunk from old stream");
258 struct StreamChunk s = streamChunks.front();
264 void PlayerLiveTV::chunkToDemuxer()
266 StreamChunk s = streamChunks.front();
268 logger->log("PlayerLiveTV", Log::DEBUG, "About to call demuxer with %p %lu", s.data, s.len);
269 demuxer->put((UCHAR*)s.data, s.len);
273 void PlayerLiveTV::switchState(UCHAR newState)
275 logger->log("PlayerLiveTV", Log::DEBUG, "Switch from state %u to state %u", state, newState);
279 case S_STOP: // FROM S_STOP
299 case S_PREBUFFERING: // FROM S_PREBUFFERING
305 vdr->stopStreaming();
311 vdr->stopStreaming();
320 audio->setStreamType(Audio::MPEG2_PES);
321 audio->systemMuteOff();
338 case S_PLAY: // FROM S_PLAY
344 vdr->stopStreaming();
357 vdr->stopStreaming();
381 void PlayerLiveTV::threadMethod()
383 logger->log("PlayerLiveTV", Log::DEBUG, "Thread started");
387 while(!instructions.empty())
389 struct PLTVInstruction i = instructions.front();
392 logger->log("PlayerLiveTV", Log::DEBUG, "%u %lu", i.instruction, i.channelIndex);
395 if (i.instruction == 1)
397 logger->log("PlayerLiveTV", Log::DEBUG, "start new stream");
399 switchState(S_PREBUFFERING);
401 Channel* chan = (*chanList)[i.channelIndex];
403 demuxer->setVID(chan->vpid);
404 demuxer->setAID(chan->apids[0].pid);
405 logger->log("PlayerLiveTV", Log::DEBUG, "Demuxer pids: %u %u", chan->vpid, chan->apids[0].pid);
406 vdr->streamChannel(chan->number, this);
409 else if (i.instruction == 2)
411 logger->log("PlayerLiveTV", Log::DEBUG, "Stopping");
421 if (streamChunks.size())
423 if (state == S_PREBUFFERING)
425 if (streamChunks.size() > 4)
427 while(streamChunks.size()) chunkToDemuxer();
431 else if (state == S_PLAY)
433 while(streamChunks.size()) chunkToDemuxer();
438 threadWaitForSignal(); // unlocks and waits for signal
441 logger->log("PlayerLiveTV", Log::DEBUG, "Woken");
444 logger->log("PlayerLiveTV", Log::DEBUG, "End of thread");
447 void PlayerLiveTV::threadPostStopCleanup()
449 logger->log("PlayerLiveTV", Log::DEBUG, "Post stop cleanup");
452 // ----------------------------------- Dev
455 void PlayerLiveTV::test1()
457 logger->log("PlayerLiveTV", Log::DEBUG, "PLAYER TEST 1");
460 void PlayerLiveTV::test2()
462 logger->log("PlayerLiveTV", Log::DEBUG, "PLAYER TEST 2");