Completed implementation of chunk caching. Playback from harddisk is now much better, crackling should be gone.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9485 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
beveloper 2004-10-24 17:15:50 +00:00
parent 846b4a22f5
commit f14dfaa7b9
3 changed files with 107 additions and 4 deletions

View File

@ -1,38 +1,118 @@
#include <Locker.h>
#include "ChunkCache.h"
#include "debug.h"
ChunkCache::ChunkCache()
{
fLocker = new BLocker("media chunk cache locker");
// fEmptyChunkCount must be one less than the real chunk count,
// because the buffer returned by GetNextChunk must be preserved
// until the next call of that function, and must not be overwritten.
fEmptyChunkCount = CHUNK_COUNT - 1;
fReadyChunkCount = 0;
fNeedsRefill = 1;
fGetWaitSem = create_sem(0, "media chunk cache sem");
fNextPut = &fChunkInfos[0];
fNextGet = &fChunkInfos[0];
for (int i = 0; i < CHUNK_COUNT; i++) {
fChunkInfos[i].next = (i == CHUNK_COUNT -1) ? &fChunkInfos[0] : &fChunkInfos[i + 1];
fChunkInfos[i].buffer = NULL;
fChunkInfos[i].sizeUsed = 0;
fChunkInfos[i].sizeMax = 0;
fChunkInfos[i].err = B_ERROR;
}
}
ChunkCache::~ChunkCache()
{
delete_sem(fGetWaitSem);
delete fLocker;
for (int i = 0; i < CHUNK_COUNT; i++) {
free(fChunkInfos[i].buffer);
}
}
void
ChunkCache::MakeEmpty()
{
fLocker->Lock();
fEmptyChunkCount = CHUNK_COUNT - 1;
fReadyChunkCount = 0;
atomic_or(&fNeedsRefill, 1);
fLocker->Unlock();
}
bool
ChunkCache::NeedsRefill()
{
return false;
return atomic_or(&fNeedsRefill, 0);
}
status_t
ChunkCache::GetNextChunk(void **chunkBuffer, int32 *chunkSize, media_header *mediaHeader)
{
return B_ERROR;
// printf("ChunkCache::GetNextChunk: %p fEmptyChunkCount %ld, fReadyChunkCount %ld\n", fNextGet, fEmptyChunkCount, fReadyChunkCount);
retry:
acquire_sem(fGetWaitSem);
fLocker->Lock();
if (fReadyChunkCount == 0) {
fLocker->Unlock();
printf("ChunkCache::GetNextChunk: %p retrying\n", fNextGet);
goto retry;
}
fEmptyChunkCount++;
fReadyChunkCount--;
atomic_or(&fNeedsRefill, 1);
fLocker->Unlock();
*chunkBuffer = fNextGet->buffer;
*chunkSize = fNextGet->sizeUsed;
*mediaHeader = fNextGet->mediaHeader;
status_t err = fNextGet->err;
fNextGet = fNextGet->next;
return err;
}
void
ChunkCache::PutNextChunk(void *chunkBuffer, int32 chunkSize, const media_header &mediaHeader, status_t err)
{
// printf("ChunkCache::PutNextChunk: %p fEmptyChunkCount %ld, fReadyChunkCount %ld\n", fNextPut, fEmptyChunkCount, fReadyChunkCount);
if (err == B_OK) {
if (fNextPut->sizeMax < chunkSize) {
// printf("ChunkCache::PutNextChunk: %p resizing from %ld to %ld\n", fNextPut, fNextPut->sizeMax, chunkSize);
free(fNextPut->buffer);
fNextPut->buffer = malloc((chunkSize + 1024) & ~1023);
fNextPut->sizeMax = chunkSize;
}
memcpy(fNextPut->buffer, chunkBuffer, chunkSize);
fNextPut->sizeUsed = chunkSize;
}
fNextPut->mediaHeader = mediaHeader;
fNextPut->err = err;
fNextPut = fNextPut->next;
fLocker->Lock();
fEmptyChunkCount--;
fReadyChunkCount++;
if (fEmptyChunkCount == 0)
atomic_and(&fNeedsRefill, 0);
fLocker->Unlock();
release_sem(fGetWaitSem);
}

View File

@ -7,6 +7,17 @@ namespace BPrivate {
namespace media {
struct chunk_info
{
chunk_info * next;
void * buffer;
int32 sizeUsed;
int32 sizeMax;
media_header mediaHeader;
status_t err;
};
class ChunkCache
{
public:
@ -20,9 +31,21 @@ public:
void PutNextChunk(void *chunkBuffer, int32 chunkSize, const media_header &mediaHeader, status_t err);
private:
enum { CHUNK_COUNT = 5 };
chunk_info * fNextPut;
chunk_info * fNextGet;
chunk_info fChunkInfos[CHUNK_COUNT];
sem_id fGetWaitSem;
int32 fEmptyChunkCount;
int32 fReadyChunkCount;
int32 fNeedsRefill;
BLocker * fLocker;
};
}; // namespace media
}; // namespace BPrivate

View File

@ -63,7 +63,7 @@ MediaExtractor::MediaExtractor(BDataIO *source, int32 flags)
}
// start extractor thread
fExtractorWaitSem = create_sem(0, "media extractor thread sem");
fExtractorWaitSem = create_sem(1, "media extractor thread sem");
fExtractorThread = spawn_thread(extractor_thread, "media extractor thread", 10, this);
resume_thread(fExtractorThread);
}