]> git.vomp.tv Git - vompclient.git/blob - playerlivetv.cc
Updates to new streaming protocol and live tv
[vompclient.git] / playerlivetv.cc
1 /*
2     Copyright 2007 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 "playerlivetv.h"
22
23 #include "log.h"
24 #include "audio.h"
25 #include "video.h"
26 #include "demuxerts.h"
27 #include "vdr.h"
28 #include "messagequeue.h"
29 #include "remote.h"
30 #include "message.h"
31 #include "channel.h"
32
33 // ----------------------------------- Called from outside, one offs or info funcs
34
35 PlayerLiveTV::PlayerLiveTV(MessageQueue* tmessageQueue, void* tmessageReceiver, ChannelList* tchanList)
36 : vfeed(this), afeed(this)
37 {
38   messageQueue = tmessageQueue;
39   messageReceiver = tmessageReceiver;
40   chanList = tchanList;
41   
42   audio = Audio::getInstance();
43   video = Video::getInstance();
44   logger = Log::getInstance();
45   vdr = VDR::getInstance();
46   initted = false;
47
48 //  videoStartup = false;
49 //  preBuffering = false;
50
51   stopNow = false;
52   state = 1;
53
54   video->turnVideoOn();
55 }
56
57 PlayerLiveTV::~PlayerLiveTV()
58 {
59   if (initted) shutdown();
60 }
61
62 int PlayerLiveTV::init()
63 {
64   if (initted) return 0;
65
66   demuxer = new DemuxerTS();
67   if (!demuxer) return 0;
68  
69   if (!demuxer->init(this, audio, video, 2097152, 524288))
70   {
71     logger->log("PlayerLiveTV", Log::ERR, "Demuxer failed to init");
72     shutdown();
73     return 0;
74   }
75
76   vfeed.init();
77   afeed.init();
78
79   video->stop();
80   video->blank();
81   audio->stop();
82
83   initted = true;
84   return 1;
85 }
86
87 int PlayerLiveTV::shutdown()
88 {
89   if (!initted) return 0;
90   stop();
91   initted = false;
92
93   delete demuxer;
94
95 #ifdef WIN32
96   CloseHandle(mutex);
97 #endif
98
99   return 1;
100 }
101
102 bool* PlayerLiveTV::getDemuxerMpegAudioChannels()
103 {
104   return demuxer->getmpAudioChannels();
105 }
106
107 bool* PlayerLiveTV::getDemuxerAc3AudioChannels()
108 {
109   return demuxer->getac3AudioChannels();
110 }
111
112 int PlayerLiveTV::getCurrentAudioChannel()
113 {
114   return demuxer->getAID();
115 }
116
117 void PlayerLiveTV::setAudioChannel(int newChannel)
118 {
119   return demuxer->setAID(newChannel);
120 }
121
122 // ----------------------------------- Externally called events
123
124 void PlayerLiveTV::go(ULONG index)
125 {
126   struct PLTVInstruction i;
127   i.instruction = 1;
128   i.channelIndex = index;
129   instructions.push(i);
130   
131   threadStart();
132 }
133
134 void PlayerLiveTV::setChannel(ULONG index)
135 {
136 //  demuxer->setVID(Vpid);
137 //  demuxer->setAID(Apid);
138 //  play();
139   logger->log("PlayerLiveTV", Log::DEBUG, "setChannel");
140   
141   struct PLTVInstruction i;
142   i.instruction = 1;
143   i.channelIndex = index;
144   instructions.push(i);  
145   
146   threadSignalNoLock();
147 }
148
149 void PlayerLiveTV::stop()
150 {
151   logger->log("PlayerLiveTV", Log::DEBUG, "stop");
152
153   struct PLTVInstruction i;
154   i.instruction = 2;
155   instructions.push(i);
156   
157   logger->log("PlayerLiveTV", Log::DEBUG, "Pushed instruction");
158
159   threadSignal();
160
161   logger->log("PlayerLiveTV", Log::DEBUG, "Signal sent");
162
163   threadStop();
164
165   logger->log("PlayerLiveTV", Log::DEBUG, "Stop returning");
166 }
167
168 // ----------------------------------- Callback
169
170 void PlayerLiveTV::call(void* caller)
171 {
172   if (caller == demuxer)
173   {
174     logger->log("PlayerLiveTV", Log::DEBUG, "Callback from demuxer");
175
176     if (video->getTVsize() == Video::ASPECT4X3)
177     {
178       logger->log("PlayerLiveTV", Log::DEBUG, "TV is 4:3, ignoring aspect switching");
179       return;
180     }
181
182     int dxCurrentAspect = demuxer->getAspectRatio();
183     if (dxCurrentAspect == Demuxer::ASPECT_4_3)
184     {
185       logger->log("PlayerLiveTV", Log::DEBUG, "Demuxer said video is 4:3 aspect, switching TV");
186       video->setAspectRatio(Video::ASPECT4X3);
187
188       Message* m = new Message();
189       m->from = this;
190       m->to = messageReceiver;
191       m->message = Message::PLAYER_EVENT;
192       m->parameter = PlayerLiveTV::ASPECT43;
193       messageQueue->postMessageFromOuterSpace(m);
194     }
195     else if (dxCurrentAspect == Demuxer::ASPECT_16_9)
196     {
197       logger->log("PlayerLiveTV", Log::DEBUG, "Demuxer said video is 16:9 aspect, switching TV");
198       video->setAspectRatio(Video::ASPECT16X9);
199
200       Message* m = new Message();
201       m->from = this;
202       m->to = messageReceiver;
203       m->message = Message::PLAYER_EVENT;
204       m->parameter = PlayerLiveTV::ASPECT169;
205       messageQueue->postMessageFromOuterSpace(m);
206     }
207     else
208     {
209       logger->log("PlayerLiveTV", Log::DEBUG, "Demuxer said video is something else... ignoring");
210     }
211
212   }
213   else
214   {
215     if (videoStartup)
216     {
217       logger->log("PlayerLiveTV", Log::DEBUG, "Video startup");
218       videoStartup = false;
219       video->reset();
220       video->play();
221       video->sync();
222       vfeed.release();
223     }
224
225     threadSignalNoLock();
226   }
227 }
228
229 // -----------------------------------
230
231 void PlayerLiveTV::streamReceive(void* data, ULONG len)
232 {
233   logger->log("PlayerLiveTV", Log::DEBUG, "Got data, %p, %lu", data, len);
234   
235
236   if (streamChunks.size() < 30)
237   {
238     StreamChunk s;
239     s.data = data;
240     s.len = len;
241     streamChunks.push(s);
242     threadSignalNoLock();
243   }
244   else
245
246   {
247     // Too many chunks in streamChunks, drop this chunk
248     free(data);
249     logger->log("PlayerLiveTV", Log::DEBUG, "Dropped chunk");
250   }
251 }
252
253 void PlayerLiveTV::clearStreamChunks()
254 {
255   while(streamChunks.size())
256   {
257     logger->log("PlayerLiveTV", Log::DEBUG, "Dropping chunk from old stream");
258     struct StreamChunk s = streamChunks.front();
259     streamChunks.pop();
260     free(s.data);
261   }
262 }
263
264 void PlayerLiveTV::chunkToDemuxer()
265 {
266   StreamChunk s = streamChunks.front();
267   streamChunks.pop();
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);
270   
271 /*  
272   FILE* fp = fopen("/data.ts", "a");
273   fwrite(s.data, s.len, 1, fp);
274   fclose(fp);
275 */
276   
277  /* logger->log("PlayerLiveTV", Log::DEBUG, "Back from demuxer %i", a);
278   if (0)//(a != 50000)
279   {
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);
301     abort();
302
303   }
304   */
305   free(s.data);  
306 }
307
308 void PlayerLiveTV::switchState(UCHAR newState)
309 {
310   logger->log("PlayerLiveTV", Log::DEBUG, "Switch from state %u to state %u", state, newState);
311
312   switch(state)
313   {
314     case S_STOP:   // FROM S_STOP
315     {
316       switch(newState)
317       {
318         case S_STOP:
319         {
320           abort();
321         }
322         case S_PREBUFFERING:
323         {
324           break;
325         }
326         case S_PLAY:
327         {
328           abort();
329         }
330       }
331       break;
332     }
333     
334     case S_PREBUFFERING:    // FROM S_PREBUFFERING
335     {
336       switch(newState)
337       {
338         case S_STOP:
339         {
340           vdr->stopStreaming();
341           clearStreamChunks();
342           break;
343         }      
344         case S_PREBUFFERING:
345         {
346           vdr->stopStreaming();
347           clearStreamChunks();
348           break;
349         }
350         case S_PLAY:
351         {
352           videoStartup = true;
353
354           audio->reset();
355           audio->setStreamType(Audio::MPEG2_PES);
356           audio->systemMuteOff();
357           video->reset();
358           demuxer->reset();
359           demuxer->seek();
360           
361           audio->sync();
362           audio->play();
363           video->sync();
364           video->pause();
365           afeed.start();
366           vfeed.start();
367           break;
368         }
369       }
370       break;
371     }
372     
373     case S_PLAY:     // FROM S_PLAY
374     {
375       switch(newState)
376       {
377         case S_STOP:
378         { 
379           vdr->stopStreaming();
380           clearStreamChunks();
381           vfeed.stop();
382           afeed.stop();
383           video->stop();
384           video->blank();
385           audio->stop();
386           audio->unPause();
387           video->reset();
388           break;
389         }
390         case S_PREBUFFERING:
391         {
392           vdr->stopStreaming();
393           clearStreamChunks();
394           vfeed.stop();
395           afeed.stop();
396           video->stop();
397           video->blank();
398           audio->stop();
399           audio->unPause();
400           video->reset();
401           demuxer->reset();
402           break;
403         }
404         case S_PLAY:
405         {
406           abort();
407         }
408       }
409       break;
410     }    
411   }  
412   
413   state = newState;
414 }
415
416 void PlayerLiveTV::threadMethod()
417 {
418   logger->log("PlayerLiveTV", Log::DEBUG, "Thread started");
419
420   while(1)
421   {
422     while(!instructions.empty())
423     {
424       struct PLTVInstruction i = instructions.front();
425       instructions.pop();
426     
427       logger->log("PlayerLiveTV", Log::DEBUG, "%u %lu", i.instruction, i.channelIndex);
428       
429
430       if (i.instruction == 1)
431       {
432         logger->log("PlayerLiveTV", Log::DEBUG, "start new stream");
433
434         switchState(S_PREBUFFERING);
435
436         Channel* chan = (*chanList)[i.channelIndex];
437         chan->loadPids();
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);
442         
443       }
444       else if (i.instruction == 2)
445       {
446         logger->log("PlayerLiveTV", Log::DEBUG, "Stopping");
447         switchState(S_STOP);
448
449         stopNow = true;
450         break;
451       }
452     }
453
454     if (stopNow) break;
455
456     if (streamChunks.size())
457     {
458       if (state == S_PREBUFFERING)
459       {
460         if (streamChunks.size() > 0)
461         {
462           while(streamChunks.size()) chunkToDemuxer();
463           switchState(S_PLAY);
464         }
465       }
466       else if (state == S_PLAY)
467       {
468         while(streamChunks.size()) chunkToDemuxer();
469       }
470     }
471     
472     threadLock();
473     threadWaitForSignal(); // unlocks and waits for signal
474     
475     threadUnlock();
476     logger->log("PlayerLiveTV", Log::DEBUG, "Woken");
477   }
478
479   logger->log("PlayerLiveTV", Log::DEBUG, "End of thread");
480 }
481
482 void PlayerLiveTV::threadPostStopCleanup()
483 {
484   logger->log("PlayerLiveTV", Log::DEBUG, "Post stop cleanup");
485 }
486
487 // ----------------------------------- Dev
488
489 #ifdef DEV
490 void PlayerLiveTV::test1()
491 {
492   logger->log("PlayerLiveTV", Log::DEBUG, "PLAYER TEST 1");
493 }
494
495 void PlayerLiveTV::test2()
496 {
497   logger->log("PlayerLiveTV", Log::DEBUG, "PLAYER TEST 2");
498 }
499 #endif
500