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