gst_plugins_symbian/gst/amrmux/gstamrmux.c
branchRCL_3
changeset 30 7e817e7e631c
parent 29 567bb019e3e3
equal deleted inserted replaced
29:567bb019e3e3 30:7e817e7e631c
     1 /*
       
     2  *  Copyright © 2010 Nokia Corporation.
       
     3  *  This material, including documentation and any related
       
     4  *  computer progrs, is protected by copyright controlled by
       
     5  *  Nokia Corporation. All rights are reserved. Copying,
       
     6  *  including reproducing, storing, adapting or translating, any
       
     7  *  or all of this material requires the prior written consent of
       
     8  *  Nokia Corporation. This material also contains confidential
       
     9  *  information which may not be disclosed to others without the
       
    10  *  prior written consent of Nokia Corporation.
       
    11  * ============================================================================
       
    12  */
       
    13 
       
    14 
       
    15 #ifdef HAVE_CONFIG_H
       
    16 #include "config.h"
       
    17 #endif
       
    18 
       
    19 
       
    20 #include "gstamrmux.h"
       
    21 
       
    22 #include <stdlib.h>
       
    23 #include <string.h>
       
    24 
       
    25 
       
    26 #ifdef __SYMBIAN32__
       
    27 #include <gst/gstinfo.h>
       
    28 #endif
       
    29 
       
    30 /* AMR nb header value */
       
    31 const char* amrnbmagicnumber = "#!AMR\n";
       
    32 
       
    33 static void gst_amrmux_base_init (gpointer g_class);
       
    34 static void gst_amrmux_class_init (GstAmrMuxClass * klass);
       
    35 static void gst_amrmux_init ( GstAmrMux * filter, GstAmrMuxClass *filter_klass);
       
    36 
       
    37 static GstFlowReturn gst_amrmux_chain (GstPad * pad, GstBuffer * buf);
       
    38 
       
    39 static void gst_amrmux_get_property (GObject * object, guint prop_id,
       
    40     GValue * value, GParamSpec * pspec);
       
    41 
       
    42 static void gst_amrmux_set_property (GObject *object, guint prop_id,
       
    43                                      const GValue *value, GParamSpec *pspec);
       
    44                                      
       
    45 static GstStateChangeReturn gst_amrmux_change_state (GstElement * element,
       
    46     GstStateChange transition);
       
    47 
       
    48 static void gst_amrmux_dispose(GObject * object);
       
    49 
       
    50 static GstElementClass *parent_class= NULL;
       
    51 
       
    52 static const GstElementDetails gst_amrmux_details =
       
    53 GST_ELEMENT_DETAILS ("AMR MUX Details",
       
    54         "Codec/Muxer/Audio",
       
    55         "Adaptive Multi-Rate Narrow-Band Muxer",
       
    56         "");
       
    57 
       
    58 static GstStaticPadTemplate sink_factory =
       
    59 GST_STATIC_PAD_TEMPLATE (
       
    60   "sink",
       
    61   GST_PAD_SINK,
       
    62   GST_PAD_ALWAYS,
       
    63   GST_STATIC_CAPS ("audio/amr")
       
    64 );
       
    65 
       
    66 static GstStaticPadTemplate source_factory =
       
    67 GST_STATIC_PAD_TEMPLATE (
       
    68   "src",
       
    69   GST_PAD_SRC,
       
    70   GST_PAD_ALWAYS,
       
    71   GST_STATIC_CAPS ("audio/amr")
       
    72 );
       
    73 
       
    74 enum {
       
    75   ARG_0,
       
    76   ARG_HEADER
       
    77 };
       
    78 
       
    79 
       
    80 GType
       
    81 gst_amrmux_get_type (void)
       
    82 {
       
    83   static GType gst_amrmux_type = 0;
       
    84 
       
    85   if (!gst_amrmux_type) {
       
    86     static const GTypeInfo amrmux_info = {
       
    87       sizeof (GstAmrMuxClass),
       
    88       gst_amrmux_base_init,
       
    89       NULL,
       
    90       (GClassInitFunc) gst_amrmux_class_init,
       
    91       NULL,
       
    92       NULL,
       
    93       sizeof (GstAmrMux),
       
    94       0,
       
    95       (GInstanceInitFunc) gst_amrmux_init,
       
    96     };
       
    97 
       
    98     gst_amrmux_type =
       
    99         g_type_register_static (GST_TYPE_ELEMENT, "GstAmrMux",
       
   100         &amrmux_info, (GTypeFlags)0);
       
   101   }
       
   102   return gst_amrmux_type;
       
   103 }
       
   104 
       
   105 
       
   106 static void
       
   107 gst_amrmux_base_init (gpointer g_class)
       
   108 {
       
   109   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
       
   110    
       
   111   gst_element_class_add_pad_template(element_class,
       
   112     gst_static_pad_template_get(&sink_factory)); 
       
   113   
       
   114   gst_element_class_add_pad_template(element_class,
       
   115   gst_static_pad_template_get(&source_factory));
       
   116           
       
   117   gst_element_class_set_details (element_class, &gst_amrmux_details);
       
   118 }
       
   119 
       
   120 static void
       
   121 gst_amrmux_class_init ( GstAmrMuxClass * klass )
       
   122 {
       
   123   GObjectClass *object_class;
       
   124   GstElementClass *gstelement_class;
       
   125 
       
   126   gstelement_class = (GstElementClass *) klass;
       
   127   object_class = (GObjectClass *) klass;
       
   128 
       
   129   
       
   130   object_class->set_property = gst_amrmux_set_property;
       
   131   object_class->get_property = gst_amrmux_get_property;
       
   132   
       
   133   gstelement_class->change_state = gst_amrmux_change_state;
       
   134   
       
   135   object_class->dispose = gst_amrmux_dispose;
       
   136   
       
   137   parent_class = g_type_class_peek_parent(klass);
       
   138   
       
   139   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HEADER,
       
   140         g_param_spec_boolean ("header", "header",
       
   141             "For writing AMR header", TRUE, (GParamFlags)G_PARAM_READWRITE));
       
   142   
       
   143  
       
   144  }
       
   145 
       
   146 static void gst_amrmux_dispose(GObject * object)
       
   147 {
       
   148     G_OBJECT_CLASS (parent_class)->dispose (object);
       
   149 }
       
   150 
       
   151 static void
       
   152 gst_amrmux_init( GstAmrMux * amrmux, GstAmrMuxClass *amrmux_klass)
       
   153 {  
       
   154    GstElementClass *klass = GST_ELEMENT_CLASS (amrmux_klass);
       
   155    
       
   156    //By default we have to write header   
       
   157    amrmux->writeheader= TRUE;
       
   158    
       
   159    //Add Sink pad to this element
       
   160       
       
   161    amrmux->sinkpad = gst_pad_new_from_template (
       
   162     gst_element_class_get_pad_template (klass, "sink"), "sink");  
       
   163   
       
   164   gst_element_add_pad (GST_ELEMENT (amrmux), amrmux->sinkpad);
       
   165 
       
   166     
       
   167   //Add Src pad to this element
       
   168   amrmux->srcpad = gst_pad_new_from_template (
       
   169     gst_element_class_get_pad_template (klass, "src"), "src");
       
   170 
       
   171   gst_element_add_pad (GST_ELEMENT (amrmux), amrmux->srcpad);  
       
   172     
       
   173   gst_pad_set_chain_function (amrmux->sinkpad, gst_amrmux_chain);
       
   174 
       
   175 }
       
   176 
       
   177 
       
   178 static void
       
   179 gst_amrmux_get_property (GObject * object,
       
   180     guint prop_id, GValue * value, GParamSpec * pspec)
       
   181 {
       
   182     
       
   183   GstAmrMux *amrmux = GST_AMRMUX( object );
       
   184   
       
   185   switch (prop_id) {
       
   186       case ARG_HEADER:
       
   187             g_value_set_boolean (value, amrmux->writeheader);
       
   188             break;
       
   189           
       
   190           default:
       
   191             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       
   192             break;
       
   193   }
       
   194 }
       
   195 
       
   196 
       
   197 static void
       
   198 gst_amrmux_set_property (GObject * object,
       
   199     guint prop_id, const GValue * value, GParamSpec * pspec)
       
   200 {
       
   201 GstAmrMux *amrmux = GST_AMRMUX( object );
       
   202   
       
   203   switch (prop_id) {
       
   204       case ARG_HEADER:
       
   205           amrmux->writeheader = g_value_get_boolean (value);
       
   206           break;
       
   207         default:
       
   208           G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       
   209           break;
       
   210   }
       
   211 }
       
   212 
       
   213 
       
   214 
       
   215 static GstFlowReturn
       
   216 gst_amrmux_chain (GstPad * pad, GstBuffer * buf)
       
   217 {    
       
   218   
       
   219   gint8 *codecdata;
       
   220   guint8* amrdata;
       
   221   guint8* amrheaderstart; 
       
   222   
       
   223   int codecdatasize = GST_BUFFER_SIZE(buf); 
       
   224    
       
   225   int magicnumberlength = strlen( amrnbmagicnumber );   
       
   226   
       
   227   GstAmrMux *amrmux = GST_AMRMUX (GST_PAD_PARENT (pad)); 
       
   228 
       
   229   if ( amrmux->writeheader )
       
   230    {
       
   231      
       
   232       buf = gst_buffer_make_writable( buf );  
       
   233       
       
   234       //Allocate a buffer which will hold codec data + magic number
       
   235       
       
   236       amrdata = ( guint8* )g_malloc( GST_BUFFER_SIZE(buf) + magicnumberlength );
       
   237       
       
   238       //To save the starting address of amr data
       
   239       
       
   240       amrheaderstart = amrdata;
       
   241       
       
   242       //Copy magic number to newly allocated buffer
       
   243       
       
   244       memcpy( amrdata, amrnbmagicnumber, magicnumberlength);
       
   245       
       
   246       codecdata = (gint8*)GST_BUFFER_DATA (buf);  
       
   247       
       
   248       //Move the pointer to the end of magic number
       
   249            
       
   250       amrdata += magicnumberlength;
       
   251       
       
   252       //Copy codec data to newly allocated buffer
       
   253            
       
   254       memcpy( amrdata , codecdata, codecdatasize );
       
   255       
       
   256       // free codec data from GstBuffer
       
   257       
       
   258       g_free(  buf->malloc_data );
       
   259       
       
   260       //Copying the newly allocated buffer and size in GstBuffer
       
   261       
       
   262       buf->data = amrheaderstart;
       
   263       
       
   264       buf->malloc_data = amrheaderstart;
       
   265       
       
   266       buf->size+= magicnumberlength; 
       
   267       
       
   268       //Do it only first time
       
   269       
       
   270       amrmux->writeheader = FALSE;  
       
   271    }  
       
   272   
       
   273   return gst_pad_push( amrmux->srcpad , buf );
       
   274   
       
   275 }
       
   276 
       
   277 static GstStateChangeReturn
       
   278 gst_amrmux_change_state (GstElement * element, GstStateChange transition)
       
   279 {
       
   280   GstStateChangeReturn ret;
       
   281   GstAmrMux *amrmux = GST_AMRMUX (element);
       
   282   
       
   283   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
       
   284   
       
   285   if (G_UNLIKELY (ret == GST_STATE_CHANGE_FAILURE))
       
   286       return ret; 
       
   287 
       
   288   switch (transition) {
       
   289         case GST_STATE_CHANGE_READY_TO_NULL: 
       
   290          {
       
   291             amrmux->writeheader = TRUE; 
       
   292             break;
       
   293          }               
       
   294       
       
   295          default:
       
   296             break;
       
   297   }
       
   298   
       
   299   return ret;    
       
   300 }
       
   301 
       
   302 static gboolean
       
   303 plugin_init (GstPlugin * plugin)
       
   304 {
       
   305  
       
   306   return gst_element_register (plugin, "amrmux", GST_RANK_PRIMARY,
       
   307           GST_TYPE_AMRMUX);
       
   308 }
       
   309 
       
   310 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
       
   311     GST_VERSION_MINOR,
       
   312     "amrmux",
       
   313     "Add header to amr-nb encoded stream",
       
   314     plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
       
   315 
       
   316 
       
   317 EXPORT_C GstPluginDesc* _GST_PLUGIN_DESC()
       
   318 {
       
   319 	return &gst_plugin_desc;
       
   320 }
       
   321