LCOV - code coverage report
Current view: top level - ext/wavpack - gstwavpackenc.c (source / functions) Hit Total Coverage
Test: GStreamer Good Plug-ins 0.10.28.1 Lines: 260 450 57.8 %
Date: 2011-03-25 Functions: 18 21 85.7 %
Branches: 89 339 26.3 %

           Branch data     Line data    Source code
       1                 :            : /* GStreamer Wavpack encoder plugin
       2                 :            :  * Copyright (c) 2006 Sebastian Dröge <slomo@circular-chaos.org>
       3                 :            :  *
       4                 :            :  * gstwavpackdec.c: Wavpack audio encoder
       5                 :            :  *
       6                 :            :  * This library is free software; you can redistribute it and/or
       7                 :            :  * modify it under the terms of the GNU Library General Public
       8                 :            :  * License as published by the Free Software Foundation; either
       9                 :            :  * version 2 of the License, or (at your option) any later version.
      10                 :            :  *
      11                 :            :  * This library is distributed in the hope that it will be useful,
      12                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14                 :            :  * Library General Public License for more details.
      15                 :            :  *
      16                 :            :  * You should have received a copy of the GNU Library General Public
      17                 :            :  * License along with this library; if not, write to the
      18                 :            :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      19                 :            :  * Boston, MA 02111-1307, USA.
      20                 :            :  */
      21                 :            : 
      22                 :            : /**
      23                 :            :  * SECTION:element-wavpackenc
      24                 :            :  *
      25                 :            :  * WavpackEnc encodes raw audio into a framed Wavpack stream.
      26                 :            :  * <ulink url="http://www.wavpack.com/">Wavpack</ulink> is an open-source
      27                 :            :  * audio codec that features both lossless and lossy encoding.
      28                 :            :  *
      29                 :            :  * <refsect2>
      30                 :            :  * <title>Example launch line</title>
      31                 :            :  * |[
      32                 :            :  * gst-launch audiotestsrc num-buffers=500 ! audioconvert ! wavpackenc ! filesink location=sinewave.wv
      33                 :            :  * ]| This pipeline encodes audio from audiotestsrc into a Wavpack file. The audioconvert element is needed
      34                 :            :  * as the Wavpack encoder only accepts input with 32 bit width (and every depth between 1 and 32 bits).
      35                 :            :  * |[
      36                 :            :  * gst-launch cdda://1 ! audioconvert ! wavpackenc ! filesink location=track1.wv
      37                 :            :  * ]| This pipeline encodes audio from an audio CD into a Wavpack file using
      38                 :            :  * lossless encoding (the file output will be fairly large).
      39                 :            :  * |[
      40                 :            :  * gst-launch cdda://1 ! audioconvert ! wavpackenc bitrate=128000 ! filesink location=track1.wv
      41                 :            :  * ]| This pipeline encodes audio from an audio CD into a Wavpack file using
      42                 :            :  * lossy encoding at a certain bitrate (the file will be fairly small).
      43                 :            :  * </refsect2>
      44                 :            :  */
      45                 :            : 
      46                 :            : /*
      47                 :            :  * TODO: - add 32 bit float mode. CONFIG_FLOAT_DATA
      48                 :            :  */
      49                 :            : 
      50                 :            : #include <string.h>
      51                 :            : #include <gst/gst.h>
      52                 :            : #include <glib/gprintf.h>
      53                 :            : 
      54                 :            : #include <wavpack/wavpack.h>
      55                 :            : #include "gstwavpackenc.h"
      56                 :            : #include "gstwavpackcommon.h"
      57                 :            : 
      58                 :            : static GstFlowReturn gst_wavpack_enc_chain (GstPad * pad, GstBuffer * buffer);
      59                 :            : static gboolean gst_wavpack_enc_sink_set_caps (GstPad * pad, GstCaps * caps);
      60                 :            : static int gst_wavpack_enc_push_block (void *id, void *data, int32_t count);
      61                 :            : static gboolean gst_wavpack_enc_sink_event (GstPad * pad, GstEvent * event);
      62                 :            : static GstStateChangeReturn gst_wavpack_enc_change_state (GstElement * element,
      63                 :            :     GstStateChange transition);
      64                 :            : static void gst_wavpack_enc_set_property (GObject * object, guint prop_id,
      65                 :            :     const GValue * value, GParamSpec * pspec);
      66                 :            : static void gst_wavpack_enc_get_property (GObject * object, guint prop_id,
      67                 :            :     GValue * value, GParamSpec * pspec);
      68                 :            : 
      69                 :            : enum
      70                 :            : {
      71                 :            :   ARG_0,
      72                 :            :   ARG_MODE,
      73                 :            :   ARG_BITRATE,
      74                 :            :   ARG_BITSPERSAMPLE,
      75                 :            :   ARG_CORRECTION_MODE,
      76                 :            :   ARG_MD5,
      77                 :            :   ARG_EXTRA_PROCESSING,
      78                 :            :   ARG_JOINT_STEREO_MODE
      79                 :            : };
      80                 :            : 
      81                 :            : GST_DEBUG_CATEGORY_STATIC (gst_wavpack_enc_debug);
      82                 :            : #define GST_CAT_DEFAULT gst_wavpack_enc_debug
      83                 :            : 
      84                 :            : static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
      85                 :            :     GST_PAD_SINK,
      86                 :            :     GST_PAD_ALWAYS,
      87                 :            :     GST_STATIC_CAPS ("audio/x-raw-int, "
      88                 :            :         "width = (int) 32, "
      89                 :            :         "depth = (int) [ 1, 32], "
      90                 :            :         "endianness = (int) BYTE_ORDER, "
      91                 :            :         "channels = (int) [ 1, 8 ], "
      92                 :            :         "rate = (int) [ 6000, 192000 ]," "signed = (boolean) TRUE")
      93                 :            :     );
      94                 :            : 
      95                 :            : static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
      96                 :            :     GST_PAD_SRC,
      97                 :            :     GST_PAD_ALWAYS,
      98                 :            :     GST_STATIC_CAPS ("audio/x-wavpack, "
      99                 :            :         "width = (int) [ 1, 32 ], "
     100                 :            :         "channels = (int) [ 1, 2 ], "
     101                 :            :         "rate = (int) [ 6000, 192000 ], " "framed = (boolean) TRUE")
     102                 :            :     );
     103                 :            : 
     104                 :            : static GstStaticPadTemplate wvcsrc_factory = GST_STATIC_PAD_TEMPLATE ("wvcsrc",
     105                 :            :     GST_PAD_SRC,
     106                 :            :     GST_PAD_SOMETIMES,
     107                 :            :     GST_STATIC_CAPS ("audio/x-wavpack-correction, " "framed = (boolean) TRUE")
     108                 :            :     );
     109                 :            : 
     110                 :            : enum
     111                 :            : {
     112                 :            :   GST_WAVPACK_ENC_MODE_VERY_FAST = 0,
     113                 :            :   GST_WAVPACK_ENC_MODE_FAST,
     114                 :            :   GST_WAVPACK_ENC_MODE_DEFAULT,
     115                 :            :   GST_WAVPACK_ENC_MODE_HIGH,
     116                 :            :   GST_WAVPACK_ENC_MODE_VERY_HIGH
     117                 :            : };
     118                 :            : 
     119                 :            : #define GST_TYPE_WAVPACK_ENC_MODE (gst_wavpack_enc_mode_get_type ())
     120                 :            : static GType
     121                 :          6 : gst_wavpack_enc_mode_get_type (void)
     122                 :            : {
     123                 :            :   static GType qtype = 0;
     124                 :            : 
     125         [ +  - ]:          6 :   if (qtype == 0) {
     126                 :            :     static const GEnumValue values[] = {
     127                 :            : #if 0
     128                 :            :       /* Very Fast Compression is not supported yet, but will be supported
     129                 :            :        * in future wavpack versions */
     130                 :            :       {GST_WAVPACK_ENC_MODE_VERY_FAST, "Very Fast Compression", "veryfast"},
     131                 :            : #endif
     132                 :            :       {GST_WAVPACK_ENC_MODE_FAST, "Fast Compression", "fast"},
     133                 :            :       {GST_WAVPACK_ENC_MODE_DEFAULT, "Normal Compression", "normal"},
     134                 :            :       {GST_WAVPACK_ENC_MODE_HIGH, "High Compression", "high"},
     135                 :            : #ifndef WAVPACK_OLD_API
     136                 :            :       {GST_WAVPACK_ENC_MODE_VERY_HIGH, "Very High Compression", "veryhigh"},
     137                 :            : #endif
     138                 :            :       {0, NULL, NULL}
     139                 :            :     };
     140                 :            : 
     141                 :          6 :     qtype = g_enum_register_static ("GstWavpackEncMode", values);
     142                 :            :   }
     143                 :          6 :   return qtype;
     144                 :            : }
     145                 :            : 
     146                 :            : enum
     147                 :            : {
     148                 :            :   GST_WAVPACK_CORRECTION_MODE_OFF = 0,
     149                 :            :   GST_WAVPACK_CORRECTION_MODE_ON,
     150                 :            :   GST_WAVPACK_CORRECTION_MODE_OPTIMIZED
     151                 :            : };
     152                 :            : 
     153                 :            : #define GST_TYPE_WAVPACK_ENC_CORRECTION_MODE (gst_wavpack_enc_correction_mode_get_type ())
     154                 :            : static GType
     155                 :          6 : gst_wavpack_enc_correction_mode_get_type (void)
     156                 :            : {
     157                 :            :   static GType qtype = 0;
     158                 :            : 
     159         [ +  - ]:          6 :   if (qtype == 0) {
     160                 :            :     static const GEnumValue values[] = {
     161                 :            :       {GST_WAVPACK_CORRECTION_MODE_OFF, "Create no correction file", "off"},
     162                 :            :       {GST_WAVPACK_CORRECTION_MODE_ON, "Create correction file", "on"},
     163                 :            :       {GST_WAVPACK_CORRECTION_MODE_OPTIMIZED,
     164                 :            :           "Create optimized correction file", "optimized"},
     165                 :            :       {0, NULL, NULL}
     166                 :            :     };
     167                 :            : 
     168                 :          6 :     qtype = g_enum_register_static ("GstWavpackEncCorrectionMode", values);
     169                 :            :   }
     170                 :          6 :   return qtype;
     171                 :            : }
     172                 :            : 
     173                 :            : enum
     174                 :            : {
     175                 :            :   GST_WAVPACK_JS_MODE_AUTO = 0,
     176                 :            :   GST_WAVPACK_JS_MODE_LEFT_RIGHT,
     177                 :            :   GST_WAVPACK_JS_MODE_MID_SIDE
     178                 :            : };
     179                 :            : 
     180                 :            : #define GST_TYPE_WAVPACK_ENC_JOINT_STEREO_MODE (gst_wavpack_enc_joint_stereo_mode_get_type ())
     181                 :            : static GType
     182                 :          6 : gst_wavpack_enc_joint_stereo_mode_get_type (void)
     183                 :            : {
     184                 :            :   static GType qtype = 0;
     185                 :            : 
     186         [ +  - ]:          6 :   if (qtype == 0) {
     187                 :            :     static const GEnumValue values[] = {
     188                 :            :       {GST_WAVPACK_JS_MODE_AUTO, "auto", "auto"},
     189                 :            :       {GST_WAVPACK_JS_MODE_LEFT_RIGHT, "left/right", "leftright"},
     190                 :            :       {GST_WAVPACK_JS_MODE_MID_SIDE, "mid/side", "midside"},
     191                 :            :       {0, NULL, NULL}
     192                 :            :     };
     193                 :            : 
     194                 :          6 :     qtype = g_enum_register_static ("GstWavpackEncJSMode", values);
     195                 :            :   }
     196                 :          6 :   return qtype;
     197                 :            : }
     198                 :            : 
     199                 :            : static void
     200                 :         11 : _do_init (GType object_type)
     201                 :            : {
     202                 :         11 :   const GInterfaceInfo preset_interface_info = {
     203                 :            :     NULL,                       /* interface_init */
     204                 :            :     NULL,                       /* interface_finalize */
     205                 :            :     NULL                        /* interface_data */
     206                 :            :   };
     207                 :            : 
     208                 :         11 :   g_type_add_interface_static (object_type, GST_TYPE_PRESET,
     209                 :            :       &preset_interface_info);
     210                 :         11 : }
     211                 :            : 
     212         [ +  + ]:       2121 : GST_BOILERPLATE_FULL (GstWavpackEnc, gst_wavpack_enc, GstElement,
     213                 :       2121 :     GST_TYPE_ELEMENT, _do_init);
     214                 :            : 
     215                 :            : static void
     216                 :          6 : gst_wavpack_enc_base_init (gpointer klass)
     217                 :            : {
     218                 :          6 :   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
     219                 :            : 
     220                 :            :   /* add pad templates */
     221                 :          6 :   gst_element_class_add_pad_template (element_class,
     222                 :            :       gst_static_pad_template_get (&sink_factory));
     223                 :          6 :   gst_element_class_add_pad_template (element_class,
     224                 :            :       gst_static_pad_template_get (&src_factory));
     225                 :          6 :   gst_element_class_add_pad_template (element_class,
     226                 :            :       gst_static_pad_template_get (&wvcsrc_factory));
     227                 :            : 
     228                 :            :   /* set element details */
     229                 :          6 :   gst_element_class_set_details_simple (element_class, "Wavpack audio encoder",
     230                 :            :       "Codec/Encoder/Audio",
     231                 :            :       "Encodes audio with the Wavpack lossless/lossy audio codec",
     232                 :            :       "Sebastian Dröge <slomo@circular-chaos.org>");
     233                 :          6 : }
     234                 :            : 
     235                 :            : 
     236                 :            : static void
     237                 :          6 : gst_wavpack_enc_class_init (GstWavpackEncClass * klass)
     238                 :            : {
     239                 :          6 :   GObjectClass *gobject_class = (GObjectClass *) klass;
     240                 :          6 :   GstElementClass *gstelement_class = (GstElementClass *) klass;
     241                 :            : 
     242                 :          6 :   parent_class = g_type_class_peek_parent (klass);
     243                 :            : 
     244                 :            :   /* set state change handler */
     245                 :          6 :   gstelement_class->change_state =
     246                 :          6 :       GST_DEBUG_FUNCPTR (gst_wavpack_enc_change_state);
     247                 :            : 
     248                 :            :   /* set property handlers */
     249                 :          6 :   gobject_class->set_property = gst_wavpack_enc_set_property;
     250                 :          6 :   gobject_class->get_property = gst_wavpack_enc_get_property;
     251                 :            : 
     252                 :            :   /* install all properties */
     253                 :          6 :   g_object_class_install_property (gobject_class, ARG_MODE,
     254                 :            :       g_param_spec_enum ("mode", "Encoding mode",
     255                 :            :           "Speed versus compression tradeoff.",
     256                 :            :           GST_TYPE_WAVPACK_ENC_MODE, GST_WAVPACK_ENC_MODE_DEFAULT,
     257                 :            :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     258                 :          6 :   g_object_class_install_property (gobject_class, ARG_BITRATE,
     259                 :            :       g_param_spec_uint ("bitrate", "Bitrate",
     260                 :            :           "Try to encode with this average bitrate (bits/sec). "
     261                 :            :           "This enables lossy encoding, values smaller than 24000 disable it again.",
     262                 :            :           0, 9600000, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     263                 :          6 :   g_object_class_install_property (gobject_class, ARG_BITSPERSAMPLE,
     264                 :            :       g_param_spec_double ("bits-per-sample", "Bits per sample",
     265                 :            :           "Try to encode with this amount of bits per sample. "
     266                 :            :           "This enables lossy encoding, values smaller than 2.0 disable it again.",
     267                 :            :           0.0, 24.0, 0.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     268                 :          6 :   g_object_class_install_property (gobject_class, ARG_CORRECTION_MODE,
     269                 :            :       g_param_spec_enum ("correction-mode", "Correction stream mode",
     270                 :            :           "Use this mode for the correction stream. Only works in lossy mode!",
     271                 :            :           GST_TYPE_WAVPACK_ENC_CORRECTION_MODE, GST_WAVPACK_CORRECTION_MODE_OFF,
     272                 :            :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     273                 :          6 :   g_object_class_install_property (gobject_class, ARG_MD5,
     274                 :            :       g_param_spec_boolean ("md5", "MD5",
     275                 :            :           "Store MD5 hash of raw samples within the file.", FALSE,
     276                 :            :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     277                 :          6 :   g_object_class_install_property (gobject_class, ARG_EXTRA_PROCESSING,
     278                 :            :       g_param_spec_uint ("extra-processing", "Extra processing",
     279                 :            :           "Use better but slower filters for better compression/quality.",
     280                 :            :           0, 6, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     281                 :          6 :   g_object_class_install_property (gobject_class, ARG_JOINT_STEREO_MODE,
     282                 :            :       g_param_spec_enum ("joint-stereo-mode", "Joint-Stereo mode",
     283                 :            :           "Use this joint-stereo mode.", GST_TYPE_WAVPACK_ENC_JOINT_STEREO_MODE,
     284                 :            :           GST_WAVPACK_JS_MODE_AUTO,
     285                 :            :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     286                 :          6 : }
     287                 :            : 
     288                 :            : static void
     289                 :         14 : gst_wavpack_enc_reset (GstWavpackEnc * enc)
     290                 :            : {
     291                 :            :   /* close and free everything stream related if we already did something */
     292         [ -  + ]:         14 :   if (enc->wp_context) {
     293                 :          0 :     WavpackCloseFile (enc->wp_context);
     294                 :          0 :     enc->wp_context = NULL;
     295                 :            :   }
     296         [ +  + ]:         14 :   if (enc->wp_config) {
     297                 :          2 :     g_free (enc->wp_config);
     298                 :          2 :     enc->wp_config = NULL;
     299                 :            :   }
     300         [ +  + ]:         14 :   if (enc->first_block) {
     301                 :          2 :     g_free (enc->first_block);
     302                 :          2 :     enc->first_block = NULL;
     303                 :            :   }
     304                 :         14 :   enc->first_block_size = 0;
     305         [ -  + ]:         14 :   if (enc->md5_context) {
     306                 :          0 :     g_checksum_free (enc->md5_context);
     307                 :          0 :     enc->md5_context = NULL;
     308                 :            :   }
     309                 :            : 
     310         [ -  + ]:         14 :   if (enc->pending_buffer) {
     311                 :          0 :     gst_buffer_unref (enc->pending_buffer);
     312                 :          0 :     enc->pending_buffer = NULL;
     313                 :          0 :     enc->pending_offset = 0;
     314                 :            :   }
     315                 :            : 
     316                 :            :   /* reset the last returns to GST_FLOW_OK. This is only set to something else
     317                 :            :    * while WavpackPackSamples() or more specific gst_wavpack_enc_push_block()
     318                 :            :    * so not valid anymore */
     319                 :         14 :   enc->srcpad_last_return = enc->wvcsrcpad_last_return = GST_FLOW_OK;
     320                 :            : 
     321                 :            :   /* reset stream information */
     322                 :         14 :   enc->samplerate = 0;
     323                 :         14 :   enc->depth = 0;
     324                 :         14 :   enc->channels = 0;
     325                 :         14 :   enc->channel_mask = 0;
     326                 :         14 :   enc->need_channel_remap = FALSE;
     327                 :            : 
     328                 :         14 :   enc->timestamp_offset = GST_CLOCK_TIME_NONE;
     329                 :         14 :   enc->next_ts = GST_CLOCK_TIME_NONE;
     330                 :         14 : }
     331                 :            : 
     332                 :            : static void
     333                 :          5 : gst_wavpack_enc_init (GstWavpackEnc * enc, GstWavpackEncClass * gclass)
     334                 :            : {
     335                 :          5 :   enc->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink");
     336                 :          5 :   gst_pad_set_setcaps_function (enc->sinkpad,
     337                 :          5 :       GST_DEBUG_FUNCPTR (gst_wavpack_enc_sink_set_caps));
     338                 :          5 :   gst_pad_set_chain_function (enc->sinkpad,
     339                 :          5 :       GST_DEBUG_FUNCPTR (gst_wavpack_enc_chain));
     340                 :          5 :   gst_pad_set_event_function (enc->sinkpad,
     341                 :          5 :       GST_DEBUG_FUNCPTR (gst_wavpack_enc_sink_event));
     342                 :          5 :   gst_element_add_pad (GST_ELEMENT (enc), enc->sinkpad);
     343                 :            : 
     344                 :            :   /* setup src pad */
     345                 :          5 :   enc->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
     346                 :          5 :   gst_element_add_pad (GST_ELEMENT (enc), enc->srcpad);
     347                 :            : 
     348                 :            :   /* initialize object attributes */
     349                 :          5 :   enc->wp_config = NULL;
     350                 :          5 :   enc->wp_context = NULL;
     351                 :          5 :   enc->first_block = NULL;
     352                 :          5 :   enc->md5_context = NULL;
     353                 :          5 :   gst_wavpack_enc_reset (enc);
     354                 :            : 
     355                 :          5 :   enc->wv_id.correction = FALSE;
     356                 :          5 :   enc->wv_id.wavpack_enc = enc;
     357                 :          5 :   enc->wv_id.passthrough = FALSE;
     358                 :          5 :   enc->wvc_id.correction = TRUE;
     359                 :          5 :   enc->wvc_id.wavpack_enc = enc;
     360                 :          5 :   enc->wvc_id.passthrough = FALSE;
     361                 :            : 
     362                 :            :   /* set default values of params */
     363                 :          5 :   enc->mode = GST_WAVPACK_ENC_MODE_DEFAULT;
     364                 :          5 :   enc->bitrate = 0;
     365                 :          5 :   enc->bps = 0.0;
     366                 :          5 :   enc->correction_mode = GST_WAVPACK_CORRECTION_MODE_OFF;
     367                 :          5 :   enc->md5 = FALSE;
     368                 :          5 :   enc->extra_processing = 0;
     369                 :          5 :   enc->joint_stereo_mode = GST_WAVPACK_JS_MODE_AUTO;
     370                 :          5 : }
     371                 :            : 
     372                 :            : static gboolean
     373                 :          2 : gst_wavpack_enc_sink_set_caps (GstPad * pad, GstCaps * caps)
     374                 :            : {
     375                 :          2 :   GstWavpackEnc *enc = GST_WAVPACK_ENC (gst_pad_get_parent (pad));
     376                 :          2 :   GstStructure *structure = gst_caps_get_structure (caps, 0);
     377                 :            :   GstAudioChannelPosition *pos;
     378                 :            : 
     379   [ +  -  +  - ]:          4 :   if (!gst_structure_get_int (structure, "channels", &enc->channels) ||
     380         [ -  + ]:          4 :       !gst_structure_get_int (structure, "rate", &enc->samplerate) ||
     381                 :          2 :       !gst_structure_get_int (structure, "depth", &enc->depth)) {
     382 [ #  # ][ #  # ]:          0 :     GST_ELEMENT_ERROR (enc, LIBRARY, INIT, (NULL),
         [ #  # ][ #  # ]
     383                 :            :         ("got invalid caps: %" GST_PTR_FORMAT, caps));
     384                 :          0 :     gst_object_unref (enc);
     385                 :          0 :     return FALSE;
     386                 :            :   }
     387                 :            : 
     388                 :          2 :   pos = gst_audio_get_channel_positions (structure);
     389                 :            :   /* If one channel is NONE they'll be all undefined */
     390 [ +  - ][ -  + ]:          2 :   if (pos != NULL && pos[0] == GST_AUDIO_CHANNEL_POSITION_NONE) {
     391                 :          0 :     g_free (pos);
     392                 :          0 :     pos = NULL;
     393                 :            :   }
     394                 :            : 
     395         [ -  + ]:          2 :   if (pos == NULL) {
     396 [ #  # ][ #  # ]:          0 :     GST_ELEMENT_ERROR (enc, STREAM, FORMAT, (NULL),
         [ #  # ][ #  # ]
     397                 :            :         ("input has no valid channel layout"));
     398                 :            : 
     399                 :          0 :     gst_object_unref (enc);
     400                 :          0 :     return FALSE;
     401                 :            :   }
     402                 :            : 
     403                 :          2 :   enc->channel_mask =
     404                 :          2 :       gst_wavpack_get_channel_mask_from_positions (pos, enc->channels);
     405                 :          2 :   enc->need_channel_remap =
     406                 :          2 :       gst_wavpack_set_channel_mapping (pos, enc->channels,
     407                 :          2 :       enc->channel_mapping);
     408                 :          2 :   g_free (pos);
     409                 :            : 
     410                 :            :   /* set fixed src pad caps now that we know what we will get */
     411                 :          2 :   caps = gst_caps_new_simple ("audio/x-wavpack",
     412                 :            :       "channels", G_TYPE_INT, enc->channels,
     413                 :            :       "rate", G_TYPE_INT, enc->samplerate,
     414                 :            :       "width", G_TYPE_INT, enc->depth, "framed", G_TYPE_BOOLEAN, TRUE, NULL);
     415                 :            : 
     416         [ -  + ]:          2 :   if (!gst_wavpack_set_channel_layout (caps, enc->channel_mask))
     417         [ #  # ]:          0 :     GST_WARNING_OBJECT (enc, "setting channel layout failed");
     418                 :            : 
     419         [ -  + ]:          2 :   if (!gst_pad_set_caps (enc->srcpad, caps)) {
     420 [ #  # ][ #  # ]:          0 :     GST_ELEMENT_ERROR (enc, LIBRARY, INIT, (NULL),
         [ #  # ][ #  # ]
     421                 :            :         ("setting caps failed: %" GST_PTR_FORMAT, caps));
     422                 :          0 :     gst_caps_unref (caps);
     423                 :          0 :     gst_object_unref (enc);
     424                 :          0 :     return FALSE;
     425                 :            :   }
     426                 :          2 :   gst_pad_use_fixed_caps (enc->srcpad);
     427                 :            : 
     428                 :          2 :   gst_caps_unref (caps);
     429                 :          2 :   gst_object_unref (enc);
     430                 :          2 :   return TRUE;
     431                 :            : }
     432                 :            : 
     433                 :            : static void
     434                 :          2 : gst_wavpack_enc_set_wp_config (GstWavpackEnc * enc)
     435                 :            : {
     436                 :          2 :   enc->wp_config = g_new0 (WavpackConfig, 1);
     437                 :            :   /* set general stream informations in the WavpackConfig */
     438                 :          2 :   enc->wp_config->bytes_per_sample = GST_ROUND_UP_8 (enc->depth) / 8;
     439                 :          2 :   enc->wp_config->bits_per_sample = enc->depth;
     440                 :          2 :   enc->wp_config->num_channels = enc->channels;
     441                 :          2 :   enc->wp_config->channel_mask = enc->channel_mask;
     442                 :          2 :   enc->wp_config->sample_rate = enc->samplerate;
     443                 :            : 
     444                 :            :   /*
     445                 :            :    * Set parameters in WavpackConfig
     446                 :            :    */
     447                 :            : 
     448                 :            :   /* Encoding mode */
     449   [ -  +  -  -  :          2 :   switch (enc->mode) {
                      - ]
     450                 :            : #if 0
     451                 :            :     case GST_WAVPACK_ENC_MODE_VERY_FAST:
     452                 :            :       enc->wp_config->flags |= CONFIG_VERY_FAST_FLAG;
     453                 :            :       enc->wp_config->flags |= CONFIG_FAST_FLAG;
     454                 :            :       break;
     455                 :            : #endif
     456                 :            :     case GST_WAVPACK_ENC_MODE_FAST:
     457                 :          0 :       enc->wp_config->flags |= CONFIG_FAST_FLAG;
     458                 :          0 :       break;
     459                 :            :     case GST_WAVPACK_ENC_MODE_DEFAULT:
     460                 :          2 :       break;
     461                 :            :     case GST_WAVPACK_ENC_MODE_HIGH:
     462                 :          0 :       enc->wp_config->flags |= CONFIG_HIGH_FLAG;
     463                 :          0 :       break;
     464                 :            : #ifndef WAVPACK_OLD_API
     465                 :            :     case GST_WAVPACK_ENC_MODE_VERY_HIGH:
     466                 :          0 :       enc->wp_config->flags |= CONFIG_HIGH_FLAG;
     467                 :          0 :       enc->wp_config->flags |= CONFIG_VERY_HIGH_FLAG;
     468                 :          0 :       break;
     469                 :            : #endif
     470                 :            :   }
     471                 :            : 
     472                 :            :   /* Bitrate, enables lossy mode */
     473         [ -  + ]:          2 :   if (enc->bitrate) {
     474                 :          0 :     enc->wp_config->flags |= CONFIG_HYBRID_FLAG;
     475                 :          0 :     enc->wp_config->flags |= CONFIG_BITRATE_KBPS;
     476                 :          0 :     enc->wp_config->bitrate = enc->bitrate / 1000.0;
     477         [ -  + ]:          2 :   } else if (enc->bps) {
     478                 :          0 :     enc->wp_config->flags |= CONFIG_HYBRID_FLAG;
     479                 :          0 :     enc->wp_config->bitrate = enc->bps;
     480                 :            :   }
     481                 :            : 
     482                 :            :   /* Correction Mode, only in lossy mode */
     483         [ -  + ]:          2 :   if (enc->wp_config->flags & CONFIG_HYBRID_FLAG) {
     484         [ #  # ]:          0 :     if (enc->correction_mode > GST_WAVPACK_CORRECTION_MODE_OFF) {
     485                 :          0 :       GstCaps *caps = gst_caps_new_simple ("audio/x-wavpack-correction",
     486                 :            :           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
     487                 :            : 
     488                 :          0 :       enc->wvcsrcpad =
     489                 :          0 :           gst_pad_new_from_static_template (&wvcsrc_factory, "wvcsrc");
     490                 :            : 
     491                 :            :       /* try to add correction src pad, don't set correction mode on failure */
     492         [ #  # ]:          0 :       GST_DEBUG_OBJECT (enc, "Adding correction pad with caps %"
     493                 :            :           GST_PTR_FORMAT, caps);
     494         [ #  # ]:          0 :       if (!gst_pad_set_caps (enc->wvcsrcpad, caps)) {
     495                 :          0 :         enc->correction_mode = 0;
     496         [ #  # ]:          0 :         GST_WARNING_OBJECT (enc, "setting correction caps failed");
     497                 :            :       } else {
     498                 :          0 :         gst_pad_use_fixed_caps (enc->wvcsrcpad);
     499                 :          0 :         gst_pad_set_active (enc->wvcsrcpad, TRUE);
     500                 :          0 :         gst_element_add_pad (GST_ELEMENT (enc), enc->wvcsrcpad);
     501                 :          0 :         enc->wp_config->flags |= CONFIG_CREATE_WVC;
     502         [ #  # ]:          0 :         if (enc->correction_mode == GST_WAVPACK_CORRECTION_MODE_OPTIMIZED) {
     503                 :          0 :           enc->wp_config->flags |= CONFIG_OPTIMIZE_WVC;
     504                 :            :         }
     505                 :            :       }
     506                 :          0 :       gst_caps_unref (caps);
     507                 :            :     }
     508                 :            :   } else {
     509         [ -  + ]:          2 :     if (enc->correction_mode > GST_WAVPACK_CORRECTION_MODE_OFF) {
     510                 :          0 :       enc->correction_mode = 0;
     511         [ #  # ]:          0 :       GST_WARNING_OBJECT (enc, "setting correction mode only has "
     512                 :            :           "any effect if a bitrate is provided.");
     513                 :            :     }
     514                 :            :   }
     515                 :          2 :   gst_element_no_more_pads (GST_ELEMENT (enc));
     516                 :            : 
     517                 :            :   /* MD5, setup MD5 context */
     518 [ -  + ][ #  # ]:          2 :   if ((enc->md5) && !(enc->md5_context)) {
     519                 :          0 :     enc->wp_config->flags |= CONFIG_MD5_CHECKSUM;
     520                 :          0 :     enc->md5_context = g_checksum_new (G_CHECKSUM_MD5);
     521                 :            :   }
     522                 :            : 
     523                 :            :   /* Extra encode processing */
     524         [ -  + ]:          2 :   if (enc->extra_processing) {
     525                 :          0 :     enc->wp_config->flags |= CONFIG_EXTRA_MODE;
     526                 :          0 :     enc->wp_config->xmode = enc->extra_processing;
     527                 :            :   }
     528                 :            : 
     529                 :            :   /* Joint stereo mode */
     530   [ +  -  -  - ]:          2 :   switch (enc->joint_stereo_mode) {
     531                 :            :     case GST_WAVPACK_JS_MODE_AUTO:
     532                 :          2 :       break;
     533                 :            :     case GST_WAVPACK_JS_MODE_LEFT_RIGHT:
     534                 :          0 :       enc->wp_config->flags |= CONFIG_JOINT_OVERRIDE;
     535                 :          0 :       enc->wp_config->flags &= ~CONFIG_JOINT_STEREO;
     536                 :          0 :       break;
     537                 :            :     case GST_WAVPACK_JS_MODE_MID_SIDE:
     538                 :          0 :       enc->wp_config->flags |= (CONFIG_JOINT_OVERRIDE | CONFIG_JOINT_STEREO);
     539                 :          0 :       break;
     540                 :            :   }
     541                 :          2 : }
     542                 :            : 
     543                 :            : static int
     544                 :         50 : gst_wavpack_enc_push_block (void *id, void *data, int32_t count)
     545                 :            : {
     546                 :         50 :   GstWavpackEncWriteID *wid = (GstWavpackEncWriteID *) id;
     547                 :         50 :   GstWavpackEnc *enc = GST_WAVPACK_ENC (wid->wavpack_enc);
     548                 :            :   GstFlowReturn *flow;
     549                 :            :   GstBuffer *buffer;
     550                 :            :   GstPad *pad;
     551                 :         50 :   guchar *block = (guchar *) data;
     552                 :            : 
     553         [ -  + ]:         50 :   pad = (wid->correction) ? enc->wvcsrcpad : enc->srcpad;
     554                 :         50 :   flow =
     555         [ -  + ]:         50 :       (wid->correction) ? &enc->wvcsrcpad_last_return : &enc->
     556                 :            :       srcpad_last_return;
     557                 :            : 
     558                 :         50 :   *flow = gst_pad_alloc_buffer_and_set_caps (pad, GST_BUFFER_OFFSET_NONE,
     559                 :            :       count, GST_PAD_CAPS (pad), &buffer);
     560                 :            : 
     561         [ -  + ]:         50 :   if (*flow != GST_FLOW_OK) {
     562 [ #  # ][ #  # ]:          0 :     GST_WARNING_OBJECT (enc, "flow on %s:%s = %s",
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     563                 :            :         GST_DEBUG_PAD_NAME (pad), gst_flow_get_name (*flow));
     564                 :          0 :     return FALSE;
     565                 :            :   }
     566                 :            : 
     567                 :         50 :   g_memmove (GST_BUFFER_DATA (buffer), block, count);
     568                 :            : 
     569 [ +  - ][ +  - ]:        100 :   if (count > sizeof (WavpackHeader) && memcmp (block, "wvpk", 4) == 0) {
     570                 :            :     /* if it's a Wavpack block set buffer timestamp and duration, etc */
     571                 :            :     WavpackHeader wph;
     572                 :            : 
     573 [ -  + ][ #  # ]:         50 :     GST_LOG_OBJECT (enc, "got %d bytes of encoded wavpack %sdata",
     574                 :            :         count, (wid->correction) ? "correction " : "");
     575                 :            : 
     576                 :         50 :     gst_wavpack_read_header (&wph, block);
     577                 :            : 
     578                 :            :     /* Only set when pushing the first buffer again, in that case
     579                 :            :      * we don't want to delay the buffer or push newsegment events
     580                 :            :      */
     581         [ +  + ]:         50 :     if (!wid->passthrough) {
     582                 :            :       /* Only push complete blocks */
     583         [ +  - ]:         48 :       if (enc->pending_buffer == NULL) {
     584                 :         48 :         enc->pending_buffer = buffer;
     585                 :         48 :         enc->pending_offset = wph.block_index;
     586         [ #  # ]:          0 :       } else if (enc->pending_offset == wph.block_index) {
     587                 :          0 :         enc->pending_buffer = gst_buffer_join (enc->pending_buffer, buffer);
     588                 :            :       } else {
     589         [ #  # ]:          0 :         GST_ERROR ("Got incomplete block, dropping");
     590                 :          0 :         gst_buffer_unref (enc->pending_buffer);
     591                 :          0 :         enc->pending_buffer = buffer;
     592                 :          0 :         enc->pending_offset = wph.block_index;
     593                 :            :       }
     594                 :            : 
     595         [ -  + ]:         48 :       if (!(wph.flags & FINAL_BLOCK))
     596                 :          0 :         return TRUE;
     597                 :            : 
     598                 :         48 :       buffer = enc->pending_buffer;
     599                 :         48 :       enc->pending_buffer = NULL;
     600                 :         48 :       enc->pending_offset = 0;
     601                 :            : 
     602                 :            :       /* if it's the first wavpack block, send a NEW_SEGMENT event */
     603         [ +  + ]:         48 :       if (wph.block_index == 0) {
     604                 :          2 :         gst_pad_push_event (pad,
     605                 :            :             gst_event_new_new_segment (FALSE,
     606                 :            :                 1.0, GST_FORMAT_TIME, 0, GST_BUFFER_OFFSET_NONE, 0));
     607                 :            : 
     608                 :            :         /* save header for later reference, so we can re-send it later on
     609                 :            :          * EOS with fixed up values for total sample count etc. */
     610 [ +  - ][ +  - ]:          2 :         if (enc->first_block == NULL && !wid->correction) {
     611                 :          2 :           enc->first_block =
     612                 :          2 :               g_memdup (GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer));
     613                 :          2 :           enc->first_block_size = GST_BUFFER_SIZE (buffer);
     614                 :            :         }
     615                 :            :       }
     616                 :            :     }
     617                 :            : 
     618                 :            :     /* set buffer timestamp, duration, offset, offset_end from
     619                 :            :      * the wavpack header */
     620                 :        100 :     GST_BUFFER_TIMESTAMP (buffer) = enc->timestamp_offset +
     621                 :         50 :         gst_util_uint64_scale_int (GST_SECOND, wph.block_index,
     622                 :            :         enc->samplerate);
     623                 :        100 :     GST_BUFFER_DURATION (buffer) =
     624                 :         50 :         gst_util_uint64_scale_int (GST_SECOND, wph.block_samples,
     625                 :            :         enc->samplerate);
     626                 :         50 :     GST_BUFFER_OFFSET (buffer) = wph.block_index;
     627                 :         50 :     GST_BUFFER_OFFSET_END (buffer) = wph.block_index + wph.block_samples;
     628                 :            :   } else {
     629                 :            :     /* if it's something else set no timestamp and duration on the buffer */
     630         [ #  # ]:          0 :     GST_DEBUG_OBJECT (enc, "got %d bytes of unknown data", count);
     631                 :            : 
     632                 :          0 :     GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
     633                 :          0 :     GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
     634                 :            :   }
     635                 :            : 
     636                 :            :   /* push the buffer and forward errors */
     637         [ -  + ]:         50 :   GST_DEBUG_OBJECT (enc, "pushing buffer with %d bytes",
     638                 :            :       GST_BUFFER_SIZE (buffer));
     639                 :         50 :   *flow = gst_pad_push (pad, buffer);
     640                 :            : 
     641         [ -  + ]:         50 :   if (*flow != GST_FLOW_OK) {
     642 [ #  # ][ #  # ]:          0 :     GST_WARNING_OBJECT (enc, "flow on %s:%s = %s",
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     643                 :            :         GST_DEBUG_PAD_NAME (pad), gst_flow_get_name (*flow));
     644                 :          0 :     return FALSE;
     645                 :            :   }
     646                 :            : 
     647                 :         50 :   return TRUE;
     648                 :            : }
     649                 :            : 
     650                 :            : static void
     651                 :          0 : gst_wavpack_enc_fix_channel_order (GstWavpackEnc * enc, gint32 * data,
     652                 :            :     gint nsamples)
     653                 :            : {
     654                 :            :   gint i, j;
     655                 :            :   gint32 tmp[8];
     656                 :            : 
     657         [ #  # ]:          0 :   for (i = 0; i < nsamples / enc->channels; i++) {
     658         [ #  # ]:          0 :     for (j = 0; j < enc->channels; j++) {
     659                 :          0 :       tmp[enc->channel_mapping[j]] = data[j];
     660                 :            :     }
     661         [ #  # ]:          0 :     for (j = 0; j < enc->channels; j++) {
     662                 :          0 :       data[j] = tmp[j];
     663                 :            :     }
     664                 :          0 :     data += enc->channels;
     665                 :            :   }
     666                 :          0 : }
     667                 :            : 
     668                 :            : static GstFlowReturn
     669                 :       2001 : gst_wavpack_enc_chain (GstPad * pad, GstBuffer * buf)
     670                 :            : {
     671                 :       2001 :   GstWavpackEnc *enc = GST_WAVPACK_ENC (gst_pad_get_parent (pad));
     672                 :       2001 :   uint32_t sample_count = GST_BUFFER_SIZE (buf) / 4;
     673                 :            :   GstFlowReturn ret;
     674                 :            : 
     675                 :            :   /* reset the last returns to GST_FLOW_OK. This is only set to something else
     676                 :            :    * while WavpackPackSamples() or more specific gst_wavpack_enc_push_block()
     677                 :            :    * so not valid anymore */
     678                 :       2001 :   enc->srcpad_last_return = enc->wvcsrcpad_last_return = GST_FLOW_OK;
     679                 :            : 
     680         [ -  + ]:       2001 :   GST_DEBUG ("got %u raw samples", sample_count);
     681                 :            : 
     682                 :            :   /* check if we already have a valid WavpackContext, otherwise make one */
     683         [ +  + ]:       2001 :   if (!enc->wp_context) {
     684                 :            :     /* create raw context */
     685                 :          2 :     enc->wp_context =
     686         [ -  + ]:          2 :         WavpackOpenFileOutput (gst_wavpack_enc_push_block, &enc->wv_id,
     687                 :          2 :         (enc->correction_mode > 0) ? &enc->wvc_id : NULL);
     688         [ -  + ]:          2 :     if (!enc->wp_context) {
     689 [ #  # ][ #  # ]:          0 :       GST_ELEMENT_ERROR (enc, LIBRARY, INIT, (NULL),
         [ #  # ][ #  # ]
     690                 :            :           ("error creating Wavpack context"));
     691                 :          0 :       gst_object_unref (enc);
     692                 :          0 :       gst_buffer_unref (buf);
     693                 :          0 :       return GST_FLOW_ERROR;
     694                 :            :     }
     695                 :            : 
     696                 :            :     /* set the WavpackConfig according to our parameters */
     697                 :          2 :     gst_wavpack_enc_set_wp_config (enc);
     698                 :            : 
     699                 :            :     /* set the configuration to the context now that we know everything
     700                 :            :      * and initialize the encoder */
     701         [ +  - ]:          2 :     if (!WavpackSetConfiguration (enc->wp_context,
     702                 :            :             enc->wp_config, (uint32_t) (-1))
     703         [ -  + ]:          2 :         || !WavpackPackInit (enc->wp_context)) {
     704 [ #  # ][ #  # ]:          0 :       GST_ELEMENT_ERROR (enc, LIBRARY, SETTINGS, (NULL),
         [ #  # ][ #  # ]
     705                 :            :           ("error setting up wavpack encoding context"));
     706                 :          0 :       WavpackCloseFile (enc->wp_context);
     707                 :          0 :       gst_object_unref (enc);
     708                 :          0 :       gst_buffer_unref (buf);
     709                 :          0 :       return GST_FLOW_ERROR;
     710                 :            :     }
     711         [ -  + ]:          2 :     GST_DEBUG ("setup of encoding context successfull");
     712                 :            :   }
     713                 :            : 
     714                 :            :   /* Save the timestamp of the first buffer. This will be later
     715                 :            :    * used as offset for all following buffers */
     716         [ +  + ]:       2001 :   if (enc->timestamp_offset == GST_CLOCK_TIME_NONE) {
     717         [ +  - ]:          2 :     if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
     718                 :          2 :       enc->timestamp_offset = GST_BUFFER_TIMESTAMP (buf);
     719                 :          2 :       enc->next_ts = GST_BUFFER_TIMESTAMP (buf);
     720                 :            :     } else {
     721                 :          0 :       enc->timestamp_offset = 0;
     722                 :          0 :       enc->next_ts = 0;
     723                 :            :     }
     724                 :            :   }
     725                 :            : 
     726                 :            :   /* Check if we have a continous stream, if not drop some samples or the buffer or
     727                 :            :    * insert some silence samples */
     728 [ +  - ][ -  + ]:       2001 :   if (enc->next_ts != GST_CLOCK_TIME_NONE &&
     729                 :       2001 :       GST_BUFFER_TIMESTAMP (buf) < enc->next_ts) {
     730                 :          0 :     guint64 diff = enc->next_ts - GST_BUFFER_TIMESTAMP (buf);
     731                 :            :     guint64 diff_bytes;
     732                 :            : 
     733 [ #  # ][ #  # ]:          0 :     GST_WARNING_OBJECT (enc, "Buffer is older than previous "
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     734                 :            :         "timestamp + duration (%" GST_TIME_FORMAT "< %" GST_TIME_FORMAT
     735                 :            :         "), cannot handle. Clipping buffer.",
     736                 :            :         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
     737                 :            :         GST_TIME_ARGS (enc->next_ts));
     738                 :            : 
     739                 :          0 :     diff_bytes =
     740                 :          0 :         GST_CLOCK_TIME_TO_FRAMES (diff, enc->samplerate) * enc->channels * 2;
     741         [ #  # ]:          0 :     if (diff_bytes >= GST_BUFFER_SIZE (buf)) {
     742                 :          0 :       gst_buffer_unref (buf);
     743                 :          0 :       return GST_FLOW_OK;
     744                 :            :     }
     745                 :          0 :     buf = gst_buffer_make_metadata_writable (buf);
     746                 :          0 :     GST_BUFFER_DATA (buf) += diff_bytes;
     747                 :          0 :     GST_BUFFER_SIZE (buf) -= diff_bytes;
     748                 :            : 
     749                 :          0 :     GST_BUFFER_TIMESTAMP (buf) += diff;
     750         [ #  # ]:          0 :     if (GST_BUFFER_DURATION_IS_VALID (buf))
     751                 :          0 :       GST_BUFFER_DURATION (buf) -= diff;
     752                 :            :   }
     753                 :            : 
     754                 :            :   /* Allow a diff of at most 5 ms */
     755         [ +  - ]:       2001 :   if (enc->next_ts != GST_CLOCK_TIME_NONE
     756         [ +  - ]:       2001 :       && GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
     757 [ -  + ][ #  # ]:       2001 :     if (GST_BUFFER_TIMESTAMP (buf) != enc->next_ts &&
     758                 :          0 :         GST_BUFFER_TIMESTAMP (buf) - enc->next_ts > 5 * GST_MSECOND) {
     759         [ #  # ]:          0 :       GST_WARNING_OBJECT (enc,
     760                 :            :           "Discontinuity detected: %" G_GUINT64_FORMAT " > %" G_GUINT64_FORMAT,
     761                 :            :           GST_BUFFER_TIMESTAMP (buf) - enc->next_ts, 5 * GST_MSECOND);
     762                 :            : 
     763                 :          0 :       WavpackFlushSamples (enc->wp_context);
     764                 :          0 :       enc->timestamp_offset += (GST_BUFFER_TIMESTAMP (buf) - enc->next_ts);
     765                 :            :     }
     766                 :            :   }
     767                 :            : 
     768         [ +  - ]:       2001 :   if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)
     769         [ +  + ]:       2001 :       && GST_BUFFER_DURATION_IS_VALID (buf))
     770                 :       2000 :     enc->next_ts = GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf);
     771                 :            :   else
     772                 :          1 :     enc->next_ts = GST_CLOCK_TIME_NONE;
     773                 :            : 
     774         [ -  + ]:       2001 :   if (enc->need_channel_remap) {
     775                 :          0 :     buf = gst_buffer_make_writable (buf);
     776                 :          0 :     gst_wavpack_enc_fix_channel_order (enc, (gint32 *) GST_BUFFER_DATA (buf),
     777                 :            :         sample_count);
     778                 :            :   }
     779                 :            : 
     780                 :            :   /* if we want to append the MD5 sum to the stream update it here
     781                 :            :    * with the current raw samples */
     782         [ -  + ]:       2001 :   if (enc->md5) {
     783                 :          0 :     g_checksum_update (enc->md5_context, GST_BUFFER_DATA (buf),
     784                 :          0 :         GST_BUFFER_SIZE (buf));
     785                 :            :   }
     786                 :            : 
     787                 :            :   /* encode and handle return values from encoding */
     788         [ +  - ]:       2001 :   if (WavpackPackSamples (enc->wp_context, (int32_t *) GST_BUFFER_DATA (buf),
     789                 :       2001 :           sample_count / enc->channels)) {
     790         [ -  + ]:       2001 :     GST_DEBUG ("encoding samples successful");
     791                 :       2001 :     ret = GST_FLOW_OK;
     792                 :            :   } else {
     793 [ #  # ][ #  # ]:          0 :     if ((enc->srcpad_last_return == GST_FLOW_RESEND) ||
     794                 :          0 :         (enc->wvcsrcpad_last_return == GST_FLOW_RESEND)) {
     795                 :          0 :       ret = GST_FLOW_RESEND;
     796 [ #  # ][ #  # ]:          0 :     } else if ((enc->srcpad_last_return == GST_FLOW_OK) ||
     797                 :          0 :         (enc->wvcsrcpad_last_return == GST_FLOW_OK)) {
     798                 :          0 :       ret = GST_FLOW_OK;
     799 [ #  # ][ #  # ]:          0 :     } else if ((enc->srcpad_last_return == GST_FLOW_NOT_LINKED) &&
     800                 :          0 :         (enc->wvcsrcpad_last_return == GST_FLOW_NOT_LINKED)) {
     801                 :          0 :       ret = GST_FLOW_NOT_LINKED;
     802 [ #  # ][ #  # ]:          0 :     } else if ((enc->srcpad_last_return == GST_FLOW_WRONG_STATE) &&
     803                 :          0 :         (enc->wvcsrcpad_last_return == GST_FLOW_WRONG_STATE)) {
     804                 :          0 :       ret = GST_FLOW_WRONG_STATE;
     805                 :            :     } else {
     806 [ #  # ][ #  # ]:          0 :       GST_ELEMENT_ERROR (enc, LIBRARY, ENCODE, (NULL),
         [ #  # ][ #  # ]
     807                 :            :           ("encoding samples failed"));
     808                 :          0 :       ret = GST_FLOW_ERROR;
     809                 :            :     }
     810                 :            :   }
     811                 :            : 
     812                 :       2001 :   gst_buffer_unref (buf);
     813                 :       2001 :   gst_object_unref (enc);
     814                 :       2001 :   return ret;
     815                 :            : }
     816                 :            : 
     817                 :            : static void
     818                 :          2 : gst_wavpack_enc_rewrite_first_block (GstWavpackEnc * enc)
     819                 :            : {
     820                 :          2 :   GstEvent *event = gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_BYTES,
     821                 :            :       0, GST_BUFFER_OFFSET_NONE, 0);
     822                 :            :   gboolean ret;
     823                 :            : 
     824         [ -  + ]:          2 :   g_return_if_fail (enc);
     825         [ -  + ]:          2 :   g_return_if_fail (enc->first_block);
     826                 :            : 
     827                 :            :   /* update the sample count in the first block */
     828                 :          2 :   WavpackUpdateNumSamples (enc->wp_context, enc->first_block);
     829                 :            : 
     830                 :            :   /* try to seek to the beginning of the output */
     831                 :          2 :   ret = gst_pad_push_event (enc->srcpad, event);
     832         [ +  - ]:          2 :   if (ret) {
     833                 :            :     /* try to rewrite the first block */
     834         [ -  + ]:          2 :     GST_DEBUG_OBJECT (enc, "rewriting first block ...");
     835                 :          2 :     enc->wv_id.passthrough = TRUE;
     836                 :          2 :     ret = gst_wavpack_enc_push_block (&enc->wv_id,
     837                 :            :         enc->first_block, enc->first_block_size);
     838                 :          2 :     enc->wv_id.passthrough = FALSE;
     839                 :            :   } else {
     840         [ #  # ]:          2 :     GST_WARNING_OBJECT (enc, "rewriting of first block failed. "
     841                 :            :         "Seeking to first block failed!");
     842                 :            :   }
     843                 :            : }
     844                 :            : 
     845                 :            : static gboolean
     846                 :          4 : gst_wavpack_enc_sink_event (GstPad * pad, GstEvent * event)
     847                 :            : {
     848                 :          4 :   GstWavpackEnc *enc = GST_WAVPACK_ENC (gst_pad_get_parent (pad));
     849                 :          4 :   gboolean ret = TRUE;
     850                 :            : 
     851         [ -  + ]:          4 :   GST_DEBUG ("Received %s event on sinkpad", GST_EVENT_TYPE_NAME (event));
     852                 :            : 
     853      [ +  +  + ]:          4 :   switch (GST_EVENT_TYPE (event)) {
     854                 :            :     case GST_EVENT_EOS:
     855                 :            :       /* Encode all remaining samples and flush them to the src pads */
     856                 :          2 :       WavpackFlushSamples (enc->wp_context);
     857                 :            : 
     858                 :            :       /* Drop all remaining data, this is no complete block otherwise
     859                 :            :        * it would've been pushed already */
     860         [ -  + ]:          2 :       if (enc->pending_buffer) {
     861                 :          0 :         gst_object_unref (enc->pending_buffer);
     862                 :          0 :         enc->pending_buffer = NULL;
     863                 :          0 :         enc->pending_offset = 0;
     864                 :            :       }
     865                 :            : 
     866                 :            :       /* write the MD5 sum if we have to write one */
     867 [ -  + ][ #  # ]:          2 :       if ((enc->md5) && (enc->md5_context)) {
     868                 :            :         guint8 md5_digest[16];
     869                 :          0 :         gsize digest_len = sizeof (md5_digest);
     870                 :            : 
     871                 :          0 :         g_checksum_get_digest (enc->md5_context, md5_digest, &digest_len);
     872         [ #  # ]:          0 :         if (digest_len == sizeof (md5_digest))
     873                 :          0 :           WavpackStoreMD5Sum (enc->wp_context, md5_digest);
     874                 :            :         else
     875         [ #  # ]:          0 :           GST_WARNING_OBJECT (enc, "Calculating MD5 digest failed");
     876                 :            :       }
     877                 :            : 
     878                 :            :       /* Try to rewrite the first frame with the correct sample number */
     879         [ +  - ]:          2 :       if (enc->first_block)
     880                 :          2 :         gst_wavpack_enc_rewrite_first_block (enc);
     881                 :            : 
     882                 :            :       /* close the context if not already happened */
     883         [ +  - ]:          2 :       if (enc->wp_context) {
     884                 :          2 :         WavpackCloseFile (enc->wp_context);
     885                 :          2 :         enc->wp_context = NULL;
     886                 :            :       }
     887                 :            : 
     888                 :          2 :       ret = gst_pad_event_default (pad, event);
     889                 :          2 :       break;
     890                 :            :     case GST_EVENT_NEWSEGMENT:
     891         [ -  + ]:          1 :       if (enc->wp_context) {
     892         [ #  # ]:          0 :         GST_WARNING_OBJECT (enc, "got NEWSEGMENT after encoding "
     893                 :            :             "already started");
     894                 :            :       }
     895                 :            :       /* drop NEWSEGMENT events, we create our own when pushing
     896                 :            :        * the first buffer to the pads */
     897                 :          1 :       gst_event_unref (event);
     898                 :          1 :       ret = TRUE;
     899                 :          1 :       break;
     900                 :            :     default:
     901                 :          1 :       ret = gst_pad_event_default (pad, event);
     902                 :          1 :       break;
     903                 :            :   }
     904                 :            : 
     905                 :          4 :   gst_object_unref (enc);
     906                 :          4 :   return ret;
     907                 :            : }
     908                 :            : 
     909                 :            : static GstStateChangeReturn
     910                 :         47 : gst_wavpack_enc_change_state (GstElement * element, GstStateChange transition)
     911                 :            : {
     912                 :         47 :   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
     913                 :         47 :   GstWavpackEnc *enc = GST_WAVPACK_ENC (element);
     914                 :            : 
     915      [ +  +  + ]:         47 :   switch (transition) {
     916                 :            :     case GST_STATE_CHANGE_NULL_TO_READY:
     917                 :            :       /* set the last returned GstFlowReturns of the two pads to GST_FLOW_OK
     918                 :            :        * as they're only set to something else in WavpackPackSamples() or more
     919                 :            :        * specific gst_wavpack_enc_push_block() and nothing happened there yet */
     920                 :          6 :       enc->srcpad_last_return = enc->wvcsrcpad_last_return = GST_FLOW_OK;
     921                 :          6 :       break;
     922                 :            :     case GST_STATE_CHANGE_READY_TO_PAUSED:
     923                 :          9 :       break;
     924                 :            :     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
     925                 :            :     default:
     926                 :         32 :       break;
     927                 :            :   }
     928                 :            : 
     929                 :         47 :   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
     930                 :            : 
     931   [ +  +  +  + ]:         47 :   switch (transition) {
     932                 :            :     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
     933                 :          8 :       break;
     934                 :            :     case GST_STATE_CHANGE_PAUSED_TO_READY:
     935                 :          9 :       gst_wavpack_enc_reset (enc);
     936                 :          9 :       break;
     937                 :            :     case GST_STATE_CHANGE_READY_TO_NULL:
     938                 :          6 :       break;
     939                 :            :     default:
     940                 :         24 :       break;
     941                 :            :   }
     942                 :            : 
     943                 :         47 :   return ret;
     944                 :            : }
     945                 :            : 
     946                 :            : static void
     947                 :          0 : gst_wavpack_enc_set_property (GObject * object, guint prop_id,
     948                 :            :     const GValue * value, GParamSpec * pspec)
     949                 :            : {
     950                 :          0 :   GstWavpackEnc *enc = GST_WAVPACK_ENC (object);
     951                 :            : 
     952   [ #  #  #  #  :          0 :   switch (prop_id) {
             #  #  #  # ]
     953                 :            :     case ARG_MODE:
     954                 :          0 :       enc->mode = g_value_get_enum (value);
     955                 :          0 :       break;
     956                 :            :     case ARG_BITRATE:{
     957                 :          0 :       guint val = g_value_get_uint (value);
     958                 :            : 
     959 [ #  # ][ #  # ]:          0 :       if ((val >= 24000) && (val <= 9600000)) {
     960                 :          0 :         enc->bitrate = val;
     961                 :          0 :         enc->bps = 0.0;
     962                 :            :       } else {
     963                 :          0 :         enc->bitrate = 0;
     964                 :          0 :         enc->bps = 0.0;
     965                 :            :       }
     966                 :          0 :       break;
     967                 :            :     }
     968                 :            :     case ARG_BITSPERSAMPLE:{
     969                 :          0 :       gdouble val = g_value_get_double (value);
     970                 :            : 
     971 [ #  # ][ #  # ]:          0 :       if ((val >= 2.0) && (val <= 24.0)) {
     972                 :          0 :         enc->bps = val;
     973                 :          0 :         enc->bitrate = 0;
     974                 :            :       } else {
     975                 :          0 :         enc->bps = 0.0;
     976                 :          0 :         enc->bitrate = 0;
     977                 :            :       }
     978                 :          0 :       break;
     979                 :            :     }
     980                 :            :     case ARG_CORRECTION_MODE:
     981                 :          0 :       enc->correction_mode = g_value_get_enum (value);
     982                 :          0 :       break;
     983                 :            :     case ARG_MD5:
     984                 :          0 :       enc->md5 = g_value_get_boolean (value);
     985                 :          0 :       break;
     986                 :            :     case ARG_EXTRA_PROCESSING:
     987                 :          0 :       enc->extra_processing = g_value_get_uint (value);
     988                 :          0 :       break;
     989                 :            :     case ARG_JOINT_STEREO_MODE:
     990                 :          0 :       enc->joint_stereo_mode = g_value_get_enum (value);
     991                 :          0 :       break;
     992                 :            :     default:
     993                 :          0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     994                 :          0 :       break;
     995                 :            :   }
     996                 :          0 : }
     997                 :            : 
     998                 :            : static void
     999                 :          0 : gst_wavpack_enc_get_property (GObject * object, guint prop_id, GValue * value,
    1000                 :            :     GParamSpec * pspec)
    1001                 :            : {
    1002                 :          0 :   GstWavpackEnc *enc = GST_WAVPACK_ENC (object);
    1003                 :            : 
    1004   [ #  #  #  #  :          0 :   switch (prop_id) {
             #  #  #  # ]
    1005                 :            :     case ARG_MODE:
    1006                 :          0 :       g_value_set_enum (value, enc->mode);
    1007                 :          0 :       break;
    1008                 :            :     case ARG_BITRATE:
    1009         [ #  # ]:          0 :       if (enc->bps == 0.0) {
    1010                 :          0 :         g_value_set_uint (value, enc->bitrate);
    1011                 :            :       } else {
    1012                 :          0 :         g_value_set_uint (value, 0);
    1013                 :            :       }
    1014                 :          0 :       break;
    1015                 :            :     case ARG_BITSPERSAMPLE:
    1016         [ #  # ]:          0 :       if (enc->bitrate == 0) {
    1017                 :          0 :         g_value_set_double (value, enc->bps);
    1018                 :            :       } else {
    1019                 :          0 :         g_value_set_double (value, 0.0);
    1020                 :            :       }
    1021                 :          0 :       break;
    1022                 :            :     case ARG_CORRECTION_MODE:
    1023                 :          0 :       g_value_set_enum (value, enc->correction_mode);
    1024                 :          0 :       break;
    1025                 :            :     case ARG_MD5:
    1026                 :          0 :       g_value_set_boolean (value, enc->md5);
    1027                 :          0 :       break;
    1028                 :            :     case ARG_EXTRA_PROCESSING:
    1029                 :          0 :       g_value_set_uint (value, enc->extra_processing);
    1030                 :          0 :       break;
    1031                 :            :     case ARG_JOINT_STEREO_MODE:
    1032                 :          0 :       g_value_set_enum (value, enc->joint_stereo_mode);
    1033                 :          0 :       break;
    1034                 :            :     default:
    1035                 :          0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    1036                 :          0 :       break;
    1037                 :            :   }
    1038                 :          0 : }
    1039                 :            : 
    1040                 :            : gboolean
    1041                 :         11 : gst_wavpack_enc_plugin_init (GstPlugin * plugin)
    1042                 :            : {
    1043         [ -  + ]:         11 :   if (!gst_element_register (plugin, "wavpackenc",
    1044                 :            :           GST_RANK_NONE, GST_TYPE_WAVPACK_ENC))
    1045                 :          0 :     return FALSE;
    1046                 :            : 
    1047         [ +  - ]:         11 :   GST_DEBUG_CATEGORY_INIT (gst_wavpack_enc_debug, "wavpack_enc", 0,
    1048                 :            :       "Wavpack encoder");
    1049                 :            : 
    1050                 :         11 :   return TRUE;
    1051                 :            : }

Generated by: LCOV version 1.9