khronosfws/openmax_al/src/gst_adaptation/xametadataadaptation.c
changeset 16 43d09473c595
child 20 b67dd1fc57c5
equal deleted inserted replaced
14:80975da52420 16:43d09473c595
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 #include <string.h>
       
    19 #include <gst.h>
       
    20 #include "xaadaptationgst.h"
       
    21 #include "xametadataadaptctx.h"
       
    22 #include "xamediaplayeradaptctx.h"
       
    23 #include "xamediarecorderadaptctx.h"
       
    24 #include "xametadataadaptation.h"
       
    25 
       
    26 /* forward declarations of internal methods */
       
    27 XAMetadataAdaptVars* XAMetadataAdapt_GetMetadataVars(XAAdaptationGstCtx *bCtx);
       
    28 GstStructure* XAMetadataAdapt_GetChildStructure(XAMetadataAdaptVars* mdv, XAuint32 index);
       
    29 gboolean XAMetadataAdapt_CountTags(GQuark gkey, const GValue *gvalue, gpointer counter);
       
    30 void XAMetadataAdapt_ParseTag(const GstTagList* list, const gchar* tag, gpointer listptr);
       
    31 gboolean XAMetadataAdapt_ParseItem(GQuark field_id, const GValue * value, gpointer listptr);
       
    32 gboolean XAMetadataAdapt_GstTagCb( GstBus *bus, GstMessage *message, gpointer data );
       
    33 
       
    34 /*NOTE: no way to query these dynamically?*/
       
    35 /*supported keys for metadata insertion*/
       
    36 static char* xaMetadataAdaptSupportedKeys[] = {
       
    37     KHRONOS_TITLE,
       
    38     KHRONOS_ALBUM,
       
    39     KHRONOS_TRACK_NUMBER,
       
    40     KHRONOS_ARTIST,
       
    41     KHRONOS_GENRE,
       
    42     KHRONOS_COMMENT,
       
    43     KHRONOS_COPYRIGHT,
       
    44     GST_TAG_TITLE,
       
    45     GST_TAG_TITLE_SORTNAME,
       
    46     GST_TAG_ARTIST,
       
    47     GST_TAG_ARTIST_SORTNAME,
       
    48     GST_TAG_ALBUM,
       
    49     GST_TAG_ALBUM_SORTNAME,
       
    50     GST_TAG_COMPOSER,
       
    51     GST_TAG_DATE,
       
    52     GST_TAG_GENRE,
       
    53     GST_TAG_COMMENT,
       
    54     GST_TAG_EXTENDED_COMMENT,
       
    55     GST_TAG_TRACK_NUMBER,
       
    56     GST_TAG_TRACK_COUNT,
       
    57     GST_TAG_ALBUM_VOLUME_NUMBER,
       
    58     GST_TAG_ALBUM_VOLUME_COUNT,
       
    59     GST_TAG_LOCATION,
       
    60     GST_TAG_DESCRIPTION,
       
    61     GST_TAG_VERSION,
       
    62     GST_TAG_ISRC,
       
    63     GST_TAG_ORGANIZATION,
       
    64     GST_TAG_COPYRIGHT,
       
    65     GST_TAG_COPYRIGHT_URI,
       
    66     GST_TAG_CONTACT,
       
    67     GST_TAG_LICENSE,
       
    68     GST_TAG_LICENSE_URI,
       
    69     GST_TAG_PERFORMER,
       
    70     NULL
       
    71 };
       
    72 
       
    73 /******************************************************************************
       
    74  * COMMONS
       
    75  ******************************************************************************/
       
    76 
       
    77 
       
    78 /* const char* XAMetadataAdapt_ParseKhronosKey(const char* pKKey)
       
    79  * Translates Khronos key string to adaptation-specific key string
       
    80  * @return Translated key string
       
    81  */
       
    82 const XAchar* XAMetadataAdapt_ParseKhronosKey(const XAchar* pKKey)
       
    83 {
       
    84     const XAchar* newKey;
       
    85     DEBUG_API_A1("->XAMetadataAdapt_ParseKhronosKey: \"%s\"", (char*)pKKey);
       
    86     if( strcmp((char*)pKKey,KHRONOS_TITLE) ==0 ) newKey = (XAchar*)GST_TAG_TITLE;
       
    87     else if( strcmp((char*)pKKey,KHRONOS_ALBUM) ==0 ) newKey = (XAchar*)GST_TAG_ALBUM;
       
    88     else if( strcmp((char*)pKKey,KHRONOS_TRACK_NUMBER) ==0 ) newKey = (XAchar*)GST_TAG_TRACK_NUMBER;
       
    89     else if( strcmp((char*)pKKey,KHRONOS_ARTIST) ==0 ) newKey = (XAchar*)GST_TAG_ARTIST;
       
    90     else if( strcmp((char*)pKKey,KHRONOS_GENRE) ==0 ) newKey = (XAchar*)GST_TAG_GENRE;
       
    91     else if( strcmp((char*)pKKey,KHRONOS_COMMENT) ==0 ) newKey = (XAchar*)GST_TAG_COMMENT;
       
    92     else if( strcmp((char*)pKKey,KHRONOS_COPYRIGHT) ==0 ) newKey = (XAchar*)GST_TAG_COPYRIGHT;
       
    93     else newKey = pKKey;
       
    94 /* No Gst keys for following:
       
    95     else if( strcmp(pKKey,KHRONOS_YEAR) ==0 ) newKey = ;
       
    96     else if( strcmp(pKKey,KHRONOS_ARTIST_URL) ==0 ) newKey = ;
       
    97     else if( strcmp(pKKey,KHRONOS_CONTENT_URL) ==0 ) newKey = ;
       
    98     else if( strcmp(pKKey,KHRONOS_RATING) ==0 ) newKey = ;
       
    99     else if( strcmp(pKKey,KHRONOS_ALBUM_ART) ==0 ) newKey = ;
       
   100  */
       
   101     DEBUG_API_A1("<-XAMetadataAdapt_ParseKhronosKey: => \"%s\"", (char*)newKey);
       
   102     return newKey;
       
   103 }
       
   104 
       
   105 /* XAresult XAMetadataAdapt_PreInit(XAAdaptationGstCtx *bCtx)
       
   106  * Initialize values needed before preroll
       
   107  * @return XAresult ret - Success value
       
   108  */
       
   109 XAresult XAMetadataAdapt_PreInit(XAAdaptationGstCtx *bCtx)
       
   110 {
       
   111     XAresult ret = XA_RESULT_SUCCESS;
       
   112     XAMetadataAdaptVars* mdv;
       
   113     DEBUG_API("->XAMetadataAdapt_PreInit");
       
   114     if( bCtx->baseObj.ctxId == XAMDAdaptation ||
       
   115         bCtx->baseObj.ctxId == XAMediaPlayerAdaptation )
       
   116     {
       
   117         mdv = (XAMetadataAdaptVars*) calloc(1, sizeof(XAMetadataAdaptVars));
       
   118         mdv->currentchild = &(mdv->generaltags);
       
   119         mdv->traversemode=XA_METADATATRAVERSALMODE_NODE;
       
   120         ((XAMediaPlayerAdaptationCtx*)bCtx)->metadatavars = mdv;
       
   121 
       
   122     }
       
   123     else if ( bCtx->baseObj.ctxId == XAMediaRecorderAdaptation )
       
   124     {
       
   125         mdv = (XAMetadataAdaptVars*) calloc(1, sizeof(XAMetadataAdaptVars));
       
   126         mdv->currentchild = &(mdv->generaltags);
       
   127         mdv->traversemode=XA_METADATATRAVERSALMODE_NODE;
       
   128         ((XAMediaRecorderAdaptationCtx*)bCtx)->metadatavars = mdv;
       
   129     }
       
   130     else
       
   131     {
       
   132         DEBUG_ERR("Unsupported metadata context!!");
       
   133         ret = XA_RESULT_FEATURE_UNSUPPORTED;
       
   134     }
       
   135 
       
   136     if(ret == XA_RESULT_SUCCESS)
       
   137     {
       
   138         if(bCtx->bus)
       
   139         {
       
   140             g_signal_connect(bCtx->bus, "message::tag", G_CALLBACK(XAMetadataAdapt_GstTagCb), bCtx );
       
   141         }
       
   142         else
       
   143         {
       
   144             DEBUG_ERR("No bus in context!!");
       
   145             ret = XA_RESULT_PRECONDITIONS_VIOLATED;
       
   146         }
       
   147     }
       
   148     DEBUG_API_A1("<-XAMetadataAdapt_PreInit (%d)", (int)ret);
       
   149     return ret;
       
   150 }
       
   151 /* XAresult XAMetadataAdapt_PostInit(XAAdaptationGstCtx *bCtx)
       
   152  * Initialize values after preroll
       
   153  * @return XAresult ret - Success value
       
   154  */
       
   155 XAresult XAMetadataAdapt_PostInit(XAAdaptationGstCtx *bCtx)
       
   156 {
       
   157     XAresult ret = XA_RESULT_SUCCESS;
       
   158     XAMetadataAdaptVars* mdv=NULL;
       
   159     XAMediaPlayerAdaptationCtx* mCtx=NULL;
       
   160     GstPad* tmppad=NULL;
       
   161     GstCaps* tmpcaps=NULL;
       
   162     GstElement* tmpelement=NULL;
       
   163     XAAdaptEvent event = {XA_METADATAEVENTS, XA_ADAPT_MDE_TAGS_AVAILABLE, 0, NULL };
       
   164 
       
   165     DEBUG_API("->XAMetadataAdapt_PostInit");
       
   166     if( bCtx->baseObj.ctxId == XAMDAdaptation ||
       
   167         bCtx->baseObj.ctxId == XAMediaPlayerAdaptation )
       
   168     {
       
   169         mdv = XAMetadataAdapt_GetMetadataVars(bCtx);
       
   170         if( mdv )
       
   171         {
       
   172             mdv->childcount = 0;
       
   173             /* try to dig out audio and video pads from decodebin for stream info tags */
       
   174             /* NOTE: currently no good deterministic way to dig out undecoded pads
       
   175              * from decodebin's internal demuxer, this is just ugly way to try to cope
       
   176              * with most demuxers.
       
   177              */
       
   178             mCtx = ((XAMediaPlayerAdaptationCtx*)bCtx);
       
   179             if(GST_IS_BIN(mCtx->codecbin))
       
   180             {
       
   181                 tmpelement=gst_bin_get_by_name(GST_BIN(mCtx->codecbin),"typefind");
       
   182                 if(tmpelement)
       
   183                 {
       
   184                     tmppad = gst_element_get_static_pad(GST_ELEMENT(tmpelement),"src");
       
   185                     tmpelement=NULL;
       
   186                     if(tmppad)
       
   187                     {
       
   188                         tmppad = gst_pad_get_peer(tmppad);
       
   189                         if(tmppad)
       
   190                         {
       
   191                             tmpelement = gst_pad_get_parent_element(tmppad);
       
   192                         }
       
   193                     }
       
   194                     /* now we have demuxer, if existing */
       
   195                     if(tmpelement)
       
   196                     {
       
   197                         tmppad = gst_element_get_pad( tmpelement, "audio_00");
       
   198                         if(tmppad)
       
   199                         {
       
   200                             tmpcaps = gst_pad_get_negotiated_caps( GST_PAD(tmppad) );
       
   201                             if(tmpcaps==NULL || gst_caps_is_any(tmpcaps) || gst_caps_is_empty(tmpcaps))
       
   202                             {
       
   203                                 mdv->audiotags = NULL;
       
   204                                 DEBUG_INFO("no usable audio properties found from pad !");
       
   205                             }
       
   206                             else
       
   207                             {
       
   208                                 mdv->audiotags = gst_caps_get_structure(tmpcaps,0);
       
   209                                 mdv->childcount++;
       
   210                                 DEBUG_INFO_A1("found audio node: %s",gst_caps_to_string(tmpcaps));
       
   211                             }
       
   212                         }
       
   213                         tmppad = gst_element_get_pad( tmpelement, "video_00");
       
   214                         if(tmppad)
       
   215                         {
       
   216                             tmpcaps = gst_pad_get_negotiated_caps( GST_PAD(tmppad) );
       
   217                             if(tmpcaps==NULL || gst_caps_is_any(tmpcaps) || gst_caps_is_empty(tmpcaps))
       
   218                             {
       
   219                                 mdv->videotags = NULL;
       
   220                                 DEBUG_INFO("no usable video properties found from pad !");
       
   221                             }
       
   222                             else
       
   223                             {
       
   224                                 mdv->videotags = gst_caps_get_structure(tmpcaps,0);
       
   225                                 mdv->childcount++;
       
   226                                 DEBUG_INFO_A1("found video node: %s",gst_caps_to_string(tmpcaps));
       
   227                             }
       
   228                         }
       
   229                     }
       
   230                 }
       
   231             }
       
   232             XAAdaptationBase_SendAdaptEvents(&bCtx->baseObj, &event );
       
   233         }
       
   234     }
       
   235 
       
   236     if ( tmpelement )
       
   237     {
       
   238     	gst_object_unref( tmpelement );
       
   239     }
       
   240     if ( tmppad )
       
   241     {
       
   242     	gst_object_unref( tmppad );
       
   243     }
       
   244     if ( tmpcaps )
       
   245     {
       
   246     	gst_object_unref( tmpcaps );
       
   247     }
       
   248 
       
   249     DEBUG_API_A1("<-XAMetadataAdapt_PostInit (%d)", (int)ret);
       
   250     return ret;
       
   251 }
       
   252 
       
   253 /*
       
   254  * void XAMetadataAdapt_FreeImplTagList(XAMetadataImplTagList *list, XAboolean freeItems)
       
   255  * deallocate elements inside taglist
       
   256  */
       
   257 void XAMetadataAdapt_FreeImplTagList(XAMetadataImplTagList *list, XAboolean freeItems)
       
   258 {
       
   259     XAuint16 i;
       
   260     DEBUG_API("->XAMetadataExtractionItfAdapt_FreeTagList");
       
   261     if(list->mdeKeys)
       
   262     {
       
   263         for(i=0;i<list->itemcount;i++)
       
   264         {
       
   265             if(list->mdeKeys[i])
       
   266             {
       
   267                 if(freeItems)
       
   268                     free(list->mdeKeys[i]);
       
   269                 list->mdeKeys[i]=NULL;
       
   270             }
       
   271         }
       
   272         free(list->mdeKeys);
       
   273         list->mdeKeys = NULL;
       
   274     }
       
   275     if(list->mdeValues)
       
   276     {
       
   277         for(i=0;i<list->itemcount;i++)
       
   278         {
       
   279             if(list->mdeValues[i])
       
   280             {
       
   281                 if(freeItems)
       
   282                     free(list->mdeValues[i]);
       
   283                 list->mdeValues[i]=NULL;
       
   284             }
       
   285         }
       
   286         free(list->mdeValues);
       
   287         list->mdeValues = NULL;
       
   288     }
       
   289     list->itemcount = 0;
       
   290     DEBUG_API("<-XAMetadataExtractionItfAdapt_FreeTagList");
       
   291 }
       
   292 
       
   293 /*
       
   294  * void XAMetadataAdapt_FreeVars(XAMetadataAdaptVars *vars)
       
   295  * deallocate XAMetadataAdaptVars
       
   296  */
       
   297 void XAMetadataAdapt_FreeVars(XAMetadataAdaptVars *vars)
       
   298 {
       
   299     DEBUG_API("->XAMetadataAdapt_FreeVars");
       
   300     if(vars)
       
   301     {
       
   302         if( vars->generaltags )
       
   303         {
       
   304             gst_tag_list_free(vars->generaltags);
       
   305         }
       
   306         if( vars->audiotags )
       
   307         {
       
   308             gst_structure_set_parent_refcount(vars->audiotags,NULL);
       
   309             gst_structure_free(vars->audiotags);
       
   310         }
       
   311         if( vars->videotags )
       
   312         {
       
   313             gst_structure_set_parent_refcount(vars->videotags,NULL);
       
   314             gst_structure_free(vars->videotags);
       
   315         }
       
   316         free(vars);
       
   317     }
       
   318     DEBUG_API("<-XAMetadataAdapt_FreeVars");
       
   319 }
       
   320 
       
   321 /******************************************************************************
       
   322  * EXTRACTION
       
   323  ******************************************************************************/
       
   324 
       
   325 /*
       
   326  * XAresult XAMetadataExtractionItfAdapt_FillTagList()
       
   327  * @param tagList - contains pointer to tag list to be updated
       
   328  * @return XAresult ret - Success value
       
   329  */
       
   330 XAresult XAMetadataExtractionItfAdapt_FillTagList(XAAdaptationGstCtx *bCtx,
       
   331                                                   XAMetadataImplTagList* tagList)
       
   332 {
       
   333     XAresult ret = XA_RESULT_SUCCESS;
       
   334     XAMetadataAdaptVars* mdv;
       
   335     XAuint32 newcount = 0;
       
   336     DEBUG_API("->XAMetadataExtractionItfAdapt_FillTagList");
       
   337 
       
   338     mdv = XAMetadataAdapt_GetMetadataVars(bCtx);
       
   339     if( mdv )
       
   340     {
       
   341         XAMetadataAdapt_FreeImplTagList(tagList, XA_BOOLEAN_TRUE);
       
   342         /* get number of tags and allocate memory for them */
       
   343         if(mdv->traversemode==XA_METADATATRAVERSALMODE_ALL)
       
   344         {
       
   345             if(mdv->generaltags)
       
   346                 gst_structure_foreach(mdv->generaltags, XAMetadataAdapt_CountTags, &newcount);
       
   347             if(mdv->audiotags)
       
   348                 gst_structure_foreach(mdv->audiotags, XAMetadataAdapt_CountTags, &newcount);
       
   349             if(mdv->videotags)
       
   350                 gst_structure_foreach(mdv->videotags, XAMetadataAdapt_CountTags, &newcount);
       
   351         }
       
   352         else
       
   353         {
       
   354             if(mdv->currentchild && *(mdv->currentchild))
       
   355                 gst_structure_foreach(*(mdv->currentchild), XAMetadataAdapt_CountTags, &newcount);
       
   356         }
       
   357         DEBUG_INFO_A1("tag count = %d",(int)newcount)
       
   358         tagList->mdeKeys = (XAMetadataInfo**)calloc(newcount,sizeof(XAMetadataInfo*));
       
   359         tagList->mdeValues = (XAMetadataInfo**)calloc(newcount,sizeof(XAMetadataInfo*));
       
   360 
       
   361         /* fill in given tag list */
       
   362         tagList->itemcount = 0;
       
   363         if(mdv->traversemode==XA_METADATATRAVERSALMODE_ALL)
       
   364         {
       
   365             if(mdv->generaltags)
       
   366                 gst_tag_list_foreach(mdv->generaltags, XAMetadataAdapt_ParseTag, tagList);
       
   367             if(mdv->audiotags)
       
   368                 gst_structure_foreach(mdv->audiotags, XAMetadataAdapt_ParseItem, tagList);
       
   369             if(mdv->videotags)
       
   370                 gst_structure_foreach(mdv->videotags, XAMetadataAdapt_ParseItem, tagList);
       
   371         }
       
   372         else
       
   373         {
       
   374             if(mdv->currentchild && *(mdv->currentchild))
       
   375             {
       
   376                 if(GST_IS_TAG_LIST(*(mdv->currentchild)))
       
   377                 {
       
   378                     gst_tag_list_foreach(*(mdv->currentchild), XAMetadataAdapt_ParseTag, tagList);
       
   379                 }
       
   380                 else
       
   381                 {
       
   382                     gst_structure_foreach(*(mdv->currentchild), XAMetadataAdapt_ParseItem, tagList);
       
   383                 }
       
   384             }
       
   385         }
       
   386     }
       
   387     else
       
   388     {
       
   389         DEBUG_ERR("Metadata variables not found!!");
       
   390         ret = XA_RESULT_PARAMETER_INVALID;
       
   391     }
       
   392 
       
   393     DEBUG_API_A1("<-XAMetadataExtractionItfAdapt_FillTagList (%d)", (int)ret);
       
   394     return ret;
       
   395 }
       
   396 
       
   397 /******************************************************************************
       
   398  * TRAVERSAL
       
   399  *****************************************************************************/
       
   400 
       
   401 /*
       
   402  * XAresult XAMetadataTraversalItfAdapt_SetMode(XAAdaptationGstCtx *bCtx, XAuint32 mode)
       
   403  */
       
   404 XAresult XAMetadataTraversalItfAdapt_SetMode(XAAdaptationGstCtx *bCtx, XAuint32 mode)
       
   405 {
       
   406     XAresult ret = XA_RESULT_SUCCESS;
       
   407     XAMetadataAdaptVars* mdv=NULL;
       
   408     XAAdaptEvent event = {XA_METADATAEVENTS, XA_ADAPT_MDE_TAGS_AVAILABLE, 0, NULL };
       
   409 
       
   410     DEBUG_API("->XAMetadataTraversalItfAdapt_SetMode");
       
   411     mdv = XAMetadataAdapt_GetMetadataVars(bCtx);
       
   412     if( mdv )
       
   413     {
       
   414         mdv->traversemode = mode;
       
   415         /* inform extractor to update tag list */
       
   416         XAAdaptationBase_SendAdaptEvents(&bCtx->baseObj, &event );
       
   417         if(mdv->traversemode==XA_METADATATRAVERSALMODE_ALL)
       
   418         {
       
   419             mdv->nodedepth = 0;
       
   420             mdv->currentchild = &(mdv->generaltags);
       
   421         }
       
   422     }
       
   423     else
       
   424     {
       
   425         DEBUG_ERR("Metadata variables not found!!");
       
   426         ret = XA_RESULT_PARAMETER_INVALID;
       
   427     }
       
   428 
       
   429     DEBUG_API("<-XAMetadataTraversalItfAdapt_SetMode");
       
   430     return ret;
       
   431 }
       
   432 
       
   433 /*
       
   434  * XAresult XAMetadataTraversalItfAdapt_GetChildCount(XAAdaptationGstCtx *bCtx, XAuint32 *pCount)
       
   435  */
       
   436 XAresult XAMetadataTraversalItfAdapt_GetChildCount(XAAdaptationGstCtx *bCtx, XAuint32 *pCount)
       
   437 {
       
   438     XAresult ret = XA_RESULT_SUCCESS;
       
   439     XAMetadataAdaptVars* mdv=NULL;
       
   440 
       
   441     DEBUG_API("->XAMetadataTraversalItfAdapt_GetChildCount");
       
   442     mdv = XAMetadataAdapt_GetMetadataVars(bCtx);
       
   443     if( mdv )
       
   444     {
       
   445         /* only depth of 1 is supported */
       
   446         if( mdv->nodedepth == 0 )
       
   447         {
       
   448             *pCount=mdv->childcount;
       
   449         }
       
   450         else
       
   451         {
       
   452             *pCount=0;
       
   453         }
       
   454     }
       
   455     else
       
   456     {
       
   457         DEBUG_ERR("Metadata variables not found!!");
       
   458         ret = XA_RESULT_PARAMETER_INVALID;
       
   459         *pCount=0;
       
   460     }
       
   461     DEBUG_API_A2("<-XAMetadataTraversalItfAdapt_GetChildCount(%d) count=%d", (int)ret, (int)*pCount);
       
   462     return ret;
       
   463 }
       
   464 
       
   465 /*
       
   466  * XAresult XAMetadataTraversalItfAdapt_GetChildMIMETypeSize(XAAdaptationGstCtx *bCtx,
       
   467  *                                                         XAuint32 index,
       
   468  *                                                         XAuint32 *pSize)
       
   469  */
       
   470 XAresult XAMetadataTraversalItfAdapt_GetChildMIMETypeSize(XAAdaptationGstCtx *bCtx,
       
   471                                                           XAuint32 index,
       
   472                                                           XAuint32 *pSize)
       
   473 {
       
   474     XAresult ret = XA_RESULT_SUCCESS;
       
   475     XAMetadataAdaptVars* mdv=NULL;
       
   476 
       
   477     DEBUG_API("->XAMetadataTraversalItfAdapt_GetChildMIMETypeSize");
       
   478     mdv = XAMetadataAdapt_GetMetadataVars(bCtx);
       
   479     if( mdv )
       
   480     {
       
   481         GstStructure* child = XAMetadataAdapt_GetChildStructure(mdv,index);
       
   482         if(child)
       
   483         {
       
   484             *pSize = strlen(gst_structure_get_name(child));
       
   485         }
       
   486     }
       
   487     else
       
   488     {
       
   489         DEBUG_ERR("Metadata variables not found!!");
       
   490         ret = XA_RESULT_PARAMETER_INVALID;
       
   491         *pSize=0;
       
   492     }
       
   493     DEBUG_API("<-XAMetadataTraversalItfAdapt_GetChildMIMETypeSize");
       
   494     return ret;
       
   495 }
       
   496 
       
   497 /*
       
   498  * XAresult XAMetadataTraversalItfAdapt_GetChildInfo(XAAdaptationGstCtx *bCtx,
       
   499  *                                                  XAuint32 index,
       
   500  *                                                 XAint32 *pNodeID,
       
   501  *                                                 XAuint32 *pType,
       
   502  *                                                 XAuint32 size,
       
   503  *                                                 XAchar *pMimeType)
       
   504  */
       
   505 XAresult XAMetadataTraversalItfAdapt_GetChildInfo(XAAdaptationGstCtx *bCtx,
       
   506                                                   XAuint32 index,
       
   507                                                   XAint32 *pNodeID,
       
   508                                                   XAuint32 *pType,
       
   509                                                   XAuint32 size,
       
   510                                                   XAchar *pMimeType)
       
   511 {
       
   512     XAresult ret = XA_RESULT_SUCCESS;
       
   513     XAMetadataAdaptVars* mdv=NULL;
       
   514     const gchar* mime;
       
   515     GstStructure* child;
       
   516 
       
   517     DEBUG_API("->XAMetadataTraversalItfAdapt_GetChildInfo");
       
   518     mdv = XAMetadataAdapt_GetMetadataVars(bCtx);
       
   519     if( mdv )
       
   520     {
       
   521         child = XAMetadataAdapt_GetChildStructure(mdv,index);
       
   522         if(child)
       
   523         {
       
   524             *pNodeID = (XAint32)child;
       
   525             mime = gst_structure_get_name(child);
       
   526             if(strncmp(mime,"audio",5)==0)
       
   527             {
       
   528                 *pType = XA_NODETYPE_AUDIO;
       
   529             }
       
   530             if(strncmp(mime,"video",5)==0)
       
   531             {
       
   532                 *pType = XA_NODETYPE_VIDEO;
       
   533             }
       
   534             if(strncmp(mime,"image",5)==0)
       
   535             {
       
   536                 *pType = XA_NODETYPE_IMAGE;
       
   537             }
       
   538             else
       
   539             {
       
   540                 *pType = XA_NODETYPE_UNSPECIFIED;
       
   541             }
       
   542             strncpy((char*)pMimeType,mime,size);
       
   543         }
       
   544     }
       
   545     else
       
   546     {
       
   547         DEBUG_ERR("Metadata variables not found!!");
       
   548         ret = XA_RESULT_PARAMETER_INVALID;
       
   549     }
       
   550     DEBUG_API("<-XAMetadataTraversalItfAdapt_GetChildInfo");
       
   551     return ret;
       
   552 }
       
   553 
       
   554 /*
       
   555  * XAresult XAMetadataTraversalItfAdapt_SetActiveNode(XAAdaptationGstCtx *bCtx,
       
   556  *                                                  XAuint32 index)
       
   557  */
       
   558 XAresult XAMetadataTraversalItfAdapt_SetActiveNode(XAAdaptationGstCtx *bCtx,
       
   559                                                    XAuint32 index)
       
   560 {
       
   561     XAresult ret = XA_RESULT_SUCCESS;
       
   562     XAMetadataAdaptVars* mdv=NULL;
       
   563     GstStructure* child;
       
   564 
       
   565     DEBUG_API("->XAMetadataTraversalItfAdapt_SetActiveNode");
       
   566     mdv = XAMetadataAdapt_GetMetadataVars(bCtx);
       
   567     if( mdv )
       
   568     {
       
   569         child = XAMetadataAdapt_GetChildStructure(mdv,index);
       
   570         if(child)
       
   571         {
       
   572             mdv->currentchild = &child;
       
   573             if(index==XA_NODE_PARENT) mdv->nodedepth--;
       
   574             else mdv->nodedepth++;
       
   575         }
       
   576     }
       
   577     else
       
   578     {
       
   579         DEBUG_ERR("Metadata variables not found!!");
       
   580         ret = XA_RESULT_PARAMETER_INVALID;
       
   581     }
       
   582     DEBUG_API("<-XAMetadataTraversalItfAdapt_SetActiveNode");
       
   583     return ret;
       
   584 }
       
   585 
       
   586 /*****************************************************************************
       
   587  * INSERTION
       
   588  *****************************************************************************/
       
   589 
       
   590 /*
       
   591  * XAresult XAMetadataInsertionItfAdapt_CreateChildNode(XAAdaptationGstCtx *bCtx,
       
   592  *                                                   XAint32 parentNodeID,
       
   593  *                                                   XAuint32 type,
       
   594  *                                                   XAchar *mimeType,
       
   595  *                                                   XAint32 *pChildNodeID)
       
   596  */
       
   597 XAresult XAMetadataInsertionItfAdapt_CreateChildNode(XAAdaptationGstCtx *bCtx,
       
   598                                                     XAint32 parentNodeID,
       
   599                                                     XAuint32 type,
       
   600                                                     XAchar *mimeType,
       
   601                                                     XAint32 *pChildNodeID)
       
   602 {
       
   603     XAresult ret = XA_RESULT_SUCCESS;
       
   604     XAMetadataAdaptVars* mdv=NULL;
       
   605     XAMediaRecorderAdaptationCtx* mCtx;
       
   606 
       
   607     DEBUG_API("->XAMetadataInsertionItfAdapt_CreateChildNode");
       
   608     if(bCtx && bCtx->baseObj.ctxId == XAMediaRecorderAdaptation)
       
   609     {
       
   610         /* no support for more than 1 levels of childs*/
       
   611         if(parentNodeID==XA_ROOT_NODE_ID)
       
   612         {
       
   613             XAMediaType mediaType;
       
   614             mCtx = (XAMediaRecorderAdaptationCtx*)bCtx;
       
   615 
       
   616             /* first check sink type */
       
   617             XACommon_CheckDataSource((XADataSource*)(mCtx->xaSink),&mediaType);
       
   618             if( ((mediaType==XA_MEDIATYPE_AUDIO||mediaType==XA_MEDIATYPE_VIDEO) && type==XA_NODETYPE_IMAGE) ||
       
   619                 (mediaType==XA_MEDIATYPE_IMAGE && (type==XA_NODETYPE_AUDIO || type==XA_NODETYPE_VIDEO)) )
       
   620             {
       
   621                 DEBUG_ERR("Nodetype not supported!");
       
   622                 ret = XA_RESULT_CONTENT_UNSUPPORTED;
       
   623                 DEBUG_API_A1("<-XAMetadataInsertionItfAdapt_CreateChildNode (%d)", (int)ret);
       
   624                 return ret;            }
       
   625 
       
   626             mdv = mCtx->metadatavars;
       
   627             if(!mdv)
       
   628             {
       
   629                 DEBUG_ERR("Metadata variables not initialized!");
       
   630                 ret = XA_RESULT_PRECONDITIONS_VIOLATED;
       
   631             }
       
   632             switch(type)
       
   633             {
       
   634             case XA_NODETYPE_IMAGE:
       
   635                 /*fall-through to use video pipe tags for image*/
       
   636             case XA_NODETYPE_VIDEO:
       
   637                 if(!mCtx->videosource)
       
   638                 {
       
   639                     DEBUG_ERR("Nodetype not found!");
       
   640                     ret = XA_RESULT_CONTENT_UNSUPPORTED;
       
   641                 }
       
   642                 else
       
   643                 {
       
   644                     if(!mdv->videotags)
       
   645                     {
       
   646                         if(strlen((char*)mimeType)==0)
       
   647                         {
       
   648                             mdv->videotags = gst_structure_empty_new("video/unknown");
       
   649                         }
       
   650                         else
       
   651                         {
       
   652                             mdv->videotags = gst_structure_empty_new((gchar*)mimeType);
       
   653                         }
       
   654                     }
       
   655                     *pChildNodeID = (XAint32)mdv->videotags;
       
   656                 }
       
   657                 break;
       
   658             case XA_NODETYPE_AUDIO:
       
   659                 if(!mCtx->audiosource)
       
   660                 {
       
   661                     DEBUG_ERR("Nodetype not found!");
       
   662                     ret = XA_RESULT_CONTENT_UNSUPPORTED;
       
   663                 }
       
   664                 else
       
   665                 {
       
   666                     if(!mdv->audiotags)
       
   667                     {
       
   668                         if(strlen((char*)mimeType)==0)
       
   669                         {
       
   670                             mdv->audiotags = gst_structure_empty_new("audio/unknown");
       
   671                         }
       
   672                         else
       
   673                         {
       
   674                             mdv->audiotags = gst_structure_empty_new((gchar*)mimeType);
       
   675                         }
       
   676                     }
       
   677                     *pChildNodeID = (XAint32)mdv->audiotags;
       
   678                 }
       
   679                 break;
       
   680             default:
       
   681                 DEBUG_ERR("Nodetype not found!");
       
   682                 ret = XA_RESULT_CONTENT_UNSUPPORTED;
       
   683                 break;
       
   684             }
       
   685         }
       
   686         else
       
   687         {
       
   688             DEBUG_ERR("Only root childs supported!!");
       
   689             ret = XA_RESULT_CONTENT_UNSUPPORTED;
       
   690         }
       
   691     }
       
   692     else
       
   693     {
       
   694         DEBUG_ERR("Unsupported metadata insertion context!!");
       
   695         ret = XA_RESULT_PARAMETER_INVALID;
       
   696     }
       
   697     DEBUG_API_A1("<-XAMetadataInsertionItfAdapt_CreateChildNode (%d)", (int)ret);
       
   698     return ret;
       
   699 }
       
   700 
       
   701 /*
       
   702  * XAresult XAMetadataInsertionItfAdapt_GetSupportedKeysCount(XAAdaptationGstCtx *bCtx,
       
   703  *                                                         XAint32 nodeID,
       
   704  *                                                         XAboolean *pFreeKeys,
       
   705  *                                                         XAuint32 *pKeyCount,
       
   706  *                                                         XAuint32 *pEncodingCount)
       
   707  */
       
   708 XAresult XAMetadataInsertionItfAdapt_GetSupportedKeysCount(XAAdaptationGstCtx *bCtx,
       
   709                                                           XAint32 nodeID,
       
   710                                                           XAboolean *pFreeKeys,
       
   711                                                           XAuint32 *pKeyCount,
       
   712                                                           XAuint32 *pEncodingCount)
       
   713 {
       
   714     XAresult ret = XA_RESULT_SUCCESS;
       
   715 
       
   716     DEBUG_API("->XAMetadataInsertionItfAdapt_GetSupportedKeysCount");
       
   717     if(bCtx && bCtx->baseObj.ctxId == XAMediaRecorderAdaptation)
       
   718     {
       
   719         *pKeyCount = 0;
       
   720         *pFreeKeys = XA_BOOLEAN_FALSE;
       
   721         while(xaMetadataAdaptSupportedKeys[*pKeyCount])
       
   722         {
       
   723             (*pKeyCount)++;
       
   724         }
       
   725         *pEncodingCount = 1;
       
   726     }
       
   727     else
       
   728     {
       
   729         DEBUG_ERR("Unsupported metadata insertion context!!");
       
   730         ret = XA_RESULT_PARAMETER_INVALID;
       
   731     }
       
   732     DEBUG_API("<-XAMetadataInsertionItfAdapt_GetSupportedKeysCount");
       
   733     return ret;
       
   734 }
       
   735 
       
   736 /*
       
   737  * XAresult XAMetadataInsertionItfAdapt_GetKeySize(XAAdaptationGstCtx *bCtx,
       
   738  *                                              XAint32 nodeID,
       
   739  *                                              XAuint32 keyIndex,
       
   740  *                                              XAuint32 *pKeySize)
       
   741  */
       
   742 XAresult XAMetadataInsertionItfAdapt_GetKeySize(XAAdaptationGstCtx *bCtx,
       
   743                                                XAint32 nodeID,
       
   744                                                XAuint32 keyIndex,
       
   745                                                XAuint32 *pKeySize)
       
   746 {
       
   747     XAresult ret = XA_RESULT_SUCCESS;
       
   748 
       
   749     DEBUG_API("->XAMetadataInsertionItfAdapt_GetKeySize");
       
   750     if(bCtx && bCtx->baseObj.ctxId == XAMediaRecorderAdaptation)
       
   751     {
       
   752         if(xaMetadataAdaptSupportedKeys[keyIndex])
       
   753         {
       
   754             *pKeySize = sizeof(XAMetadataInfo)+strlen(xaMetadataAdaptSupportedKeys[keyIndex]);
       
   755         }
       
   756         else
       
   757         {
       
   758             ret = XA_RESULT_PARAMETER_INVALID;
       
   759         }
       
   760     }
       
   761     else
       
   762     {
       
   763         DEBUG_ERR("Unsupported metadata insertion context!!");
       
   764         ret = XA_RESULT_PARAMETER_INVALID;
       
   765     }
       
   766     DEBUG_API("<-XAMetadataInsertionItfAdapt_GetKeySize");
       
   767     return ret;
       
   768 }
       
   769 
       
   770 /*
       
   771  * XAresult XAMetadataInsertionItfAdapt_GetKey(XAAdaptationGstCtx *bCtx,
       
   772  *                                          XAint32 nodeID,
       
   773  *                                          XAuint32 keyIndex,
       
   774  *                                          XAuint32 keySize,
       
   775  *                                          XAMetadataInfo *pKey)
       
   776  */
       
   777 XAresult XAMetadataInsertionItfAdapt_GetKey(XAAdaptationGstCtx *bCtx,
       
   778                                            XAint32 nodeID,
       
   779                                            XAuint32 keyIndex,
       
   780                                            XAuint32 keySize,
       
   781                                            XAMetadataInfo *pKey)
       
   782 {
       
   783     XAresult ret = XA_RESULT_SUCCESS;
       
   784     XAuint32 datasize, neededsize;
       
   785 
       
   786     DEBUG_API("->XAMetadataInsertionItfAdapt_GetKey");
       
   787     if(bCtx && bCtx->baseObj.ctxId == XAMediaRecorderAdaptation)
       
   788     {
       
   789         memset(pKey,0,keySize);
       
   790         if(xaMetadataAdaptSupportedKeys[keyIndex] && (keySize > sizeof(XAMetadataInfo)))
       
   791         {
       
   792             neededsize = strlen(xaMetadataAdaptSupportedKeys[keyIndex])+1;
       
   793             datasize = keySize-sizeof(XAMetadataInfo)+1;
       
   794             if(neededsize>datasize)
       
   795             {
       
   796                 strncpy((char*)pKey->data,xaMetadataAdaptSupportedKeys[keyIndex],datasize);
       
   797                 pKey->size=datasize;
       
   798                 ret=XA_RESULT_BUFFER_INSUFFICIENT;
       
   799             }
       
   800             else
       
   801             {
       
   802                 strncpy((char*)pKey->data,xaMetadataAdaptSupportedKeys[keyIndex],neededsize);
       
   803                 pKey->size=neededsize;
       
   804             }
       
   805             pKey->encoding = XA_CHARACTERENCODING_ASCII;
       
   806             strcpy((char*)(pKey->langCountry),"en");
       
   807         }
       
   808         else
       
   809         {
       
   810             ret = XA_RESULT_PARAMETER_INVALID;
       
   811         }
       
   812     }
       
   813     else
       
   814     {
       
   815         DEBUG_ERR("Unsupported metadata insertion context!!");
       
   816         ret = XA_RESULT_PARAMETER_INVALID;
       
   817     }
       
   818     DEBUG_API("<-XAMetadataInsertionItfAdapt_GetKey");
       
   819     return ret;
       
   820 }
       
   821 
       
   822 /*
       
   823  * XAresult XAMetadataInsertionItfAdapt_GetFreeKeysEncoding(XAAdaptationGstCtx *bCtx,
       
   824  *                                                       XAint32 nodeID,
       
   825  *                                                       XAuint32 encodingIndex,
       
   826  *                                                       XAuint32 *pEncoding)
       
   827  */
       
   828 XAresult XAMetadataInsertionItfAdapt_GetFreeKeysEncoding(XAAdaptationGstCtx *bCtx,
       
   829                                                         XAint32 nodeID,
       
   830                                                         XAuint32 encodingIndex,
       
   831                                                         XAuint32 *pEncoding)
       
   832 {
       
   833     DEBUG_API("->XAMetadataInsertionItfAdapt_GetFreeKeysEncoding");
       
   834     DEBUG_API("<-XAMetadataInsertionItfAdapt_GetFreeKeysEncoding");
       
   835     /* no free keys*/
       
   836     return XA_RESULT_PRECONDITIONS_VIOLATED;
       
   837 }
       
   838 
       
   839 /*
       
   840  * XAresult XAMetadataInsertionItfAdapt_InsertMetadataItem(XAAdaptationGstCtx *bCtx,
       
   841  *                                                      XAint32 nodeID,
       
   842  *                                                      XAMetadataInfo *pKey,
       
   843  *                                                      XAMetadataInfo *pValue,
       
   844  *                                                      XAboolean overwrite)
       
   845  */
       
   846 XAresult XAMetadataInsertionItfAdapt_InsertMetadataItem(XAAdaptationGstCtx *bCtx,
       
   847                                                        XAint32 nodeID,
       
   848                                                        XAMetadataInfo *pKey,
       
   849                                                        XAMetadataInfo *pValue,
       
   850                                                        XAboolean overwrite)
       
   851 {
       
   852     XAresult ret = XA_RESULT_SUCCESS;
       
   853     XAMetadataAdaptVars* mdv=NULL;
       
   854     XAMediaRecorderAdaptationCtx* mCtx;
       
   855     GstTagMergeMode mode = (overwrite?GST_TAG_MERGE_REPLACE:GST_TAG_MERGE_KEEP);
       
   856     gchar* parsedKey = (gchar*)XAMetadataAdapt_ParseKhronosKey((XAchar*)pKey->data);
       
   857     DEBUG_API("->XAMetadataInsertionItfAdapt_InsertMetadataItem");
       
   858     if(bCtx && bCtx->baseObj.ctxId == XAMediaRecorderAdaptation)
       
   859     {
       
   860         mCtx = (XAMediaRecorderAdaptationCtx*)bCtx;
       
   861         mdv = mCtx->metadatavars;
       
   862         if(mdv)
       
   863         {
       
   864             if( nodeID==XA_ROOT_NODE_ID )
       
   865             {
       
   866                 if(!mdv->generaltags)
       
   867                 {
       
   868                     mdv->generaltags = gst_tag_list_new();
       
   869                 }
       
   870                 if (gst_tag_get_type (parsedKey) == G_TYPE_STRING)
       
   871                 {
       
   872                     gst_tag_list_add(mdv->generaltags, mode, parsedKey, (gchar*)pValue->data, NULL );
       
   873                 }
       
   874                 else
       
   875                 {
       
   876                     gst_tag_list_add(mdv->generaltags, mode, parsedKey, atoi((gchar*)pValue->data), NULL );
       
   877                 }
       
   878             }
       
   879             else
       
   880             {
       
   881                 if(nodeID == (XAint32)mdv->audiotags || nodeID == (XAint32)mdv->videotags)
       
   882                 {
       
   883                     if (gst_tag_get_type (parsedKey) == G_TYPE_STRING)
       
   884                     {
       
   885                         gst_structure_set((GstStructure*)nodeID, parsedKey, G_TYPE_STRING, g_strdup((gchar*)pValue->data), NULL );
       
   886                     }
       
   887                     else
       
   888                     {
       
   889                         gst_structure_set((GstStructure*)nodeID, parsedKey, gst_tag_get_type (parsedKey), atoi((gchar*)pValue->data), NULL );
       
   890                     }
       
   891                 }
       
   892                 else
       
   893                 {
       
   894                     DEBUG_ERR("Unknown node!!");
       
   895                     ret = XA_RESULT_PARAMETER_INVALID;
       
   896                 }
       
   897             }
       
   898             if( ret == XA_RESULT_SUCCESS )
       
   899             {   /* let (possible) extraction itf to know new tags  */
       
   900                 XAAdaptEvent event = {XA_METADATAEVENTS, XA_ADAPT_MDE_TAGS_AVAILABLE, 0, NULL };
       
   901                 XAAdaptationBase_SendAdaptEvents(&bCtx->baseObj, &event );
       
   902             }
       
   903         }
       
   904         else
       
   905         {
       
   906             DEBUG_ERR("Metadata not initialized!!");
       
   907             ret = XA_RESULT_PARAMETER_INVALID;
       
   908         }
       
   909     }
       
   910     else
       
   911     {
       
   912         DEBUG_ERR("Unsupported metadata insertion context!!");
       
   913         ret = XA_RESULT_PARAMETER_INVALID;
       
   914     }
       
   915     DEBUG_API("<-XAMetadataInsertionItfAdapt_InsertMetadataItem");
       
   916     return ret;
       
   917 }
       
   918 
       
   919 /*****************************************************************************
       
   920  * INTERNALS
       
   921  *****************************************************************************/
       
   922 
       
   923 
       
   924 /*
       
   925  * GstStructure* XAMetadataAdapt_GetChildStructure(XAMetadataAdaptVars* mdv, XAuint32 index)
       
   926  * helper to get gst structure corresponding to child index
       
   927  */
       
   928 GstStructure* XAMetadataAdapt_GetChildStructure(XAMetadataAdaptVars* mdv, XAuint32 index)
       
   929 {
       
   930     if(mdv->nodedepth == 0)
       
   931     {   /*root childs, if existent, the order is 1)video 2)audio*/
       
   932         if (index==0)
       
   933         {
       
   934             if(mdv->videotags) return mdv->videotags;
       
   935             else if (mdv->audiotags) return mdv->audiotags;
       
   936         }
       
   937         else if (index==1)
       
   938         {
       
   939             if (mdv->audiotags) return mdv->audiotags;
       
   940         }
       
   941     }
       
   942     else
       
   943     {
       
   944         if(index==XA_NODE_PARENT)
       
   945         {
       
   946             return GST_STRUCTURE(mdv->generaltags);
       
   947         }
       
   948     }
       
   949     /*else*/
       
   950     return NULL;
       
   951 }
       
   952 
       
   953 /*
       
   954  * XAMetadataAdaptVars* XAMetadataAdapt_GetMetadataVars(XAAdaptationGstCtx *bCtx)
       
   955  * Return metadata variables from different types of context
       
   956  */
       
   957 XAMetadataAdaptVars* XAMetadataAdapt_GetMetadataVars(XAAdaptationGstCtx *bCtx)
       
   958 {
       
   959     if( bCtx->baseObj.ctxId == XAMDAdaptation ||
       
   960         bCtx->baseObj.ctxId == XAMediaPlayerAdaptation )
       
   961     {
       
   962         return ((XAMediaPlayerAdaptationCtx*)bCtx)->metadatavars;
       
   963     }
       
   964     else if( bCtx->baseObj.ctxId == XAMediaRecorderAdaptation )
       
   965     {
       
   966         return ((XAMediaRecorderAdaptationCtx*)bCtx)->metadatavars;
       
   967     }
       
   968     else
       
   969     {
       
   970         DEBUG_ERR("Invalid context for metadata");
       
   971         return NULL;
       
   972     }
       
   973 }
       
   974 
       
   975 /*
       
   976  * gboolean XAMetadataAdapt_CountTags(GQuark field_id, const GValue* value, gpointer counter)
       
   977  * GstStructureForeachFunc to count number of items inside list
       
   978  */
       
   979 gboolean XAMetadataAdapt_CountTags(GQuark field_id, const GValue* value, gpointer counter)
       
   980 {
       
   981     XAuint32* cnt = (XAuint32*)counter;
       
   982     (*cnt)++;
       
   983     return TRUE;
       
   984 }
       
   985 
       
   986 /*
       
   987  * void XAMetadataAdapt_ParseTag(const GstTagList* list, const gchar* tag, gpointer listptr)
       
   988  * GstTaglistForeachFunc to parse items inside gsttaglist
       
   989  */
       
   990 void XAMetadataAdapt_ParseTag(const GstTagList* list, const gchar* tag, gpointer listptr)
       
   991 {
       
   992     XAMetadataImplTagList* tagList = (XAMetadataImplTagList*)listptr;
       
   993     const gchar *key;
       
   994     gchar *value;
       
   995     guint32 keylen, valuelen;
       
   996 
       
   997     DEBUG_API("->XAMetadataAdapt_ParseTag");
       
   998     key = gst_tag_get_nick(tag);
       
   999     /*include null-terminator*/
       
  1000     keylen = strlen(key)+1;
       
  1001     tagList->mdeKeys[tagList->itemcount] = (XAMetadataInfo*)calloc(1,keylen+sizeof(XAMetadataInfo));
       
  1002     tagList->mdeKeys[tagList->itemcount]->size = keylen;
       
  1003     strncpy((char*)tagList->mdeKeys[tagList->itemcount]->data,key,keylen-1);
       
  1004 
       
  1005     if (gst_tag_get_type (tag) == G_TYPE_STRING)
       
  1006     {
       
  1007         gst_tag_list_get_string_index(list, tag, 0, &value);
       
  1008     }
       
  1009     else
       
  1010     {
       
  1011         value = g_strdup_value_contents (gst_tag_list_get_value_index (list, tag, 0));
       
  1012     }
       
  1013     /*include null-terminator*/
       
  1014     valuelen = strlen(value)+1;
       
  1015     tagList->mdeValues[tagList->itemcount] = (XAMetadataInfo*)calloc(1,valuelen+sizeof(XAMetadataInfo));
       
  1016     tagList->mdeValues[tagList->itemcount]->size = valuelen;
       
  1017     strncpy((char*)tagList->mdeValues[tagList->itemcount]->data,value,valuelen-1);
       
  1018 
       
  1019     /* NOTE: for now, encoding and language fixed */
       
  1020     tagList->mdeKeys[tagList->itemcount]->encoding = XA_CHARACTERENCODING_ASCII;
       
  1021     tagList->mdeValues[tagList->itemcount]->encoding = XA_CHARACTERENCODING_ASCII;
       
  1022     strcpy((char*)tagList->mdeKeys[tagList->itemcount]->langCountry,"en");
       
  1023     strcpy((char*)tagList->mdeValues[tagList->itemcount]->langCountry,"en");
       
  1024     tagList->itemcount++;
       
  1025     DEBUG_API_A2("<-XAMetadataAdapt_ParseTag: added %s : %s",
       
  1026                  tagList->mdeKeys[tagList->itemcount-1]->data,
       
  1027                  tagList->mdeValues[tagList->itemcount-1]->data);
       
  1028 }
       
  1029 
       
  1030 /*
       
  1031  * gboolean XAMetadataAdapt_ParseItem(GQuark gkey,
       
  1032  *                                const GValue* gvalue,
       
  1033  *                                gpointer listptr)
       
  1034  * GstStructureForeachFunc to parse items inside caps structure
       
  1035  */
       
  1036 gboolean XAMetadataAdapt_ParseItem(GQuark gkey,
       
  1037                                  const GValue* gvalue,
       
  1038                                  gpointer listptr)
       
  1039 {
       
  1040     XAMetadataImplTagList* tagList = (XAMetadataImplTagList*)listptr;
       
  1041     const gchar *key;
       
  1042     gchar *value;
       
  1043     guint32 keylen, valuelen;
       
  1044 
       
  1045     DEBUG_API("->XAMetadataAdapt_ParseItem");
       
  1046     key = g_quark_to_string(gkey);
       
  1047     /*include null-terminator*/
       
  1048     keylen = strlen(key)+1;
       
  1049     tagList->mdeKeys[tagList->itemcount] = (XAMetadataInfo*)calloc(1,keylen+sizeof(XAMetadataInfo));
       
  1050     tagList->mdeKeys[tagList->itemcount]->size = keylen;
       
  1051     strncpy((char*)tagList->mdeKeys[tagList->itemcount]->data,key,keylen-1);
       
  1052 
       
  1053     value = gst_value_serialize(gvalue);
       
  1054     /*include null-terminator*/
       
  1055     valuelen = strlen(value)+1;
       
  1056     tagList->mdeValues[tagList->itemcount] = (XAMetadataInfo*)calloc(1,valuelen+sizeof(XAMetadataInfo));
       
  1057     tagList->mdeValues[tagList->itemcount]->size = valuelen;
       
  1058     strncpy((char*)tagList->mdeValues[tagList->itemcount]->data,value,valuelen-1);
       
  1059 
       
  1060     /* for Gst, encoding and language fixed */
       
  1061     tagList->mdeKeys[tagList->itemcount]->encoding = XA_CHARACTERENCODING_ASCII;
       
  1062     tagList->mdeValues[tagList->itemcount]->encoding = XA_CHARACTERENCODING_ASCII;
       
  1063     strcpy((char*)tagList->mdeKeys[tagList->itemcount]->langCountry,"en");
       
  1064     strcpy((char*)tagList->mdeValues[tagList->itemcount]->langCountry,"en");
       
  1065     tagList->itemcount++;
       
  1066     DEBUG_API_A2("<-XAMetadataAdapt_ParseItem: added %15s : %s",
       
  1067                  tagList->mdeKeys[tagList->itemcount-1]->data,
       
  1068                  tagList->mdeValues[tagList->itemcount-1]->data);
       
  1069     return TRUE;
       
  1070 }
       
  1071 
       
  1072 /*
       
  1073  * gboolean XAMetadataAdapt_GstTagCb( GstBus *bus, GstMessage *message, gpointer data )
       
  1074  * Metadata callback - called when new tags found from stream
       
  1075  */
       
  1076 gboolean XAMetadataAdapt_GstTagCb( GstBus *bus, GstMessage *message, gpointer data )
       
  1077 {
       
  1078     GstTagList *new_tags;
       
  1079     GstTagList **old_tags = NULL;
       
  1080     XAAdaptationGstCtx* bCtx;
       
  1081     GstTagMergeMode mode;
       
  1082 
       
  1083     bCtx = (XAAdaptationGstCtx*)data;
       
  1084     if(GST_MESSAGE_TAG==GST_MESSAGE_TYPE(message))
       
  1085     {
       
  1086         DEBUG_API_A2("->XAMetadataAdapt_GstTagCb:\"%s\" from object \"%s\"",
       
  1087                         GST_MESSAGE_TYPE_NAME(message), GST_OBJECT_NAME(GST_MESSAGE_SRC(message)));
       
  1088         gst_message_parse_tag (message, &new_tags);
       
  1089         /* NOTE: only general tags received this way (not child nodes)*/
       
  1090         if( bCtx->baseObj.ctxId == XAMDAdaptation ||
       
  1091             bCtx->baseObj.ctxId == XAMediaPlayerAdaptation )
       
  1092         {
       
  1093             old_tags = &((XAMediaPlayerAdaptationCtx*)bCtx)->metadatavars->generaltags;
       
  1094             mode = GST_TAG_MERGE_REPLACE;
       
  1095         }
       
  1096         else if( bCtx->baseObj.ctxId == XAMediaRecorderAdaptation )
       
  1097         {
       
  1098             old_tags = &((XAMediaRecorderAdaptationCtx*)bCtx)->metadatavars->generaltags;
       
  1099             /* keep user's tags */
       
  1100             mode = GST_TAG_MERGE_KEEP;
       
  1101         }
       
  1102         else
       
  1103         {   /*context not applicable*/
       
  1104             return TRUE;
       
  1105         }
       
  1106 
       
  1107         if( *old_tags )
       
  1108             *old_tags = gst_tag_list_merge (*old_tags, new_tags, mode);
       
  1109         else
       
  1110             *old_tags = new_tags;
       
  1111 
       
  1112         if( GST_STATE(bCtx->bin)==GST_STATE_PLAYING )
       
  1113         {   /* send event only for live stream, otherwise wait for preroll to complete */
       
  1114             XAAdaptEvent event = {XA_METADATAEVENTS, XA_ADAPT_MDE_TAGS_AVAILABLE, 0, NULL };
       
  1115             XAAdaptationBase_SendAdaptEvents(&bCtx->baseObj, &event );
       
  1116         }
       
  1117         DEBUG_API("<-XAMetadataAdapt_GstTagCb");
       
  1118     }
       
  1119     return TRUE;
       
  1120 }
       
  1121 
       
  1122 /*
       
  1123  * void XAMetadataAdapt_TryWriteTag(const GstTagList* list, const gchar* tag, gpointer taggerptr)
       
  1124  * GstTaglistForeachFunc to write single tag entries to stream
       
  1125  */
       
  1126 void XAMetadataAdapt_TryWriteTag(const GstTagList* list, const gchar* tag, gpointer taggerptr)
       
  1127 {
       
  1128     GstTagSetter* tagger = (GstTagSetter*)taggerptr;
       
  1129     const gchar *key;
       
  1130     gchar *value;
       
  1131 
       
  1132     DEBUG_API("->XAMetadataAdapt_ParseTag");
       
  1133     key = gst_tag_get_nick(tag);
       
  1134     if (gst_tag_get_type (tag) == G_TYPE_STRING)
       
  1135     {
       
  1136         gst_tag_list_get_string_index(list, tag, 0, &value);
       
  1137     }
       
  1138     else
       
  1139     {
       
  1140         value = g_strdup_value_contents (gst_tag_list_get_value_index (list, tag, 0));
       
  1141     }
       
  1142     gst_tag_setter_add_tags(tagger, GST_TAG_MERGE_REPLACE, key, value, NULL);
       
  1143 }
       
  1144 
       
  1145 /*
       
  1146  * XAresult XAMetadataAdapt_TryWriteTags(XAAdaptationGstCtx* bCtx, GstBin* binToWriteTo)
       
  1147  */
       
  1148 XAresult XAMetadataAdapt_TryWriteTags(XAAdaptationGstCtx* bCtx, GstBin* binToWriteTo)
       
  1149 {
       
  1150     XAresult ret = XA_RESULT_SUCCESS;
       
  1151     GstTagSetter *tagger=NULL;
       
  1152     /* Find metadata tagger from bin (if any) */
       
  1153     GstIterator *iter = gst_bin_iterate_all_by_interface( binToWriteTo, GST_TYPE_TAG_SETTER );
       
  1154     gboolean done = FALSE;
       
  1155     XAMediaRecorderAdaptationCtx* mCtx;
       
  1156     XAAdaptEvent mdevent = {XA_METADATAEVENTS, XA_ADAPT_MDE_TAGS_WRITTEN, 0, NULL };
       
  1157 
       
  1158     DEBUG_API("->XAMetadataAdapt_TryWriteTags");
       
  1159 
       
  1160     if( bCtx->baseObj.ctxId != XAMediaRecorderAdaptation )
       
  1161     {
       
  1162         return XA_RESULT_FEATURE_UNSUPPORTED;
       
  1163     }
       
  1164     mCtx = ((XAMediaRecorderAdaptationCtx*)bCtx);
       
  1165     while (!done)
       
  1166     {
       
  1167         switch (gst_iterator_next(iter, (gpointer)&tagger))
       
  1168         {
       
  1169         case GST_ITERATOR_OK:
       
  1170             if(mCtx->metadatavars)
       
  1171             {
       
  1172                 if(mCtx->metadatavars->generaltags)
       
  1173                 {
       
  1174                     gst_tag_setter_merge_tags(tagger, mCtx->metadatavars->generaltags, GST_TAG_MERGE_REPLACE);
       
  1175                 }
       
  1176             }
       
  1177             done = TRUE;
       
  1178         break;
       
  1179         case GST_ITERATOR_ERROR:
       
  1180             done = TRUE;
       
  1181             DEBUG_ERR("Pipeline does not support tag setting");
       
  1182             ret = XA_RESULT_CONTENT_UNSUPPORTED;
       
  1183         break;
       
  1184         case GST_ITERATOR_DONE:
       
  1185             done = TRUE;
       
  1186             DEBUG_ERR("Pipeline does not support tag setting");
       
  1187             ret = XA_RESULT_CONTENT_UNSUPPORTED;
       
  1188         break;
       
  1189         case GST_ITERATOR_RESYNC:
       
  1190             gst_iterator_resync(iter);
       
  1191         break;
       
  1192         }
       
  1193     }
       
  1194     /*here datasize field is used for return value*/
       
  1195     mdevent.datasize = ret;
       
  1196     XAAdaptationBase_SendAdaptEvents(&bCtx->baseObj, &mdevent );
       
  1197     gst_iterator_free (iter);
       
  1198     DEBUG_API("<-XAMetadataAdapt_TryWriteTags");
       
  1199     return ret;
       
  1200 }