khronosfws/openmax_al/src/common/xametadataextractionitf.c
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 14 May 2010 16:22:35 +0300
changeset 16 43d09473c595
parent 12 5a06f39ad45b
child 25 6f7ceef7b1d1
permissions -rw-r--r--
Revision: 201017 Kit: 201019

/*
* 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"

#include "xametadataadaptation.h"

#include "xaadaptationmmf.h"
#include "xametadataadaptctxmmf.h"
#include "xamediaplayeradaptctxmmf.h"
#include "cmetadatautilityitf.h"

/* 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;
}

static void* GetMetadataUtilityContext(XAAdaptationMMFCtx* adaptCtx)
{
	switch(adaptCtx->baseObj.ctxId)
	{
		case XAMediaPlayerAdaptation:
	          return ((XAMediaPlayerAdaptationMMFCtx*)adaptCtx)->mmfMetadataContext;
		case XAMDAdaptation:
	          return ((XAMetadataAdaptationMMFCtx*)adaptCtx)->mmfContext;
		default:
			break;
	}

	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
    {
 
        if( impl->adaptCtx )
        {
        	
			if(impl->adaptCtx->fwtype == FWMgrFWMMF)
			{
				void *mmfCtx = GetMetadataUtilityContext((XAAdaptationMMFCtx*)impl->adaptCtx);
				if(mmfCtx)
				{
					res = mmf_get_item_count(mmfCtx, pItemCount);
				}
				else
				{
					res = XA_RESULT_PARAMETER_INVALID;
				}
			}
			else
			{
            	if(impl->filteringOn)
            	{
	                *pItemCount = impl->filteredcount;
    	        }
        	    else
            	{
	                *pItemCount = impl->currentTags.itemcount;
    	        }
        	    res = XA_RESULT_SUCCESS;
			}
        }
        else
        {
            res = XA_RESULT_INTERNAL_ERROR;
        }

        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;

	if(impl->adaptCtx && impl->adaptCtx->fwtype == FWMgrFWMMF)
	{
		void *mmfCtx = GetMetadataUtilityContext((XAAdaptationMMFCtx*)impl->adaptCtx);
		if(mmfCtx)
		{
			res = mmf_get_key_size(mmfCtx, index, pKeySize);
		}
		else
		{
			res = XA_RESULT_PARAMETER_INVALID;
		}
	}
	else
	{
	    /* 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;
	    }
 
	    /* size = size of struct + size of data - 1 (struct size already includes one char) */
    	*pKeySize = sizeof(XAMetadataInfo) + impl->currentTags.mdeKeys[newidx]->size - 1;
	}

    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;
 
    XAuint32 neededsize = 0;

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

    memset(pKey,0,keySize);
	
	if(impl->adaptCtx && impl->adaptCtx->fwtype == FWMgrFWMMF)
	{
		void *mmfCtx = GetMetadataUtilityContext((XAAdaptationMMFCtx*)impl->adaptCtx);
		if(mmfCtx)
		{
			res = mmf_get_key(mmfCtx, index, keySize, pKey);
		}
		else
		{
			res = XA_RESULT_PARAMETER_INVALID;
		}
	}
	else
	{

	    /* 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;
	    }

	    
	    /* 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 */
	    
	    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;

	if(impl->adaptCtx && impl->adaptCtx->fwtype == FWMgrFWMMF)
	{
		void *mmfCtx = GetMetadataUtilityContext((XAAdaptationMMFCtx*)impl->adaptCtx);
		if(mmfCtx)
		{
			res = mmf_get_value_size(mmfCtx, index,pValueSize);
		}
		else
		{
			res = XA_RESULT_PARAMETER_INVALID;
		}
	}
	else
	{
	    /* 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;
	    }
	 
	    /* size = size of struct + size of data - 1 (struct size already includes one char) */
	    *pValueSize = sizeof(XAMetadataInfo) + impl->currentTags.mdeValues[newidx]->size - 1;
	}

    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;
 
    XAuint32 neededsize = 0;

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

	memset(pValue,0,valueSize);

	if(impl->adaptCtx && impl->adaptCtx->fwtype == FWMgrFWMMF)
	{
		void *mmfCtx = GetMetadataUtilityContext((XAAdaptationMMFCtx*)impl->adaptCtx);
		if(mmfCtx)
		{
			res = mmf_get_value(mmfCtx, index, valueSize, pValue);
		}
		else
		{
			res = XA_RESULT_PARAMETER_INVALID;
		}
	}
	else
	{
	    /* 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;
	    }

	    /* 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 */

	    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;
    
    XAuint32 idx = 0;
    XAuint8 matchMask = 0;
    
 
    XAMetadataExtractionItfImpl *impl = NULL;
    const XAchar* parsedkey;
    impl = GetImpl(self);

    DEBUG_API("->XAMetadataExtractionItfImpl_AddKeyFilter");

 

    if( !impl )
    {
        DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
        DEBUG_API("<-XAMetadataExtractionItfImpl_AddKeyFilter");
        return XA_RESULT_PARAMETER_INVALID;
    }
    else
    {
    
		if(impl->adaptCtx && impl->adaptCtx->fwtype == FWMgrFWMMF)
		{
			DEBUG_API("<-XAMetadataExtractionItfImpl_AddKeyFilter Not Supported in MMF");
			res = 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;
	        }
	    }
    }
    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;
 
    XAuint32 idx = 0;

    DEBUG_API("->XAMetadataExtractionItfImpl_ClearKeyFilter");
    impl = GetImpl(self);
    if( !impl )
    {
        DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
        res = XA_RESULT_PARAMETER_INVALID;
    }
    else
    {
    
		if(impl->adaptCtx && impl->adaptCtx->fwtype == FWMgrFWMMF)
		{
			DEBUG_API("<-XAMetadataExtractionItfImpl_ClearKeyFilter Not Supported in MMF");
			res = XA_RESULT_PARAMETER_INVALID;
		}
		else
		{
	        if(impl->tagmatchesfilter)
	        {
	 
	            for(idx=0; idx < impl->currentTags.itemcount; idx++)
	            {
	                impl->tagmatchesfilter[idx] = XA_BOOLEAN_FALSE;
	            }

	        }
	        impl->filteredcount = 0;
	        impl->filteringOn = XA_BOOLEAN_FALSE;
	    }
    }

    DEBUG_API_A1("<-XAMetadataExtractionItfImpl_ClearKeyFilter (%d)", (int)res);
    return res;
}

/*****************************************************************************
 * XAMetadataExtractionItfImpl -specific methods
 *****************************************************************************/

/* 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;

		if(self->adaptCtx->fwtype != FWMgrFWMMF)
		{
	        XAAdaptationBase_AddEventHandler( adaptCtx, &XAMetadataExtractionItfImp_AdaptCb, XA_METADATAEVENTS, self );
		}

        self->self = self;
    }

    DEBUG_API("<-XAMetadataExtractionItfImpl_Create");
    return self;
}

/* 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);
 
	 if(self->adaptCtx->fwtype != FWMgrFWMMF)
	 {
    	XAAdaptationBase_RemoveEventHandler( self->adaptCtx, &XAMetadataExtractionItfImp_AdaptCb );
	    XAMetadataAdapt_FreeImplTagList(&(self->currentTags), XA_BOOLEAN_TRUE);
		
		if(self->tagmatchesfilter)
		{
			free(self->tagmatchesfilter);
		}
	 }

    free(self);
    DEBUG_API("<-XAMetadataExtractionItfImpl_Free");
}

 
/* 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( (XAAdaptationGstCtx*)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");
}


/* For given index over filtered array, return index over whole array
 */
XAresult CheckAndUnfilterIndex(XAMetadataExtractionItfImpl *impl,
                               XAuint32 oldidx, XAuint32 *newidx)
{
    DEBUG_API("->CheckAndUnfilterIndex");
 
    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;
    }

    DEBUG_API("<-CheckAndUnfilterIndex");
    return XA_RESULT_SUCCESS;
}