2 Copyright 2005-2006 Mark Calderbank
4 This file is part of VOMP.
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.
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.
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
25 #define __LITTLE_ENDIAN 1234
26 #define __BIG_ENDIAN 4321
27 #define __BYTE_ORDER __LITTLE_ENDIAN
30 #if __BYTE_ORDER == __BIG_ENDIAN
31 #define DEMUXER_SEQ_HEAD 0x000001B3
33 #define DEMUXER_SEQ_HEAD 0xB3010000
36 #define DEMUXER_PIC_HEAD 0x00000101
38 #define SEEK_THRESHOLD 150000 // About 1.5 seconds
40 const int Demuxer::FrameRates[9] = { 0, 23, 24, 25, 29, 30, 50, 59, 60 };
41 const ULLONG Demuxer::PESPacket::PTS_INVALID = (1LL << 33);
43 Demuxer* Demuxer::instance = NULL;
52 vid_seeking = aud_seeking = false;
53 video_pts = audio_pts = 0;
63 Demuxer* Demuxer::getInstance()
68 int Demuxer::init(Callback* tcallback, DrainTarget* audio, DrainTarget* video, ULONG demuxMemoryV, ULONG demuxMemoryA)
72 if ( !videostream.init(video, demuxMemoryV) ||
73 !audiostream.init(audio, demuxMemoryA))
75 Log::getInstance()->log("Demuxer", Log::CRIT,
76 "Failed to initialize demuxer");
91 video_current = audio_current = -1;
92 horizontal_size = vertical_size = 0;
93 aspect_ratio = (enum AspectRatio) 0;
94 frame_rate = bit_rate = 0;
97 for (int i = 0; i <= (PESTYPE_AUDMAX - PESTYPE_AUD0); i++)
99 avail_mpaudchan[i] = false;
101 for (int i = 0; i <= (PESTYPE_SUBSTREAM_AC3MAX - PESTYPE_SUBSTREAM_AC30); i++)
103 avail_ac3audchan[i] = false;
107 int Demuxer::shutdown()
109 videostream.shutdown();
110 audiostream.shutdown();
115 void Demuxer::flush()
121 void Demuxer::flushAudio()
128 vid_seeking = aud_seeking = true;
129 video_pts = audio_pts = 0;
132 void Demuxer::setAudioStream(int id)
137 void Demuxer::setVideoStream(int id)
142 void Demuxer::setAspectRatio(enum AspectRatio ar)
144 if (aspect_ratio != ar)
146 Log::getInstance()->log("Demux", Log::DEBUG,
147 "Aspect ratio difference signalled");
148 if (++arcnt > 3) // avoid changing aspect ratio if glitch in signal
152 if (callback) callback->call(this);
159 bool Demuxer::writeAudio()
161 return audiostream.drain();
164 bool Demuxer::writeVideo()
166 return videostream.drain();
169 Demuxer::PESPacket::PESPacket()
177 void Demuxer::PESPacket::init(UCHAR type)
179 length = submitted = 0;
180 size = 6; closed = false;
182 data[4] = data[5] = 0;
188 void Demuxer::PESPacket::truncate()
193 int Demuxer::PESPacket::write(UCHAR *buf, int len)
195 if (closed) return 0;
196 if (length + len > 0xFFFA) return 0;
197 memcpy(data+length+6, buf, len);
200 data[4] = (length >> 8);
201 data[5] = (length & 0xFF);
205 int Demuxer::PESPacket::submit()
207 if (submitted >= size) return 0;
208 if (!closed) parseDetails();
211 Demuxer* dx = Demuxer::getInstance();
213 if (packetType >= PESTYPE_VID0 && packetType <= PESTYPE_VIDMAX)
215 if (dx->video_current == -1) dx->video_current = packetType;
216 if (dx->video_current == packetType && !dx->vid_seeking)
217 sent = dx->videostream.put(data+submitted, size-submitted, MPTYPE_VIDEO);
219 sent = size-submitted;
221 else if (packetType >= PESTYPE_AUD0 && packetType <= PESTYPE_AUDMAX)
223 if (dx->audio_current == -1) dx->audio_current = packetType;
225 dx->avail_mpaudchan[packetType-PESTYPE_AUD0]=true;
227 //Log::getInstance()->log("PESPacket", Log::DEBUG, "%i", dx->audio_current);
228 if (dx->audio_current == packetType && !dx->aud_seeking)
229 sent = dx->audiostream.put(data+submitted, size-submitted, MPTYPE_MPEG_AUDIO);
231 sent = size-submitted;
233 else if (packetType == PESTYPE_PRIVATE_1)
235 if (substream >= PESTYPE_SUBSTREAM_AC30 && substream <= PESTYPE_SUBSTREAM_AC3MAX)
237 dx->avail_ac3audchan[substream-PESTYPE_SUBSTREAM_AC30]=true;
238 if (substream == dx->audio_current)
240 sent = dx->audiostream.put(data+submitted,size-submitted,(dx->ispre_1_3_19)?MPTYPE_AC3_PRE13:MPTYPE_AC3);
244 sent = size-submitted;
250 sent = size-submitted;
254 if (submitted < size) // Stream is full.
260 void Demuxer::PESPacket::parseDetails()
262 Demuxer* dx = Demuxer::getInstance();
263 if (packetType >= PESTYPE_AUD0 && packetType <= PESTYPE_AUDMAX)
265 // Extract audio PTS if it exists
266 if ( size >= 14 && (data[7] & 0x80) ) // PTS_DTS_flags indicate PTS
268 dx->audio_pts = pts = ( (ULLONG)(data[9] & 0x0E) << 29 ) |
269 ( (ULLONG)(data[10]) << 22 ) |
270 ( (ULLONG)(data[11] & 0xFE) << 14 ) |
271 ( (ULLONG)(data[12]) << 7 ) |
272 ( (ULLONG)(data[13] & 0xFE) >> 1 );
274 // We continue to seek on the audio if the video PTS that we
275 // are trying to match is ahead of the audio PTS by at most
276 // SEEK_THRESHOLD. We consider the possibility of PTS wrap.
277 if (dx->aud_seeking && !dx->vid_seeking &&
278 !( (dx->video_pts_seek > dx->audio_pts &&
279 dx->video_pts_seek - dx->audio_pts < SEEK_THRESHOLD)
281 (dx->video_pts_seek < dx->audio_pts &&
282 dx->video_pts_seek + (1LL<<33) -
283 dx->audio_pts < SEEK_THRESHOLD) ))
286 Log::getInstance()->log("Demuxer", Log::DEBUG,
287 "Leaving audio sync: Audio PTS = %llu", dx->audio_pts);
291 else if (packetType == PESTYPE_PRIVATE_1) //Private Stream
293 //Inspired by vdr's device.c
294 int payload_begin = data[8]+9;
295 unsigned char substream_id = data[payload_begin];
296 unsigned char substream_type = substream_id & 0xF0;
297 unsigned char substream_index = substream_id & 0x1F;
298 pre_1_3_19_Recording: //This is for old recordings stuff
299 if (dx->ispre_1_3_19)
301 substream_id = PESTYPE_PRIVATE_1;
302 substream_type = 0x80;
305 switch (substream_type)
310 case 0xA0: //LPCM //not supported yet, is there any LPCM transmissio out there?
312 case 0x80: //ac3, currently only one ac3 track per recording supported
313 substream=substream_type+substream_index;
315 // Extract audio PTS if it exists
316 if ( size >= 14 && (data[7] & 0x80) ) // PTS_DTS_flags indicate PTS
318 dx->audio_pts = pts = ( (ULLONG)(data[9] & 0x0E) << 29 ) |
319 ( (ULLONG)(data[10]) << 22 ) |
320 ( (ULLONG)(data[11] & 0xFE) << 14 ) |
321 ( (ULLONG)(data[12]) << 7 ) |
322 ( (ULLONG)(data[13] & 0xFE) >> 1 );
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 (dx->aud_seeking && !dx->vid_seeking &&
327 !( (dx->video_pts_seek > dx->audio_pts &&
328 dx->video_pts_seek - dx->audio_pts < SEEK_THRESHOLD)
330 (dx->video_pts_seek < dx->audio_pts &&
331 dx->video_pts_seek + (1LL<<33) -
332 dx->audio_pts < SEEK_THRESHOLD) ))
335 Log::getInstance()->log("Demuxer", Log::DEBUG, "Leaving audio sync: Audio PTS = %llu", dx->audio_pts);
340 if (!dx->ispre_1_3_19)
342 dx->ispre_1_3_19=true; //switching to compat mode
343 goto pre_1_3_19_Recording;
352 else if (packetType >= PESTYPE_VID0 && packetType <= PESTYPE_VIDMAX)
354 // Extract video PTS if it exists
355 if ( size >= 14 && (data[7] & 0x80) ) // PTS_DTS_flags indicate PTS
357 dx->video_pts = pts = ( (ULLONG)(data[9] & 0x0E) << 29 ) |
358 ( (ULLONG)(data[10]) << 22 ) |
359 ( (ULLONG)(data[11] & 0xFE) << 14 ) |
360 ( (ULLONG)(data[12]) << 7 ) |
361 ( (ULLONG)(data[13] & 0xFE) >> 1 );
364 // Now, scan for a sequence header and extract information
365 UINT pos = 9; // Start searching from byte 9
366 while (pos < size - 5)
368 UINT pattern = *(UINT*)(data+pos);
369 if (pattern == DEMUXER_SEQ_HEAD)
373 if (pos+6 >= size) return;
374 dx->horizontal_size = ((int)data[pos] << 4) | ((int)data[pos+1] >> 4);
375 dx->vertical_size = (((int)data[pos+1] & 0xf) << 8) | (int)data[pos+2];
376 dx->setAspectRatio((enum AspectRatio)(data[pos+3] >> 4));
377 dx->frame_rate = data[pos+3] & 0x0f;
378 if (dx->frame_rate >= 1 && dx->frame_rate <= 8)
379 dx->frame_rate = FrameRates[dx->frame_rate];
382 dx->bit_rate = ((int)data[pos+4] << 10) |
383 ((int)data[pos+5] << 2) |
384 ((int)data[pos+6] >> 6);
388 dx->video_pts_seek = dx->video_pts;
389 Log::getInstance()->log("Demuxer", Log::DEBUG,
390 "Entering audio sync: Video PTS = %llu", dx->video_pts);
391 Log::getInstance()->log("Demuxer", Log::DEBUG,
392 "Entering audio sync: Audio PTS = %llu", dx->audio_pts);
401 UINT Demuxer::PESPacket::findPictureHeader()
403 if (size < 12) return 0;
404 UINT pattern = *(UINT*)(data+8);
406 while (pattern != DEMUXER_PIC_HEAD)
408 if (++pos >= size) return 0;
409 pattern = (pattern << 8) | data[pos];
414 UINT Demuxer::stripAudio(UCHAR* buf, UINT len)
416 UINT read_pos = 0, write_pos = 0;
417 UINT pattern, packet_length;
418 if (len < 4) return 0;
419 pattern = (buf[0] << 16) | (buf[1] << 8) | (buf[2]);
420 while (read_pos + 7 <= len)
422 pattern = ((pattern & 0xFFFFFF) << 8) | buf[read_pos+3];
423 if (pattern < (0x100|PESTYPE_VID0) || pattern > (0x100|PESTYPE_VIDMAX))
427 packet_length = ((buf[read_pos+4] << 8) | (buf[read_pos+5])) + 6;
428 if (read_pos + packet_length > len)
432 if (read_pos != write_pos)
433 memmove(buf+write_pos, buf+read_pos, packet_length);
434 read_pos += packet_length;
435 write_pos += packet_length;
436 pattern = (buf[read_pos] << 16) | (buf[read_pos+1] << 8)
444 bool Demuxer::scanForVideo(UCHAR* buf, UINT len)
448 if (len < 4) return false;
449 pattern = (buf[0] << 16) | (buf[1] << 8) | (buf[2]);
452 pattern = ((pattern & 0xFFFFFF) << 8) | buf[pos++];
453 if (pattern >= (0x100|PESTYPE_VID0) && pattern <= (0x100|PESTYPE_VIDMAX))
459 bool* Demuxer::getmpAudioChannels()
461 return avail_mpaudchan;
464 bool* Demuxer::getac3AudioChannels()
466 return avail_ac3audchan;
469 int Demuxer::getselAudioChannel()
471 return audio_current;
474 void Demuxer::setAudioChannel(int aud_channel)
476 audio_current = aud_channel;