LCOV - code coverage report
Current view: top level - ext/wavpack - gstwavpackdec.c (source / functions) Hit Total Coverage
Test: GStreamer Good Plug-ins 0.10.28.1 Lines: 172 201 85.6 %
Date: 2011-03-25 Functions: 13 13 100.0 %
Branches: 70 158 44.3 %

           Branch data     Line data    Source code
       1                 :            : /* GStreamer Wavpack plugin
       2                 :            :  * Copyright (c) 2005 Arwed v. Merkatz <v.merkatz@gmx.net>
       3                 :            :  * Copyright (c) 2006 Edward Hervey <bilboed@gmail.com>
       4                 :            :  * Copyright (c) 2006 Sebastian Dröge <slomo@circular-chaos.org>
       5                 :            :  *
       6                 :            :  * gstwavpackdec.c: raw Wavpack bitstream decoder
       7                 :            :  *
       8                 :            :  * This library is free software; you can redistribute it and/or
       9                 :            :  * modify it under the terms of the GNU Library General Public
      10                 :            :  * License as published by the Free Software Foundation; either
      11                 :            :  * version 2 of the License, or (at your option) any later version.
      12                 :            :  *
      13                 :            :  * This library is distributed in the hope that it will be useful,
      14                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      15                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16                 :            :  * Library General Public License for more details.
      17                 :            :  *
      18                 :            :  * You should have received a copy of the GNU Library General Public
      19                 :            :  * License along with this library; if not, write to the
      20                 :            :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      21                 :            :  * Boston, MA 02111-1307, USA.
      22                 :            :  */
      23                 :            : 
      24                 :            : /**
      25                 :            :  * SECTION:element-wavpackdec
      26                 :            :  *
      27                 :            :  * WavpackDec decodes framed (for example by the WavpackParse element)
      28                 :            :  * Wavpack streams and decodes them to raw audio.
      29                 :            :  * <ulink url="http://www.wavpack.com/">Wavpack</ulink> is an open-source
      30                 :            :  * audio codec that features both lossless and lossy encoding.
      31                 :            :  *
      32                 :            :  * <refsect2>
      33                 :            :  * <title>Example launch line</title>
      34                 :            :  * |[
      35                 :            :  * gst-launch filesrc location=test.wv ! wavpackparse ! wavpackdec ! audioconvert ! audioresample ! autoaudiosink
      36                 :            :  * ]| This pipeline decodes the Wavpack file test.wv into raw audio buffers and
      37                 :            :  * tries to play it back using an automatically found audio sink.
      38                 :            :  * </refsect2>
      39                 :            :  */
      40                 :            : 
      41                 :            : #ifdef HAVE_CONFIG_H
      42                 :            : #include "config.h"
      43                 :            : #endif
      44                 :            : 
      45                 :            : #include <gst/gst.h>
      46                 :            : #include <gst/audio/audio.h>
      47                 :            : #include <gst/audio/multichannel.h>
      48                 :            : 
      49                 :            : #include <math.h>
      50                 :            : #include <string.h>
      51                 :            : 
      52                 :            : #include <wavpack/wavpack.h>
      53                 :            : #include "gstwavpackdec.h"
      54                 :            : #include "gstwavpackcommon.h"
      55                 :            : #include "gstwavpackstreamreader.h"
      56                 :            : 
      57                 :            : 
      58                 :            : #define WAVPACK_DEC_MAX_ERRORS 16
      59                 :            : 
      60                 :            : GST_DEBUG_CATEGORY_STATIC (gst_wavpack_dec_debug);
      61                 :            : #define GST_CAT_DEFAULT gst_wavpack_dec_debug
      62                 :            : 
      63                 :            : static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
      64                 :            :     GST_PAD_SINK,
      65                 :            :     GST_PAD_ALWAYS,
      66                 :            :     GST_STATIC_CAPS ("audio/x-wavpack, "
      67                 :            :         "width = (int) [ 1, 32 ], "
      68                 :            :         "channels = (int) [ 1, 8 ], "
      69                 :            :         "rate = (int) [ 6000, 192000 ], " "framed = (boolean) true")
      70                 :            :     );
      71                 :            : 
      72                 :            : static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
      73                 :            :     GST_PAD_SRC,
      74                 :            :     GST_PAD_ALWAYS,
      75                 :            :     GST_STATIC_CAPS ("audio/x-raw-int, "
      76                 :            :         "width = (int) 32, "
      77                 :            :         "depth = (int) [ 1, 32 ], "
      78                 :            :         "channels = (int) [ 1, 8 ], "
      79                 :            :         "rate = (int) [ 6000, 192000 ], "
      80                 :            :         "endianness = (int) BYTE_ORDER, " "signed = (boolean) true")
      81                 :            :     );
      82                 :            : 
      83                 :            : static GstFlowReturn gst_wavpack_dec_chain (GstPad * pad, GstBuffer * buffer);
      84                 :            : static gboolean gst_wavpack_dec_sink_set_caps (GstPad * pad, GstCaps * caps);
      85                 :            : static gboolean gst_wavpack_dec_sink_event (GstPad * pad, GstEvent * event);
      86                 :            : static void gst_wavpack_dec_finalize (GObject * object);
      87                 :            : static GstStateChangeReturn gst_wavpack_dec_change_state (GstElement * element,
      88                 :            :     GstStateChange transition);
      89                 :            : static void gst_wavpack_dec_post_tags (GstWavpackDec * dec);
      90                 :            : 
      91         [ +  + ]:        143 : GST_BOILERPLATE (GstWavpackDec, gst_wavpack_dec, GstElement, GST_TYPE_ELEMENT);
      92                 :            : 
      93                 :            : static void
      94                 :          8 : gst_wavpack_dec_base_init (gpointer klass)
      95                 :            : {
      96                 :          8 :   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
      97                 :            : 
      98                 :          8 :   gst_element_class_add_pad_template (element_class,
      99                 :            :       gst_static_pad_template_get (&src_factory));
     100                 :          8 :   gst_element_class_add_pad_template (element_class,
     101                 :            :       gst_static_pad_template_get (&sink_factory));
     102                 :          8 :   gst_element_class_set_details_simple (element_class, "Wavpack audio decoder",
     103                 :            :       "Codec/Decoder/Audio",
     104                 :            :       "Decodes Wavpack audio data",
     105                 :            :       "Arwed v. Merkatz <v.merkatz@gmx.net>, "
     106                 :            :       "Sebastian Dröge <slomo@circular-chaos.org>");
     107                 :          8 : }
     108                 :            : 
     109                 :            : static void
     110                 :          8 : gst_wavpack_dec_class_init (GstWavpackDecClass * klass)
     111                 :            : {
     112                 :          8 :   GObjectClass *gobject_class = (GObjectClass *) klass;
     113                 :          8 :   GstElementClass *gstelement_class = (GstElementClass *) klass;
     114                 :            : 
     115                 :          8 :   gstelement_class->change_state =
     116                 :          8 :       GST_DEBUG_FUNCPTR (gst_wavpack_dec_change_state);
     117                 :          8 :   gobject_class->finalize = gst_wavpack_dec_finalize;
     118                 :          8 : }
     119                 :            : 
     120                 :            : static void
     121                 :         18 : gst_wavpack_dec_reset (GstWavpackDec * dec)
     122                 :            : {
     123                 :         18 :   dec->wv_id.buffer = NULL;
     124                 :         18 :   dec->wv_id.position = dec->wv_id.length = 0;
     125                 :            : 
     126                 :         18 :   dec->error_count = 0;
     127                 :            : 
     128                 :         18 :   dec->channels = 0;
     129                 :         18 :   dec->channel_mask = 0;
     130                 :         18 :   dec->sample_rate = 0;
     131                 :         18 :   dec->depth = 0;
     132                 :            : 
     133                 :         18 :   gst_segment_init (&dec->segment, GST_FORMAT_TIME);
     134                 :         18 :   dec->next_block_index = 0;
     135                 :         18 : }
     136                 :            : 
     137                 :            : static void
     138                 :          7 : gst_wavpack_dec_init (GstWavpackDec * dec, GstWavpackDecClass * gklass)
     139                 :            : {
     140                 :          7 :   dec->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink");
     141                 :          7 :   gst_pad_set_chain_function (dec->sinkpad,
     142                 :          7 :       GST_DEBUG_FUNCPTR (gst_wavpack_dec_chain));
     143                 :          7 :   gst_pad_set_setcaps_function (dec->sinkpad,
     144                 :          7 :       GST_DEBUG_FUNCPTR (gst_wavpack_dec_sink_set_caps));
     145                 :          7 :   gst_pad_set_event_function (dec->sinkpad,
     146                 :          7 :       GST_DEBUG_FUNCPTR (gst_wavpack_dec_sink_event));
     147                 :          7 :   gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad);
     148                 :            : 
     149                 :          7 :   dec->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
     150                 :          7 :   gst_pad_use_fixed_caps (dec->srcpad);
     151                 :          7 :   gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
     152                 :            : 
     153                 :          7 :   dec->context = NULL;
     154                 :          7 :   dec->stream_reader = gst_wavpack_stream_reader_new ();
     155                 :            : 
     156                 :          7 :   gst_wavpack_dec_reset (dec);
     157                 :          7 : }
     158                 :            : 
     159                 :            : static void
     160                 :          7 : gst_wavpack_dec_finalize (GObject * object)
     161                 :            : {
     162                 :          7 :   GstWavpackDec *dec = GST_WAVPACK_DEC (object);
     163                 :            : 
     164                 :          7 :   g_free (dec->stream_reader);
     165                 :          7 :   dec->stream_reader = NULL;
     166                 :            : 
     167                 :          7 :   G_OBJECT_CLASS (parent_class)->finalize (object);
     168                 :          7 : }
     169                 :            : 
     170                 :            : static gboolean
     171                 :          1 : gst_wavpack_dec_sink_set_caps (GstPad * pad, GstCaps * caps)
     172                 :            : {
     173                 :          1 :   GstWavpackDec *dec = GST_WAVPACK_DEC (gst_pad_get_parent (pad));
     174                 :          1 :   GstStructure *structure = gst_caps_get_structure (caps, 0);
     175                 :            : 
     176                 :            :   /* Check if we can set the caps here already */
     177   [ +  -  +  - ]:          2 :   if (gst_structure_get_int (structure, "channels", &dec->channels) &&
     178         [ +  - ]:          2 :       gst_structure_get_int (structure, "rate", &dec->sample_rate) &&
     179                 :          1 :       gst_structure_get_int (structure, "width", &dec->depth)) {
     180                 :            :     GstCaps *caps;
     181                 :            :     GstAudioChannelPosition *pos;
     182                 :            : 
     183                 :          1 :     caps = gst_caps_new_simple ("audio/x-raw-int",
     184                 :            :         "rate", G_TYPE_INT, dec->sample_rate,
     185                 :            :         "channels", G_TYPE_INT, dec->channels,
     186                 :            :         "depth", G_TYPE_INT, dec->depth,
     187                 :            :         "width", G_TYPE_INT, 32,
     188                 :            :         "endianness", G_TYPE_INT, G_BYTE_ORDER,
     189                 :            :         "signed", G_TYPE_BOOLEAN, TRUE, NULL);
     190                 :            : 
     191                 :            :     /* If we already have the channel layout set from upstream
     192                 :            :      * take this */
     193         [ +  - ]:          1 :     if (gst_structure_has_field (structure, "channel-positions")) {
     194                 :          1 :       pos = gst_audio_get_channel_positions (structure);
     195 [ +  - ][ -  + ]:          1 :       if (pos != NULL && dec->channels > 2) {
     196                 :          0 :         GstStructure *new_str = gst_caps_get_structure (caps, 0);
     197                 :            : 
     198                 :          0 :         gst_audio_set_channel_positions (new_str, pos);
     199                 :          0 :         dec->channel_mask =
     200                 :          0 :             gst_wavpack_get_channel_mask_from_positions (pos, dec->channels);
     201                 :            :       }
     202                 :            : 
     203         [ +  - ]:          1 :       if (pos != NULL)
     204                 :          1 :         g_free (pos);
     205                 :            :     }
     206                 :            : 
     207         [ -  + ]:          1 :     GST_DEBUG_OBJECT (dec, "setting caps %" GST_PTR_FORMAT, caps);
     208                 :            : 
     209                 :            :     /* should always succeed */
     210                 :          1 :     gst_pad_set_caps (dec->srcpad, caps);
     211                 :          1 :     gst_caps_unref (caps);
     212                 :            : 
     213                 :            :     /* send GST_TAG_AUDIO_CODEC and GST_TAG_BITRATE tags before something
     214                 :            :      * is decoded or after the format has changed */
     215                 :          1 :     gst_wavpack_dec_post_tags (dec);
     216                 :            :   }
     217                 :            : 
     218                 :          1 :   gst_object_unref (dec);
     219                 :            : 
     220                 :          1 :   return TRUE;
     221                 :            : }
     222                 :            : 
     223                 :            : static void
     224                 :          3 : gst_wavpack_dec_post_tags (GstWavpackDec * dec)
     225                 :            : {
     226                 :            :   GstTagList *list;
     227                 :          3 :   GstFormat format_time = GST_FORMAT_TIME, format_bytes = GST_FORMAT_BYTES;
     228                 :            :   gint64 duration, size;
     229                 :            : 
     230                 :          3 :   list = gst_tag_list_new ();
     231                 :            : 
     232                 :          3 :   gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
     233                 :            :       GST_TAG_AUDIO_CODEC, "Wavpack", NULL);
     234                 :            : 
     235                 :            :   /* try to estimate the average bitrate */
     236   [ +  +  +  - ]:          5 :   if (gst_pad_query_peer_duration (dec->sinkpad, &format_bytes, &size) &&
     237         [ -  + ]:          4 :       gst_pad_query_peer_duration (dec->sinkpad, &format_time, &duration) &&
     238         [ #  # ]:          0 :       size > 0 && duration > 0) {
     239                 :            :     guint64 bitrate;
     240                 :            : 
     241                 :          0 :     bitrate = gst_util_uint64_scale (size, 8 * GST_SECOND, duration);
     242                 :          0 :     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
     243                 :            :         (guint) bitrate, NULL);
     244                 :            :   }
     245                 :            : 
     246                 :          3 :   gst_element_post_message (GST_ELEMENT (dec),
     247                 :          3 :       gst_message_new_tag (GST_OBJECT (dec), list));
     248                 :          3 : }
     249                 :            : 
     250                 :            : static GstFlowReturn
     251                 :         51 : gst_wavpack_dec_chain (GstPad * pad, GstBuffer * buf)
     252                 :            : {
     253                 :            :   GstWavpackDec *dec;
     254                 :         51 :   GstBuffer *outbuf = NULL;
     255                 :         51 :   GstFlowReturn ret = GST_FLOW_OK;
     256                 :            :   WavpackHeader wph;
     257                 :            :   int32_t decoded, unpacked_size;
     258                 :            :   gboolean format_changed;
     259                 :            : 
     260                 :         51 :   dec = GST_WAVPACK_DEC (GST_PAD_PARENT (pad));
     261                 :            : 
     262                 :            :   /* check input, we only accept framed input with complete chunks */
     263         [ -  + ]:         51 :   if (GST_BUFFER_SIZE (buf) < sizeof (WavpackHeader))
     264                 :          0 :     goto input_not_framed;
     265                 :            : 
     266         [ +  + ]:         51 :   if (!gst_wavpack_read_header (&wph, GST_BUFFER_DATA (buf)))
     267                 :          1 :     goto invalid_header;
     268                 :            : 
     269         [ +  + ]:         50 :   if (GST_BUFFER_SIZE (buf) < wph.ckSize + 4 * 1 + 4)
     270                 :          1 :     goto input_not_framed;
     271                 :            : 
     272         [ -  + ]:         49 :   if (!(wph.flags & INITIAL_BLOCK))
     273                 :          0 :     goto input_not_framed;
     274                 :            : 
     275                 :         49 :   dec->wv_id.buffer = GST_BUFFER_DATA (buf);
     276                 :         49 :   dec->wv_id.length = GST_BUFFER_SIZE (buf);
     277                 :         49 :   dec->wv_id.position = 0;
     278                 :            : 
     279                 :            :   /* create a new wavpack context if there is none yet but if there
     280                 :            :    * was already one (i.e. caps were set on the srcpad) check whether
     281                 :            :    * the new one has the same caps */
     282         [ +  + ]:         49 :   if (!dec->context) {
     283                 :            :     gchar error_msg[80];
     284                 :            : 
     285                 :          2 :     dec->context = WavpackOpenFileInputEx (dec->stream_reader,
     286                 :          2 :         &dec->wv_id, NULL, error_msg, OPEN_STREAMING, 0);
     287                 :            : 
     288         [ -  + ]:          2 :     if (!dec->context) {
     289         [ #  # ]:          0 :       GST_WARNING ("Couldn't decode buffer: %s", error_msg);
     290                 :          0 :       dec->error_count++;
     291         [ #  # ]:          0 :       if (dec->error_count <= WAVPACK_DEC_MAX_ERRORS) {
     292                 :          0 :         goto out;               /* just return OK for now */
     293                 :            :       } else {
     294                 :          0 :         goto decode_error;
     295                 :            :       }
     296                 :            :     }
     297                 :            :   }
     298                 :            : 
     299         [ -  + ]:         49 :   g_assert (dec->context != NULL);
     300                 :            : 
     301                 :         49 :   dec->error_count = 0;
     302                 :            : 
     303         [ +  + ]:         97 :   format_changed =
     304         [ +  - ]:         97 :       (dec->sample_rate != WavpackGetSampleRate (dec->context)) ||
     305         [ +  - ]:         96 :       (dec->channels != WavpackGetNumChannels (dec->context)) ||
     306         [ +  + ]:         96 :       (dec->depth != WavpackGetBitsPerSample (dec->context)) ||
     307                 :            : #ifdef WAVPACK_OLD_API
     308                 :            :       (dec->channel_mask != dec->context->config.channel_mask);
     309                 :            : #else
     310                 :         48 :       (dec->channel_mask != WavpackGetChannelMask (dec->context));
     311                 :            : #endif
     312                 :            : 
     313 [ +  + ][ +  + ]:         49 :   if (!GST_PAD_CAPS (dec->srcpad) || format_changed) {
     314                 :            :     GstCaps *caps;
     315                 :            :     gint channel_mask;
     316                 :            : 
     317                 :          2 :     dec->sample_rate = WavpackGetSampleRate (dec->context);
     318                 :          2 :     dec->channels = WavpackGetNumChannels (dec->context);
     319                 :          2 :     dec->depth = WavpackGetBitsPerSample (dec->context);
     320                 :            : 
     321                 :          2 :     caps = gst_caps_new_simple ("audio/x-raw-int",
     322                 :            :         "rate", G_TYPE_INT, dec->sample_rate,
     323                 :            :         "channels", G_TYPE_INT, dec->channels,
     324                 :            :         "depth", G_TYPE_INT, dec->depth,
     325                 :            :         "width", G_TYPE_INT, 32,
     326                 :            :         "endianness", G_TYPE_INT, G_BYTE_ORDER,
     327                 :            :         "signed", G_TYPE_BOOLEAN, TRUE, NULL);
     328                 :            : 
     329                 :            : #ifdef WAVPACK_OLD_API
     330                 :            :     channel_mask = dec->context->config.channel_mask;
     331                 :            : #else
     332                 :          2 :     channel_mask = WavpackGetChannelMask (dec->context);
     333                 :            : #endif
     334         [ -  + ]:          2 :     if (channel_mask == 0)
     335                 :          0 :       channel_mask = gst_wavpack_get_default_channel_mask (dec->channels);
     336                 :            : 
     337                 :          2 :     dec->channel_mask = channel_mask;
     338                 :            : 
     339                 :            :     /* Only set the channel layout for more than two channels
     340                 :            :      * otherwise things break unfortunately */
     341 [ +  - ][ -  + ]:          2 :     if (channel_mask != 0 && dec->channels > 2)
     342         [ #  # ]:          0 :       if (!gst_wavpack_set_channel_layout (caps, channel_mask))
     343         [ #  # ]:          0 :         GST_WARNING_OBJECT (dec, "Failed to set channel layout");
     344                 :            : 
     345         [ -  + ]:          2 :     GST_DEBUG_OBJECT (dec, "setting caps %" GST_PTR_FORMAT, caps);
     346                 :            : 
     347                 :            :     /* should always succeed */
     348                 :          2 :     gst_pad_set_caps (dec->srcpad, caps);
     349                 :          2 :     gst_caps_unref (caps);
     350                 :            : 
     351                 :            :     /* send GST_TAG_AUDIO_CODEC and GST_TAG_BITRATE tags before something
     352                 :            :      * is decoded or after the format has changed */
     353                 :          2 :     gst_wavpack_dec_post_tags (dec);
     354                 :            :   }
     355                 :            : 
     356                 :            :   /* alloc output buffer */
     357                 :         49 :   unpacked_size = 4 * wph.block_samples * dec->channels;
     358                 :         49 :   ret = gst_pad_alloc_buffer (dec->srcpad, GST_BUFFER_OFFSET (buf),
     359                 :         49 :       unpacked_size, GST_PAD_CAPS (dec->srcpad), &outbuf);
     360                 :            : 
     361         [ -  + ]:         49 :   if (ret != GST_FLOW_OK)
     362                 :          0 :     goto out;
     363                 :            : 
     364                 :         49 :   gst_buffer_copy_metadata (outbuf, buf, GST_BUFFER_COPY_TIMESTAMPS);
     365                 :            : 
     366                 :            :   /* If we got a DISCONT buffer forward the flag. Nothing else
     367                 :            :    * has to be done as libwavpack doesn't store state between
     368                 :            :    * Wavpack blocks */
     369 [ +  - ][ +  + ]:         49 :   if (GST_BUFFER_IS_DISCONT (buf) || dec->next_block_index != wph.block_index)
     370                 :          1 :     GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
     371                 :            : 
     372                 :         49 :   dec->next_block_index = wph.block_index + wph.block_samples;
     373                 :            : 
     374                 :            :   /* decode */
     375                 :         49 :   decoded = WavpackUnpackSamples (dec->context,
     376                 :         49 :       (int32_t *) GST_BUFFER_DATA (outbuf), wph.block_samples);
     377         [ -  + ]:         49 :   if (decoded != wph.block_samples)
     378                 :          0 :     goto decode_error;
     379                 :            : 
     380         [ +  - ]:         49 :   if ((outbuf = gst_audio_buffer_clip (outbuf, &dec->segment,
     381                 :         49 :               dec->sample_rate, 4 * dec->channels))) {
     382 [ -  + ][ #  # ]:         49 :     GST_LOG_OBJECT (dec, "pushing buffer with time %" GST_TIME_FORMAT,
         [ #  # ][ #  # ]
                 [ #  # ]
     383                 :            :         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)));
     384                 :         49 :     ret = gst_pad_push (dec->srcpad, outbuf);
     385                 :            :   }
     386                 :            : 
     387                 :            : out:
     388                 :            : 
     389         [ -  + ]:         49 :   if (G_UNLIKELY (ret != GST_FLOW_OK)) {
     390         [ #  # ]:          0 :     GST_DEBUG_OBJECT (dec, "flow: %s", gst_flow_get_name (ret));
     391                 :            :   }
     392                 :            : 
     393                 :         49 :   gst_buffer_unref (buf);
     394                 :            : 
     395                 :         49 :   return ret;
     396                 :            : 
     397                 :            : /* ERRORS */
     398                 :            : input_not_framed:
     399                 :            :   {
     400 [ -  + ][ #  # ]:          1 :     GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), ("Expected framed input"));
         [ +  - ][ -  + ]
     401                 :          1 :     gst_buffer_unref (buf);
     402                 :          1 :     return GST_FLOW_ERROR;
     403                 :            :   }
     404                 :            : invalid_header:
     405                 :            :   {
     406 [ -  + ][ #  # ]:          1 :     GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), ("Invalid wavpack header"));
         [ +  - ][ -  + ]
     407                 :          1 :     gst_buffer_unref (buf);
     408                 :          1 :     return GST_FLOW_ERROR;
     409                 :            :   }
     410                 :            : decode_error:
     411                 :            :   {
     412                 :          0 :     const gchar *reason = "unknown";
     413                 :            : 
     414         [ #  # ]:          0 :     if (dec->context) {
     415                 :            : #ifdef WAVPACK_OLD_API
     416                 :            :       reason = dec->context->error_message;
     417                 :            : #else
     418                 :          0 :       reason = WavpackGetErrorMessage (dec->context);
     419                 :            : #endif
     420                 :            :     } else {
     421                 :          0 :       reason = "couldn't create decoder context";
     422                 :            :     }
     423 [ #  # ][ #  # ]:          0 :     GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL),
         [ #  # ][ #  # ]
     424                 :            :         ("Failed to decode wavpack stream: %s", reason));
     425         [ #  # ]:          0 :     if (outbuf)
     426                 :          0 :       gst_buffer_unref (outbuf);
     427                 :          0 :     gst_buffer_unref (buf);
     428                 :         51 :     return GST_FLOW_ERROR;
     429                 :            :   }
     430                 :            : }
     431                 :            : 
     432                 :            : static gboolean
     433                 :          4 : gst_wavpack_dec_sink_event (GstPad * pad, GstEvent * event)
     434                 :            : {
     435                 :          4 :   GstWavpackDec *dec = GST_WAVPACK_DEC (gst_pad_get_parent (pad));
     436                 :            : 
     437         [ -  + ]:          4 :   GST_LOG_OBJECT (dec, "Received %s event", GST_EVENT_TYPE_NAME (event));
     438         [ +  + ]:          4 :   switch (GST_EVENT_TYPE (event)) {
     439                 :            :     case GST_EVENT_NEWSEGMENT:{
     440                 :            :       GstFormat fmt;
     441                 :            :       gboolean is_update;
     442                 :            :       gint64 start, end, base;
     443                 :            :       gdouble rate;
     444                 :            : 
     445                 :          2 :       gst_event_parse_new_segment (event, &is_update, &rate, &fmt, &start,
     446                 :            :           &end, &base);
     447         [ +  + ]:          2 :       if (fmt == GST_FORMAT_TIME) {
     448 [ -  + ][ #  # ]:          1 :         GST_DEBUG ("Got NEWSEGMENT event in GST_FORMAT_TIME, passing on (%"
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     449                 :            :             GST_TIME_FORMAT " - %" GST_TIME_FORMAT ")", GST_TIME_ARGS (start),
     450                 :            :             GST_TIME_ARGS (end));
     451                 :          1 :         gst_segment_set_newsegment (&dec->segment, is_update, rate, fmt,
     452                 :            :             start, end, base);
     453                 :            :       } else {
     454                 :          1 :         gst_segment_init (&dec->segment, GST_FORMAT_TIME);
     455                 :            :       }
     456                 :          2 :       break;
     457                 :            :     }
     458                 :            :     default:
     459                 :          2 :       break;
     460                 :            :   }
     461                 :            : 
     462                 :          4 :   gst_object_unref (dec);
     463                 :          4 :   return gst_pad_event_default (pad, event);
     464                 :            : }
     465                 :            : 
     466                 :            : static GstStateChangeReturn
     467                 :         61 : gst_wavpack_dec_change_state (GstElement * element, GstStateChange transition)
     468                 :            : {
     469                 :         61 :   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
     470                 :         61 :   GstWavpackDec *dec = GST_WAVPACK_DEC (element);
     471                 :            : 
     472   [ +  +  +  + ]:         61 :   switch (transition) {
     473                 :            :     case GST_STATE_CHANGE_NULL_TO_READY:
     474                 :          8 :       break;
     475                 :            :     case GST_STATE_CHANGE_READY_TO_PAUSED:
     476                 :         11 :       break;
     477                 :            :     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
     478                 :         10 :       break;
     479                 :            :     default:
     480                 :         32 :       break;
     481                 :            :   }
     482                 :            : 
     483                 :         61 :   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
     484                 :            : 
     485   [ +  +  +  + ]:         61 :   switch (transition) {
     486                 :            :     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
     487                 :         10 :       break;
     488                 :            :     case GST_STATE_CHANGE_PAUSED_TO_READY:
     489         [ +  + ]:         11 :       if (dec->context) {
     490                 :          2 :         WavpackCloseFile (dec->context);
     491                 :          2 :         dec->context = NULL;
     492                 :            :       }
     493                 :            : 
     494                 :         11 :       gst_wavpack_dec_reset (dec);
     495                 :         11 :       break;
     496                 :            :     case GST_STATE_CHANGE_READY_TO_NULL:
     497                 :          8 :       break;
     498                 :            :     default:
     499                 :         32 :       break;
     500                 :            :   }
     501                 :            : 
     502                 :         61 :   return ret;
     503                 :            : }
     504                 :            : 
     505                 :            : gboolean
     506                 :         11 : gst_wavpack_dec_plugin_init (GstPlugin * plugin)
     507                 :            : {
     508         [ -  + ]:         11 :   if (!gst_element_register (plugin, "wavpackdec",
     509                 :            :           GST_RANK_PRIMARY, GST_TYPE_WAVPACK_DEC))
     510                 :          0 :     return FALSE;
     511         [ +  - ]:         11 :   GST_DEBUG_CATEGORY_INIT (gst_wavpack_dec_debug, "wavpack_dec", 0,
     512                 :            :       "Wavpack decoder");
     513                 :         11 :   return TRUE;
     514                 :            : }

Generated by: LCOV version 1.9