codec_kit: First half
* Move all codec stuff into libcodec.so
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* 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 -
|
||||
|
||||
|
||||
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(Reader* 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(Reader* 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;
|
||||
}
|
||||
Reference in New Issue
Block a user