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