]> git.vomp.tv Git - vompclient.git/blob - demuxer.cc
DVB Subtitles: Live TV
[vompclient.git] / demuxer.cc
1 /*
2     Copyright 2005-2008 Mark Calderbank
3     Copyright 2007 Marten Richter (AC3 support)
4
5     This file is part of VOMP.
6
7     VOMP is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11
12     VOMP is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16
17     You should have received a copy of the GNU General Public License
18     along with VOMP; if not, write to the Free Software Foundation, Inc.,
19     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 */
21
22 #include "demuxer.h"
23
24 #include "callback.h"
25 #include "dvbsubtitles.h"
26 #include "log.h"
27
28 #define DEMUXER_SEQ_HEAD 0x000001B3
29 #define DEMUXER_PIC_HEAD 0x00000101
30 #define SEEK_THRESHOLD 150000 // About 1.5 seconds
31
32 // Statics
33 const int Demuxer::FrameRates[9] = { 0, 23, 24, 25, 29, 30, 50, 59, 60 };
34 Demuxer* Demuxer::instance = NULL;
35
36 // PESPacket methods
37 PESPacket::PESPacket()
38 {
39   init(0);
40   data[2] = 0x01;
41 }
42
43 void PESPacket::init(UCHAR type, UCHAR sub)
44 {
45   data.resize(6);
46   length = 0; 
47   size = 6;
48   data[3] = type;
49   packetType = type;
50   substream = sub;
51   seq_header = 1; // Unknown seq_header status
52 }
53
54 void PESPacket::truncate()
55 {
56   init(packetType,substream);
57 }
58
59 int PESPacket::write(const UCHAR *buf, int len)
60 {
61   if (length + len > 0xFFFA) return 0;
62   data.insert(data.end(), buf, buf+len);
63   length += len;
64   size += len;
65   data[4] = (length >> 8);
66   data[5] = (length & 0xFF);
67   // We have added data - reset seq_header indicator if necessary
68   if (seq_header == 0) seq_header = 1; // Reset to 'unknown'
69   return 1;
70 }
71
72 ULLONG PESPacket::getPTS() const
73 {
74   if ( ( (packetType >= Demuxer::PESTYPE_AUD0 &&
75           packetType <= Demuxer::PESTYPE_AUDMAX)
76          ||
77          (packetType >= Demuxer::PESTYPE_VID0 &&
78           packetType <= Demuxer::PESTYPE_VIDMAX)
79    ||
80           packetType == Demuxer::PESTYPE_PRIVATE_1
81        )
82        && size >= 14 && data[7] & 0x80)
83   {
84     return ( (ULLONG)(data[ 9] & 0x0E) << 29) |
85            ( (ULLONG)(data[10])        << 22 ) |
86            ( (ULLONG)(data[11] & 0xFE) << 14 ) |
87            ( (ULLONG)(data[12])        <<  7 ) |
88            ( (ULLONG)(data[13] & 0xFE) >>  1 );
89   }
90   else return PTS_INVALID;
91 }
92
93 UCHAR PESPacket::operator[] (UINT index) const
94 {
95   if (index >= size)
96     return 0;
97   else
98     return data[index];
99 }
100
101 UINT PESPacket::findPictureHeader() const
102 {
103   if (size < 12) return 0;
104   UINT pattern = ( ((UINT)data[ 8] << 24) |
105                    ((UINT)data[ 9] << 16) |
106                    ((UINT)data[10] <<  8) |
107                     (UINT)data[11]  );
108   UINT pos = 11;
109   while (pattern != DEMUXER_PIC_HEAD)
110   {
111     if (++pos >= size) return 0;
112     pattern = (pattern << 8) | data[pos];
113   }
114   return pos-3;
115 }
116
117 UINT PESPacket::findSeqHeader() const
118 {
119   if (seq_header != 1) return seq_header;
120   if (size < 12) return 0;
121   UINT pattern = ( ((UINT)data[ 8] << 24) |
122                    ((UINT)data[ 9] << 16) |
123                    ((UINT)data[10] <<  8) |
124                     (UINT)data[11]  );
125   UINT pos = 11;
126   while (pattern != DEMUXER_SEQ_HEAD)
127   {
128     if (++pos >= size)
129     {
130       seq_header = 0;
131       return 0;
132     }
133     pattern = (pattern << 8) | data[pos];
134   }
135   seq_header = pos - 3;
136   return seq_header;
137 }
138
139 // Demuxer methods
140 Demuxer::Demuxer()
141 {
142   if (instance) return;
143   instance = this;
144   initted = false;
145   callback = NULL;
146   arcnt = 0;
147   vid_seeking = aud_seeking = false;
148   video_pts = audio_pts = 0;
149   ispre_1_3_19 = false;
150 }
151
152 Demuxer::~Demuxer()
153 {
154   shutdown();
155   instance = NULL;
156 }
157
158 Demuxer* Demuxer::getInstance()
159 {
160   return instance;
161 }
162
163 int Demuxer::init(Callback* tcallback, DrainTarget* audio, DrainTarget* video, ULONG demuxMemoryV, ULONG demuxMemoryA, DVBSubtitles* tsubtitles)
164 {
165   if (!initted)
166   {
167     if ( !videostream.init(video, demuxMemoryV) ||
168          !audiostream.init(audio, demuxMemoryA))
169     {
170       Log::getInstance()->log("Demuxer", Log::CRIT,
171                               "Failed to initialize demuxer");
172       shutdown();
173       return 0;
174     }
175   }
176
177   reset();
178   initted = true;
179   subtitles = tsubtitles;
180   callback = tcallback;
181   return 1;
182 }
183
184 void Demuxer::reset()
185 {
186   Log::getInstance()->log("Demuxer", Log::DEBUG, "Reset called");
187   flush();
188   video_current = audio_current = -1;
189   horizontal_size = vertical_size = 0;
190   aspect_ratio = (enum AspectRatio) 0;
191   frame_rate = bit_rate = 0;
192   ispre_1_3_19 = false;
193
194   for (int i = 0; i <= (PESTYPE_AUDMAX - PESTYPE_AUD0); i++)
195   {
196     avail_mpaudchan[i] = false;
197   }
198   for (int i = 0; i <= (PESTYPE_SUBSTREAM_AC3MAX - PESTYPE_SUBSTREAM_AC30); i++)
199   {
200     avail_ac3audchan[i] = false;
201   }
202 }
203
204 int Demuxer::shutdown()
205 {
206   videostream.shutdown();
207   audiostream.shutdown();
208   initted = false;
209   return 1;
210 }
211
212 void Demuxer::flush()
213 {
214   Log::getInstance()->log("Demuxer", Log::DEBUG, "Flush called");
215
216   videostream.flush();
217   audiostream.flush();
218 }
219
220 void Demuxer::flushAudio()
221 {
222   audiostream.flush();
223 }
224
225 void Demuxer::seek()
226 {
227   vid_seeking = aud_seeking = true;
228   video_pts = audio_pts = 0;
229 }
230
231 void Demuxer::setAudioStream(int id)
232 {
233   audio_current = id;
234 }
235
236 void Demuxer::setVideoStream(int id)
237 {
238   video_current = id;
239 }
240
241 void Demuxer::setAspectRatio(enum AspectRatio ar)
242 {
243   if (aspect_ratio != ar)
244   {
245     Log::getInstance()->log("Demux", Log::DEBUG,
246                             "Aspect ratio difference signalled");
247     if (++arcnt > 3) // avoid changing aspect ratio if glitch in signal
248     {
249       arcnt = 0;
250       aspect_ratio = ar;
251       if (callback) callback->call(this);
252     }
253   }
254   else
255     arcnt = 0;
256 }
257
258 bool Demuxer::writeAudio()
259 {
260   return audiostream.drain();
261 }
262
263 bool Demuxer::writeVideo()
264 {
265   return videostream.drain();
266 }
267
268 bool Demuxer::submitPacket(PESPacket& packet)
269 {
270   UINT sent = 0;
271   UCHAR packet_type = packet.getPacketType();
272   const std::vector<UCHAR>& packetdata = packet.getData();
273
274   if (packet_type >= PESTYPE_VID0 && packet_type <= PESTYPE_VIDMAX)
275   {
276     if (video_current == -1) video_current = packet_type;
277     if (video_current == packet_type && !vid_seeking)
278       sent = videostream.put(&packetdata[0], packet.getSize(), MPTYPE_VIDEO);
279     else
280       sent = packet.getSize();
281   }
282   else if (packet_type >= PESTYPE_AUD0 && packet_type <= PESTYPE_AUDMAX)
283   {
284     if (audio_current == -1) audio_current = packet_type;
285     avail_mpaudchan[packet_type - PESTYPE_AUD0] = true;
286     if (audio_current == packet_type && !aud_seeking)
287       sent = audiostream.put(&packetdata[0], packet.getSize(), MPTYPE_MPEG_AUDIO);
288     else
289       sent = packet.getSize();
290   }
291   else if (packet_type == PESTYPE_PRIVATE_1 &&
292            packet.getSubstream() >= PESTYPE_SUBSTREAM_AC30 &&
293            packet.getSubstream() <= PESTYPE_SUBSTREAM_AC3MAX)
294   {
295     avail_ac3audchan[packet.getSubstream() - PESTYPE_SUBSTREAM_AC30] = true;
296     if (packet.getSubstream() == audio_current)
297     {
298       sent = audiostream.put(&packetdata[0], packet.getSize(), (ispre_1_3_19)? MPTYPE_AC3_PRE13 : MPTYPE_AC3);
299     }
300     else
301     {
302       sent = packet.getSize();
303     }
304   }
305   else if (packet_type == PESTYPE_PRIVATE_1 &&
306            packet.getSubstream() == 0x20)
307   {
308     if (subtitles) subtitles->put(packet);
309     sent = packet.getSize();
310   }
311   else
312   {
313     sent = packet.getSize();
314   }
315
316   if (sent < packet.getSize()) // Stream is full.
317     return false;
318   else
319     return true;
320 }
321
322 void Demuxer::parsePacketDetails(PESPacket& packet)
323 {
324   if (packet.getPacketType() >= PESTYPE_AUD0 &&
325       packet.getPacketType() <= PESTYPE_AUDMAX)
326   {
327     // Extract audio PTS if it exists
328     if (packet.hasPTS())
329     {
330       audio_pts = packet.getPTS();
331       // We continue to seek on the audio if the video PTS that we
332       // are trying to match is ahead of the audio PTS by at most
333       // SEEK_THRESHOLD. We consider the possibility of PTS wrap.
334       if (aud_seeking && !vid_seeking &&
335           !( (video_pts_seek > audio_pts &&
336               video_pts_seek - audio_pts < SEEK_THRESHOLD)
337               ||
338              (video_pts_seek < audio_pts &&
339               video_pts_seek + (1LL<<33) - audio_pts < SEEK_THRESHOLD) ))
340       {
341         aud_seeking = 0;
342         Log::getInstance()->log("Demuxer", Log::DEBUG,
343             "Leaving  audio sync: Audio PTS = %llu", audio_pts);
344       }
345     }
346   }
347   else if (packet.getPacketType() == PESTYPE_PRIVATE_1) // Private stream
348   {
349     //Inspired by vdr's device.c
350     int payload_begin = packet[8]+9;
351     unsigned char substream_id = packet[payload_begin];
352     unsigned char substream_type = substream_id & 0xF0;
353     unsigned char substream_index = substream_id & 0x1F;
354 pre_1_3_19_Recording: //This is for old recordings stuff and live TV
355     if (ispre_1_3_19)
356     {
357       substream_id = PESTYPE_PRIVATE_1;
358       substream_type = 0x80;
359       substream_index = 0;
360     }
361     switch (substream_type)
362     {
363       case 0x20://SPU
364       case 0x30://SPU
365         packet.setSubstream(substream_id);
366         break;
367       case 0xA0: //LPCM //not supported yet, is there any LPCM transmissio out there?
368         break;
369       case 0x80: //ac3, currently only one ac3 track per recording supported
370         packet.setSubstream(substream_type+substream_index);
371
372         // Extract audio PTS if it exists
373         if (packet.hasPTS())
374         {
375           audio_pts = packet.getPTS();
376           // We continue to seek on the audio if the video PTS that we
377           // are trying to match is ahead of the audio PTS by at most
378           // SEEK_THRESHOLD. We consider the possibility of PTS wrap.
379           if (aud_seeking && !vid_seeking &&
380               !( (video_pts_seek > audio_pts &&
381                   video_pts_seek - audio_pts < SEEK_THRESHOLD)
382               ||
383               (video_pts_seek < audio_pts &&
384                     video_pts_seek + (1LL<<33) - audio_pts < SEEK_THRESHOLD) ))
385           {
386             aud_seeking = 0;
387             Log::getInstance()->log("Demuxer", Log::DEBUG, "Leaving  audio sync: Audio PTS = %llu", audio_pts);
388           }
389         }
390         break;
391       default:
392         if (!ispre_1_3_19)
393         {
394           ispre_1_3_19=true; //switching to compat mode and live tv mode
395           goto pre_1_3_19_Recording;
396         }
397         else
398         {
399           packet.setSubstream(0);
400         }
401         break;
402     }
403   }
404   else if (packet.getPacketType() >= PESTYPE_VID0 &&
405            packet.getPacketType() <= PESTYPE_VIDMAX)
406   {
407     // Extract video PTS if it exists
408     if (packet.hasPTS()) video_pts = packet.getPTS();
409
410     // If there is a sequence header, extract information
411     UINT pos = packet.findSeqHeader();
412     if (pos > 1)
413     {
414       pos += 4;
415       if (pos+6 >= packet.getSize()) return;
416       horizontal_size = ((int)packet[pos] << 4) | ((int)packet[pos+1] >> 4);
417       vertical_size = (((int)packet[pos+1] & 0xf) << 8) | (int)packet[pos+2];
418       setAspectRatio((enum AspectRatio)(packet[pos+3] >> 4));
419       frame_rate = packet[pos+3] & 0x0f;
420       if (frame_rate >= 1 && frame_rate <= 8)
421         frame_rate = FrameRates[frame_rate];
422       else
423         frame_rate = 0;
424       bit_rate = ((int)packet[pos+4] << 10) |
425                  ((int)packet[pos+5] << 2) |
426                  ((int)packet[pos+6] >> 6);
427       if (vid_seeking)
428       {
429         vid_seeking = 0;
430         video_pts_seek = video_pts;
431         Log::getInstance()->log("Demuxer", Log::DEBUG,
432             "Entering audio sync: Video PTS = %llu", video_pts);
433         Log::getInstance()->log("Demuxer", Log::DEBUG,
434             "Entering audio sync: Audio PTS = %llu", audio_pts);
435       }
436       return;
437     }
438   }
439 }
440
441 UINT Demuxer::stripAudio(UCHAR* buf, UINT len)
442 {
443   UINT read_pos = 0, write_pos = 0;
444   UINT pattern, packet_length;
445   if (len < 4) return 0;
446   pattern = (buf[0] << 16) | (buf[1] << 8) | (buf[2]);
447   while (read_pos + 7 <= len)
448   {
449     pattern = ((pattern & 0xFFFFFF) << 8) | buf[read_pos+3];
450     if (pattern < (0x100|PESTYPE_VID0) || pattern > (0x100|PESTYPE_VIDMAX))
451       read_pos++;
452     else
453     {
454       packet_length = ((buf[read_pos+4] << 8) | (buf[read_pos+5])) + 6;
455       if (read_pos + packet_length > len)
456         read_pos = len;
457       else
458       {
459         if (read_pos != write_pos)
460           memmove(buf+write_pos, buf+read_pos, packet_length);
461         read_pos += packet_length;
462         write_pos += packet_length;
463         pattern = (buf[read_pos] << 16) | (buf[read_pos+1] << 8)
464                                         | (buf[read_pos+2]);
465       }
466     }
467   }
468   return write_pos;
469 }
470
471 bool Demuxer::scanForVideo(UCHAR* buf, UINT len)
472 {
473   UINT pos = 3;
474   UINT pattern;
475   if (len < 4) return false;
476   pattern = (buf[0] << 16) | (buf[1] << 8) | (buf[2]);
477   while (pos < len)
478   {
479     pattern = ((pattern & 0xFFFFFF) << 8) | buf[pos++];
480     if (pattern >= (0x100|PESTYPE_VID0) && pattern <= (0x100|PESTYPE_VIDMAX))
481       return true;
482   }
483   return false;
484 }
485
486 bool* Demuxer::getmpAudioChannels()
487 {
488   return avail_mpaudchan;
489 }
490
491 bool* Demuxer::getac3AudioChannels()
492 {
493   return avail_ac3audchan;
494 }
495
496 int Demuxer::getselAudioChannel()
497 {
498   return audio_current;
499 }
500
501 void Demuxer::setAudioChannel(int aud_channel)
502 {
503   audio_current = aud_channel;
504 }