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
21 #include "demuxervdr.h"
26 #define __LITTLE_ENDIAN 1234
27 #define __BIG_ENDIAN 4321
28 #define __BYTE_ORDER __LITTLE_ENDIAN
31 #if __BYTE_ORDER == __BIG_ENDIAN
32 #define DEMUXER_SEQ_HEAD 0x000001B3
34 #define DEMUXER_SEQ_HEAD 0xB3010000
37 #define PTS_JUMP_MARGIN 10000
38 #define PTS_ERASE_MARGIN 900000 // Erase PTS record if we get within 10 seconds
39 #define PTS_ALLOWANCE 90000
40 //#define PTS_UPDATE_FRAMES 2048
41 //#define PTS_EXPIRE_FRAMES 2500
43 // TODO: PTS class to handle wrapping arithmetic & comparisons?
44 static ULLONG PTSDistance(ULLONG pts1, ULLONG pts2)
46 // Assume pts1, pts2 < 2^33; calculate shortest distance between
47 ULLONG ret = (pts1 > pts2) ? pts1 - pts2 : pts2 - pts1;
48 if (ret > (1LL<<32)) ret = (1LL<<33) - ret;
52 static ULLONG PTSDifference(ULLONG pts1, ULLONG pts2)
54 // Assume pts1, pts2 < 2^33; calculate pts1 - pts2
58 return (1LL<<33) + pts1 - pts2;
61 DemuxerVDR::DemuxerVDR()
63 frameCounting = false;
66 void DemuxerVDR::reset()
68 frameCounting = false;
73 void DemuxerVDR::flush()
80 int DemuxerVDR::scan(UCHAR *buf, int len)
82 // Temporarily, just look for the lowest audio stream and return it
83 UCHAR HiByte = PESTYPE_AUDMAX;
88 UINT pattern = *(UINT*)buf;
91 #if __BYTE_ORDER == __BIG_ENDIAN
92 if (pattern < (UINT)(0x100 | PESTYPE_AUD0) ||
93 pattern > (UINT)(0x100 | HiByte)) continue;
94 HiByte = pattern & 0xFF;
96 if ((pattern & 0xFFFFFF) != 0x010000 ||
97 pattern < ((UINT)PESTYPE_AUD0 << 24) ||
98 pattern > ((UINT)HiByte << 24)) continue;
99 HiByte = pattern >> 24;
102 if (HiByte == PESTYPE_AUD0) break;
107 int DemuxerVDR::findVideoPTS(UCHAR* buf, int len, ULLONG* dest)
111 UINT pattern = *(UINT*)buf;
113 #if __BYTE_ORDER == __BIG_ENDIAN
114 if (pattern < (0x100 | PESTYPE_VID0) ||
115 pattern > (0x100 | PESTYPE_VIDMAX)) continue;
117 if ((pattern & 0xFFFFFF) != 0x010000 ||
118 pattern < ((UINT)PESTYPE_VID0 << 24) ||
119 pattern > ((UINT)PESTYPE_VIDMAX << 24)) continue;
121 if ((buf[5] & 0xC0) != 0x80) continue;
123 UINT packetlength = ((UINT)buf[3] << 8) | buf[4];
125 if ( buf[6] & 0x80 ) // PTS_DTS_flags indicate that PTS is present
127 if ( (buf[8] & 0x01) != 0x01 ||
128 (buf[10] & 0x01) != 0x01 ||
129 (buf[12] & 0x01) != 0x01) continue;
131 *dest = ( (ULLONG)(buf[8] & 0x0E) << 29 ) |
132 ( (ULLONG)(buf[9]) << 22 ) |
133 ( (ULLONG)(buf[10] & 0xFE) << 14 ) |
134 ( (ULLONG)(buf[11]) << 7 ) |
135 ( (ULLONG)(buf[12] & 0xFE) >> 1 );
140 buf += packetlength; len -= packetlength;
146 void DemuxerVDR::setFrameNum(ULONG frame)
148 frameCounting = true;
150 Log::getInstance()->log("Demuxer", Log::DEBUG, "setFrameNum %d", frame);
154 int DemuxerVDR::put(UCHAR* buf, int len)
156 int DemuxerVDR::put(UCHAR* buf, int len, ULLONG cur_pos)
159 int ret = 0; // return number of bytes consumed
162 ULLONG current_position = cur_pos;
168 if (packet.submit() == 0) // Still full!
170 if (packet.submit(current_position) == 0) // Still full!
177 if (state > 0) // We are half way through a PES packet.
179 if (len >= state) // The remainder of the packet is available.
181 packet.write(buf, state);
182 buf += state; len -= state; ret += state;
185 if (packet.submit() == 0) // Stream is full
187 if (packet.submit(current_position) == 0) // Stream is full
194 else // Write what we have, then exit.
196 packet.write(buf, len);
208 if (*buf == 0x00) state--; else state = 0;
212 if (*buf == 0x01) state--; else if (*buf != 0x00) state = 0;
216 if ((*buf >= PESTYPE_VID0 && *buf <= PESTYPE_VIDMAX) ||
217 (*buf >= PESTYPE_AUD0 && *buf <= PESTYPE_AUDMAX) ||
218 (*buf == PESTYPE_PRIVATE_1))
223 else if (*buf == 0x00)
230 packetLength = ((UINT)*buf) << 8;
235 packetLength += *buf;
245 if (state == -6) // Packet header complete
247 if (len >= packetLength) // The entire packet is available.
249 packet.write(buf, packetLength);
250 buf += packetLength; len -= packetLength; ret += packetLength;
252 current_position+=(ULLONG)packetLength;
256 if (packet.submit() == 0) // Stream is full
258 if (packet.submit(current_position) == 0) // Stream is full
265 else // Write what we have.
267 packet.write(buf, len);
268 state = packetLength - len;
277 ULONG DemuxerVDR::getFrameNumFromPTS(ULLONG pts)
279 ULLONG difference = (1LL<<33);
281 int total = 0, actual = 0;
282 pthread_mutex_lock(&pts_map_mutex);
283 PTSMap::iterator iter = pts_map.begin();
284 while (iter != pts_map.end())
287 if (PTSDifference(iter->pts, pts) < PTS_ALLOWANCE)
290 ref_frame = iter->frame;
294 ULLONG newdiff = PTSDifference(pts, iter->pts);
295 if (newdiff < difference)
297 difference = newdiff;
298 ref_frame = iter->frame;
303 if (total > 1 && actual == 1) // We are using the most recent PTS ref.
304 { // Delete the rest.
305 iter = pts_map.begin(); iter++;
306 pts_map.erase(iter, pts_map.end());
308 pthread_mutex_unlock(&pts_map_mutex);
309 if (total > 1 && actual == 1)
310 Log::getInstance()->log("Demuxer", Log::DEBUG, "DELETED REFERENCES");
312 Log::getInstance()->log("Demuxer", Log::DEBUG, "STILL USING OLD REF");
314 //ULONG ret = ref_frame + difference * Video::getInstance()->getFPS() / 90000;
315 //Log::getInstance()->log("Demuxer", Log::DEBUG, "%llu: FOUND %d from %d, diff %llu", pts, ret, ref_frame, difference);
317 if (difference == (1LL<<33))
318 return 0; // We cannot make sense of the pts
320 return ref_frame + difference * Video::getInstance()->getFPS() / 90000;
323 void DemuxerVDR::PESPacketVDR::parseDetails()
325 // TODO: Currently, we naïvely assume that a packet contains a new frame
326 // if and only if it contains a pts, and that no packet contains more
327 // than one new frame
329 DemuxerVDR* dx = (DemuxerVDR*)(DemuxerVDR::getInstance());
330 PESPacket::parseDetails();
331 if (dx->frameCounting && pts != PTS_INVALID &&
332 packetType >= PESTYPE_VID0 && packetType <= PESTYPE_VIDMAX)
334 ULONG frame_num = (dx->frameNumber)++;
338 pthread_mutex_lock(&(dx->pts_map_mutex));
339 if (dx->pts_map.empty())
342 me.frame = frame_num;
343 pthread_mutex_unlock(&(dx->pts_map_mutex));
344 Log::getInstance()->log("Demuxer", Log::DEBUG, "+* PTS INIT *+ %llu %u", me.pts, me.frame);
345 pthread_mutex_lock(&(dx->pts_map_mutex));
346 dx->pts_map.push_front(me);
348 me = dx->pts_map.front();
349 pthread_mutex_unlock(&(dx->pts_map_mutex));
351 UINT fps = Video::getInstance()->getFPS();
352 ULLONG pts_expected = me.pts + 90000*(frame_num - me.frame) / fps;
353 while (pts_expected > (1LL<<33)) pts_expected -= (1LL<<33);
355 if (PTSDistance(pts_expected, pts) > PTS_JUMP_MARGIN) // PTS jump!
357 Log::getInstance()->log("Demuxer", Log::DEBUG, "+* PTS JUMP *+ %llu %u", pts, frame_num);
359 me.frame = frame_num;
360 pthread_mutex_lock(&(dx->pts_map_mutex));
361 dx->pts_map.push_front(me);
362 pthread_mutex_unlock(&(dx->pts_map_mutex));