2 Copyright 2005-2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include "demuxermedia.h"
30 #define __LITTLE_ENDIAN 1234
31 #define __BIG_ENDIAN 4321
32 #define __BYTE_ORDER __LITTLE_ENDIAN
35 #define PTS_JUMP_MARGIN 10000
36 #define PTS_ALLOWANCE 90000
38 // TODO: PTS class to handle wrapping arithmetic & comparisons?
39 static ULLONG PTSDistance(ULLONG pts1, ULLONG pts2)
41 // Assume pts1, pts2 < 2^33; calculate shortest distance between
42 ULLONG ret = (pts1 > pts2) ? pts1 - pts2 : pts2 - pts1;
43 if (ret > (1LL<<32)) ret = (1LL<<33) - ret;
47 DemuxerMedia::DemuxerMedia()
49 frameCounting = false;
50 packetCounting = false;
53 void DemuxerMedia::reset()
55 frameCounting = false;
56 packetCounting = false;
62 last_horizontal_size=-1;
63 last_vertical_size=-1;
66 void DemuxerMedia::flush()
73 int DemuxerMedia::scan(UCHAR *buf, int len)
76 int astate=0; //hdrbyte
78 while ((len + astate)> 3)
81 case 0: //1st hdr byte
92 case 2: //3rd header byte
99 case 3: //4th header byte
100 if ((*buf <PESTYPE_AUD0 || *buf > PESTYPE_AUDMAX) && *buf != PESTYPE_PRIVATE_1) {
104 if (*buf != PESTYPE_PRIVATE_1) {
121 int DemuxerMedia::findPTS(UCHAR* buf, int len, ULLONG* dest)
128 void DemuxerMedia::setFrameNum(ULONG frame)
130 frameCounting = true;
132 Log::getInstance()->log("Demuxer", Log::DEBUG, "setFrameNum %d", frame);
135 void DemuxerMedia::setPacketNum(ULONG npacket)
137 packetCounting = true;
138 packetNumber = npacket;
139 Log::getInstance()->log("Demuxer", Log::DEBUG, "setPacketNum %d", npacket);
142 int DemuxerMedia::put(UCHAR* buf, int len)
144 int ret = 0; // return number of bytes consumed
147 if (submitPacket(packet) == 0) // Still full!
153 if (state > 0) // We are half way through a PES packet.
155 if (len >= state) // The remainder of the packet is available.
157 packet.write(buf, state);
158 buf += state; len -= state; ret += state;
160 parseVDRPacketDetails();
161 if (submitPacket(packet) == 0) // Stream is full
167 else // Write what we have, then exit.
169 packet.write(buf, len);
181 if (*buf == 0x00) state--; else state = 0;
185 if (*buf == 0x01) state--; else if (*buf != 0x00) state = 0;
189 if ((*buf >= PESTYPE_VID0 && *buf <= PESTYPE_VIDMAX) ||
190 (*buf >= PESTYPE_AUD0 && *buf <= PESTYPE_AUDMAX) ||
191 (*buf == PESTYPE_PRIVATE_1))
196 else if (*buf == 0x00)
203 packetLength = ((UINT)*buf) << 8;
208 packetLength += *buf;
214 if (state == -6) // Packet header complete
216 if (len >= packetLength) // The entire packet is available.
218 packet.write(buf, packetLength);
219 buf += packetLength; len -= packetLength; ret += packetLength;
221 parseVDRPacketDetails();
222 if (submitPacket(packet) == 0) // Stream is full
228 else // Write what we have.
230 packet.write(buf, len);
231 state = packetLength - len;
240 ULONG DemuxerMedia::getPacketNum()
245 void DemuxerMedia::parseVDRPacketDetails()
247 parsePacketDetails(packet);
249 if (packetCounting && packet.getPacketType() >= PESTYPE_AUD0 &&
250 packet.getPacketType() <= PESTYPE_AUDMAX)
255 if (frameCounting && packet.findPictureHeader(h264) &&
256 packet.getPacketType() >= PESTYPE_VID0 &&
257 packet.getPacketType() <= PESTYPE_VIDMAX)
259 ULLONG pts=packet.getPTS();
260 if (packet.findSeqHeader(h264) > 1 && pts != PESPacket::PTS_INVALID)
262 if (firstPTS == 0) firstPTS=pts;
267 if (packet.getPacketType() >= PESTYPE_VID0 &&
268 packet.getPacketType() <= PESTYPE_VIDMAX &&
269 packet.findSeqHeader(h264)) {
271 if (horizontal_size != last_horizontal_size ||
272 vertical_size != last_vertical_size) {
273 last_horizontal_size=horizontal_size;
274 last_vertical_size=vertical_size;
275 Log::getInstance()->log("Demux", Log::DEBUG,"signal size change, new x %d, y %d",
276 horizontal_size,vertical_size);
277 if (callback) callback->call(this);
283 //find a sequence header backward
284 //search for 00 00 01 <video> backwards
285 ULLONG DemuxerMedia::findLastPTS(UCHAR *buffer, ULONG len) {
289 if (len < minlen) return 0;
290 UCHAR *curpos=buffer+len-minlen;
291 UCHAR *packend=buffer+len;
292 while ((curpos - pstate) > buffer) {
295 if (*curpos < PESTYPE_VID0 || *curpos > PESTYPE_VIDMAX) break;
299 if (*curpos != 0x1) {
321 //curpos points before the first 0
322 pack.init(*(curpos+4));
323 pack.write(curpos+7,packend-curpos-7);
325 ULLONG pts=pack.getPTS();
326 if (pts != PESPacket::PTS_INVALID) {
329 Log::getInstance()->log("DemuxerMedia",Log::DEBUG,"findLastPTS found pts %llu at packet offset %lu from end",pts,len-(curpos+1-buffer));
332 //hmm - still no PTS, continue search
338 ULLONG DemuxerMedia::getCurrentPTS() {
339 return PTSDistance(currentPTS,firstPTS);
341 ULLONG DemuxerMedia::getLenPTS() {
342 if (lastPTS == 0) return 0;
343 if (lastPTS < firstPTS) return 0;
344 return PTSDistance(lastPTS,firstPTS);