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