gst_plugins_symbian/gst/devsound/gstdevsoundsink.c
changeset 7 71e347f905f2
parent 0 0e761a78d257
child 11 1373546e05c6
equal deleted inserted replaced
2:5505e8908944 7:71e347f905f2
    30 #include "gstg711decoderinterface.h"
    30 #include "gstg711decoderinterface.h"
    31 #include "gstg729decoderinterface.h"
    31 #include "gstg729decoderinterface.h"
    32 #include "gstilbcdecoderinterface.h"
    32 #include "gstilbcdecoderinterface.h"
    33 #include "string.h"
    33 #include "string.h"
    34 #include <glib_global.h>
    34 #include <glib_global.h>
       
    35 #ifdef AV_SYNC
       
    36 #include <gst/audio/gstaudioclock.h>
       
    37 #endif /*AV_SYNC*/
       
    38 
    35 
    39 
    36 GST_DEBUG_CATEGORY_EXTERN (devsound_debug);
    40 GST_DEBUG_CATEGORY_EXTERN (devsound_debug);
    37 #define GST_CAT_DEFAULT devsound_debug
    41 #define GST_CAT_DEFAULT devsound_debug
    38 
    42 
    39 /* elementfactory information */
    43 /* elementfactory information */
    57         const GValue * value, GParamSpec * pspec);
    61         const GValue * value, GParamSpec * pspec);
    58 
    62 
    59 static GstCaps *gst_devsound_sink_getcaps(GstBaseSink * bsink);
    63 static GstCaps *gst_devsound_sink_getcaps(GstBaseSink * bsink);
    60 static gboolean gst_devsound_sink_setcaps(GstBaseSink *bsink, GstCaps *caps);
    64 static gboolean gst_devsound_sink_setcaps(GstBaseSink *bsink, GstCaps *caps);
    61 
    65 
    62 
       
    63 static gboolean gst_devsound_sink_event(GstBaseSink * asink, GstEvent * event);
    66 static gboolean gst_devsound_sink_event(GstBaseSink * asink, GstEvent * event);
       
    67 #ifdef AV_SYNC
       
    68 static void gst_devsound_sink_get_times(GstBaseSink * bsink, GstBuffer * buffer,
       
    69     GstClockTime * start, GstClockTime * end);
       
    70 static GstClock *gst_devsound_sink_provide_clock (GstElement * element);
       
    71 static GstClockTime gst_devsound_sink_get_time (GstClock * clock,
       
    72     gpointer user_data);
       
    73 #endif /*AV_SYNC*/
       
    74 
       
    75 static GstStateChangeReturn gst_devsound_sink_change_state (GstElement * element,
       
    76     GstStateChange transition);
       
    77 
    64 
    78 
    65 static void *StartDevSoundThread(void *threadid);
    79 static void *StartDevSoundThread(void *threadid);
    66 
       
    67 
    80 
    68 //Error concealment interface impl
    81 //Error concealment interface impl
    69 static void gst_error_concealment_handler_init (gpointer g_iface,
    82 static void gst_error_concealment_handler_init (gpointer g_iface,
    70     gpointer iface_data);
    83     gpointer iface_data);
    71 static gint gst_ConcealErrorForNextBuffer();
    84 static gint gst_ConcealErrorForNextBuffer();
    95 static gint gst_GetIlbcCng(gboolean* aCng);
   108 static gint gst_GetIlbcCng(gboolean* aCng);
    96 static gint gst_SetIlbcCng(gboolean aCng);
   109 static gint gst_SetIlbcCng(gboolean aCng);
    97 static gint gst_SetIlbcDecoderMode(enum TIlbcDecodeMode aDecodeMode);
   110 static gint gst_SetIlbcDecoderMode(enum TIlbcDecodeMode aDecodeMode);
    98 static void  gst_Apply_Ilbc_Decoder_Update(GstDevsoundSink* dssink );
   111 static void  gst_Apply_Ilbc_Decoder_Update(GstDevsoundSink* dssink );
    99 
   112 
       
   113 static void get_PopulateIntfcProperties(GstDevsoundSink* dssink);
   100 
   114 
   101 static gboolean gst_sink_start (GstBaseSink * sink);
   115 static gboolean gst_sink_start (GstBaseSink * sink);
   102 static gboolean gst_sink_stop (GstBaseSink * sink);
   116 static gboolean gst_sink_stop (GstBaseSink * sink);
   103 static GstFlowReturn gst_sink_render (GstBaseSink * sink,
   117 static GstFlowReturn gst_sink_render (GstBaseSink * sink,
   104     GstBuffer * buffer);
   118     GstBuffer * buffer);
   158     PROP_0,
   172     PROP_0,
   159     PROP_DEVICE,
   173     PROP_DEVICE,
   160     VOLUME,
   174     VOLUME,
   161     MAXVOLUME,
   175     MAXVOLUME,
   162     VOLUMERAMP,
   176     VOLUMERAMP,
   163     CHANNELS,
   177 /*    CHANNELS,*/
   164     LEFTBALANCE,
   178     LEFTBALANCE,
   165     RIGHTBALANCE,
   179     RIGHTBALANCE,
   166     RATE,
   180 /*    RATE,*/
   167     PRIORITY,
   181     PRIORITY,
   168     PREFERENCE,
   182     PREFERENCE,
   169     SAMPLESPLAYED,
   183 /*    SAMPLESPLAYED,*/
   170     FOURCC, //FOURCC is not needed
   184 /*    FOURCC, //FOURCC is not needed*/
   171     MIMETYPE,
   185 /*    MIMETYPE,*/
   172     OUTPUTDEVICE
   186     OUTPUTDEVICE
   173     };
   187     };
   174 
   188 
   175 enum command_to_consumer_thread_enum
   189 enum command_to_consumer_thread_enum
   176     {
   190     {
   177     OPEN = 2,
   191     OPEN = 2,
   178     WRITEDATA,
   192     PLAYING,
       
   193     PAUSE,
       
   194     RESUME,
   179     /*UPDATE,*/
   195     /*UPDATE,*/
       
   196     WAIT,
   180     CLOSE
   197     CLOSE
   181     };
   198     };
   182 enum command_to_consumer_thread_enum cmd;
   199 enum command_to_consumer_thread_enum cmd;
   183 
   200 
   184 static GstStaticPadTemplate devsoundsink_sink_factory=
   201 static GstStaticPadTemplate devsoundsink_sink_factory=
   185     GST_STATIC_PAD_TEMPLATE ("sink",
   202     GST_STATIC_PAD_TEMPLATE ("sink",
   186         GST_PAD_SINK,
   203         GST_PAD_SINK,
   187         GST_PAD_ALWAYS,
   204         GST_PAD_ALWAYS,
   188         GST_STATIC_CAPS ("audio/x-raw-int, "
   205         GST_STATIC_CAPS ("audio/x-raw-int, " "endianness = (int) { " G_STRINGIFY (G_BYTE_ORDER) " }, " "signed = (boolean) TRUE, " "width = (int) 16, " "depth = (int) 16, " "rate = (int) [ 8000, 48000 ]," "channels = (int) [ 1, 2 ]; "
   189                 "endianness = (int) { " G_STRINGIFY (G_BYTE_ORDER) " }, "
   206                 "audio/amr, " "rate = (int) 8000, " "channels = (int) 1 ; "
   190                 "signed = (boolean) TRUE, "
   207                 "audio/AMR, " "rate = (int) 8000, " "channels = (int) 1 ; "
   191                 "width = (int) 16, "
   208                 "audio/x-alaw, " "rate = (int) [ 8000, 48000 ], " "channels = (int) [ 1, 2 ]; "
   192                 "depth = (int) 16, "
   209                 "audio/g729, " "rate = (int) [ 8000, 48000 ], " "channels = (int) [ 1, 2 ]; "
   193                 "rate = (int) [ 8000, 48000 ],"
   210                 "audio/mp3, " "rate = (int) [ 8000, 48000 ], " "channels = (int) [ 1, 2 ]; "                
   194                 "channels = (int) [ 1, 2 ]; "
   211                 "audio/ilbc, " "rate = (int) [ 8000, 48000 ], " "channels = (int) [ 1, 2 ]; "
   195                 "audio/amr, "
   212                 "audio/x-mulaw, " "rate = (int) [ 8000, 48000 ], " "channels = (int) [ 1, 2 ]")
   196                 //"width = (int) 8, "
       
   197                 //"depth = (int) 8, "
       
   198                 "rate = (int) 8000, "
       
   199                 "channels = (int) 1 ; "
       
   200                 "audio/x-alaw, "
       
   201                 "rate = (int) [ 8000, 48000 ], "
       
   202                 "channels = (int) [ 1, 2 ]; "
       
   203                 "audio/g729, "
       
   204                 "rate = (int) [ 8000, 48000 ], "
       
   205                 "channels = (int) [ 1, 2 ]; "
       
   206                 "audio/mp3, "
       
   207                 "rate = (int) [ 8000, 48000 ], "
       
   208                 "channels = (int) [ 1, 2 ]; "                
       
   209                 "audio/ilbc, "
       
   210                 "rate = (int) [ 8000, 48000 ], "
       
   211                 "channels = (int) [ 1, 2 ]; "
       
   212                 "audio/x-mulaw, "
       
   213                 "rate = (int) [ 8000, 48000 ], "
       
   214                 "channels = (int) [ 1, 2 ]")
       
   215                 );
   213                 );
   216 
   214 
   217 static GstElementClass *parent_class= NULL;
   215 static GstElementClass *parent_class= NULL;
   218 
   216 
   219 GType gst_devsound_sink_get_type(void)
   217 GType gst_devsound_sink_get_type(void)
   282     return devsoundsink_type;
   280     return devsoundsink_type;
   283     }
   281     }
   284 
   282 
   285 static void gst_devsound_sink_dispose(GObject * object)
   283 static void gst_devsound_sink_dispose(GObject * object)
   286     {
   284     {
   287     GstDevsoundSink *devsoundsink= GST_DEVSOUND_SINK (object);
   285     GstDevsoundSink *devsoundsink = GST_DEVSOUND_SINK (object);
   288 
   286 
   289     if (devsoundsink->probed_caps)
   287     if (devsoundsink->probed_caps)
   290         {
   288         {
   291         gst_caps_unref(devsoundsink->probed_caps);
   289         gst_caps_unref(devsoundsink->probed_caps);
   292         devsoundsink->probed_caps = NULL;
   290         devsoundsink->probed_caps = NULL;
   293         }
   291         }
   294 
   292 #ifdef AV_SYNC
       
   293     if (devsoundsink->clock)
       
   294         {
       
   295         gst_object_unref (devsoundsink->clock);
       
   296         }
       
   297     devsoundsink->clock = NULL;
       
   298 #endif /*AV_SYNC*/
   295     G_OBJECT_CLASS (parent_class)->dispose (object);
   299     G_OBJECT_CLASS (parent_class)->dispose (object);
   296     }
   300     }
   297 
   301 
   298 static void gst_devsound_sink_base_init(gpointer g_class)
   302 static void gst_devsound_sink_base_init(gpointer g_class)
   299     {
   303     {
   322 
   326 
   323     gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_devsound_sink_dispose);
   327     gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_devsound_sink_dispose);
   324     gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_devsound_sink_finalise);
   328     gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_devsound_sink_finalise);
   325     gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_devsound_sink_get_property);
   329     gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_devsound_sink_get_property);
   326     gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_devsound_sink_set_property);
   330     gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_devsound_sink_set_property);
   327 
   331     
       
   332     
       
   333     gstelement_class->change_state = GST_DEBUG_FUNCPTR(gst_devsound_sink_change_state);
       
   334     
   328     g_object_class_install_property(gobject_class, PROP_DEVICE,
   335     g_object_class_install_property(gobject_class, PROP_DEVICE,
   329             g_param_spec_string("device", "Device", "Devsound device ",
   336             g_param_spec_string("device", "Device", "Devsound device ",
   330             DEFAULT_DEVICE, G_PARAM_READWRITE));
   337             DEFAULT_DEVICE, G_PARAM_READWRITE));
   331 
   338 
   332     g_object_class_install_property(gobject_class, VOLUME,
   339     g_object_class_install_property(gobject_class, VOLUME,
   346                           -1, G_MAXINT, -1, G_PARAM_READWRITE));
   353                           -1, G_MAXINT, -1, G_PARAM_READWRITE));
   347 
   354 
   348     g_object_class_install_property(gobject_class, RIGHTBALANCE,
   355     g_object_class_install_property(gobject_class, RIGHTBALANCE,
   349                    g_param_spec_int("rightbalance", "Right Balance", "Right Balance",
   356                    g_param_spec_int("rightbalance", "Right Balance", "Right Balance",
   350                            -1, G_MAXINT, -1, G_PARAM_READWRITE));
   357                            -1, G_MAXINT, -1, G_PARAM_READWRITE));
   351 
   358 /*
   352     g_object_class_install_property(gobject_class, SAMPLESPLAYED,
   359     g_object_class_install_property(gobject_class, SAMPLESPLAYED,
   353                       g_param_spec_int("samplesplayed", "Samples Played", "Samples Played",
   360                       g_param_spec_int("samplesplayed", "Samples Played", "Samples Played",
   354                               -1, G_MAXINT, -1, G_PARAM_READABLE));
   361                               -1, G_MAXINT, -1, G_PARAM_READABLE));
   355 
   362 */
   356     g_object_class_install_property(gobject_class, PRIORITY,
   363     g_object_class_install_property(gobject_class, PRIORITY,
   357             g_param_spec_int("priority", "Priority", "Priority ", -1,
   364             g_param_spec_int("priority", "Priority", "Priority ", -1,
   358                     G_MAXINT, -1,
   365                     G_MAXINT, -1,
   359                     G_PARAM_READWRITE));
   366                     G_PARAM_READWRITE));
   360 
   367 
   361     g_object_class_install_property(gobject_class, PREFERENCE,
   368     g_object_class_install_property(gobject_class, PREFERENCE,
   362             g_param_spec_int("preference", "Preference", "Preference ", -1,
   369             g_param_spec_int("preference", "Preference", "Preference ", -1,
   363                     G_MAXINT, -1,
   370                     G_MAXINT, -1,
   364                     G_PARAM_READWRITE));
   371                     G_PARAM_READWRITE));
   365 
   372 /*
   366     g_object_class_install_property(gobject_class, RATE,
   373     g_object_class_install_property(gobject_class, RATE,
   367             g_param_spec_int("rate", "Rate", "Rate ", -1,
   374             g_param_spec_int("rate", "Rate", "Rate ", -1,
   368                     G_MAXINT, -1,
   375                     G_MAXINT, -1,
   369                     G_PARAM_READWRITE));
   376                     G_PARAM_READWRITE));
   370 
   377 
   371     g_object_class_install_property(gobject_class, CHANNELS,
   378     g_object_class_install_property(gobject_class, CHANNELS,
   372             g_param_spec_int("channels", "Channels", "Channels ", -1,
   379             g_param_spec_int("channels", "Channels", "Channels ", -1,
   373                     G_MAXINT, -1,
   380                     G_MAXINT, -1,
   374                     G_PARAM_READWRITE));
   381                     G_PARAM_READWRITE));
   375 
   382 */
   376     g_object_class_install_property(gobject_class, OUTPUTDEVICE,
   383     g_object_class_install_property(gobject_class, OUTPUTDEVICE,
   377              g_param_spec_int("outputdevice", "Output Device", "Output Device ", -1,
   384              g_param_spec_int("outputdevice", "Output Device", "Output Device ", -1,
   378                      G_MAXINT, -1,
   385                      G_MAXINT, -1,
   379                      G_PARAM_READWRITE));
   386                      G_PARAM_READWRITE));
   380     
   387     
       
   388 #ifdef AV_SYNC
       
   389     gstelement_class->provide_clock = GST_DEBUG_FUNCPTR (gst_devsound_sink_provide_clock);
       
   390 #endif /*AV_SYNC*/
       
   391 
   381     gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_sink_start);
   392     gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_sink_start);
   382     gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_sink_stop);
   393     gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_sink_stop);
   383     gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_sink_render);
   394     gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_sink_render);
   384 
   395 
   385     gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_devsound_sink_getcaps);
   396     gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_devsound_sink_getcaps);
   386     gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_devsound_sink_setcaps);
   397     gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_devsound_sink_setcaps);
   387     gstbasesink_class->event    = GST_DEBUG_FUNCPTR (gst_devsound_sink_event);
   398     gstbasesink_class->event    = GST_DEBUG_FUNCPTR (gst_devsound_sink_event);
   388     }
   399 #ifdef AV_SYNC
   389 
   400     gstbasesink_class->get_times = GST_DEBUG_FUNCPTR (gst_devsound_sink_get_times);
   390 static void gst_devsound_sink_init(GstDevsoundSink * devsoundsink)
   401 #endif /*AV_SYNC*/
   391     {
   402     }
   392     GST_DEBUG_OBJECT(devsoundsink, "initializing devsoundsink");
   403 
   393     devsoundsink->device = g_strdup(DEFAULT_DEVICE);
   404 static void gst_devsound_sink_init(GstDevsoundSink * dssink)
   394     devsoundsink->handle = NULL;
   405     {
   395     devsoundsink->preference = 0; //default=>EMdaPriorityPreferenceNone;
   406     GST_DEBUG_OBJECT(dssink, "initializing devsoundsink");
   396     devsoundsink->priority = 0;   //default=>EMdaPriorityNormal;
   407     dssink->device = g_strdup(DEFAULT_DEVICE);
       
   408     dssink->handle = NULL;
       
   409     dssink->preference = 0; //default=>EMdaPriorityPreferenceNone;
       
   410     dssink->priority = 0;   //default=>EMdaPriorityNormal;
       
   411 #ifdef AV_SYNC
       
   412     dssink->time_or_samples_played = 0;
       
   413     dssink->timeplayedavailable = FALSE;
       
   414     /* Create the provided clock. */
       
   415     dssink->clock = gst_audio_clock_new ("clock", gst_devsound_sink_get_time, dssink);
       
   416 #endif /*AV_SYNC*/
   397     pthread_mutex_init(&ds_mutex, NULL);
   417     pthread_mutex_init(&ds_mutex, NULL);
   398     pthread_cond_init(&ds_condition, NULL);
   418     pthread_cond_init(&ds_condition, NULL);
   399     }
   419     }
   400 
   420 
   401 static void *StartDevSoundThread(void *threadarg)
   421 static void *StartDevSoundThread(void *threadarg)
   402     {
   422     {
   403 
   423     GstDevsoundSink *dssink;
   404     GstDevsoundSink *devsound;
       
   405 
   424 
   406     gint remainingDataLen = 0;
   425     gint remainingDataLen = 0;
   407     GstBuffer *buffer = NULL;
   426     GstBuffer *buffer = NULL;
   408     gboolean lastBufferSet=FALSE;
   427     gboolean lastBufferSet=FALSE;
   409     devsound = (GstDevsoundSink*) threadarg;
   428     dssink = (GstDevsoundSink*) threadarg;
   410 
   429 
   411     open_devsound(&(devsound->handle));
   430     // TODO handle error here
       
   431     open_devsound(&(dssink->handle));
       
   432 #ifdef AV_SYNC
       
   433     dssink->timeplayedavailable = is_timeplayed_supported(dssink->handle);
       
   434 #endif /*AV_SYNC*/
   412 
   435 
   413 
   436 
   414     //get supported (in/out)put datatypes
   437     //get supported (in/out)put datatypes
   415     //from devsound to build caps
   438     //from devsound to build caps
   416     getsupporteddatatypes(devsound);
   439     getsupporteddatatypes(dssink);
   417 
   440 
   418     // TODO obtain mutex to update variable here???
   441     // TODO obtain mutex to update variable here???
   419     consumer_thread_state = CONSUMER_THREAD_INITIALIZED;
   442     consumer_thread_state = CONSUMER_THREAD_INITIALIZED;
   420 
   443 
   421     // Signal any waiting threads that consumer thread creation was successful.
   444     // Signal any waiting threads that consumer thread creation was successful.
   436     // without putting it to play state
   459     // without putting it to play state
   437     if ( cmd != CLOSE )
   460     if ( cmd != CLOSE )
   438         {
   461         {
   439         //TODO if there is preemption we have to somehow signal
   462         //TODO if there is preemption we have to somehow signal
   440         //the pipeline in the render
   463         //the pipeline in the render
   441         initialize_devsound(devsound);
   464         initialize_devsound(dssink);
   442 
   465 
   443         playinit(devsound->handle);
   466         playinit(dssink->handle);
   444         initproperties(devsound);
   467         dssink->eosreceived = FALSE;
       
   468         initproperties(dssink);
   445         }
   469         }
   446     while (1)
   470     while (1)
   447         {
   471         {
   448         switch (cmd)
   472         switch (cmd)
   449             {
   473             {
   450             case WRITEDATA:
   474             case PAUSE:
       
   475                 pause_devsound(dssink);
       
   476                 cmd = WAIT;
       
   477                 break;
       
   478                 
       
   479             case RESUME:
       
   480                 resume_devsound(dssink);
       
   481                 cmd = PLAYING;
       
   482                 break;
       
   483             
       
   484             case WAIT:
       
   485                 pthread_mutex_lock(&ds_mutex);
       
   486                 pthread_cond_signal(&ds_condition);
       
   487                 pthread_mutex_unlock(&ds_mutex);
       
   488                             
       
   489                 pthread_mutex_lock(&ds_mutex);
       
   490                 pthread_cond_wait(&ds_condition, &ds_mutex);
       
   491                 pthread_mutex_unlock(&ds_mutex);
       
   492                 break;
       
   493                 
       
   494             case PLAYING:
   451                 {
   495                 {
   452                 pre_init_setconf(devsound);
   496                 pre_init_setconf(dssink);
   453                 gst_Apply_ErrorConcealment_Update(devsound);
   497                 gst_Apply_ErrorConcealment_Update(dssink);
   454                 gst_Apply_G711_Decoder_Update(devsound);
   498                 gst_Apply_G711_Decoder_Update(dssink);
   455                 gst_Apply_G729_Decoder_Update(devsound);
   499                 gst_Apply_G729_Decoder_Update(dssink);
   456                 gst_Apply_Ilbc_Decoder_Update(devsound);
   500                 gst_Apply_Ilbc_Decoder_Update(dssink);
   457 
   501 
   458                 // TODO we could do this in BTBF callback
   502                 // TODO we could do this in BTBF callback
   459                 populateproperties(devsound);
   503                 populateproperties(dssink);
   460 
   504                 get_PopulateIntfcProperties(dssink);
   461                 framemodereq = devsound->framemodereq;
   505                 
   462                 g711cng = devsound->g711cng;
       
   463                 ilbccng = devsound->ilbccng;
       
   464                 output = devsound->output;
       
   465 
       
   466                 if(buffer_queue->length > 0)
   506                 if(buffer_queue->length > 0)
   467                     {
   507                     {
   468                     if (remainingDataLen == 0)
   508                     if (remainingDataLen == 0)
   469                         {
   509                         {
   470                         // TODO enable lock and unlock
   510                         // TODO enable lock and unlock
   471                         GST_OBJECT_LOCK (devsound);
   511                         GST_OBJECT_LOCK (dssink);
   472                         buffer = GST_BUFFER_CAST(g_queue_peek_head(buffer_queue));
   512                         buffer = GST_BUFFER_CAST(g_queue_peek_head(buffer_queue));
   473                         GST_OBJECT_UNLOCK(devsound);
   513                         GST_OBJECT_UNLOCK(dssink);
   474                         remainingDataLen = GST_BUFFER_SIZE(buffer);
   514                         remainingDataLen = GST_BUFFER_SIZE(buffer);
   475                         }
   515                         }
   476 
   516 
   477                     lastBufferSet =  GST_BUFFER_FLAG_IS_SET(buffer,GST_BUFFER_FLAG_LAST);
   517                     lastBufferSet =  GST_BUFFER_FLAG_IS_SET(buffer,GST_BUFFER_FLAG_LAST);
   478                     remainingDataLen = write_data(devsound->handle,
   518                     remainingDataLen = write_data(dssink->handle,
   479                             GST_BUFFER_DATA(buffer) + (GST_BUFFER_SIZE(buffer) - remainingDataLen),
   519                             GST_BUFFER_DATA(buffer) + (GST_BUFFER_SIZE(buffer) - remainingDataLen),
   480                             remainingDataLen,
   520                             remainingDataLen,
   481                             lastBufferSet);
   521                             lastBufferSet);
   482 
   522 
   483                     if (remainingDataLen == 0)
   523                     if (remainingDataLen == 0)
   484                         {
   524                         {
   485                         GST_OBJECT_LOCK (devsound);
   525                         GST_OBJECT_LOCK (dssink);
   486                         buffer = GST_BUFFER_CAST(g_queue_pop_head(buffer_queue));
   526                         buffer = GST_BUFFER_CAST(g_queue_pop_head(buffer_queue));
   487                         GST_OBJECT_UNLOCK(devsound);
   527                         GST_OBJECT_UNLOCK(dssink);
   488                         gst_buffer_unref(buffer);
   528                         gst_buffer_unref(buffer);
   489                         buffer = NULL;
   529                         buffer = NULL;
   490                         }
   530                         }
   491 
   531 
   492                     if (lastBufferSet && remainingDataLen == 0)
   532                     if (lastBufferSet && remainingDataLen == 0)
   493                         {
   533                         {
   494                         // Last Buffer is already sent to DevSound
   534                         lastBufferSet = FALSE;
   495                         // and we have received PlayError so now we exit
   535                         dssink->eosreceived = FALSE;
   496                         // from the big loop next time
   536                         playinit(dssink->handle);
   497 /*
   537                         initproperties(dssink);
   498                         pthread_mutex_lock(&ds_mutex);
   538                         get_PopulateIntfcProperties(dssink);
   499                         pthread_cond_signal(&ds_condition);
   539                         cmd = WAIT;
   500                         pthread_mutex_unlock(&ds_mutex);
   540                         }
   501 */
       
   502                         cmd = CLOSE;
       
   503                        }
       
   504                     }
   541                     }
   505                 else
   542                 else
   506                     {
   543                     {
   507                     pthread_mutex_lock(&ds_mutex);
   544                     cmd = WAIT;
   508                     pthread_cond_wait(&ds_condition, &ds_mutex);
       
   509                     pthread_mutex_unlock(&ds_mutex);
       
   510                     }
   545                     }
   511                 }
   546                 }
   512                 break;
   547                 break;
   513             case CLOSE:
   548             case CLOSE:
   514                 {
   549                 {
   515                 close_devsound(devsound);
   550                 close_devsound(dssink);
   516                 devsound->handle= NULL;
   551                 dssink->handle= NULL;
   517                 pthread_mutex_lock(&ds_mutex);
   552                 pthread_mutex_lock(&ds_mutex);
   518                 pthread_cond_signal(&ds_condition);
   553                 pthread_cond_signal(&ds_condition);
   519                 pthread_mutex_unlock(&ds_mutex);
   554                 pthread_mutex_unlock(&ds_mutex);
   520                 // TODO obtain mutex here
   555                 // TODO obtain mutex here
   521                 consumer_thread_state = CONSUMER_THREAD_UNINITIALIZED;
   556                 consumer_thread_state = CONSUMER_THREAD_UNINITIALIZED;
   535     }
   570     }
   536 
   571 
   537 static gboolean gst_sink_start (GstBaseSink * sink)
   572 static gboolean gst_sink_start (GstBaseSink * sink)
   538     {
   573     {
   539     GstBuffer *tmp_gstbuffer=NULL;
   574     GstBuffer *tmp_gstbuffer=NULL;
   540     GstDevsoundSink *devsound = GST_DEVSOUND_SINK(sink);
   575     GstDevsoundSink *dssink = GST_DEVSOUND_SINK(sink);
   541 
   576 
   542     if(buffer_queue)
   577     if(buffer_queue)
   543         {
   578         {
   544         while (buffer_queue->length)
   579         while (buffer_queue->length)
   545             {
   580             {
   555           buffer_queue = g_queue_new();
   590           buffer_queue = g_queue_new();
   556           }
   591           }
   557 
   592 
   558     consumer_thread_state = CONSUMER_THREAD_INITIALIZING;
   593     consumer_thread_state = CONSUMER_THREAD_INITIALIZING;
   559     cmd = OPEN;
   594     cmd = OPEN;
   560     pthread_create(&ds_thread,  NULL, StartDevSoundThread, (void *)devsound);
   595     pthread_create(&ds_thread,  NULL, StartDevSoundThread, (void *)dssink);
   561 
   596 
   562     // Wait until consumer thread is created
   597     // Wait until consumer thread is created
   563     // TODO : obtain mutex to retreive thread state?
   598     // TODO : obtain mutex to retreive thread state?
   564     if (consumer_thread_state == CONSUMER_THREAD_INITIALIZING)
   599     if (consumer_thread_state == CONSUMER_THREAD_INITIALIZING)
   565         {
   600         {
   572     }
   607     }
   573 
   608 
   574 static gboolean gst_sink_stop (GstBaseSink * sink)
   609 static gboolean gst_sink_stop (GstBaseSink * sink)
   575     {
   610     {
   576     GstBuffer *tmp_gstbuffer=NULL;
   611     GstBuffer *tmp_gstbuffer=NULL;
   577     GstDevsoundSink *devsound = GST_DEVSOUND_SINK(sink);
   612     GstDevsoundSink *dssink = GST_DEVSOUND_SINK(sink);
   578 
   613 
   579     cmd = CLOSE;
   614     cmd = CLOSE;
   580 
   615 
   581     pthread_mutex_lock(&ds_mutex);
   616     pthread_mutex_lock(&ds_mutex);
   582     pthread_cond_signal(&ds_condition);
   617     pthread_cond_signal(&ds_condition);
   583     pthread_mutex_unlock(&ds_mutex);
   618     pthread_mutex_unlock(&ds_mutex);
   584 
   619 
   585     GST_OBJECT_LOCK(devsound);
   620     pthread_mutex_lock(&ds_mutex);
       
   621     pthread_cond_wait(&ds_condition, &ds_mutex);
       
   622     pthread_mutex_unlock(&ds_mutex);
       
   623     
       
   624 
       
   625     GST_OBJECT_LOCK(dssink);
   586     while (buffer_queue->length)
   626     while (buffer_queue->length)
   587         {
   627         {
   588         tmp_gstbuffer = (GstBuffer*)g_queue_pop_tail(buffer_queue);
   628         tmp_gstbuffer = (GstBuffer*)g_queue_pop_tail(buffer_queue);
   589         gst_buffer_unref(tmp_gstbuffer);
   629         gst_buffer_unref(tmp_gstbuffer);
   590         }
   630         }
   591     g_queue_free(buffer_queue);
   631     g_queue_free(buffer_queue);
   592     buffer_queue = NULL;
   632     buffer_queue = NULL;
   593     GST_OBJECT_UNLOCK(devsound);
   633     GST_OBJECT_UNLOCK(dssink);
   594 
   634 
   595     return TRUE;
   635     return TRUE;
   596     }
   636     }
   597 
   637 
   598 static GstFlowReturn gst_sink_render (GstBaseSink * sink,
   638 static GstFlowReturn gst_sink_render (GstBaseSink * sink,
   599     GstBuffer * buffer)
   639     GstBuffer * buffer)
   600     {
   640     {
   601     GstDevsoundSink *devsound = GST_DEVSOUND_SINK(sink);
   641     GstDevsoundSink *dssink = GST_DEVSOUND_SINK(sink);
   602     GstBuffer* tmp;
   642     GstBuffer* tmp;
   603 
   643 
   604     if (get_ds_cb_error(devsound->handle))
   644     if (get_ds_cb_error(dssink->handle))
   605         {
   645         {
   606         return GST_FLOW_CUSTOM_ERROR;
   646         return GST_FLOW_CUSTOM_ERROR;
   607         }
   647         }
   608         
   648         
   609     tmp = gst_buffer_copy(buffer);
   649     tmp = gst_buffer_copy(buffer);
   610  
   650  
   611     GST_OBJECT_LOCK (devsound);
   651     GST_OBJECT_LOCK (dssink);
   612     g_queue_push_tail (buffer_queue, tmp);
   652     g_queue_push_tail (buffer_queue, tmp);
   613     GST_OBJECT_UNLOCK (devsound);
   653     GST_OBJECT_UNLOCK (dssink);
   614 
   654 
   615     cmd = WRITEDATA;
   655     cmd = PLAYING;
   616     pthread_mutex_lock(&ds_mutex);
   656     pthread_mutex_lock(&ds_mutex);
   617     pthread_cond_signal(&ds_condition);
   657     pthread_cond_signal(&ds_condition);
   618     pthread_mutex_unlock(&ds_mutex);
   658     pthread_mutex_unlock(&ds_mutex);
   619 
   659 
   620     return GST_FLOW_OK;
   660     return GST_FLOW_OK;
   621     }
   661     }
   622 
   662 
   623 static void gst_devsound_sink_finalise(GObject * object)
   663 static void gst_devsound_sink_finalise(GObject * object)
   624     {
   664     {
   625     GstDevsoundSink *devsoundsink= GST_DEVSOUND_SINK (object);
   665     GstDevsoundSink *devsoundsink = GST_DEVSOUND_SINK (object);
   626     g_free(devsoundsink->device);
   666     g_free(devsoundsink->device);
   627 
   667 
   628     }
   668     }
   629 
   669 
   630 static void gst_devsound_sink_set_property(GObject * object, guint prop_id,
   670 static void gst_devsound_sink_set_property(GObject * object, guint prop_id,
   644                 {
   684                 {
   645                 gst_caps_unref(sink->probed_caps);
   685                 gst_caps_unref(sink->probed_caps);
   646                 sink->probed_caps = NULL;
   686                 sink->probed_caps = NULL;
   647                 }
   687                 }
   648             break;
   688             break;
   649         case CHANNELS:
   689 /*        case CHANNELS:
   650             sink->channels = g_value_get_int(value);
   690             sink->channels = g_value_get_int(value);
   651             sink->pending.channelsupdate = TRUE;
   691             sink->pending.channelsupdate = TRUE;
   652             break;
   692             break;
   653         case RATE:
   693         case RATE:
   654             sink->rate = g_value_get_int(value);
   694             sink->rate = g_value_get_int(value);
   655             //Convert rate to something devsound understands
   695             //Convert rate to something devsound understands
   656             sink->rate = gst_devsound_sink_get_rate(sink->rate);
   696             sink->rate = gst_devsound_sink_get_rate(sink->rate);
   657             sink->pending.rateupdate = TRUE;
   697             sink->pending.rateupdate = TRUE;
   658             break;
   698             break;
   659         case VOLUME:
   699 */        case VOLUME:
   660             sink->volume = g_value_get_int(value);
   700             sink->volume = g_value_get_int(value);
   661             sink->pending.volumeupdate = TRUE;
   701             sink->pending.volumeupdate = TRUE;
   662             break;
   702             break;
   663         case LEFTBALANCE:
   703         case LEFTBALANCE:
   664             sink->leftbalance = g_value_get_int(value);
   704             sink->leftbalance = g_value_get_int(value);
   678             break;
   718             break;
   679         case PREFERENCE:
   719         case PREFERENCE:
   680             sink->preference = g_value_get_int(value);
   720             sink->preference = g_value_get_int(value);
   681             sink->pending.preferenceupdate = TRUE;
   721             sink->pending.preferenceupdate = TRUE;
   682             break;
   722             break;
   683         case FOURCC: //FOURCC is not needed
   723 /*        case FOURCC: //FOURCC is not needed
   684             sink->fourcc = g_value_get_int(value);
   724             sink->fourcc = g_value_get_int(value);
   685             sink->pending.fourccupdate = TRUE;
   725             sink->pending.fourccupdate = TRUE;
   686             break;
   726             break;
   687 
       
   688         case MIMETYPE:
   727         case MIMETYPE:
   689             sink->mimetype = g_value_dup_string(value);
   728             sink->mimetype = g_value_dup_string(value);
   690             break;
   729             break;*/
   691         case OUTPUTDEVICE:
   730         case OUTPUTDEVICE:
   692             sink->output = g_value_get_int(value);
   731             sink->output = g_value_get_int(value);
   693             sink->pending.outputupdate = TRUE;
   732             sink->pending.outputupdate = TRUE;
   694             break;
   733             break;
   695         default:
   734         default:
   708     switch (prop_id)
   747     switch (prop_id)
   709         {
   748         {
   710         case PROP_DEVICE:
   749         case PROP_DEVICE:
   711             g_value_set_string(value, sink->device);
   750             g_value_set_string(value, sink->device);
   712             break;
   751             break;
   713         case CHANNELS:
   752 /*        case CHANNELS:
   714             g_value_set_int(value, sink->channels);
   753             g_value_set_int(value, sink->channels);
   715             break;
   754             break;
   716         case RATE:
   755         case RATE:
   717             g_value_set_int(value, sink->rate);
   756             g_value_set_int(value, sink->rate);
   718             break;
   757             break;*/
   719         case VOLUME:
   758         case VOLUME:
   720             g_value_set_int(value, sink->volume);
   759             g_value_set_int(value, sink->volume);
   721             break;
   760             break;
   722         case MAXVOLUME:
   761         case MAXVOLUME:
   723             g_value_set_int(value, sink->maxvolume);
   762             g_value_set_int(value, sink->maxvolume);
   724             break;
   763             break;
   725         case SAMPLESPLAYED:
   764 /*        case SAMPLESPLAYED:
   726               g_value_set_int(value, sink->samplesplayed);
   765               g_value_set_int(value, sink->samplesplayed);
   727               break;
   766               break;*/
   728         case OUTPUTDEVICE:
   767         case OUTPUTDEVICE:
   729               g_value_set_int(value, sink->output);
   768               g_value_set_int(value, sink->output);
   730               break;
   769               break;
   731         default:
   770         default:
   732             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   771             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   921 
   960 
   922 
   961 
   923 
   962 
   924 static gboolean gst_devsound_sink_event(GstBaseSink *asink, GstEvent *event)
   963 static gboolean gst_devsound_sink_event(GstBaseSink *asink, GstEvent *event)
   925     {
   964     {
   926     GstDevsoundSink *sink= GST_DEVSOUND_SINK (asink);
   965     GstDevsoundSink *sink = GST_DEVSOUND_SINK (asink);
   927     GstBuffer* lastBuffer = NULL;
   966     GstBuffer* lastBuffer = NULL;
   928     switch (GST_EVENT_TYPE (event))
   967     switch (GST_EVENT_TYPE (event))
   929         {
   968         {
   930         case GST_EVENT_EOS:
   969         case GST_EVENT_EOS:
   931             // end-of-stream, we should close down all stream leftovers here
   970             // end-of-stream, we should close down all stream leftovers here
   932             //reset_devsound(sink->handle);
   971             //reset_devsound(sink->handle);
   933 
   972             sink->eosreceived = TRUE;
   934             if(buffer_queue->length)
   973             if(buffer_queue->length)
   935                 {
   974                 {
   936                 GST_OBJECT_LOCK(sink);
   975                 GST_OBJECT_LOCK(sink);
   937                 lastBuffer = GST_BUFFER(g_queue_peek_tail(buffer_queue));
   976                 lastBuffer = GST_BUFFER(g_queue_peek_tail(buffer_queue));
   938                 GST_BUFFER_FLAG_SET(lastBuffer,GST_BUFFER_FLAG_LAST);
   977                 GST_BUFFER_FLAG_SET(lastBuffer,GST_BUFFER_FLAG_LAST);
   943                 lastBuffer = gst_buffer_new();
   982                 lastBuffer = gst_buffer_new();
   944                 GST_BUFFER_FLAG_SET(lastBuffer,GST_BUFFER_FLAG_LAST);
   983                 GST_BUFFER_FLAG_SET(lastBuffer,GST_BUFFER_FLAG_LAST);
   945                 GST_OBJECT_LOCK(sink);
   984                 GST_OBJECT_LOCK(sink);
   946                 g_queue_push_tail(buffer_queue,lastBuffer);
   985                 g_queue_push_tail(buffer_queue,lastBuffer);
   947                 GST_OBJECT_UNLOCK(sink);
   986                 GST_OBJECT_UNLOCK(sink);
   948                 cmd = WRITEDATA;
   987                 cmd = PLAYING;
   949                 pthread_mutex_lock(&ds_mutex);
   988                 pthread_mutex_lock(&ds_mutex);
   950                 pthread_cond_signal(&ds_condition);
   989                 pthread_cond_signal(&ds_condition);
   951                 pthread_mutex_unlock(&ds_mutex);
   990                 pthread_mutex_unlock(&ds_mutex);
   952                 }
   991                 }
   953             pthread_mutex_lock(&ds_mutex);
   992             pthread_mutex_lock(&ds_mutex);
   960         }
   999         }
   961 
  1000 
   962     return TRUE;
  1001     return TRUE;
   963     }
  1002     }
   964 
  1003 
       
  1004 #ifdef AV_SYNC
       
  1005 static void gst_devsound_sink_get_times (GstBaseSink * bsink, GstBuffer * buffer,
       
  1006     GstClockTime * start, GstClockTime * end)
       
  1007     {
       
  1008     /* Like GstBaseAudioSink, we set these to NONE */
       
  1009     *start = GST_CLOCK_TIME_NONE;
       
  1010     *end = GST_CLOCK_TIME_NONE;
       
  1011     }
       
  1012 
       
  1013 static GstClock *gst_devsound_sink_provide_clock (GstElement * element)
       
  1014     {
       
  1015     GstDevsoundSink *sink = GST_DEVSOUND_SINK (element);
       
  1016     return GST_CLOCK (gst_object_ref (sink->clock));
       
  1017     }
       
  1018 
       
  1019 static GstClockTime gst_devsound_sink_get_time (GstClock * clock, gpointer user_data)
       
  1020     {
       
  1021     GstClockTime result = 0;
       
  1022     GstDevsoundSink *sink = GST_DEVSOUND_SINK (user_data);
       
  1023 
       
  1024     /* The value returned must be in nano seconds. 1 sec = 1000000000 nano seconds (9 zeros)*/
       
  1025     /*If time played is available from DevSound (a3f devsound onwards) get it*/
       
  1026     if (sink->timeplayedavailable)
       
  1027         {
       
  1028         result = sink->time_or_samples_played;
       
  1029         }
       
  1030     else if ((sink->time_or_samples_played > 0 ) && (sink->rate > 0 ))/*This is a pre-a3f devsound. So calculate times played based on samples played*/
       
  1031         { /*GST_SECOND = 1000000000*/
       
  1032         result = gst_util_uint64_scale_int (sink->time_or_samples_played, GST_SECOND, sink->rate);
       
  1033         }
       
  1034     GST_LOG_OBJECT (sink, "Time: %" GST_TIME_FORMAT, GST_TIME_ARGS (result));
       
  1035     return result;
       
  1036     }
       
  1037 #endif /*AV_SYNC*/
       
  1038 
       
  1039 static GstStateChangeReturn gst_devsound_sink_change_state (GstElement * element, GstStateChange transition)
       
  1040     {
       
  1041     GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
       
  1042     GstDevsoundSink *sink= GST_DEVSOUND_SINK (element);
       
  1043     
       
  1044     switch (transition)
       
  1045         {
       
  1046         case GST_STATE_CHANGE_NULL_TO_READY:
       
  1047             {
       
  1048 #ifdef AV_SYNC
       
  1049             sink->time_or_samples_played = 0;
       
  1050 #endif /*AV_SYNC*/			
       
  1051             }
       
  1052             break;
       
  1053 
       
  1054         case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
       
  1055             if(cmd == WAIT)
       
  1056                 {
       
  1057                 cmd = RESUME;
       
  1058                 pthread_mutex_lock(&ds_mutex);
       
  1059                 pthread_cond_signal(&ds_condition);
       
  1060                 pthread_mutex_unlock(&ds_mutex);
       
  1061                 
       
  1062                 pthread_mutex_lock(&ds_mutex);
       
  1063                 pthread_cond_wait(&ds_condition, &ds_mutex);
       
  1064                 pthread_mutex_unlock(&ds_mutex);
       
  1065                 }
       
  1066             break;
       
  1067         default:
       
  1068             break;
       
  1069         }
       
  1070 
       
  1071     ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
       
  1072       if (G_UNLIKELY (ret == GST_STATE_CHANGE_FAILURE))
       
  1073         goto activate_failed;
       
  1074 
       
  1075       switch (transition) {
       
  1076           
       
  1077           case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
       
  1078               cmd = PAUSE;
       
  1079               pthread_mutex_lock(&ds_mutex);
       
  1080               pthread_cond_signal(&ds_condition);
       
  1081               pthread_mutex_unlock(&ds_mutex);
       
  1082               
       
  1083               pthread_mutex_lock(&ds_mutex);
       
  1084               pthread_cond_wait(&ds_condition, &ds_mutex);
       
  1085               pthread_mutex_unlock(&ds_mutex);
       
  1086               break;
       
  1087           default:
       
  1088               break;
       
  1089           }
       
  1090       
       
  1091       return ret;
       
  1092     
       
  1093     activate_failed:
       
  1094       {
       
  1095         GST_DEBUG_OBJECT (sink,
       
  1096             "element failed to change states -- activation problem?");
       
  1097         return GST_STATE_CHANGE_FAILURE;
       
  1098       }    
       
  1099     }
       
  1100 
   965 
  1101 
   966 /************************************
  1102 /************************************
   967 * Error Concealment Interface begins
  1103 * Error Concealment Interface begins
   968 * **********************************/
  1104 * **********************************/
   969 static void gst_error_concealment_handler_init (gpointer g_iface,
  1105 static void gst_error_concealment_handler_init (gpointer g_iface,
  1140         {
  1276         {
  1141         set_ilbcdecodermode(dssink->handle,ilbcdecodemode);
  1277         set_ilbcdecodermode(dssink->handle,ilbcdecodemode);
  1142         customInfaceUpdate.ilbcdecodermodeupdate = FALSE;
  1278         customInfaceUpdate.ilbcdecodermodeupdate = FALSE;
  1143         }
  1279         }
  1144     }
  1280     }
       
  1281 
       
  1282 static void get_PopulateIntfcProperties(GstDevsoundSink* dssink)
       
  1283     {
       
  1284     framemode_rqrd_for_ec(dssink->handle,&framemodereq);   
       
  1285 
       
  1286     get_cng(dssink->handle,&g711cng);
       
  1287     
       
  1288     get_ilbccng(dssink->handle,&ilbccng);
       
  1289     }
       
  1290