3 *****************************************************************************
4 * Copyright (C) 2010 - 2011 Klagenfurt University
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>
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.
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.
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 *****************************************************************************/
28 #include "buffer/BlockBuffer.h"
30 using namespace dash::buffer;
32 BlockBuffer::BlockBuffer (stream_t *stream) :
39 this->capacityMicroSec = var_InheritInteger(stream, "dash-buffersize") * 1000000;
41 if(this->capacityMicroSec <= 0)
42 this->capacityMicroSec = DEFAULTBUFFERLENGTH;
44 this->peekBlock = block_Alloc(INTIALPEEKSIZE);
46 block_BytestreamInit(&this->buffer);
47 vlc_mutex_init(&this->monitorMutex);
48 vlc_cond_init(&this->empty);
49 vlc_cond_init(&this->full);
51 BlockBuffer::~BlockBuffer ()
53 block_Release(this->peekBlock);
55 block_BytestreamRelease(&this->buffer);
56 vlc_mutex_destroy(&this->monitorMutex);
57 vlc_cond_destroy(&this->empty);
58 vlc_cond_destroy(&this->full);
61 int BlockBuffer::peek (const uint8_t **pp_peek, unsigned int len)
63 vlc_mutex_lock(&this->monitorMutex);
65 while(this->sizeBytes == 0 && !this->isEOF)
66 vlc_cond_wait(&this->full, &this->monitorMutex);
68 if(this->sizeBytes == 0)
70 vlc_cond_signal(&this->empty);
71 vlc_mutex_unlock(&this->monitorMutex);
75 size_t ret = len > this->sizeBytes ? this->sizeBytes : len;
77 if(ret > this->peekBlock->i_buffer)
78 this->peekBlock = block_Realloc(this->peekBlock, 0, ret);
80 block_PeekBytes(&this->buffer, this->peekBlock->p_buffer, ret);
81 *pp_peek = this->peekBlock->p_buffer;
83 vlc_mutex_unlock(&this->monitorMutex);
87 int BlockBuffer::seekBackwards (unsigned len)
89 vlc_mutex_lock(&this->monitorMutex);
90 if( this->buffer.i_offset > len )
92 this->buffer.i_offset -= len;
93 this->sizeBytes += len;
94 vlc_mutex_unlock(&this->monitorMutex);
98 vlc_mutex_unlock(&this->monitorMutex);
102 int BlockBuffer::get (void *p_data, unsigned int len)
104 vlc_mutex_lock(&this->monitorMutex);
106 while(this->sizeBytes == 0 && !this->isEOF)
107 vlc_cond_wait(&this->full, &this->monitorMutex);
109 if(this->sizeBytes == 0)
111 vlc_cond_signal(&this->empty);
112 vlc_mutex_unlock(&this->monitorMutex);
116 int ret = len > this->sizeBytes ? this->sizeBytes : len;
119 block_SkipBytes(&this->buffer, ret);
121 block_GetBytes(&this->buffer, (uint8_t *)p_data, ret);
123 block_BytestreamFlush(&this->buffer);
124 this->updateBufferSize(ret);
128 vlc_cond_signal(&this->empty);
129 vlc_mutex_unlock(&this->monitorMutex);
132 void BlockBuffer::put (block_t *block)
134 vlc_mutex_lock(&this->monitorMutex);
136 while(this->sizeMicroSec >= this->capacityMicroSec && !this->isEOF)
137 vlc_cond_wait(&this->empty, &this->monitorMutex);
141 vlc_cond_signal(&this->full);
142 vlc_mutex_unlock(&this->monitorMutex);
146 this->sizeMicroSec += block->i_length;
147 this->sizeBytes += block->i_buffer;
149 block_BytestreamPush(&this->buffer, block);
152 vlc_cond_signal(&this->full);
153 vlc_mutex_unlock(&this->monitorMutex);
155 void BlockBuffer::setEOF (bool value)
157 vlc_mutex_lock(&this->monitorMutex);
159 vlc_cond_signal(&this->empty);
160 vlc_cond_signal(&this->full);
161 vlc_mutex_unlock(&this->monitorMutex);
163 bool BlockBuffer::getEOF ()
165 vlc_mutex_locker lock(&this->monitorMutex);
169 void BlockBuffer::attach (IBufferObserver *observer)
171 this->bufferObservers.push_back(observer);
173 void BlockBuffer::notify ()
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);
178 void BlockBuffer::updateBufferSize (size_t bytes)
180 block_t *block = this->buffer.p_block;
182 this->sizeMicroSec = 0;
186 this->sizeMicroSec += block->i_length;
187 block = block->p_next;
190 this->sizeBytes -= bytes;
192 mtime_t BlockBuffer::size ()
194 vlc_mutex_lock(&this->monitorMutex);
195 mtime_t ret = this->sizeMicroSec;
196 vlc_mutex_unlock(&this->monitorMutex);