From 046f31f91f5d4f56b2fed3ff5c5759328d222cf2 Mon Sep 17 00:00:00 2001 From: beveloper Date: Sun, 14 Dec 2003 19:23:16 +0000 Subject: [PATCH] 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 --- headers/os/media/MediaDefs.h | 1 + headers/private/media/DataExchange.h | 39 ++- headers/private/media/DecoderPlugin.h | 16 +- headers/private/media/PluginManager.h | 4 +- .../plugins/mp3_reader/MP3ReaderPlugin.cpp | 4 +- src/kits/media/DecoderPlugin.cpp | 13 +- src/kits/media/MediaFormats.cpp | 33 ++- src/kits/media/PluginManager.cpp | 168 ++++++------ src/kits/media/SoundPlayNode.cpp | 13 +- src/servers/media/AddOnManager.cpp | 258 ++++++++++++++++++ src/servers/media/AddOnManager.h | 72 +++++ src/servers/media/FormatManager.cpp | 180 ++++++++++++ src/servers/media/FormatManager.h | 21 ++ src/servers/media/Jamfile | 2 + src/servers/media/MMediaFilesManager.cpp | 2 +- src/servers/media/media_server.cpp | 58 +++- 16 files changed, 757 insertions(+), 127 deletions(-) create mode 100644 src/servers/media/AddOnManager.cpp create mode 100644 src/servers/media/AddOnManager.h create mode 100644 src/servers/media/FormatManager.cpp create mode 100644 src/servers/media/FormatManager.h diff --git a/headers/os/media/MediaDefs.h b/headers/os/media/MediaDefs.h index e12286b47b..6277bfa7bf 100644 --- a/headers/os/media/MediaDefs.h +++ b/headers/os/media/MediaDefs.h @@ -599,6 +599,7 @@ typedef enum { B_WAV_FORMAT_FAMILY = 6, B_AIFF_FORMAT_FAMILY = 7, B_AVR_FORMAT_FAMILY = 8, + B_OGG_FORMAT_FAMILY = 9, B_MISC_FORMAT_FAMILY = 99999, B_META_FORMAT_FAMILY = 100000 } media_format_family; diff --git a/headers/private/media/DataExchange.h b/headers/private/media/DataExchange.h index 0a714c4024..2c16067ea8 100644 --- a/headers/private/media/DataExchange.h +++ b/headers/private/media/DataExchange.h @@ -106,7 +106,9 @@ enum { SERVER_REMOVEREFFOR, SERVER_REMOVEITEM, 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, NODE_MESSAGE_START = 0x200, @@ -206,7 +208,7 @@ public: private: dev_t device; 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, }; +// used by SERVER_GET_READERS +enum +{ + MAX_READERS = 40, +}; + struct addonserver_instantiate_dormant_node_request : public request_data { media_addon_id addonid; @@ -889,14 +897,35 @@ struct server_get_format_for_description_reply : public reply_data 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; }; -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 diff --git a/headers/private/media/DecoderPlugin.h b/headers/private/media/DecoderPlugin.h index 5e9a4c6ba1..21804bb2af 100644 --- a/headers/private/media/DecoderPlugin.h +++ b/headers/private/media/DecoderPlugin.h @@ -6,6 +6,8 @@ #include "MediaPlugin.h" #include "MediaExtractor.h" +class AddOnManager; + namespace BPrivate { namespace media { class Decoder @@ -41,11 +43,19 @@ private: class DecoderPlugin : public MediaPlugin { 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 diff --git a/headers/private/media/PluginManager.h b/headers/private/media/PluginManager.h index ec56bf39c8..c8b730062c 100644 --- a/headers/private/media/PluginManager.h +++ b/headers/private/media/PluginManager.h @@ -24,11 +24,11 @@ public: PluginManager(); ~PluginManager(); - MediaPlugin * GetPlugin(const char *name); + MediaPlugin * GetPlugin(const entry_ref &ref); void PutPlugin(MediaPlugin *plugin); 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 { diff --git a/src/add-ons/media/plugins/mp3_reader/MP3ReaderPlugin.cpp b/src/add-ons/media/plugins/mp3_reader/MP3ReaderPlugin.cpp index f016ecd7bb..6ea03d8c5b 100644 --- a/src/add-ons/media/plugins/mp3_reader/MP3ReaderPlugin.cpp +++ b/src/add-ons/media/plugins/mp3_reader/MP3ReaderPlugin.cpp @@ -154,7 +154,7 @@ mp3Reader::Sniff(int32 *streamCount) TRACE("mp3Reader::Sniff: file size is %Ld bytes\n", fFileSize); if (!IsMp3File()) { - TRACE("mp3Reader::Sniff: non recognized as mp3 file\n"); + TRACE("mp3Reader::Sniff: not recognized as mp3 file\n"); return B_ERROR; } @@ -903,7 +903,7 @@ mp3Reader::GetFrameLength(void *header) int bitrate_index = (h[2] >> 4) & 0x0f; int sampling_rate_index = (h[2] >> 2) & 0x03; 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 framerate = frame_rate_table[mpeg_version_index][sampling_rate_index]; diff --git a/src/kits/media/DecoderPlugin.cpp b/src/kits/media/DecoderPlugin.cpp index 841efb69e5..2bd46bfc38 100644 --- a/src/kits/media/DecoderPlugin.cpp +++ b/src/kits/media/DecoderPlugin.cpp @@ -27,14 +27,25 @@ Decoder::Setup(MediaExtractor *extractor, int32 stream) } DecoderPlugin::DecoderPlugin() + : fPublishHook(0) { } +typedef status_t (*publish_func)(DecoderPlugin *, const char *, const char *, const char *, const char *); + status_t DecoderPlugin::PublishDecoder(const char *meta_description, const char *short_name, const char *pretty_name, 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; } diff --git a/src/kits/media/MediaFormats.cpp b/src/kits/media/MediaFormats.cpp index 36e27ea6b6..c4c0cd1b5d 100644 --- a/src/kits/media/MediaFormats.cpp +++ b/src/kits/media/MediaFormats.cpp @@ -172,8 +172,14 @@ BMediaFormats::GetCodeFor(const media_format & format, media_format_family family, media_format_description * out_description) { - UNIMPLEMENTED(); - return B_ERROR; + server_get_description_for_format_request request; + 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; case B_AVR_FORMAT_FAMILY: return a.u.avr.id == b.u.avr.id; + case B_OGG_FORMAT_FAMILY: + return false; // XXX fix this case B_MISC_FORMAT_FAMILY: return a.u.misc.file_format == b.u.misc.file_format && a.u.misc.codec == b.u.misc.codec; 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; case B_AVR_FORMAT_FAMILY: return a.u.avr.id < b.u.avr.id; + case B_OGG_FORMAT_FAMILY: + return false; // XXX fix this case B_MISC_FORMAT_FAMILY: return a.u.misc.file_format < b.u.misc.file_format || a.u.misc.codec < b.u.misc.codec; 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; -// if (B_OK != QueryServer(SERVER_GET_FORMAT_FOR_DESCRIPTION, &request, sizeof(request), &reply, sizeof(reply))) -// 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; + if (B_OK != QueryServer(SERVER_GET_FORMAT_FOR_DESCRIPTION, &request, sizeof(request), &reply, sizeof(reply))) + return B_ERROR; *out_format = reply.format; return B_OK; @@ -319,13 +323,14 @@ _get_format_for_description(media_format *out_format, const media_format_descrip status_t _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_meta_description_for_format_reply reply; + server_get_description_for_format_request request; + server_get_description_for_format_reply reply; 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))) -// return B_ERROR; + if (B_OK != QueryServer(SERVER_GET_DESCRIPTION_FOR_FORMAT, &request, sizeof(request), &reply, sizeof(reply))) + return B_ERROR; *out_desc = reply.description; return B_OK; diff --git a/src/kits/media/PluginManager.cpp b/src/kits/media/PluginManager.cpp index a92c1cf297..fbce5753eb 100644 --- a/src/kits/media/PluginManager.cpp +++ b/src/kits/media/PluginManager.cpp @@ -3,6 +3,7 @@ #include #include "PluginManager.h" +#include "DataExchange.h" #include "debug.h" PluginManager _plugin_manager; @@ -12,41 +13,50 @@ _CreateReader(Reader **reader, int32 *streamCount, media_file_format *mff, BData { printf("_CreateReader enter\n"); - MediaPlugin *plugin; - ReaderPlugin *readerplugin; - - plugin = _plugin_manager.GetPlugin("mp3_reader"); - if (!plugin) { - printf("_CreateReader: GetPlugin failed\n"); + // get list of available readers from, the server + server_get_readers_request request; + server_get_readers_reply reply; + if (B_OK != QueryServer(SERVER_GET_READERS, &request, sizeof(request), &reply, sizeof(reply))) { + printf("_CreateReader: can't get list of readers\n"); return B_ERROR; } - readerplugin = dynamic_cast(plugin); - if (!readerplugin) { - printf("_CreateReader: dynamic_cast failed\n"); - return B_ERROR; - } + // try each reader by calling it's Sniff function... + for (int32 i = 0; i < reply.count; i++) { + entry_ref ref = reply.ref[i]; + MediaPlugin *plugin = _plugin_manager.GetPlugin(ref); + if (!plugin) { + printf("_CreateReader: GetPlugin failed\n"); + return B_ERROR; + } - *reader = readerplugin->NewReader(); - if (! *reader) { - printf("_CreateReader: NewReader failed\n"); - return B_ERROR; - } + ReaderPlugin *readerplugin = dynamic_cast(plugin); + if (!readerplugin) { + printf("_CreateReader: dynamic_cast failed\n"); + 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)) { - printf("_CreateReader: Sniff failed\n"); - _DestroyReader(*reader); - return B_MEDIA_NO_HANDLER; -// return B_ERROR; - } + (*reader)->Setup(source); - (*reader)->GetFileFormatInfo(mff); - - printf("_CreateReader leave\n"); + if (B_OK == (*reader)->Sniff(streamCount)) { + printf("_CreateReader: Sniff success\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 @@ -54,10 +64,19 @@ _CreateDecoder(Decoder **decoder, media_codec_info *mci, const media_format *for { 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; DecoderPlugin *decoderplugin; - plugin = _plugin_manager.GetPlugin("mp3_decoder"); + plugin = _plugin_manager.GetPlugin(reply.ref); if (!plugin) { printf("_CreateDecoder: GetPlugin failed\n"); return B_ERROR; @@ -96,20 +115,6 @@ _DestroyDecoder(Decoder *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() { @@ -135,7 +140,7 @@ PluginManager::~PluginManager() MediaPlugin * -PluginManager::GetPlugin(const char *name) +PluginManager::GetPlugin(const entry_ref &ref) { fLocker->Lock(); @@ -144,7 +149,7 @@ PluginManager::GetPlugin(const char *name) plugin_info info; for (fPluginList->Rewind(); fPluginList->GetNext(&pinfo); ) { - if (0 == strcmp(name, pinfo->name)) { + if (0 == strcmp(ref.name, pinfo->name)) { plugin = pinfo->plugin; pinfo->usecount++; fLocker->Unlock(); @@ -152,17 +157,17 @@ PluginManager::GetPlugin(const char *name) } } - if (!LoadPlugin(name, &info.plugin, &info.image)) { - printf("PluginManager: Error, loading PlugIn %s failed\n", name); + if (!LoadPlugin(ref, &info.plugin, &info.image)) { + printf("PluginManager: Error, loading PlugIn %s failed\n", ref.name); fLocker->Unlock(); return 0; } - strcpy(info.name, name); + strcpy(info.name, ref.name); info.usecount = 1; fPluginList->Insert(info); - printf("PluginManager: PlugIn %s loaded\n", name); + printf("PluginManager: PlugIn %s loaded\n", ref.name); plugin = info.plugin; @@ -198,46 +203,35 @@ PluginManager::PutPlugin(MediaPlugin *plugin) 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[] = { - "/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 - }; + BPath p(&ref); + + printf("PluginManager: LoadPlugin trying to load %s\n", p.Path()); + + 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++) { - BPath p(searchdir[i], name); - - printf("PluginManager: LoadPlugin 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("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; + 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); + return false; } - - 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; } diff --git a/src/kits/media/SoundPlayNode.cpp b/src/kits/media/SoundPlayNode.cpp index b64039a191..9293734968 100644 --- a/src/kits/media/SoundPlayNode.cpp +++ b/src/kits/media/SoundPlayNode.cpp @@ -41,7 +41,7 @@ _SoundPlayNode::_SoundPlayNode(const char *name, const media_multi_audio_format mFormat.u.raw_audio = *format; 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(" byte_order: %ld (",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); // reset our buffer duration, etc. to avoid later calculations - bigtime_t duration = mOutput.format.u.raw_audio.buffer_size * 10000 - / ( (mOutput.format.u.raw_audio.format & media_raw_audio_format::B_AUDIO_SIZE_MASK) - * mOutput.format.u.raw_audio.channel_count) - / ((int32)(mOutput.format.u.raw_audio.frame_rate / 100)); + 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.channel_count)) + / (int32)mOutput.format.u.raw_audio.frame_rate; SetBufferDuration(duration); - TRACE("_SoundPlayNode::Connect: buffer duaration is %Ld\n", duration); + TRACE("_SoundPlayNode::Connect: buffer duration is %Ld\n", duration); mInternalLatency = (3 * BufferDuration()) / 4; 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 // 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); EventQueue()->AddEvent(nextBufferEvent); diff --git a/src/servers/media/AddOnManager.cpp b/src/servers/media/AddOnManager.cpp new file mode 100644 index 0000000000..4fcf7a541b --- /dev/null +++ b/src/servers/media/AddOnManager.cpp @@ -0,0 +1,258 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#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), + fWriterList(new List), + fDecoderList(new List), + fEncoderList(new List), + 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(pl); + if (rp) + RegisterReader(rp, ref); + + DecoderPlugin *dp = dynamic_cast(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); +} diff --git a/src/servers/media/AddOnManager.h b/src/servers/media/AddOnManager.h new file mode 100644 index 0000000000..92cd1bfbf7 --- /dev/null +++ b/src/servers/media/AddOnManager.h @@ -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 meta_desc; + }; + struct encoder_info + { + entry_ref ref; + }; + + BLocker *fLocker; + List *fReaderList; + List *fWriterList; + List *fDecoderList; + List *fEncoderList; + + reader_info *fReaderInfo; + writer_info *fWriterInfo; + decoder_info *fDecoderInfo; + encoder_info *fEncoderInfo; + +}; + + +#endif // _ADD_ON_MANAGER_H diff --git a/src/servers/media/FormatManager.cpp b/src/servers/media/FormatManager.cpp new file mode 100644 index 0000000000..1219b4350e --- /dev/null +++ b/src/servers/media/FormatManager.cpp @@ -0,0 +1,180 @@ +#include +#include +#include +#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; +} diff --git a/src/servers/media/FormatManager.h b/src/servers/media/FormatManager.h new file mode 100644 index 0000000000..d0b5ae55bc --- /dev/null +++ b/src/servers/media/FormatManager.h @@ -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 diff --git a/src/servers/media/Jamfile b/src/servers/media/Jamfile index 66c6a77478..f1f8e74746 100644 --- a/src/servers/media/Jamfile +++ b/src/servers/media/Jamfile @@ -6,9 +6,11 @@ AddResources media_server : media_server.rdef ; Server media_server : media_server.cpp + AddOnManager.cpp AppManager.cpp BufferManager.cpp DefaultManager.cpp + FormatManager.cpp MMediaFilesManager.cpp NodeManager.cpp NotificationManager.cpp diff --git a/src/servers/media/MMediaFilesManager.cpp b/src/servers/media/MMediaFilesManager.cpp index c9f0db6019..ee4c7aa9cf 100644 --- a/src/servers/media/MMediaFilesManager.cpp +++ b/src/servers/media/MMediaFilesManager.cpp @@ -118,7 +118,7 @@ MMediaFilesManager::LoadState() } /*if (file.Read(&vol, sizeof(uint32)) < (int32)sizeof(uint32)) 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; if(len>1) { diff --git a/src/servers/media/media_server.cpp b/src/servers/media/media_server.cpp index cd3f936cc9..42c611b88c 100644 --- a/src/servers/media/media_server.cpp +++ b/src/servers/media/media_server.cpp @@ -43,7 +43,9 @@ char __dont_remove_copyright_from_binary[] = "Copyright (c) 2002, 2003 Marcus Ov #include "DataExchange.h" #include "BufferManager.h" #include "NodeManager.h" +#include "AddOnManager.h" #include "AppManager.h" +#include "FormatManager.h" #include "MediaMisc.h" #include "media_server.h" #include "debug.h" @@ -55,11 +57,13 @@ char __dont_remove_copyright_from_binary[] = "Copyright (c) 2002, 2003 Marcus Ov * */ -NotificationManager *gNotificationManager; -BufferManager *gBufferManager; -AppManager *gAppManager; -NodeManager *gNodeManager; -MMediaFilesManager *gMMediaFilesManager; +AddOnManager * gAddOnManager; +AppManager * gAppManager; +BufferManager * gBufferManager; +FormatManager * gFormatManager; +MMediaFilesManager * gMMediaFilesManager; +NodeManager * gNodeManager; +NotificationManager * gNotificationManager; namespace BPrivate { namespace media { extern team_id team; @@ -121,6 +125,8 @@ ServerApp::ServerApp() gAppManager = new AppManager; gNodeManager = new NodeManager; gMMediaFilesManager = new MMediaFilesManager; + gFormatManager = new FormatManager; + gAddOnManager = new AddOnManager; control_port = create_port(64, MEDIA_SERVER_PORT_NAME); control_thread = spawn_thread(controlthread, "media_server control", 105, this); @@ -128,17 +134,21 @@ ServerApp::ServerApp() // StartSystemTimeSource(); gNodeManager->LoadState(); + gFormatManager->LoadState(); + gAddOnManager->LoadState(); gAppManager->StartAddonServer(); } ServerApp::~ServerApp() { TRACE("ServerApp::~ServerApp()\n"); + delete gAddOnManager; delete gNotificationManager; delete gBufferManager; delete gAppManager; delete gNodeManager; delete gMMediaFilesManager; + delete gFormatManager; delete fLocker; delete_port(control_port); status_t err; @@ -173,6 +183,8 @@ ServerApp::QuitRequested() TRACE("ServerApp::QuitRequested()\n"); gMMediaFilesManager->SaveState(); gNodeManager->SaveState(); + gFormatManager->SaveState(); + gAddOnManager->SaveState(); gAppManager->TerminateAddonServer(); return true; } @@ -671,6 +683,42 @@ ServerApp::HandleMessage(int32 code, void *data, size_t size) break; } + case SERVER_GET_FORMAT_FOR_DESCRIPTION: + { + const server_get_format_for_description_request *request = reinterpret_cast(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(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(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(data); + server_get_decoder_for_format_reply reply; + rv = gAddOnManager->GetDecoderForFormat(&reply.ref, request->format); + request->SendReply(rv, &reply, sizeof(reply)); + break; + } + default: printf("media_server: received unknown message code %#08lx\n",code); }