gst_plugins_good/gst/law/mulaw-decode.c
changeset 26 69c7080681bf
parent 24 bc39b352897e
child 28 4ed5253bb6ba
equal deleted inserted replaced
24:bc39b352897e 26:69c7080681bf
     1 /* GStreamer
       
     2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
       
     3  *
       
     4  * This library is free software; you can redistribute it and/or
       
     5  * modify it under the terms of the GNU Library General Public
       
     6  * License as published by the Free Software Foundation; either
       
     7  * version 2 of the License, or (at your option) any later version.
       
     8  *
       
     9  * This library is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    12  * Library General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU Library General Public
       
    15  * License along with this library; if not, write to the
       
    16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    17  * Boston, MA 02111-1307, USA.
       
    18  */
       
    19 /**
       
    20  * SECTION:element-mulawdec
       
    21  *
       
    22  * This element decodes mulaw audio. Mulaw coding is also known as G.711.
       
    23  */
       
    24 
       
    25 #ifdef HAVE_CONFIG_H
       
    26 #include "config.h"
       
    27 #endif
       
    28 #include <gst/gst.h>
       
    29 #include "mulaw-decode.h"
       
    30 #include "mulaw-conversion.h"
       
    31 
       
    32 extern GstStaticPadTemplate mulaw_dec_src_factory;
       
    33 extern GstStaticPadTemplate mulaw_dec_sink_factory;
       
    34 
       
    35 /* Stereo signals and args */
       
    36 enum
       
    37 {
       
    38   /* FILL ME */
       
    39   LAST_SIGNAL
       
    40 };
       
    41 
       
    42 enum
       
    43 {
       
    44   ARG_0
       
    45 };
       
    46 
       
    47 static void gst_mulawdec_class_init (GstMuLawDecClass * klass);
       
    48 static void gst_mulawdec_base_init (GstMuLawDecClass * klass);
       
    49 static void gst_mulawdec_init (GstMuLawDec * mulawdec);
       
    50 static GstStateChangeReturn
       
    51 gst_mulawdec_change_state (GstElement * element, GstStateChange transition);
       
    52 
       
    53 static GstFlowReturn gst_mulawdec_chain (GstPad * pad, GstBuffer * buffer);
       
    54 
       
    55 static GstElementClass *parent_class = NULL;
       
    56 
       
    57 static gboolean
       
    58 mulawdec_sink_setcaps (GstPad * pad, GstCaps * caps)
       
    59 {
       
    60   GstMuLawDec *mulawdec;
       
    61   GstStructure *structure;
       
    62   int rate, channels;
       
    63   gboolean ret;
       
    64   GstCaps *outcaps;
       
    65 
       
    66   mulawdec = GST_MULAWDEC (GST_PAD_PARENT (pad));
       
    67 
       
    68   structure = gst_caps_get_structure (caps, 0);
       
    69   ret = gst_structure_get_int (structure, "rate", &rate);
       
    70   ret = ret && gst_structure_get_int (structure, "channels", &channels);
       
    71   if (!ret)
       
    72     return FALSE;
       
    73 
       
    74   outcaps = gst_caps_new_simple ("audio/x-raw-int",
       
    75       "width", G_TYPE_INT, 16,
       
    76       "depth", G_TYPE_INT, 16,
       
    77       "endianness", G_TYPE_INT, G_BYTE_ORDER,
       
    78       "signed", G_TYPE_BOOLEAN, TRUE,
       
    79       "rate", G_TYPE_INT, rate, "channels", G_TYPE_INT, channels, NULL);
       
    80   ret = gst_pad_set_caps (mulawdec->srcpad, outcaps);
       
    81   gst_caps_unref (outcaps);
       
    82 
       
    83   if (ret) {
       
    84     GST_DEBUG_OBJECT (mulawdec, "rate=%d, channels=%d", rate, channels);
       
    85     mulawdec->rate = rate;
       
    86     mulawdec->channels = channels;
       
    87   }
       
    88   return ret;
       
    89 }
       
    90 
       
    91 static GstCaps *
       
    92 mulawdec_getcaps (GstPad * pad)
       
    93 {
       
    94   GstMuLawDec *mulawdec;
       
    95   GstPad *otherpad;
       
    96   GstCaps *othercaps, *result;
       
    97   const GstCaps *templ;
       
    98   gchar *name;
       
    99   gint i;
       
   100 
       
   101   mulawdec = GST_MULAWDEC (GST_PAD_PARENT (pad));
       
   102 
       
   103   /* figure out the name of the caps we are going to return */
       
   104   if (pad == mulawdec->srcpad) {
       
   105     name = "audio/x-raw-int";
       
   106     otherpad = mulawdec->sinkpad;
       
   107   } else {
       
   108     name = "audio/x-mulaw";
       
   109     otherpad = mulawdec->srcpad;
       
   110   }
       
   111   /* get caps from the peer, this can return NULL when there is no peer */
       
   112   othercaps = gst_pad_peer_get_caps (otherpad);
       
   113 
       
   114   /* get the template caps to make sure we return something acceptable */
       
   115   templ = gst_pad_get_pad_template_caps (pad);
       
   116 
       
   117   if (othercaps) {
       
   118     /* there was a peer */
       
   119     othercaps = gst_caps_make_writable (othercaps);
       
   120 
       
   121     /* go through the caps and remove the fields we don't want */
       
   122     for (i = 0; i < gst_caps_get_size (othercaps); i++) {
       
   123       GstStructure *structure;
       
   124 
       
   125       structure = gst_caps_get_structure (othercaps, i);
       
   126 
       
   127       /* adjust the name */
       
   128       gst_structure_set_name (structure, name);
       
   129 
       
   130       if (pad == mulawdec->sinkpad) {
       
   131         /* remove the fields we don't want */
       
   132         gst_structure_remove_fields (structure, "width", "depth", "endianness",
       
   133             "signed", NULL);
       
   134       } else {
       
   135         /* add fixed fields */
       
   136         gst_structure_set (structure, "width", G_TYPE_INT, 16,
       
   137             "depth", G_TYPE_INT, 16,
       
   138             "endianness", G_TYPE_INT, G_BYTE_ORDER,
       
   139             "signed", G_TYPE_BOOLEAN, TRUE, NULL);
       
   140       }
       
   141     }
       
   142     /* filter against the allowed caps of the pad to return our result */
       
   143     result = gst_caps_intersect (othercaps, templ);
       
   144     gst_caps_unref (othercaps);
       
   145   } else {
       
   146     /* there was no peer, return the template caps */
       
   147     result = gst_caps_copy (templ);
       
   148   }
       
   149   return result;
       
   150 }
       
   151 
       
   152 GType
       
   153 gst_mulawdec_get_type (void)
       
   154 {
       
   155   static GType mulawdec_type = 0;
       
   156 
       
   157   if (!mulawdec_type) {
       
   158     static const GTypeInfo mulawdec_info = {
       
   159       sizeof (GstMuLawDecClass),
       
   160       (GBaseInitFunc) gst_mulawdec_base_init,
       
   161       NULL,
       
   162       (GClassInitFunc) gst_mulawdec_class_init,
       
   163       NULL,
       
   164       NULL,
       
   165       sizeof (GstMuLawDec),
       
   166       0,
       
   167       (GInstanceInitFunc) gst_mulawdec_init,
       
   168     };
       
   169 
       
   170     mulawdec_type =
       
   171         g_type_register_static (GST_TYPE_ELEMENT, "GstMuLawDec", &mulawdec_info,
       
   172         0);
       
   173   }
       
   174   return mulawdec_type;
       
   175 }
       
   176 
       
   177 static void
       
   178 gst_mulawdec_base_init (GstMuLawDecClass * klass)
       
   179 {
       
   180   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
       
   181   const GstElementDetails mulawdec_details =
       
   182       GST_ELEMENT_DETAILS ("Mu Law audio decoder",
       
   183       "Codec/Decoder/Audio",
       
   184       "Convert 8bit mu law to 16bit PCM",
       
   185       "Zaheer Abbas Merali <zaheerabbas at merali dot org>");
       
   186 
       
   187   gst_element_class_add_pad_template (element_class,
       
   188       gst_static_pad_template_get (&mulaw_dec_src_factory));
       
   189   gst_element_class_add_pad_template (element_class,
       
   190       gst_static_pad_template_get (&mulaw_dec_sink_factory));
       
   191   gst_element_class_set_details (element_class, &mulawdec_details);
       
   192 }
       
   193 
       
   194 static void
       
   195 gst_mulawdec_class_init (GstMuLawDecClass * klass)
       
   196 {
       
   197   GstElementClass *element_class = (GstElementClass *) klass;
       
   198 
       
   199   parent_class = g_type_class_peek_parent (klass);
       
   200 
       
   201   element_class->change_state = GST_DEBUG_FUNCPTR (gst_mulawdec_change_state);
       
   202 }
       
   203 
       
   204 static void
       
   205 gst_mulawdec_init (GstMuLawDec * mulawdec)
       
   206 {
       
   207   mulawdec->sinkpad =
       
   208       gst_pad_new_from_static_template (&mulaw_dec_sink_factory, "sink");
       
   209   gst_pad_set_setcaps_function (mulawdec->sinkpad, mulawdec_sink_setcaps);
       
   210   gst_pad_set_getcaps_function (mulawdec->sinkpad, mulawdec_getcaps);
       
   211   gst_pad_set_chain_function (mulawdec->sinkpad, gst_mulawdec_chain);
       
   212   gst_element_add_pad (GST_ELEMENT (mulawdec), mulawdec->sinkpad);
       
   213 
       
   214   mulawdec->srcpad =
       
   215       gst_pad_new_from_static_template (&mulaw_dec_src_factory, "src");
       
   216   gst_pad_use_fixed_caps (mulawdec->srcpad);
       
   217   gst_pad_set_getcaps_function (mulawdec->srcpad, mulawdec_getcaps);
       
   218   gst_element_add_pad (GST_ELEMENT (mulawdec), mulawdec->srcpad);
       
   219 }
       
   220 
       
   221 static GstFlowReturn
       
   222 gst_mulawdec_chain (GstPad * pad, GstBuffer * buffer)
       
   223 {
       
   224   GstMuLawDec *mulawdec;
       
   225   gint16 *linear_data;
       
   226   guint8 *mulaw_data;
       
   227   guint mulaw_size;
       
   228   GstBuffer *outbuf;
       
   229   GstFlowReturn ret;
       
   230 
       
   231   mulawdec = GST_MULAWDEC (GST_PAD_PARENT (pad));
       
   232 
       
   233   if (G_UNLIKELY (mulawdec->rate == 0))
       
   234     goto not_negotiated;
       
   235 
       
   236   mulaw_data = (guint8 *) GST_BUFFER_DATA (buffer);
       
   237   mulaw_size = GST_BUFFER_SIZE (buffer);
       
   238 
       
   239   ret =
       
   240       gst_pad_alloc_buffer_and_set_caps (mulawdec->srcpad,
       
   241       GST_BUFFER_OFFSET_NONE, mulaw_size * 2, GST_PAD_CAPS (mulawdec->srcpad),
       
   242       &outbuf);
       
   243   if (ret != GST_FLOW_OK)
       
   244     goto alloc_failed;
       
   245 
       
   246   linear_data = (gint16 *) GST_BUFFER_DATA (outbuf);
       
   247 
       
   248   /* copy discont flag */
       
   249   if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))
       
   250     GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
       
   251 
       
   252   GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buffer);
       
   253   if (GST_BUFFER_DURATION (outbuf) == GST_CLOCK_TIME_NONE)
       
   254     GST_BUFFER_DURATION (outbuf) = gst_util_uint64_scale_int (GST_SECOND,
       
   255         mulaw_size * 2, 2 * mulawdec->rate * mulawdec->channels);
       
   256   else
       
   257     GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buffer);
       
   258   gst_buffer_set_caps (outbuf, GST_PAD_CAPS (mulawdec->srcpad));
       
   259 
       
   260   mulaw_decode (mulaw_data, linear_data, mulaw_size);
       
   261 
       
   262   gst_buffer_unref (buffer);
       
   263 
       
   264   ret = gst_pad_push (mulawdec->srcpad, outbuf);
       
   265 
       
   266   return ret;
       
   267 
       
   268   /* ERRORS */
       
   269 not_negotiated:
       
   270   {
       
   271     GST_WARNING_OBJECT (mulawdec, "no input format set: not-negotiated");
       
   272     gst_buffer_unref (buffer);
       
   273     return GST_FLOW_NOT_NEGOTIATED;
       
   274   }
       
   275 alloc_failed:
       
   276   {
       
   277     GST_DEBUG_OBJECT (mulawdec, "pad alloc failed, flow: %s",
       
   278         gst_flow_get_name (ret));
       
   279     gst_buffer_unref (buffer);
       
   280     return ret;
       
   281   }
       
   282 }
       
   283 
       
   284 static GstStateChangeReturn
       
   285 gst_mulawdec_change_state (GstElement * element, GstStateChange transition)
       
   286 {
       
   287   GstStateChangeReturn ret;
       
   288   GstMuLawDec *dec = GST_MULAWDEC (element);
       
   289 
       
   290   switch (transition) {
       
   291     default:
       
   292       break;
       
   293   }
       
   294 
       
   295   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
       
   296   if (ret != GST_STATE_CHANGE_SUCCESS)
       
   297     return ret;
       
   298 
       
   299   switch (transition) {
       
   300     case GST_STATE_CHANGE_PAUSED_TO_READY:
       
   301       dec->rate = 0;
       
   302       dec->channels = 0;
       
   303       break;
       
   304     default:
       
   305       break;
       
   306   }
       
   307 
       
   308   return ret;
       
   309 }