switch to use STL containers, limit to 10 cache entries, don't clear cache on findkeyframe, removed inflight list as it was not needed, report error conditions better. This makes video work again

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34650 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
David McPaul 2009-12-13 12:09:17 +00:00
parent 42ee486389
commit 2a9896ce47
3 changed files with 54 additions and 60 deletions

View File

@ -10,23 +10,7 @@
#include <stdlib.h>
#include <string.h>
#include <Debug.h>
chunk_buffer::chunk_buffer()
:
buffer(NULL),
size(0),
capacity(0)
{
}
chunk_buffer::~chunk_buffer()
{
rtm_free(buffer);
}
#include "debug.h"
// #pragma mark -
@ -62,8 +46,11 @@ ChunkCache::MakeEmpty()
{
ASSERT(IsLocked());
fUnusedChunks.MoveFrom(&fChunks);
while (!fChunkCache.empty()) {
RecycleChunk(fChunkCache.front());
fChunkCache.pop();
}
release_sem(fWaitSem);
}
@ -73,18 +60,31 @@ 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()
ChunkCache::NextChunk(Reader* reader, void* cookie)
{
ASSERT(IsLocked());
chunk_buffer* chunk = fChunks.RemoveHead();
if (chunk != NULL) {
fInFlightChunks.Add(chunk);
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);
}
@ -92,7 +92,7 @@ ChunkCache::NextChunk()
}
/*! Moves the specified chunk from the in-flight list to the unused list.
/* Moves the specified chunk to the unused list.
This means the chunk data can be overwritten again.
*/
void
@ -100,8 +100,11 @@ ChunkCache::RecycleChunk(chunk_buffer* chunk)
{
ASSERT(IsLocked());
fInFlightChunks.Remove(chunk);
fUnusedChunks.Add(chunk);
rtm_free(chunk->buffer);
chunk->capacity = 0;
chunk->size = 0;
chunk->buffer = NULL;
fUnusedChunks.push_back(chunk);
}
@ -111,14 +114,22 @@ ChunkCache::ReadNextChunk(Reader* reader, void* cookie)
ASSERT(IsLocked());
// retrieve chunk buffer
chunk_buffer* chunk = fUnusedChunks.RemoveHead();
if (chunk == NULL) {
chunk_buffer* chunk = NULL;
if (fUnusedChunks.empty()) {
// allocate a new one
chunk = (chunk_buffer*)rtm_alloc(fRealTimePool, sizeof(chunk_buffer));
if (chunk == NULL)
if (chunk == NULL) {
ERROR("RTM Pool empty allocating chunk buffer structure");
return false;
}
chunk->size = 0;
chunk->capacity = 0;
chunk->buffer = NULL;
new(chunk) chunk_buffer;
} else {
chunk = fUnusedChunks.front();
fUnusedChunks.pop_front();
}
const void* buffer;
@ -133,6 +144,7 @@ ChunkCache::ReadNextChunk(Reader* reader, void* cookie)
chunk->buffer = rtm_alloc(fRealTimePool, chunk->capacity);
if (chunk->buffer == NULL) {
rtm_free(chunk);
ERROR("RTM Pool empty allocating chunk buffer\n");
return false;
}
}
@ -141,6 +153,6 @@ ChunkCache::ReadNextChunk(Reader* reader, void* cookie)
chunk->size = bufferSize;
}
fChunks.Add(chunk);
fChunkCache.push(chunk);
return chunk->status == B_OK;
}

View File

@ -9,8 +9,8 @@
#include <Locker.h>
#include <MediaDefs.h>
#include <RealtimeAlloc.h>
#include <kernel/util/DoublyLinkedList.h>
#include <queue>
#include <deque>
#include "ReaderPlugin.h"
@ -18,14 +18,10 @@
namespace BPrivate {
namespace media {
// Limit to 10 entries, we might want to instead limit to a length of time
#define CACHE_MAX_ENTRIES 10
struct chunk_buffer;
typedef DoublyLinkedList<chunk_buffer> ChunkList;
struct chunk_buffer : public DoublyLinkedListLinkImpl<chunk_buffer> {
chunk_buffer();
~chunk_buffer();
struct chunk_buffer {
void* buffer;
size_t size;
size_t capacity;
@ -33,6 +29,8 @@ struct chunk_buffer : public DoublyLinkedListLinkImpl<chunk_buffer> {
status_t status;
};
typedef queue<chunk_buffer*> ChunkQueue;
typedef deque<chunk_buffer*> ChunkList;
class ChunkCache : public BLocker {
public:
@ -44,7 +42,7 @@ public:
void MakeEmpty();
bool SpaceLeft() const;
chunk_buffer* NextChunk();
chunk_buffer* NextChunk(Reader* reader, void* cookie);
void RecycleChunk(chunk_buffer* chunk);
bool ReadNextChunk(Reader* reader, void* cookie);
@ -52,9 +50,8 @@ private:
rtm_pool* fRealTimePool;
sem_id fWaitSem;
size_t fMaxBytes;
ChunkList fChunks;
ChunkQueue fChunkCache;
ChunkList fUnusedChunks;
ChunkList fInFlightChunks;
};

View File

@ -274,16 +274,7 @@ MediaExtractor::FindKeyFrame(int32 stream, uint32 seekTo, int64* _frame,
if (info.status != B_OK)
return info.status;
BAutolock _(info.chunkCache);
status_t status = fReader->FindKeyFrame(info.cookie, seekTo, _frame, _time);
if (status != B_OK)
return status;
// clear buffered chunks after seek
info.chunkCache->MakeEmpty();
return B_OK;
return fReader->FindKeyFrame(info.cookie, seekTo, _frame, _time);
}
@ -307,13 +298,7 @@ MediaExtractor::GetNextChunk(int32 stream, const void** _chunkBuffer,
_RecycleLastChunk(info);
// Retrieve next chunk - read it directly, if the cache is drained
chunk_buffer* chunk;
do {
chunk = info.chunkCache->NextChunk();
if (chunk == NULL
&& !info.chunkCache->ReadNextChunk(fReader, info.cookie))
break;
} while (chunk == NULL);
chunk_buffer* chunk = info.chunkCache->NextChunk(fReader, info.cookie);
if (chunk == NULL)
return B_NO_MEMORY;