2 Copyright 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 "demuxerts.h"
23 DemuxerTS::DemuxerTS(int p_vID, int p_aID)
29 void DemuxerTS::flush()
37 int DemuxerTS::scan(UCHAR *buf, int len)
41 // Temporarily, just look for the lowest audio stream and return it
43 UINT LoPattern = 0x100 | PESTYPE_AUD0,
44 HiPattern = 0x100 | PESTYPE_AUDMAX;
49 UINT pattern = *(UINT*)buf;
52 if (pattern < LoPattern || pattern > HiPattern) continue;
55 if (HiPattern == LoPattern) break;
61 void DemuxerTS::setVID(int p_vID)
66 void DemuxerTS::setAID(int p_aID)
71 int DemuxerTS::findPTS(UCHAR* buf, int len, ULLONG* dest)
73 UINT LoPattern = 0x100 | PESTYPE_VID0,
74 HiPattern = 0x100 | PESTYPE_VIDMAX;
78 UINT pattern = *(UINT*)buf;
80 if (pattern < LoPattern || pattern > HiPattern) continue;
82 UINT framelength = ((UINT)buf[3] << 8) | buf[4];
85 if ( buf[1] & 0x80 ) // PTS_DTS_flags indicate that PTS is present
87 *dest = ( (ULLONG)(buf[3] & 0x0E) << 29 ) |
88 ( (ULLONG)(buf[4]) << 22 ) |
89 ( (ULLONG)(buf[5] & 0xFE) << 14 ) |
90 ( (ULLONG)(buf[6]) << 7 ) |
91 ( (ULLONG)(buf[7] & 0xFE) >> 1 );
95 buf += framelength; len -= framelength;
101 int DemuxerTS::put(UCHAR* buf, int len)
103 int ret = 0; // return number of bytes consumed
107 if (len >= TS_SIZE + 1 - partPacket)
108 { // Remainder of partial packet is available, plus one
109 memcpy(store+partPacket, buf, TS_SIZE - partPacket);
110 ret += TS_SIZE - partPacket;
111 buf += TS_SIZE - partPacket;
112 len -= TS_SIZE - partPacket;
113 partPacket = TS_SIZE;
115 { // Packet is properly terminated
116 int rc = processTS(store);
118 partPacket = 0; // Successfully processed
120 return ret; // Try again later.
123 { // Packet not terminated. Find another candidate, and shift store
124 Log::getInstance()->log("TS Demuxer", Log::ERR, "TS Misaligned!");
126 while (search < partPacket && store[search] != TS_SIG)
128 partPacket -= search;
129 if (partPacket) memcpy(store, store+search, partPacket);
133 { // Still don't have complete packet. Consume what we do have.
134 memcpy(store+partPacket, buf, len);
141 // Position ourselves at a candidate TS packet
142 while (*buf != TS_SIG && len)
144 Log::getInstance()->log("TS Demuxer", Log::ERR, "TS Misaligned!");
150 if (len < TS_SIZE + 1)
151 { // Not enough data. Store what we have.
152 memcpy(store, buf, len);
158 if (buf[TS_SIZE] != TS_SIG)
159 { // Not terminated correctly.
160 while (*buf != TS_SIG && len)
167 int rc = processTS(buf);
169 { // Successfully processed
170 buf += TS_SIZE; ret += TS_SIZE; len -= TS_SIZE;
173 { // Processing failed.
181 int DemuxerTS::processTS(UCHAR* buf)
183 int datalen = TS_SIZE - 4;
184 int pid = ( (buf[1] & 0x1F) << 8 ) | buf[2];
185 UCHAR payload = buf[1] & 0x40;
187 if (buf[3] & 0x20) // Adaptation field is present
188 datalen -= (buf[4] + 1);
189 if (datalen < 0) // Error in stream TODO log this
191 if (datalen == 0) // Null packet
193 buf += (TS_SIZE - datalen);
199 if (pid == vID) rc = vPacket.submit();
200 if (pid == aID) rc = aPacket.submit();
201 if (rc == 0) return 0;
206 buf += 6; datalen -= 6;
211 buf += 6; datalen -= 6;
214 // if (datalen >= 4) pesID = buf[3];
217 // case PESTYPE_VID0 ... PESTYPE_VIDMAX:
218 // if (video_current == -1) video_current = pesID;
219 // if (video_current == pesID)
222 // vPacket.init(pesID);
223 // buf += 6; datalen -= 6;
226 // case PESTYPE_AUD0 ... PESTYPE_AUDMAX:
227 // if (audio_current == -1) audio_current = pesID;
228 // if (audio_current == pesID)
231 // aPacket.init(pesID);
232 // buf += 6; datalen -= 6;
238 PESPacket* packet = NULL;
239 if (pid == vID) packet = &vPacket;
240 if (pid == aID) packet = &aPacket;
243 if (packet->write(buf, datalen) == 0)
244 { // Writing to packet failed. It has overflowed.
245 Log::getInstance()->log("TS Demuxer", Log::DEBUG, "Packet overflow, pid %d", pid);
246 if (packet->submit() == 0)
249 packet->write((UCHAR*)"\200\000\000", 3);
250 packet->write(buf, datalen);