khronosfws/openmax_al/src/adaptation/xametadataadaptation.c
changeset 12 5a06f39ad45b
equal deleted inserted replaced
0:71ca22bcf22a 12:5a06f39ad45b
       
     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 "XAAdaptation.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(XAAdaptationBaseCtx *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(XAAdaptationBaseCtx *bCtx)
       
   106  * Initialize values needed before preroll
       
   107  * @return XAresult ret - Success value
       
   108  */
       
   109 XAresult XAMetadataAdapt_PreInit(XAAdaptationBaseCtx *bCtx)
       
   110 {
       
   111     XAresult ret = XA_RESULT_SUCCESS;
       
   112     XAMetadataAdaptVars* mdv;
       
   113     DEBUG_API("->XAMetadataAdapt_PreInit");
       
   114     if( bCtx->ctxId == XAMDAdaptation ||
       
   115         bCtx->ctxId == XAMediaPlayerAdaptation )
       
   116     {
       
   117         mdv = 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->ctxId == XAMediaRecorderAdaptation )
       
   124     {
       
   125         mdv = 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(XAAdaptationBaseCtx *bCtx)
       
   152  * Initialize values after preroll
       
   153  * @return XAresult ret - Success value
       
   154  */
       
   155 XAresult XAMetadataAdapt_PostInit(XAAdaptationBaseCtx *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->ctxId == XAMDAdaptation ||
       
   167         bCtx->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, &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(XAAdaptationBaseCtx *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 = calloc(newcount,sizeof(XAMetadataInfo*));
       
   359         tagList->mdeValues = 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(XAAdaptationBaseCtx *bCtx, XAuint32 mode)
       
   403  */
       
   404 XAresult XAMetadataTraversalItfAdapt_SetMode(XAAdaptationBaseCtx *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, &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(XAAdaptationBaseCtx *bCtx, XAuint32 *pCount)
       
   435  */
       
   436 XAresult XAMetadataTraversalItfAdapt_GetChildCount(XAAdaptationBaseCtx *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(XAAdaptationBaseCtx *bCtx,
       
   467  *                                                         XAuint32 index,
       
   468  *                                                         XAuint32 *pSize)
       
   469  */
       
   470 XAresult XAMetadataTraversalItfAdapt_GetChildMIMETypeSize(XAAdaptationBaseCtx *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(XAAdaptationBaseCtx *bCtx,
       
   499  *                                                  XAuint32 index,
       
   500  *                                                 XAint32 *pNodeID,
       
   501  *                                                 XAuint32 *pType,
       
   502  *                                                 XAuint32 size,
       
   503  *                                                 XAchar *pMimeType)
       
   504  */
       
   505 XAresult XAMetadataTraversalItfAdapt_GetChildInfo(XAAdaptationBaseCtx *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(XAAdaptationBaseCtx *bCtx,
       
   556  *                                                  XAuint32 index)
       
   557  */
       
   558 XAresult XAMetadataTraversalItfAdapt_SetActiveNode(XAAdaptationBaseCtx *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(XAAdaptationBaseCtx *bCtx,
       
   592  *                                                   XAint32 parentNodeID,
       
   593  *                                                   XAuint32 type,
       
   594  *                                                   XAchar *mimeType,
       
   595  *                                                   XAint32 *pChildNodeID)
       
   596  */
       
   597 XAresult XAMetadataInsertionItfAdapt_CreateChildNode(XAAdaptationBaseCtx *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->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(XAAdaptationBaseCtx *bCtx,
       
   703  *                                                         XAint32 nodeID,
       
   704  *                                                         XAboolean *pFreeKeys,
       
   705  *                                                         XAuint32 *pKeyCount,
       
   706  *                                                         XAuint32 *pEncodingCount)
       
   707  */
       
   708 XAresult XAMetadataInsertionItfAdapt_GetSupportedKeysCount(XAAdaptationBaseCtx *bCtx,
       
   709                                                           XAint32 nodeID,
       
   710                                                           XAboolean *pFreeKeys,
       
   711                                                           XAuint32 *pKeyCount,
       
   712                                                           XAuint32 *pEncodingCount)
       
   713 {
       
   714     XAresult ret = XA_RESULT_SUCCESS;
       
   715     XAMediaRecorderAdaptationCtx* mCtx;
       
   716 
       
   717     DEBUG_API("->XAMetadataInsertionItfAdapt_GetSupportedKeysCount");
       
   718     if(bCtx && bCtx->ctxId == XAMediaRecorderAdaptation)
       
   719     {
       
   720         mCtx = (XAMediaRecorderAdaptationCtx*)bCtx;
       
   721         *pKeyCount = 0;
       
   722         *pFreeKeys = XA_BOOLEAN_FALSE;
       
   723         while(xaMetadataAdaptSupportedKeys[*pKeyCount])
       
   724         {
       
   725             (*pKeyCount)++;
       
   726         }
       
   727         *pEncodingCount = 1;
       
   728     }
       
   729     else
       
   730     {
       
   731         DEBUG_ERR("Unsupported metadata insertion context!!");
       
   732         ret = XA_RESULT_PARAMETER_INVALID;
       
   733     }
       
   734     DEBUG_API("<-XAMetadataInsertionItfAdapt_GetSupportedKeysCount");
       
   735     return ret;
       
   736 }
       
   737 
       
   738 /*
       
   739  * XAresult XAMetadataInsertionItfAdapt_GetKeySize(XAAdaptationBaseCtx *bCtx,
       
   740  *                                              XAint32 nodeID,
       
   741  *                                              XAuint32 keyIndex,
       
   742  *                                              XAuint32 *pKeySize)
       
   743  */
       
   744 XAresult XAMetadataInsertionItfAdapt_GetKeySize(XAAdaptationBaseCtx *bCtx,
       
   745                                                XAint32 nodeID,
       
   746                                                XAuint32 keyIndex,
       
   747                                                XAuint32 *pKeySize)
       
   748 {
       
   749     XAresult ret = XA_RESULT_SUCCESS;
       
   750 
       
   751     DEBUG_API("->XAMetadataInsertionItfAdapt_GetKeySize");
       
   752     if(bCtx && bCtx->ctxId == XAMediaRecorderAdaptation)
       
   753     {
       
   754         if(xaMetadataAdaptSupportedKeys[keyIndex])
       
   755         {
       
   756             *pKeySize = sizeof(XAMetadataInfo)+strlen(xaMetadataAdaptSupportedKeys[keyIndex]);
       
   757         }
       
   758         else
       
   759         {
       
   760             ret = XA_RESULT_PARAMETER_INVALID;
       
   761         }
       
   762     }
       
   763     else
       
   764     {
       
   765         DEBUG_ERR("Unsupported metadata insertion context!!");
       
   766         ret = XA_RESULT_PARAMETER_INVALID;
       
   767     }
       
   768     DEBUG_API("<-XAMetadataInsertionItfAdapt_GetKeySize");
       
   769     return ret;
       
   770 }
       
   771 
       
   772 /*
       
   773  * XAresult XAMetadataInsertionItfAdapt_GetKey(XAAdaptationBaseCtx *bCtx,
       
   774  *                                          XAint32 nodeID,
       
   775  *                                          XAuint32 keyIndex,
       
   776  *                                          XAuint32 keySize,
       
   777  *                                          XAMetadataInfo *pKey)
       
   778  */
       
   779 XAresult XAMetadataInsertionItfAdapt_GetKey(XAAdaptationBaseCtx *bCtx,
       
   780                                            XAint32 nodeID,
       
   781                                            XAuint32 keyIndex,
       
   782                                            XAuint32 keySize,
       
   783                                            XAMetadataInfo *pKey)
       
   784 {
       
   785     XAresult ret = XA_RESULT_SUCCESS;
       
   786     XAuint32 datasize, neededsize;
       
   787 
       
   788     DEBUG_API("->XAMetadataInsertionItfAdapt_GetKey");
       
   789     if(bCtx && bCtx->ctxId == XAMediaRecorderAdaptation)
       
   790     {
       
   791         memset(pKey,0,keySize);
       
   792         if(xaMetadataAdaptSupportedKeys[keyIndex])
       
   793         {
       
   794             neededsize = strlen(xaMetadataAdaptSupportedKeys[keyIndex])+1;
       
   795             datasize = keySize-sizeof(XAMetadataInfo)+1;
       
   796             if(neededsize>datasize)
       
   797             {
       
   798                 strncpy((char*)pKey->data,xaMetadataAdaptSupportedKeys[keyIndex],datasize);
       
   799                 pKey->size=datasize;
       
   800                 ret=XA_RESULT_BUFFER_INSUFFICIENT;
       
   801             }
       
   802             else
       
   803             {
       
   804                 strncpy((char*)pKey->data,xaMetadataAdaptSupportedKeys[keyIndex],neededsize);
       
   805                 pKey->size=neededsize;
       
   806             }
       
   807             pKey->encoding = XA_CHARACTERENCODING_ASCII;
       
   808             strcpy((char*)(pKey->langCountry),"en");
       
   809         }
       
   810         else
       
   811         {
       
   812             ret = XA_RESULT_PARAMETER_INVALID;
       
   813         }
       
   814     }
       
   815     else
       
   816     {
       
   817         DEBUG_ERR("Unsupported metadata insertion context!!");
       
   818         ret = XA_RESULT_PARAMETER_INVALID;
       
   819     }
       
   820     DEBUG_API("<-XAMetadataInsertionItfAdapt_GetKey");
       
   821     return ret;
       
   822 }
       
   823 
       
   824 /*
       
   825  * XAresult XAMetadataInsertionItfAdapt_GetFreeKeysEncoding(XAAdaptationBaseCtx *bCtx,
       
   826  *                                                       XAint32 nodeID,
       
   827  *                                                       XAuint32 encodingIndex,
       
   828  *                                                       XAuint32 *pEncoding)
       
   829  */
       
   830 XAresult XAMetadataInsertionItfAdapt_GetFreeKeysEncoding(XAAdaptationBaseCtx *bCtx,
       
   831                                                         XAint32 nodeID,
       
   832                                                         XAuint32 encodingIndex,
       
   833                                                         XAuint32 *pEncoding)
       
   834 {
       
   835     DEBUG_API("->XAMetadataInsertionItfAdapt_GetFreeKeysEncoding");
       
   836     DEBUG_API("<-XAMetadataInsertionItfAdapt_GetFreeKeysEncoding");
       
   837     /* no free keys*/
       
   838     return XA_RESULT_PRECONDITIONS_VIOLATED;
       
   839 }
       
   840 
       
   841 /*
       
   842  * XAresult XAMetadataInsertionItfAdapt_InsertMetadataItem(XAAdaptationBaseCtx *bCtx,
       
   843  *                                                      XAint32 nodeID,
       
   844  *                                                      XAMetadataInfo *pKey,
       
   845  *                                                      XAMetadataInfo *pValue,
       
   846  *                                                      XAboolean overwrite)
       
   847  */
       
   848 XAresult XAMetadataInsertionItfAdapt_InsertMetadataItem(XAAdaptationBaseCtx *bCtx,
       
   849                                                        XAint32 nodeID,
       
   850                                                        XAMetadataInfo *pKey,
       
   851                                                        XAMetadataInfo *pValue,
       
   852                                                        XAboolean overwrite)
       
   853 {
       
   854     XAresult ret = XA_RESULT_SUCCESS;
       
   855     XAMetadataAdaptVars* mdv=NULL;
       
   856     XAMediaRecorderAdaptationCtx* mCtx;
       
   857     GstTagMergeMode mode = (overwrite?GST_TAG_MERGE_REPLACE:GST_TAG_MERGE_KEEP);
       
   858     gchar* parsedKey = (gchar*)XAMetadataAdapt_ParseKhronosKey((XAchar*)pKey->data);
       
   859     DEBUG_API("->XAMetadataInsertionItfAdapt_InsertMetadataItem");
       
   860     if(bCtx && bCtx->ctxId == XAMediaRecorderAdaptation)
       
   861     {
       
   862         mCtx = (XAMediaRecorderAdaptationCtx*)bCtx;
       
   863         mdv = mCtx->metadatavars;
       
   864         if(mdv)
       
   865         {
       
   866             if( nodeID==XA_ROOT_NODE_ID )
       
   867             {
       
   868                 if(!mdv->generaltags)
       
   869                 {
       
   870                     mdv->generaltags = gst_tag_list_new();
       
   871                 }
       
   872                 if (gst_tag_get_type (parsedKey) == G_TYPE_STRING)
       
   873                 {
       
   874                     gst_tag_list_add(mdv->generaltags, mode, parsedKey, (gchar*)pValue->data, NULL );
       
   875                 }
       
   876                 else
       
   877                 {
       
   878                     gst_tag_list_add(mdv->generaltags, mode, parsedKey, atoi((gchar*)pValue->data), NULL );
       
   879                 }
       
   880             }
       
   881             else
       
   882             {
       
   883                 if(nodeID == (XAint32)mdv->audiotags || nodeID == (XAint32)mdv->videotags)
       
   884                 {
       
   885                     if (gst_tag_get_type (parsedKey) == G_TYPE_STRING)
       
   886                     {
       
   887                         gst_structure_set((GstStructure*)nodeID, parsedKey, G_TYPE_STRING, g_strdup((gchar*)pValue->data), NULL );
       
   888                     }
       
   889                     else
       
   890                     {
       
   891                         gst_structure_set((GstStructure*)nodeID, parsedKey, gst_tag_get_type (parsedKey), atoi((gchar*)pValue->data), NULL );
       
   892                     }
       
   893                 }
       
   894                 else
       
   895                 {
       
   896                     DEBUG_ERR("Unknown node!!");
       
   897                     ret = XA_RESULT_PARAMETER_INVALID;
       
   898                 }
       
   899             }
       
   900             if( ret == XA_RESULT_SUCCESS )
       
   901             {   /* let (possible) extraction itf to know new tags  */
       
   902                 XAAdaptEvent event = {XA_METADATAEVENTS, XA_ADAPT_MDE_TAGS_AVAILABLE, 0, NULL };
       
   903                 XAAdaptationBase_SendAdaptEvents(bCtx, &event );
       
   904             }
       
   905         }
       
   906         else
       
   907         {
       
   908             DEBUG_ERR("Metadata not initialized!!");
       
   909             ret = XA_RESULT_PARAMETER_INVALID;
       
   910         }
       
   911     }
       
   912     else
       
   913     {
       
   914         DEBUG_ERR("Unsupported metadata insertion context!!");
       
   915         ret = XA_RESULT_PARAMETER_INVALID;
       
   916     }
       
   917     DEBUG_API("<-XAMetadataInsertionItfAdapt_InsertMetadataItem");
       
   918     return ret;
       
   919 }
       
   920 
       
   921 /*****************************************************************************
       
   922  * INTERNALS
       
   923  *****************************************************************************/
       
   924 
       
   925 
       
   926 /*
       
   927  * GstStructure* XAMetadataAdapt_GetChildStructure(XAMetadataAdaptVars* mdv, XAuint32 index)
       
   928  * helper to get gst structure corresponding to child index
       
   929  */
       
   930 GstStructure* XAMetadataAdapt_GetChildStructure(XAMetadataAdaptVars* mdv, XAuint32 index)
       
   931 {
       
   932     if(mdv->nodedepth == 0)
       
   933     {   /*root childs, if existent, the order is 1)video 2)audio*/
       
   934         if (index==0)
       
   935         {
       
   936             if(mdv->videotags) return mdv->videotags;
       
   937             else if (mdv->audiotags) return mdv->audiotags;
       
   938         }
       
   939         else if (index==1)
       
   940         {
       
   941             if (mdv->audiotags) return mdv->audiotags;
       
   942         }
       
   943     }
       
   944     else
       
   945     {
       
   946         if(index==XA_NODE_PARENT)
       
   947         {
       
   948             return GST_STRUCTURE(mdv->generaltags);
       
   949         }
       
   950     }
       
   951     /*else*/
       
   952     return NULL;
       
   953 }
       
   954 
       
   955 /*
       
   956  * XAMetadataAdaptVars* XAMetadataAdapt_GetMetadataVars(XAAdaptationBaseCtx *bCtx)
       
   957  * Return metadata variables from different types of context
       
   958  */
       
   959 XAMetadataAdaptVars* XAMetadataAdapt_GetMetadataVars(XAAdaptationBaseCtx *bCtx)
       
   960 {
       
   961     if( bCtx->ctxId == XAMDAdaptation ||
       
   962         bCtx->ctxId == XAMediaPlayerAdaptation )
       
   963     {
       
   964         return ((XAMediaPlayerAdaptationCtx*)bCtx)->metadatavars;
       
   965     }
       
   966     else if( bCtx->ctxId == XAMediaRecorderAdaptation )
       
   967     {
       
   968         return ((XAMediaRecorderAdaptationCtx*)bCtx)->metadatavars;
       
   969     }
       
   970     else
       
   971     {
       
   972         DEBUG_ERR("Invalid context for metadata");
       
   973         return NULL;
       
   974     }
       
   975 }
       
   976 
       
   977 /*
       
   978  * gboolean XAMetadataAdapt_CountTags(GQuark field_id, const GValue* value, gpointer counter)
       
   979  * GstStructureForeachFunc to count number of items inside list
       
   980  */
       
   981 gboolean XAMetadataAdapt_CountTags(GQuark field_id, const GValue* value, gpointer counter)
       
   982 {
       
   983     XAuint32* cnt = (XAuint32*)counter;
       
   984     (*cnt)++;
       
   985     return TRUE;
       
   986 }
       
   987 
       
   988 /*
       
   989  * void XAMetadataAdapt_ParseTag(const GstTagList* list, const gchar* tag, gpointer listptr)
       
   990  * GstTaglistForeachFunc to parse items inside gsttaglist
       
   991  */
       
   992 void XAMetadataAdapt_ParseTag(const GstTagList* list, const gchar* tag, gpointer listptr)
       
   993 {
       
   994     XAMetadataImplTagList* tagList = (XAMetadataImplTagList*)listptr;
       
   995     const gchar *key;
       
   996     gchar *value;
       
   997     guint32 keylen, valuelen;
       
   998 
       
   999     DEBUG_API("->XAMetadataAdapt_ParseTag");
       
  1000     key = gst_tag_get_nick(tag);
       
  1001     /*include null-terminator*/
       
  1002     keylen = strlen(key)+1;
       
  1003     tagList->mdeKeys[tagList->itemcount] = calloc(1,keylen+sizeof(XAMetadataInfo));
       
  1004     tagList->mdeKeys[tagList->itemcount]->size = keylen;
       
  1005     strncpy((char*)tagList->mdeKeys[tagList->itemcount]->data,key,keylen-1);
       
  1006 
       
  1007     if (gst_tag_get_type (tag) == G_TYPE_STRING)
       
  1008     {
       
  1009         gst_tag_list_get_string_index(list, tag, 0, &value);
       
  1010     }
       
  1011     else
       
  1012     {
       
  1013         value = g_strdup_value_contents (gst_tag_list_get_value_index (list, tag, 0));
       
  1014     }
       
  1015     /*include null-terminator*/
       
  1016     valuelen = strlen(value)+1;
       
  1017     tagList->mdeValues[tagList->itemcount] = calloc(1,valuelen+sizeof(XAMetadataInfo));
       
  1018     tagList->mdeValues[tagList->itemcount]->size = valuelen;
       
  1019     strncpy((char*)tagList->mdeValues[tagList->itemcount]->data,value,valuelen-1);
       
  1020 
       
  1021     /* NOTE: for now, encoding and language fixed */
       
  1022     tagList->mdeKeys[tagList->itemcount]->encoding = XA_CHARACTERENCODING_ASCII;
       
  1023     tagList->mdeValues[tagList->itemcount]->encoding = XA_CHARACTERENCODING_ASCII;
       
  1024     strcpy((char*)tagList->mdeKeys[tagList->itemcount]->langCountry,"en");
       
  1025     strcpy((char*)tagList->mdeValues[tagList->itemcount]->langCountry,"en");
       
  1026     tagList->itemcount++;
       
  1027     DEBUG_API_A2("<-XAMetadataAdapt_ParseTag: added %s : %s",
       
  1028                  tagList->mdeKeys[tagList->itemcount-1]->data,
       
  1029                  tagList->mdeValues[tagList->itemcount-1]->data);
       
  1030 }
       
  1031 
       
  1032 /*
       
  1033  * gboolean XAMetadataAdapt_ParseItem(GQuark gkey,
       
  1034  *                                const GValue* gvalue,
       
  1035  *                                gpointer listptr)
       
  1036  * GstStructureForeachFunc to parse items inside caps structure
       
  1037  */
       
  1038 gboolean XAMetadataAdapt_ParseItem(GQuark gkey,
       
  1039                                  const GValue* gvalue,
       
  1040                                  gpointer listptr)
       
  1041 {
       
  1042     XAMetadataImplTagList* tagList = (XAMetadataImplTagList*)listptr;
       
  1043     const gchar *key;
       
  1044     gchar *value;
       
  1045     guint32 keylen, valuelen;
       
  1046 
       
  1047     DEBUG_API("->XAMetadataAdapt_ParseItem");
       
  1048     key = g_quark_to_string(gkey);
       
  1049     /*include null-terminator*/
       
  1050     keylen = strlen(key)+1;
       
  1051     tagList->mdeKeys[tagList->itemcount] = calloc(1,keylen+sizeof(XAMetadataInfo));
       
  1052     tagList->mdeKeys[tagList->itemcount]->size = keylen;
       
  1053     strncpy((char*)tagList->mdeKeys[tagList->itemcount]->data,key,keylen-1);
       
  1054 
       
  1055     value = gst_value_serialize(gvalue);
       
  1056     /*include null-terminator*/
       
  1057     valuelen = strlen(value)+1;
       
  1058     tagList->mdeValues[tagList->itemcount] = calloc(1,valuelen+sizeof(XAMetadataInfo));
       
  1059     tagList->mdeValues[tagList->itemcount]->size = valuelen;
       
  1060     strncpy((char*)tagList->mdeValues[tagList->itemcount]->data,value,valuelen-1);
       
  1061 
       
  1062     /* for Gst, encoding and language fixed */
       
  1063     tagList->mdeKeys[tagList->itemcount]->encoding = XA_CHARACTERENCODING_ASCII;
       
  1064     tagList->mdeValues[tagList->itemcount]->encoding = XA_CHARACTERENCODING_ASCII;
       
  1065     strcpy((char*)tagList->mdeKeys[tagList->itemcount]->langCountry,"en");
       
  1066     strcpy((char*)tagList->mdeValues[tagList->itemcount]->langCountry,"en");
       
  1067     tagList->itemcount++;
       
  1068     DEBUG_API_A2("<-XAMetadataAdapt_ParseItem: added %15s : %s",
       
  1069                  tagList->mdeKeys[tagList->itemcount-1]->data,
       
  1070                  tagList->mdeValues[tagList->itemcount-1]->data);
       
  1071     return TRUE;
       
  1072 }
       
  1073 
       
  1074 /*
       
  1075  * gboolean XAMetadataAdapt_GstTagCb( GstBus *bus, GstMessage *message, gpointer data )
       
  1076  * Metadata callback - called when new tags found from stream
       
  1077  */
       
  1078 gboolean XAMetadataAdapt_GstTagCb( GstBus *bus, GstMessage *message, gpointer data )
       
  1079 {
       
  1080     GstTagList *new_tags;
       
  1081     GstTagList **old_tags = NULL;
       
  1082     XAAdaptationBaseCtx* bCtx;
       
  1083     GstTagMergeMode mode;
       
  1084 
       
  1085     bCtx = (XAAdaptationBaseCtx*)data;
       
  1086     if(GST_MESSAGE_TAG==GST_MESSAGE_TYPE(message))
       
  1087     {
       
  1088         DEBUG_API_A2("->XAMetadataAdapt_GstTagCb:\"%s\" from object \"%s\"",
       
  1089                         GST_MESSAGE_TYPE_NAME(message), GST_OBJECT_NAME(GST_MESSAGE_SRC(message)));
       
  1090         gst_message_parse_tag (message, &new_tags);
       
  1091         /* NOTE: only general tags received this way (not child nodes)*/
       
  1092         if( bCtx->ctxId == XAMDAdaptation ||
       
  1093             bCtx->ctxId == XAMediaPlayerAdaptation )
       
  1094         {
       
  1095             old_tags = &((XAMediaPlayerAdaptationCtx*)bCtx)->metadatavars->generaltags;
       
  1096             mode = GST_TAG_MERGE_REPLACE;
       
  1097         }
       
  1098         else if( bCtx->ctxId == XAMediaRecorderAdaptation )
       
  1099         {
       
  1100             old_tags = &((XAMediaRecorderAdaptationCtx*)bCtx)->metadatavars->generaltags;
       
  1101             /* keep user's tags */
       
  1102             mode = GST_TAG_MERGE_KEEP;
       
  1103         }
       
  1104         else
       
  1105         {   /*context not applicable*/
       
  1106             return TRUE;
       
  1107         }
       
  1108 
       
  1109         if( *old_tags )
       
  1110             *old_tags = gst_tag_list_merge (*old_tags, new_tags, mode);
       
  1111         else
       
  1112             *old_tags = new_tags;
       
  1113 
       
  1114         if( GST_STATE(bCtx->bin)==GST_STATE_PLAYING )
       
  1115         {   /* send event only for live stream, otherwise wait for preroll to complete */
       
  1116             XAAdaptEvent event = {XA_METADATAEVENTS, XA_ADAPT_MDE_TAGS_AVAILABLE, 0, NULL };
       
  1117             XAAdaptationBase_SendAdaptEvents(bCtx, &event );
       
  1118         }
       
  1119         DEBUG_API("<-XAMetadataAdapt_GstTagCb");
       
  1120     }
       
  1121     return TRUE;
       
  1122 }
       
  1123 
       
  1124 /*
       
  1125  * void XAMetadataAdapt_TryWriteTag(const GstTagList* list, const gchar* tag, gpointer taggerptr)
       
  1126  * GstTaglistForeachFunc to write single tag entries to stream
       
  1127  */
       
  1128 void XAMetadataAdapt_TryWriteTag(const GstTagList* list, const gchar* tag, gpointer taggerptr)
       
  1129 {
       
  1130     GstTagSetter* tagger = (GstTagSetter*)taggerptr;
       
  1131     const gchar *key;
       
  1132     gchar *value;
       
  1133 
       
  1134     DEBUG_API("->XAMetadataAdapt_ParseTag");
       
  1135     key = gst_tag_get_nick(tag);
       
  1136     if (gst_tag_get_type (tag) == G_TYPE_STRING)
       
  1137     {
       
  1138         gst_tag_list_get_string_index(list, tag, 0, &value);
       
  1139     }
       
  1140     else
       
  1141     {
       
  1142         value = g_strdup_value_contents (gst_tag_list_get_value_index (list, tag, 0));
       
  1143     }
       
  1144     gst_tag_setter_add_tags(tagger, GST_TAG_MERGE_REPLACE, key, value, NULL);
       
  1145 }
       
  1146 
       
  1147 /*
       
  1148  * XAresult XAMetadataAdapt_TryWriteTags(XAAdaptationBaseCtx* bCtx, GstBin* binToWriteTo)
       
  1149  */
       
  1150 XAresult XAMetadataAdapt_TryWriteTags(XAAdaptationBaseCtx* bCtx, GstBin* binToWriteTo)
       
  1151 {
       
  1152     XAresult ret = XA_RESULT_SUCCESS;
       
  1153     GstTagSetter *tagger=NULL;
       
  1154     /* Find metadata tagger from bin (if any) */
       
  1155     GstIterator *iter = gst_bin_iterate_all_by_interface( binToWriteTo, GST_TYPE_TAG_SETTER );
       
  1156     gboolean done = FALSE;
       
  1157     XAMediaRecorderAdaptationCtx* mCtx;
       
  1158     XAAdaptEvent mdevent = {XA_METADATAEVENTS, XA_ADAPT_MDE_TAGS_WRITTEN, 0, NULL };
       
  1159 
       
  1160     DEBUG_API("->XAMetadataAdapt_TryWriteTags");
       
  1161 
       
  1162     if( bCtx->ctxId != XAMediaRecorderAdaptation )
       
  1163     {
       
  1164         return XA_RESULT_FEATURE_UNSUPPORTED;
       
  1165     }
       
  1166     mCtx = ((XAMediaRecorderAdaptationCtx*)bCtx);
       
  1167     while (!done)
       
  1168     {
       
  1169         switch (gst_iterator_next(iter, (gpointer)&tagger))
       
  1170         {
       
  1171         case GST_ITERATOR_OK:
       
  1172             if(mCtx->metadatavars)
       
  1173             {
       
  1174                 if(mCtx->metadatavars->generaltags)
       
  1175                 {
       
  1176                     gst_tag_setter_merge_tags(tagger, mCtx->metadatavars->generaltags, GST_TAG_MERGE_REPLACE);
       
  1177                 }
       
  1178             }
       
  1179             done = TRUE;
       
  1180         break;
       
  1181         case GST_ITERATOR_ERROR:
       
  1182             done = TRUE;
       
  1183             DEBUG_ERR("Pipeline does not support tag setting");
       
  1184             ret = XA_RESULT_CONTENT_UNSUPPORTED;
       
  1185         break;
       
  1186         case GST_ITERATOR_DONE:
       
  1187             done = TRUE;
       
  1188             DEBUG_ERR("Pipeline does not support tag setting");
       
  1189             ret = XA_RESULT_CONTENT_UNSUPPORTED;
       
  1190         break;
       
  1191         case GST_ITERATOR_RESYNC:
       
  1192             gst_iterator_resync(iter);
       
  1193         break;
       
  1194         }
       
  1195     }
       
  1196     /*here datasize field is used for return value*/
       
  1197     mdevent.datasize = ret;
       
  1198     XAAdaptationBase_SendAdaptEvents(bCtx, &mdevent );
       
  1199     gst_iterator_free (iter);
       
  1200     DEBUG_API("<-XAMetadataAdapt_TryWriteTags");
       
  1201     return ret;
       
  1202 }