2 Copyright 2005-2007 Mark Calderbank
3 Copyright 2007 Marten Richter (AC3 support)
5 This file is part of VOMP.
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.
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.
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
26 #define __LITTLE_ENDIAN 1234
27 #define __BIG_ENDIAN 4321
28 #define __BYTE_ORDER __LITTLE_ENDIAN
31 #define DEMUXER_SEQ_HEAD 0x000001B3
32 #define DEMUXER_PIC_HEAD 0x00000101
34 #define SEEK_THRESHOLD 150000 // About 1.5 seconds
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;
42 PESPacket::PESPacket()
50 void PESPacket::init(UCHAR type)
54 data[4] = data[5] = 0;
57 seq_header = 1; // Unknown seq_header status
60 void PESPacket::truncate()
65 int PESPacket::write(UCHAR *buf, int len)
67 if (length + len > 0xFFFA) return 0;
68 memcpy(data+length+6, buf, 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)
80 (packetType >= Demuxer::PESTYPE_VID0 &&
81 packetType <= Demuxer::PESTYPE_VIDMAX)
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 );
94 UCHAR PESPacket::operator[] (UINT index)
102 UINT PESPacket::findPictureHeader()
104 if (size < 12) return 0;
105 UINT pattern = ( ((UINT)data[ 8] << 24) |
106 ((UINT)data[ 9] << 16) |
107 ((UINT)data[10] << 8) |
110 while (pattern != DEMUXER_PIC_HEAD)
112 if (++pos >= size) return 0;
113 pattern = (pattern << 8) | data[pos];
118 UINT PESPacket::findSeqHeader()
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) |
127 while (pattern != DEMUXER_SEQ_HEAD)
134 pattern = (pattern << 8) | data[pos];
136 seq_header = pos - 3;
143 if (instance) return;
148 vid_seeking = aud_seeking = false;
149 video_pts = audio_pts = 0;
150 ispre_1_3_19 = false;
159 Demuxer* Demuxer::getInstance()
164 int Demuxer::init(Callback* tcallback, DrainTarget* audio, DrainTarget* video, ULONG demuxMemoryV, ULONG demuxMemoryA)
168 if ( !videostream.init(video, demuxMemoryV) ||
169 !audiostream.init(audio, demuxMemoryA))
171 Log::getInstance()->log("Demuxer", Log::CRIT,
172 "Failed to initialize demuxer");
180 callback = tcallback;
184 void Demuxer::reset()
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;
193 for (int i = 0; i <= (PESTYPE_AUDMAX - PESTYPE_AUD0); i++)
195 avail_mpaudchan[i] = false;
197 for (int i = 0; i <= (PESTYPE_SUBSTREAM_AC3MAX - PESTYPE_SUBSTREAM_AC30); i++)
199 avail_ac3audchan[i] = false;
203 int Demuxer::shutdown()
205 videostream.shutdown();
206 audiostream.shutdown();
211 void Demuxer::flush()
217 void Demuxer::flushAudio()
224 vid_seeking = aud_seeking = true;
225 video_pts = audio_pts = 0;
228 void Demuxer::setAudioStream(int id)
233 void Demuxer::setVideoStream(int id)
238 void Demuxer::setAspectRatio(enum AspectRatio ar)
240 if (aspect_ratio != ar)
242 Log::getInstance()->log("Demux", Log::DEBUG,
243 "Aspect ratio difference signalled");
244 if (++arcnt > 3) // avoid changing aspect ratio if glitch in signal
248 if (callback) callback->call(this);
255 bool Demuxer::writeAudio()
257 return audiostream.drain();
260 bool Demuxer::writeVideo()
262 return videostream.drain();
265 bool Demuxer::submitPacket(PESPacket& packet)
268 UCHAR packet_type = packet.getPacketType();
270 if (packet_type >= PESTYPE_VID0 && packet_type <= PESTYPE_VIDMAX)
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);
276 sent = packet.getSize();
278 else if (packet_type >= PESTYPE_AUD0 && packet_type <= PESTYPE_AUDMAX)
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);
285 sent = packet.getSize();
287 else if (packet_type == PESTYPE_PRIVATE_1)
289 if (packet.getSubstream() >= PESTYPE_SUBSTREAM_AC30 &&
290 packet.getSubstream() <= PESTYPE_SUBSTREAM_AC3MAX)
292 avail_ac3audchan[packet.getSubstream() - PESTYPE_SUBSTREAM_AC30] = true;
293 if (packet.getSubstream() == audio_current)
295 sent = audiostream.put(packet.getData(), packet.getSize(), (ispre_1_3_19)? MPTYPE_AC3_PRE13 : MPTYPE_AC3);
299 sent = packet.getSize();
305 sent = packet.getSize();
308 if (sent < packet.getSize()) // Stream is full.
314 void Demuxer::parsePacketDetails(PESPacket& packet)
316 if (packet.getPacketType() >= PESTYPE_AUD0 &&
317 packet.getPacketType() <= PESTYPE_AUDMAX)
319 // Extract audio PTS if it exists
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)
330 (video_pts_seek < audio_pts &&
331 video_pts_seek + (1LL<<33) - audio_pts < SEEK_THRESHOLD) ))
334 Log::getInstance()->log("Demuxer", Log::DEBUG,
335 "Leaving audio sync: Audio PTS = %llu", audio_pts);
339 else if (packet.getPacketType() == PESTYPE_PRIVATE_1) // Private stream
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
349 substream_id = PESTYPE_PRIVATE_1;
350 substream_type = 0x80;
353 switch (substream_type)
358 case 0xA0: //LPCM //not supported yet, is there any LPCM transmissio out there?
360 case 0x80: //ac3, currently only one ac3 track per recording supported
361 packet.setSubstream(substream_type+substream_index);
363 // Extract audio PTS if it exists
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)
374 (video_pts_seek < audio_pts &&
375 video_pts_seek + (1LL<<33) - audio_pts < SEEK_THRESHOLD) ))
378 Log::getInstance()->log("Demuxer", Log::DEBUG, "Leaving audio sync: Audio PTS = %llu", audio_pts);
385 ispre_1_3_19=true; //switching to compat mode
386 goto pre_1_3_19_Recording;
390 packet.setSubstream(0);
395 else if (packet.getPacketType() >= PESTYPE_VID0 &&
396 packet.getPacketType() <= PESTYPE_VIDMAX)
398 // Extract video PTS if it exists
399 if (packet.hasPTS()) video_pts = packet.getPTS();
401 // If there is a sequence header, extract information
402 UINT pos = packet.findSeqHeader();
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];
415 bit_rate = ((int)packet[pos+4] << 10) |
416 ((int)packet[pos+5] << 2) |
417 ((int)packet[pos+6] >> 6);
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);
432 UINT Demuxer::stripAudio(UCHAR* buf, UINT len)
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)
440 pattern = ((pattern & 0xFFFFFF) << 8) | buf[read_pos+3];
441 if (pattern < (0x100|PESTYPE_VID0) || pattern > (0x100|PESTYPE_VIDMAX))
445 packet_length = ((buf[read_pos+4] << 8) | (buf[read_pos+5])) + 6;
446 if (read_pos + packet_length > len)
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)
462 bool Demuxer::scanForVideo(UCHAR* buf, UINT len)
466 if (len < 4) return false;
467 pattern = (buf[0] << 16) | (buf[1] << 8) | (buf[2]);
470 pattern = ((pattern & 0xFFFFFF) << 8) | buf[pos++];
471 if (pattern >= (0x100|PESTYPE_VID0) && pattern <= (0x100|PESTYPE_VIDMAX))
477 bool* Demuxer::getmpAudioChannels()
479 return avail_mpaudchan;
482 bool* Demuxer::getac3AudioChannels()
484 return avail_ac3audchan;
487 int Demuxer::getselAudioChannel()
489 return audio_current;
492 void Demuxer::setAudioChannel(int aud_channel)
494 audio_current = aud_channel;