Resolved TODOs in PluginManager about leaking plugins when they are no longer
needed. I've added MediaPlugin* fields to Reader and Decoder plugin classes which are set when the PluginManager hands out new instances. This way the manager knows what plugin created the Decoder or Reader instance in the Destroy*() methods and can decrease the reference count accordingly. Also added some FBC stuffing to Decoder and Reader. All media plugins need to be recompiled, in case anyone has some outside the Haiku tree. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30984 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
5fa2230d99
commit
bb56a763a6
@ -9,53 +9,75 @@ class AddOnManager;
|
||||
|
||||
namespace BPrivate { namespace media {
|
||||
|
||||
class PluginManager;
|
||||
|
||||
class ChunkProvider {
|
||||
public:
|
||||
virtual ~ChunkProvider() {};
|
||||
virtual status_t GetNextChunk(const void **chunkBuffer, size_t *chunkSize,
|
||||
media_header *mediaHeader) = 0;
|
||||
virtual ~ChunkProvider() {};
|
||||
virtual status_t GetNextChunk(const void** chunkBuffer,
|
||||
size_t* chunkSize,
|
||||
media_header* mediaHeader) = 0;
|
||||
};
|
||||
|
||||
class Decoder
|
||||
{
|
||||
class Decoder {
|
||||
public:
|
||||
Decoder();
|
||||
virtual ~Decoder();
|
||||
Decoder();
|
||||
virtual ~Decoder();
|
||||
|
||||
virtual void GetCodecInfo(media_codec_info *codecInfo) = 0;
|
||||
virtual void GetCodecInfo(media_codec_info* codecInfo) = 0;
|
||||
|
||||
// Setup get's called with the info data from Reader::GetStreamInfo
|
||||
virtual status_t Setup(media_format *ioEncodedFormat, const void *infoBuffer, size_t infoSize) = 0;
|
||||
// Setup get's called with the info data from Reader::GetStreamInfo
|
||||
virtual status_t Setup(media_format* ioEncodedFormat,
|
||||
const void* infoBuffer,
|
||||
size_t infoSize) = 0;
|
||||
|
||||
virtual status_t NegotiateOutputFormat(media_format *ioDecodedFormat) = 0;
|
||||
virtual status_t NegotiateOutputFormat(
|
||||
media_format* ioDecodedFormat) = 0;
|
||||
|
||||
virtual status_t Seek(uint32 seekTo,
|
||||
int64 seekFrame, int64 *frame,
|
||||
bigtime_t seekTime, bigtime_t *time) = 0;
|
||||
virtual status_t Seek(uint32 seekTo, int64 seekFrame,
|
||||
int64* frame, bigtime_t seekTime,
|
||||
bigtime_t* time) = 0;
|
||||
|
||||
virtual status_t Decode(void *buffer, int64 *frameCount,
|
||||
media_header *mediaHeader, media_decode_info *info = 0) = 0;
|
||||
virtual status_t Decode(void* buffer, int64* frameCount,
|
||||
media_header* mediaHeader,
|
||||
media_decode_info* info = 0) = 0;
|
||||
|
||||
status_t GetNextChunk(const void **chunkBuffer, size_t *chunkSize,
|
||||
media_header *mediaHeader);
|
||||
status_t GetNextChunk(const void** chunkBuffer,
|
||||
size_t* chunkSize,
|
||||
media_header* mediaHeader);
|
||||
|
||||
void SetChunkProvider(ChunkProvider* provider);
|
||||
|
||||
virtual status_t Perform(perform_code code, void* data);
|
||||
|
||||
void SetChunkProvider(ChunkProvider *provider);
|
||||
private:
|
||||
ChunkProvider * fChunkProvider;
|
||||
virtual void _ReservedDecoder1();
|
||||
virtual void _ReservedDecoder2();
|
||||
virtual void _ReservedDecoder3();
|
||||
virtual void _ReservedDecoder4();
|
||||
virtual void _ReservedDecoder5();
|
||||
|
||||
ChunkProvider* fChunkProvider;
|
||||
|
||||
// needed for plug-in reference count management
|
||||
friend class PluginManager;
|
||||
MediaPlugin* fMediaPlugin;
|
||||
|
||||
uint32 fReserved[5];
|
||||
};
|
||||
|
||||
|
||||
class DecoderPlugin : public virtual MediaPlugin
|
||||
{
|
||||
public:
|
||||
DecoderPlugin();
|
||||
class DecoderPlugin : public virtual MediaPlugin {
|
||||
public:
|
||||
DecoderPlugin();
|
||||
|
||||
virtual Decoder *NewDecoder(uint index) = 0;
|
||||
virtual status_t GetSupportedFormats(media_format ** formats, size_t * count) = 0;
|
||||
virtual Decoder* NewDecoder(uint index) = 0;
|
||||
virtual status_t GetSupportedFormats(media_format** formats,
|
||||
size_t * count) = 0;
|
||||
};
|
||||
|
||||
} } // namespace BPrivate::media
|
||||
|
||||
using namespace BPrivate::media;
|
||||
|
||||
#endif
|
||||
#endif // _DECODER_PLUGIN_H
|
||||
|
@ -36,6 +36,15 @@ private:
|
||||
int usecount;
|
||||
MediaPlugin *plugin;
|
||||
image_id image;
|
||||
|
||||
plugin_info& operator=(const plugin_info& other)
|
||||
{
|
||||
strcpy(name, other.name);
|
||||
usecount = other.usecount;
|
||||
plugin = other.plugin;
|
||||
image = other.image;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
List<plugin_info> *fPluginList;
|
||||
|
@ -6,6 +6,8 @@
|
||||
|
||||
namespace BPrivate { namespace media {
|
||||
|
||||
class PluginManager;
|
||||
|
||||
enum {
|
||||
B_MEDIA_SEEK_TO_TIME = 0x10000,
|
||||
B_MEDIA_SEEK_TO_FRAME = 0x20000
|
||||
@ -41,12 +43,26 @@ public:
|
||||
media_header* mediaHeader) = 0;
|
||||
|
||||
BDataIO* Source() const;
|
||||
|
||||
|
||||
virtual status_t Perform(perform_code code, void* data);
|
||||
|
||||
private:
|
||||
virtual void _ReservedReader1();
|
||||
virtual void _ReservedReader2();
|
||||
virtual void _ReservedReader3();
|
||||
virtual void _ReservedReader4();
|
||||
virtual void _ReservedReader5();
|
||||
|
||||
public: // XXX for test programs only
|
||||
void Setup(BDataIO* source);
|
||||
|
||||
BDataIO* fSource;
|
||||
|
||||
// needed for plug-in reference count management
|
||||
friend class PluginManager;
|
||||
MediaPlugin* fMediaPlugin;
|
||||
|
||||
uint32 fReserved[5];
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,18 +1,20 @@
|
||||
/*
|
||||
** Copyright 2004, Marcus Overhagen. All rights reserved.
|
||||
** Distributed under the terms of the OpenBeOS License.
|
||||
*/
|
||||
|
||||
* Copyright 2004, Marcus Overhagen. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include "DecoderPlugin.h"
|
||||
|
||||
#include <MediaFormats.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <MediaFormats.h>
|
||||
|
||||
|
||||
Decoder::Decoder()
|
||||
: fChunkProvider(NULL)
|
||||
:
|
||||
fChunkProvider(NULL),
|
||||
fMediaPlugin(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
@ -39,6 +41,18 @@ Decoder::SetChunkProvider(ChunkProvider *provider)
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Decoder::Perform(perform_code code, void* _data)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
void Decoder::_ReservedDecoder1() {}
|
||||
void Decoder::_ReservedDecoder2() {}
|
||||
void Decoder::_ReservedDecoder3() {}
|
||||
void Decoder::_ReservedDecoder4() {}
|
||||
void Decoder::_ReservedDecoder5() {}
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
|
@ -49,7 +49,7 @@ PluginManager::CreateReader(Reader **reader, int32 *streamCount,
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
ReaderPlugin *readerPlugin = dynamic_cast<ReaderPlugin *>(plugin);
|
||||
ReaderPlugin *readerPlugin = dynamic_cast<ReaderPlugin*>(plugin);
|
||||
if (!readerPlugin) {
|
||||
printf("PluginManager::CreateReader: dynamic_cast failed\n");
|
||||
PutPlugin(plugin);
|
||||
@ -57,7 +57,7 @@ PluginManager::CreateReader(Reader **reader, int32 *streamCount,
|
||||
}
|
||||
|
||||
*reader = readerPlugin->NewReader();
|
||||
if (! *reader) {
|
||||
if (*reader == NULL) {
|
||||
printf("PluginManager::CreateReader: NewReader failed\n");
|
||||
PutPlugin(plugin);
|
||||
return B_ERROR;
|
||||
@ -65,6 +65,7 @@ PluginManager::CreateReader(Reader **reader, int32 *streamCount,
|
||||
|
||||
seekable_source->Seek(0, SEEK_SET);
|
||||
(*reader)->Setup(seekable_source);
|
||||
(*reader)->fMediaPlugin = plugin;
|
||||
|
||||
if ((*reader)->Sniff(streamCount) == B_OK) {
|
||||
TRACE("PluginManager::CreateReader: Sniff success "
|
||||
@ -73,9 +74,7 @@ PluginManager::CreateReader(Reader **reader, int32 *streamCount,
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// _DestroyReader(*reader);
|
||||
delete *reader;
|
||||
PutPlugin(plugin);
|
||||
DestroyReader(*reader);
|
||||
}
|
||||
|
||||
TRACE("PluginManager::CreateReader leave\n");
|
||||
@ -84,10 +83,18 @@ PluginManager::CreateReader(Reader **reader, int32 *streamCount,
|
||||
|
||||
|
||||
void
|
||||
PluginManager::DestroyReader(Reader *reader)
|
||||
PluginManager::DestroyReader(Reader* reader)
|
||||
{
|
||||
// ToDo: must call put plugin
|
||||
delete reader;
|
||||
if (reader != NULL) {
|
||||
TRACE("PluginManager::DestroyReader(%p (plugin: %p))\n", reader,
|
||||
reader->fMediaPlugin);
|
||||
// NOTE: We have to put the plug-in after deleting the reader,
|
||||
// since otherwise we may actually unload the code for the
|
||||
// destructor...
|
||||
MediaPlugin* plugin = reader->fMediaPlugin;
|
||||
delete reader;
|
||||
PutPlugin(plugin);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -108,7 +115,7 @@ PluginManager::CreateDecoder(Decoder **_decoder, const media_format &format)
|
||||
return ret;
|
||||
}
|
||||
|
||||
MediaPlugin *plugin = GetPlugin(reply.ref);
|
||||
MediaPlugin* plugin = GetPlugin(reply.ref);
|
||||
if (!plugin) {
|
||||
printf("PluginManager::CreateDecoder: GetPlugin failed\n");
|
||||
return B_ERROR;
|
||||
@ -127,6 +134,8 @@ PluginManager::CreateDecoder(Decoder **_decoder, const media_format &format)
|
||||
PutPlugin(plugin);
|
||||
return B_ERROR;
|
||||
}
|
||||
TRACE(" created decoder: %p\n", *_decoder);
|
||||
(*_decoder)->fMediaPlugin = plugin;
|
||||
|
||||
TRACE("PluginManager::CreateDecoder leave\n");
|
||||
|
||||
@ -161,8 +170,16 @@ PluginManager::GetDecoderInfo(Decoder *decoder,
|
||||
void
|
||||
PluginManager::DestroyDecoder(Decoder *decoder)
|
||||
{
|
||||
// ToDo: must call put plugin
|
||||
delete decoder;
|
||||
if (decoder != NULL) {
|
||||
TRACE("PluginManager::DestroyDecoder(%p, plugin: %p)\n", decoder,
|
||||
decoder->fMediaPlugin);
|
||||
// NOTE: We have to put the plug-in after deleting the decoder,
|
||||
// since otherwise we may actually unload the code for the
|
||||
// destructor...
|
||||
MediaPlugin* plugin = decoder->fMediaPlugin;
|
||||
delete decoder;
|
||||
PutPlugin(plugin);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -180,14 +197,13 @@ PluginManager::PluginManager()
|
||||
PluginManager::~PluginManager()
|
||||
{
|
||||
CALLED();
|
||||
while (!fPluginList->IsEmpty()) {
|
||||
for (int i = fPluginList->CountItems() - 1; i >= 0; i--) {
|
||||
plugin_info *info = NULL;
|
||||
fPluginList->Get(fPluginList->CountItems() - 1, &info);
|
||||
fPluginList->Get(i, &info);
|
||||
printf("PluginManager: Error, unloading PlugIn %s with usecount "
|
||||
"%d\n", info->name, info->usecount);
|
||||
delete info->plugin;
|
||||
unload_add_on(info->image);
|
||||
fPluginList->Remove(fPluginList->CountItems() - 1);
|
||||
}
|
||||
delete fLocker;
|
||||
}
|
||||
@ -196,6 +212,7 @@ PluginManager::~PluginManager()
|
||||
MediaPlugin *
|
||||
PluginManager::GetPlugin(const entry_ref &ref)
|
||||
{
|
||||
TRACE("PluginManager::GetPlugin(%s)\n", ref.name);
|
||||
fLocker->Lock();
|
||||
|
||||
MediaPlugin *plugin;
|
||||
@ -206,6 +223,7 @@ PluginManager::GetPlugin(const entry_ref &ref)
|
||||
if (0 == strcmp(ref.name, pinfo->name)) {
|
||||
plugin = pinfo->plugin;
|
||||
pinfo->usecount++;
|
||||
TRACE(" found existing plugin: %p\n", pinfo->plugin);
|
||||
fLocker->Unlock();
|
||||
return plugin;
|
||||
}
|
||||
@ -224,6 +242,7 @@ PluginManager::GetPlugin(const entry_ref &ref)
|
||||
TRACE("PluginManager: PlugIn %s loaded\n", ref.name);
|
||||
|
||||
plugin = info.plugin;
|
||||
TRACE(" loaded plugin: %p\n", plugin);
|
||||
|
||||
fLocker->Unlock();
|
||||
return plugin;
|
||||
@ -231,8 +250,9 @@ PluginManager::GetPlugin(const entry_ref &ref)
|
||||
|
||||
|
||||
void
|
||||
PluginManager::PutPlugin(MediaPlugin *plugin)
|
||||
PluginManager::PutPlugin(MediaPlugin* plugin)
|
||||
{
|
||||
TRACE("PluginManager::PutPlugin()\n");
|
||||
fLocker->Lock();
|
||||
|
||||
plugin_info *pinfo;
|
||||
@ -241,7 +261,9 @@ PluginManager::PutPlugin(MediaPlugin *plugin)
|
||||
if (plugin == pinfo->plugin) {
|
||||
pinfo->usecount--;
|
||||
if (pinfo->usecount == 0) {
|
||||
TRACE(" deleting %p\n", pinfo->plugin);
|
||||
delete pinfo->plugin;
|
||||
TRACE(" unloading add-on: %ld\n\n", pinfo->image);
|
||||
unload_add_on(pinfo->image);
|
||||
fPluginList->RemoveCurrent();
|
||||
}
|
||||
@ -266,6 +288,7 @@ PluginManager::LoadPlugin(const entry_ref &ref, MediaPlugin **plugin,
|
||||
|
||||
image_id id;
|
||||
id = load_add_on(p.Path());
|
||||
TRACE(" loaded add-on: %ld\n", id);
|
||||
if (id < 0)
|
||||
return B_ERROR;
|
||||
|
||||
|
@ -1,8 +1,17 @@
|
||||
/*
|
||||
* Copyright 2004, Marcus Overhagen. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include "ReaderPlugin.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
Reader::Reader()
|
||||
: fSource(0)
|
||||
:
|
||||
fSource(0),
|
||||
fMediaPlugin(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
@ -38,3 +47,17 @@ Reader::Setup(BDataIO *source)
|
||||
{
|
||||
fSource = source;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Reader::Perform(perform_code code, void* _data)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
void Reader::_ReservedReader1() {}
|
||||
void Reader::_ReservedReader2() {}
|
||||
void Reader::_ReservedReader3() {}
|
||||
void Reader::_ReservedReader4() {}
|
||||
void Reader::_ReservedReader5() {}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user