]> git.vomp.tv Git - vompclient.git/blob - demuxerts.cc
Windows fixes
[vompclient.git] / demuxerts.cc
1 /*
2     Copyright 2006 Mark Calderbank
3
4     This file is part of VOMP.
5
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.
10
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.
15
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
19 */
20
21 #include "demuxerts.h"
22
23 DemuxerTS::DemuxerTS(int p_vID, int p_aID)
24 {
25   vID = p_vID;
26   aID = p_aID;
27 }
28
29 void DemuxerTS::flush()
30 {
31   partPacket = 0;
32   Demuxer::flush();
33   vPacket.init(0xE0);
34   aPacket.init(0xC0);
35 }
36
37 int DemuxerTS::scan(UCHAR *buf, int len)
38 {
39   // Temporarily, just look for the lowest audio stream and return it
40
41   UINT LoPattern = 0x100 | PESTYPE_AUD0,
42        HiPattern = 0x100 | PESTYPE_AUDMAX;
43   int ret = 0;
44
45   while (len >= 4)
46   {
47     UINT pattern = *(UINT*)buf;
48     buf++; len--;
49
50     if (pattern < LoPattern || pattern > HiPattern) continue;
51     ret = pattern & 0xFF;
52     HiPattern = pattern;
53     if (HiPattern == LoPattern) break;
54   }
55   return ret;
56 }
57
58 void DemuxerTS::setVID(int p_vID)
59 {
60   vID = p_vID;
61 }
62
63 void DemuxerTS::setAID(int p_aID)
64 {
65   aID = p_aID;
66 }
67
68 int DemuxerTS::findPTS(UCHAR* buf, int len, ULLONG* dest)
69 {
70   UINT LoPattern = 0x100 | PESTYPE_VID0,
71        HiPattern = 0x100 | PESTYPE_VIDMAX;
72
73   while (len >= 14)
74   {
75     UINT pattern = *(UINT*)buf;
76     buf++; len--;
77     if (pattern < LoPattern || pattern > HiPattern) continue;
78
79     UINT framelength = ((UINT)buf[3] << 8) | buf[4];
80     buf += 5; len -= 5;
81
82     if ( buf[1] & 0x80 ) // PTS_DTS_flags indicate that PTS is present
83     {
84       *dest = ( (ULLONG)(buf[3] & 0x0E) << 29 ) |
85               ( (ULLONG)(buf[4])        << 22 ) |
86               ( (ULLONG)(buf[5] & 0xFE) << 14 ) |
87               ( (ULLONG)(buf[6])        <<  7 ) |
88               ( (ULLONG)(buf[7] & 0xFE) >>  1 );
89       return 1;
90     }
91
92     buf += framelength; len -= framelength;
93   }
94   // No PTS found.
95   return 0;
96 }
97
98 int DemuxerTS::put(UCHAR* buf, int len)
99 {
100   int ret = 0;    // return number of bytes consumed
101
102   while (partPacket)
103   {
104     if (len >= TS_SIZE + 1 - partPacket)
105     { // Remainder of partial packet is available, plus one
106       memcpy(store+partPacket, buf, TS_SIZE - partPacket);
107       ret += TS_SIZE - partPacket;
108       buf += TS_SIZE - partPacket;
109       len -= TS_SIZE - partPacket;
110       partPacket = TS_SIZE;
111       if (*buf == TS_SIG)
112       { // Packet is properly terminated
113         int rc = processTS(store);
114         if (rc)
115           partPacket = 0; // Successfully processed
116         else
117           return ret;     // Try again later.
118       }
119       else
120       { // Packet not terminated. Find another candidate, and shift store
121         Log::getInstance()->log("TS Demuxer", Log::ERR, "TS Misaligned!");
122         int search = 1;
123         while (search < partPacket && store[search] != TS_SIG)
124           search++;
125         partPacket -= search;
126         if (partPacket) memcpy(store, store+search, partPacket);
127       }
128     }
129     else
130     { // Still don't have complete packet. Consume what we do have.
131       memcpy(store+partPacket, buf, len);
132       partPacket += len;
133       ret += len;
134       return ret;
135     }
136   }
137
138   // Position ourselves at a candidate TS packet
139   while (*buf != TS_SIG && len)
140   {
141     Log::getInstance()->log("TS Demuxer", Log::ERR, "TS Misaligned!");
142     buf++; ret++; len--;
143   }
144
145   while (len)
146   {
147     if (len < TS_SIZE + 1)
148     { // Not enough data. Store what we have.
149       memcpy(store, buf, len);
150       partPacket = len;
151       ret += len;
152       return ret;
153     }
154
155     if (buf[TS_SIZE] != TS_SIG)
156     { // Not terminated correctly.
157       while (*buf != TS_SIG && len)
158       {
159         buf++; ret++; len--;
160       }
161     }
162     else
163     {
164       int rc = processTS(buf);
165       if (rc)
166       { // Successfully processed
167         buf += TS_SIZE; ret += TS_SIZE; len -= TS_SIZE;
168       }
169       else
170       { // Processing failed.
171         return ret;
172       }
173     }
174   }
175   return ret;
176 }
177
178 int DemuxerTS::processTS(UCHAR* buf)
179 {
180   int datalen = TS_SIZE - 4;
181   int pid = ( (buf[1] & 0x1F) << 8 ) | buf[2];
182   UCHAR payload = buf[1] & 0x40;
183
184   if (buf[3] & 0x20) // Adaptation field is present
185     datalen -= (buf[4] + 1);
186   if (datalen < 0) // Error in stream TODO log this
187     return 1;
188   if (datalen == 0) // Null packet
189     return 1;
190   buf += (TS_SIZE - datalen);
191
192   if (payload)
193   {
194     int rc = 1;
195
196     if (pid == vID) rc = vPacket.submit();
197     if (pid == aID) rc = aPacket.submit();
198     if (rc == 0) return 0;
199
200     if (pid == vID)
201     {
202       vPacket.init(0xE0);
203       buf += 6; datalen -= 6;
204     }
205     if (pid == aID)
206     {
207       aPacket.init(0xC0);
208       buf += 6; datalen -= 6;
209     }
210 //    int pesID = -1;
211 //    if (datalen >= 4) pesID = buf[3];
212 //    switch (pesID)
213 //    {
214 //    case PESTYPE_VID0 ... PESTYPE_VIDMAX:
215 //      if (video_current == -1) video_current = pesID;
216 //      if (video_current == pesID)
217 //      {
218 //        vPID = pid;
219 //        vPacket.init(pesID);
220 //        buf += 6; datalen -= 6;
221 //      }
222 //      break;
223 //    case PESTYPE_AUD0 ... PESTYPE_AUDMAX:
224 //      if (audio_current == -1) audio_current = pesID;
225 //      if (audio_current == pesID)
226 //      {
227 //        aPID = pid;
228 //        aPacket.init(pesID);
229 //        buf += 6; datalen -= 6;
230 //      }
231 //      break;
232 //    }
233   }
234
235   PESPacket* packet = NULL;
236   if (pid == vID) packet = &vPacket;
237   if (pid == aID) packet = &aPacket;
238   if (packet != NULL)
239   {
240     if (packet->write(buf, datalen) == 0)
241     { // Writing to packet failed. It has overflowed.
242       Log::getInstance()->log("TS Demuxer", Log::DEBUG, "Packet overflow, pid %d", pid);
243       if (packet->submit() == 0)
244         return 0;
245       packet->truncate();
246       packet->write((UCHAR*)"\200\000\000", 3);
247       packet->write(buf, datalen);
248     }
249   }
250
251   return 1;
252 }