khronosfws/openmax_al/src/gst_adaptation/xametadataadaptation.c
changeset 16 43d09473c595
child 20 b67dd1fc57c5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/khronosfws/openmax_al/src/gst_adaptation/xametadataadaptation.c	Fri May 14 16:22:35 2010 +0300
@@ -0,0 +1,1200 @@
+/*
+* 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 <string.h>
+#include <gst.h>
+#include "xaadaptationgst.h"
+#include "xametadataadaptctx.h"
+#include "xamediaplayeradaptctx.h"
+#include "xamediarecorderadaptctx.h"
+#include "xametadataadaptation.h"
+
+/* forward declarations of internal methods */
+XAMetadataAdaptVars* XAMetadataAdapt_GetMetadataVars(XAAdaptationGstCtx *bCtx);
+GstStructure* XAMetadataAdapt_GetChildStructure(XAMetadataAdaptVars* mdv, XAuint32 index);
+gboolean XAMetadataAdapt_CountTags(GQuark gkey, const GValue *gvalue, gpointer counter);
+void XAMetadataAdapt_ParseTag(const GstTagList* list, const gchar* tag, gpointer listptr);
+gboolean XAMetadataAdapt_ParseItem(GQuark field_id, const GValue * value, gpointer listptr);
+gboolean XAMetadataAdapt_GstTagCb( GstBus *bus, GstMessage *message, gpointer data );
+
+/*NOTE: no way to query these dynamically?*/
+/*supported keys for metadata insertion*/
+static char* xaMetadataAdaptSupportedKeys[] = {
+    KHRONOS_TITLE,
+    KHRONOS_ALBUM,
+    KHRONOS_TRACK_NUMBER,
+    KHRONOS_ARTIST,
+    KHRONOS_GENRE,
+    KHRONOS_COMMENT,
+    KHRONOS_COPYRIGHT,
+    GST_TAG_TITLE,
+    GST_TAG_TITLE_SORTNAME,
+    GST_TAG_ARTIST,
+    GST_TAG_ARTIST_SORTNAME,
+    GST_TAG_ALBUM,
+    GST_TAG_ALBUM_SORTNAME,
+    GST_TAG_COMPOSER,
+    GST_TAG_DATE,
+    GST_TAG_GENRE,
+    GST_TAG_COMMENT,
+    GST_TAG_EXTENDED_COMMENT,
+    GST_TAG_TRACK_NUMBER,
+    GST_TAG_TRACK_COUNT,
+    GST_TAG_ALBUM_VOLUME_NUMBER,
+    GST_TAG_ALBUM_VOLUME_COUNT,
+    GST_TAG_LOCATION,
+    GST_TAG_DESCRIPTION,
+    GST_TAG_VERSION,
+    GST_TAG_ISRC,
+    GST_TAG_ORGANIZATION,
+    GST_TAG_COPYRIGHT,
+    GST_TAG_COPYRIGHT_URI,
+    GST_TAG_CONTACT,
+    GST_TAG_LICENSE,
+    GST_TAG_LICENSE_URI,
+    GST_TAG_PERFORMER,
+    NULL
+};
+
+/******************************************************************************
+ * COMMONS
+ ******************************************************************************/
+
+
+/* const char* XAMetadataAdapt_ParseKhronosKey(const char* pKKey)
+ * Translates Khronos key string to adaptation-specific key string
+ * @return Translated key string
+ */
+const XAchar* XAMetadataAdapt_ParseKhronosKey(const XAchar* pKKey)
+{
+    const XAchar* newKey;
+    DEBUG_API_A1("->XAMetadataAdapt_ParseKhronosKey: \"%s\"", (char*)pKKey);
+    if( strcmp((char*)pKKey,KHRONOS_TITLE) ==0 ) newKey = (XAchar*)GST_TAG_TITLE;
+    else if( strcmp((char*)pKKey,KHRONOS_ALBUM) ==0 ) newKey = (XAchar*)GST_TAG_ALBUM;
+    else if( strcmp((char*)pKKey,KHRONOS_TRACK_NUMBER) ==0 ) newKey = (XAchar*)GST_TAG_TRACK_NUMBER;
+    else if( strcmp((char*)pKKey,KHRONOS_ARTIST) ==0 ) newKey = (XAchar*)GST_TAG_ARTIST;
+    else if( strcmp((char*)pKKey,KHRONOS_GENRE) ==0 ) newKey = (XAchar*)GST_TAG_GENRE;
+    else if( strcmp((char*)pKKey,KHRONOS_COMMENT) ==0 ) newKey = (XAchar*)GST_TAG_COMMENT;
+    else if( strcmp((char*)pKKey,KHRONOS_COPYRIGHT) ==0 ) newKey = (XAchar*)GST_TAG_COPYRIGHT;
+    else newKey = pKKey;
+/* No Gst keys for following:
+    else if( strcmp(pKKey,KHRONOS_YEAR) ==0 ) newKey = ;
+    else if( strcmp(pKKey,KHRONOS_ARTIST_URL) ==0 ) newKey = ;
+    else if( strcmp(pKKey,KHRONOS_CONTENT_URL) ==0 ) newKey = ;
+    else if( strcmp(pKKey,KHRONOS_RATING) ==0 ) newKey = ;
+    else if( strcmp(pKKey,KHRONOS_ALBUM_ART) ==0 ) newKey = ;
+ */
+    DEBUG_API_A1("<-XAMetadataAdapt_ParseKhronosKey: => \"%s\"", (char*)newKey);
+    return newKey;
+}
+
+/* XAresult XAMetadataAdapt_PreInit(XAAdaptationGstCtx *bCtx)
+ * Initialize values needed before preroll
+ * @return XAresult ret - Success value
+ */
+XAresult XAMetadataAdapt_PreInit(XAAdaptationGstCtx *bCtx)
+{
+    XAresult ret = XA_RESULT_SUCCESS;
+    XAMetadataAdaptVars* mdv;
+    DEBUG_API("->XAMetadataAdapt_PreInit");
+    if( bCtx->baseObj.ctxId == XAMDAdaptation ||
+        bCtx->baseObj.ctxId == XAMediaPlayerAdaptation )
+    {
+        mdv = (XAMetadataAdaptVars*) calloc(1, sizeof(XAMetadataAdaptVars));
+        mdv->currentchild = &(mdv->generaltags);
+        mdv->traversemode=XA_METADATATRAVERSALMODE_NODE;
+        ((XAMediaPlayerAdaptationCtx*)bCtx)->metadatavars = mdv;
+
+    }
+    else if ( bCtx->baseObj.ctxId == XAMediaRecorderAdaptation )
+    {
+        mdv = (XAMetadataAdaptVars*) calloc(1, sizeof(XAMetadataAdaptVars));
+        mdv->currentchild = &(mdv->generaltags);
+        mdv->traversemode=XA_METADATATRAVERSALMODE_NODE;
+        ((XAMediaRecorderAdaptationCtx*)bCtx)->metadatavars = mdv;
+    }
+    else
+    {
+        DEBUG_ERR("Unsupported metadata context!!");
+        ret = XA_RESULT_FEATURE_UNSUPPORTED;
+    }
+
+    if(ret == XA_RESULT_SUCCESS)
+    {
+        if(bCtx->bus)
+        {
+            g_signal_connect(bCtx->bus, "message::tag", G_CALLBACK(XAMetadataAdapt_GstTagCb), bCtx );
+        }
+        else
+        {
+            DEBUG_ERR("No bus in context!!");
+            ret = XA_RESULT_PRECONDITIONS_VIOLATED;
+        }
+    }
+    DEBUG_API_A1("<-XAMetadataAdapt_PreInit (%d)", (int)ret);
+    return ret;
+}
+/* XAresult XAMetadataAdapt_PostInit(XAAdaptationGstCtx *bCtx)
+ * Initialize values after preroll
+ * @return XAresult ret - Success value
+ */
+XAresult XAMetadataAdapt_PostInit(XAAdaptationGstCtx *bCtx)
+{
+    XAresult ret = XA_RESULT_SUCCESS;
+    XAMetadataAdaptVars* mdv=NULL;
+    XAMediaPlayerAdaptationCtx* mCtx=NULL;
+    GstPad* tmppad=NULL;
+    GstCaps* tmpcaps=NULL;
+    GstElement* tmpelement=NULL;
+    XAAdaptEvent event = {XA_METADATAEVENTS, XA_ADAPT_MDE_TAGS_AVAILABLE, 0, NULL };
+
+    DEBUG_API("->XAMetadataAdapt_PostInit");
+    if( bCtx->baseObj.ctxId == XAMDAdaptation ||
+        bCtx->baseObj.ctxId == XAMediaPlayerAdaptation )
+    {
+        mdv = XAMetadataAdapt_GetMetadataVars(bCtx);
+        if( mdv )
+        {
+            mdv->childcount = 0;
+            /* try to dig out audio and video pads from decodebin for stream info tags */
+            /* NOTE: currently no good deterministic way to dig out undecoded pads
+             * from decodebin's internal demuxer, this is just ugly way to try to cope
+             * with most demuxers.
+             */
+            mCtx = ((XAMediaPlayerAdaptationCtx*)bCtx);
+            if(GST_IS_BIN(mCtx->codecbin))
+            {
+                tmpelement=gst_bin_get_by_name(GST_BIN(mCtx->codecbin),"typefind");
+                if(tmpelement)
+                {
+                    tmppad = gst_element_get_static_pad(GST_ELEMENT(tmpelement),"src");
+                    tmpelement=NULL;
+                    if(tmppad)
+                    {
+                        tmppad = gst_pad_get_peer(tmppad);
+                        if(tmppad)
+                        {
+                            tmpelement = gst_pad_get_parent_element(tmppad);
+                        }
+                    }
+                    /* now we have demuxer, if existing */
+                    if(tmpelement)
+                    {
+                        tmppad = gst_element_get_pad( tmpelement, "audio_00");
+                        if(tmppad)
+                        {
+                            tmpcaps = gst_pad_get_negotiated_caps( GST_PAD(tmppad) );
+                            if(tmpcaps==NULL || gst_caps_is_any(tmpcaps) || gst_caps_is_empty(tmpcaps))
+                            {
+                                mdv->audiotags = NULL;
+                                DEBUG_INFO("no usable audio properties found from pad !");
+                            }
+                            else
+                            {
+                                mdv->audiotags = gst_caps_get_structure(tmpcaps,0);
+                                mdv->childcount++;
+                                DEBUG_INFO_A1("found audio node: %s",gst_caps_to_string(tmpcaps));
+                            }
+                        }
+                        tmppad = gst_element_get_pad( tmpelement, "video_00");
+                        if(tmppad)
+                        {
+                            tmpcaps = gst_pad_get_negotiated_caps( GST_PAD(tmppad) );
+                            if(tmpcaps==NULL || gst_caps_is_any(tmpcaps) || gst_caps_is_empty(tmpcaps))
+                            {
+                                mdv->videotags = NULL;
+                                DEBUG_INFO("no usable video properties found from pad !");
+                            }
+                            else
+                            {
+                                mdv->videotags = gst_caps_get_structure(tmpcaps,0);
+                                mdv->childcount++;
+                                DEBUG_INFO_A1("found video node: %s",gst_caps_to_string(tmpcaps));
+                            }
+                        }
+                    }
+                }
+            }
+            XAAdaptationBase_SendAdaptEvents(&bCtx->baseObj, &event );
+        }
+    }
+
+    if ( tmpelement )
+    {
+    	gst_object_unref( tmpelement );
+    }
+    if ( tmppad )
+    {
+    	gst_object_unref( tmppad );
+    }
+    if ( tmpcaps )
+    {
+    	gst_object_unref( tmpcaps );
+    }
+
+    DEBUG_API_A1("<-XAMetadataAdapt_PostInit (%d)", (int)ret);
+    return ret;
+}
+
+/*
+ * void XAMetadataAdapt_FreeImplTagList(XAMetadataImplTagList *list, XAboolean freeItems)
+ * deallocate elements inside taglist
+ */
+void XAMetadataAdapt_FreeImplTagList(XAMetadataImplTagList *list, XAboolean freeItems)
+{
+    XAuint16 i;
+    DEBUG_API("->XAMetadataExtractionItfAdapt_FreeTagList");
+    if(list->mdeKeys)
+    {
+        for(i=0;i<list->itemcount;i++)
+        {
+            if(list->mdeKeys[i])
+            {
+                if(freeItems)
+                    free(list->mdeKeys[i]);
+                list->mdeKeys[i]=NULL;
+            }
+        }
+        free(list->mdeKeys);
+        list->mdeKeys = NULL;
+    }
+    if(list->mdeValues)
+    {
+        for(i=0;i<list->itemcount;i++)
+        {
+            if(list->mdeValues[i])
+            {
+                if(freeItems)
+                    free(list->mdeValues[i]);
+                list->mdeValues[i]=NULL;
+            }
+        }
+        free(list->mdeValues);
+        list->mdeValues = NULL;
+    }
+    list->itemcount = 0;
+    DEBUG_API("<-XAMetadataExtractionItfAdapt_FreeTagList");
+}
+
+/*
+ * void XAMetadataAdapt_FreeVars(XAMetadataAdaptVars *vars)
+ * deallocate XAMetadataAdaptVars
+ */
+void XAMetadataAdapt_FreeVars(XAMetadataAdaptVars *vars)
+{
+    DEBUG_API("->XAMetadataAdapt_FreeVars");
+    if(vars)
+    {
+        if( vars->generaltags )
+        {
+            gst_tag_list_free(vars->generaltags);
+        }
+        if( vars->audiotags )
+        {
+            gst_structure_set_parent_refcount(vars->audiotags,NULL);
+            gst_structure_free(vars->audiotags);
+        }
+        if( vars->videotags )
+        {
+            gst_structure_set_parent_refcount(vars->videotags,NULL);
+            gst_structure_free(vars->videotags);
+        }
+        free(vars);
+    }
+    DEBUG_API("<-XAMetadataAdapt_FreeVars");
+}
+
+/******************************************************************************
+ * EXTRACTION
+ ******************************************************************************/
+
+/*
+ * XAresult XAMetadataExtractionItfAdapt_FillTagList()
+ * @param tagList - contains pointer to tag list to be updated
+ * @return XAresult ret - Success value
+ */
+XAresult XAMetadataExtractionItfAdapt_FillTagList(XAAdaptationGstCtx *bCtx,
+                                                  XAMetadataImplTagList* tagList)
+{
+    XAresult ret = XA_RESULT_SUCCESS;
+    XAMetadataAdaptVars* mdv;
+    XAuint32 newcount = 0;
+    DEBUG_API("->XAMetadataExtractionItfAdapt_FillTagList");
+
+    mdv = XAMetadataAdapt_GetMetadataVars(bCtx);
+    if( mdv )
+    {
+        XAMetadataAdapt_FreeImplTagList(tagList, XA_BOOLEAN_TRUE);
+        /* get number of tags and allocate memory for them */
+        if(mdv->traversemode==XA_METADATATRAVERSALMODE_ALL)
+        {
+            if(mdv->generaltags)
+                gst_structure_foreach(mdv->generaltags, XAMetadataAdapt_CountTags, &newcount);
+            if(mdv->audiotags)
+                gst_structure_foreach(mdv->audiotags, XAMetadataAdapt_CountTags, &newcount);
+            if(mdv->videotags)
+                gst_structure_foreach(mdv->videotags, XAMetadataAdapt_CountTags, &newcount);
+        }
+        else
+        {
+            if(mdv->currentchild && *(mdv->currentchild))
+                gst_structure_foreach(*(mdv->currentchild), XAMetadataAdapt_CountTags, &newcount);
+        }
+        DEBUG_INFO_A1("tag count = %d",(int)newcount)
+        tagList->mdeKeys = (XAMetadataInfo**)calloc(newcount,sizeof(XAMetadataInfo*));
+        tagList->mdeValues = (XAMetadataInfo**)calloc(newcount,sizeof(XAMetadataInfo*));
+
+        /* fill in given tag list */
+        tagList->itemcount = 0;
+        if(mdv->traversemode==XA_METADATATRAVERSALMODE_ALL)
+        {
+            if(mdv->generaltags)
+                gst_tag_list_foreach(mdv->generaltags, XAMetadataAdapt_ParseTag, tagList);
+            if(mdv->audiotags)
+                gst_structure_foreach(mdv->audiotags, XAMetadataAdapt_ParseItem, tagList);
+            if(mdv->videotags)
+                gst_structure_foreach(mdv->videotags, XAMetadataAdapt_ParseItem, tagList);
+        }
+        else
+        {
+            if(mdv->currentchild && *(mdv->currentchild))
+            {
+                if(GST_IS_TAG_LIST(*(mdv->currentchild)))
+                {
+                    gst_tag_list_foreach(*(mdv->currentchild), XAMetadataAdapt_ParseTag, tagList);
+                }
+                else
+                {
+                    gst_structure_foreach(*(mdv->currentchild), XAMetadataAdapt_ParseItem, tagList);
+                }
+            }
+        }
+    }
+    else
+    {
+        DEBUG_ERR("Metadata variables not found!!");
+        ret = XA_RESULT_PARAMETER_INVALID;
+    }
+
+    DEBUG_API_A1("<-XAMetadataExtractionItfAdapt_FillTagList (%d)", (int)ret);
+    return ret;
+}
+
+/******************************************************************************
+ * TRAVERSAL
+ *****************************************************************************/
+
+/*
+ * XAresult XAMetadataTraversalItfAdapt_SetMode(XAAdaptationGstCtx *bCtx, XAuint32 mode)
+ */
+XAresult XAMetadataTraversalItfAdapt_SetMode(XAAdaptationGstCtx *bCtx, XAuint32 mode)
+{
+    XAresult ret = XA_RESULT_SUCCESS;
+    XAMetadataAdaptVars* mdv=NULL;
+    XAAdaptEvent event = {XA_METADATAEVENTS, XA_ADAPT_MDE_TAGS_AVAILABLE, 0, NULL };
+
+    DEBUG_API("->XAMetadataTraversalItfAdapt_SetMode");
+    mdv = XAMetadataAdapt_GetMetadataVars(bCtx);
+    if( mdv )
+    {
+        mdv->traversemode = mode;
+        /* inform extractor to update tag list */
+        XAAdaptationBase_SendAdaptEvents(&bCtx->baseObj, &event );
+        if(mdv->traversemode==XA_METADATATRAVERSALMODE_ALL)
+        {
+            mdv->nodedepth = 0;
+            mdv->currentchild = &(mdv->generaltags);
+        }
+    }
+    else
+    {
+        DEBUG_ERR("Metadata variables not found!!");
+        ret = XA_RESULT_PARAMETER_INVALID;
+    }
+
+    DEBUG_API("<-XAMetadataTraversalItfAdapt_SetMode");
+    return ret;
+}
+
+/*
+ * XAresult XAMetadataTraversalItfAdapt_GetChildCount(XAAdaptationGstCtx *bCtx, XAuint32 *pCount)
+ */
+XAresult XAMetadataTraversalItfAdapt_GetChildCount(XAAdaptationGstCtx *bCtx, XAuint32 *pCount)
+{
+    XAresult ret = XA_RESULT_SUCCESS;
+    XAMetadataAdaptVars* mdv=NULL;
+
+    DEBUG_API("->XAMetadataTraversalItfAdapt_GetChildCount");
+    mdv = XAMetadataAdapt_GetMetadataVars(bCtx);
+    if( mdv )
+    {
+        /* only depth of 1 is supported */
+        if( mdv->nodedepth == 0 )
+        {
+            *pCount=mdv->childcount;
+        }
+        else
+        {
+            *pCount=0;
+        }
+    }
+    else
+    {
+        DEBUG_ERR("Metadata variables not found!!");
+        ret = XA_RESULT_PARAMETER_INVALID;
+        *pCount=0;
+    }
+    DEBUG_API_A2("<-XAMetadataTraversalItfAdapt_GetChildCount(%d) count=%d", (int)ret, (int)*pCount);
+    return ret;
+}
+
+/*
+ * XAresult XAMetadataTraversalItfAdapt_GetChildMIMETypeSize(XAAdaptationGstCtx *bCtx,
+ *                                                         XAuint32 index,
+ *                                                         XAuint32 *pSize)
+ */
+XAresult XAMetadataTraversalItfAdapt_GetChildMIMETypeSize(XAAdaptationGstCtx *bCtx,
+                                                          XAuint32 index,
+                                                          XAuint32 *pSize)
+{
+    XAresult ret = XA_RESULT_SUCCESS;
+    XAMetadataAdaptVars* mdv=NULL;
+
+    DEBUG_API("->XAMetadataTraversalItfAdapt_GetChildMIMETypeSize");
+    mdv = XAMetadataAdapt_GetMetadataVars(bCtx);
+    if( mdv )
+    {
+        GstStructure* child = XAMetadataAdapt_GetChildStructure(mdv,index);
+        if(child)
+        {
+            *pSize = strlen(gst_structure_get_name(child));
+        }
+    }
+    else
+    {
+        DEBUG_ERR("Metadata variables not found!!");
+        ret = XA_RESULT_PARAMETER_INVALID;
+        *pSize=0;
+    }
+    DEBUG_API("<-XAMetadataTraversalItfAdapt_GetChildMIMETypeSize");
+    return ret;
+}
+
+/*
+ * XAresult XAMetadataTraversalItfAdapt_GetChildInfo(XAAdaptationGstCtx *bCtx,
+ *                                                  XAuint32 index,
+ *                                                 XAint32 *pNodeID,
+ *                                                 XAuint32 *pType,
+ *                                                 XAuint32 size,
+ *                                                 XAchar *pMimeType)
+ */
+XAresult XAMetadataTraversalItfAdapt_GetChildInfo(XAAdaptationGstCtx *bCtx,
+                                                  XAuint32 index,
+                                                  XAint32 *pNodeID,
+                                                  XAuint32 *pType,
+                                                  XAuint32 size,
+                                                  XAchar *pMimeType)
+{
+    XAresult ret = XA_RESULT_SUCCESS;
+    XAMetadataAdaptVars* mdv=NULL;
+    const gchar* mime;
+    GstStructure* child;
+
+    DEBUG_API("->XAMetadataTraversalItfAdapt_GetChildInfo");
+    mdv = XAMetadataAdapt_GetMetadataVars(bCtx);
+    if( mdv )
+    {
+        child = XAMetadataAdapt_GetChildStructure(mdv,index);
+        if(child)
+        {
+            *pNodeID = (XAint32)child;
+            mime = gst_structure_get_name(child);
+            if(strncmp(mime,"audio",5)==0)
+            {
+                *pType = XA_NODETYPE_AUDIO;
+            }
+            if(strncmp(mime,"video",5)==0)
+            {
+                *pType = XA_NODETYPE_VIDEO;
+            }
+            if(strncmp(mime,"image",5)==0)
+            {
+                *pType = XA_NODETYPE_IMAGE;
+            }
+            else
+            {
+                *pType = XA_NODETYPE_UNSPECIFIED;
+            }
+            strncpy((char*)pMimeType,mime,size);
+        }
+    }
+    else
+    {
+        DEBUG_ERR("Metadata variables not found!!");
+        ret = XA_RESULT_PARAMETER_INVALID;
+    }
+    DEBUG_API("<-XAMetadataTraversalItfAdapt_GetChildInfo");
+    return ret;
+}
+
+/*
+ * XAresult XAMetadataTraversalItfAdapt_SetActiveNode(XAAdaptationGstCtx *bCtx,
+ *                                                  XAuint32 index)
+ */
+XAresult XAMetadataTraversalItfAdapt_SetActiveNode(XAAdaptationGstCtx *bCtx,
+                                                   XAuint32 index)
+{
+    XAresult ret = XA_RESULT_SUCCESS;
+    XAMetadataAdaptVars* mdv=NULL;
+    GstStructure* child;
+
+    DEBUG_API("->XAMetadataTraversalItfAdapt_SetActiveNode");
+    mdv = XAMetadataAdapt_GetMetadataVars(bCtx);
+    if( mdv )
+    {
+        child = XAMetadataAdapt_GetChildStructure(mdv,index);
+        if(child)
+        {
+            mdv->currentchild = &child;
+            if(index==XA_NODE_PARENT) mdv->nodedepth--;
+            else mdv->nodedepth++;
+        }
+    }
+    else
+    {
+        DEBUG_ERR("Metadata variables not found!!");
+        ret = XA_RESULT_PARAMETER_INVALID;
+    }
+    DEBUG_API("<-XAMetadataTraversalItfAdapt_SetActiveNode");
+    return ret;
+}
+
+/*****************************************************************************
+ * INSERTION
+ *****************************************************************************/
+
+/*
+ * XAresult XAMetadataInsertionItfAdapt_CreateChildNode(XAAdaptationGstCtx *bCtx,
+ *                                                   XAint32 parentNodeID,
+ *                                                   XAuint32 type,
+ *                                                   XAchar *mimeType,
+ *                                                   XAint32 *pChildNodeID)
+ */
+XAresult XAMetadataInsertionItfAdapt_CreateChildNode(XAAdaptationGstCtx *bCtx,
+                                                    XAint32 parentNodeID,
+                                                    XAuint32 type,
+                                                    XAchar *mimeType,
+                                                    XAint32 *pChildNodeID)
+{
+    XAresult ret = XA_RESULT_SUCCESS;
+    XAMetadataAdaptVars* mdv=NULL;
+    XAMediaRecorderAdaptationCtx* mCtx;
+
+    DEBUG_API("->XAMetadataInsertionItfAdapt_CreateChildNode");
+    if(bCtx && bCtx->baseObj.ctxId == XAMediaRecorderAdaptation)
+    {
+        /* no support for more than 1 levels of childs*/
+        if(parentNodeID==XA_ROOT_NODE_ID)
+        {
+            XAMediaType mediaType;
+            mCtx = (XAMediaRecorderAdaptationCtx*)bCtx;
+
+            /* first check sink type */
+            XACommon_CheckDataSource((XADataSource*)(mCtx->xaSink),&mediaType);
+            if( ((mediaType==XA_MEDIATYPE_AUDIO||mediaType==XA_MEDIATYPE_VIDEO) && type==XA_NODETYPE_IMAGE) ||
+                (mediaType==XA_MEDIATYPE_IMAGE && (type==XA_NODETYPE_AUDIO || type==XA_NODETYPE_VIDEO)) )
+            {
+                DEBUG_ERR("Nodetype not supported!");
+                ret = XA_RESULT_CONTENT_UNSUPPORTED;
+                DEBUG_API_A1("<-XAMetadataInsertionItfAdapt_CreateChildNode (%d)", (int)ret);
+                return ret;            }
+
+            mdv = mCtx->metadatavars;
+            if(!mdv)
+            {
+                DEBUG_ERR("Metadata variables not initialized!");
+                ret = XA_RESULT_PRECONDITIONS_VIOLATED;
+            }
+            switch(type)
+            {
+            case XA_NODETYPE_IMAGE:
+                /*fall-through to use video pipe tags for image*/
+            case XA_NODETYPE_VIDEO:
+                if(!mCtx->videosource)
+                {
+                    DEBUG_ERR("Nodetype not found!");
+                    ret = XA_RESULT_CONTENT_UNSUPPORTED;
+                }
+                else
+                {
+                    if(!mdv->videotags)
+                    {
+                        if(strlen((char*)mimeType)==0)
+                        {
+                            mdv->videotags = gst_structure_empty_new("video/unknown");
+                        }
+                        else
+                        {
+                            mdv->videotags = gst_structure_empty_new((gchar*)mimeType);
+                        }
+                    }
+                    *pChildNodeID = (XAint32)mdv->videotags;
+                }
+                break;
+            case XA_NODETYPE_AUDIO:
+                if(!mCtx->audiosource)
+                {
+                    DEBUG_ERR("Nodetype not found!");
+                    ret = XA_RESULT_CONTENT_UNSUPPORTED;
+                }
+                else
+                {
+                    if(!mdv->audiotags)
+                    {
+                        if(strlen((char*)mimeType)==0)
+                        {
+                            mdv->audiotags = gst_structure_empty_new("audio/unknown");
+                        }
+                        else
+                        {
+                            mdv->audiotags = gst_structure_empty_new((gchar*)mimeType);
+                        }
+                    }
+                    *pChildNodeID = (XAint32)mdv->audiotags;
+                }
+                break;
+            default:
+                DEBUG_ERR("Nodetype not found!");
+                ret = XA_RESULT_CONTENT_UNSUPPORTED;
+                break;
+            }
+        }
+        else
+        {
+            DEBUG_ERR("Only root childs supported!!");
+            ret = XA_RESULT_CONTENT_UNSUPPORTED;
+        }
+    }
+    else
+    {
+        DEBUG_ERR("Unsupported metadata insertion context!!");
+        ret = XA_RESULT_PARAMETER_INVALID;
+    }
+    DEBUG_API_A1("<-XAMetadataInsertionItfAdapt_CreateChildNode (%d)", (int)ret);
+    return ret;
+}
+
+/*
+ * XAresult XAMetadataInsertionItfAdapt_GetSupportedKeysCount(XAAdaptationGstCtx *bCtx,
+ *                                                         XAint32 nodeID,
+ *                                                         XAboolean *pFreeKeys,
+ *                                                         XAuint32 *pKeyCount,
+ *                                                         XAuint32 *pEncodingCount)
+ */
+XAresult XAMetadataInsertionItfAdapt_GetSupportedKeysCount(XAAdaptationGstCtx *bCtx,
+                                                          XAint32 nodeID,
+                                                          XAboolean *pFreeKeys,
+                                                          XAuint32 *pKeyCount,
+                                                          XAuint32 *pEncodingCount)
+{
+    XAresult ret = XA_RESULT_SUCCESS;
+
+    DEBUG_API("->XAMetadataInsertionItfAdapt_GetSupportedKeysCount");
+    if(bCtx && bCtx->baseObj.ctxId == XAMediaRecorderAdaptation)
+    {
+        *pKeyCount = 0;
+        *pFreeKeys = XA_BOOLEAN_FALSE;
+        while(xaMetadataAdaptSupportedKeys[*pKeyCount])
+        {
+            (*pKeyCount)++;
+        }
+        *pEncodingCount = 1;
+    }
+    else
+    {
+        DEBUG_ERR("Unsupported metadata insertion context!!");
+        ret = XA_RESULT_PARAMETER_INVALID;
+    }
+    DEBUG_API("<-XAMetadataInsertionItfAdapt_GetSupportedKeysCount");
+    return ret;
+}
+
+/*
+ * XAresult XAMetadataInsertionItfAdapt_GetKeySize(XAAdaptationGstCtx *bCtx,
+ *                                              XAint32 nodeID,
+ *                                              XAuint32 keyIndex,
+ *                                              XAuint32 *pKeySize)
+ */
+XAresult XAMetadataInsertionItfAdapt_GetKeySize(XAAdaptationGstCtx *bCtx,
+                                               XAint32 nodeID,
+                                               XAuint32 keyIndex,
+                                               XAuint32 *pKeySize)
+{
+    XAresult ret = XA_RESULT_SUCCESS;
+
+    DEBUG_API("->XAMetadataInsertionItfAdapt_GetKeySize");
+    if(bCtx && bCtx->baseObj.ctxId == XAMediaRecorderAdaptation)
+    {
+        if(xaMetadataAdaptSupportedKeys[keyIndex])
+        {
+            *pKeySize = sizeof(XAMetadataInfo)+strlen(xaMetadataAdaptSupportedKeys[keyIndex]);
+        }
+        else
+        {
+            ret = XA_RESULT_PARAMETER_INVALID;
+        }
+    }
+    else
+    {
+        DEBUG_ERR("Unsupported metadata insertion context!!");
+        ret = XA_RESULT_PARAMETER_INVALID;
+    }
+    DEBUG_API("<-XAMetadataInsertionItfAdapt_GetKeySize");
+    return ret;
+}
+
+/*
+ * XAresult XAMetadataInsertionItfAdapt_GetKey(XAAdaptationGstCtx *bCtx,
+ *                                          XAint32 nodeID,
+ *                                          XAuint32 keyIndex,
+ *                                          XAuint32 keySize,
+ *                                          XAMetadataInfo *pKey)
+ */
+XAresult XAMetadataInsertionItfAdapt_GetKey(XAAdaptationGstCtx *bCtx,
+                                           XAint32 nodeID,
+                                           XAuint32 keyIndex,
+                                           XAuint32 keySize,
+                                           XAMetadataInfo *pKey)
+{
+    XAresult ret = XA_RESULT_SUCCESS;
+    XAuint32 datasize, neededsize;
+
+    DEBUG_API("->XAMetadataInsertionItfAdapt_GetKey");
+    if(bCtx && bCtx->baseObj.ctxId == XAMediaRecorderAdaptation)
+    {
+        memset(pKey,0,keySize);
+        if(xaMetadataAdaptSupportedKeys[keyIndex] && (keySize > sizeof(XAMetadataInfo)))
+        {
+            neededsize = strlen(xaMetadataAdaptSupportedKeys[keyIndex])+1;
+            datasize = keySize-sizeof(XAMetadataInfo)+1;
+            if(neededsize>datasize)
+            {
+                strncpy((char*)pKey->data,xaMetadataAdaptSupportedKeys[keyIndex],datasize);
+                pKey->size=datasize;
+                ret=XA_RESULT_BUFFER_INSUFFICIENT;
+            }
+            else
+            {
+                strncpy((char*)pKey->data,xaMetadataAdaptSupportedKeys[keyIndex],neededsize);
+                pKey->size=neededsize;
+            }
+            pKey->encoding = XA_CHARACTERENCODING_ASCII;
+            strcpy((char*)(pKey->langCountry),"en");
+        }
+        else
+        {
+            ret = XA_RESULT_PARAMETER_INVALID;
+        }
+    }
+    else
+    {
+        DEBUG_ERR("Unsupported metadata insertion context!!");
+        ret = XA_RESULT_PARAMETER_INVALID;
+    }
+    DEBUG_API("<-XAMetadataInsertionItfAdapt_GetKey");
+    return ret;
+}
+
+/*
+ * XAresult XAMetadataInsertionItfAdapt_GetFreeKeysEncoding(XAAdaptationGstCtx *bCtx,
+ *                                                       XAint32 nodeID,
+ *                                                       XAuint32 encodingIndex,
+ *                                                       XAuint32 *pEncoding)
+ */
+XAresult XAMetadataInsertionItfAdapt_GetFreeKeysEncoding(XAAdaptationGstCtx *bCtx,
+                                                        XAint32 nodeID,
+                                                        XAuint32 encodingIndex,
+                                                        XAuint32 *pEncoding)
+{
+    DEBUG_API("->XAMetadataInsertionItfAdapt_GetFreeKeysEncoding");
+    DEBUG_API("<-XAMetadataInsertionItfAdapt_GetFreeKeysEncoding");
+    /* no free keys*/
+    return XA_RESULT_PRECONDITIONS_VIOLATED;
+}
+
+/*
+ * XAresult XAMetadataInsertionItfAdapt_InsertMetadataItem(XAAdaptationGstCtx *bCtx,
+ *                                                      XAint32 nodeID,
+ *                                                      XAMetadataInfo *pKey,
+ *                                                      XAMetadataInfo *pValue,
+ *                                                      XAboolean overwrite)
+ */
+XAresult XAMetadataInsertionItfAdapt_InsertMetadataItem(XAAdaptationGstCtx *bCtx,
+                                                       XAint32 nodeID,
+                                                       XAMetadataInfo *pKey,
+                                                       XAMetadataInfo *pValue,
+                                                       XAboolean overwrite)
+{
+    XAresult ret = XA_RESULT_SUCCESS;
+    XAMetadataAdaptVars* mdv=NULL;
+    XAMediaRecorderAdaptationCtx* mCtx;
+    GstTagMergeMode mode = (overwrite?GST_TAG_MERGE_REPLACE:GST_TAG_MERGE_KEEP);
+    gchar* parsedKey = (gchar*)XAMetadataAdapt_ParseKhronosKey((XAchar*)pKey->data);
+    DEBUG_API("->XAMetadataInsertionItfAdapt_InsertMetadataItem");
+    if(bCtx && bCtx->baseObj.ctxId == XAMediaRecorderAdaptation)
+    {
+        mCtx = (XAMediaRecorderAdaptationCtx*)bCtx;
+        mdv = mCtx->metadatavars;
+        if(mdv)
+        {
+            if( nodeID==XA_ROOT_NODE_ID )
+            {
+                if(!mdv->generaltags)
+                {
+                    mdv->generaltags = gst_tag_list_new();
+                }
+                if (gst_tag_get_type (parsedKey) == G_TYPE_STRING)
+                {
+                    gst_tag_list_add(mdv->generaltags, mode, parsedKey, (gchar*)pValue->data, NULL );
+                }
+                else
+                {
+                    gst_tag_list_add(mdv->generaltags, mode, parsedKey, atoi((gchar*)pValue->data), NULL );
+                }
+            }
+            else
+            {
+                if(nodeID == (XAint32)mdv->audiotags || nodeID == (XAint32)mdv->videotags)
+                {
+                    if (gst_tag_get_type (parsedKey) == G_TYPE_STRING)
+                    {
+                        gst_structure_set((GstStructure*)nodeID, parsedKey, G_TYPE_STRING, g_strdup((gchar*)pValue->data), NULL );
+                    }
+                    else
+                    {
+                        gst_structure_set((GstStructure*)nodeID, parsedKey, gst_tag_get_type (parsedKey), atoi((gchar*)pValue->data), NULL );
+                    }
+                }
+                else
+                {
+                    DEBUG_ERR("Unknown node!!");
+                    ret = XA_RESULT_PARAMETER_INVALID;
+                }
+            }
+            if( ret == XA_RESULT_SUCCESS )
+            {   /* let (possible) extraction itf to know new tags  */
+                XAAdaptEvent event = {XA_METADATAEVENTS, XA_ADAPT_MDE_TAGS_AVAILABLE, 0, NULL };
+                XAAdaptationBase_SendAdaptEvents(&bCtx->baseObj, &event );
+            }
+        }
+        else
+        {
+            DEBUG_ERR("Metadata not initialized!!");
+            ret = XA_RESULT_PARAMETER_INVALID;
+        }
+    }
+    else
+    {
+        DEBUG_ERR("Unsupported metadata insertion context!!");
+        ret = XA_RESULT_PARAMETER_INVALID;
+    }
+    DEBUG_API("<-XAMetadataInsertionItfAdapt_InsertMetadataItem");
+    return ret;
+}
+
+/*****************************************************************************
+ * INTERNALS
+ *****************************************************************************/
+
+
+/*
+ * GstStructure* XAMetadataAdapt_GetChildStructure(XAMetadataAdaptVars* mdv, XAuint32 index)
+ * helper to get gst structure corresponding to child index
+ */
+GstStructure* XAMetadataAdapt_GetChildStructure(XAMetadataAdaptVars* mdv, XAuint32 index)
+{
+    if(mdv->nodedepth == 0)
+    {   /*root childs, if existent, the order is 1)video 2)audio*/
+        if (index==0)
+        {
+            if(mdv->videotags) return mdv->videotags;
+            else if (mdv->audiotags) return mdv->audiotags;
+        }
+        else if (index==1)
+        {
+            if (mdv->audiotags) return mdv->audiotags;
+        }
+    }
+    else
+    {
+        if(index==XA_NODE_PARENT)
+        {
+            return GST_STRUCTURE(mdv->generaltags);
+        }
+    }
+    /*else*/
+    return NULL;
+}
+
+/*
+ * XAMetadataAdaptVars* XAMetadataAdapt_GetMetadataVars(XAAdaptationGstCtx *bCtx)
+ * Return metadata variables from different types of context
+ */
+XAMetadataAdaptVars* XAMetadataAdapt_GetMetadataVars(XAAdaptationGstCtx *bCtx)
+{
+    if( bCtx->baseObj.ctxId == XAMDAdaptation ||
+        bCtx->baseObj.ctxId == XAMediaPlayerAdaptation )
+    {
+        return ((XAMediaPlayerAdaptationCtx*)bCtx)->metadatavars;
+    }
+    else if( bCtx->baseObj.ctxId == XAMediaRecorderAdaptation )
+    {
+        return ((XAMediaRecorderAdaptationCtx*)bCtx)->metadatavars;
+    }
+    else
+    {
+        DEBUG_ERR("Invalid context for metadata");
+        return NULL;
+    }
+}
+
+/*
+ * gboolean XAMetadataAdapt_CountTags(GQuark field_id, const GValue* value, gpointer counter)
+ * GstStructureForeachFunc to count number of items inside list
+ */
+gboolean XAMetadataAdapt_CountTags(GQuark field_id, const GValue* value, gpointer counter)
+{
+    XAuint32* cnt = (XAuint32*)counter;
+    (*cnt)++;
+    return TRUE;
+}
+
+/*
+ * void XAMetadataAdapt_ParseTag(const GstTagList* list, const gchar* tag, gpointer listptr)
+ * GstTaglistForeachFunc to parse items inside gsttaglist
+ */
+void XAMetadataAdapt_ParseTag(const GstTagList* list, const gchar* tag, gpointer listptr)
+{
+    XAMetadataImplTagList* tagList = (XAMetadataImplTagList*)listptr;
+    const gchar *key;
+    gchar *value;
+    guint32 keylen, valuelen;
+
+    DEBUG_API("->XAMetadataAdapt_ParseTag");
+    key = gst_tag_get_nick(tag);
+    /*include null-terminator*/
+    keylen = strlen(key)+1;
+    tagList->mdeKeys[tagList->itemcount] = (XAMetadataInfo*)calloc(1,keylen+sizeof(XAMetadataInfo));
+    tagList->mdeKeys[tagList->itemcount]->size = keylen;
+    strncpy((char*)tagList->mdeKeys[tagList->itemcount]->data,key,keylen-1);
+
+    if (gst_tag_get_type (tag) == G_TYPE_STRING)
+    {
+        gst_tag_list_get_string_index(list, tag, 0, &value);
+    }
+    else
+    {
+        value = g_strdup_value_contents (gst_tag_list_get_value_index (list, tag, 0));
+    }
+    /*include null-terminator*/
+    valuelen = strlen(value)+1;
+    tagList->mdeValues[tagList->itemcount] = (XAMetadataInfo*)calloc(1,valuelen+sizeof(XAMetadataInfo));
+    tagList->mdeValues[tagList->itemcount]->size = valuelen;
+    strncpy((char*)tagList->mdeValues[tagList->itemcount]->data,value,valuelen-1);
+
+    /* NOTE: for now, encoding and language fixed */
+    tagList->mdeKeys[tagList->itemcount]->encoding = XA_CHARACTERENCODING_ASCII;
+    tagList->mdeValues[tagList->itemcount]->encoding = XA_CHARACTERENCODING_ASCII;
+    strcpy((char*)tagList->mdeKeys[tagList->itemcount]->langCountry,"en");
+    strcpy((char*)tagList->mdeValues[tagList->itemcount]->langCountry,"en");
+    tagList->itemcount++;
+    DEBUG_API_A2("<-XAMetadataAdapt_ParseTag: added %s : %s",
+                 tagList->mdeKeys[tagList->itemcount-1]->data,
+                 tagList->mdeValues[tagList->itemcount-1]->data);
+}
+
+/*
+ * gboolean XAMetadataAdapt_ParseItem(GQuark gkey,
+ *                                const GValue* gvalue,
+ *                                gpointer listptr)
+ * GstStructureForeachFunc to parse items inside caps structure
+ */
+gboolean XAMetadataAdapt_ParseItem(GQuark gkey,
+                                 const GValue* gvalue,
+                                 gpointer listptr)
+{
+    XAMetadataImplTagList* tagList = (XAMetadataImplTagList*)listptr;
+    const gchar *key;
+    gchar *value;
+    guint32 keylen, valuelen;
+
+    DEBUG_API("->XAMetadataAdapt_ParseItem");
+    key = g_quark_to_string(gkey);
+    /*include null-terminator*/
+    keylen = strlen(key)+1;
+    tagList->mdeKeys[tagList->itemcount] = (XAMetadataInfo*)calloc(1,keylen+sizeof(XAMetadataInfo));
+    tagList->mdeKeys[tagList->itemcount]->size = keylen;
+    strncpy((char*)tagList->mdeKeys[tagList->itemcount]->data,key,keylen-1);
+
+    value = gst_value_serialize(gvalue);
+    /*include null-terminator*/
+    valuelen = strlen(value)+1;
+    tagList->mdeValues[tagList->itemcount] = (XAMetadataInfo*)calloc(1,valuelen+sizeof(XAMetadataInfo));
+    tagList->mdeValues[tagList->itemcount]->size = valuelen;
+    strncpy((char*)tagList->mdeValues[tagList->itemcount]->data,value,valuelen-1);
+
+    /* for Gst, encoding and language fixed */
+    tagList->mdeKeys[tagList->itemcount]->encoding = XA_CHARACTERENCODING_ASCII;
+    tagList->mdeValues[tagList->itemcount]->encoding = XA_CHARACTERENCODING_ASCII;
+    strcpy((char*)tagList->mdeKeys[tagList->itemcount]->langCountry,"en");
+    strcpy((char*)tagList->mdeValues[tagList->itemcount]->langCountry,"en");
+    tagList->itemcount++;
+    DEBUG_API_A2("<-XAMetadataAdapt_ParseItem: added %15s : %s",
+                 tagList->mdeKeys[tagList->itemcount-1]->data,
+                 tagList->mdeValues[tagList->itemcount-1]->data);
+    return TRUE;
+}
+
+/*
+ * gboolean XAMetadataAdapt_GstTagCb( GstBus *bus, GstMessage *message, gpointer data )
+ * Metadata callback - called when new tags found from stream
+ */
+gboolean XAMetadataAdapt_GstTagCb( GstBus *bus, GstMessage *message, gpointer data )
+{
+    GstTagList *new_tags;
+    GstTagList **old_tags = NULL;
+    XAAdaptationGstCtx* bCtx;
+    GstTagMergeMode mode;
+
+    bCtx = (XAAdaptationGstCtx*)data;
+    if(GST_MESSAGE_TAG==GST_MESSAGE_TYPE(message))
+    {
+        DEBUG_API_A2("->XAMetadataAdapt_GstTagCb:\"%s\" from object \"%s\"",
+                        GST_MESSAGE_TYPE_NAME(message), GST_OBJECT_NAME(GST_MESSAGE_SRC(message)));
+        gst_message_parse_tag (message, &new_tags);
+        /* NOTE: only general tags received this way (not child nodes)*/
+        if( bCtx->baseObj.ctxId == XAMDAdaptation ||
+            bCtx->baseObj.ctxId == XAMediaPlayerAdaptation )
+        {
+            old_tags = &((XAMediaPlayerAdaptationCtx*)bCtx)->metadatavars->generaltags;
+            mode = GST_TAG_MERGE_REPLACE;
+        }
+        else if( bCtx->baseObj.ctxId == XAMediaRecorderAdaptation )
+        {
+            old_tags = &((XAMediaRecorderAdaptationCtx*)bCtx)->metadatavars->generaltags;
+            /* keep user's tags */
+            mode = GST_TAG_MERGE_KEEP;
+        }
+        else
+        {   /*context not applicable*/
+            return TRUE;
+        }
+
+        if( *old_tags )
+            *old_tags = gst_tag_list_merge (*old_tags, new_tags, mode);
+        else
+            *old_tags = new_tags;
+
+        if( GST_STATE(bCtx->bin)==GST_STATE_PLAYING )
+        {   /* send event only for live stream, otherwise wait for preroll to complete */
+            XAAdaptEvent event = {XA_METADATAEVENTS, XA_ADAPT_MDE_TAGS_AVAILABLE, 0, NULL };
+            XAAdaptationBase_SendAdaptEvents(&bCtx->baseObj, &event );
+        }
+        DEBUG_API("<-XAMetadataAdapt_GstTagCb");
+    }
+    return TRUE;
+}
+
+/*
+ * void XAMetadataAdapt_TryWriteTag(const GstTagList* list, const gchar* tag, gpointer taggerptr)
+ * GstTaglistForeachFunc to write single tag entries to stream
+ */
+void XAMetadataAdapt_TryWriteTag(const GstTagList* list, const gchar* tag, gpointer taggerptr)
+{
+    GstTagSetter* tagger = (GstTagSetter*)taggerptr;
+    const gchar *key;
+    gchar *value;
+
+    DEBUG_API("->XAMetadataAdapt_ParseTag");
+    key = gst_tag_get_nick(tag);
+    if (gst_tag_get_type (tag) == G_TYPE_STRING)
+    {
+        gst_tag_list_get_string_index(list, tag, 0, &value);
+    }
+    else
+    {
+        value = g_strdup_value_contents (gst_tag_list_get_value_index (list, tag, 0));
+    }
+    gst_tag_setter_add_tags(tagger, GST_TAG_MERGE_REPLACE, key, value, NULL);
+}
+
+/*
+ * XAresult XAMetadataAdapt_TryWriteTags(XAAdaptationGstCtx* bCtx, GstBin* binToWriteTo)
+ */
+XAresult XAMetadataAdapt_TryWriteTags(XAAdaptationGstCtx* bCtx, GstBin* binToWriteTo)
+{
+    XAresult ret = XA_RESULT_SUCCESS;
+    GstTagSetter *tagger=NULL;
+    /* Find metadata tagger from bin (if any) */
+    GstIterator *iter = gst_bin_iterate_all_by_interface( binToWriteTo, GST_TYPE_TAG_SETTER );
+    gboolean done = FALSE;
+    XAMediaRecorderAdaptationCtx* mCtx;
+    XAAdaptEvent mdevent = {XA_METADATAEVENTS, XA_ADAPT_MDE_TAGS_WRITTEN, 0, NULL };
+
+    DEBUG_API("->XAMetadataAdapt_TryWriteTags");
+
+    if( bCtx->baseObj.ctxId != XAMediaRecorderAdaptation )
+    {
+        return XA_RESULT_FEATURE_UNSUPPORTED;
+    }
+    mCtx = ((XAMediaRecorderAdaptationCtx*)bCtx);
+    while (!done)
+    {
+        switch (gst_iterator_next(iter, (gpointer)&tagger))
+        {
+        case GST_ITERATOR_OK:
+            if(mCtx->metadatavars)
+            {
+                if(mCtx->metadatavars->generaltags)
+                {
+                    gst_tag_setter_merge_tags(tagger, mCtx->metadatavars->generaltags, GST_TAG_MERGE_REPLACE);
+                }
+            }
+            done = TRUE;
+        break;
+        case GST_ITERATOR_ERROR:
+            done = TRUE;
+            DEBUG_ERR("Pipeline does not support tag setting");
+            ret = XA_RESULT_CONTENT_UNSUPPORTED;
+        break;
+        case GST_ITERATOR_DONE:
+            done = TRUE;
+            DEBUG_ERR("Pipeline does not support tag setting");
+            ret = XA_RESULT_CONTENT_UNSUPPORTED;
+        break;
+        case GST_ITERATOR_RESYNC:
+            gst_iterator_resync(iter);
+        break;
+        }
+    }
+    /*here datasize field is used for return value*/
+    mdevent.datasize = ret;
+    XAAdaptationBase_SendAdaptEvents(&bCtx->baseObj, &mdevent );
+    gst_iterator_free (iter);
+    DEBUG_API("<-XAMetadataAdapt_TryWriteTags");
+    return ret;
+}