gst_plugins_symbian/gst/AudioRecordBin/src/GstAudioRecordBin.cpp
author hgs
Fri, 14 May 2010 18:43:44 -0500
changeset 20 7e3786c5ed27
parent 18 5824eee55f42
permissions -rw-r--r--
201019
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
18
hgs
parents:
diff changeset
     1
/*
hgs
parents:
diff changeset
     2
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
hgs
parents:
diff changeset
     3
*
hgs
parents:
diff changeset
     4
* This library is free software; you can redistribute it and/or
hgs
parents:
diff changeset
     5
* modify it under the terms of the GNU Lesser General Public
hgs
parents:
diff changeset
     6
* License as published by the Free Software Foundation; either
hgs
parents:
diff changeset
     7
* version 2 of the License, or (at your option) any later version.
hgs
parents:
diff changeset
     8
*
hgs
parents:
diff changeset
     9
* This library is distributed in the hope that it will be useful,
hgs
parents:
diff changeset
    10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
hgs
parents:
diff changeset
    11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
hgs
parents:
diff changeset
    12
* Lesser General Public License for more details.
hgs
parents:
diff changeset
    13
*
hgs
parents:
diff changeset
    14
* You should have received a copy of the GNU Lesser General Public
hgs
parents:
diff changeset
    15
* License along with this library; if not, write to the
hgs
parents:
diff changeset
    16
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
hgs
parents:
diff changeset
    17
* Boston, MA 02111-1307, USA.
hgs
parents:
diff changeset
    18
*
hgs
parents:
diff changeset
    19
* Description:
hgs
parents:
diff changeset
    20
*
hgs
parents:
diff changeset
    21
*/
hgs
parents:
diff changeset
    22
hgs
parents:
diff changeset
    23
//  Include Files  
hgs
parents:
diff changeset
    24
hgs
parents:
diff changeset
    25
#include "GstAudioRecordBin.h"
hgs
parents:
diff changeset
    26
#include "gstfactorylists.h"
hgs
parents:
diff changeset
    27
#include <gst/gst.h>
hgs
parents:
diff changeset
    28
#include <string.h>
hgs
parents:
diff changeset
    29
#include <stdlib.h>
hgs
parents:
diff changeset
    30
hgs
parents:
diff changeset
    31
GST_DEBUG_CATEGORY_STATIC (aud_recbin_cat);     // define category (statically)
20
hgs
parents: 18
diff changeset
    32
#ifdef GST_CAT_DEFAULT
hgs
parents: 18
diff changeset
    33
#undef GST_CAT_DEFAULT
hgs
parents: 18
diff changeset
    34
#endif
hgs
parents: 18
diff changeset
    35
18
hgs
parents:
diff changeset
    36
#define GST_CAT_DEFAULT aud_recbin_cat     // set as default
hgs
parents:
diff changeset
    37
hgs
parents:
diff changeset
    38
/** Macro to enable weak ref monitoring, used to track
hgs
parents:
diff changeset
    39
 * ref / unref problems. 
hgs
parents:
diff changeset
    40
 * NOTE : DO NOT USE IN HARDWARE, can be used in EMULATOR ONLY */
hgs
parents:
diff changeset
    41
//#define WEAK_REF
hgs
parents:
diff changeset
    42
#ifdef WEAK_REF
hgs
parents:
diff changeset
    43
#define MONITOR_REF(gobj) if( G_IS_OBJECT(gobj) ) g_object_weak_ref( G_OBJECT(gobj), sWeakNotify, (gpointer) #gobj)
hgs
parents:
diff changeset
    44
/** Weak Ref callback */
hgs
parents:
diff changeset
    45
static void sWeakNotify (gpointer  data, GObject  *where_the_object_was);
hgs
parents:
diff changeset
    46
#else
hgs
parents:
diff changeset
    47
#define MONITOR_REF(gobj) /* NOP */
hgs
parents:
diff changeset
    48
#endif // WEAK_REF
hgs
parents:
diff changeset
    49
hgs
parents:
diff changeset
    50
/** Enable the caps filter */
hgs
parents:
diff changeset
    51
//#define ENABLE_CAPS_FILTER
hgs
parents:
diff changeset
    52
hgs
parents:
diff changeset
    53
/** The struct used to indicated the filter criteria for gst plugin factory */
hgs
parents:
diff changeset
    54
typedef struct
hgs
parents:
diff changeset
    55
{
hgs
parents:
diff changeset
    56
    /** The type of the factory */
hgs
parents:
diff changeset
    57
    GstFactoryListType type;
hgs
parents:
diff changeset
    58
    /** The caps expected to be supported by a sink pad */
hgs
parents:
diff changeset
    59
    GstCaps* sinkCaps;
hgs
parents:
diff changeset
    60
    /** The caps expected to be supported by a src pad */
hgs
parents:
diff changeset
    61
    GstCaps* srcCaps;
hgs
parents:
diff changeset
    62
} FilterData;
20
hgs
parents: 18
diff changeset
    63
#ifdef ENABLE_CAPS_FILTER
18
hgs
parents:
diff changeset
    64
/** Create the capability filter */
hgs
parents:
diff changeset
    65
static GstElement* sCreateCapsFilter( GstCaps* encCaps);
20
hgs
parents: 18
diff changeset
    66
#endif
18
hgs
parents:
diff changeset
    67
hgs
parents:
diff changeset
    68
/** Creates the element , which accepts \a sinkcaps and 
hgs
parents:
diff changeset
    69
 * provides \a srccaps on the src pad */
hgs
parents:
diff changeset
    70
GstElement* sCreateCompatibleFilter(GstFactoryListType type,
hgs
parents:
diff changeset
    71
        const gchar* name, GstCaps* sinkcaps, GstCaps* srccaps);
hgs
parents:
diff changeset
    72
hgs
parents:
diff changeset
    73
hgs
parents:
diff changeset
    74
/** Utility function to create the caps depending on the mimetype, fills in the default
hgs
parents:
diff changeset
    75
 * values
hgs
parents:
diff changeset
    76
 * */
hgs
parents:
diff changeset
    77
static GstCaps* sCreateCaps( const char* mimetype );
hgs
parents:
diff changeset
    78
hgs
parents:
diff changeset
    79
/**
hgs
parents:
diff changeset
    80
 * Checks if a given element \a factory can accpet the \a caps on a pad
hgs
parents:
diff changeset
    81
 * of given \a direction.
hgs
parents:
diff changeset
    82
 */
hgs
parents:
diff changeset
    83
gboolean gst_element_factory_can_accept_caps (GstElementFactory * factory,
hgs
parents:
diff changeset
    84
    const GstCaps * caps, GstPadDirection direction )
hgs
parents:
diff changeset
    85
{
hgs
parents:
diff changeset
    86
  GList *templates;
hgs
parents:
diff changeset
    87
hgs
parents:
diff changeset
    88
  g_return_val_if_fail (factory != NULL, FALSE);
hgs
parents:
diff changeset
    89
  g_return_val_if_fail (caps != NULL, FALSE);
hgs
parents:
diff changeset
    90
hgs
parents:
diff changeset
    91
  templates = factory->staticpadtemplates;
hgs
parents:
diff changeset
    92
hgs
parents:
diff changeset
    93
  while (templates) {
hgs
parents:
diff changeset
    94
    GstStaticPadTemplate *template1 = (GstStaticPadTemplate *) templates->data;
hgs
parents:
diff changeset
    95
hgs
parents:
diff changeset
    96
    if (template1->direction == direction ) {
hgs
parents:
diff changeset
    97
      if (gst_caps_is_subset( caps, gst_static_caps_get(&template1->static_caps)))
hgs
parents:
diff changeset
    98
        return TRUE;
hgs
parents:
diff changeset
    99
    }
hgs
parents:
diff changeset
   100
    templates = g_list_next (templates);
hgs
parents:
diff changeset
   101
  }
hgs
parents:
diff changeset
   102
hgs
parents:
diff changeset
   103
  return FALSE;
hgs
parents:
diff changeset
   104
}
hgs
parents:
diff changeset
   105
/**
hgs
parents:
diff changeset
   106
 * Checks if the element factory has the \a klass_type and checks if the filter data
hgs
parents:
diff changeset
   107
 * criteria ( accepts sinkCaps & srcCaps ) is met.
hgs
parents:
diff changeset
   108
 */
hgs
parents:
diff changeset
   109
static inline gboolean element_klass_filter (GstElementFactory * factory, const gchar *klass_type, FilterData* pData)
hgs
parents:
diff changeset
   110
{
hgs
parents:
diff changeset
   111
    const gchar *klass = NULL;
hgs
parents:
diff changeset
   112
    gboolean sink_caps_supported = FALSE;
hgs
parents:
diff changeset
   113
    gboolean src_caps_supported = FALSE;
hgs
parents:
diff changeset
   114
hgs
parents:
diff changeset
   115
    klass = gst_element_factory_get_klass (factory);
hgs
parents:
diff changeset
   116
    GST_DEBUG("klass = %s\n", klass);
hgs
parents:
diff changeset
   117
hgs
parents:
diff changeset
   118
    if (strstr (klass, klass_type) != NULL)
hgs
parents:
diff changeset
   119
    {
hgs
parents:
diff changeset
   120
        sink_caps_supported = gst_element_factory_can_accept_caps( factory, pData->sinkCaps, GST_PAD_SINK );               
hgs
parents:
diff changeset
   121
    
hgs
parents:
diff changeset
   122
        src_caps_supported = gst_element_factory_can_accept_caps( factory, pData->srcCaps, GST_PAD_SRC );
hgs
parents:
diff changeset
   123
hgs
parents:
diff changeset
   124
        GST_INFO("%s fact name = %s, can sink %d can src %d \n",
hgs
parents:
diff changeset
   125
                klass_type,
hgs
parents:
diff changeset
   126
                GST_PLUGIN_FEATURE_NAME(factory),
hgs
parents:
diff changeset
   127
                sink_caps_supported, src_caps_supported
hgs
parents:
diff changeset
   128
                );
hgs
parents:
diff changeset
   129
hgs
parents:
diff changeset
   130
        return TRUE && sink_caps_supported && src_caps_supported;
hgs
parents:
diff changeset
   131
    }
hgs
parents:
diff changeset
   132
hgs
parents:
diff changeset
   133
    return FALSE;
hgs
parents:
diff changeset
   134
}
hgs
parents:
diff changeset
   135
hgs
parents:
diff changeset
   136
/**
hgs
parents:
diff changeset
   137
 * gst_factory_list_is_type:
hgs
parents:
diff changeset
   138
 * @factory: a #GstElementFactory
hgs
parents:
diff changeset
   139
 * @type: a #GstFactoryListType
hgs
parents:
diff changeset
   140
 *
hgs
parents:
diff changeset
   141
 * Check if @factory if of the given types.
hgs
parents:
diff changeset
   142
 *
hgs
parents:
diff changeset
   143
 * Returns: %TRUE if @factory is of @type.
hgs
parents:
diff changeset
   144
 */
hgs
parents:
diff changeset
   145
gboolean gst_factory_list_is_type (GstElementFactory * factory, FilterData * pData)
hgs
parents:
diff changeset
   146
{
hgs
parents:
diff changeset
   147
    gboolean res = FALSE;
hgs
parents:
diff changeset
   148
    const char* encoder_klass_str = "Encoder";
hgs
parents:
diff changeset
   149
    const char* muxer_klass_str = "Muxer";
hgs
parents:
diff changeset
   150
hgs
parents:
diff changeset
   151
    /* NOTE : GST_FACTORY_LIST_SINK, GST_FACTORY_LIST_DECODER, GST_FACTORY_LIST_SRC
hgs
parents:
diff changeset
   152
     * ignored.
hgs
parents:
diff changeset
   153
     */
hgs
parents:
diff changeset
   154
    if (!res && (pData->type & GST_FACTORY_LIST_ENCODER))
hgs
parents:
diff changeset
   155
        res = element_klass_filter (factory,encoder_klass_str, pData);
hgs
parents:
diff changeset
   156
    if (!res && (pData->type & GST_FACTORY_LIST_MUXER))
hgs
parents:
diff changeset
   157
        res = element_klass_filter (factory,muxer_klass_str, pData);
hgs
parents:
diff changeset
   158
hgs
parents:
diff changeset
   159
    return res;
hgs
parents:
diff changeset
   160
}
hgs
parents:
diff changeset
   161
hgs
parents:
diff changeset
   162
/** The element filter used along with gst registry feature filter;
hgs
parents:
diff changeset
   163
 * The filter criteria is indicated in \a pData. */ 
hgs
parents:
diff changeset
   164
static gboolean element_filter (GstPluginFeature * feature, FilterData * pData)
hgs
parents:
diff changeset
   165
{
hgs
parents:
diff changeset
   166
    gboolean res;
hgs
parents:
diff changeset
   167
hgs
parents:
diff changeset
   168
    /* we only care about element factories */
hgs
parents:
diff changeset
   169
    if (G_UNLIKELY (!GST_IS_ELEMENT_FACTORY (feature)))
hgs
parents:
diff changeset
   170
        return FALSE;
hgs
parents:
diff changeset
   171
hgs
parents:
diff changeset
   172
    res = gst_factory_list_is_type (GST_ELEMENT_FACTORY_CAST (feature), pData);
hgs
parents:
diff changeset
   173
hgs
parents:
diff changeset
   174
    return res;
hgs
parents:
diff changeset
   175
}
hgs
parents:
diff changeset
   176
hgs
parents:
diff changeset
   177
/* function used to sort element features, by comparing the ranks.
hgs
parents:
diff changeset
   178
 * If ranks are same, then the plugin name is used. */
hgs
parents:
diff changeset
   179
static gint compare_ranks(GstPluginFeature * f1, GstPluginFeature * f2)
hgs
parents:
diff changeset
   180
{
hgs
parents:
diff changeset
   181
  gint diff;
hgs
parents:
diff changeset
   182
  const gchar *rname1, *rname2;
hgs
parents:
diff changeset
   183
hgs
parents:
diff changeset
   184
  diff = gst_plugin_feature_get_rank (f2) - gst_plugin_feature_get_rank (f1);
hgs
parents:
diff changeset
   185
  if (diff != 0)
hgs
parents:
diff changeset
   186
    return diff;
hgs
parents:
diff changeset
   187
hgs
parents:
diff changeset
   188
  rname1 = gst_plugin_feature_get_name (f1);
hgs
parents:
diff changeset
   189
  rname2 = gst_plugin_feature_get_name (f2);
hgs
parents:
diff changeset
   190
hgs
parents:
diff changeset
   191
  diff = strcmp (rname2, rname1);
hgs
parents:
diff changeset
   192
hgs
parents:
diff changeset
   193
  return diff;
hgs
parents:
diff changeset
   194
}
hgs
parents:
diff changeset
   195
hgs
parents:
diff changeset
   196
/** Returns a GList of factory elements, of a given \a type and which accpets \a sinkCaps and
hgs
parents:
diff changeset
   197
 * and provides \a srcCaps.
hgs
parents:
diff changeset
   198
 * */
hgs
parents:
diff changeset
   199
GList* gst_factory_list_get_elements (GstFactoryListType type, GstCaps* sinkCaps, GstCaps* srcCaps)
hgs
parents:
diff changeset
   200
{
hgs
parents:
diff changeset
   201
    FilterData* pData = NULL;
hgs
parents:
diff changeset
   202
    GList *list = NULL;
hgs
parents:
diff changeset
   203
hgs
parents:
diff changeset
   204
    // construct the data
hgs
parents:
diff changeset
   205
    pData = (FilterData*) calloc(sizeof(FilterData), 1);
hgs
parents:
diff changeset
   206
    pData->sinkCaps = sinkCaps;
hgs
parents:
diff changeset
   207
    pData->srcCaps = srcCaps;
hgs
parents:
diff changeset
   208
    pData->type = type;
hgs
parents:
diff changeset
   209
hgs
parents:
diff changeset
   210
    /* get the feature list using the filter */
hgs
parents:
diff changeset
   211
    list = gst_default_registry_feature_filter ((GstPluginFeatureFilter)
hgs
parents:
diff changeset
   212
            element_filter, FALSE, pData);
hgs
parents:
diff changeset
   213
hgs
parents:
diff changeset
   214
    free( pData );
hgs
parents:
diff changeset
   215
    
hgs
parents:
diff changeset
   216
    // sort depending on the ranks
hgs
parents:
diff changeset
   217
    if ( list )
hgs
parents:
diff changeset
   218
        list = g_list_sort( list, (GCompareFunc) compare_ranks );
hgs
parents:
diff changeset
   219
hgs
parents:
diff changeset
   220
    GST_INFO("sort list done");
hgs
parents:
diff changeset
   221
hgs
parents:
diff changeset
   222
    return list;
hgs
parents:
diff changeset
   223
hgs
parents:
diff changeset
   224
}
hgs
parents:
diff changeset
   225
/** Gets the pad depending on th pad template. */
hgs
parents:
diff changeset
   226
static GstPad * gst_element_get_pad_from_template (GstElement * element, GstPadTemplate * templ)
hgs
parents:
diff changeset
   227
{
hgs
parents:
diff changeset
   228
    GstPad *ret = NULL;
hgs
parents:
diff changeset
   229
    GstPadPresence presence;
hgs
parents:
diff changeset
   230
hgs
parents:
diff changeset
   231
    /* If this function is ever exported, we need check the validity of `element'
hgs
parents:
diff changeset
   232
     * and `templ', and to make sure the template actually belongs to the
hgs
parents:
diff changeset
   233
     * element. */
hgs
parents:
diff changeset
   234
hgs
parents:
diff changeset
   235
    presence = GST_PAD_TEMPLATE_PRESENCE (templ);
hgs
parents:
diff changeset
   236
hgs
parents:
diff changeset
   237
    switch (presence) {
hgs
parents:
diff changeset
   238
        case GST_PAD_ALWAYS:
hgs
parents:
diff changeset
   239
        case GST_PAD_SOMETIMES:
hgs
parents:
diff changeset
   240
            GST_INFO("presence : always/sometimes");
hgs
parents:
diff changeset
   241
            ret = gst_element_get_static_pad (element, templ->name_template);
hgs
parents:
diff changeset
   242
            if (!ret && presence == GST_PAD_ALWAYS)
hgs
parents:
diff changeset
   243
                g_warning
hgs
parents:
diff changeset
   244
                    ("Element %s has an ALWAYS template %s, but no pad of the same name",
hgs
parents:
diff changeset
   245
                     GST_OBJECT_NAME (element), templ->name_template);
hgs
parents:
diff changeset
   246
            break;
hgs
parents:
diff changeset
   247
hgs
parents:
diff changeset
   248
        case GST_PAD_REQUEST:
hgs
parents:
diff changeset
   249
            GST_INFO("presence : request audio_1");
hgs
parents:
diff changeset
   250
            //ret = gst_element_request_pad (element, templ, NULL);
hgs
parents:
diff changeset
   251
            ret = gst_element_get_request_pad( element, "audio_%d");
hgs
parents:
diff changeset
   252
            break;
hgs
parents:
diff changeset
   253
    }
hgs
parents:
diff changeset
   254
hgs
parents:
diff changeset
   255
    return ret;
hgs
parents:
diff changeset
   256
}
hgs
parents:
diff changeset
   257
hgs
parents:
diff changeset
   258
/* Finds compatible muxer sink pad, for a given \a encoder \ref GstElement */
hgs
parents:
diff changeset
   259
static inline GstPad * get_compatible_muxer_sink_pad (GstElement * muxer, GstElement * encoder) //pass in the right arguments here
hgs
parents:
diff changeset
   260
{
hgs
parents:
diff changeset
   261
    GstPad *srcpad = 0, *sinkpad = 0;
hgs
parents:
diff changeset
   262
    GstPadTemplate *srctempl = 0;
hgs
parents:
diff changeset
   263
    GstPadTemplate *sinktempl = 0;
hgs
parents:
diff changeset
   264
hgs
parents:
diff changeset
   265
    srcpad = gst_element_get_static_pad (encoder, "src");
hgs
parents:
diff changeset
   266
hgs
parents:
diff changeset
   267
    srctempl = gst_pad_get_pad_template (srcpad);
hgs
parents:
diff changeset
   268
hgs
parents:
diff changeset
   269
    GST_DEBUG (
hgs
parents:
diff changeset
   270
            "Attempting to find pad from muxer %s compatible with %s:%s",
hgs
parents:
diff changeset
   271
            GST_ELEMENT_NAME (muxer), GST_DEBUG_PAD_NAME (srcpad));
hgs
parents:
diff changeset
   272
    
hgs
parents:
diff changeset
   273
    gst_object_unref( srcpad );
hgs
parents:
diff changeset
   274
hgs
parents:
diff changeset
   275
    sinktempl = gst_element_get_compatible_pad_template (muxer, srctempl);
hgs
parents:
diff changeset
   276
    if (G_UNLIKELY (sinktempl == NULL))
hgs
parents:
diff changeset
   277
        goto no_template;
hgs
parents:
diff changeset
   278
hgs
parents:
diff changeset
   279
    sinkpad = gst_element_get_pad_from_template (muxer, sinktempl);
hgs
parents:
diff changeset
   280
    
hgs
parents:
diff changeset
   281
    return sinkpad;
hgs
parents:
diff changeset
   282
hgs
parents:
diff changeset
   283
no_template:
hgs
parents:
diff changeset
   284
    {
hgs
parents:
diff changeset
   285
        GST_ERROR ("No compatible pad available on muxer");
hgs
parents:
diff changeset
   286
        return NULL;
hgs
parents:
diff changeset
   287
    }
hgs
parents:
diff changeset
   288
}
hgs
parents:
diff changeset
   289
hgs
parents:
diff changeset
   290
hgs
parents:
diff changeset
   291
/**
hgs
parents:
diff changeset
   292
 * Creates the encoder bin.
hgs
parents:
diff changeset
   293
 * If the function is successful, A encoder bin with a ghost sink pad 
hgs
parents:
diff changeset
   294
 * which accepts the \a encCaps and a ghost source pad which gives
hgs
parents:
diff changeset
   295
 * \a muxCaps type is available.
hgs
parents:
diff changeset
   296
 * 
hgs
parents:
diff changeset
   297
 * Algo:
hgs
parents:
diff changeset
   298
 * 
hgs
parents:
diff changeset
   299
 * 1. Check if any pads of src give out encCaps
hgs
parents:
diff changeset
   300
 * 1.1 If yes, 
hgs
parents:
diff changeset
   301
 *      -> Create a list of muxers available in the gst plugin repository and select the appropriate muxer
hgs
parents:
diff changeset
   302
 *      -> connect src -> muxer, create encbin.
hgs
parents:
diff changeset
   303
 * 1.2 If no,
hgs
parents:
diff changeset
   304
 *      -> Create a list of encoders availabe in the gst plugin repo and  select a appropriate enc
hgs
parents:
diff changeset
   305
 *      -> connect src -> capsfilter (optional) -> enc -> muxer and return encbin
hgs
parents:
diff changeset
   306
 *      
hgs
parents:
diff changeset
   307
 * 
hgs
parents:
diff changeset
   308
 * \param [in] src The source gst element
hgs
parents:
diff changeset
   309
 * \param [in] encCaps The capability of the encoder being created.
hgs
parents:
diff changeset
   310
 * \param [in] muxCaps The capability type of the muxer to create.
hgs
parents:
diff changeset
   311
 * 
hgs
parents:
diff changeset
   312
 * \return On successful the ptr to encoder bin gst element is returned, else NULL.
hgs
parents:
diff changeset
   313
 */
hgs
parents:
diff changeset
   314
EXPORT_C GstElement* CreateAudioRecordBin( GstElement* src, GstCaps* encCaps, GstCaps* muxCaps)
hgs
parents:
diff changeset
   315
{
hgs
parents:
diff changeset
   316
    GstElement *encbin = NULL; // The top level encoder bin
hgs
parents:
diff changeset
   317
    GstPad *ghostsrc = NULL, *ghostsink = NULL; // Ghost src, sink pads of the enc bin
hgs
parents:
diff changeset
   318
    GstElement *muxer = NULL; // The muxer
hgs
parents:
diff changeset
   319
    GstElement *encoder = NULL; // The encoder
hgs
parents:
diff changeset
   320
#ifdef ENABLE_CAPS_FILTER
hgs
parents:
diff changeset
   321
    GstElement * audiofilter = NULL; // Audio filter
hgs
parents:
diff changeset
   322
#endif // ENABLE_CAPS_FILTER
hgs
parents:
diff changeset
   323
    GstPad* src_pad = 0;
hgs
parents:
diff changeset
   324
    gboolean accept_src_pad = 0;
hgs
parents:
diff changeset
   325
    GstCaps* src_caps = 0;
hgs
parents:
diff changeset
   326
    
hgs
parents:
diff changeset
   327
    if ( !src || !encCaps || !muxCaps )
hgs
parents:
diff changeset
   328
    {
hgs
parents:
diff changeset
   329
    		GST_ERROR("invalid args");
hgs
parents:
diff changeset
   330
    		return NULL;
hgs
parents:
diff changeset
   331
    }    
hgs
parents:
diff changeset
   332
hgs
parents:
diff changeset
   333
    /* gst initialization */
hgs
parents:
diff changeset
   334
    if ( FALSE == gst_init_check(NULL, NULL,NULL) )
hgs
parents:
diff changeset
   335
    {
hgs
parents:
diff changeset
   336
        GST_ERROR("gst_init_check FAIL");
hgs
parents:
diff changeset
   337
        return NULL;
hgs
parents:
diff changeset
   338
    }
hgs
parents:
diff changeset
   339
hgs
parents:
diff changeset
   340
    /* Initialize the debug category */
hgs
parents:
diff changeset
   341
    GST_DEBUG_CATEGORY_INIT (aud_recbin_cat, "AudioRecordBin",
hgs
parents:
diff changeset
   342
            0, "Audio record bin plugin");
hgs
parents:
diff changeset
   343
hgs
parents:
diff changeset
   344
hgs
parents:
diff changeset
   345
    /* 1. Create the bin */
hgs
parents:
diff changeset
   346
    encbin = gst_bin_new("encbin");
hgs
parents:
diff changeset
   347
    if ( !encbin )
hgs
parents:
diff changeset
   348
    {
hgs
parents:
diff changeset
   349
        GST_ERROR("encbin creation FAIL");
hgs
parents:
diff changeset
   350
        return NULL;
hgs
parents:
diff changeset
   351
    }
hgs
parents:
diff changeset
   352
    MONITOR_REF(encbin);
hgs
parents:
diff changeset
   353
hgs
parents:
diff changeset
   354
    /* 2. Get the src pad, of the source element */
hgs
parents:
diff changeset
   355
    src_pad = gst_element_get_pad (src, "src");
hgs
parents:
diff changeset
   356
hgs
parents:
diff changeset
   357
    src_caps = gst_pad_get_caps( src_pad );
hgs
parents:
diff changeset
   358
hgs
parents:
diff changeset
   359
    /* 2.1 Check if the src gst element can directly give the encCaps */
hgs
parents:
diff changeset
   360
    accept_src_pad = gst_caps_is_subset( encCaps ,src_caps);   
hgs
parents:
diff changeset
   361
hgs
parents:
diff changeset
   362
    GST_INFO(" accept caps %d ", accept_src_pad );
hgs
parents:
diff changeset
   363
    gst_object_unref (src_pad);
hgs
parents:
diff changeset
   364
    gst_caps_unref( src_caps );
hgs
parents:
diff changeset
   365
hgs
parents:
diff changeset
   366
    if ( !accept_src_pad )
hgs
parents:
diff changeset
   367
    {
hgs
parents:
diff changeset
   368
        GstCaps* enc_in_caps = 0;
hgs
parents:
diff changeset
   369
hgs
parents:
diff changeset
   370
        /* The src pad does not directly give the encoded format,
hgs
parents:
diff changeset
   371
         * fallback to x-raw-int / x-raw-float and construct the pipeline
hgs
parents:
diff changeset
   372
         * */
hgs
parents:
diff changeset
   373
        enc_in_caps = sCreateCaps("audio/x-raw-int");
hgs
parents:
diff changeset
   374
hgs
parents:
diff changeset
   375
        encoder = sCreateCompatibleFilter( GST_FACTORY_LIST_ENCODER, "encoder", enc_in_caps, encCaps);
hgs
parents:
diff changeset
   376
        if (!encoder )
hgs
parents:
diff changeset
   377
        {
hgs
parents:
diff changeset
   378
            GST_ERROR("encoder creation FAIL");
hgs
parents:
diff changeset
   379
            gst_caps_unref( enc_in_caps );
hgs
parents:
diff changeset
   380
            goto CLEANUP;
hgs
parents:
diff changeset
   381
        }
hgs
parents:
diff changeset
   382
        
hgs
parents:
diff changeset
   383
#ifdef ENABLE_CAPS_FILTER
hgs
parents:
diff changeset
   384
        audiofilter = sCreateCapsFilter(enc_in_caps);
hgs
parents:
diff changeset
   385
#endif // ENABLE_CAPS_FILTER
hgs
parents:
diff changeset
   386
        
hgs
parents:
diff changeset
   387
        gst_caps_unref( enc_in_caps );
hgs
parents:
diff changeset
   388
hgs
parents:
diff changeset
   389
        // add elements to the enc bin
hgs
parents:
diff changeset
   390
        if (gst_bin_add(GST_BIN(encbin), encoder))
hgs
parents:
diff changeset
   391
        {
hgs
parents:
diff changeset
   392
            GST_INFO("Added encoder to bin");
hgs
parents:
diff changeset
   393
        }
hgs
parents:
diff changeset
   394
        else
hgs
parents:
diff changeset
   395
        {
hgs
parents:
diff changeset
   396
            GST_ERROR("Could not add encoder to bin");
hgs
parents:
diff changeset
   397
            goto CLEANUP;
hgs
parents:
diff changeset
   398
        }
hgs
parents:
diff changeset
   399
hgs
parents:
diff changeset
   400
    }
hgs
parents:
diff changeset
   401
hgs
parents:
diff changeset
   402
    /* construct the muxer which can accept the encCaps and give out muxCaps */
hgs
parents:
diff changeset
   403
#ifdef ENABLE_CAPS_FILTER
hgs
parents:
diff changeset
   404
    /* Add a caps filter, if not created above */
hgs
parents:
diff changeset
   405
    if ( !audiofilter )
hgs
parents:
diff changeset
   406
        audiofilter = sCreateCapsFilter(encCaps);
hgs
parents:
diff changeset
   407
hgs
parents:
diff changeset
   408
    if ( !audiofilter)
hgs
parents:
diff changeset
   409
    {
hgs
parents:
diff changeset
   410
        GST_ERROR("audio filter creation FAIL ");
hgs
parents:
diff changeset
   411
        goto CLEANUP;
hgs
parents:
diff changeset
   412
    }
hgs
parents:
diff changeset
   413
    MONITOR_REF(audiofilter);
hgs
parents:
diff changeset
   414
    
hgs
parents:
diff changeset
   415
    // add elements to the enc bin
hgs
parents:
diff changeset
   416
    if (gst_bin_add(GST_BIN(encbin), audiofilter))
hgs
parents:
diff changeset
   417
    {
hgs
parents:
diff changeset
   418
        GST_INFO("Added audio filter to bin");
hgs
parents:
diff changeset
   419
    }
hgs
parents:
diff changeset
   420
    else
hgs
parents:
diff changeset
   421
    {
hgs
parents:
diff changeset
   422
        GST_ERROR("Could not add audio filter to bin");
hgs
parents:
diff changeset
   423
        goto CLEANUP;
hgs
parents:
diff changeset
   424
    }
hgs
parents:
diff changeset
   425
#endif // ENABLE_CAPS_FILTER
hgs
parents:
diff changeset
   426
hgs
parents:
diff changeset
   427
hgs
parents:
diff changeset
   428
    // Create the muxer 
hgs
parents:
diff changeset
   429
    muxer = sCreateCompatibleFilter( GST_FACTORY_LIST_MUXER, "muxer", encCaps, muxCaps );
hgs
parents:
diff changeset
   430
hgs
parents:
diff changeset
   431
    if ( !muxer )
hgs
parents:
diff changeset
   432
    {
hgs
parents:
diff changeset
   433
        GST_ERROR("no suitable muxer found");
hgs
parents:
diff changeset
   434
        goto CLEANUP;
hgs
parents:
diff changeset
   435
    }
hgs
parents:
diff changeset
   436
hgs
parents:
diff changeset
   437
    MONITOR_REF(muxer);
hgs
parents:
diff changeset
   438
hgs
parents:
diff changeset
   439
    if (gst_bin_add(GST_BIN(encbin), muxer))
hgs
parents:
diff changeset
   440
    {
hgs
parents:
diff changeset
   441
        GST_INFO("Added muxer to bin");
hgs
parents:
diff changeset
   442
    }
hgs
parents:
diff changeset
   443
    else
hgs
parents:
diff changeset
   444
    {
hgs
parents:
diff changeset
   445
        GST_ERROR("Could not add muxer to bin");
hgs
parents:
diff changeset
   446
        goto CLEANUP;
hgs
parents:
diff changeset
   447
    }
hgs
parents:
diff changeset
   448
hgs
parents:
diff changeset
   449
    // link the added elements.
hgs
parents:
diff changeset
   450
    // If encoder is present, then the bin will have,
hgs
parents:
diff changeset
   451
    // capsfilter -> encoder -> muxer
hgs
parents:
diff changeset
   452
    // or else
hgs
parents:
diff changeset
   453
    // capsfilter -> muxer.
hgs
parents:
diff changeset
   454
    // Note that caps filter is optionally controlled by macro ENABLE_CAPS_FILTER
hgs
parents:
diff changeset
   455
    if ( encoder )
hgs
parents:
diff changeset
   456
    {
hgs
parents:
diff changeset
   457
        GstPad* srcpad      = 0;
hgs
parents:
diff changeset
   458
        GstPad* muxerpad    = 0;
hgs
parents:
diff changeset
   459
#ifdef ENABLE_CAPS_FILTER
hgs
parents:
diff changeset
   460
        GST_INFO("audiofilter -> encoder");
hgs
parents:
diff changeset
   461
        if(!gst_element_link(audiofilter, encoder))
hgs
parents:
diff changeset
   462
        {
hgs
parents:
diff changeset
   463
            GST_ERROR("Could not link audiofilter -> encoder!!");
hgs
parents:
diff changeset
   464
            goto CLEANUP;
hgs
parents:
diff changeset
   465
        }
hgs
parents:
diff changeset
   466
#endif //ENABLE_CAPS_FILTER
hgs
parents:
diff changeset
   467
        
hgs
parents:
diff changeset
   468
        // get the src pad
hgs
parents:
diff changeset
   469
        srcpad = gst_element_get_static_pad (encoder, "src");
hgs
parents:
diff changeset
   470
        
hgs
parents:
diff changeset
   471
        // get the sink pad of muxer
hgs
parents:
diff changeset
   472
        GST_INFO("get compatible mux sink pad ... ");
hgs
parents:
diff changeset
   473
        muxerpad = get_compatible_muxer_sink_pad (muxer, encoder);
hgs
parents:
diff changeset
   474
hgs
parents:
diff changeset
   475
        // link 
hgs
parents:
diff changeset
   476
        if (G_UNLIKELY (gst_pad_link (srcpad, muxerpad) != GST_PAD_LINK_OK))
hgs
parents:
diff changeset
   477
        {
hgs
parents:
diff changeset
   478
            GST_ERROR("gst_pad_link fail");
hgs
parents:
diff changeset
   479
            goto CLEANUP;
hgs
parents:
diff changeset
   480
        }
hgs
parents:
diff changeset
   481
        gst_object_unref( srcpad );
hgs
parents:
diff changeset
   482
        gst_object_unref( muxerpad );
hgs
parents:
diff changeset
   483
        GST_INFO("gst_pad_link successful");
hgs
parents:
diff changeset
   484
hgs
parents:
diff changeset
   485
    }
hgs
parents:
diff changeset
   486
#ifdef ENABLE_CAPS_FILTER
hgs
parents:
diff changeset
   487
    else 
hgs
parents:
diff changeset
   488
    {
hgs
parents:
diff changeset
   489
        GST_INFO("audiofilter -> muxer ");
hgs
parents:
diff changeset
   490
        if(!gst_element_link(audiofilter, muxer))
hgs
parents:
diff changeset
   491
        {
hgs
parents:
diff changeset
   492
            GST_ERROR("Could not link audiofilter to muxer!!");
hgs
parents:
diff changeset
   493
            goto CLEANUP;
hgs
parents:
diff changeset
   494
        }
hgs
parents:
diff changeset
   495
    }
hgs
parents:
diff changeset
   496
#endif //ENABLE_CAPS_FILTER
hgs
parents:
diff changeset
   497
    GST_INFO("linking complete");
hgs
parents:
diff changeset
   498
hgs
parents:
diff changeset
   499
    // create the ghost pads
hgs
parents:
diff changeset
   500
    // The ghost src pad is provided by the muxer
hgs
parents:
diff changeset
   501
    ghostsrc = gst_element_get_static_pad(muxer, "src");
hgs
parents:
diff changeset
   502
    // The ghost sink pad is determined by the availability
hgs
parents:
diff changeset
   503
    // of audiofilter, encoder.
hgs
parents:
diff changeset
   504
#ifdef ENABLE_CAPS_FILTER
hgs
parents:
diff changeset
   505
    ghostsink = gst_element_get_static_pad(audiofilter, "sink");
hgs
parents:
diff changeset
   506
#else
hgs
parents:
diff changeset
   507
    if ( encoder )
hgs
parents:
diff changeset
   508
        ghostsink = gst_element_get_static_pad(encoder, "sink");
hgs
parents:
diff changeset
   509
    else
hgs
parents:
diff changeset
   510
        ghostsink = gst_element_get_static_pad(muxer, "sink");
hgs
parents:
diff changeset
   511
#endif //ENABLE_CAPS_FILTER
hgs
parents:
diff changeset
   512
hgs
parents:
diff changeset
   513
    MONITOR_REF( ghostsrc );
hgs
parents:
diff changeset
   514
    MONITOR_REF( ghostsink );
hgs
parents:
diff changeset
   515
hgs
parents:
diff changeset
   516
    if(ghostsrc)
hgs
parents:
diff changeset
   517
    {
hgs
parents:
diff changeset
   518
        gst_element_add_pad(encbin, gst_ghost_pad_new("src",ghostsrc));
hgs
parents:
diff changeset
   519
        gst_object_unref(GST_OBJECT(ghostsrc));
hgs
parents:
diff changeset
   520
        GST_INFO("+ghost src");
hgs
parents:
diff changeset
   521
    }
hgs
parents:
diff changeset
   522
    if(ghostsink)
hgs
parents:
diff changeset
   523
    {
hgs
parents:
diff changeset
   524
        gst_element_add_pad(encbin, gst_ghost_pad_new("sink",ghostsink));
hgs
parents:
diff changeset
   525
        gst_object_unref(GST_OBJECT(ghostsink));
hgs
parents:
diff changeset
   526
        GST_INFO("+ghost sink");
hgs
parents:
diff changeset
   527
    }
hgs
parents:
diff changeset
   528
    return encbin;
hgs
parents:
diff changeset
   529
CLEANUP:
hgs
parents:
diff changeset
   530
    // release only if the gst element has not been added to the bin;
hgs
parents:
diff changeset
   531
    // when added to a bin, the bin ( i.e the parent ) takes care of
hgs
parents:
diff changeset
   532
    // releasing.
hgs
parents:
diff changeset
   533
    if ( encoder && !gst_element_get_parent(encoder) )
hgs
parents:
diff changeset
   534
        gst_object_unref( encoder );
hgs
parents:
diff changeset
   535
    if ( muxer && !gst_element_get_parent(muxer))
hgs
parents:
diff changeset
   536
        gst_object_unref( muxer );
hgs
parents:
diff changeset
   537
    #ifdef ENABLE_CAPS_FILTER
hgs
parents:
diff changeset
   538
    if ( audiofilter && !gst_element_get_parent(audiofilter))
hgs
parents:
diff changeset
   539
        gst_object_unref( audiofilter );
hgs
parents:
diff changeset
   540
    #endif //ENABLE_CAPS_FILTER
hgs
parents:
diff changeset
   541
    if ( encbin )
hgs
parents:
diff changeset
   542
        gst_object_unref( encbin );
hgs
parents:
diff changeset
   543
    return NULL;
hgs
parents:
diff changeset
   544
}
20
hgs
parents: 18
diff changeset
   545
#ifdef ENABLE_CAPS_FILTER
18
hgs
parents:
diff changeset
   546
/** Create the caps filter */
hgs
parents:
diff changeset
   547
GstElement* sCreateCapsFilter( GstCaps* encCaps)
hgs
parents:
diff changeset
   548
{
hgs
parents:
diff changeset
   549
    GstElement* audiofilter = NULL;
hgs
parents:
diff changeset
   550
hgs
parents:
diff changeset
   551
    audiofilter = gst_element_factory_make("capsfilter", "audiofilter");
hgs
parents:
diff changeset
   552
    if( !audiofilter )
hgs
parents:
diff changeset
   553
    {
hgs
parents:
diff changeset
   554
        return NULL;
hgs
parents:
diff changeset
   555
    }
hgs
parents:
diff changeset
   556
hgs
parents:
diff changeset
   557
    g_object_set( G_OBJECT(audiofilter), "caps",encCaps,NULL);
hgs
parents:
diff changeset
   558
hgs
parents:
diff changeset
   559
    return audiofilter;
hgs
parents:
diff changeset
   560
}
20
hgs
parents: 18
diff changeset
   561
#endif
18
hgs
parents:
diff changeset
   562
/** Create a filter, which accepts \a encCaps on sink pad and 
hgs
parents:
diff changeset
   563
 * provides \a muxCaps on the src pad */
hgs
parents:
diff changeset
   564
GstElement* sCreateCompatibleFilter(GstFactoryListType type,
hgs
parents:
diff changeset
   565
        const gchar* name, GstCaps* sinkcaps, GstCaps* srccaps)
hgs
parents:
diff changeset
   566
{
hgs
parents:
diff changeset
   567
hgs
parents:
diff changeset
   568
    GList* factory_lst = NULL;
hgs
parents:
diff changeset
   569
    GstElementFactory * factory = NULL;
hgs
parents:
diff changeset
   570
    GstElement* element = NULL;
hgs
parents:
diff changeset
   571
    guint nFactory = 0;
hgs
parents:
diff changeset
   572
    
hgs
parents:
diff changeset
   573
    GST_DEBUG("before gst_factory_list_get_elements");
hgs
parents:
diff changeset
   574
hgs
parents:
diff changeset
   575
    factory_lst = gst_factory_list_get_elements(type, sinkcaps, srccaps);
hgs
parents:
diff changeset
   576
    
hgs
parents:
diff changeset
   577
    GST_DEBUG("gst_factory_list_get_elements");
hgs
parents:
diff changeset
   578
    
hgs
parents:
diff changeset
   579
    nFactory = g_list_length ( factory_lst );   
hgs
parents:
diff changeset
   580
    
hgs
parents:
diff changeset
   581
    if ( !nFactory )
hgs
parents:
diff changeset
   582
    {
hgs
parents:
diff changeset
   583
        GST_ERROR("no matching %s found", name );
hgs
parents:
diff changeset
   584
        return NULL;
hgs
parents:
diff changeset
   585
    }
hgs
parents:
diff changeset
   586
    GST_INFO("nElement %d", nFactory);
hgs
parents:
diff changeset
   587
hgs
parents:
diff changeset
   588
    // The first element factory in the sorted list is chosen
hgs
parents:
diff changeset
   589
    factory = (GstElementFactory*) g_list_nth_data (factory_lst, 0);
hgs
parents:
diff changeset
   590
    if ( factory )
hgs
parents:
diff changeset
   591
    {
hgs
parents:
diff changeset
   592
        GST_INFO("%s selected = %s can sink %d src %d ", 
hgs
parents:
diff changeset
   593
                name,
hgs
parents:
diff changeset
   594
                GST_PLUGIN_FEATURE_NAME(factory),
hgs
parents:
diff changeset
   595
                gst_element_factory_can_sink_caps(factory,sinkcaps),
hgs
parents:
diff changeset
   596
                gst_element_factory_can_src_caps(factory,srccaps)
hgs
parents:
diff changeset
   597
                );
hgs
parents:
diff changeset
   598
hgs
parents:
diff changeset
   599
        element =  gst_element_factory_create(factory, name);
hgs
parents:
diff changeset
   600
        if (!element)
hgs
parents:
diff changeset
   601
        {
hgs
parents:
diff changeset
   602
            g_print("could not create element!");
hgs
parents:
diff changeset
   603
        }
hgs
parents:
diff changeset
   604
    }
hgs
parents:
diff changeset
   605
hgs
parents:
diff changeset
   606
    // free the muxers list
hgs
parents:
diff changeset
   607
    gst_plugin_feature_list_free( factory_lst );
hgs
parents:
diff changeset
   608
hgs
parents:
diff changeset
   609
    return element;
hgs
parents:
diff changeset
   610
}
hgs
parents:
diff changeset
   611
hgs
parents:
diff changeset
   612
hgs
parents:
diff changeset
   613
/** Utility function to create the caps depending on the mimetype, fills in the default
hgs
parents:
diff changeset
   614
 * values
hgs
parents:
diff changeset
   615
 * */
hgs
parents:
diff changeset
   616
static GstCaps* sCreateCaps( const char* mimetype )
hgs
parents:
diff changeset
   617
{
hgs
parents:
diff changeset
   618
    GstCaps* caps = NULL;
hgs
parents:
diff changeset
   619
    GST_INFO( "inside sCreateCaps");
hgs
parents:
diff changeset
   620
    if ( !strcmp(mimetype, "audio/x-raw-int") ||
hgs
parents:
diff changeset
   621
            !strcmp(mimetype, "audio/x-raw-float") )
hgs
parents:
diff changeset
   622
    {
hgs
parents:
diff changeset
   623
        caps = gst_caps_new_simple(mimetype,
hgs
parents:
diff changeset
   624
                "width", G_TYPE_INT, 16,
hgs
parents:
diff changeset
   625
                "depth", G_TYPE_INT, 16,
hgs
parents:
diff changeset
   626
                "signed",G_TYPE_BOOLEAN, TRUE,
hgs
parents:
diff changeset
   627
                "endianness",G_TYPE_INT, G_BYTE_ORDER,
hgs
parents:
diff changeset
   628
                "rate", G_TYPE_INT, 16000,
hgs
parents:
diff changeset
   629
                "channels", G_TYPE_INT, 1, 
hgs
parents:
diff changeset
   630
                NULL);
hgs
parents:
diff changeset
   631
    }
hgs
parents:
diff changeset
   632
    else
hgs
parents:
diff changeset
   633
    {
hgs
parents:
diff changeset
   634
        // fallback to default 
hgs
parents:
diff changeset
   635
        GST_INFO("fallback");
hgs
parents:
diff changeset
   636
        caps = gst_caps_new_simple(mimetype, NULL);
hgs
parents:
diff changeset
   637
        
hgs
parents:
diff changeset
   638
    }
hgs
parents:
diff changeset
   639
    return caps;
hgs
parents:
diff changeset
   640
} 
hgs
parents:
diff changeset
   641
hgs
parents:
diff changeset
   642
#ifdef WEAK_REF
hgs
parents:
diff changeset
   643
void sWeakNotify (gpointer  data, GObject  *where_the_object_was)
hgs
parents:
diff changeset
   644
{
hgs
parents:
diff changeset
   645
    GST_DEBUG("__release__ %s", (const char*) data );
hgs
parents:
diff changeset
   646
}
hgs
parents:
diff changeset
   647
#endif // WEAK_REF
hgs
parents:
diff changeset
   648
hgs
parents:
diff changeset
   649
hgs
parents:
diff changeset
   650
//  Exported Functions
hgs
parents:
diff changeset
   651
hgs
parents:
diff changeset
   652
#ifndef EKA2 // for EKA1 only
hgs
parents:
diff changeset
   653
EXPORT_C TInt E32Dll(TDllReason /*aReason*/)
hgs
parents:
diff changeset
   654
    // Called when the DLL is loaded and unloaded. Note: have to define
hgs
parents:
diff changeset
   655
    // epoccalldllentrypoints in MMP file to get this called in THUMB.
hgs
parents:
diff changeset
   656
{
hgs
parents:
diff changeset
   657
    return KErrNone;
hgs
parents:
diff changeset
   658
}
hgs
parents:
diff changeset
   659
#endif
hgs
parents:
diff changeset
   660
hgs
parents:
diff changeset
   661