PluginManager: Refactor of MediaIOWrapper
* Use BPositionIO version of Read/Write. * Implementation of fallback buffering. * Other cleanup.
This commit is contained in:
@@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
PluginManager gPluginManager;
|
PluginManager gPluginManager;
|
||||||
|
|
||||||
|
#define BLOCK_SIZE 4096
|
||||||
|
|
||||||
|
|
||||||
class BMediaIOWrapper : public BMediaIO {
|
class BMediaIOWrapper : public BMediaIO {
|
||||||
public:
|
public:
|
||||||
@@ -28,10 +30,14 @@ public:
|
|||||||
fPosition(NULL),
|
fPosition(NULL),
|
||||||
fMedia(NULL),
|
fMedia(NULL),
|
||||||
fFile(NULL),
|
fFile(NULL),
|
||||||
|
fFallbackBuffer(NULL),
|
||||||
|
fFallbackPosition(0),
|
||||||
fErr(B_NO_ERROR)
|
fErr(B_NO_ERROR)
|
||||||
{
|
{
|
||||||
fPosition = dynamic_cast<BPositionIO*>(source);
|
fPosition = dynamic_cast<BPositionIO*>(source);
|
||||||
fMedia = dynamic_cast<BMediaIO*>(source);
|
fMedia = dynamic_cast<BMediaIO*>(source);
|
||||||
|
fFile = dynamic_cast<BFile*>(source);
|
||||||
|
fData = source;
|
||||||
|
|
||||||
// No need to do additional buffering if we have
|
// No need to do additional buffering if we have
|
||||||
// a BBufferIO or a BMediaIO.
|
// a BBufferIO or a BMediaIO.
|
||||||
@@ -40,40 +46,29 @@ public:
|
|||||||
// Source needs to be at least a BPositionIO to wrap with a BBufferIO
|
// Source needs to be at least a BPositionIO to wrap with a BBufferIO
|
||||||
if (fPosition != NULL) {
|
if (fPosition != NULL) {
|
||||||
fPosition = new(std::nothrow) BBufferIO(fPosition, 65536, true);
|
fPosition = new(std::nothrow) BBufferIO(fPosition, 65536, true);
|
||||||
// We have to reset our BDataIO reference
|
|
||||||
fData = dynamic_cast<BDataIO*>(fPosition);
|
|
||||||
if (fPosition == NULL) {
|
if (fPosition == NULL) {
|
||||||
fErr = B_NO_MEMORY;
|
fErr = B_NO_MEMORY;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// We have to reset our BDataIO reference too
|
||||||
|
fData = dynamic_cast<BDataIO*>(fPosition);
|
||||||
} else {
|
} else {
|
||||||
TRACE("Unable to improve performance with a BufferIO\n");
|
|
||||||
// TODO: fallback buffering
|
// TODO: fallback buffering
|
||||||
|
// In this case we have to supply our own form
|
||||||
|
// of pseudo-seekable object from a non-seekable
|
||||||
|
// BDataIO.
|
||||||
|
fFallbackBuffer = new BMallocIO();
|
||||||
|
fFallbackBuffer->SetBlockSize(BLOCK_SIZE);
|
||||||
|
TRACE("Unable to improve performance with a BufferIO\n");
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
fData = source;
|
|
||||||
}
|
}
|
||||||
fFile = dynamic_cast<BFile*>(source);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~BMediaIOWrapper()
|
virtual ~BMediaIOWrapper()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ssize_t Read(void* buffer, size_t size)
|
// BPositionIO interface
|
||||||
{
|
|
||||||
return fData->Read(buffer, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ssize_t Write(const void* buffer, size_t size)
|
|
||||||
{
|
|
||||||
return fData->Write(buffer, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual status_t Flush()
|
|
||||||
{
|
|
||||||
return fData->Flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ssize_t ReadAt(off_t position, void* buffer,
|
virtual ssize_t ReadAt(off_t position, void* buffer,
|
||||||
size_t size)
|
size_t size)
|
||||||
@@ -81,9 +76,22 @@ public:
|
|||||||
if (IsSeekable())
|
if (IsSeekable())
|
||||||
return fPosition->ReadAt(position, buffer, size);
|
return fPosition->ReadAt(position, buffer, size);
|
||||||
|
|
||||||
// if (IsCached()) {
|
if (IsEndless()) {
|
||||||
//
|
off_t nextPos = position+size;
|
||||||
// }
|
off_t bufSize = 0;
|
||||||
|
fFallbackBuffer->GetSize(&bufSize);
|
||||||
|
|
||||||
|
if (fFallbackPosition == position
|
||||||
|
&& nextPos > bufSize) {
|
||||||
|
fData->Read(buffer, size);
|
||||||
|
fFallbackBuffer->WriteAt(fFallbackPosition, buffer, size);
|
||||||
|
fFallbackPosition = nextPos;
|
||||||
|
return size;
|
||||||
|
} else if (nextPos <= bufSize) {
|
||||||
|
fFallbackPosition = nextPos;
|
||||||
|
return fFallbackBuffer->ReadAt(position, buffer, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return B_NOT_SUPPORTED;
|
return B_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
@@ -94,6 +102,11 @@ public:
|
|||||||
if (IsSeekable())
|
if (IsSeekable())
|
||||||
return fPosition->WriteAt(position, buffer, size);
|
return fPosition->WriteAt(position, buffer, size);
|
||||||
|
|
||||||
|
if (IsEndless() && position == fFallbackPosition) {
|
||||||
|
fData->Write(buffer, size);
|
||||||
|
fFallbackPosition = position+size;
|
||||||
|
}
|
||||||
|
|
||||||
return B_NOT_SUPPORTED;
|
return B_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,32 +115,34 @@ public:
|
|||||||
if (IsSeekable())
|
if (IsSeekable())
|
||||||
return fPosition->Seek(position, seekMode);
|
return fPosition->Seek(position, seekMode);
|
||||||
|
|
||||||
// if (IsCached()) {
|
if (IsEndless())
|
||||||
//
|
return fFallbackBuffer->Seek(position, seekMode);
|
||||||
// }
|
|
||||||
|
|
||||||
return B_NOT_SUPPORTED;
|
return B_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual off_t Position() const
|
virtual off_t Position() const
|
||||||
{
|
{
|
||||||
if (!IsEndless())
|
if (IsSeekable())
|
||||||
return fPosition->Position();
|
return fPosition->Position();
|
||||||
|
|
||||||
// TODO: buffering
|
if (IsEndless())
|
||||||
|
return fFallbackBuffer->Position();
|
||||||
|
|
||||||
return 0;
|
return B_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual status_t SetSize(off_t size)
|
virtual status_t SetSize(off_t size)
|
||||||
{
|
{
|
||||||
if (IsEndless())
|
if (IsEndless())
|
||||||
return B_NOT_SUPPORTED;
|
return B_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
// TODO: What a non seekable stream should do here?
|
||||||
|
|
||||||
return fPosition->SetSize(size);
|
return fPosition->SetSize(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual status_t GetSize(off_t* size) const
|
virtual status_t GetSize(off_t* size) const
|
||||||
{
|
{
|
||||||
if (IsEndless())
|
if (IsEndless())
|
||||||
return B_NOT_SUPPORTED;
|
return B_NOT_SUPPORTED;
|
||||||
@@ -135,6 +150,8 @@ public:
|
|||||||
return fPosition->GetSize(size);
|
return fPosition->GetSize(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BMediaIO interface
|
||||||
|
|
||||||
virtual bool IsSeekable() const
|
virtual bool IsSeekable() const
|
||||||
{
|
{
|
||||||
if (IsMedia())
|
if (IsMedia())
|
||||||
@@ -152,26 +169,14 @@ public:
|
|||||||
{
|
{
|
||||||
if (IsMedia())
|
if (IsMedia())
|
||||||
return fMedia->IsEndless();
|
return fMedia->IsEndless();
|
||||||
|
|
||||||
if (IsPosition())
|
if (IsPosition())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool IsCached() const
|
// Utility methods
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual size_t CacheSize() const
|
|
||||||
{
|
|
||||||
// TODO: it should be another buffering level
|
|
||||||
// but we might to optimize with the underlying level
|
|
||||||
//if (IsMedia() && IsCached())
|
|
||||||
// return CacheSize();
|
|
||||||
|
|
||||||
return B_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t InitCheck() const
|
status_t InitCheck() const
|
||||||
{
|
{
|
||||||
@@ -179,11 +184,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Utility methods
|
|
||||||
bool IsData() const
|
|
||||||
{
|
|
||||||
return fData != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsPosition() const
|
bool IsPosition() const
|
||||||
{
|
{
|
||||||
@@ -201,6 +201,8 @@ private:
|
|||||||
BMediaIO* fMedia;
|
BMediaIO* fMedia;
|
||||||
BFile* fFile;
|
BFile* fFile;
|
||||||
|
|
||||||
|
BMallocIO* fFallbackBuffer;
|
||||||
|
off_t fFallbackPosition;
|
||||||
status_t fErr;
|
status_t fErr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user