* ChunkCache::fLocker is now aggregated.
* Cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34239 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
40fddd06d6
commit
608d959d73
@ -1,78 +1,85 @@
|
||||
/*
|
||||
* Copyright 2004-2007, Marcus Overhagen. All rights reserved.
|
||||
* Copyright 2008, Maurice Kalinowski. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _MEDIA_EXTRACTOR_H
|
||||
#define _MEDIA_EXTRACTOR_H
|
||||
|
||||
|
||||
#include "ReaderPlugin.h"
|
||||
#include "DecoderPlugin.h"
|
||||
|
||||
|
||||
namespace BPrivate {
|
||||
namespace media {
|
||||
|
||||
class ChunkCache;
|
||||
|
||||
struct stream_info
|
||||
{
|
||||
struct stream_info {
|
||||
status_t status;
|
||||
void * cookie;
|
||||
void* cookie;
|
||||
bool hasCookie;
|
||||
const void * infoBuffer;
|
||||
const void* infoBuffer;
|
||||
size_t infoBufferSize;
|
||||
ChunkCache * chunkCache;
|
||||
ChunkCache* chunkCache;
|
||||
media_format encodedFormat;
|
||||
};
|
||||
|
||||
class MediaExtractor
|
||||
{
|
||||
class MediaExtractor {
|
||||
public:
|
||||
MediaExtractor(BDataIO * source, int32 flags);
|
||||
~MediaExtractor();
|
||||
MediaExtractor(BDataIO* source, int32 flags);
|
||||
~MediaExtractor();
|
||||
|
||||
status_t InitCheck();
|
||||
status_t InitCheck();
|
||||
|
||||
void GetFileFormatInfo(media_file_format *mfi) const;
|
||||
void GetFileFormatInfo(
|
||||
media_file_format* fileFormat) const;
|
||||
|
||||
int32 StreamCount();
|
||||
int32 StreamCount();
|
||||
|
||||
const char* Copyright();
|
||||
const char* Copyright();
|
||||
|
||||
const media_format * EncodedFormat(int32 stream);
|
||||
int64 CountFrames(int32 stream) const;
|
||||
bigtime_t Duration(int32 stream) const;
|
||||
const media_format* EncodedFormat(int32 stream);
|
||||
int64 CountFrames(int32 stream) const;
|
||||
bigtime_t Duration(int32 stream) const;
|
||||
|
||||
status_t Seek(int32 stream, uint32 seekTo,
|
||||
int64 *frame, bigtime_t *time);
|
||||
status_t FindKeyFrame(int32 stream, uint32 seekTo,
|
||||
int64 *frame, bigtime_t *time) const;
|
||||
status_t Seek(int32 stream, uint32 seekTo, int64* _frame,
|
||||
bigtime_t* _time);
|
||||
status_t FindKeyFrame(int32 stream, uint32 seekTo,
|
||||
int64* _frame, bigtime_t* _time) const;
|
||||
|
||||
status_t GetNextChunk(int32 stream,
|
||||
const void **chunkBuffer, size_t *chunkSize,
|
||||
media_header *mediaHeader);
|
||||
status_t GetNextChunk(int32 stream,
|
||||
const void** _chunkBuffer,
|
||||
size_t* _chunkSize,
|
||||
media_header* mediaHeader);
|
||||
|
||||
status_t CreateDecoder(int32 stream, Decoder **decoder,
|
||||
media_codec_info *mci);
|
||||
status_t CreateDecoder(int32 stream, Decoder** _decoder,
|
||||
media_codec_info* codecInfo);
|
||||
|
||||
private:
|
||||
static int32 extractor_thread(void *arg);
|
||||
void ExtractorThread();
|
||||
static int32 _ExtractorEntry(void* arg);
|
||||
void _ExtractorThread();
|
||||
|
||||
private:
|
||||
status_t fErr;
|
||||
status_t fInitStatus;
|
||||
|
||||
sem_id fExtractorWaitSem;
|
||||
thread_id fExtractorThread;
|
||||
volatile bool fTerminateExtractor;
|
||||
sem_id fExtractorWaitSem;
|
||||
thread_id fExtractorThread;
|
||||
volatile bool fTerminateExtractor;
|
||||
|
||||
BDataIO *fSource;
|
||||
Reader *fReader;
|
||||
BDataIO* fSource;
|
||||
Reader* fReader;
|
||||
|
||||
stream_info * fStreamInfo;
|
||||
int32 fStreamCount;
|
||||
stream_info* fStreamInfo;
|
||||
int32 fStreamCount;
|
||||
|
||||
media_file_format fMff;
|
||||
media_file_format fFileFormat;
|
||||
};
|
||||
|
||||
}; // namespace media
|
||||
}; // namespace BPrivate
|
||||
} // namespace media
|
||||
} // namespace BPrivate
|
||||
|
||||
using namespace BPrivate::media;
|
||||
|
||||
#endif
|
||||
#endif // _MEDIA_EXTRACTOR_H
|
||||
|
@ -1,42 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Marcus Overhagen
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* Copyright 2004, Marcus Overhagen. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#include <Locker.h>
|
||||
|
||||
#include "ChunkCache.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <Autolock.h>
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
ChunkCache::ChunkCache()
|
||||
:
|
||||
fLocker("media chunk cache locker")
|
||||
{
|
||||
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;
|
||||
@ -45,13 +29,14 @@ ChunkCache::ChunkCache()
|
||||
|
||||
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].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;
|
||||
fChunkInfos[i].status = B_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,7 +44,7 @@ ChunkCache::ChunkCache()
|
||||
ChunkCache::~ChunkCache()
|
||||
{
|
||||
delete_sem(fGetWaitSem);
|
||||
delete fLocker;
|
||||
|
||||
for (int i = 0; i < CHUNK_COUNT; i++) {
|
||||
free(fChunkInfos[i].buffer);
|
||||
}
|
||||
@ -69,13 +54,13 @@ ChunkCache::~ChunkCache()
|
||||
void
|
||||
ChunkCache::MakeEmpty()
|
||||
{
|
||||
fLocker->Lock();
|
||||
BAutolock _(fLocker);
|
||||
|
||||
fEmptyChunkCount = CHUNK_COUNT - 1;
|
||||
fReadyChunkCount = 0;
|
||||
fNextPut = &fChunkInfos[0];
|
||||
fNextGet = &fChunkInfos[0];
|
||||
atomic_or(&fNeedsRefill, 1);
|
||||
fLocker->Unlock();
|
||||
}
|
||||
|
||||
|
||||
@ -85,48 +70,53 @@ ChunkCache::NeedsRefill()
|
||||
return atomic_or(&fNeedsRefill, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
status_t
|
||||
ChunkCache::GetNextChunk(const void **chunkBuffer, size_t *chunkSize, media_header *mediaHeader)
|
||||
ChunkCache::GetNextChunk(const void** _chunkBuffer, size_t* _chunkSize,
|
||||
media_header* mediaHeader)
|
||||
{
|
||||
uint8 retry_count = 0;
|
||||
uint8 retryCount = 0;
|
||||
|
||||
// printf("ChunkCache::GetNextChunk: %p fEmptyChunkCount %ld, fReadyChunkCount %ld\n", fNextGet, fEmptyChunkCount, fReadyChunkCount);
|
||||
retry:
|
||||
acquire_sem(fGetWaitSem);
|
||||
|
||||
fLocker->Lock();
|
||||
BAutolock locker(fLocker);
|
||||
if (fReadyChunkCount == 0) {
|
||||
fLocker->Unlock();
|
||||
locker.Unlock();
|
||||
|
||||
printf("ChunkCache::GetNextChunk: %p retrying\n", fNextGet);
|
||||
// Limit to 5 retries
|
||||
retry_count++;
|
||||
if (retry_count > 4) {
|
||||
retryCount++;
|
||||
if (retryCount > 4)
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
goto retry;
|
||||
}
|
||||
|
||||
fEmptyChunkCount++;
|
||||
fReadyChunkCount--;
|
||||
atomic_or(&fNeedsRefill, 1);
|
||||
fLocker->Unlock();
|
||||
|
||||
*chunkBuffer = fNextGet->buffer;
|
||||
*chunkSize = fNextGet->sizeUsed;
|
||||
|
||||
locker.Unlock();
|
||||
|
||||
*_chunkBuffer = fNextGet->buffer;
|
||||
*_chunkSize = fNextGet->sizeUsed;
|
||||
*mediaHeader = fNextGet->mediaHeader;
|
||||
status_t err = fNextGet->err;
|
||||
status_t status = fNextGet->status;
|
||||
fNextGet = fNextGet->next;
|
||||
|
||||
return err;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ChunkCache::PutNextChunk(const void *chunkBuffer, size_t chunkSize, const media_header &mediaHeader, status_t err)
|
||||
ChunkCache::PutNextChunk(const void* chunkBuffer, size_t chunkSize,
|
||||
const media_header& mediaHeader, status_t status)
|
||||
{
|
||||
// printf("ChunkCache::PutNextChunk: %p fEmptyChunkCount %ld, fReadyChunkCount %ld\n", fNextPut, fEmptyChunkCount, fReadyChunkCount);
|
||||
|
||||
if (err == B_OK) {
|
||||
if (status == B_OK) {
|
||||
if (fNextPut->sizeMax < chunkSize) {
|
||||
// printf("ChunkCache::PutNextChunk: %p resizing from %ld to %ld\n", fNextPut, fNextPut->sizeMax, chunkSize);
|
||||
free(fNextPut->buffer);
|
||||
@ -136,18 +126,18 @@ ChunkCache::PutNextChunk(const void *chunkBuffer, size_t chunkSize, const media_
|
||||
memcpy(fNextPut->buffer, chunkBuffer, chunkSize);
|
||||
fNextPut->sizeUsed = chunkSize;
|
||||
}
|
||||
|
||||
|
||||
fNextPut->mediaHeader = mediaHeader;
|
||||
fNextPut->err = err;
|
||||
fNextPut->status = status;
|
||||
|
||||
fNextPut = fNextPut->next;
|
||||
|
||||
fLocker->Lock();
|
||||
fLocker.Lock();
|
||||
fEmptyChunkCount--;
|
||||
fReadyChunkCount++;
|
||||
if (fEmptyChunkCount == 0)
|
||||
atomic_and(&fNeedsRefill, 0);
|
||||
fLocker->Unlock();
|
||||
fLocker.Unlock();
|
||||
|
||||
release_sem(fGetWaitSem);
|
||||
}
|
||||
|
@ -1,78 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Marcus Overhagen
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* Copyright 2004, Marcus Overhagen. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _CHUNK_CACHE_H
|
||||
#define _CHUNK_CACHE_H
|
||||
|
||||
|
||||
#include <Locker.h>
|
||||
#include <MediaDefs.h>
|
||||
|
||||
|
||||
namespace BPrivate {
|
||||
namespace media {
|
||||
|
||||
|
||||
struct chunk_info
|
||||
{
|
||||
chunk_info * next;
|
||||
void * buffer;
|
||||
struct chunk_info {
|
||||
chunk_info* next;
|
||||
void* buffer;
|
||||
size_t sizeUsed;
|
||||
size_t sizeMax;
|
||||
media_header mediaHeader;
|
||||
status_t err;
|
||||
status_t status;
|
||||
};
|
||||
|
||||
|
||||
class ChunkCache
|
||||
{
|
||||
class ChunkCache {
|
||||
public:
|
||||
ChunkCache();
|
||||
~ChunkCache();
|
||||
ChunkCache();
|
||||
~ChunkCache();
|
||||
|
||||
void MakeEmpty();
|
||||
bool NeedsRefill();
|
||||
|
||||
status_t GetNextChunk(const void** _chunkBuffer,
|
||||
size_t* _chunkSize,
|
||||
media_header* mediaHeader);
|
||||
void PutNextChunk(const void* chunkBuffer,
|
||||
size_t chunkSize,
|
||||
const media_header& mediaHeader,
|
||||
status_t status);
|
||||
|
||||
void MakeEmpty();
|
||||
bool NeedsRefill();
|
||||
|
||||
status_t GetNextChunk(const void **chunkBuffer, size_t *chunkSize, media_header *mediaHeader);
|
||||
void PutNextChunk(const void *chunkBuffer, size_t 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;
|
||||
|
||||
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
|
||||
} // namespace media
|
||||
} // namespace BPrivate
|
||||
|
||||
using namespace BPrivate::media;
|
||||
|
||||
#endif
|
||||
#endif // _CHUNK_CACHE_H
|
||||
|
@ -6,22 +6,48 @@
|
||||
|
||||
|
||||
#include "MediaExtractor.h"
|
||||
#include "PluginManager.h"
|
||||
#include "ChunkCache.h"
|
||||
#include "debug.h"
|
||||
|
||||
#include <new>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <Autolock.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <new>
|
||||
#include "debug.h"
|
||||
#include "ChunkCache.h"
|
||||
#include "PluginManager.h"
|
||||
|
||||
|
||||
// should be 0, to disable the chunk cache set it to 1
|
||||
#define DISABLE_CHUNK_CACHE 0
|
||||
|
||||
|
||||
MediaExtractor::MediaExtractor(BDataIO *source, int32 flags)
|
||||
class MediaExtractorChunkProvider : public ChunkProvider {
|
||||
public:
|
||||
MediaExtractorChunkProvider(MediaExtractor* extractor, int32 stream)
|
||||
:
|
||||
fExtractor(extractor),
|
||||
fStream(stream)
|
||||
{
|
||||
}
|
||||
|
||||
virtual status_t GetNextChunk(const void** _chunkBuffer, size_t* _chunkSize,
|
||||
media_header *mediaHeader)
|
||||
{
|
||||
return fExtractor->GetNextChunk(fStream, _chunkBuffer, _chunkSize,
|
||||
mediaHeader);
|
||||
}
|
||||
|
||||
private:
|
||||
MediaExtractor* fExtractor;
|
||||
int32 fStream;
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
MediaExtractor::MediaExtractor(BDataIO* source, int32 flags)
|
||||
{
|
||||
CALLED();
|
||||
fSource = source;
|
||||
@ -30,8 +56,9 @@ MediaExtractor::MediaExtractor(BDataIO *source, int32 flags)
|
||||
fExtractorWaitSem = -1;
|
||||
fTerminateExtractor = false;
|
||||
|
||||
fErr = _plugin_manager.CreateReader(&fReader, &fStreamCount, &fMff, source);
|
||||
if (fErr) {
|
||||
fInitStatus = _plugin_manager.CreateReader(&fReader, &fStreamCount,
|
||||
&fFileFormat, source);
|
||||
if (fInitStatus != B_OK) {
|
||||
fStreamCount = 0;
|
||||
fReader = NULL;
|
||||
return;
|
||||
@ -66,11 +93,13 @@ MediaExtractor::MediaExtractor(BDataIO *source, int32 flags)
|
||||
for (int32 i = 0; i < fStreamCount; i++) {
|
||||
if (fStreamInfo[i].status != B_OK)
|
||||
continue;
|
||||
|
||||
int64 frameCount;
|
||||
bigtime_t duration;
|
||||
if (B_OK != fReader->GetStreamInfo(fStreamInfo[i].cookie, &frameCount,
|
||||
if (fReader->GetStreamInfo(fStreamInfo[i].cookie, &frameCount,
|
||||
&duration, &fStreamInfo[i].encodedFormat,
|
||||
&fStreamInfo[i].infoBuffer, &fStreamInfo[i].infoBufferSize)) {
|
||||
&fStreamInfo[i].infoBuffer, &fStreamInfo[i].infoBufferSize)
|
||||
!= B_OK) {
|
||||
fStreamInfo[i].status = B_ERROR;
|
||||
ERROR("MediaExtractor::MediaExtractor: GetStreamInfo for "
|
||||
"stream %ld failed\n", i);
|
||||
@ -80,8 +109,8 @@ MediaExtractor::MediaExtractor(BDataIO *source, int32 flags)
|
||||
#if DISABLE_CHUNK_CACHE == 0
|
||||
// start extractor thread
|
||||
fExtractorWaitSem = create_sem(1, "media extractor thread sem");
|
||||
fExtractorThread = spawn_thread(extractor_thread, "media extractor thread",
|
||||
10, this);
|
||||
fExtractorThread = spawn_thread(_ExtractorEntry, "media extractor thread",
|
||||
40, this);
|
||||
resume_thread(fExtractorThread);
|
||||
#endif
|
||||
}
|
||||
@ -117,15 +146,15 @@ status_t
|
||||
MediaExtractor::InitCheck()
|
||||
{
|
||||
CALLED();
|
||||
return fErr;
|
||||
return fInitStatus;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MediaExtractor::GetFileFormatInfo(media_file_format *mfi) const
|
||||
MediaExtractor::GetFileFormatInfo(media_file_format* fileFormat) const
|
||||
{
|
||||
CALLED();
|
||||
*mfi = fMff;
|
||||
*fileFormat = fFileFormat;
|
||||
}
|
||||
|
||||
|
||||
@ -144,7 +173,7 @@ MediaExtractor::Copyright()
|
||||
}
|
||||
|
||||
|
||||
const media_format *
|
||||
const media_format*
|
||||
MediaExtractor::EncodedFormat(int32 stream)
|
||||
{
|
||||
return &fStreamInfo[stream].encodedFormat;
|
||||
@ -161,7 +190,7 @@ MediaExtractor::CountFrames(int32 stream) const
|
||||
int64 frameCount;
|
||||
bigtime_t duration;
|
||||
media_format format;
|
||||
const void *infoBuffer;
|
||||
const void* infoBuffer;
|
||||
size_t infoSize;
|
||||
|
||||
fReader->GetStreamInfo(fStreamInfo[stream].cookie, &frameCount, &duration,
|
||||
@ -193,8 +222,7 @@ MediaExtractor::Duration(int32 stream) const
|
||||
|
||||
|
||||
status_t
|
||||
MediaExtractor::Seek(int32 stream, uint32 seekTo,
|
||||
int64 *frame, bigtime_t *time)
|
||||
MediaExtractor::Seek(int32 stream, uint32 seekTo, int64* frame, bigtime_t* time)
|
||||
{
|
||||
CALLED();
|
||||
if (fStreamInfo[stream].status != B_OK)
|
||||
@ -214,22 +242,21 @@ MediaExtractor::Seek(int32 stream, uint32 seekTo,
|
||||
|
||||
|
||||
status_t
|
||||
MediaExtractor::FindKeyFrame(int32 stream, uint32 seekTo, int64 *frame,
|
||||
bigtime_t *time) const
|
||||
MediaExtractor::FindKeyFrame(int32 stream, uint32 seekTo, int64* _frame,
|
||||
bigtime_t* _time) const
|
||||
{
|
||||
CALLED();
|
||||
if (fStreamInfo[stream].status != B_OK)
|
||||
return fStreamInfo[stream].status;
|
||||
|
||||
return fReader->FindKeyFrame(fStreamInfo[stream].cookie,
|
||||
seekTo, frame, time);
|
||||
seekTo, _frame, _time);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
MediaExtractor::GetNextChunk(int32 stream,
|
||||
const void **chunkBuffer, size_t *chunkSize,
|
||||
media_header *mediaHeader)
|
||||
MediaExtractor::GetNextChunk(int32 stream, const void** _chunkBuffer,
|
||||
size_t* _chunkSize, media_header* mediaHeader)
|
||||
{
|
||||
if (fStreamInfo[stream].status != B_OK)
|
||||
return fStreamInfo[stream].status;
|
||||
@ -237,68 +264,51 @@ MediaExtractor::GetNextChunk(int32 stream,
|
||||
#if DISABLE_CHUNK_CACHE > 0
|
||||
static BLocker locker("media extractor next chunk");
|
||||
BAutolock lock(locker);
|
||||
return fReader->GetNextChunk(fStreamInfo[stream].cookie, chunkBuffer,
|
||||
chunkSize, mediaHeader);
|
||||
return fReader->GetNextChunk(fStreamInfo[stream].cookie, _chunkBuffer,
|
||||
_chunkSize, mediaHeader);
|
||||
#endif
|
||||
|
||||
status_t err;
|
||||
err = fStreamInfo[stream].chunkCache->GetNextChunk(chunkBuffer, chunkSize,
|
||||
mediaHeader);
|
||||
status_t status = fStreamInfo[stream].chunkCache->GetNextChunk(_chunkBuffer,
|
||||
_chunkSize, mediaHeader);
|
||||
release_sem(fExtractorWaitSem);
|
||||
return err;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
class MediaExtractorChunkProvider : public ChunkProvider {
|
||||
private:
|
||||
MediaExtractor * fExtractor;
|
||||
int32 fStream;
|
||||
public:
|
||||
MediaExtractorChunkProvider(MediaExtractor * extractor, int32 stream)
|
||||
{
|
||||
fExtractor = extractor;
|
||||
fStream = stream;
|
||||
}
|
||||
|
||||
virtual status_t GetNextChunk(const void **chunkBuffer, size_t *chunkSize,
|
||||
media_header *mediaHeader)
|
||||
{
|
||||
return fExtractor->GetNextChunk(fStream, chunkBuffer, chunkSize,
|
||||
mediaHeader);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
status_t
|
||||
MediaExtractor::CreateDecoder(int32 stream, Decoder **out_decoder,
|
||||
media_codec_info *mci)
|
||||
MediaExtractor::CreateDecoder(int32 stream, Decoder** _decoder,
|
||||
media_codec_info* codecInfo)
|
||||
{
|
||||
CALLED();
|
||||
status_t res;
|
||||
Decoder *decoder;
|
||||
|
||||
res = fStreamInfo[stream].status;
|
||||
if (res != B_OK) {
|
||||
status_t status = fStreamInfo[stream].status;
|
||||
if (status != B_OK) {
|
||||
ERROR("MediaExtractor::CreateDecoder can't create decoder for "
|
||||
"stream %ld\n", stream);
|
||||
return res;
|
||||
"stream %ld: %s\n", stream, strerror(status));
|
||||
return status;
|
||||
}
|
||||
|
||||
// TODO Here we should work out a way so that if there is a setup failure we can try the next decoder
|
||||
res = _plugin_manager.CreateDecoder(&decoder,
|
||||
// TODO: Here we should work out a way so that if there is a setup
|
||||
// failure we can try the next decoder
|
||||
Decoder* decoder;
|
||||
status = _plugin_manager.CreateDecoder(&decoder,
|
||||
fStreamInfo[stream].encodedFormat);
|
||||
if (res != B_OK) {
|
||||
if (status != B_OK) {
|
||||
#if DEBUG
|
||||
char formatString[256];
|
||||
string_for_format(fStreamInfo[stream].encodedFormat, formatString,
|
||||
256);
|
||||
sizeof(formatString));
|
||||
|
||||
ERROR("MediaExtractor::CreateDecoder _plugin_manager.CreateDecoder "
|
||||
"failed for stream %ld, format: %s\n", stream, formatString);
|
||||
return res;
|
||||
"failed for stream %ld, format: %s: %s\n", stream, formatString,
|
||||
strerror(status));
|
||||
#endif
|
||||
return status;
|
||||
}
|
||||
|
||||
ChunkProvider *chunkProvider
|
||||
ChunkProvider* chunkProvider
|
||||
= new(std::nothrow) MediaExtractorChunkProvider(this, stream);
|
||||
if (!chunkProvider) {
|
||||
if (chunkProvider == NULL) {
|
||||
_plugin_manager.DestroyDecoder(decoder);
|
||||
ERROR("MediaExtractor::CreateDecoder can't create chunk provider "
|
||||
"for stream %ld\n", stream);
|
||||
@ -307,64 +317,65 @@ MediaExtractor::CreateDecoder(int32 stream, Decoder **out_decoder,
|
||||
|
||||
decoder->SetChunkProvider(chunkProvider);
|
||||
|
||||
res = decoder->Setup(&fStreamInfo[stream].encodedFormat,
|
||||
status = decoder->Setup(&fStreamInfo[stream].encodedFormat,
|
||||
fStreamInfo[stream].infoBuffer, fStreamInfo[stream].infoBufferSize);
|
||||
if (res != B_OK) {
|
||||
if (status != B_OK) {
|
||||
_plugin_manager.DestroyDecoder(decoder);
|
||||
ERROR("MediaExtractor::CreateDecoder Setup failed for stream %ld: "
|
||||
"%ld (%s)\n", stream, res, strerror(res));
|
||||
return res;
|
||||
ERROR("MediaExtractor::CreateDecoder Setup failed for stream %ld: %s\n",
|
||||
stream, strerror(status));
|
||||
return status;
|
||||
}
|
||||
|
||||
res = _plugin_manager.GetDecoderInfo(decoder, mci);
|
||||
if (res != B_OK) {
|
||||
status = _plugin_manager.GetDecoderInfo(decoder, codecInfo);
|
||||
if (status != B_OK) {
|
||||
_plugin_manager.DestroyDecoder(decoder);
|
||||
ERROR("MediaExtractor::CreateDecoder GetCodecInfo failed for stream "
|
||||
"%ld: %ld (%s)\n", stream, res, strerror(res));
|
||||
return res;
|
||||
"%ld: %s\n", stream, strerror(status));
|
||||
return status;
|
||||
}
|
||||
|
||||
*out_decoder = decoder;
|
||||
*_decoder = decoder;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
MediaExtractor::extractor_thread(void *arg)
|
||||
status_t
|
||||
MediaExtractor::_ExtractorEntry(void* extractor)
|
||||
{
|
||||
static_cast<MediaExtractor *>(arg)->ExtractorThread();
|
||||
return 0;
|
||||
static_cast<MediaExtractor*>(extractor)->_ExtractorThread();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MediaExtractor::ExtractorThread()
|
||||
MediaExtractor::_ExtractorThread()
|
||||
{
|
||||
for (;;) {
|
||||
while (true) {
|
||||
acquire_sem(fExtractorWaitSem);
|
||||
if (fTerminateExtractor)
|
||||
return;
|
||||
|
||||
bool refill_done;
|
||||
bool refillDone;
|
||||
do {
|
||||
refill_done = false;
|
||||
refillDone = false;
|
||||
for (int32 stream = 0; stream < fStreamCount; stream++) {
|
||||
if (fStreamInfo[stream].status != B_OK)
|
||||
continue;
|
||||
|
||||
if (fStreamInfo[stream].chunkCache->NeedsRefill()) {
|
||||
media_header mediaHeader;
|
||||
const void *chunkBuffer;
|
||||
const void* chunkBuffer;
|
||||
size_t chunkSize;
|
||||
status_t err;
|
||||
err = fReader->GetNextChunk(fStreamInfo[stream].cookie,
|
||||
&chunkBuffer, &chunkSize, &mediaHeader);
|
||||
status_t status = fReader->GetNextChunk(
|
||||
fStreamInfo[stream].cookie, &chunkBuffer, &chunkSize,
|
||||
&mediaHeader);
|
||||
fStreamInfo[stream].chunkCache->PutNextChunk(chunkBuffer,
|
||||
chunkSize, mediaHeader, err);
|
||||
refill_done = true;
|
||||
chunkSize, mediaHeader, status);
|
||||
refillDone = true;
|
||||
}
|
||||
}
|
||||
if (fTerminateExtractor)
|
||||
return;
|
||||
} while (refill_done);
|
||||
} while (refillDone);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user