]> git.vomp.tv Git - vompclient.git/blob - stream.cc
A little convergence to NEW_DEMUXER
[vompclient.git] / stream.cc
1 /*
2     Copyright 2005 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 "stream.h"
22
23 Stream::Stream()
24 {
25   initted = 0;
26   draintarget=NULL;
27 #ifdef NEW_DEMUXER
28   cur_packet_pos=0;
29 #endif
30 }
31
32 Stream::~Stream()
33 {
34   shutdown();
35 }
36
37 void Stream::shutdown()
38 {
39   if (initted) free(outbuf);
40   initted = 0;
41
42 }
43
44 int Stream::init(DrainTarget* tdt, int bufsize)
45 {
46   outbuf = (UCHAR*) malloc(bufsize);
47   if (!outbuf) return 0;
48   draintarget = tdt;
49   bufferSize = bufsize;
50   bufferHead = 0;
51   bufferTail = 0;
52   bufferMark = -1;
53   initted = 1;
54   return 1;
55 }
56
57 void Stream::flush()
58 {
59 #ifdef NEW_DEMUXER
60   mediapackets.clear();
61   if (draintarget) draintarget->ResetTimeOffsets();
62 #endif
63   bufferHead = 0;
64   bufferTail = 0;
65   bufferMark = -1;
66 }
67
68 #ifndef NEW_DEMUXER
69 int Stream::put(UCHAR* inbuf, int len)
70 {
71   int ret = 0;
72   int tail = bufferTail;
73   int head = bufferHead;
74   if (tail == 0) tail = bufferSize;
75
76   if (head < tail)
77   {
78     // The free space is in one continuous chunk.
79     if (len < tail - head)
80     {
81       memcpy(outbuf + head, inbuf, len);
82       bufferHead += len;
83       ret = len;
84     }
85   }
86   else if (len <= bufferSize - head)
87   {
88     // There is enough space above the Head.
89     memcpy(outbuf + head, inbuf, len);
90     if (head + len == bufferSize)
91       bufferHead = 0;
92     else
93       bufferHead += len;
94     ret = len;
95   }
96   else if (len < tail)
97   {
98     bufferMark = head;
99     memcpy(outbuf, inbuf, len);
100     bufferHead = len;
101     ret = len;
102   }
103   return ret;
104 }
105 #else
106 int Stream::put(UCHAR* inbuf, int len,ULLONG curpos)
107 {
108   int ret = 0;
109   int tail = bufferTail;
110   int head = bufferHead;
111   if (tail == 0) tail = bufferSize;
112
113   if (!draintarget) return 0;
114   MediaPacket newPacket;
115   newPacket.length=len;
116   newPacket.pos_buffer=0;
117   newPacket.recording_byte_pos=curpos;
118   newPacket.synched=false;
119   newPacket.disconti=false;
120   newPacket.pts=0;
121   newPacket.presentation_time=0;
122   //Extract the pts...
123   if ((inbuf[7] & 0x80) && len>14 ) {
124     newPacket.synched=true;
125     newPacket.pts=((ULLONG)(inbuf[9] & 0x0E) << 29 ) |
126                 ( (ULLONG)(inbuf[10])        << 22 ) |
127                 ( (ULLONG)(inbuf[11] & 0xFE) << 14 ) |
128                 ( (ULLONG)(inbuf[12])        <<  7 ) |
129                 ( (ULLONG)(inbuf[13] & 0xFE) >>  1 );
130   //ok we have the pts now convert it to a continously time code in 100ns units
131     newPacket.presentation_time=(ULLONG)(newPacket.pts*10000LL/90LL);
132     newPacket.presentation_time-=draintarget->SetStartOffset(newPacket.presentation_time,&newPacket.disconti);
133   }
134
135   if (head < tail)
136   {
137     // The free space is in one continuous chunk.
138     if (len < tail - head)
139     {
140       memcpy(outbuf + head, inbuf, len);
141       bufferHead += len;
142       ret = len;
143       newPacket.pos_buffer=head;
144       mediapackets.push_front(newPacket);
145     }
146   }
147   else if (len <= bufferSize - head)
148   {
149     // There is enough space above the Head.
150     memcpy(outbuf + head, inbuf, len);
151     if (head + len == bufferSize)
152       bufferHead = 0;
153     else
154       bufferHead += len;
155
156     newPacket.pos_buffer=head;
157     mediapackets.push_front(newPacket);
158
159     ret = len;
160   }
161   else if (len < tail)
162   {
163     bufferMark = head;
164     memcpy(outbuf, inbuf, len);
165     bufferHead = len;
166     ret = len;
167     newPacket.pos_buffer=0;
168     mediapackets.push_front(newPacket);
169   }
170   return ret;
171 }
172 #endif
173
174 #ifndef NEW_DEMUXER
175
176 int Stream::drain()
177 {
178   int ret = 0;
179   int head = bufferHead;
180   int tail = bufferTail;
181   int mark = bufferMark;
182   int written;
183
184   if (mark == -1 && tail > head) mark = bufferSize;
185
186   if (mark >= 0)
187   {
188     // Drain up to the marker.
189 #ifndef WIN32
190     written = draintarget->write(outbuf + tail, (mark - tail));
191 #else
192     written=mark-tail;
193     MILLISLEEP(1);
194 #endif
195     if (written < 0) return ret;
196     ret += written;
197     if (written == (mark - tail))
198     {
199       bufferMark = -1;
200       bufferTail = tail = 0;
201     }
202     else
203     {
204       bufferTail += written;
205       return ret;
206     }
207   }
208
209   if (tail == head) return ret; // Empty
210 #ifndef WIN32
211   written = draintarget->write(outbuf + tail, (head - tail));
212 #else
213   written=(head - tail);
214   MILLISLEEP(1);
215 #endif
216   if (written < 0) return ret;
217   ret += written;
218   bufferTail = tail + written;
219   return ret;
220 }
221
222 #else
223
224 int Stream::drain()
225 {
226   int ret = 0;
227   int written=1;
228 //  draintarget=dt; // this is now set in init, is this ok?
229
230
231
232   if (mediapackets.empty()) {
233     return 0;
234   }
235    // using mediapackets, may be this is slower but it is more flexible
236  // while (!mediapackets.empty() && written) {
237
238   int head = bufferHead;
239   int tail = bufferTail;
240   int mark = bufferMark;
241   if (mark == -1 && tail > head) mark = bufferSize;
242   MediaPacket cur_mp=mediapackets.back();
243   written=0;
244   written=dt->DeliverMediaSample(cur_mp,outbuf,&cur_packet_pos);
245
246   ret+=written;
247
248   if (cur_packet_pos==cur_mp.length) {
249     cur_packet_pos=0;
250     mediapackets.pop_back();
251     if ((((ULONG)tail)+cur_mp.length) < ((ULONG)mark)) {
252       bufferTail=tail+cur_mp.length;
253     } else {
254       bufferTail=0;
255       bufferMark=-1;
256     }
257
258   }
259
260   return ret;
261 }
262
263 #endif