LCOV - code coverage report
Current view: top level - gst-editing-services/ges - ges-track-audio-transition.c (source / functions) Hit Total Coverage
Test: GStreamer Lines: 113 120 94.2 %
Date: 2011-03-25 Functions: 10 12 83.3 %
Branches: 20 40 50.0 %

           Branch data     Line data    Source code
       1                 :            : /* GStreamer Editing Services
       2                 :            :  * Copyright (C) 2010 Brandon Lewis <brandon.lewis@collabora.co.uk>
       3                 :            :  *               2010 Nokia Corporation
       4                 :            :  *
       5                 :            :  * This library is free software; you can redistribute it and/or
       6                 :            :  * modify it under the terms of the GNU Library General Public
       7                 :            :  * License as published by the Free Software Foundation; either
       8                 :            :  * version 2 of the License, or (at your option) any later version.
       9                 :            :  *
      10                 :            :  * This library is distributed in the hope that it will be useful,
      11                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13                 :            :  * Library General Public License for more details.
      14                 :            :  *
      15                 :            :  * You should have received a copy of the GNU Library General Public
      16                 :            :  * License along with this library; if not, write to the
      17                 :            :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      18                 :            :  * Boston, MA 02111-1307, USA.
      19                 :            :  */
      20                 :            : 
      21                 :            : /**
      22                 :            :  * SECTION:ges-track-audio-transition
      23                 :            :  * @short_description: implements audio crossfade transition
      24                 :            :  */
      25                 :            : 
      26                 :            : #include "ges-internal.h"
      27                 :            : #include "ges-track-object.h"
      28                 :            : #include "ges-track-audio-transition.h"
      29                 :            : 
      30         [ +  + ]:         43 : G_DEFINE_TYPE (GESTrackAudioTransition, ges_track_audio_transition,
      31                 :         43 :     GES_TYPE_TRACK_TRANSITION);
      32                 :            : 
      33                 :            : struct _GESTrackAudioTransitionPrivate
      34                 :            : {
      35                 :            :   /* these enable volume interpolation. Unlike video, both inputs are adjusted
      36                 :            :    * simultaneously */
      37                 :            :   GstController *a_controller;
      38                 :            :   GstInterpolationControlSource *a_control_source;
      39                 :            : 
      40                 :            :   GstController *b_controller;
      41                 :            :   GstInterpolationControlSource *b_control_source;
      42                 :            : 
      43                 :            : };
      44                 :            : 
      45                 :            : enum
      46                 :            : {
      47                 :            :   PROP_0,
      48                 :            : };
      49                 :            : 
      50                 :            : 
      51                 :            : #define fast_element_link(a,b) gst_element_link_pads_full((a),"src",(b),"sink",GST_PAD_LINK_CHECK_NOTHING)
      52                 :            : 
      53                 :            : static void
      54                 :            : ges_track_audio_transition_duration_changed (GESTrackObject * self, guint64);
      55                 :            : 
      56                 :            : static GstElement *ges_track_audio_transition_create_element (GESTrackObject
      57                 :            :     * self);
      58                 :            : 
      59                 :            : static void ges_track_audio_transition_dispose (GObject * object);
      60                 :            : 
      61                 :            : static void ges_track_audio_transition_finalize (GObject * object);
      62                 :            : 
      63                 :            : static void ges_track_audio_transition_get_property (GObject * object, guint
      64                 :            :     property_id, GValue * value, GParamSpec * pspec);
      65                 :            : 
      66                 :            : static void ges_track_audio_transition_set_property (GObject * object, guint
      67                 :            :     property_id, const GValue * value, GParamSpec * pspec);
      68                 :            : 
      69                 :            : static void
      70                 :          3 : ges_track_audio_transition_class_init (GESTrackAudioTransitionClass * klass)
      71                 :            : {
      72                 :            :   GObjectClass *object_class;
      73                 :            :   GESTrackObjectClass *toclass;
      74                 :            : 
      75                 :          3 :   g_type_class_add_private (klass, sizeof (GESTrackAudioTransitionPrivate));
      76                 :            : 
      77                 :          3 :   object_class = G_OBJECT_CLASS (klass);
      78                 :          3 :   toclass = GES_TRACK_OBJECT_CLASS (klass);
      79                 :            : 
      80                 :          3 :   object_class->get_property = ges_track_audio_transition_get_property;
      81                 :          3 :   object_class->set_property = ges_track_audio_transition_set_property;
      82                 :          3 :   object_class->dispose = ges_track_audio_transition_dispose;
      83                 :          3 :   object_class->finalize = ges_track_audio_transition_finalize;
      84                 :            : 
      85                 :          3 :   toclass->duration_changed = ges_track_audio_transition_duration_changed;
      86                 :            : 
      87                 :          3 :   toclass->create_element = ges_track_audio_transition_create_element;
      88                 :            : 
      89                 :          3 : }
      90                 :            : 
      91                 :            : static void
      92                 :          8 : ges_track_audio_transition_init (GESTrackAudioTransition * self)
      93                 :            : {
      94                 :            : 
      95                 :          8 :   self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
      96                 :            :       GES_TYPE_TRACK_AUDIO_TRANSITION, GESTrackAudioTransitionPrivate);
      97                 :            : 
      98                 :          8 :   self->priv->a_controller = NULL;
      99                 :          8 :   self->priv->a_control_source = NULL;
     100                 :            : 
     101                 :          8 :   self->priv->b_controller = NULL;
     102                 :          8 :   self->priv->b_control_source = NULL;
     103                 :          8 : }
     104                 :            : 
     105                 :            : static void
     106                 :          8 : ges_track_audio_transition_dispose (GObject * object)
     107                 :            : {
     108                 :            :   GESTrackAudioTransition *self;
     109                 :            : 
     110                 :          8 :   self = GES_TRACK_AUDIO_TRANSITION (object);
     111                 :            : 
     112         [ +  - ]:          8 :   if (self->priv->a_controller) {
     113                 :          8 :     g_object_unref (self->priv->a_controller);
     114                 :          8 :     self->priv->a_controller = NULL;
     115         [ +  - ]:          8 :     if (self->priv->a_control_source)
     116                 :          8 :       gst_object_unref (self->priv->a_control_source);
     117                 :          8 :     self->priv->a_control_source = NULL;
     118                 :            :   }
     119                 :            : 
     120         [ +  - ]:          8 :   if (self->priv->b_controller) {
     121                 :          8 :     g_object_unref (self->priv->b_controller);
     122                 :          8 :     self->priv->b_controller = NULL;
     123         [ +  - ]:          8 :     if (self->priv->b_control_source)
     124                 :          8 :       gst_object_unref (self->priv->b_control_source);
     125                 :          8 :     self->priv->b_control_source = NULL;
     126                 :            :   }
     127                 :            : 
     128                 :          8 :   G_OBJECT_CLASS (ges_track_audio_transition_parent_class)->dispose (object);
     129                 :          8 : }
     130                 :            : 
     131                 :            : static void
     132                 :          8 : ges_track_audio_transition_finalize (GObject * object)
     133                 :            : {
     134                 :          8 :   G_OBJECT_CLASS (ges_track_audio_transition_parent_class)->finalize (object);
     135                 :          8 : }
     136                 :            : 
     137                 :            : static void
     138                 :          0 : ges_track_audio_transition_get_property (GObject * object,
     139                 :            :     guint property_id, GValue * value, GParamSpec * pspec)
     140                 :            : {
     141                 :            :   switch (property_id) {
     142                 :            :     default:
     143                 :          0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     144                 :            :   }
     145                 :          0 : }
     146                 :            : 
     147                 :            : static void
     148                 :          0 : ges_track_audio_transition_set_property (GObject * object,
     149                 :            :     guint property_id, const GValue * value, GParamSpec * pspec)
     150                 :            : {
     151                 :            :   switch (property_id) {
     152                 :            :     default:
     153                 :          0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     154                 :            :   }
     155                 :          0 : }
     156                 :            : 
     157                 :            : static GObject *
     158                 :         16 : link_element_to_mixer_with_volume (GstBin * bin, GstElement * element,
     159                 :            :     GstElement * mixer)
     160                 :            : {
     161                 :         16 :   GstElement *volume = gst_element_factory_make ("volume", NULL);
     162                 :         16 :   gst_bin_add (bin, volume);
     163                 :            : 
     164   [ +  -  -  + ]:         32 :   if (!fast_element_link (element, volume) ||
     165                 :         16 :       !gst_element_link_pads_full (volume, "src", mixer, "sink%d",
     166                 :            :           GST_PAD_LINK_CHECK_NOTHING))
     167         [ #  # ]:          0 :     GST_ERROR_OBJECT (bin, "Error linking volume to mixer");
     168                 :            : 
     169                 :         16 :   return G_OBJECT (volume);
     170                 :            : }
     171                 :            : 
     172                 :            : static GstElement *
     173                 :          8 : ges_track_audio_transition_create_element (GESTrackObject * object)
     174                 :            : {
     175                 :            :   GESTrackAudioTransition *self;
     176                 :            :   GstElement *topbin, *iconva, *iconvb, *oconv;
     177                 :          8 :   GObject *atarget, *btarget = NULL;
     178                 :          8 :   const gchar *propname = "volume";
     179                 :          8 :   GstElement *mixer = NULL;
     180                 :            :   GstPad *sinka_target, *sinkb_target, *src_target, *sinka, *sinkb, *src;
     181                 :            :   GstController *acontroller, *bcontroller;
     182                 :            :   GstInterpolationControlSource *acontrol_source, *bcontrol_source;
     183                 :            : 
     184                 :          8 :   self = GES_TRACK_AUDIO_TRANSITION (object);
     185                 :            : 
     186                 :            : 
     187         [ -  + ]:          8 :   GST_LOG ("creating an audio bin");
     188                 :            : 
     189                 :          8 :   topbin = gst_bin_new ("transition-bin");
     190                 :          8 :   iconva = gst_element_factory_make ("audioconvert", "tr-aconv-a");
     191                 :          8 :   iconvb = gst_element_factory_make ("audioconvert", "tr-aconv-b");
     192                 :          8 :   oconv = gst_element_factory_make ("audioconvert", "tr-aconv-output");
     193                 :            : 
     194                 :          8 :   gst_bin_add_many (GST_BIN (topbin), iconva, iconvb, oconv, NULL);
     195                 :            : 
     196                 :          8 :   mixer = gst_element_factory_make ("adder", NULL);
     197                 :          8 :   gst_bin_add (GST_BIN (topbin), mixer);
     198                 :            : 
     199                 :          8 :   atarget = link_element_to_mixer_with_volume (GST_BIN (topbin), iconva, mixer);
     200                 :          8 :   btarget = link_element_to_mixer_with_volume (GST_BIN (topbin), iconvb, mixer);
     201                 :            : 
     202 [ +  - ][ +  - ]:          8 :   g_assert (atarget && btarget);
     203                 :            : 
     204                 :          8 :   fast_element_link (mixer, oconv);
     205                 :            : 
     206                 :          8 :   sinka_target = gst_element_get_static_pad (iconva, "sink");
     207                 :          8 :   sinkb_target = gst_element_get_static_pad (iconvb, "sink");
     208                 :          8 :   src_target = gst_element_get_static_pad (oconv, "src");
     209                 :            : 
     210                 :          8 :   sinka = gst_ghost_pad_new ("sinka", sinka_target);
     211                 :          8 :   sinkb = gst_ghost_pad_new ("sinkb", sinkb_target);
     212                 :          8 :   src = gst_ghost_pad_new ("src", src_target);
     213                 :            : 
     214                 :          8 :   gst_element_add_pad (topbin, src);
     215                 :          8 :   gst_element_add_pad (topbin, sinka);
     216                 :          8 :   gst_element_add_pad (topbin, sinkb);
     217                 :            : 
     218                 :            :   /* set up interpolation */
     219                 :            : 
     220                 :          8 :   gst_object_unref (sinka_target);
     221                 :          8 :   gst_object_unref (sinkb_target);
     222                 :          8 :   gst_object_unref (src_target);
     223                 :            : 
     224                 :            : 
     225                 :            :   //g_object_set(atarget, propname, (gdouble) 0, NULL);
     226                 :            :   //g_object_set(btarget, propname, (gdouble) 0, NULL);
     227                 :            : 
     228                 :          8 :   acontroller = gst_object_control_properties (atarget, propname, NULL);
     229                 :          8 :   bcontroller = gst_object_control_properties (btarget, propname, NULL);
     230                 :            : 
     231 [ +  - ][ +  - ]:          8 :   g_assert (acontroller && bcontroller);
     232                 :            : 
     233                 :          8 :   acontrol_source = gst_interpolation_control_source_new ();
     234                 :          8 :   gst_controller_set_control_source (acontroller,
     235                 :          8 :       propname, GST_CONTROL_SOURCE (acontrol_source));
     236                 :          8 :   gst_interpolation_control_source_set_interpolation_mode (acontrol_source,
     237                 :            :       GST_INTERPOLATE_LINEAR);
     238                 :            : 
     239                 :          8 :   bcontrol_source = gst_interpolation_control_source_new ();
     240                 :          8 :   gst_controller_set_control_source (bcontroller,
     241                 :          8 :       propname, GST_CONTROL_SOURCE (bcontrol_source));
     242                 :          8 :   gst_interpolation_control_source_set_interpolation_mode (bcontrol_source,
     243                 :            :       GST_INTERPOLATE_LINEAR);
     244                 :            : 
     245                 :          8 :   self->priv->a_controller = acontroller;
     246                 :          8 :   self->priv->b_controller = bcontroller;
     247                 :          8 :   self->priv->a_control_source = acontrol_source;
     248                 :          8 :   self->priv->b_control_source = bcontrol_source;
     249                 :            : 
     250                 :          8 :   return topbin;
     251                 :            : }
     252                 :            : 
     253                 :            : static void
     254                 :          8 : ges_track_audio_transition_duration_changed (GESTrackObject * object,
     255                 :            :     guint64 duration)
     256                 :            : {
     257                 :            :   GESTrackAudioTransition *self;
     258                 :          8 :   GstElement *gnlobj = ges_track_object_get_gnlobject (object);
     259                 :            : 
     260                 :          8 :   GValue zero = { 0, };
     261                 :          8 :   GValue one = { 0, };
     262                 :            : 
     263                 :          8 :   self = GES_TRACK_AUDIO_TRANSITION (object);
     264                 :            : 
     265         [ -  + ]:          8 :   GST_LOG ("updating controller: gnlobj (%p) acontroller(%p) bcontroller(%p)",
     266                 :            :       gnlobj, self->priv->a_controller, self->priv->b_controller);
     267                 :            : 
     268 [ +  - ][ +  - ]:          8 :   if (G_UNLIKELY ((!gnlobj || !self->priv->a_control_source ||
                 [ -  + ]
     269                 :            :               !self->priv->b_control_source)))
     270                 :          8 :     return;
     271                 :            : 
     272         [ -  + ]:          8 :   GST_INFO ("duration: %" G_GUINT64_FORMAT, duration);
     273                 :          8 :   g_value_init (&zero, G_TYPE_DOUBLE);
     274                 :          8 :   g_value_init (&one, G_TYPE_DOUBLE);
     275                 :          8 :   g_value_set_double (&zero, 0.0);
     276                 :          8 :   g_value_set_double (&one, 1.0);
     277                 :            : 
     278         [ -  + ]:          8 :   GST_LOG ("setting values on controller");
     279                 :            : 
     280                 :          8 :   gst_interpolation_control_source_unset_all (self->priv->a_control_source);
     281                 :          8 :   gst_interpolation_control_source_set (self->priv->a_control_source, 0, &one);
     282                 :          8 :   gst_interpolation_control_source_set (self->priv->a_control_source,
     283                 :            :       duration, &zero);
     284                 :            : 
     285                 :          8 :   gst_interpolation_control_source_unset_all (self->priv->b_control_source);
     286                 :          8 :   gst_interpolation_control_source_set (self->priv->b_control_source, 0, &zero);
     287                 :          8 :   gst_interpolation_control_source_set (self->priv->b_control_source, duration,
     288                 :            :       &one);
     289                 :            : 
     290         [ -  + ]:          8 :   GST_LOG ("done updating controller");
     291                 :            : }
     292                 :            : 
     293                 :            : /**
     294                 :            :  * ges_track_audio_transition_new:
     295                 :            :  *
     296                 :            :  * Creates a new #GESTrackAudioTransition.
     297                 :            :  *
     298                 :            :  * Returns: The newly created #GESTrackAudioTransition.
     299                 :            :  */
     300                 :            : GESTrackAudioTransition *
     301                 :          8 : ges_track_audio_transition_new (void)
     302                 :            : {
     303                 :          8 :   return g_object_new (GES_TYPE_TRACK_AUDIO_TRANSITION, NULL);
     304                 :            : }

Generated by: LCOV version 1.9