From 0f34281e3ece385548d3b9efbae9f10ebedb644e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Fri, 23 Jan 2004 07:09:19 +0000 Subject: [PATCH] The BMediaFormats class is now completely implemented. Removed wrong old implementation and the now unused old meta_description stuff. Also fixed the == and < operator for media_format_description. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@6237 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/kits/media/Jamfile | 1 + src/kits/media/MediaFormats.cpp | 625 +++++++++++++++++++++----------- 2 files changed, 414 insertions(+), 212 deletions(-) diff --git a/src/kits/media/Jamfile b/src/kits/media/Jamfile index e2b1baef2c..548d618b55 100644 --- a/src/kits/media/Jamfile +++ b/src/kits/media/Jamfile @@ -1,6 +1,7 @@ SubDir OBOS_TOP src kits media ; UsePrivateHeaders media ; +UsePrivateHeaders shared ; if $(CHECK_MALLOC) { SubDirC++Flags -D_NO_INLINE_ASM -fcheck-memory-usage ; diff --git a/src/kits/media/MediaFormats.cpp b/src/kits/media/MediaFormats.cpp index c4c0cd1b5d..674e061e7b 100644 --- a/src/kits/media/MediaFormats.cpp +++ b/src/kits/media/MediaFormats.cpp @@ -1,73 +1,90 @@ -/*********************************************************************** - * AUTHOR: Marcus Overhagen - * FILE: MediaFormats.cpp - * DESCR: - ***********************************************************************/ -#include -#include +/* +** Copyright 2004, the OpenBeOS project. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +** +** Authors: Axel Dörfler, Marcus Overhagen +*/ + + #include "DataExchange.h" +#include "MetaFormat.h" #include "debug.h" -/************************************************************* - * - *************************************************************/ +#include +#include +#include +#include -status_t get_next_encoder(int32 *cookie, - const media_file_format *mfi, // this comes from get_next_file_format() - const media_format *input_format, // this is the type of data given to the encoder - media_format *output_format, // this is the type of data encoder will output - media_codec_info *ei) // information about the encoder +#include + +using namespace BPrivate::media; + + +static BLocker sLock; +static BObjectList sFormats; +static bigtime_t sLastFormatsUpdate; + +_MakeFormatHookFunc BPrivate::media::_gMakeFormatHook = NULL; + + +status_t +get_next_encoder(int32 *cookie, const media_file_format *_fileFormat, + const media_format *inFormat, media_format *_outFormat, + media_codec_info *_codecInfo) { UNIMPLEMENTED(); return B_ERROR; } -status_t get_next_encoder(int32 *cookie, - const media_file_format *mfi, - const media_format *input_format, - const media_format *output_format, - media_codec_info *ei, - media_format *accepted_input_format, - media_format *accepted_output_format) +status_t +get_next_encoder(int32 *cookie, const media_file_format *_fileFormat, + const media_format *inFormat, const media_format *_outFormat, + media_codec_info *_codecInfo, media_format *_acceptedInputFormat, + media_format *_acceptedOutputFormat) { UNIMPLEMENTED(); return B_ERROR; } -status_t get_next_encoder(int32 *cookie, media_codec_info *ei) +status_t +get_next_encoder(int32 *cookie, media_codec_info *_codecInfo) { UNIMPLEMENTED(); return B_ERROR; } -bool does_file_accept_format(const media_file_format *mfi, - media_format *format, uint32 flags) +bool +does_file_accept_format(const media_file_format *_fileFormat, + media_format *format, uint32 flags) { UNIMPLEMENTED(); return false; } -/************************************************************* - * _media_format_description - *************************************************************/ + +// #pragma mark - + _media_format_description::_media_format_description() { memset(this, 0, sizeof(*this)); } + _media_format_description::~_media_format_description() { } + _media_format_description::_media_format_description(const _media_format_description & other) { memcpy(this, &other, sizeof(*this)); } + _media_format_description & _media_format_description::operator=(const _media_format_description & other) { @@ -75,166 +92,13 @@ _media_format_description::operator=(const _media_format_description & other) return *this; } -/************************************************************* - * public BMediaFormats - *************************************************************/ -BMediaFormats::BMediaFormats() - : fLocker(new BLocker("some BMediaFormats locker")), - fIndex(0) -{ -} - -/* virtual */ -BMediaFormats::~BMediaFormats() -{ - delete fLocker; -} - -status_t -BMediaFormats::InitCheck() -{ - return B_OK; -} - -status_t -BMediaFormats::MakeFormatFor(const media_format_description * descs, - int32 desc_count, - media_format * io_format, - uint32 flags, - void * _reserved) -{ - CALLED(); - if (descs == 0 || desc_count < 1 || io_format == 0) - return B_BAD_VALUE; - - return B_ERROR; -} - - -status_t -BMediaFormats::GetFormatFor(const media_format_description & desc, - media_format * out_format) -{ - return _get_format_for_description(out_format, desc); -} - - -/* static */ status_t -BMediaFormats::GetBeOSFormatFor(uint32 fourcc, - media_format * out_format, - media_type type) -{ - media_format_description mfd; - mfd.family = B_BEOS_FORMAT_FAMILY; - mfd.u.beos.format = fourcc; - memset(out_format, 0, sizeof(*out_format)); - out_format->type = type; -// return MakeFormatFor(&mfd, 1, out_format); - return B_ERROR; -} - - -/* static */ status_t -BMediaFormats::GetAVIFormatFor(uint32 fourcc, - media_format * out_format, - media_type type) -{ - media_format_description mfd; - mfd.family = B_AVI_FORMAT_FAMILY; - mfd.u.avi.codec = fourcc; - memset(out_format, 0, sizeof(*out_format)); - out_format->type = type; -// return MakeFormatFor(&mfd, 1, out_format); - return B_ERROR; -} - - -/* static */ status_t -BMediaFormats::GetQuicktimeFormatFor(uint32 vendor, - uint32 fourcc, - media_format * out_format, - media_type type) -{ - media_format_description mfd; - mfd.family = B_QUICKTIME_FORMAT_FAMILY; - mfd.u.quicktime.codec = fourcc; - mfd.u.quicktime.vendor = vendor; - memset(out_format, 0, sizeof(*out_format)); - out_format->type = type; -// return MakeFormatFor(&mfd, 1, out_format); - return B_ERROR; -} - - -status_t -BMediaFormats::GetCodeFor(const media_format & format, - media_format_family family, - media_format_description * out_description) -{ - 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; -} - - -status_t -BMediaFormats::RewindFormats() -{ - if (!fLocker->IsLocked()) - return B_NOT_ALLOWED; - fIndex = 0; - return B_OK; -} - - -status_t -BMediaFormats::GetNextFormat(media_format * out_format, - media_format_description * out_description) -{ - if (!fLocker->IsLocked()) - return B_NOT_ALLOWED; - - UNIMPLEMENTED(); - return B_ERROR; -} - -// You need to lock/unlock (only) when using RewindFormats()/GetNextFormat() bool -BMediaFormats::Lock() -{ - return fLocker->Lock(); -} - -void -BMediaFormats::Unlock() -{ - fLocker->Unlock(); -} - -/* --- begin deprecated API --- */ -status_t -BMediaFormats::MakeFormatFor(const media_format_description & desc, - const media_format & in_format, - media_format * out_format) -{ - *out_format = in_format; - return MakeFormatFor(&desc, 1, out_format); -} - -/************************************************************* - * - *************************************************************/ - -bool operator==(const media_format_description & a, const media_format_description & b) +operator==(const media_format_description & a, const media_format_description & b) { if (a.family != b.family) return false; + switch (a.family) { case B_BEOS_FORMAT_FAMILY: return a.u.beos.format == b.u.beos.format; @@ -256,22 +120,26 @@ bool operator==(const media_format_description & a, const media_format_descripti 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: - return strncmp(a.u.meta.description, b.u.meta.description, sizeof(a.u.meta.description)) == 0; + default: return false; } } -bool operator<(const media_format_description & a, const media_format_description & b) + +bool +operator<(const media_format_description & a, const media_format_description & b) { if (a.family != b.family) return a.family < b.family; + switch (a.family) { case B_BEOS_FORMAT_FAMILY: return a.u.beos.format < b.u.beos.format; case B_QUICKTIME_FORMAT_FAMILY: - return a.u.quicktime.codec < b.u.quicktime.codec || a.u.quicktime.vendor < b.u.quicktime.vendor; + if (a.u.quicktime.vendor == b.u.quicktime.vendor) + return a.u.quicktime.codec < b.u.quicktime.codec; + return a.u.quicktime.vendor < b.u.quicktime.vendor; case B_AVI_FORMAT_FAMILY: return a.u.avi.codec < b.u.avi.codec; case B_ASF_FORMAT_FAMILY: @@ -287,51 +155,384 @@ bool operator<(const media_format_description & a, const media_format_descriptio 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: - return strncmp(a.u.meta.description, b.u.meta.description, sizeof(a.u.meta.description)) < 0; + if (a.u.misc.file_format == b.u.misc.file_format) + return a.u.misc.codec < b.u.misc.codec; + return a.u.misc.file_format < b.u.misc.file_format; + default: return true; } } -bool operator==(const GUID & a, const GUID & b) + +bool +operator==(const GUID & a, const GUID & b) { return memcmp(&a, &b, sizeof(a)) == 0; } -bool operator<(const GUID & a, const GUID & b) + +bool +operator<(const GUID & a, const GUID & b) { return memcmp(&a, &b, sizeof(a)) < 0; } -status_t -_get_format_for_description(media_format *out_format, const media_format_description &in_desc) + +// #pragma mark - +// +// Some (meta) formats supply functions + + +meta_format::meta_format() + : + id(0) { - server_get_format_for_description_request request; - server_get_format_for_description_reply reply; +} + + + +meta_format::meta_format(const media_format_description &description, + const media_format &format, int32 id) + : + description(description), + format(format), + id(id) +{ +} + +meta_format::meta_format(const media_format_description &description) + : + description(description), + id(0) +{ +} + + +meta_format::meta_format(const meta_format &other) + : + description(other.description), + format(other.format) +{ +} + + +bool +meta_format::Matches(const media_format &otherFormat, media_format_family family) +{ + if (family != description.family) + return false; + + return format.Matches(&otherFormat); +} + + +int +meta_format::CompareDescriptions(const meta_format *a, const meta_format *b) +{ + if (a->description == b->description) + return 0; + + if (a->description < b->description) + return -1; + + return 1; +} + + +int +meta_format::Compare(const meta_format *a, const meta_format *b) +{ + int compare = CompareDescriptions(a, b); + if (compare != 0) + return compare; + + return a->id - b->id; +} + + +/** We share one global list for all BMediaFormats in the team - since the + * format data can change at any time, we have to ask the server to update + * the list to ensure that we are working on the latest data set. + * The list we get from the server is always sorted by description. + * The formats lock has to be hold when you call this function. + */ + +static status_t +update_media_formats() +{ + ASSERT(sLock.IsLocked()); + + BMessage request(MEDIA_SERVER_GET_FORMATS); + request.AddInt64("last_timestamp", sLastFormatsUpdate); - request.description = in_desc; - - if (B_OK != QueryServer(SERVER_GET_FORMAT_FOR_DESCRIPTION, &request, sizeof(request), &reply, sizeof(reply))) + BMessage reply; + status_t status = QueryServer(request, reply); + if (status < B_OK) { + ERROR("BMediaFormats: Could not update formats: %s\n", strerror(status)); + return status; + } + + // do we need an update at all? + bool needUpdate; + if (reply.FindBool("need_update", &needUpdate) < B_OK) + return B_ERROR; + if (!needUpdate) + return B_OK; + + // update timestamp and check if the message is okay + type_code code; + int32 count; + if (reply.FindInt64("timestamp", &sLastFormatsUpdate) < B_OK + || reply.GetInfo("formats", &code, &count) < B_OK) return B_ERROR; - *out_format = reply.format; + // overwrite already existing formats + + int32 index = 0; + for (; index < sFormats.CountItems() && index < count; index++) { + meta_format *item = sFormats.ItemAt(index); + + const meta_format *newItem; + ssize_t size; + if (reply.FindData("formats", MEDIA_META_FORMAT_TYPE, index, + (const void **)&newItem, &size) == B_OK) + *item = *newItem; + } + + // allocate additional formats + + for (; index < count; index++) { + const meta_format *newItem; + ssize_t size; + if (reply.FindData("formats", MEDIA_META_FORMAT_TYPE, index, + (const void **)&newItem, &size) == B_OK) + sFormats.AddItem(new meta_format(*newItem)); + } + + // remove no longer used formats + + while (count < sFormats.CountItems()) + delete sFormats.RemoveItemAt(count); + return B_OK; } -status_t -_get_meta_description_for_format(media_format_description *out_desc, const media_format &in_format) + +// #pragma mark - + + +BMediaFormats::BMediaFormats() + : + fIteratorIndex(0) +{ +} + + +BMediaFormats::~BMediaFormats() +{ +} + + +status_t +BMediaFormats::InitCheck() { - 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_DESCRIPTION_FOR_FORMAT, &request, sizeof(request), &reply, sizeof(reply))) - return B_ERROR; - - *out_desc = reply.description; return B_OK; } + + +status_t +BMediaFormats::GetCodeFor(const media_format &format, + media_format_family family, + media_format_description *_description) +{ + BAutolock locker(sLock); + + status_t status = update_media_formats(); + if (status < B_OK) + return status; + + // search for a matching format + + for (int32 index = sFormats.CountItems(); index-- > 0;) { + meta_format *metaFormat = sFormats.ItemAt(index); + + if (metaFormat->Matches(format, family)) { + *_description = metaFormat->description; + return B_OK; + } + } + + return B_MEDIA_BAD_FORMAT; +} + + +status_t +BMediaFormats::GetFormatFor(const media_format_description &description, + media_format *_format) +{ + BAutolock locker(sLock); + + status_t status = update_media_formats(); + if (status < B_OK) { + printf("BMediaFormats: updating formats from server failed: %s!\n", strerror(status)); + return status; + } + printf("search for description family = %d, a = 0x%lx, b = 0x%lx\n", + description.family, description.u.misc.file_format, description.u.misc.codec); + + // search for a matching format description + + meta_format other(description); + const meta_format *metaFormat = sFormats.BinarySearch(other, meta_format::CompareDescriptions); + printf("meta format == %p\n", metaFormat); + if (metaFormat == NULL) + return B_MEDIA_BAD_FORMAT; + + // found it! + *_format = metaFormat->format; + return B_OK; +} + + +status_t +BMediaFormats::GetBeOSFormatFor(uint32 format, + media_format *_format, media_type type) +{ + BMediaFormats formats; + + media_format_description description; + description.family = B_BEOS_FORMAT_FAMILY; + description.u.beos.format = format; + + status_t status = formats.GetFormatFor(description, _format); + if (status < B_OK) + return status; + + if (type != B_MEDIA_UNKNOWN_TYPE && type != _format->type) + return B_BAD_TYPE; + + return B_OK; +} + + +status_t +BMediaFormats::GetAVIFormatFor(uint32 codec, + media_format *_format, media_type type) +{ + UNIMPLEMENTED(); + BMediaFormats formats; + + media_format_description description; + description.family = B_AVI_FORMAT_FAMILY; + description.u.avi.codec = codec; + + status_t status = formats.GetFormatFor(description, _format); + if (status < B_OK) + return status; + + if (type != B_MEDIA_UNKNOWN_TYPE && type != _format->type) + return B_BAD_TYPE; + + return B_OK; +} + + +status_t +BMediaFormats::GetQuicktimeFormatFor(uint32 vendor, uint32 codec, + media_format *_format, media_type type) +{ + BMediaFormats formats; + + media_format_description description; + description.family = B_QUICKTIME_FORMAT_FAMILY; + description.u.quicktime.vendor = vendor; + description.u.quicktime.codec = codec; + + status_t status = formats.GetFormatFor(description, _format); + if (status < B_OK) + return status; + + if (type != B_MEDIA_UNKNOWN_TYPE && type != _format->type) + return B_BAD_TYPE; + + return B_OK; +} + + +status_t +BMediaFormats::RewindFormats() +{ + if (!sLock.IsLocked() || sLock.LockingThread() != find_thread(NULL)) { + // ToDo: shouldn't we simply drop into the debugger in this case? + return B_NOT_ALLOWED; + } + + fIteratorIndex = 0; + return B_OK; +} + + +status_t +BMediaFormats::GetNextFormat(media_format *_format, + media_format_description *_description) +{ + if (!sLock.IsLocked() || sLock.LockingThread() != find_thread(NULL)) { + // ToDo: shouldn't we simply drop into the debugger in this case? + return B_NOT_ALLOWED; + } + + if (fIteratorIndex == 0) { + // this is the first call, so let's make sure we have + // current data to operate on + status_t status = update_media_formats(); + if (status < B_OK) + return status; + } + + meta_format *format = sFormats.ItemAt(fIteratorIndex++); + if (format == NULL) + return B_BAD_INDEX; + + return B_OK; +} + + +bool +BMediaFormats::Lock() +{ + return sLock.Lock(); +} + + +void +BMediaFormats::Unlock() +{ + sLock.Unlock(); +} + + +status_t +BMediaFormats::MakeFormatFor(const media_format_description *descriptions, + int32 descriptionCount, media_format *format, uint32 flags, void * _reserved) +{ + if (_gMakeFormatHook == NULL) + return B_NOT_ALLOWED; + + // This function is callable from the server in the + // context of a codec registration only. + // The add-on manager is locked during this call + + return _gMakeFormatHook(descriptions, descriptionCount, format, flags); +} + +/* --- begin deprecated API --- */ + +status_t +BMediaFormats::MakeFormatFor(const media_format_description &description, + const media_format &inFormat, media_format *_outFormat) +{ + *_outFormat = inFormat; + return MakeFormatFor(&description, 1, _outFormat); +} +