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:
parent
42ee486389
commit
2a9896ce47
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user