/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "xametadataextractionitf.h"
#include "xadebug.h"
#ifdef _GSTREAMER_BACKEND_
#include "XAMetadataAdaptation.h"
#endif
/* XAMetadataExtractionItfImpl* GetImpl(XAMetadataExtractionItf self)
* Description: Validate interface pointer and cast it to implementation pointer.
**/
static XAMetadataExtractionItfImpl* GetImpl(XAMetadataExtractionItf self)
{
if( self )
{
XAMetadataExtractionItfImpl* impl = (XAMetadataExtractionItfImpl*)(*self);
if( impl && (impl == impl->self) )
{
return impl;
}
}
return NULL;
}
/*****************************************************************************
* Base interface XAMetadataExtractionItf implementation
*****************************************************************************/
/*
* Returns the number of metadata items within the current scope of the object.
* @XAuint32 *pItemCount
* Number of metadata items. Must be non-NULL
*/
XAresult XAMetadataExtractionItfImpl_GetItemCount(XAMetadataExtractionItf self,
XAuint32 *pItemCount)
{
XAMetadataExtractionItfImpl *impl = NULL;
XAresult res = XA_RESULT_SUCCESS;
DEBUG_API("->XAMetadataExtractionItfImpl_GetItemCount");
impl = GetImpl(self);
/* check parameters */
if( !impl || !pItemCount )
{
DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
res = XA_RESULT_PARAMETER_INVALID;
}
else
{
#ifdef _GSTREAMER_BACKEND_
if( impl->adaptCtx )
{
if(impl->filteringOn)
{
*pItemCount = impl->filteredcount;
}
else
{
*pItemCount = impl->currentTags.itemcount;
}
res = XA_RESULT_SUCCESS;
}
else
{
res = XA_RESULT_INTERNAL_ERROR;
}
#endif
DEBUG_INFO_A1("itemCount = %d", (int)*pItemCount);
}
DEBUG_API_A1("<-XAMetadataExtractionItfImpl_GetItemCount (%d)", (int)res);
return res;
}
/*
* Returns the byte size of a given metadata key
*
* @XAuint32 index
* Metadata item Index. Range is [0, GetItemCount)
* @XAuint32 *pKeySize
* Address to store key size. size must be greater than 0. Must be non-NULL
*/
XAresult XAMetadataExtractionItfImpl_GetKeySize(XAMetadataExtractionItf self,
XAuint32 index,
XAuint32 *pKeySize)
{
XAMetadataExtractionItfImpl *impl = NULL;
XAresult res = XA_RESULT_SUCCESS;
XAuint32 newidx = 0;
DEBUG_API("->XAMetadataExtractionItfImpl_GetKeySize");
impl = GetImpl(self);
if( !impl || !pKeySize )
{
DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
DEBUG_API("<-XAMetadataExtractionItfImpl_GetKeySize");
return XA_RESULT_PARAMETER_INVALID;
}
*pKeySize = 0;
/* check index and return unfiltered index */
if( CheckAndUnfilterIndex(impl,index,&newidx) != XA_RESULT_SUCCESS )
{
DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
DEBUG_API("<-XAMetadataExtractionItfImpl_GetKeySize");
return XA_RESULT_PARAMETER_INVALID;
}
#ifdef _GSTREAMER_BACKEND_
/* size = size of struct + size of data - 1 (struct size already includes one char) */
*pKeySize = sizeof(XAMetadataInfo) + impl->currentTags.mdeKeys[newidx]->size - 1;
#endif
DEBUG_API_A1("<-XAMetadataExtractionItfImpl_GetKeySize (%d)", (int)res);
return res;
}
/*
* Returns a XAMetadataInfo structure and associated data referenced by the structure for a key.
* @XAuint32 index
* Metadata item Index. Range is [0, GetItemCount())
* @XAuint32 keySize
* Size of the memory block passed as key. Range is [1, GetKeySize].
* @XAMetadataInfo *pKey
* Address to store the key. Must be non-NULL
*/
XAresult XAMetadataExtractionItfImpl_GetKey(XAMetadataExtractionItf self,
XAuint32 index,
XAuint32 keySize,
XAMetadataInfo *pKey)
{
XAMetadataExtractionItfImpl *impl = NULL;
XAresult res = XA_RESULT_SUCCESS;
XAuint32 newidx = 0;
#ifdef _GSTREAMER_BACKEND_
XAuint32 neededsize = 0;
#endif
XAuint32 newdatasize = 0;
DEBUG_API("->XAMetadataExtractionItfImpl_GetKey");
impl = GetImpl(self);
if( !impl || !pKey )
{
DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
DEBUG_API("<-XAMetadataExtractionItfImpl_GetKey");
return XA_RESULT_PARAMETER_INVALID;
}
/* check index and return unfiltered index */
if(CheckAndUnfilterIndex(impl,index,&newidx) != XA_RESULT_SUCCESS)
{
DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
DEBUG_API("<-XAMetadataExtractionItfImpl_GetKey");
return XA_RESULT_PARAMETER_INVALID;
}
memset(pKey,0,keySize);
#ifdef _GSTREAMER_BACKEND_
/* needed size = size of struct + size of data - 1 (struct size already includes one char) */
neededsize = sizeof(XAMetadataInfo) + impl->currentTags.mdeKeys[newidx]->size - 1;
if( keySize<neededsize )
{ /* cannot fit all of key data */
newdatasize = impl->currentTags.mdeKeys[newidx]->size - (neededsize-keySize);
DEBUG_ERR("XA_RESULT_BUFFER_INSUFFICIENT");
res = XA_RESULT_BUFFER_INSUFFICIENT;
}
else
{
newdatasize = impl->currentTags.mdeKeys[newidx]->size;
res = XA_RESULT_SUCCESS;
}
/* copy data up to given size */
memcpy(pKey,impl->currentTags.mdeKeys[newidx],keySize-1);
/* ensure null-termination */
#endif
memset(pKey->data+newdatasize-1,0,1);
pKey->size = newdatasize;
DEBUG_API_A1("<-XAMetadataExtractionItfImpl_GetKey (%d)", (int)res);
return res;
}
/*
* Returns the byte size of a given metadata value
* @XAuint32 index
* Metadata item Index. Range is [0, GetItemCount())
* @XAuint32 *pValueSize
* Address to store value size. size must be greater than 0. Must be non-NULL
*/
XAresult XAMetadataExtractionItfImpl_GetValueSize(XAMetadataExtractionItf self,
XAuint32 index,
XAuint32 *pValueSize)
{
XAMetadataExtractionItfImpl *impl = NULL;
XAresult res = XA_RESULT_SUCCESS;
XAuint32 newidx = 0;
DEBUG_API("->XAMetadataExtractionItfImpl_GetValueSize");
impl = GetImpl(self);
if( !impl || !pValueSize )
{
DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
DEBUG_API("<-XAMetadataExtractionItfImpl_GetValueSize");
return XA_RESULT_PARAMETER_INVALID;
}
*pValueSize = 0;
/* check index and return unfiltered index */
if(CheckAndUnfilterIndex(impl,index,&newidx) != XA_RESULT_SUCCESS)
{
DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
DEBUG_API("<-XAMetadataExtractionItfImpl_GetValueSize");
return XA_RESULT_PARAMETER_INVALID;
}
#ifdef _GSTREAMER_BACKEND_
/* size = size of struct + size of data - 1 (struct size already includes one char) */
*pValueSize = sizeof(XAMetadataInfo) + impl->currentTags.mdeValues[newidx]->size - 1;
#endif
DEBUG_API_A1("<-XAMetadataExtractionItfImpl_GetValueSize (%d)", (int)res);
return res;
}
/*
* Returns a XAMetadataInfo structure and associated data referenced by the structure for a value.
* @XAuint32 index
* Metadata item Index. Range is [0, GetItemCount())
* @XAuint32 valueSize
* Size of the memory block passed as value. Range is [0, GetValueSize]
* @XAMetadataInfo *pValue
* Address to store the value. Must be non-NULL
*/
XAresult XAMetadataExtractionItfImpl_GetValue(XAMetadataExtractionItf self,
XAuint32 index,
XAuint32 valueSize,
XAMetadataInfo *pValue)
{
XAMetadataExtractionItfImpl *impl = NULL;
XAresult res = XA_RESULT_SUCCESS;
XAuint32 newidx = 0;
#ifdef _GSTREAMER_BACKEND_
XAuint32 neededsize = 0;
#endif
XAuint32 newdatasize = 0;
DEBUG_API("->XAMetadataExtractionItfImpl_GetValue");
impl = GetImpl(self);
if( !impl || !pValue )
{
DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
DEBUG_API("<-XAMetadataExtractionItfImpl_GetValue");
return XA_RESULT_PARAMETER_INVALID;
}
/* check index and return unfiltered index */
if(CheckAndUnfilterIndex(impl,index,&newidx) != XA_RESULT_SUCCESS)
{
DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
DEBUG_API("<-XAMetadataExtractionItfImpl_GetValue");
return XA_RESULT_PARAMETER_INVALID;
}
memset(pValue,0,valueSize);
#ifdef _GSTREAMER_BACKEND_
/* needed size = size of struct + size of data - 1 (struct size already includes one char) */
neededsize = sizeof(XAMetadataInfo) + impl->currentTags.mdeValues[newidx]->size - 1;
if( valueSize<neededsize )
{ /* cannot fit all of key data */
newdatasize = impl->currentTags.mdeValues[newidx]->size - (neededsize-valueSize);
DEBUG_ERR("XA_RESULT_BUFFER_INSUFFICIENT");
res = XA_RESULT_BUFFER_INSUFFICIENT;
}
else
{
newdatasize = impl->currentTags.mdeValues[newidx]->size;
res = XA_RESULT_SUCCESS;
}
/* copy data up to given size */
memcpy(pValue,impl->currentTags.mdeValues[newidx],valueSize-1);
/* ensure null-termination */
#endif
memset(pValue->data+newdatasize-1,0,1);
pValue->size = newdatasize;
DEBUG_API_A1("<-XAMetadataExtractionItfImpl_GetValue (%d)",(int)res);
return res;
}
/*
* Adds a filter for a specific key
* @XAuint32 keySize
* Size in bytes, of the pKey parameter. Ignored if filtering by key is disabled
* @const void *pKey
* The key to filter by. The entire key must match. Ignored if filtering by key is disabled.
* @XAuint32 keyEncoding
* Character encoding of the pKey parameter. Ignored if filtering by key is disabled
* @const XAchar *pValueLangCountry
* Language / country code of the value to filter by. Ignored if filtering by language / country is disabled
* @XAuint32 valueEncoding
* Encoding of the value to filter by. Ignored if filtering by encoding is disabled
* @XAuint8 filterMask
* Bitmask indicating which criteria to filter by. Should be one of the XA_METADATA_FILTER macros
*/
XAresult XAMetadataExtractionItfImpl_AddKeyFilter(XAMetadataExtractionItf self,
XAuint32 keySize,
const void *pKey,
XAuint32 keyEncoding,
const XAchar *pValueLangCountry,
XAuint32 valueEncoding,
XAuint8 filterMask)
{
XAresult res = XA_RESULT_SUCCESS;
#ifdef _GSTREAMER_BACKEND_
XAMetadataExtractionItfImpl *impl = NULL;
const XAchar* parsedkey;
impl = GetImpl(self);
#endif
DEBUG_API("->XAMetadataExtractionItfImpl_AddKeyFilter");
#ifdef _GSTREAMER_BACKEND_
XAuint32 idx = 0;
XAuint8 matchMask = 0;
if( !impl )
{
DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
DEBUG_API("<-XAMetadataExtractionItfImpl_AddKeyFilter");
return XA_RESULT_PARAMETER_INVALID;
}
else
{
impl->filteringOn = XA_BOOLEAN_TRUE;
for(idx=0; idx < impl->currentTags.itemcount; idx++)
{
if((filterMask & XA_METADATA_FILTER_KEY) && pKey)
{
parsedkey = XAMetadataAdapt_ParseKhronosKey(pKey);
if( strcmp((char*)parsedkey,
(char*)impl->currentTags.mdeKeys[idx]->data) == 0 )
{
matchMask |= XA_METADATA_FILTER_KEY;
}
}
if(filterMask & XA_METADATA_FILTER_LANG && pValueLangCountry)
{
if( strcmp((char*)pValueLangCountry,
(char*)impl->currentTags.mdeKeys[idx]->langCountry) == 0 )
{
matchMask |= XA_METADATA_FILTER_LANG;
}
}
if(filterMask & XA_METADATA_FILTER_ENCODING)
{
if(keyEncoding==impl->currentTags.mdeKeys[idx]->encoding)
{
matchMask |= XA_METADATA_FILTER_ENCODING;
}
if(valueEncoding==impl->currentTags.mdeValues[idx]->encoding)
{
matchMask |= XA_METADATA_FILTER_ENCODING;
}
}
/* check if all filters apply */
if(filterMask == matchMask)
{
if(impl->tagmatchesfilter[idx] == XA_BOOLEAN_FALSE)
{
impl->tagmatchesfilter[idx] = XA_BOOLEAN_TRUE;
impl->filteredcount++;
}
}
/*reset matchmask*/
matchMask=0;
}
}
#endif
DEBUG_API_A1("<-XAMetadataExtractionItfImpl_AddKeyFilter (%d)", (int)res);
return res;
}
/*
* Clears the key filter
*/
XAresult XAMetadataExtractionItfImpl_ClearKeyFilter(XAMetadataExtractionItf self)
{
XAMetadataExtractionItfImpl *impl = NULL;
XAresult res = XA_RESULT_SUCCESS;
#ifdef _GSTREAMER_BACKEND_
XAuint32 idx = 0;
#endif
DEBUG_API("->XAMetadataExtractionItfImpl_ClearKeyFilter");
impl = GetImpl(self);
if( !impl )
{
DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
res = XA_RESULT_PARAMETER_INVALID;
}
else
{
if(impl->tagmatchesfilter)
{
#ifdef _GSTREAMER_BACKEND_
for(idx=0; idx < impl->currentTags.itemcount; idx++)
{
impl->tagmatchesfilter[idx] = XA_BOOLEAN_FALSE;
}
#endif
}
impl->filteredcount = 0;
impl->filteringOn = XA_BOOLEAN_FALSE;
}
DEBUG_API_A1("<-XAMetadataExtractionItfImpl_ClearKeyFilter (%d)", (int)res);
return res;
}
/*****************************************************************************
* XAMetadataExtractionItfImpl -specific methods
*****************************************************************************/
#ifdef _GSTREAMER_BACKEND_
/* XAMetadataExtractionItfImpl* XAMetadataExtractionItfImpl_Create()
* Description: Allocate and initialize XAMetadataExtractionItfImpl
*/
XAMetadataExtractionItfImpl* XAMetadataExtractionItfImpl_Create(XAAdaptationBaseCtx *adaptCtx)
{
XAMetadataExtractionItfImpl *self = NULL;
DEBUG_API("->XAMetadataExtractionItfImpl_Create");
self = (XAMetadataExtractionItfImpl*)calloc(1,sizeof(XAMetadataExtractionItfImpl));
if( self )
{
/* init itf default implementation */
self->itf.GetItemCount = XAMetadataExtractionItfImpl_GetItemCount;
self->itf.GetKeySize = XAMetadataExtractionItfImpl_GetKeySize;
self->itf.GetKey = XAMetadataExtractionItfImpl_GetKey;
self->itf.GetValueSize = XAMetadataExtractionItfImpl_GetValueSize;
self->itf.GetValue = XAMetadataExtractionItfImpl_GetValue;
self->itf.AddKeyFilter = XAMetadataExtractionItfImpl_AddKeyFilter;
self->itf.ClearKeyFilter = XAMetadataExtractionItfImpl_ClearKeyFilter;
/* init variables */
self->filteredcount = 0;
self->filteringOn = XA_BOOLEAN_FALSE;
self->adaptCtx = adaptCtx;
XAAdaptationBase_AddEventHandler( adaptCtx, &XAMetadataExtractionItfImp_AdaptCb, XA_METADATAEVENTS, self );
self->self = self;
}
DEBUG_API("<-XAMetadataExtractionItfImpl_Create");
return self;
}
#endif
/* void XAMetadataExtractionItfImpl_Free(XAMetadataExtractionItfImpl* self)
* Description: Free all resources reserved at XAMetadataExtractionItfImpl_Create
*/
void XAMetadataExtractionItfImpl_Free(XAMetadataExtractionItfImpl* self)
{
DEBUG_API("->XAMetadataExtractionItfImpl_Free");
assert(self==self->self);
#ifdef _GSTREAMER_BACKEND_
XAAdaptationBase_RemoveEventHandler( self->adaptCtx, &XAMetadataExtractionItfImp_AdaptCb );
XAMetadataAdapt_FreeImplTagList(&(self->currentTags), XA_BOOLEAN_TRUE);
#endif
if(self->tagmatchesfilter)
{
free(self->tagmatchesfilter);
}
free(self);
DEBUG_API("<-XAMetadataExtractionItfImpl_Free");
}
#ifdef _GSTREAMER_BACKEND_
/* With this method, adaptation infroms that new tags are found (e.g. if source,
* has changed, live stream contains metadata...)
*/
void XAMetadataExtractionItfImp_AdaptCb( void *pHandlerCtx, XAAdaptEvent *event )
{
XAMetadataExtractionItfImpl* impl = NULL;
DEBUG_API("->XAMetadataExtractionItfImp_AdaptCb");
impl = (XAMetadataExtractionItfImpl*)pHandlerCtx;
if(!impl)
{
DEBUG_ERR("XAMetadataExtractionItfImp_AdaptCb, invalid context pointer!");
DEBUG_API("<-XAMetadataExtractionItfImp_AdaptCb");
return;
}
if( event && event->eventid == XA_ADAPT_MDE_TAGS_AVAILABLE )
{
/* get the tag list */
XAMetadataExtractionItfAdapt_FillTagList( impl->adaptCtx, &(impl->currentTags) );
if(impl->tagmatchesfilter)
{
free(impl->tagmatchesfilter);
}
impl->tagmatchesfilter = calloc(impl->currentTags.itemcount,sizeof(XAboolean));
impl->filteredcount = 0;
}
else
{
DEBUG_INFO("unhandled");
}
DEBUG_API("<-XAMetadataExtractionItfImp_AdaptCb");
}
#endif
/* For given index over filtered array, return index over whole array
*/
XAresult CheckAndUnfilterIndex(XAMetadataExtractionItfImpl *impl,
XAuint32 oldidx, XAuint32 *newidx)
{
DEBUG_API("->CheckAndUnfilterIndex");
#ifdef _GSTREAMER_BACKEND_
if( impl->filteringOn )
{
XAint16 i=-1;
if(oldidx>=impl->filteredcount)
{
DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
DEBUG_API("<-CheckAndUnfilterIndex");
return XA_RESULT_PARAMETER_INVALID;
}
*newidx=0;
while(*newidx<impl->currentTags.itemcount)
{
if(impl->tagmatchesfilter[*newidx]) i++;
if(i<oldidx) (*newidx)++;
else break;
}
if(*newidx==impl->currentTags.itemcount)
{
/* should not end up here */
*newidx=0;
DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
DEBUG_API("<-CheckAndUnfilterIndex");
return XA_RESULT_PARAMETER_INVALID;
}
}
else
{
if(oldidx>=impl->currentTags.itemcount)
{
DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
DEBUG_API("<-CheckAndUnfilterIndex");
return XA_RESULT_PARAMETER_INVALID;
}
*newidx=oldidx;
}
#endif
DEBUG_API("<-CheckAndUnfilterIndex");
return XA_RESULT_SUCCESS;
}