From 2a9896ce478f061890a65d57d6985f0c571c6df1 Mon Sep 17 00:00:00 2001 From: David McPaul Date: Sun, 13 Dec 2009 12:09:17 +0000 Subject: [PATCH] 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 --- src/kits/media/ChunkCache.cpp | 74 ++++++++++++++++++------------- src/kits/media/ChunkCache.h | 21 ++++----- src/kits/media/MediaExtractor.cpp | 19 +------- 3 files changed, 54 insertions(+), 60 deletions(-) diff --git a/src/kits/media/ChunkCache.cpp b/src/kits/media/ChunkCache.cpp index 94d9c151ca..68de9df754 100644 --- a/src/kits/media/ChunkCache.cpp +++ b/src/kits/media/ChunkCache.cpp @@ -10,23 +10,7 @@ #include #include -#include - - -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; } diff --git a/src/kits/media/ChunkCache.h b/src/kits/media/ChunkCache.h index 3b912c6076..b0b4204a63 100644 --- a/src/kits/media/ChunkCache.h +++ b/src/kits/media/ChunkCache.h @@ -9,8 +9,8 @@ #include #include #include - -#include +#include +#include #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 ChunkList; - -struct chunk_buffer : public DoublyLinkedListLinkImpl { - chunk_buffer(); - ~chunk_buffer(); - +struct chunk_buffer { void* buffer; size_t size; size_t capacity; @@ -33,6 +29,8 @@ struct chunk_buffer : public DoublyLinkedListLinkImpl { status_t status; }; +typedef queue ChunkQueue; +typedef deque 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; }; diff --git a/src/kits/media/MediaExtractor.cpp b/src/kits/media/MediaExtractor.cpp index 84d35ccda1..16f0e61df7 100644 --- a/src/kits/media/MediaExtractor.cpp +++ b/src/kits/media/MediaExtractor.cpp @@ -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;