]> git.sesse.net Git - vlc/blob - modules/stream_filter/dash/buffer/BlockBuffer.cpp
stream_filter: dash: simplify next chunk condition
[vlc] / modules / stream_filter / dash / buffer / BlockBuffer.cpp
1 /*
2  * BlockBuffer.cpp
3  *****************************************************************************
4  * Copyright (C) 2010 - 2011 Klagenfurt University
5  *
6  * Created on: Aug 10, 2010
7  * Authors: Christopher Mueller <christopher.mueller@itec.uni-klu.ac.at>
8  *          Christian Timmerer  <christian.timmerer@itec.uni-klu.ac.at>
9  *
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU Lesser General Public License as published
12  * by the Free Software Foundation; either version 2.1 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with this program; if not, write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27
28 #include "buffer/BlockBuffer.h"
29
30 using namespace dash::buffer;
31
32 BlockBuffer::BlockBuffer    (stream_t *stream) :
33              sizeMicroSec   (0),
34              sizeBytes      (0),
35              stream         (stream),
36              isEOF          (false)
37
38 {
39     this->capacityMicroSec  = var_InheritInteger(stream, "dash-buffersize") * 1000000;
40
41     if(this->capacityMicroSec <= 0)
42         this->capacityMicroSec = DEFAULTBUFFERLENGTH;
43
44     this->peekBlock = block_Alloc(INTIALPEEKSIZE);
45
46     block_BytestreamInit(&this->buffer);
47     vlc_mutex_init(&this->monitorMutex);
48     vlc_cond_init(&this->empty);
49     vlc_cond_init(&this->full);
50 }
51 BlockBuffer::~BlockBuffer   ()
52 {
53     block_Release(this->peekBlock);
54
55     block_BytestreamRelease(&this->buffer);
56     vlc_mutex_destroy(&this->monitorMutex);
57     vlc_cond_destroy(&this->empty);
58     vlc_cond_destroy(&this->full);
59 }
60
61 int     BlockBuffer::peek                 (const uint8_t **pp_peek, unsigned int len)
62 {
63     vlc_mutex_lock(&this->monitorMutex);
64
65     while(this->sizeBytes == 0 && !this->isEOF)
66         vlc_cond_wait(&this->full, &this->monitorMutex);
67
68     if(this->sizeBytes == 0)
69     {
70         vlc_cond_signal(&this->empty);
71         vlc_mutex_unlock(&this->monitorMutex);
72         return 0;
73     }
74
75     size_t ret = len > this->sizeBytes ? this->sizeBytes : len;
76
77     if(ret > this->peekBlock->i_buffer)
78         this->peekBlock = block_Realloc(this->peekBlock, 0, ret);
79
80     block_PeekBytes(&this->buffer, this->peekBlock->p_buffer, ret);
81     *pp_peek = this->peekBlock->p_buffer;
82
83     vlc_mutex_unlock(&this->monitorMutex);
84     return ret;
85 }
86
87 int     BlockBuffer::seekBackwards       (unsigned len)
88 {
89     vlc_mutex_lock(&this->monitorMutex);
90     if( this->buffer.i_offset > len )
91     {
92         this->buffer.i_offset -= len;
93         this->sizeBytes += len;
94         vlc_mutex_unlock(&this->monitorMutex);
95         return VLC_SUCCESS;
96     }
97
98     vlc_mutex_unlock(&this->monitorMutex);
99     return VLC_EGENERIC;
100 }
101
102 int     BlockBuffer::get                  (void *p_data, unsigned int len)
103 {
104     vlc_mutex_lock(&this->monitorMutex);
105
106     while(this->sizeBytes == 0 && !this->isEOF)
107         vlc_cond_wait(&this->full, &this->monitorMutex);
108
109     if(this->sizeBytes == 0)
110     {
111         vlc_cond_signal(&this->empty);
112         vlc_mutex_unlock(&this->monitorMutex);
113         return 0;
114     }
115
116     int ret = len > this->sizeBytes ? this->sizeBytes : len;
117
118     if(p_data == NULL)
119         block_SkipBytes(&this->buffer, ret);
120     else
121         block_GetBytes(&this->buffer, (uint8_t *)p_data, ret);
122
123     block_BytestreamFlush(&this->buffer);
124     this->updateBufferSize(ret);
125
126     this->notify();
127
128     vlc_cond_signal(&this->empty);
129     vlc_mutex_unlock(&this->monitorMutex);
130     return ret;
131 }
132 void    BlockBuffer::put                  (block_t *block)
133 {
134     vlc_mutex_lock(&this->monitorMutex);
135
136     while(this->sizeMicroSec >= this->capacityMicroSec && !this->isEOF)
137         vlc_cond_wait(&this->empty, &this->monitorMutex);
138
139     if(this->isEOF)
140     {
141         vlc_cond_signal(&this->full);
142         vlc_mutex_unlock(&this->monitorMutex);
143         return;
144     }
145
146     this->sizeMicroSec  += block->i_length;
147     this->sizeBytes     += block->i_buffer;
148
149     block_BytestreamPush(&this->buffer, block);
150     this->notify();
151
152     vlc_cond_signal(&this->full);
153     vlc_mutex_unlock(&this->monitorMutex);
154 }
155 void    BlockBuffer::setEOF               (bool value)
156 {
157     vlc_mutex_lock(&this->monitorMutex);
158     this->isEOF = value;
159     vlc_cond_signal(&this->empty);
160     vlc_cond_signal(&this->full);
161     vlc_mutex_unlock(&this->monitorMutex);
162 }
163 bool    BlockBuffer::getEOF               ()
164 {
165     vlc_mutex_locker    lock(&this->monitorMutex);
166
167     return this->isEOF;
168 }
169 void    BlockBuffer::attach               (IBufferObserver *observer)
170 {
171     this->bufferObservers.push_back(observer);
172 }
173 void    BlockBuffer::notify               ()
174 {
175     for(size_t i = 0; i < this->bufferObservers.size(); i++)
176         this->bufferObservers.at(i)->bufferLevelChanged(this->sizeMicroSec, ((float)this->sizeMicroSec / this->capacityMicroSec) * 100);
177 }
178 void    BlockBuffer::updateBufferSize     (size_t bytes)
179 {
180     block_t *block = this->buffer.p_block;
181
182     this->sizeMicroSec = 0;
183
184     while(block)
185     {
186         this->sizeMicroSec += block->i_length;
187         block = block->p_next;
188     }
189
190     this->sizeBytes -= bytes;
191 }
192 mtime_t BlockBuffer::size                 ()
193 {
194     vlc_mutex_lock(&this->monitorMutex);
195     mtime_t ret = this->sizeMicroSec;
196     vlc_mutex_unlock(&this->monitorMutex);
197     return ret;
198 }