khronosfws/openmax_al/src/gst_adaptation/xasnapshotitfadaptation.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 <gstappsrc.h>
       
    21 #include <gstappsink.h>
       
    22 #include "xaadaptationgst.h"
       
    23 #include "xasnapshotitfadaptation.h"
       
    24 #include "xamediarecorderadaptctx.h"
       
    25 #include "xametadataadaptation.h"
       
    26 #include "xacameraadaptctx.h"
       
    27 #include "xacapabilitiesmgr.h"
       
    28 
       
    29 #define SSMAXPIC 30
       
    30 #define SSMAXFPS 30 /*technically, same as FPS of video stream*/
       
    31 #define SSMINFPS 1
       
    32 
       
    33 extern XAboolean cameraRealized;
       
    34 extern XACameraAdaptationCtx_* cameraCtx;
       
    35 
       
    36 /* Forward declarations for internal methods */
       
    37 XAresult XASnapshotItfAdaptation_CreateSnapshotPipeline(XAAdaptationGstCtx* bCtx);
       
    38 XAresult XASnapshotItfAdaptation_FreeSnapshot(XAAdaptationGstCtx* bCtx);
       
    39 const char* XASnapshotItfAdaptation_GetFileSuffix(XADataFormat_MIME* format);
       
    40 void XASnapshotItfAdaptation_AllocNextFilename(char** fname, const char* template);
       
    41 void XASnapshotItfAdaptation_StopSnapshotting(XAAdaptationGstCtx* bCtx);
       
    42 
       
    43 /* callbacks */
       
    44 gboolean XASnapshotItfAdaptation_SnapshotBusCb( GstBus *bus, GstMessage *message, gpointer data );
       
    45 void XASnapshotItfAdaptation_BufferHandoffCb( GstElement *extract, GstBuffer *buffer, gpointer data);
       
    46 
       
    47 /*********************************
       
    48  * SnapshotItf adaptation methods
       
    49  *********************************/
       
    50 
       
    51 /*
       
    52  * XAresult XASnapshotItfAdaptation_InitiateSnapshot(XAAdaptationGstCtx* bCtx,
       
    53  *                                                 XAuint32 numberOfPictures,
       
    54  *                                                 XAuint32 fps,
       
    55  *                                                 XAboolean freezeViewFinder,
       
    56  *                                                 XADataSink* sink)
       
    57  */
       
    58 XAresult XASnapshotItfAdaptation_InitiateSnapshot(XAAdaptationGstCtx* bCtx,
       
    59                                                   XAuint32 numberOfPictures,
       
    60                                                   XAuint32 fps,
       
    61                                                   XAboolean freezeViewFinder,
       
    62                                                   XADataSink* sink)
       
    63 {
       
    64     XAMediaRecorderAdaptationCtx* mCtx = (XAMediaRecorderAdaptationCtx*)bCtx;
       
    65     XADataLocator_URI* uri=NULL;
       
    66 
       
    67     DEBUG_API("->XASnapshotItfAdaptation_InitiateSnapshot");
       
    68     /* Store initialization variables */
       
    69     mCtx->snapshotVars.numpics = numberOfPictures;
       
    70     mCtx->snapshotVars.fps = fps;
       
    71     mCtx->snapshotVars.freeze =freezeViewFinder;
       
    72     mCtx->snapshotVars.parsenegotiated = FALSE;
       
    73     mCtx->snapshotVars.snapshotbuffer = NULL;
       
    74 
       
    75     if( sink )
       
    76     {   /* parse file sink name*/
       
    77         if( sink->pLocator && *((XAuint32*)(sink->pLocator)) == XA_DATALOCATOR_URI )
       
    78         {
       
    79             uri = (XADataLocator_URI*)sink->pLocator;
       
    80             if ( uri->URI != NULL )
       
    81             {
       
    82                 /* parse filename template: <prefix><nnnn><suffix> */
       
    83                 mCtx->snapshotVars.fnametemplate = (char*)calloc(1,strlen((char*)uri->URI)+10);
       
    84                 DEBUG_INFO_A1("URI: %s", uri->URI);
       
    85                 if(strncmp((char*)uri->URI, "file://", 7) == 0)
       
    86                 {
       
    87                     strcat(mCtx->snapshotVars.fnametemplate, (char*)&((uri->URI)[7]));
       
    88                 }
       
    89                 else
       
    90                 {
       
    91                     strcat(mCtx->snapshotVars.fnametemplate, (char*)uri->URI);
       
    92                 }
       
    93                 strcat(mCtx->snapshotVars.fnametemplate, "%04d.");
       
    94                 strcat(mCtx->snapshotVars.fnametemplate,
       
    95                         XASnapshotItfAdaptation_GetFileSuffix(sink->pFormat));
       
    96                 DEBUG_INFO_A1("->template name %s", mCtx->snapshotVars.fnametemplate);
       
    97             }
       
    98             else
       
    99             {
       
   100                 DEBUG_ERR("No uri specified.");
       
   101                 return XA_RESULT_PARAMETER_INVALID;
       
   102             }
       
   103         }
       
   104         else
       
   105         { /* take snapshot to memory buffer */
       
   106             if( mCtx->snapshotVars.fnametemplate )
       
   107             {
       
   108                 free( mCtx->snapshotVars.fnametemplate );
       
   109             }
       
   110             mCtx->snapshotVars.fnametemplate = NULL;
       
   111         }
       
   112         if( sink->pFormat && *((XAuint32*)(sink->pFormat)) == XA_DATAFORMAT_RAWIMAGE )
       
   113         {
       
   114             XADataFormat_RawImage* img = ((XADataFormat_RawImage*)sink->pFormat);
       
   115             /*set needed image settings from the sink structure*/
       
   116             mCtx->imageEncSettings.encoderId = XA_IMAGECODEC_RAW;
       
   117             mCtx->imageEncSettings.width = img->width;
       
   118             mCtx->imageEncSettings.height = img->height;
       
   119             mCtx->imageEncSettings.colorFormat = img->colorFormat;
       
   120         }
       
   121     }
       
   122     else
       
   123     {
       
   124         DEBUG_ERR("XASnapshotItfAdaptation_InitiateSnapshot, invalid data sink!");
       
   125         DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
       
   126         DEBUG_API("<-XASnapshotItfAdaptation_InitiateSnapshot");
       
   127         return XA_RESULT_PARAMETER_INVALID;
       
   128     }
       
   129 
       
   130 
       
   131     if( mCtx->snapshotVars.sspipeline )
       
   132     {
       
   133         XASnapshotItfAdaptation_FreeSnapshot(bCtx);
       
   134     }
       
   135     if( XASnapshotItfAdaptation_CreateSnapshotPipeline(bCtx) != XA_RESULT_SUCCESS )
       
   136     {
       
   137         DEBUG_ERR("Failed to create pipeline!!");
       
   138         DEBUG_ERR("XA_RESULT_INTERNAL_ERROR");
       
   139         DEBUG_API("<-XASnapshotItfAdaptation_InitiateSnapshot");
       
   140         return XA_RESULT_INTERNAL_ERROR;
       
   141     }
       
   142     DEBUG_API("<-XASnapshotItfAdaptation_InitiateSnapshot");
       
   143     return XA_RESULT_SUCCESS;
       
   144 }
       
   145 
       
   146 /*
       
   147  * XAresult XASnapshotItfAdaptation_TakeSnapshot(XAAdaptationGstCtx* bCtx)
       
   148  */
       
   149 XAresult XASnapshotItfAdaptation_TakeSnapshot(XAAdaptationGstCtx* bCtx)
       
   150 {
       
   151     XAMediaRecorderAdaptationCtx* mCtx = NULL;
       
   152 
       
   153     DEBUG_API("->XASnapshotItfAdaptation_TakeSnapshot");
       
   154     if(!bCtx || bCtx->baseObj.ctxId != XAMediaRecorderAdaptation )
       
   155     {
       
   156         DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
       
   157         DEBUG_API("<-XASnapshotItfAdaptation_TakeSnapshot");
       
   158         /* invalid parameter */
       
   159         return XA_RESULT_PARAMETER_INVALID;
       
   160     }
       
   161     mCtx = (XAMediaRecorderAdaptationCtx*)bCtx;
       
   162     /*to get buffer, base pipeline must be playing...*/
       
   163     if( GST_STATE(mCtx->baseObj.bin) != GST_STATE_PLAYING )
       
   164     {
       
   165         DEBUG_INFO_A1("Parent bin in state %d, set to PLAYING", GST_STATE(mCtx->baseObj.bin));
       
   166         gst_element_set_state( GST_ELEMENT(mCtx->baseObj.bin), GST_STATE_PLAYING );
       
   167         gst_element_get_state( GST_ELEMENT(mCtx->baseObj.bin), NULL,NULL, XA_ADAPT_ASYNC_TIMEOUT_SHORT_NSEC);
       
   168     }
       
   169     if ( mCtx->isobjvsrc && mCtx->videosource && cameraCtx && cameraRealized )
       
   170     {
       
   171     	GstPad *pad=NULL;
       
   172     	GstPad *pad1=NULL;
       
   173 
       
   174     	cameraCtx->snapshotting = XA_BOOLEAN_TRUE;
       
   175     	pad = gst_element_get_static_pad( GST_ELEMENT(cameraCtx->baseObj.bin), "MRObjSrc");
       
   176 		if( pad && gst_pad_is_linked(pad) )
       
   177 		{
       
   178 			DEBUG_INFO_A2("unblock element:%s pad:%s",
       
   179 					gst_element_get_name(cameraCtx->baseObj.bin),
       
   180 					gst_pad_get_name(pad));
       
   181 			gst_pad_set_blocked_async(pad, FALSE, XAAdaptationGst_PadBlockCb, NULL);
       
   182 		}
       
   183 
       
   184     	pad1 = gst_element_get_static_pad( GST_ELEMENT(cameraCtx->baseObj.bin), "MPObjSrc");
       
   185 		if( pad1 && gst_pad_is_linked(pad1) )
       
   186 		{
       
   187 			DEBUG_INFO_A2("unblock element:%s pad:%s",
       
   188 					gst_element_get_name(cameraCtx->baseObj.bin),
       
   189 					gst_pad_get_name(pad1));
       
   190 			gst_pad_set_blocked_async(pad, FALSE, XAAdaptationGst_PadBlockCb, NULL);
       
   191 		}
       
   192 
       
   193     	DEBUG_INFO_A1("Using camera from global pointer %x", cameraCtx);
       
   194     	if ( GST_STATE( GST_ELEMENT(cameraCtx->baseObj.bin)) != GST_STATE_PLAYING )
       
   195 		{
       
   196 			cameraCtx->baseObj.binWantedState = GST_STATE(cameraCtx->baseObj.bin);
       
   197 			DEBUG_INFO_A1("Camerabin state %d, set to PLAYING", GST_STATE(GST_ELEMENT(cameraCtx->baseObj.bin)));
       
   198 			gst_element_set_state( GST_ELEMENT(cameraCtx->baseObj.bin), GST_STATE_PLAYING );
       
   199 			gst_element_get_state( GST_ELEMENT(cameraCtx->baseObj.bin), NULL,NULL, XA_ADAPT_ASYNC_TIMEOUT_SHORT_NSEC);
       
   200 		}
       
   201 	}
       
   202 
       
   203     /* Connect signal for getting current buffer from video pipeline*/
       
   204     mCtx->snapshotVars.numpicstaken = 0;
       
   205     mCtx->snapshotVars.waitforbuffer = TRUE;
       
   206     if(mCtx->videoextract)
       
   207     {
       
   208         mCtx->snapshotVars.sighandler = g_signal_connect(mCtx->videoextract, "handoff",
       
   209                                 G_CALLBACK (XASnapshotItfAdaptation_BufferHandoffCb),mCtx);
       
   210     }
       
   211     if( mCtx->snapshotVars.sighandler==0 )
       
   212     {
       
   213         DEBUG_ERR("XA_RESULT_INTERNAL_ERROR");
       
   214         DEBUG_API("<-XASnapshotItfAdaptation_TakeSnapshot");
       
   215         return XA_RESULT_INTERNAL_ERROR;
       
   216     }
       
   217     DEBUG_API("<-XASnapshotItfAdaptation_TakeSnapshot");
       
   218     return XA_RESULT_SUCCESS;
       
   219 }
       
   220 
       
   221 /*
       
   222  * XAresult XASnapshotItfAdaptation_CancelSnapshot(XAAdaptationGstCtx* bCtx)
       
   223  */
       
   224 XAresult XASnapshotItfAdaptation_CancelSnapshot(XAAdaptationGstCtx* bCtx)
       
   225 {
       
   226     DEBUG_API("->XASnapshotItfAdaptation_CancelSnapshot");
       
   227     if(!bCtx || bCtx->baseObj.ctxId != XAMediaRecorderAdaptation )
       
   228     {
       
   229         DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
       
   230         DEBUG_API("<-XASnapshotItfAdaptation_CancelSnapshot");
       
   231         /* invalid parameter */
       
   232         return XA_RESULT_PARAMETER_INVALID;
       
   233     }
       
   234 
       
   235     XASnapshotItfAdaptation_FreeSnapshot(bCtx);
       
   236 
       
   237     DEBUG_API("<-XASnapshotItfAdaptation_CancelSnapshot");
       
   238     return XA_RESULT_SUCCESS;
       
   239 }
       
   240 
       
   241 /*
       
   242  * XAresult XASnapshotItfAdaptation_GetMaxPicsPerBurst(XAAdaptationGstCtx* bCtx,
       
   243  *                                              XAuint32 *maxNumberOfPictures)
       
   244  */
       
   245 XAresult XASnapshotItfAdaptation_GetMaxPicsPerBurst(XAAdaptationGstCtx* bCtx,
       
   246                                               XAuint32 *maxNumberOfPictures)
       
   247 {
       
   248     DEBUG_API("->XASnapshotItfAdaptation_GetMaxPicsPerBurst");
       
   249     if(!bCtx || bCtx->baseObj.ctxId != XAMediaRecorderAdaptation )
       
   250     {
       
   251         DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
       
   252         DEBUG_API("<-XASnapshotItfAdaptation_GetMaxPicsPerBurst");
       
   253         return XA_RESULT_PARAMETER_INVALID;
       
   254     }
       
   255     *maxNumberOfPictures = SSMAXPIC;
       
   256     DEBUG_API("<-XASnapshotItfAdaptation_GetMaxPicsPerBurst");
       
   257     return XA_RESULT_SUCCESS;
       
   258 }
       
   259 
       
   260 /*
       
   261  * XAresult XASnapshotItfAdaptation_GetBurstFPSRange(XAAdaptationGstCtx* bCtx,
       
   262  *                                            XAuint32 *minFPS,
       
   263  *                                           XAuint32 *maxFPS)
       
   264  */
       
   265 XAresult XASnapshotItfAdaptation_GetBurstFPSRange(XAAdaptationGstCtx* bCtx,
       
   266                                             XAuint32 *minFPS,
       
   267                                             XAuint32 *maxFPS)
       
   268 {
       
   269     DEBUG_API("->XASnapshotItfAdaptation_GetBurstFPSRange");
       
   270     if(!bCtx || bCtx->baseObj.ctxId != XAMediaRecorderAdaptation )
       
   271         {
       
   272             DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
       
   273             DEBUG_API("<-XASnapshotItfAdaptation_GetBurstFPSRange");
       
   274             return XA_RESULT_PARAMETER_INVALID;
       
   275         }
       
   276     *minFPS = SSMINFPS;
       
   277     *maxFPS = SSMAXFPS;
       
   278 
       
   279     DEBUG_API("<-XASnapshotItfAdaptation_GetBurstFPSRange");
       
   280     return XA_RESULT_SUCCESS;
       
   281 }
       
   282 
       
   283 /*
       
   284  * XAresult XASnapshotItfAdaptation_SetShutterFeedback(XAAdaptationGstCtx* bCtx,
       
   285  *                                              XAboolean enabled)
       
   286  */
       
   287 XAresult XASnapshotItfAdaptation_SetShutterFeedback(XAAdaptationGstCtx* bCtx,
       
   288                                               XAboolean enabled)
       
   289 {
       
   290     DEBUG_API("->XASnapshotItfAdaptation_SetShutterFeedback");
       
   291     if(!bCtx || bCtx->baseObj.ctxId != XAMediaRecorderAdaptation )
       
   292     {
       
   293         DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
       
   294         DEBUG_API("<-XASnapshotItfAdaptation_SetShutterFeedback");
       
   295         /* invalid parameter */
       
   296         return XA_RESULT_PARAMETER_INVALID;
       
   297     }
       
   298     /* stubbed, no implementation */
       
   299     DEBUG_API("<-XASnapshotItfAdaptation_SetShutterFeedback");
       
   300     return XA_RESULT_SUCCESS;
       
   301 }
       
   302 
       
   303 /********************
       
   304  * Internal methods
       
   305  ********************/
       
   306 
       
   307 /*
       
   308  * void XASnapshotItfAdaptation_StopSnapshotting(XAAdaptationGstCtx* bCtx)
       
   309  */
       
   310 void XASnapshotItfAdaptation_StopSnapshotting(XAAdaptationGstCtx* bCtx)
       
   311 {
       
   312     XAMediaRecorderAdaptationCtx* mCtx = (XAMediaRecorderAdaptationCtx*) bCtx;
       
   313     DEBUG_API("->XASnapshotItfAdaptation_StopSnapshotting");
       
   314     mCtx->snapshotVars.waitforbuffer = FALSE;
       
   315     mCtx->snapshotVars.snapshotbuffer = NULL;
       
   316     if(mCtx->snapshotVars.sighandler)
       
   317     {
       
   318         if(mCtx->videoextract)
       
   319         {
       
   320             g_signal_handler_disconnect(mCtx->videoextract,mCtx->snapshotVars.sighandler);
       
   321         }
       
   322         mCtx->snapshotVars.sighandler = 0;
       
   323     }
       
   324     /* did we change the state of parent pipeline?*/
       
   325     if( mCtx->baseObj.bin && (GST_STATE(mCtx->baseObj.bin) != mCtx->baseObj.binWantedState) )
       
   326     {
       
   327         gst_element_set_state( GST_ELEMENT(mCtx->baseObj.bin), mCtx->baseObj.binWantedState );
       
   328     }
       
   329 
       
   330     if ( cameraCtx && (GST_STATE(cameraCtx->baseObj.bin) != cameraCtx->baseObj.binWantedState) )
       
   331 	{
       
   332     	cameraCtx->snapshotting = XA_BOOLEAN_FALSE;
       
   333 		DEBUG_INFO_A2("Camerabin state %d, restored to %d", GST_STATE(cameraCtx->baseObj.bin), cameraCtx->baseObj.binWantedState );
       
   334 		gst_element_set_state( GST_ELEMENT(cameraCtx->baseObj.bin), cameraCtx->baseObj.binWantedState );
       
   335 		gst_element_get_state( GST_ELEMENT(cameraCtx->baseObj.bin), NULL,NULL, XA_ADAPT_ASYNC_TIMEOUT_SHORT_NSEC);
       
   336 	}
       
   337     DEBUG_API("<-XASnapshotItfAdaptation_StopSnapshotting");
       
   338 }
       
   339 
       
   340 /*
       
   341  * XAresult XASnapshotItfAdaptation_FreeSnapshot(XAAdaptationGstCtx* bCtx)
       
   342  */
       
   343 XAresult XASnapshotItfAdaptation_FreeSnapshot(XAAdaptationGstCtx* bCtx)
       
   344 {
       
   345     XAMediaRecorderAdaptationCtx* mCtx = NULL;
       
   346     DEBUG_API("->XASnapshotItfAdaptation_FreeSnapshot");
       
   347     if(!bCtx || bCtx->baseObj.ctxId != XAMediaRecorderAdaptation)
       
   348     {
       
   349         DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
       
   350         DEBUG_API("<-XASnapshotItfAdaptation_FreeSnapshot");
       
   351         return XA_RESULT_PARAMETER_INVALID;
       
   352     }
       
   353     mCtx = (XAMediaRecorderAdaptationCtx*) bCtx;
       
   354     XASnapshotItfAdaptation_StopSnapshotting(bCtx);
       
   355     /* Clean up pipeline and set current pipeline state to null*/
       
   356     if( mCtx->snapshotVars.sspipeline )
       
   357     {
       
   358         gst_element_set_state( GST_ELEMENT(mCtx->snapshotVars.sspipeline), GST_STATE_NULL );
       
   359         gst_object_unref( GST_OBJECT(mCtx->snapshotVars.sspipeline) );
       
   360         mCtx->snapshotVars.sspipeline = NULL;
       
   361     }
       
   362     if( mCtx->snapshotVars.ssbus )
       
   363     {
       
   364         gst_object_unref( GST_OBJECT(mCtx->snapshotVars.ssbus) );
       
   365         mCtx->snapshotVars.ssbus = NULL;
       
   366     }
       
   367     if( mCtx->snapshotVars.fnametemplate )
       
   368     {
       
   369         free(mCtx->snapshotVars.fnametemplate);
       
   370         mCtx->snapshotVars.fnametemplate=NULL;
       
   371     }
       
   372     DEBUG_API("<-XASnapshotItfAdaptation_FreeSnapshot");
       
   373     return XA_RESULT_SUCCESS;
       
   374 }
       
   375 
       
   376 /*
       
   377  * XAresult XASnapshotItfAdaptation_CreateSnapshotPipeline(XAAdaptationGstCtx* bCtx)
       
   378  */
       
   379 XAresult XASnapshotItfAdaptation_CreateSnapshotPipeline(XAAdaptationGstCtx* bCtx)
       
   380 {
       
   381     XAMediaRecorderAdaptationCtx* mCtx = NULL;
       
   382 
       
   383     XACapabilities temp;
       
   384     GstCaps *imageCaps=NULL;
       
   385 
       
   386     DEBUG_API("->XASnapshotItfAdaptation_CreateSnapshotPipeline");
       
   387     if(!bCtx || bCtx->baseObj.ctxId != XAMediaRecorderAdaptation)
       
   388     {
       
   389         DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
       
   390         return XA_RESULT_PARAMETER_INVALID;
       
   391     }
       
   392     mCtx = (XAMediaRecorderAdaptationCtx*) bCtx;
       
   393 
       
   394     /*Create snapshotpipeline*/
       
   395     mCtx->snapshotVars.sspipeline = gst_pipeline_new ("sspipeline");
       
   396     if( mCtx->snapshotVars.sspipeline  )
       
   397     {
       
   398         /*add listener*/
       
   399         mCtx->snapshotVars.ssbus = gst_pipeline_get_bus(GST_PIPELINE( mCtx->snapshotVars.sspipeline ) );
       
   400         if( ! mCtx->snapshotVars.ssbus )
       
   401         {
       
   402             DEBUG_API("Cannot create snapshotbus");
       
   403             DEBUG_API("<-XASnapshotItfAdaptation_CreateSnapshotPipeline - XA_RESULT_INTERNAL_ERROR");
       
   404             return XA_RESULT_INTERNAL_ERROR;
       
   405         }
       
   406         gst_bus_add_signal_watch( mCtx->snapshotVars.ssbus );
       
   407         g_signal_connect(mCtx->snapshotVars.ssbus, "message::eos",
       
   408                 G_CALLBACK(XASnapshotItfAdaptation_SnapshotBusCb), bCtx );
       
   409         g_signal_connect(mCtx->snapshotVars.ssbus, "message::state-changed",
       
   410                 G_CALLBACK(XASnapshotItfAdaptation_SnapshotBusCb), bCtx );
       
   411         g_signal_connect(mCtx->snapshotVars.ssbus, "message::async-done",
       
   412                 G_CALLBACK(XASnapshotItfAdaptation_SnapshotBusCb), bCtx );
       
   413 
       
   414         /*Create snapshotsource element*/
       
   415         mCtx->snapshotVars.ssbuffersrc = gst_element_factory_make("appsrc", "ssbuffersrc");
       
   416         if( !mCtx->snapshotVars.ssbuffersrc )
       
   417         {
       
   418             DEBUG_ERR("Cannot create ssbuffersrc!");
       
   419             DEBUG_API("<-XASnapshotItfAdaptation_CreateSnapshotPipeline - XA_RESULT_INTERNAL_ERROR");
       
   420             return XA_RESULT_INTERNAL_ERROR;
       
   421         }
       
   422         /*Frame parser*/
       
   423         mCtx->snapshotVars.ssparser =
       
   424             gst_element_factory_make("videoparse","ssparser");
       
   425         if( !mCtx->snapshotVars.ssparser )
       
   426         {
       
   427             DEBUG_ERR("Could not create snapshotparse");
       
   428             DEBUG_API("<-XASnapshotItfAdaptation_CreateSnapshotPipeline - XA_RESULT_INTERNAL_ERROR");
       
   429             return XA_RESULT_INTERNAL_ERROR;
       
   430         }
       
   431 
       
   432         /*Scaler and filter for XAImageSettings width&height*/
       
   433         mCtx->snapshotVars.ssscaler =
       
   434             gst_element_factory_make("videoscale","ssscaler");
       
   435         if( !mCtx->snapshotVars.ssscaler )
       
   436         {
       
   437             DEBUG_ERR("Could not create ssscaler");
       
   438             DEBUG_API("<-XASnapshotItfAdaptation_CreateSnapshotPipeline - XA_RESULT_INTERNAL_ERROR");
       
   439             return XA_RESULT_INTERNAL_ERROR;
       
   440         }
       
   441         mCtx->snapshotVars.ssfilter =
       
   442             gst_element_factory_make("capsfilter","ssfilter");
       
   443         if( !mCtx->snapshotVars.ssfilter )
       
   444         {
       
   445             DEBUG_ERR("Could not create ssfilter");
       
   446             DEBUG_API("<-XASnapshotItfAdaptation_CreateSnapshotPipeline - XA_RESULT_INTERNAL_ERROR");
       
   447             return XA_RESULT_INTERNAL_ERROR;
       
   448         }
       
   449 
       
   450         /*Create imageencoder */
       
   451         if(XACapabilitiesMgr_GetCapsById(NULL, (XACapsType)(XACAP_ENCODER|XACAP_IMAGE), mCtx->imageEncSettings.encoderId, &temp) == XA_RESULT_SUCCESS)
       
   452         {
       
   453             if(temp.adaptId != NULL)
       
   454             {
       
   455                 mCtx->snapshotVars.ssencoder = gst_element_factory_make((char*)temp.adaptId, "ssencoder");
       
   456             }
       
   457             else if(mCtx->imageEncSettings.encoderId == XA_IMAGECODEC_RAW)
       
   458             {
       
   459                 /* raw frames are internal format, so no codec needed. just insert identity for linking*/
       
   460                mCtx->snapshotVars.ssencoder = gst_element_factory_make("identity", "ssencoder");
       
   461             }
       
   462         }
       
   463         if( !mCtx->snapshotVars.ssencoder )
       
   464         {
       
   465             DEBUG_API("Cannot create image encoder");
       
   466             DEBUG_API("<-XASnapshotItfAdaptation_CreateSnapshotPipeline - XA_RESULT_INTERNAL_ERROR");
       
   467             return XA_RESULT_INTERNAL_ERROR;
       
   468         }
       
   469 
       
   470         /* Create also tag setter for JPG */
       
   471         if(mCtx->imageEncSettings.encoderId == XA_IMAGECODEC_JPEG)
       
   472         {
       
   473             mCtx->snapshotVars.sstagger = gst_element_factory_make("metadatamux", "sstagger");
       
   474             if( !mCtx->snapshotVars.sstagger || !gst_bin_add(GST_BIN(mCtx->snapshotVars.sspipeline),mCtx->snapshotVars.sstagger))
       
   475             {
       
   476                 DEBUG_API("Cannot create metadatamux");
       
   477                 DEBUG_API("<-XASnapshotItfAdaptation_CreateSnapshotPipeline - XA_RESULT_INTERNAL_ERROR");
       
   478             }
       
   479             g_object_set( G_OBJECT(mCtx->snapshotVars.sstagger), "xmp", TRUE, "exif", TRUE, "iptc", TRUE, NULL );
       
   480         }
       
   481 
       
   482         /*Create sink*/
       
   483         if(mCtx->snapshotVars.fnametemplate)
       
   484         {
       
   485             DEBUG_INFO("RECORD SNAPSHOT TO FILE");
       
   486             mCtx->snapshotVars.sssink = gst_element_factory_make("filesink","ssfilesink");
       
   487             g_object_set( G_OBJECT(mCtx->snapshotVars.sssink), "location", "temp",
       
   488                                                                 "async", FALSE,
       
   489                                                                 "qos", FALSE,
       
   490                                                                 "max-lateness", (gint64)(-1),
       
   491                                                                 "buffer-mode", 2,
       
   492                                                                 NULL );
       
   493         }
       
   494         else
       
   495         {
       
   496             DEBUG_INFO("RECORD SNAPSHOT TO MEMORY");
       
   497             mCtx->snapshotVars.sssink = gst_element_factory_make("appsink","ssbuffersink");
       
   498         }
       
   499         if( !mCtx->snapshotVars.sssink )
       
   500         {
       
   501             DEBUG_ERR("Could not create sssink!!");
       
   502             DEBUG_API("<-XASnapshotItfAdaptation_CreateSnapshotPipeline - XA_RESULT_INTERNAL_ERROR");
       
   503             return XA_RESULT_INTERNAL_ERROR;
       
   504         }
       
   505         g_object_set( G_OBJECT(mCtx->snapshotVars.sssink), "async", FALSE, NULL );
       
   506 
       
   507         /*Add elements to bin*/
       
   508         gst_bin_add_many (GST_BIN (mCtx->snapshotVars.sspipeline),
       
   509                 mCtx->snapshotVars.ssbuffersrc,
       
   510                 mCtx->snapshotVars.ssparser,
       
   511                 mCtx->snapshotVars.ssscaler,
       
   512                 mCtx->snapshotVars.ssfilter,
       
   513                 mCtx->snapshotVars.ssencoder,
       
   514                 mCtx->snapshotVars.sssink,
       
   515                 NULL);
       
   516 
       
   517         /* set needed XAImageSettings properties*/
       
   518         /* set caps from imagesettings */
       
   519         imageCaps = gst_caps_new_simple("video/x-raw-yuv",
       
   520                                         "width", G_TYPE_INT, mCtx->imageEncSettings.width,
       
   521                                         "height", G_TYPE_INT, mCtx->imageEncSettings.height, NULL);
       
   522         g_object_set( G_OBJECT(mCtx->snapshotVars.ssfilter), "caps", imageCaps, NULL );
       
   523         DEBUG_INFO_A1("new caps: %s",gst_caps_to_string(imageCaps));
       
   524         gst_caps_unref(imageCaps);
       
   525 
       
   526         /* set compression level */
       
   527         if(mCtx->imageEncSettings.encoderId == XA_IMAGECODEC_JPEG)
       
   528         {
       
   529             g_object_set( G_OBJECT(mCtx->snapshotVars.ssencoder), "quality", (gint)(1000 - mCtx->imageEncSettings.compressionLevel)/10, NULL );
       
   530         }
       
   531 
       
   532         /*Chain elements together*/
       
   533         if(mCtx->snapshotVars.sstagger)
       
   534         {
       
   535             if( !gst_element_link_many(
       
   536                     mCtx->snapshotVars.ssbuffersrc,
       
   537                     mCtx->snapshotVars.ssparser,
       
   538                     mCtx->snapshotVars.ssscaler,
       
   539                     mCtx->snapshotVars.ssfilter,
       
   540                     mCtx->snapshotVars.ssencoder,
       
   541                     mCtx->snapshotVars.sstagger,
       
   542                     mCtx->snapshotVars.sssink,
       
   543                     NULL) )
       
   544             {
       
   545                 DEBUG_ERR("Could not link pipeline")
       
   546                 return XA_RESULT_INTERNAL_ERROR;
       
   547             }
       
   548         }
       
   549         else
       
   550         {
       
   551             if( !gst_element_link_many(
       
   552                     mCtx->snapshotVars.ssbuffersrc,
       
   553                     mCtx->snapshotVars.ssparser,
       
   554                     mCtx->snapshotVars.ssscaler,
       
   555                     mCtx->snapshotVars.ssfilter,
       
   556                     mCtx->snapshotVars.ssencoder,
       
   557                     mCtx->snapshotVars.sssink,
       
   558                     NULL) )
       
   559             {
       
   560                 DEBUG_ERR("Could not link pipeline")
       
   561                 return XA_RESULT_INTERNAL_ERROR;
       
   562             }
       
   563         }
       
   564         gst_element_set_state(GST_ELEMENT(mCtx->snapshotVars.sspipeline), GST_STATE_READY);
       
   565         DEBUG_API("<-XASnapshotItfAdaptation_CreateSnapshotPipeline");
       
   566         return XA_RESULT_SUCCESS;
       
   567 
       
   568     }
       
   569     else
       
   570     {
       
   571         DEBUG_ERR("XA_RESULT_PRECONDITIONS_VIOLATED");
       
   572         DEBUG_API("<-XASnapshotItfAdaptation_CreateSnapshotPipeline");
       
   573         return  XA_RESULT_PRECONDITIONS_VIOLATED;
       
   574     }
       
   575 }
       
   576 
       
   577 /*
       
   578  * gboolean XASnapshotItfAdaptation_SnapshotBusCb( GstBus *bus, GstMessage *message, gpointer data )
       
   579  */
       
   580 gboolean XASnapshotItfAdaptation_SnapshotBusCb( GstBus *bus, GstMessage *message, gpointer data )
       
   581 {
       
   582     XAMediaRecorderAdaptationCtx* mCtx = (XAMediaRecorderAdaptationCtx*)data;
       
   583 
       
   584     GstState oldstate = GST_STATE_NULL , newstate = GST_STATE_NULL , pendingstate = GST_STATE_NULL;
       
   585 
       
   586     /* only interested in messages from snapshot pipeline */
       
   587     if( GST_MESSAGE_SRC(message) == GST_OBJECT(mCtx->snapshotVars.sspipeline) )
       
   588     {
       
   589         DEBUG_API_A2("->XASnapshotItfAdaptation_SnapshotBusCb:\"%s\" from object \"%s\"",
       
   590                 GST_MESSAGE_TYPE_NAME(message), GST_OBJECT_NAME(GST_MESSAGE_SRC(message)));
       
   591 
       
   592         switch( GST_MESSAGE_TYPE(message))
       
   593         {
       
   594             case GST_MESSAGE_EOS:
       
   595             {
       
   596                 if( gst_element_set_state(GST_ELEMENT(mCtx->snapshotVars.sspipeline), GST_STATE_READY)
       
   597                         == GST_STATE_CHANGE_FAILURE )
       
   598                 {
       
   599                     DEBUG_ERR("Error stopping snapshot pipeline!!!");
       
   600                 }
       
   601                 gst_element_get_state(mCtx->snapshotVars.sspipeline, NULL, NULL, XA_ADAPT_ASYNC_TIMEOUT_SHORT_NSEC);
       
   602 
       
   603                 DEBUG_INFO_A2("Requested %lu snapshots, taked %lu",mCtx->snapshotVars.numpics,mCtx->snapshotVars.numpicstaken+1);
       
   604                 if( ++mCtx->snapshotVars.numpicstaken >= mCtx->snapshotVars.numpics )
       
   605                 {
       
   606                     XAAdaptEvent takenevent = {XA_SNAPSHOTITFEVENTS, XA_ADAPT_SNAPSHOT_TAKEN, 0, NULL };
       
   607                     DEBUG_INFO("Snapshot burst finished");
       
   608                     XASnapshotItfAdaptation_StopSnapshotting(&(mCtx->baseObj));
       
   609                     if( mCtx->snapshotVars.fnametemplate == NULL )
       
   610                     {   /* non-datasink snapshot, return buffer */
       
   611                         GstBuffer* pullBuffer = NULL;
       
   612                         XADataSink* pullSink = NULL;
       
   613                         XADataLocator_Address* pullSinkLoc = NULL;
       
   614                         DEBUG_INFO("Get buffer from appsink");
       
   615                         pullBuffer = gst_app_sink_pull_preroll( GST_APP_SINK(mCtx->snapshotVars.sssink) );
       
   616                         /* allocate XADataSink, client should release this later*/
       
   617                         pullSink = (XADataSink*)calloc(1, sizeof(XADataSink));
       
   618                         pullSinkLoc = (XADataLocator_Address*)calloc(1, sizeof(XADataLocator_Address));
       
   619                         pullSinkLoc->length = pullBuffer->size;
       
   620                         pullSinkLoc->pAddress = (XADataLocator_Address*)calloc(1, pullBuffer->size);
       
   621                         memcpy(pullSinkLoc->pAddress, pullBuffer->data, pullBuffer->size);
       
   622                         pullSinkLoc->locatorType = XA_DATALOCATOR_ADDRESS;
       
   623                         pullSink->pLocator = pullSinkLoc;
       
   624                         pullSink->pFormat = NULL;
       
   625                         takenevent.data = pullSink;
       
   626                     }
       
   627                     /* send needed events */
       
   628                     takenevent.datasize = mCtx->snapshotVars.numpicstaken;
       
   629                     XAAdaptationBase_SendAdaptEvents(&(mCtx->baseObj.baseObj), &takenevent );
       
   630                 }
       
   631                 else
       
   632                 {
       
   633                     /* videoparse element can not handle renegotiation of stream for new buffer
       
   634                      * after EOS, so recreate it */
       
   635                     gst_element_unlink_many(
       
   636                             mCtx->snapshotVars.ssbuffersrc,
       
   637                             mCtx->snapshotVars.ssparser,
       
   638                             mCtx->snapshotVars.ssscaler,
       
   639                             NULL);
       
   640                     gst_element_set_state(GST_ELEMENT(mCtx->snapshotVars.ssparser), GST_STATE_NULL);
       
   641                     gst_bin_remove(GST_BIN (mCtx->snapshotVars.sspipeline),mCtx->snapshotVars.ssparser);
       
   642                     mCtx->snapshotVars.ssparser = gst_element_factory_make("videoparse", "ssparser");
       
   643                     if( !mCtx->snapshotVars.ssparser )
       
   644                     {
       
   645                         DEBUG_ERR("Cannot create ssparser!");
       
   646                         DEBUG_API("<-XASnapshotItfAdaptation_CreateSnapshotPipeline - XA_RESULT_INTERNAL_ERROR");
       
   647                         return XA_RESULT_INTERNAL_ERROR;
       
   648                     }
       
   649                     gst_bin_add(GST_BIN (mCtx->snapshotVars.sspipeline),mCtx->snapshotVars.ssparser);
       
   650                     if( !gst_element_link_many(
       
   651                             mCtx->snapshotVars.ssbuffersrc,
       
   652                             mCtx->snapshotVars.ssparser,
       
   653                             mCtx->snapshotVars.ssscaler,
       
   654                             NULL) )
       
   655                     {
       
   656                         DEBUG_ERR("Could not link pipeline")
       
   657                         return XA_RESULT_INTERNAL_ERROR;
       
   658                     }
       
   659                     mCtx->snapshotVars.parsenegotiated = FALSE;
       
   660 
       
   661                     /*now, wait for new buffer to arrive*/
       
   662                     DEBUG_INFO("Wait for more pictures");
       
   663                     mCtx->snapshotVars.waitforbuffer = TRUE;
       
   664                     mCtx->snapshotVars.sighandler = g_signal_connect(mCtx->videoextract, "handoff",
       
   665                                             G_CALLBACK (XASnapshotItfAdaptation_BufferHandoffCb),mCtx);
       
   666                 }
       
   667                 break;
       
   668             }
       
   669             case GST_MESSAGE_STATE_CHANGED:
       
   670             {
       
   671                 gst_message_parse_state_changed(message, &oldstate, &newstate, &pendingstate);
       
   672                 DEBUG_INFO_A4("old %s -> new %s ( pending %s, gsttarget %s )",
       
   673                         gst_element_state_get_name(oldstate),
       
   674                         gst_element_state_get_name(newstate),
       
   675                         gst_element_state_get_name(pendingstate),
       
   676                         gst_element_state_get_name(GST_STATE_TARGET(mCtx->snapshotVars.sspipeline)) );
       
   677                 if( newstate==GST_STATE_READY && oldstate==GST_STATE_NULL )
       
   678                 {
       
   679                     XAAdaptEvent initevent = {XA_SNAPSHOTITFEVENTS, XA_ADAPT_SNAPSHOT_INITIATED,0, NULL };
       
   680                     DEBUG_INFO("Init complete");
       
   681                     /* send needed events */
       
   682                     XAAdaptationBase_SendAdaptEvents( &(mCtx->baseObj.baseObj), &initevent);
       
   683                 }
       
   684                 else if( newstate==GST_STATE_PLAYING && oldstate==GST_STATE_PAUSED && mCtx->snapshotVars.snapshotbuffer )
       
   685                 {
       
   686                     DEBUG_INFO("Pushing buffer");
       
   687                     gst_app_src_push_buffer( GST_APP_SRC(mCtx->snapshotVars.ssbuffersrc),
       
   688                                              mCtx->snapshotVars.snapshotbuffer );
       
   689                     DEBUG_INFO_A1("Sent buffer at 0x%x to  ssbuffersrc", (int)mCtx->snapshotVars.snapshotbuffer );
       
   690                     gst_app_src_end_of_stream( GST_APP_SRC(mCtx->snapshotVars.ssbuffersrc) );
       
   691                     mCtx->snapshotVars.snapshotbuffer = NULL;
       
   692                     DEBUG_INFO("Sent EOS ssbuffersrc");
       
   693                 }
       
   694 
       
   695                 break;
       
   696             }
       
   697             default:
       
   698                 break;
       
   699         }
       
   700         DEBUG_API("<-XASnapshotItfAdaptation_SnapshotBusCb");
       
   701     }
       
   702     return TRUE;
       
   703 }
       
   704 
       
   705 /*
       
   706  * void XASnapshotItfAdaptation_BufferHandoffCb( GstElement *extract, GstBuffer  *buffer, gpointer data )
       
   707  */
       
   708 void XASnapshotItfAdaptation_BufferHandoffCb( GstElement *extract, GstBuffer  *buffer, gpointer data )
       
   709 {
       
   710     XAMediaRecorderAdaptationCtx* mCtx = (XAMediaRecorderAdaptationCtx*)data;
       
   711     gint32 width=0, height=0;
       
   712     guint32  fourcc=0, formatnum=0;
       
   713     GstPad* srcPad=NULL;
       
   714     GstCaps* srcPadCaps=NULL;
       
   715     GstStructure* capS=NULL;
       
   716     XAAdaptEvent event = {XA_SNAPSHOTITFEVENTS, XA_ADAPT_SNAPSHOT_TAKEN, 0, NULL };
       
   717     char* fname=NULL;
       
   718 
       
   719     DEBUG_API("->XASnapshotItfAdaptation_BufferHandoffCb");
       
   720     if( !mCtx->snapshotVars.waitforbuffer ||
       
   721         !GST_IS_BUFFER(buffer) )
       
   722     {   /* pass on... */
       
   723         DEBUG_API("<-XASnapshotItfAdaptation_BufferHandoffCb");
       
   724         return;
       
   725     }
       
   726 
       
   727     if(mCtx->snapshotVars.snapshotbuffer)
       
   728     {
       
   729         DEBUG_INFO("WARNING: snapshotbuffer already exists!!");
       
   730         gst_buffer_unref(GST_BUFFER(mCtx->snapshotVars.snapshotbuffer));
       
   731     }
       
   732     DEBUG_INFO("Receiced snapshotbuffer");
       
   733     mCtx->snapshotVars.snapshotbuffer = gst_buffer_copy(buffer);
       
   734     mCtx->snapshotVars.waitforbuffer = FALSE;
       
   735     g_signal_handler_disconnect(mCtx->videoextract,mCtx->snapshotVars.sighandler);
       
   736     mCtx->snapshotVars.sighandler = 0;
       
   737 
       
   738     if( GST_STATE(mCtx->snapshotVars.sspipeline)==GST_STATE_READY )
       
   739     {
       
   740         if( !(mCtx->snapshotVars.parsenegotiated) )
       
   741         {
       
   742             /*read relevant caps of extraction source and set them to videoparse*/
       
   743             srcPad = gst_element_get_pad( GST_ELEMENT(extract), "src");
       
   744             srcPadCaps = gst_pad_get_negotiated_caps( GST_PAD(srcPad) );
       
   745             capS = gst_caps_get_structure(srcPadCaps,0);
       
   746             DEBUG_INFO_A1("buffer caps from extraction source: %s",gst_caps_to_string(srcPadCaps));
       
   747             if( !gst_structure_get_int(capS,"width",&width) ||
       
   748                 !gst_structure_get_int(capS,"height",&height) ||
       
   749                 !gst_structure_get_fourcc(capS,"format",&fourcc) )
       
   750             {
       
   751                 DEBUG_ERR("ERROR! Missing crucial capabilities for buffer!!");
       
   752                 DEBUG_API("<-XASnapshotItfAdaptation_BufferHandoffCb");
       
   753                 return;
       
   754             }
       
   755             /* convert fourcc to videoparse enumeration */
       
   756             switch(fourcc)
       
   757             {
       
   758                 case GST_MAKE_FOURCC('I','4','2','0'):
       
   759                     formatnum = 0;
       
   760                     break;
       
   761                 case GST_MAKE_FOURCC('Y','V','1','2'):
       
   762                     formatnum = 1;
       
   763                     break;
       
   764                 case GST_MAKE_FOURCC('Y','U','Y','2'):
       
   765                     formatnum = 2;
       
   766                     break;
       
   767                 case GST_MAKE_FOURCC('U','Y','V','Y'):
       
   768                     formatnum = 3;
       
   769                     break;
       
   770                 case GST_MAKE_FOURCC('R','G','B',' '):
       
   771                     formatnum = 10;
       
   772                     break;
       
   773                 case GST_MAKE_FOURCC('G','R','A','Y'):
       
   774                     formatnum = 11;
       
   775                     break;
       
   776                 default:
       
   777                     formatnum = 0;
       
   778                     break;
       
   779             }
       
   780             /* set source width and height for parser */
       
   781             g_object_set(mCtx->snapshotVars.ssparser,"width",width,"height",height,"format",formatnum,NULL);
       
   782             mCtx->snapshotVars.parsenegotiated = TRUE;
       
   783         }
       
   784         if(mCtx->snapshotVars.fnametemplate)
       
   785         {   /* get actual filename from template */
       
   786             XASnapshotItfAdaptation_AllocNextFilename(&fname, mCtx->snapshotVars.fnametemplate);
       
   787             DEBUG_INFO_A1("start taking snapshot (%s)", fname);
       
   788             gst_element_set_state(GST_ELEMENT(mCtx->snapshotVars.sssink), GST_STATE_NULL);
       
   789             g_object_set( G_OBJECT(mCtx->snapshotVars.sssink), "location", fname,
       
   790                                                                 "async", FALSE,
       
   791                                                                 "qos", FALSE,
       
   792                                                                 "max-lateness", (gint64)(-1),
       
   793                                                                 NULL );
       
   794             gst_element_sync_state_with_parent(mCtx->snapshotVars.sssink);
       
   795             gst_element_get_state(mCtx->snapshotVars.sssink, NULL, NULL, XA_ADAPT_ASYNC_TIMEOUT_SHORT_NSEC);
       
   796             free(fname);
       
   797         }
       
   798         else
       
   799         {   /* take snapshot to buffer */
       
   800             DEBUG_INFO("start taking snapshot (memory buffer used)");
       
   801         }
       
   802         /* write metadata, if any */
       
   803         XAMetadataAdapt_TryWriteTags(&(mCtx->baseObj), GST_BIN(mCtx->snapshotVars.sspipeline));
       
   804         /* start buffering */
       
   805         if( gst_element_set_state(GST_ELEMENT(mCtx->snapshotVars.sspipeline), GST_STATE_PLAYING )
       
   806                 == GST_STATE_CHANGE_FAILURE )
       
   807         {
       
   808             DEBUG_ERR("Error taking picture!!!");
       
   809             /* NOTE: no event for errors in snapshotitf!!! */
       
   810             event.datasize = mCtx->snapshotVars.numpicstaken;
       
   811             XAAdaptationBase_SendAdaptEvents(&(mCtx->baseObj.baseObj), &event );
       
   812         }
       
   813     }
       
   814     else
       
   815     {
       
   816         DEBUG_INFO_A1("warning: sspipeline in wrong state (%d)",
       
   817                         GST_STATE(mCtx->snapshotVars.sspipeline));
       
   818     }
       
   819     DEBUG_API("<-XASnapshotItfAdaptation_BufferHandoffCb");
       
   820 }
       
   821 
       
   822 /*
       
   823  * const char* XASnapshotItfAdaptation_GetFileSuffix(XADataFormat_MIME* format)
       
   824  */
       
   825 const char* XASnapshotItfAdaptation_GetFileSuffix(XADataFormat_MIME* format)
       
   826 {
       
   827     const char* ret=NULL;
       
   828     if( format )
       
   829     {
       
   830         if( *(XAuint32*)format == XA_DATAFORMAT_MIME )
       
   831         {
       
   832             switch (format->containerType)
       
   833             {
       
   834                 case XA_CONTAINERTYPE_JPG:
       
   835                     ret = "jpg";
       
   836                     break;
       
   837                 case XA_CONTAINERTYPE_RAW:
       
   838                     ret = "raw";
       
   839                     break;
       
   840                 case XA_CONTAINERTYPE_BMP:
       
   841                     ret = "bmp";
       
   842                     break;
       
   843                 default:
       
   844                     break;
       
   845             }
       
   846             if(!ret)
       
   847             { /*parse from mimetype*/
       
   848                 if(format->mimeType)
       
   849                 {
       
   850                     ret = strrchr((char*)format->mimeType,'/');
       
   851                     if (ret)
       
   852                     {
       
   853                         ret++;
       
   854                     }
       
   855                 }
       
   856             }
       
   857         }
       
   858         else if( *(XAuint32*)format == XA_DATAFORMAT_RAWIMAGE )
       
   859         {
       
   860             ret = "raw";
       
   861         }
       
   862     }
       
   863     if(!ret)
       
   864     {
       
   865         ret="jpg"; /*default*/
       
   866     }
       
   867     return ret;
       
   868 }
       
   869 
       
   870 /*
       
   871  * void XASnapshotItfAdaptation_AllocNextFilename(char** fname, const char* template)
       
   872  */
       
   873 void XASnapshotItfAdaptation_AllocNextFilename(char** fname, const char* template)
       
   874 {
       
   875     XAuint32 idx=0;
       
   876     XAboolean found=XA_BOOLEAN_FALSE;
       
   877     FILE* file=NULL;
       
   878     *fname = (char*)calloc(1,strlen(template)+10);
       
   879     while(!found)
       
   880     {
       
   881         sprintf(*fname, template, idx++ );
       
   882         strcat(*fname, "\0");
       
   883         file = fopen(*fname, "r");
       
   884         if(file==NULL)
       
   885         {
       
   886             found = XA_BOOLEAN_TRUE;
       
   887             break;
       
   888         }
       
   889         fclose(file);
       
   890     }
       
   891 }