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() < 30)
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);
272 FILE* fp = fopen("/data.ts", "a");
273 fwrite(s.data, s.len, 1, fp);
277 /* logger->log("PlayerLiveTV", Log::DEBUG, "Back from demuxer %i", a);
280 logger->log("PlayerLiveTV", Log::ERR, "--------------------------------------- Back from demuxer %i", a);
281 logger->log("PlayerLiveTV", Log::ERR, "--------------------------------------- Back from demuxer %i", a);
282 logger->log("PlayerLiveTV", Log::ERR, "--------------------------------------- Back from demuxer %i", a);
283 logger->log("PlayerLiveTV", Log::ERR, "--------------------------------------- Back from demuxer %i", a);
284 logger->log("PlayerLiveTV", Log::ERR, "--------------------------------------- Back from demuxer %i", a);
285 logger->log("PlayerLiveTV", Log::ERR, "--------------------------------------- Back from demuxer %i", a);
286 logger->log("PlayerLiveTV", Log::ERR, "--------------------------------------- Back from demuxer %i", a);
287 logger->log("PlayerLiveTV", Log::ERR, "--------------------------------------- Back from demuxer %i", a);
288 logger->log("PlayerLiveTV", Log::ERR, "--------------------------------------- Back from demuxer %i", a);
289 logger->log("PlayerLiveTV", Log::ERR, "--------------------------------------- Back from demuxer %i", a);
290 logger->log("PlayerLiveTV", Log::ERR, "--------------------------------------- Back from demuxer %i", a);
291 logger->log("PlayerLiveTV", Log::ERR, "--------------------------------------- Back from demuxer %i", a);
292 logger->log("PlayerLiveTV", Log::ERR, "--------------------------------------- Back from demuxer %i", a);
293 logger->log("PlayerLiveTV", Log::ERR, "--------------------------------------- Back from demuxer %i", a);
294 logger->log("PlayerLiveTV", Log::ERR, "--------------------------------------- Back from demuxer %i", a);
295 logger->log("PlayerLiveTV", Log::ERR, "--------------------------------------- Back from demuxer %i", a);
296 logger->log("PlayerLiveTV", Log::ERR, "--------------------------------------- Back from demuxer %i", a);
297 logger->log("PlayerLiveTV", Log::ERR, "--------------------------------------- Back from demuxer %i", a);
298 logger->log("PlayerLiveTV", Log::ERR, "--------------------------------------- Back from demuxer %i", a);
299 logger->log("PlayerLiveTV", Log::ERR, "--------------------------------------- Back from demuxer %i", a);
300 logger->log("PlayerLiveTV", Log::ERR, "--------------------------------------- Back from demuxer %i", a);
308 void PlayerLiveTV::switchState(UCHAR newState)
310 logger->log("PlayerLiveTV", Log::DEBUG, "Switch from state %u to state %u", state, newState);
314 case S_STOP: // FROM S_STOP
334 case S_PREBUFFERING: // FROM S_PREBUFFERING
340 vdr->stopStreaming();
346 vdr->stopStreaming();
355 audio->setStreamType(Audio::MPEG2_PES);
356 audio->systemMuteOff();
373 case S_PLAY: // FROM S_PLAY
379 vdr->stopStreaming();
392 vdr->stopStreaming();
416 void PlayerLiveTV::threadMethod()
418 logger->log("PlayerLiveTV", Log::DEBUG, "Thread started");
422 while(!instructions.empty())
424 struct PLTVInstruction i = instructions.front();
427 logger->log("PlayerLiveTV", Log::DEBUG, "%u %lu", i.instruction, i.channelIndex);
430 if (i.instruction == 1)
432 logger->log("PlayerLiveTV", Log::DEBUG, "start new stream");
434 switchState(S_PREBUFFERING);
436 Channel* chan = (*chanList)[i.channelIndex];
438 demuxer->setVID(chan->vpid);
439 demuxer->setAID(chan->apids[0].pid);
440 logger->log("PlayerLiveTV", Log::DEBUG, "Demuxer pids: %u %u", chan->vpid, chan->apids[0].pid);
441 vdr->streamChannel(chan->number, this);
444 else if (i.instruction == 2)
446 logger->log("PlayerLiveTV", Log::DEBUG, "Stopping");
456 if (streamChunks.size())
458 if (state == S_PREBUFFERING)
460 if (streamChunks.size() > 0)
462 while(streamChunks.size()) chunkToDemuxer();
466 else if (state == S_PLAY)
468 while(streamChunks.size()) chunkToDemuxer();
473 threadWaitForSignal(); // unlocks and waits for signal
476 logger->log("PlayerLiveTV", Log::DEBUG, "Woken");
479 logger->log("PlayerLiveTV", Log::DEBUG, "End of thread");
482 void PlayerLiveTV::threadPostStopCleanup()
484 logger->log("PlayerLiveTV", Log::DEBUG, "Post stop cleanup");
487 // ----------------------------------- Dev
490 void PlayerLiveTV::test1()
492 logger->log("PlayerLiveTV", Log::DEBUG, "PLAYER TEST 1");
495 void PlayerLiveTV::test2()
497 logger->log("PlayerLiveTV", Log::DEBUG, "PLAYER TEST 2");