gst_plugins_good/gst/law/mulaw-encode.c
changeset 27 d43ce56a1534
parent 23 29ecd5cb86b3
child 31 aec498aab1d3
equal deleted inserted replaced
23:29ecd5cb86b3 27:d43ce56a1534
     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-mulawenc
       
    21  *
       
    22  * This element encode 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-encode.h"
       
    30 #include "mulaw-conversion.h"
       
    31 
       
    32 extern GstStaticPadTemplate mulaw_enc_src_factory;
       
    33 extern GstStaticPadTemplate mulaw_enc_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_mulawenc_class_init (GstMuLawEncClass * klass);
       
    48 static void gst_mulawenc_base_init (GstMuLawEncClass * klass);
       
    49 static void gst_mulawenc_init (GstMuLawEnc * mulawenc);
       
    50 
       
    51 static GstFlowReturn gst_mulawenc_chain (GstPad * pad, GstBuffer * buffer);
       
    52 
       
    53 static GstElementClass *parent_class = NULL;
       
    54 
       
    55 /*static guint gst_stereo_signals[LAST_SIGNAL] = { 0 }; */
       
    56 
       
    57 static GstCaps *
       
    58 mulawenc_getcaps (GstPad * pad)
       
    59 {
       
    60   GstMuLawEnc *mulawenc;
       
    61   GstPad *otherpad;
       
    62   GstCaps *othercaps, *result;
       
    63   const GstCaps *templ;
       
    64   gchar *name;
       
    65   gint i;
       
    66 
       
    67   mulawenc = GST_MULAWENC (GST_PAD_PARENT (pad));
       
    68 
       
    69   /* figure out the name of the caps we are going to return */
       
    70   if (pad == mulawenc->srcpad) {
       
    71     name = "audio/x-mulaw";
       
    72     otherpad = mulawenc->sinkpad;
       
    73   } else {
       
    74     name = "audio/x-raw-int";
       
    75     otherpad = mulawenc->srcpad;
       
    76   }
       
    77   /* get caps from the peer, this can return NULL when there is no peer */
       
    78   othercaps = gst_pad_peer_get_caps (otherpad);
       
    79 
       
    80   /* get the template caps to make sure we return something acceptable */
       
    81   templ = gst_pad_get_pad_template_caps (pad);
       
    82 
       
    83   if (othercaps) {
       
    84     /* there was a peer */
       
    85     othercaps = gst_caps_make_writable (othercaps);
       
    86 
       
    87     /* go through the caps and remove the fields we don't want */
       
    88     for (i = 0; i < gst_caps_get_size (othercaps); i++) {
       
    89       GstStructure *structure;
       
    90 
       
    91       structure = gst_caps_get_structure (othercaps, i);
       
    92 
       
    93       /* adjust the name */
       
    94       gst_structure_set_name (structure, name);
       
    95 
       
    96       if (pad == mulawenc->srcpad) {
       
    97         /* remove the fields we don't want */
       
    98         gst_structure_remove_fields (structure, "width", "depth", "endianness",
       
    99             "signed", NULL);
       
   100       } else {
       
   101         /* add fixed fields */
       
   102         gst_structure_set (structure, "width", G_TYPE_INT, 16,
       
   103             "depth", G_TYPE_INT, 16,
       
   104             "endianness", G_TYPE_INT, G_BYTE_ORDER,
       
   105             "signed", G_TYPE_BOOLEAN, TRUE, NULL);
       
   106       }
       
   107     }
       
   108     /* filter against the allowed caps of the pad to return our result */
       
   109     result = gst_caps_intersect (othercaps, templ);
       
   110     gst_caps_unref (othercaps);
       
   111   } else {
       
   112     /* there was no peer, return the template caps */
       
   113     result = gst_caps_copy (templ);
       
   114   }
       
   115   return result;
       
   116 }
       
   117 
       
   118 static gboolean
       
   119 mulawenc_setcaps (GstPad * pad, GstCaps * caps)
       
   120 {
       
   121   GstMuLawEnc *mulawenc;
       
   122   GstPad *otherpad;
       
   123   GstStructure *structure;
       
   124   GstCaps *base_caps;
       
   125 
       
   126   mulawenc = GST_MULAWENC (gst_pad_get_parent (pad));
       
   127 
       
   128   structure = gst_caps_get_structure (caps, 0);
       
   129   gst_structure_get_int (structure, "channels", &mulawenc->channels);
       
   130   gst_structure_get_int (structure, "rate", &mulawenc->rate);
       
   131 
       
   132   if (pad == mulawenc->sinkpad) {
       
   133     otherpad = mulawenc->srcpad;
       
   134   } else {
       
   135     otherpad = mulawenc->sinkpad;
       
   136   }
       
   137   base_caps = gst_caps_copy (gst_pad_get_pad_template_caps (otherpad));
       
   138 
       
   139   structure = gst_caps_get_structure (base_caps, 0);
       
   140   gst_structure_set (structure, "rate", G_TYPE_INT, mulawenc->rate, NULL);
       
   141   gst_structure_set (structure, "channels", G_TYPE_INT, mulawenc->channels,
       
   142       NULL);
       
   143 
       
   144   gst_pad_set_caps (otherpad, base_caps);
       
   145 
       
   146   gst_object_unref (mulawenc);
       
   147   gst_caps_unref (base_caps);
       
   148 
       
   149   return TRUE;
       
   150 }
       
   151 
       
   152 GType
       
   153 gst_mulawenc_get_type (void)
       
   154 {
       
   155   static GType mulawenc_type = 0;
       
   156 
       
   157   if (!mulawenc_type) {
       
   158     static const GTypeInfo mulawenc_info = {
       
   159       sizeof (GstMuLawEncClass),
       
   160       (GBaseInitFunc) gst_mulawenc_base_init,
       
   161       NULL,
       
   162       (GClassInitFunc) gst_mulawenc_class_init,
       
   163       NULL,
       
   164       NULL,
       
   165       sizeof (GstMuLawEnc),
       
   166       0,
       
   167       (GInstanceInitFunc) gst_mulawenc_init,
       
   168     };
       
   169 
       
   170     mulawenc_type =
       
   171         g_type_register_static (GST_TYPE_ELEMENT, "GstMuLawEnc", &mulawenc_info,
       
   172         0);
       
   173   }
       
   174   return mulawenc_type;
       
   175 }
       
   176 
       
   177 static void
       
   178 gst_mulawenc_base_init (GstMuLawEncClass * klass)
       
   179 {
       
   180   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
       
   181   const GstElementDetails mulawenc_details =
       
   182       GST_ELEMENT_DETAILS ("Mu Law audio encoder",
       
   183       "Codec/Encoder/Audio",
       
   184       "Convert 16bit PCM to 8bit mu law",
       
   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_enc_src_factory));
       
   189   gst_element_class_add_pad_template (element_class,
       
   190       gst_static_pad_template_get (&mulaw_enc_sink_factory));
       
   191   gst_element_class_set_details (element_class, &mulawenc_details);
       
   192 }
       
   193 
       
   194 static void
       
   195 gst_mulawenc_class_init (GstMuLawEncClass * klass)
       
   196 {
       
   197   parent_class = g_type_class_peek_parent (klass);
       
   198 }
       
   199 
       
   200 static void
       
   201 gst_mulawenc_init (GstMuLawEnc * mulawenc)
       
   202 {
       
   203   mulawenc->sinkpad =
       
   204       gst_pad_new_from_static_template (&mulaw_enc_sink_factory, "sink");
       
   205   gst_pad_set_setcaps_function (mulawenc->sinkpad, mulawenc_setcaps);
       
   206   gst_pad_set_getcaps_function (mulawenc->sinkpad, mulawenc_getcaps);
       
   207   gst_pad_set_chain_function (mulawenc->sinkpad, gst_mulawenc_chain);
       
   208   gst_element_add_pad (GST_ELEMENT (mulawenc), mulawenc->sinkpad);
       
   209 
       
   210   mulawenc->srcpad =
       
   211       gst_pad_new_from_static_template (&mulaw_enc_src_factory, "src");
       
   212   gst_pad_set_setcaps_function (mulawenc->srcpad, mulawenc_setcaps);
       
   213   gst_pad_set_getcaps_function (mulawenc->srcpad, mulawenc_getcaps);
       
   214   gst_pad_use_fixed_caps (mulawenc->srcpad);
       
   215   gst_element_add_pad (GST_ELEMENT (mulawenc), mulawenc->srcpad);
       
   216 
       
   217   /* init rest */
       
   218   mulawenc->channels = 0;
       
   219   mulawenc->rate = 0;
       
   220 }
       
   221 
       
   222 static GstFlowReturn
       
   223 gst_mulawenc_chain (GstPad * pad, GstBuffer * buffer)
       
   224 {
       
   225   GstMuLawEnc *mulawenc;
       
   226   gint16 *linear_data;
       
   227   guint linear_size;
       
   228   guint8 *mulaw_data;
       
   229   guint mulaw_size;
       
   230   GstBuffer *outbuf;
       
   231   GstFlowReturn ret;
       
   232   GstClockTime timestamp, duration;
       
   233 
       
   234   mulawenc = GST_MULAWENC (gst_pad_get_parent (pad));
       
   235 
       
   236   if (!mulawenc->rate || !mulawenc->channels)
       
   237     goto not_negotiated;
       
   238 
       
   239   linear_data = (gint16 *) GST_BUFFER_DATA (buffer);
       
   240   linear_size = GST_BUFFER_SIZE (buffer);
       
   241 
       
   242   mulaw_size = linear_size / 2;
       
   243 
       
   244   timestamp = GST_BUFFER_TIMESTAMP (buffer);
       
   245   duration = GST_BUFFER_DURATION (buffer);
       
   246 
       
   247   ret = gst_pad_alloc_buffer_and_set_caps (mulawenc->srcpad,
       
   248       GST_BUFFER_OFFSET_NONE, mulaw_size, GST_PAD_CAPS (mulawenc->srcpad),
       
   249       &outbuf);
       
   250   if (ret != GST_FLOW_OK)
       
   251     goto alloc_failed;
       
   252 
       
   253   if (duration == -1) {
       
   254     duration = gst_util_uint64_scale_int (mulaw_size,
       
   255         GST_SECOND, mulawenc->rate * mulawenc->channels);
       
   256   }
       
   257 
       
   258   if (GST_BUFFER_SIZE (outbuf) < mulaw_size) {
       
   259     /* pad-alloc can suggest a smaller size */
       
   260     gst_buffer_unref (outbuf);
       
   261     outbuf = gst_buffer_new_and_alloc (mulaw_size);
       
   262   }
       
   263 
       
   264   mulaw_data = (guint8 *) GST_BUFFER_DATA (outbuf);
       
   265 
       
   266   /* copy discont flag */
       
   267   if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))
       
   268     GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
       
   269 
       
   270   GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
       
   271   GST_BUFFER_DURATION (outbuf) = duration;
       
   272 
       
   273   gst_buffer_set_caps (outbuf, GST_PAD_CAPS (mulawenc->srcpad));
       
   274 
       
   275   mulaw_encode (linear_data, mulaw_data, mulaw_size);
       
   276 
       
   277   gst_buffer_unref (buffer);
       
   278 
       
   279   ret = gst_pad_push (mulawenc->srcpad, outbuf);
       
   280 
       
   281 done:
       
   282   gst_object_unref (mulawenc);
       
   283 
       
   284   return ret;
       
   285 
       
   286 not_negotiated:
       
   287   {
       
   288     GST_DEBUG_OBJECT (mulawenc, "no format negotiated");
       
   289     ret = GST_FLOW_NOT_NEGOTIATED;
       
   290     gst_buffer_unref (buffer);
       
   291     goto done;
       
   292   }
       
   293 alloc_failed:
       
   294   {
       
   295     GST_DEBUG_OBJECT (mulawenc, "pad alloc failed");
       
   296     gst_buffer_unref (buffer);
       
   297     goto done;
       
   298   }
       
   299 }