update to the codec api, docoder assignment is now handled in the server

multiple reader add-ons are probed to recognize a media file
FormatManager does the translation from media_format to media_description


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5667 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
beveloper 2003-12-14 19:23:16 +00:00
parent 6d59046016
commit 046f31f91f
16 changed files with 757 additions and 127 deletions

View File

@ -599,6 +599,7 @@ typedef enum {
B_WAV_FORMAT_FAMILY = 6, B_WAV_FORMAT_FAMILY = 6,
B_AIFF_FORMAT_FAMILY = 7, B_AIFF_FORMAT_FAMILY = 7,
B_AVR_FORMAT_FAMILY = 8, B_AVR_FORMAT_FAMILY = 8,
B_OGG_FORMAT_FAMILY = 9,
B_MISC_FORMAT_FAMILY = 99999, B_MISC_FORMAT_FAMILY = 99999,
B_META_FORMAT_FAMILY = 100000 B_META_FORMAT_FAMILY = 100000
} media_format_family; } media_format_family;

View File

@ -106,7 +106,9 @@ enum {
SERVER_REMOVEREFFOR, SERVER_REMOVEREFFOR,
SERVER_REMOVEITEM, SERVER_REMOVEITEM,
SERVER_GET_FORMAT_FOR_DESCRIPTION, SERVER_GET_FORMAT_FOR_DESCRIPTION,
SERVER_GET_META_DESCRIPTION_FOR_FORMAT, SERVER_GET_DESCRIPTION_FOR_FORMAT,
SERVER_GET_READERS,
SERVER_GET_DECODER_FOR_FORMAT,
SERVER_MESSAGE_END, SERVER_MESSAGE_END,
NODE_MESSAGE_START = 0x200, NODE_MESSAGE_START = 0x200,
@ -206,7 +208,7 @@ public:
private: private:
dev_t device; dev_t device;
ino_t directory; ino_t directory;
char name[B_FILE_NAME_LENGTH]; char name[B_FILE_NAME_LENGTH]; // == 256 bytes
}; };
@ -243,6 +245,12 @@ enum
MAX_NODE_ID = 4000, MAX_NODE_ID = 4000,
}; };
// used by SERVER_GET_READERS
enum
{
MAX_READERS = 40,
};
struct addonserver_instantiate_dormant_node_request : public request_data struct addonserver_instantiate_dormant_node_request : public request_data
{ {
media_addon_id addonid; media_addon_id addonid;
@ -889,14 +897,35 @@ struct server_get_format_for_description_reply : public reply_data
media_format format; media_format format;
}; };
struct server_get_meta_description_for_format_request : public request_data struct server_get_description_for_format_request : public request_data
{
media_format format;
media_format_family family;
};
struct server_get_description_for_format_reply : public reply_data
{
media_format_description description;
};
struct server_get_decoder_for_format_request : public request_data
{ {
media_format format; media_format format;
}; };
struct server_get_meta_description_for_format_reply : public reply_data struct server_get_decoder_for_format_reply : public reply_data
{ {
media_format_description description; xfer_entry_ref ref; // a ref to the decoder
};
struct server_get_readers_request : public request_data
{
};
struct server_get_readers_reply : public reply_data
{
xfer_entry_ref ref[MAX_READERS]; // a list of refs to the reader
int32 count;
}; };
struct node_request_completed_command : public command_data struct node_request_completed_command : public command_data

View File

@ -6,6 +6,8 @@
#include "MediaPlugin.h" #include "MediaPlugin.h"
#include "MediaExtractor.h" #include "MediaExtractor.h"
class AddOnManager;
namespace BPrivate { namespace media { namespace BPrivate { namespace media {
class Decoder class Decoder
@ -41,11 +43,19 @@ private:
class DecoderPlugin : public MediaPlugin class DecoderPlugin : public MediaPlugin
{ {
public: public:
DecoderPlugin(); DecoderPlugin();
virtual Decoder *NewDecoder() = 0; virtual Decoder * NewDecoder() = 0;
status_t PublishDecoder(const char *meta_description, const char *short_name, const char *pretty_name, const char *default_mapping = 0); status_t PublishDecoder(const char *meta_description,
const char *short_name,
const char *pretty_name,
const char *default_mapping = 0);
private:
friend class AddOnManager;
void Setup(void *publish_hook);
void * fPublishHook;
}; };
} } // namespace BPrivate::media } } // namespace BPrivate::media

View File

@ -24,11 +24,11 @@ public:
PluginManager(); PluginManager();
~PluginManager(); ~PluginManager();
MediaPlugin * GetPlugin(const char *name); MediaPlugin * GetPlugin(const entry_ref &ref);
void PutPlugin(MediaPlugin *plugin); void PutPlugin(MediaPlugin *plugin);
private: private:
bool LoadPlugin(const char *name, MediaPlugin **plugin, image_id *image); bool LoadPlugin(const entry_ref &ref, MediaPlugin **plugin, image_id *image);
struct plugin_info struct plugin_info
{ {

View File

@ -154,7 +154,7 @@ mp3Reader::Sniff(int32 *streamCount)
TRACE("mp3Reader::Sniff: file size is %Ld bytes\n", fFileSize); TRACE("mp3Reader::Sniff: file size is %Ld bytes\n", fFileSize);
if (!IsMp3File()) { if (!IsMp3File()) {
TRACE("mp3Reader::Sniff: non recognized as mp3 file\n"); TRACE("mp3Reader::Sniff: not recognized as mp3 file\n");
return B_ERROR; return B_ERROR;
} }
@ -903,7 +903,7 @@ mp3Reader::GetFrameLength(void *header)
int bitrate_index = (h[2] >> 4) & 0x0f; int bitrate_index = (h[2] >> 4) & 0x0f;
int sampling_rate_index = (h[2] >> 2) & 0x03; int sampling_rate_index = (h[2] >> 2) & 0x03;
int padding = (h[2] >> 1) & 0x01; int padding = (h[2] >> 1) & 0x01;
/* no interested in the other bits */ /* not interested in the other bits */
int bitrate = bit_rate_table[mpeg_version_index][layer_index][bitrate_index]; int bitrate = bit_rate_table[mpeg_version_index][layer_index][bitrate_index];
int framerate = frame_rate_table[mpeg_version_index][sampling_rate_index]; int framerate = frame_rate_table[mpeg_version_index][sampling_rate_index];

View File

@ -27,14 +27,25 @@ Decoder::Setup(MediaExtractor *extractor, int32 stream)
} }
DecoderPlugin::DecoderPlugin() DecoderPlugin::DecoderPlugin()
: fPublishHook(0)
{ {
} }
typedef status_t (*publish_func)(DecoderPlugin *, const char *, const char *, const char *, const char *);
status_t status_t
DecoderPlugin::PublishDecoder(const char *meta_description, DecoderPlugin::PublishDecoder(const char *meta_description,
const char *short_name, const char *short_name,
const char *pretty_name, const char *pretty_name,
const char *default_mapping /* = 0 */) const char *default_mapping /* = 0 */)
{ {
return _PublishDecoder(this, meta_description, short_name, pretty_name, default_mapping); if (fPublishHook)
return ((publish_func)fPublishHook)(this, meta_description, short_name, pretty_name, default_mapping);
return B_ERROR;
}
void
DecoderPlugin::Setup(void *publish_hook)
{
fPublishHook = publish_hook;
} }

View File

@ -172,8 +172,14 @@ BMediaFormats::GetCodeFor(const media_format & format,
media_format_family family, media_format_family family,
media_format_description * out_description) media_format_description * out_description)
{ {
UNIMPLEMENTED(); server_get_description_for_format_request request;
return B_ERROR; server_get_description_for_format_reply reply;
request.format = format;
request.family = family;
if (B_OK != QueryServer(SERVER_GET_DESCRIPTION_FOR_FORMAT, &request, sizeof(request), &reply, sizeof(reply)))
return B_ERROR;
*out_description = reply.description;
return B_OK;
} }
@ -246,6 +252,8 @@ bool operator==(const media_format_description & a, const media_format_descripti
return a.u.aiff.codec == b.u.aiff.codec; return a.u.aiff.codec == b.u.aiff.codec;
case B_AVR_FORMAT_FAMILY: case B_AVR_FORMAT_FAMILY:
return a.u.avr.id == b.u.avr.id; return a.u.avr.id == b.u.avr.id;
case B_OGG_FORMAT_FAMILY:
return false; // XXX fix this
case B_MISC_FORMAT_FAMILY: case B_MISC_FORMAT_FAMILY:
return a.u.misc.file_format == b.u.misc.file_format && a.u.misc.codec == b.u.misc.codec; return a.u.misc.file_format == b.u.misc.file_format && a.u.misc.codec == b.u.misc.codec;
case B_META_FORMAT_FAMILY: case B_META_FORMAT_FAMILY:
@ -276,6 +284,8 @@ bool operator<(const media_format_description & a, const media_format_descriptio
return a.u.aiff.codec < b.u.aiff.codec; return a.u.aiff.codec < b.u.aiff.codec;
case B_AVR_FORMAT_FAMILY: case B_AVR_FORMAT_FAMILY:
return a.u.avr.id < b.u.avr.id; return a.u.avr.id < b.u.avr.id;
case B_OGG_FORMAT_FAMILY:
return false; // XXX fix this
case B_MISC_FORMAT_FAMILY: case B_MISC_FORMAT_FAMILY:
return a.u.misc.file_format < b.u.misc.file_format || a.u.misc.codec < b.u.misc.codec; return a.u.misc.file_format < b.u.misc.file_format || a.u.misc.codec < b.u.misc.codec;
case B_META_FORMAT_FAMILY: case B_META_FORMAT_FAMILY:
@ -303,14 +313,8 @@ _get_format_for_description(media_format *out_format, const media_format_descrip
request.description = in_desc; request.description = in_desc;
// if (B_OK != QueryServer(SERVER_GET_FORMAT_FOR_DESCRIPTION, &request, sizeof(request), &reply, sizeof(reply))) if (B_OK != QueryServer(SERVER_GET_FORMAT_FOR_DESCRIPTION, &request, sizeof(request), &reply, sizeof(reply)))
// return B_ERROR; return B_ERROR;
if (in_desc.family == B_BEOS_FORMAT_FAMILY && in_desc.u.beos.format == B_BEOS_FORMAT_RAW_AUDIO)
reply.format.type = B_MEDIA_RAW_AUDIO;
else
reply.format.type = B_MEDIA_ENCODED_AUDIO;
reply.format.u.encoded_audio.encoding = (enum media_encoded_audio_format::audio_encoding) 1;
*out_format = reply.format; *out_format = reply.format;
return B_OK; return B_OK;
@ -319,13 +323,14 @@ _get_format_for_description(media_format *out_format, const media_format_descrip
status_t status_t
_get_meta_description_for_format(media_format_description *out_desc, const media_format &in_format) _get_meta_description_for_format(media_format_description *out_desc, const media_format &in_format)
{ {
server_get_meta_description_for_format_request request; server_get_description_for_format_request request;
server_get_meta_description_for_format_reply reply; server_get_description_for_format_reply reply;
request.format = in_format; request.format = in_format;
request.family = B_META_FORMAT_FAMILY;
// if (B_OK != QueryServer(SERVER_GET_META_DESCRIPTION_FOR_FORMAT, &request, sizeof(request), &reply, sizeof(reply))) if (B_OK != QueryServer(SERVER_GET_DESCRIPTION_FOR_FORMAT, &request, sizeof(request), &reply, sizeof(reply)))
// return B_ERROR; return B_ERROR;
*out_desc = reply.description; *out_desc = reply.description;
return B_OK; return B_OK;

View File

@ -3,6 +3,7 @@
#include <string.h> #include <string.h>
#include "PluginManager.h" #include "PluginManager.h"
#include "DataExchange.h"
#include "debug.h" #include "debug.h"
PluginManager _plugin_manager; PluginManager _plugin_manager;
@ -12,41 +13,50 @@ _CreateReader(Reader **reader, int32 *streamCount, media_file_format *mff, BData
{ {
printf("_CreateReader enter\n"); printf("_CreateReader enter\n");
MediaPlugin *plugin; // get list of available readers from, the server
ReaderPlugin *readerplugin; server_get_readers_request request;
server_get_readers_reply reply;
plugin = _plugin_manager.GetPlugin("mp3_reader"); if (B_OK != QueryServer(SERVER_GET_READERS, &request, sizeof(request), &reply, sizeof(reply))) {
if (!plugin) { printf("_CreateReader: can't get list of readers\n");
printf("_CreateReader: GetPlugin failed\n");
return B_ERROR; return B_ERROR;
} }
readerplugin = dynamic_cast<ReaderPlugin *>(plugin); // try each reader by calling it's Sniff function...
if (!readerplugin) { for (int32 i = 0; i < reply.count; i++) {
printf("_CreateReader: dynamic_cast failed\n"); entry_ref ref = reply.ref[i];
return B_ERROR; MediaPlugin *plugin = _plugin_manager.GetPlugin(ref);
} if (!plugin) {
printf("_CreateReader: GetPlugin failed\n");
return B_ERROR;
}
*reader = readerplugin->NewReader(); ReaderPlugin *readerplugin = dynamic_cast<ReaderPlugin *>(plugin);
if (! *reader) { if (!readerplugin) {
printf("_CreateReader: NewReader failed\n"); printf("_CreateReader: dynamic_cast failed\n");
return B_ERROR; return B_ERROR;
} }
(*reader)->Setup(source); *reader = readerplugin->NewReader();
if (! *reader) {
printf("_CreateReader: NewReader failed\n");
return B_ERROR;
}
if (B_OK != (*reader)->Sniff(streamCount)) { (*reader)->Setup(source);
printf("_CreateReader: Sniff failed\n");
_DestroyReader(*reader);
return B_MEDIA_NO_HANDLER;
// return B_ERROR;
}
(*reader)->GetFileFormatInfo(mff); if (B_OK == (*reader)->Sniff(streamCount)) {
printf("_CreateReader: Sniff success\n");
printf("_CreateReader leave\n"); (*reader)->GetFileFormatInfo(mff);
return B_OK;
}
return B_OK; // _DestroyReader(*reader);
delete *reader;
_plugin_manager.PutPlugin(plugin);
}
printf("_CreateReader leave\n");
return B_MEDIA_NO_HANDLER;
} }
status_t status_t
@ -54,10 +64,19 @@ _CreateDecoder(Decoder **decoder, media_codec_info *mci, const media_format *for
{ {
printf("_CreateDecoder enter\n"); printf("_CreateDecoder enter\n");
// get decoder for this format from the server
server_get_decoder_for_format_request request;
server_get_decoder_for_format_reply reply;
request.format = *format;
if (B_OK != QueryServer(SERVER_GET_DECODER_FOR_FORMAT, &request, sizeof(request), &reply, sizeof(reply))) {
printf("_CreateReader: can't get decoder for format\n");
return B_ERROR;
}
MediaPlugin *plugin; MediaPlugin *plugin;
DecoderPlugin *decoderplugin; DecoderPlugin *decoderplugin;
plugin = _plugin_manager.GetPlugin("mp3_decoder"); plugin = _plugin_manager.GetPlugin(reply.ref);
if (!plugin) { if (!plugin) {
printf("_CreateDecoder: GetPlugin failed\n"); printf("_CreateDecoder: GetPlugin failed\n");
return B_ERROR; return B_ERROR;
@ -96,20 +115,6 @@ _DestroyDecoder(Decoder *decoder)
delete decoder; delete decoder;
} }
status_t
_PublishDecoder(DecoderPlugin *decoderplugin,
const char *meta_description,
const char *short_name,
const char *pretty_name,
const char *default_mapping /* = 0 */)
{
printf("_PublishDecoder: meta_description \"%s\", short_name \"%s\", pretty_name \"%s\", default_mapping \"%s\"\n",
meta_description, short_name, pretty_name, default_mapping);
return B_OK;
}
PluginManager::PluginManager() PluginManager::PluginManager()
{ {
@ -135,7 +140,7 @@ PluginManager::~PluginManager()
MediaPlugin * MediaPlugin *
PluginManager::GetPlugin(const char *name) PluginManager::GetPlugin(const entry_ref &ref)
{ {
fLocker->Lock(); fLocker->Lock();
@ -144,7 +149,7 @@ PluginManager::GetPlugin(const char *name)
plugin_info info; plugin_info info;
for (fPluginList->Rewind(); fPluginList->GetNext(&pinfo); ) { for (fPluginList->Rewind(); fPluginList->GetNext(&pinfo); ) {
if (0 == strcmp(name, pinfo->name)) { if (0 == strcmp(ref.name, pinfo->name)) {
plugin = pinfo->plugin; plugin = pinfo->plugin;
pinfo->usecount++; pinfo->usecount++;
fLocker->Unlock(); fLocker->Unlock();
@ -152,17 +157,17 @@ PluginManager::GetPlugin(const char *name)
} }
} }
if (!LoadPlugin(name, &info.plugin, &info.image)) { if (!LoadPlugin(ref, &info.plugin, &info.image)) {
printf("PluginManager: Error, loading PlugIn %s failed\n", name); printf("PluginManager: Error, loading PlugIn %s failed\n", ref.name);
fLocker->Unlock(); fLocker->Unlock();
return 0; return 0;
} }
strcpy(info.name, name); strcpy(info.name, ref.name);
info.usecount = 1; info.usecount = 1;
fPluginList->Insert(info); fPluginList->Insert(info);
printf("PluginManager: PlugIn %s loaded\n", name); printf("PluginManager: PlugIn %s loaded\n", ref.name);
plugin = info.plugin; plugin = info.plugin;
@ -198,46 +203,35 @@ PluginManager::PutPlugin(MediaPlugin *plugin)
bool bool
PluginManager::LoadPlugin(const char *name, MediaPlugin **plugin, image_id *image) PluginManager::LoadPlugin(const entry_ref &ref, MediaPlugin **plugin, image_id *image)
{ {
const char *searchdir[] = { BPath p(&ref);
"/boot/home/config/add-ons/media/plugins",
"/boot/beos/system/add-ons/media/plugins", printf("PluginManager: LoadPlugin trying to load %s\n", p.Path());
"/boot/home/develop/openbeos/current/distro/x86.R1/beos/system/add-ons/media/plugins",
NULL image_id id;
}; id = load_add_on(p.Path());
if (id < 0)
return false;
MediaPlugin *(*instantiate_plugin_func)();
for (int i = 0; searchdir[i]; i++) { if (get_image_symbol(id, "instantiate_plugin", B_SYMBOL_TYPE_TEXT, (void**)&instantiate_plugin_func) < B_OK) {
BPath p(searchdir[i], name); printf("PluginManager: Error, LoadPlugin can't find instantiate_plugin in %s\n", p.Path());
unload_add_on(id);
printf("PluginManager: LoadPlugin trying to load %s\n", p.Path()); return false;
image_id id;
id = load_add_on(p.Path());
if (id < 0)
continue;
MediaPlugin *(*instantiate_plugin_func)();
if (get_image_symbol(id, "instantiate_plugin", B_SYMBOL_TYPE_TEXT, (void**)&instantiate_plugin_func) < B_OK) {
printf("PluginManager: Error, LoadPlugin can't find instantiate_plugin in %s\n", p.Path());
unload_add_on(id);
continue;
}
MediaPlugin *pl;
pl = (*instantiate_plugin_func)();
if (pl == 0) {
printf("PluginManager: Error, LoadPlugin instantiate_plugin in %s returned 0\n", p.Path());
unload_add_on(id);
continue;
}
*plugin = pl;
*image = id;
return true;
} }
return false; MediaPlugin *pl;
pl = (*instantiate_plugin_func)();
if (pl == 0) {
printf("PluginManager: Error, LoadPlugin instantiate_plugin in %s returned 0\n", p.Path());
unload_add_on(id);
return false;
}
*plugin = pl;
*image = id;
return true;
} }

View File

@ -41,7 +41,7 @@ _SoundPlayNode::_SoundPlayNode(const char *name, const media_multi_audio_format
mFormat.u.raw_audio = *format; mFormat.u.raw_audio = *format;
DPRINTF("Format Info:\n"); DPRINTF("Format Info:\n");
DPRINTF(" frame_rate: %f\n",mFormat.u.raw_audio.frame_rate); DPRINTF(" frame_rate: %.1f (%ld)\n", mFormat.u.raw_audio.frame_rate, (int32)mFormat.u.raw_audio.frame_rate);
DPRINTF(" channel_count: %ld\n",mFormat.u.raw_audio.channel_count); DPRINTF(" channel_count: %ld\n",mFormat.u.raw_audio.channel_count);
DPRINTF(" byte_order: %ld (",mFormat.u.raw_audio.byte_order); DPRINTF(" byte_order: %ld (",mFormat.u.raw_audio.byte_order);
switch (mFormat.u.raw_audio.byte_order) { switch (mFormat.u.raw_audio.byte_order) {
@ -366,12 +366,11 @@ _SoundPlayNode::Connect(status_t error, const media_source& source, const media_
TRACE("_SoundPlayNode::Connect: downstream latency = %Ld\n", mLatency); TRACE("_SoundPlayNode::Connect: downstream latency = %Ld\n", mLatency);
// reset our buffer duration, etc. to avoid later calculations // reset our buffer duration, etc. to avoid later calculations
bigtime_t duration = mOutput.format.u.raw_audio.buffer_size * 10000 bigtime_t duration = ((mOutput.format.u.raw_audio.buffer_size * 1000000LL)
/ ( (mOutput.format.u.raw_audio.format & media_raw_audio_format::B_AUDIO_SIZE_MASK) / ((mOutput.format.u.raw_audio.format & media_raw_audio_format::B_AUDIO_SIZE_MASK) * mOutput.format.u.raw_audio.channel_count))
* mOutput.format.u.raw_audio.channel_count) / (int32)mOutput.format.u.raw_audio.frame_rate;
/ ((int32)(mOutput.format.u.raw_audio.frame_rate / 100));
SetBufferDuration(duration); SetBufferDuration(duration);
TRACE("_SoundPlayNode::Connect: buffer duaration is %Ld\n", duration); TRACE("_SoundPlayNode::Connect: buffer duration is %Ld\n", duration);
mInternalLatency = (3 * BufferDuration()) / 4; mInternalLatency = (3 * BufferDuration()) / 4;
TRACE("_SoundPlayNode::Connect: using %Ld as internal latency\n", mInternalLatency); TRACE("_SoundPlayNode::Connect: using %Ld as internal latency\n", mInternalLatency);
@ -614,7 +613,7 @@ _SoundPlayNode::SendNewBuffer(const media_timed_event *event, bigtime_t lateness
// The buffer is on its way; now schedule the next one to go // The buffer is on its way; now schedule the next one to go
// nextEvent is the time at which the buffer should arrive at it's destination // nextEvent is the time at which the buffer should arrive at it's destination
bigtime_t nextEvent = mStartTime + bigtime_t((1000000LL * mFramesSent) / mOutput.format.u.raw_audio.frame_rate); bigtime_t nextEvent = mStartTime + bigtime_t((1000000LL * mFramesSent) / (int32)mOutput.format.u.raw_audio.frame_rate);
media_timed_event nextBufferEvent(nextEvent, SEND_NEW_BUFFER_EVENT); media_timed_event nextBufferEvent(nextEvent, SEND_NEW_BUFFER_EVENT);
EventQueue()->AddEvent(nextBufferEvent); EventQueue()->AddEvent(nextBufferEvent);

View File

@ -0,0 +1,258 @@
#include <MediaFormats.h>
#include <Locker.h>
#include <Path.h>
#include <Entry.h>
#include <Directory.h>
#include <image.h>
#include <stdio.h>
#include <string.h>
#include "AddOnManager.h"
#include "FormatManager.h"
#include "debug.h"
extern FormatManager *gFormatManager;
extern AddOnManager *gAddOnManager;
status_t
_PublishDecoder(DecoderPlugin *decoderplugin,
const char *meta_description,
const char *short_name,
const char *pretty_name,
const char *default_mapping /* = 0 */);
bool operator==(const media_meta_description & a, const media_meta_description & b);
AddOnManager::AddOnManager()
: fLocker(new BLocker),
fReaderList(new List<reader_info>),
fWriterList(new List<writer_info>),
fDecoderList(new List<decoder_info>),
fEncoderList(new List<encoder_info>),
fReaderInfo(0),
fWriterInfo(0),
fDecoderInfo(0),
fEncoderInfo(0)
{
}
AddOnManager::~AddOnManager()
{
delete fLocker;
delete fReaderList;
delete fWriterList;
delete fDecoderList;
delete fEncoderList;
}
void
AddOnManager::LoadState()
{
RegisterAddOns();
}
void
AddOnManager::SaveState()
{
}
status_t
AddOnManager::GetDecoderForFormat(xfer_entry_ref *out_ref,
const media_format &in_format)
{
media_format_description desc;
if (B_OK != gFormatManager->GetDescriptionForFormat(&desc, in_format, B_META_FORMAT_FAMILY)) {
printf("AddOnManager::GetDecoderForFormat: Error, meta format description unknown\n");
return B_ERROR;
}
fLocker->Lock();
decoder_info *info;
for (fDecoderList->Rewind(); fDecoderList->GetNext(&info); ) {
media_meta_description *meta_desc;
for (info->meta_desc.Rewind(); info->meta_desc.GetNext(&meta_desc); ) {
if (desc.u.meta == *meta_desc) {
printf("AddOnManager::GetDecoderForFormat: found decoder %s for format %s\n", info->ref.name, meta_desc->description);
*out_ref = info->ref;
fLocker->Unlock();
return B_OK;
}
}
}
fLocker->Unlock();
return B_ERROR;
}
status_t
AddOnManager::GetReaders(xfer_entry_ref *out_res, int32 *out_count, int32 max_count)
{
fLocker->Lock();
*out_count = 0;
reader_info *info;
for (*out_count = 0, fReaderList->Rewind(); fReaderList->GetNext(&info) && *out_count <= max_count; *out_count += 1)
out_res[*out_count] = info->ref;
fLocker->Unlock();
return B_OK;
}
void
AddOnManager::RegisterAddOns()
{
const char *searchdir[] = {
"/boot/home/config/add-ons/media/plugins",
"/boot/beos/system/add-ons/media/plugins",
"/boot/home/develop/openbeos/current/distro/x86.R1/beos/system/add-ons/media/plugins",
NULL
};
for (int i = 0; searchdir[i]; i++) {
BDirectory dir(searchdir[i]);
BEntry e;
while (B_OK == dir.GetNextEntry(&e)) {
BPath p(&e);
entry_ref ref;
e.GetRef(&ref);
printf("AddOnManager: RegisterAddOns trying to load %s\n", p.Path());
image_id id;
id = load_add_on(p.Path());
if (id < 0)
continue;
MediaPlugin *(*instantiate_plugin_func)();
if (get_image_symbol(id, "instantiate_plugin", B_SYMBOL_TYPE_TEXT, (void**)&instantiate_plugin_func) < B_OK) {
printf("AddOnManager: Error, RegisterAddOns can't find instantiate_plugin in %s\n", p.Path());
unload_add_on(id);
continue;
}
MediaPlugin *pl;
pl = (*instantiate_plugin_func)();
if (pl == 0) {
printf("AddOnManager: Error, RegisterAddOns instantiate_plugin in %s returned 0\n", p.Path());
unload_add_on(id);
continue;
}
ReaderPlugin *rp = dynamic_cast<ReaderPlugin *>(pl);
if (rp)
RegisterReader(rp, ref);
DecoderPlugin *dp = dynamic_cast<DecoderPlugin *>(pl);
if (dp)
RegisterDecoder(dp, ref);
delete pl;
unload_add_on(id);
}
}
}
void
AddOnManager::RegisterReader(ReaderPlugin *reader, const entry_ref &ref)
{
bool already_found;
reader_info *pinfo;
fLocker->Lock();
for (already_found = false, fReaderList->Rewind(); fReaderList->GetNext(&pinfo); )
if (0 == strcmp(pinfo->ref.name, ref.name)) {
already_found = true;
break;
}
fLocker->Unlock();
if (already_found)
return;
printf("AddOnManager::RegisterReader, name %s\n", ref.name);
reader_info info;
info.ref = ref;
if (B_OK != reader->RegisterPlugin())
return;
fLocker->Lock();
fReaderList->Insert(info);
fLocker->Unlock();
}
void
AddOnManager::RegisterDecoder(DecoderPlugin *decoder, const entry_ref &ref)
{
bool already_found;
decoder_info *pinfo;
fLocker->Lock();
for (already_found = false, fDecoderList->Rewind(); fDecoderList->GetNext(&pinfo); )
if (0 == strcmp(pinfo->ref.name, ref.name)) {
already_found = true;
break;
}
fLocker->Unlock();
if (already_found)
return;
printf("AddOnManager::RegisterDecoder, name %s\n", ref.name);
decoder->Setup((void*)&_PublishDecoder);
decoder_info info;
info.ref = ref;
fDecoderInfo = &info;
if (B_OK != decoder->RegisterPlugin())
return;
fLocker->Lock();
fDecoderList->Insert(info);
fLocker->Unlock();
fDecoderInfo = 0;
}
status_t
AddOnManager::PublishDecoderCallback(DecoderPlugin *decoderplugin,
const char *meta_description,
const char *short_name,
const char *pretty_name,
const char *default_mapping /* = 0 */)
{
printf("AddOnManager::PublishDecoderCallback: meta_description \"%s\", short_name \"%s\", pretty_name \"%s\", default_mapping \"%s\"\n",
meta_description, short_name, pretty_name, default_mapping);
media_meta_description meta_desc;
snprintf(meta_desc.description, sizeof(meta_desc), "%s", meta_description);
fDecoderInfo->meta_desc.Insert(meta_desc);
return B_OK;
}
//typedef status_t *(*publish_func)(DecoderPlugin *, const char *, const char *, const char *, const char *);
status_t
_PublishDecoder(DecoderPlugin *decoderplugin,
const char *meta_description,
const char *short_name,
const char *pretty_name,
const char *default_mapping /* = 0 */)
{
return gAddOnManager->PublishDecoderCallback(decoderplugin,
meta_description,
short_name,
pretty_name,
default_mapping);
}
bool
operator==(const media_meta_description & a, const media_meta_description & b)
{
return 0 == strcmp(a.description, b.description);
}

View File

@ -0,0 +1,72 @@
#ifndef _ADD_ON_MANAGER_H
#define _ADD_ON_MANAGER_H
// Manager for codec add-ons (reader, writer, encoder, decoder)
// BMediaAddOn are handled in the NodeManager
#include "TList.h"
#include "ReaderPlugin.h"
#include "DecoderPlugin.h"
#include "DataExchange.h"
class AddOnManager
{
public:
AddOnManager();
~AddOnManager();
void LoadState();
void SaveState();
status_t GetDecoderForFormat(xfer_entry_ref *out_ref,
const media_format &in_format);
status_t GetReaders(xfer_entry_ref *out_res, int32 *out_count, int32 max_count);
status_t PublishDecoderCallback(DecoderPlugin *decoderplugin,
const char *meta_description,
const char *short_name,
const char *pretty_name,
const char *default_mapping /* = 0 */);
private:
void RegisterAddOns();
void RegisterReader(ReaderPlugin *reader, const entry_ref &ref);
void RegisterDecoder(DecoderPlugin *decoder, const entry_ref &ref);
private:
struct reader_info
{
entry_ref ref;
};
struct writer_info
{
entry_ref ref;
};
struct decoder_info
{
entry_ref ref;
List<media_meta_description> meta_desc;
};
struct encoder_info
{
entry_ref ref;
};
BLocker *fLocker;
List<reader_info> *fReaderList;
List<writer_info> *fWriterList;
List<decoder_info> *fDecoderList;
List<encoder_info> *fEncoderList;
reader_info *fReaderInfo;
writer_info *fWriterInfo;
decoder_info *fDecoderInfo;
encoder_info *fEncoderInfo;
};
#endif // _ADD_ON_MANAGER_H

View File

@ -0,0 +1,180 @@
#include <stdio.h>
#include <MediaFormats.h>
#include <string.h>
#include "FormatManager.h"
#include "debug.h"
const char *family_to_string(media_format_family in_family);
const char *string_for_description(const media_format_description &in_description, char *string, size_t length);
FormatManager::FormatManager()
{
}
FormatManager::~FormatManager()
{
}
status_t
FormatManager::GetFormatForDescription(media_format *out_format,
const media_format_description &in_desc)
{
char s[128];
printf("GetFormatForDescription, description: %s\n",
string_for_description(in_desc, s, sizeof(s)));
memset(out_format, 0, sizeof(*out_format));
if (in_desc.family == B_BEOS_FORMAT_FAMILY && in_desc.u.beos.format == B_BEOS_FORMAT_RAW_AUDIO)
out_format->type = B_MEDIA_RAW_AUDIO;
else {
out_format->type = B_MEDIA_ENCODED_AUDIO;
out_format->u.encoded_audio.encoding = (enum media_encoded_audio_format::audio_encoding) in_desc.family;
}
string_for_format(*out_format, s, sizeof(s));
printf(" encoding %d, format %s\n", (int)out_format->u.encoded_audio.encoding, s);
return B_OK;
}
status_t
FormatManager::GetDescriptionForFormat(media_format_description *out_description,
const media_format &in_format,
media_format_family in_family)
{
printf("GetDescriptionForFormat, requested %s family\n",
family_to_string(in_family));
char s[128];
string_for_format(in_format, s, sizeof(s));
printf(" encoding %d, format %s\n", (int)in_format.u.encoded_audio.encoding, s);
if (in_family != B_META_FORMAT_FAMILY)
return B_ERROR;
if (in_format.type == B_MEDIA_RAW_AUDIO) {
out_description->family = B_META_FORMAT_FAMILY;
strcpy(out_description->u.meta.description, "audiocodec/raw");
goto finished;
}
if (in_format.type == B_MEDIA_RAW_VIDEO) {
out_description->family = B_META_FORMAT_FAMILY;
strcpy(out_description->u.meta.description, "videocodec/raw");
goto finished;
}
out_description->family = B_META_FORMAT_FAMILY;
switch (in_format.u.encoded_audio.encoding) {
case B_MPEG_FORMAT_FAMILY:
strcpy(out_description->u.meta.description, "audiocodec/mpeg1layer3");
break;
default:
return B_ERROR;
}
finished:
printf(" description: %s\n",
string_for_description(*out_description, s, sizeof(s)));
return B_OK;
}
void
FormatManager::LoadState()
{
}
void
FormatManager::SaveState()
{
}
const char *
family_to_string(media_format_family family)
{
switch (family) {
case B_ANY_FORMAT_FAMILY:
return "any";
case B_BEOS_FORMAT_FAMILY:
return "BeOS";
case B_QUICKTIME_FORMAT_FAMILY:
return "Quicktime";
case B_AVI_FORMAT_FAMILY:
return "AVI";
case B_ASF_FORMAT_FAMILY:
return "ASF";
case B_MPEG_FORMAT_FAMILY:
return "MPEG";
case B_WAV_FORMAT_FAMILY:
return "WAV";
case B_AIFF_FORMAT_FAMILY:
return "AIFF";
case B_AVR_FORMAT_FAMILY:
return "AVR";
case B_OGG_FORMAT_FAMILY:
return "OGG";
case B_MISC_FORMAT_FAMILY:
return "misc";
case B_META_FORMAT_FAMILY:
return "meta";
default:
return "unknown";
}
}
const char *
string_for_description(const media_format_description &desc, char *string, size_t length)
{
switch (desc.family) {
case B_ANY_FORMAT_FAMILY:
snprintf(string, length, "any format");
break;
case B_BEOS_FORMAT_FAMILY:
snprintf(string, length, "BeOS format, format id 0x%lx", desc.u.beos.format);
break;
case B_QUICKTIME_FORMAT_FAMILY:
snprintf(string, length, "Quicktime format, vendor id 0x%lx, codec id 0x%lx", desc.u.quicktime.vendor, desc.u.quicktime.codec);
break;
case B_AVI_FORMAT_FAMILY:
snprintf(string, length, "AVI format, codec id 0x%lx", desc.u.avi.codec);
break;
case B_ASF_FORMAT_FAMILY:
snprintf(string, length, "ASF format, GUID %02x %02x %02x %02x %02x %02x "
"%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
desc.u.asf.guid.data[0], desc.u.asf.guid.data[1],
desc.u.asf.guid.data[2], desc.u.asf.guid.data[3],
desc.u.asf.guid.data[4], desc.u.asf.guid.data[5],
desc.u.asf.guid.data[6], desc.u.asf.guid.data[7],
desc.u.asf.guid.data[8], desc.u.asf.guid.data[9],
desc.u.asf.guid.data[10], desc.u.asf.guid.data[11],
desc.u.asf.guid.data[12], desc.u.asf.guid.data[13],
desc.u.asf.guid.data[14], desc.u.asf.guid.data[15]);
break;
case B_MPEG_FORMAT_FAMILY:
snprintf(string, length, "MPEG format, id 0x%lx", desc.u.mpeg.id);
break;
case B_WAV_FORMAT_FAMILY:
snprintf(string, length, "WAV format, codec id 0x%lx", desc.u.wav.codec);
break;
case B_AIFF_FORMAT_FAMILY:
snprintf(string, length, "AIFF format, codec id 0x%lx", desc.u.aiff.codec);
break;
case B_AVR_FORMAT_FAMILY:
snprintf(string, length, "AVR format, id 0x%lx", desc.u.avr.id);
break;
case B_OGG_FORMAT_FAMILY:
snprintf(string, length, "OGG format");
break;
case B_MISC_FORMAT_FAMILY:
snprintf(string, length, "misc format, file-format id 0x%lx, codec id 0x%lx", desc.u.misc.file_format, desc.u.misc.codec);
break;
case B_META_FORMAT_FAMILY:
snprintf(string, length, "meta format, description %s", desc.u.meta.description);
break;
default:
snprintf(string, length, "unknown format");
break;
}
return string;
}

View File

@ -0,0 +1,21 @@
#ifndef _FORMAT_MANAGER_H
#define _FORMAT_MANAGER_H
class FormatManager
{
public:
FormatManager();
~FormatManager();
void LoadState();
void SaveState();
status_t GetFormatForDescription(media_format *out_format,
const media_format_description &in_description);
status_t GetDescriptionForFormat(media_format_description *out_description,
const media_format &in_format,
media_format_family in_family);
};
#endif // _FORMAT_MANAGER_H

View File

@ -6,9 +6,11 @@ AddResources media_server : media_server.rdef ;
Server media_server : Server media_server :
media_server.cpp media_server.cpp
AddOnManager.cpp
AppManager.cpp AppManager.cpp
BufferManager.cpp BufferManager.cpp
DefaultManager.cpp DefaultManager.cpp
FormatManager.cpp
MMediaFilesManager.cpp MMediaFilesManager.cpp
NodeManager.cpp NodeManager.cpp
NotificationManager.cpp NotificationManager.cpp

View File

@ -118,7 +118,7 @@ MMediaFilesManager::LoadState()
} }
/*if (file.Read(&vol, sizeof(uint32)) < (int32)sizeof(uint32)) /*if (file.Read(&vol, sizeof(uint32)) < (int32)sizeof(uint32))
return B_ERROR;*/ return B_ERROR;*/
TRACE(" %s: %s, volume: %f\n", key, val, *(float *)&vol); //TRACE(" %s: %s, volume: %f\n", key, val, *(float *)&vol);
entry_ref ref; entry_ref ref;
if(len>1) { if(len>1) {

View File

@ -43,7 +43,9 @@ char __dont_remove_copyright_from_binary[] = "Copyright (c) 2002, 2003 Marcus Ov
#include "DataExchange.h" #include "DataExchange.h"
#include "BufferManager.h" #include "BufferManager.h"
#include "NodeManager.h" #include "NodeManager.h"
#include "AddOnManager.h"
#include "AppManager.h" #include "AppManager.h"
#include "FormatManager.h"
#include "MediaMisc.h" #include "MediaMisc.h"
#include "media_server.h" #include "media_server.h"
#include "debug.h" #include "debug.h"
@ -55,11 +57,13 @@ char __dont_remove_copyright_from_binary[] = "Copyright (c) 2002, 2003 Marcus Ov
* *
*/ */
NotificationManager *gNotificationManager; AddOnManager * gAddOnManager;
BufferManager *gBufferManager; AppManager * gAppManager;
AppManager *gAppManager; BufferManager * gBufferManager;
NodeManager *gNodeManager; FormatManager * gFormatManager;
MMediaFilesManager *gMMediaFilesManager; MMediaFilesManager * gMMediaFilesManager;
NodeManager * gNodeManager;
NotificationManager * gNotificationManager;
namespace BPrivate { namespace media { namespace BPrivate { namespace media {
extern team_id team; extern team_id team;
@ -121,6 +125,8 @@ ServerApp::ServerApp()
gAppManager = new AppManager; gAppManager = new AppManager;
gNodeManager = new NodeManager; gNodeManager = new NodeManager;
gMMediaFilesManager = new MMediaFilesManager; gMMediaFilesManager = new MMediaFilesManager;
gFormatManager = new FormatManager;
gAddOnManager = new AddOnManager;
control_port = create_port(64, MEDIA_SERVER_PORT_NAME); control_port = create_port(64, MEDIA_SERVER_PORT_NAME);
control_thread = spawn_thread(controlthread, "media_server control", 105, this); control_thread = spawn_thread(controlthread, "media_server control", 105, this);
@ -128,17 +134,21 @@ ServerApp::ServerApp()
// StartSystemTimeSource(); // StartSystemTimeSource();
gNodeManager->LoadState(); gNodeManager->LoadState();
gFormatManager->LoadState();
gAddOnManager->LoadState();
gAppManager->StartAddonServer(); gAppManager->StartAddonServer();
} }
ServerApp::~ServerApp() ServerApp::~ServerApp()
{ {
TRACE("ServerApp::~ServerApp()\n"); TRACE("ServerApp::~ServerApp()\n");
delete gAddOnManager;
delete gNotificationManager; delete gNotificationManager;
delete gBufferManager; delete gBufferManager;
delete gAppManager; delete gAppManager;
delete gNodeManager; delete gNodeManager;
delete gMMediaFilesManager; delete gMMediaFilesManager;
delete gFormatManager;
delete fLocker; delete fLocker;
delete_port(control_port); delete_port(control_port);
status_t err; status_t err;
@ -173,6 +183,8 @@ ServerApp::QuitRequested()
TRACE("ServerApp::QuitRequested()\n"); TRACE("ServerApp::QuitRequested()\n");
gMMediaFilesManager->SaveState(); gMMediaFilesManager->SaveState();
gNodeManager->SaveState(); gNodeManager->SaveState();
gFormatManager->SaveState();
gAddOnManager->SaveState();
gAppManager->TerminateAddonServer(); gAppManager->TerminateAddonServer();
return true; return true;
} }
@ -671,6 +683,42 @@ ServerApp::HandleMessage(int32 code, void *data, size_t size)
break; break;
} }
case SERVER_GET_FORMAT_FOR_DESCRIPTION:
{
const server_get_format_for_description_request *request = reinterpret_cast<const server_get_format_for_description_request *>(data);
server_get_format_for_description_reply reply;
rv = gFormatManager->GetFormatForDescription(&reply.format, request->description);
request->SendReply(rv, &reply, sizeof(reply));
break;
}
case SERVER_GET_DESCRIPTION_FOR_FORMAT:
{
const server_get_description_for_format_request *request = reinterpret_cast<const server_get_description_for_format_request *>(data);
server_get_description_for_format_reply reply;
rv = gFormatManager->GetDescriptionForFormat(&reply.description, request->format, request->family);
request->SendReply(rv, &reply, sizeof(reply));
break;
}
case SERVER_GET_READERS:
{
const server_get_readers_request *request = reinterpret_cast<const server_get_readers_request *>(data);
server_get_readers_reply reply;
rv = gAddOnManager->GetReaders(reply.ref, &reply.count, MAX_READERS);
request->SendReply(rv, &reply, sizeof(reply));
break;
}
case SERVER_GET_DECODER_FOR_FORMAT:
{
const server_get_decoder_for_format_request *request = reinterpret_cast<const server_get_decoder_for_format_request *>(data);
server_get_decoder_for_format_reply reply;
rv = gAddOnManager->GetDecoderForFormat(&reply.ref, request->format);
request->SendReply(rv, &reply, sizeof(reply));
break;
}
default: default:
printf("media_server: received unknown message code %#08lx\n",code); printf("media_server: received unknown message code %#08lx\n",code);
} }