167 lines
3.0 KiB
C++
167 lines
3.0 KiB
C++
/*
|
|||
* Copyright 2009, Axel Dörfler, [email protected].
|
|||
* Distributed under the terms of the MIT License.
|
|||
*/
|
|||
|
|||
|
|||
#include "ChunkCache.h"
|
|||
|
|||
#include <new>
|
|||
|
|
#include <stdlib.h>
|
||
#include <string.h>
|
|||
|
|||
#include "MediaDebug.h"
|
|||
|
|||
// #pragma mark -
|
|||
|
|
|
||
|
|
|
||
namespace BCodecKit {
|
|||
|
|
namespace BPrivate {
|
||
|
|
|
||
|
|
|
||
ChunkCache::ChunkCache(sem_id waitSem, size_t maxBytes)
|
|||
:
|
|||
BLocker("media chunk cache"),
|
|||
fWaitSem(waitSem)
|
|||
{
|
|||
rtm_create_pool(&fRealTimePool, maxBytes, "media chunk cache");
|
|||
|
|
fMaxBytes = rtm_available(fRealTimePool);
|
||
}
|
|||
|
|
|
||
|
|
|
||
|
|
ChunkCache::~ChunkCache()
|
||
|
|
{
|
||
rtm_delete_pool(fRealTimePool);
|
|||
|
|
}
|
||
|
|
|
||
|
|||
status_t
|
|||
|
|
ChunkCache::InitCheck() const
|
||
|
|
{
|
||
|
|
if (fRealTimePool == NULL)
|
||
|
|
return B_NO_MEMORY;
|
||
|
|||
return B_OK;
|
|||
}
|
|||
|
|
|
||
|
|
|
||
|
|
void
|
||
|
|
ChunkCache::MakeEmpty()
|
||
|
|
{
|
||
ASSERT(IsLocked());
|
|||
|
|
|
||
while (!fChunkCache.empty()) {
|
|||
|
|
RecycleChunk(fChunkCache.front());
|
||
|
|
fChunkCache.pop();
|
||
|
|
}
|
||
|
|
|
||
release_sem(fWaitSem);
|
|||
}
|
|||
|
|
|
||
|
|
|
||
|
|
bool
|
||
ChunkCache::SpaceLeft() const
|
|||
{
|
|||
ASSERT(IsLocked());
|
|||
|
|
|
||
if (fChunkCache.size() >= CACHE_MAX_ENTRIES) {
|
|||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// If there is no more memory we are likely to fail soon after
|
||
return sizeof(chunk_buffer) + 2048 < rtm_available(fRealTimePool);
|
|||
}
|
|||
|
|
|
||
|
|||
chunk_buffer*
|
|||
ChunkCache::NextChunk(BReader* reader, void* cookie)
|
|||
{
|
|||
ASSERT(IsLocked());
|
|||
|
|||
chunk_buffer* chunk = NULL;
|
|||
|
|
|
||
|
|
if (fChunkCache.empty()) {
|
||
|
|
TRACE("ChunkCache is empty, going direct to reader\n");
|
||
|
|
if (ReadNextChunk(reader, cookie)) {
|
||
|
|
return NextChunk(reader, cookie);
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
chunk = fChunkCache.front();
|
||
|
|
fChunkCache.pop();
|
||
|
|
|
||
release_sem(fWaitSem);
|
|||
}
|
|||
|
|||
return chunk;
|
|||
|
|
}
|
||
|
|||
|
|
|
||
/* Moves the specified chunk to the unused list.
|
|||
This means the chunk data can be overwritten again.
|
|||
|
|
*/
|
||
|
|
void
|
||
|
|
ChunkCache::RecycleChunk(chunk_buffer* chunk)
|
||
|
|
{
|
||
|
|
ASSERT(IsLocked());
|
||
|
|||
rtm_free(chunk->buffer);
|
|||
|
|
chunk->capacity = 0;
|
||
|
|
chunk->size = 0;
|
||
|
|
chunk->buffer = NULL;
|
||
|
|
fUnusedChunks.push_back(chunk);
|
||
}
|
|||
|
|
|
||
|
|
|
||
bool
|
|||
ChunkCache::ReadNextChunk(BReader* reader, void* cookie)
|
|||
{
|
|||
ASSERT(IsLocked());
|
|||
|
|||
// retrieve chunk buffer
|
|||
chunk_buffer* chunk = NULL;
|
|||
|
|
if (fUnusedChunks.empty()) {
|
||
// allocate a new one
|
|||
chunk = (chunk_buffer*)rtm_alloc(fRealTimePool, sizeof(chunk_buffer));
|
|||
if (chunk == NULL) {
|
|||
|
|
ERROR("RTM Pool empty allocating chunk buffer structure");
|
||
return false;
|
|||
}
|
|||
|
|
|
||
|
|
chunk->size = 0;
|
||
|
|
chunk->capacity = 0;
|
||
|
|
chunk->buffer = NULL;
|
||
|
|
|
||
|
|
} else {
|
||
|
|
chunk = fUnusedChunks.front();
|
||
|
|
fUnusedChunks.pop_front();
|
||
}
|
|||
|
|||
const void* buffer;
|
|||
|
|
size_t bufferSize;
|
||
|
|
chunk->status = reader->GetNextChunk(cookie, &buffer, &bufferSize,
|
||
|
|
&chunk->header);
|
||
|
|
if (chunk->status == B_OK) {
|
||
|
|
if (chunk->capacity < bufferSize) {
|
||
|
|
// adapt buffer size
|
||
rtm_free(chunk->buffer);
|
|||
chunk->capacity = (bufferSize + 2047) & ~2047;
|
|||
chunk->buffer = rtm_alloc(fRealTimePool, chunk->capacity);
|
|||
if (chunk->buffer == NULL) {
|
|||
rtm_free(chunk);
|
|||
ERROR("RTM Pool empty allocating chunk buffer\n");
|
|||
return false;
|
|||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
memcpy(chunk->buffer, buffer, bufferSize);
|
||
|
|
chunk->size = bufferSize;
|
||
|
|
}
|
||
|
|||
fChunkCache.push(chunk);
|
|||
return chunk->status == B_OK;
|
|||
}
|
|||
|
|||
|
|
|
||
|
|
} // namespace BPrivate
|
||
|
|
} // namespace BCodecKit
|