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
This commit is contained in:
Axel Dörfler 2004-01-23 07:09:19 +00:00
parent b6b1e538a7
commit 0f34281e3e
2 changed files with 414 additions and 212 deletions

View File

@ -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 ;

View File

@ -1,73 +1,90 @@
/***********************************************************************
* AUTHOR: Marcus Overhagen
* FILE: MediaFormats.cpp
* DESCR:
***********************************************************************/
#include <MediaFormats.h>
#include <string.h>
/*
** 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 <MediaFormats.h>
#include <ObjectList.h>
#include <Message.h>
#include <Autolock.h>
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 <string.h>
using namespace BPrivate::media;
static BLocker sLock;
static BObjectList<meta_format> 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);
}