]> git.vomp.tv Git - vompclient-marten.git/blob - stream.cc
Live TV updates
[vompclient-marten.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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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   initted = 0;
46 }
47
48 int Stream::init(DrainTarget* tdt, int bufsize)
49 {
50   outbuf = (UCHAR*) malloc(bufsize);
51   if (!outbuf) return 0;
52   draintarget = tdt;
53   bufferSize = bufsize;
54   initted = 1;
55 #ifndef WIN32
56   pthread_mutex_init(&mutex, NULL);
57 #else
58   mutex=CreateMutex(NULL,FALSE,NULL);
59 #endif
60   return 1;
61 }
62
63 void Stream::flush()
64 {
65   lock();
66   mediapackets.clear();
67   unLock();
68   if (draintarget) draintarget->ResetTimeOffsets();
69 }
70
71 int Stream::put(const UCHAR* inbuf, int len, UCHAR type)
72 {
73   int ret = 0;
74   if (!draintarget) return 0;
75   MediaPacket newPacket;
76   newPacket.length = len;
77   newPacket.pos_buffer = 0;
78   newPacket.type = type;
79 #ifdef WIN32
80   newPacket.synched=false;
81   newPacket.disconti=false;
82   newPacket.pts=0;
83   newPacket.presentation_time=0;
84   if (type!=MPTYPE_MPEG_AUDIO_LAYER3) {//no PES
85     //Extract the pts...
86     if ((inbuf[7] & 0x80) && len>14 ) {
87         newPacket.synched=true;
88         newPacket.pts=((ULLONG)(inbuf[9] & 0x0E) << 29 ) |
89                     ( (ULLONG)(inbuf[10])        << 22 ) |
90                     ( (ULLONG)(inbuf[11] & 0xFE) << 14 ) |
91                      ( (ULLONG)(inbuf[12])        <<  7 ) |
92                      ( (ULLONG)(inbuf[13] & 0xFE) >>  1 );
93         //ok we have the pts now convert it to a continously time code in 100ns units
94         newPacket.presentation_time=(ULLONG)(newPacket.pts*10000LL/90LL);
95         newPacket.presentation_time-=draintarget->SetStartOffset(newPacket.presentation_time,&newPacket.disconti);
96     }
97   }
98 #endif
99
100   lock();
101   int front, back;
102   if (mediapackets.empty())
103   {
104     back = 0; front = bufferSize;
105   }
106   else
107   {
108     front = mediapackets.front().pos_buffer;
109     back = mediapackets.back().pos_buffer + mediapackets.back().length;
110     if (back == bufferSize) back = 0;
111   }
112   unLock();
113
114   if (back <= front)
115   {
116     // The free space (if any) is in one continuous chunk.
117     if (len <= front - back) ret = len; // Is there enough of it?
118   }
119   else if (len <= bufferSize - back)
120   {
121     // There is enough space at the end of the buffer
122     ret = len;
123   }
124   else if (len <= front)
125   {
126     // There is enough space at the start of the buffer
127     back = 0;
128     ret = len;
129   }
130
131   if (ret) // Nonzero if we managed to find room for the packet
132   {
133     memcpy(outbuf + back, inbuf, len);
134     newPacket.pos_buffer = back;
135     lock();
136     mediapackets.push_back(newPacket);
137     unLock();
138   }
139   return ret;
140 }
141
142 bool Stream::drain()
143 {
144   bool ret = false;
145   lock();
146   UINT listlength = mediapackets.size();
147   if (listlength != 0)
148   {
149     draintarget->PrepareMediaSample(mediapackets, cur_packet_pos);
150     unLock();
151     UINT consumed = draintarget->DeliverMediaSample(outbuf, &cur_packet_pos);
152     lock();
153     if (consumed != 0) ret = true;
154     if (consumed > listlength) consumed = listlength;
155     while (consumed--) mediapackets.pop_front();
156   }
157   unLock();
158   return ret;
159 }
160
161 void Stream::lock()
162 {
163 #ifndef WIN32
164   pthread_mutex_lock(&mutex);
165   //logger->log("Player", Log::DEBUG, "LOCKED");
166
167 #else
168    WaitForSingleObject(mutex, INFINITE );
169 #endif
170 }
171
172 void Stream::unLock()
173 {
174 #ifndef WIN32
175   //logger->log("Player", Log::DEBUG, "UNLOCKING");
176   pthread_mutex_unlock(&mutex);
177 #else
178    ReleaseMutex(mutex);
179 #endif
180 }