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