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