]> git.vomp.tv Git - vompclient.git/blob - stream.cc
Fix text corruption in channel number display on live tv
[vompclient.git] / stream.cc
1 /*
2     Copyright 2005-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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19 */
20
21 #include "stream.h"
22 #include "log.h"
23
24 Stream::Stream()
25 {
26   initted = 0;
27   draintarget = NULL;
28   cur_packet_pos = 0;
29 }
30
31 Stream::~Stream()
32 {
33   shutdown();
34 }
35
36 void Stream::shutdown()
37 {
38   if (initted)
39   {
40     free(outbuf);
41 #ifdef WIN32
42     CloseHandle(mutex);
43 #endif
44       
45   }
46   initted = 0;
47 }
48
49 int Stream::init(DrainTarget* tdt, int bufsize)
50 {
51   outbuf = (UCHAR*) malloc(bufsize);
52   if (!outbuf) return 0;
53   draintarget = tdt;
54   bufferSize = bufsize;
55   initted = 1;
56 #ifndef WIN32
57   pthread_mutex_init(&mutex, NULL);
58 #else
59   mutex=CreateMutex(NULL,FALSE,NULL);
60 #endif
61   return 1;
62 }
63
64 void Stream::flush()
65 {
66   lock();
67
68   mediapackets.clear();
69   cur_packet_pos = 0;
70   unLock();
71   if (draintarget) draintarget->ResetTimeOffsets();
72 }
73
74 int Stream::put(const UCHAR* inbuf, int len, UCHAR type,unsigned int index)
75 {
76   int ret = 0;
77   if (!draintarget) return 0;
78   MediaPacket newPacket;
79   newPacket.length = len;
80   newPacket.pos_buffer = 0;
81   newPacket.type = type;
82   newPacket.pts=0;
83   newPacket.dts=0;
84   newPacket.synched=false;
85   newPacket.index=index;
86 #ifndef VOMP_PLATTFORM_MVP
87   newPacket.disconti=false;
88   newPacket.presentation_time=0;
89 #endif
90   if (type!=MPTYPE_MPEG_AUDIO_LAYER3) {//no PES
91     //Extract the pts...
92       bool hasdts=false;
93     if ((inbuf[7] & 0x80) && len>14 ) {
94         newPacket.synched=true;
95         newPacket.pts=((ULLONG)(inbuf[9] & 0x0E) << 29 ) |
96                     ( (ULLONG)(inbuf[10])        << 22 ) |
97                     ( (ULLONG)(inbuf[11] & 0xFE) << 14 ) |
98                      ( (ULLONG)(inbuf[12])        <<  7 ) |
99                      ( (ULLONG)(inbuf[13] & 0xFE) >>  1 );
100         if ((inbuf[7] & 0x40) && len>19) {
101             newPacket.dts=((ULLONG)(inbuf[14] & 0x0E) << 29 ) |
102                     ( (ULLONG)(inbuf[15])        << 22 ) |
103                     ( (ULLONG)(inbuf[16] & 0xFE) << 14 ) |
104                      ( (ULLONG)(inbuf[17])        <<  7 ) |
105                      ( (ULLONG)(inbuf[18] & 0xFE) >>  1 );
106             hasdts=true;
107         }
108 #ifndef VOMP_PLATTFORM_MVP
109         //ok we have the pts now convert it to a continously time code in 100ns units
110         if (hasdts && draintarget->dtsTimefix()) newPacket.presentation_time=(ULLONG)(newPacket.dts*10000LL/90LL);
111         else newPacket.presentation_time=(ULLONG)(newPacket.pts*10000LL/90LL);
112
113         //newPacket.presentation_time-=draintarget->SetStartOffset((ULLONG)(newPacket.pts*10000LL/90LL),&newPacket.disconti);
114         newPacket.presentation_time-=draintarget->SetStartOffset((ULLONG)(newPacket.pts*10000LL/90LL),&newPacket.disconti);
115 #endif
116     }
117   }
118
119   lock();
120   int front, back;
121   if (mediapackets.empty())
122   {
123     back = 0; front = bufferSize;
124   }
125   else
126   {
127     front = mediapackets.front().pos_buffer;
128     back = mediapackets.back().pos_buffer + mediapackets.back().length;
129     if (back == bufferSize) back = 0;
130   }
131   unLock();
132
133   if (back <= front)
134   {
135     // The free space (if any) is in one continuous chunk.
136     if (len <= front - back) ret = len; // Is there enough of it?
137   }
138   else if (len <= bufferSize - back)
139   {
140     // There is enough space at the end of the buffer
141     ret = len;
142   }
143   else if (len <= front)
144   {
145     // There is enough space at the start of the buffer
146     back = 0;
147     ret = len;
148   }
149
150   if (ret) // Nonzero if we managed to find room for the packet
151   {
152     memcpy(outbuf + back, inbuf, len);
153     newPacket.pos_buffer = back;
154     lock();
155     mediapackets.push_back(newPacket);
156     unLock();
157   } else {
158      // Log::getInstance()->log("Stream", Log::DEBUG, "We are full %d!",bufferSize);
159   }
160
161   return ret;
162 }
163
164 bool Stream::drain(bool * dataavail)
165 {
166   bool ret = false;
167   if (dataavail) *dataavail=false;
168   if (draintarget->DrainTargetBufferFull()) return false; //We are full, no need to do something else
169   lock();
170   UINT listlength = mediapackets.size();
171   if (listlength != 0)
172   {
173     draintarget->PrepareMediaSample(mediapackets, cur_packet_pos);
174     unLock();
175     if (dataavail && draintarget->DrainTargetReady()) *dataavail=true;
176     UINT consumed = draintarget->DeliverMediaSample(outbuf, &cur_packet_pos);
177     lock();
178     if (consumed != 0) ret = true;
179     if (consumed > listlength) consumed = listlength;
180     while (consumed--) 
181     {
182         mediapackets.pop_front();
183     }
184   }
185   unLock();
186   return ret;
187 }
188
189 void Stream::lock()
190 {
191 #ifndef WIN32
192   pthread_mutex_lock(&mutex);
193   //logger->log("Player", Log::DEBUG, "LOCKED");
194
195 #else
196    WaitForSingleObject(mutex, INFINITE );
197 #endif
198 }
199
200 void Stream::unLock()
201 {
202 #ifndef WIN32
203   //logger->log("Player", Log::DEBUG, "UNLOCKING");
204   pthread_mutex_unlock(&mutex);
205 #else
206    ReleaseMutex(mutex);
207 #endif
208 }