LCOV - code coverage report
Current view: top level - ext/wavpack - gstwavpackcommon.c (source / functions) Hit Total Coverage
Test: GStreamer Good Plug-ins 0.10.28.1 Lines: 46 99 46.5 %
Date: 2011-03-25 Functions: 5 7 71.4 %
Branches: 19 63 30.2 %

           Branch data     Line data    Source code
       1                 :            : /* GStreamer Wavpack plugin
       2                 :            :  * Copyright (c) 2005 Arwed v. Merkatz <v.merkatz@gmx.net>
       3                 :            :  * Copyright (c) 1998 - 2005 Conifer Software
       4                 :            :  * Copyright (c) 2006 Sebastian Dröge <slomo@circular-chaos.org>
       5                 :            :  *
       6                 :            :  * gstwavpackcommon.c: common helper functions
       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                 :            : #ifdef HAVE_CONFIG_H
      25                 :            : #include "config.h"
      26                 :            : #endif
      27                 :            : 
      28                 :            : #include "gstwavpackcommon.h"
      29                 :            : #include <string.h>
      30                 :            : 
      31                 :            : #include <gst/gst.h>
      32                 :            : #include <gst/audio/multichannel.h>
      33                 :            : 
      34                 :            : GST_DEBUG_CATEGORY_EXTERN (wavpack_debug);
      35                 :            : #define GST_CAT_DEFAULT wavpack_debug
      36                 :            : 
      37                 :            : gboolean
      38                 :        116 : gst_wavpack_read_header (WavpackHeader * header, guint8 * buf)
      39                 :            : {
      40                 :        116 :   g_memmove (header, buf, sizeof (WavpackHeader));
      41                 :            : 
      42                 :            : #ifndef WAVPACK_OLD_API
      43                 :        116 :   WavpackLittleEndianToNative (header, (char *) WavpackHeaderFormat);
      44                 :            : #else
      45                 :            :   little_endian_to_native (header, WavpackHeaderFormat);
      46                 :            : #endif
      47                 :            : 
      48                 :        116 :   return (memcmp (header->ckID, "wvpk", 4) == 0);
      49                 :            : }
      50                 :            : 
      51                 :            : /* inspired by the original one in wavpack */
      52                 :            : gboolean
      53                 :         12 : gst_wavpack_read_metadata (GstWavpackMetadata * wpmd, guint8 * header_data,
      54                 :            :     guint8 ** p_data)
      55                 :            : {
      56                 :            :   WavpackHeader hdr;
      57                 :            :   guint8 *end;
      58                 :            : 
      59                 :         12 :   gst_wavpack_read_header (&hdr, header_data);
      60                 :         12 :   end = header_data + hdr.ckSize + 8;
      61                 :            : 
      62         [ -  + ]:         12 :   if (end - *p_data < 2)
      63                 :          0 :     return FALSE;
      64                 :            : 
      65                 :         12 :   wpmd->id = GST_READ_UINT8 (*p_data);
      66                 :         12 :   wpmd->byte_length = 2 * (guint) GST_READ_UINT8 (*p_data + 1);
      67                 :            : 
      68                 :         12 :   *p_data += 2;
      69                 :            : 
      70         [ +  + ]:         12 :   if ((wpmd->id & ID_LARGE) == ID_LARGE) {
      71                 :            :     guint extra;
      72                 :            : 
      73                 :          2 :     wpmd->id &= ~ID_LARGE;
      74                 :            : 
      75         [ -  + ]:          2 :     if (end - *p_data < 2)
      76                 :          0 :       return FALSE;
      77                 :            : 
      78                 :          2 :     extra = GST_READ_UINT16_LE (*p_data);
      79                 :          2 :     wpmd->byte_length += (extra << 9);
      80                 :          2 :     *p_data += 2;
      81                 :            :   }
      82                 :            : 
      83         [ +  + ]:         12 :   if ((wpmd->id & ID_ODD_SIZE) == ID_ODD_SIZE) {
      84                 :          1 :     wpmd->id &= ~ID_ODD_SIZE;
      85                 :          1 :     --wpmd->byte_length;
      86                 :            :   }
      87                 :            : 
      88         [ +  + ]:         12 :   if (wpmd->byte_length > 0) {
      89         [ -  + ]:          6 :     if (end - *p_data < wpmd->byte_length + (wpmd->byte_length & 1)) {
      90                 :          0 :       wpmd->data = NULL;
      91                 :          0 :       return FALSE;
      92                 :            :     }
      93                 :            : 
      94                 :          6 :     wpmd->data = *p_data;
      95                 :          6 :     *p_data += wpmd->byte_length + (wpmd->byte_length & 1);
      96                 :            :   } else {
      97                 :          6 :     wpmd->data = NULL;
      98                 :            :   }
      99                 :            : 
     100                 :         12 :   return TRUE;
     101                 :            : }
     102                 :            : 
     103                 :            : gint
     104                 :          0 : gst_wavpack_get_default_channel_mask (gint nchannels)
     105                 :            : {
     106                 :          0 :   gint channel_mask = 0;
     107                 :            : 
     108                 :            :   /* Set the default channel mask for the given number of channels.
     109                 :            :    * It's the same as for WAVE_FORMAT_EXTENDED:
     110                 :            :    * http://www.microsoft.com/whdc/device/audio/multichaud.mspx
     111                 :            :    */
     112   [ #  #  #  #  :          0 :   switch (nchannels) {
             #  #  #  #  
                      # ]
     113                 :            :     case 11:
     114                 :          0 :       channel_mask |= 0x00400;
     115                 :          0 :       channel_mask |= 0x00200;
     116                 :            :     case 9:
     117                 :          0 :       channel_mask |= 0x00100;
     118                 :            :     case 8:
     119                 :          0 :       channel_mask |= 0x00080;
     120                 :          0 :       channel_mask |= 0x00040;
     121                 :            :     case 6:
     122                 :          0 :       channel_mask |= 0x00020;
     123                 :          0 :       channel_mask |= 0x00010;
     124                 :            :     case 4:
     125                 :          0 :       channel_mask |= 0x00008;
     126                 :            :     case 3:
     127                 :          0 :       channel_mask |= 0x00004;
     128                 :            :     case 2:
     129                 :          0 :       channel_mask |= 0x00002;
     130                 :          0 :       channel_mask |= 0x00001;
     131                 :          0 :       break;
     132                 :            :     case 1:
     133                 :            :       /* For mono use front center */
     134                 :          0 :       channel_mask |= 0x00004;
     135                 :          0 :       break;
     136                 :            :   }
     137                 :            : 
     138                 :          0 :   return channel_mask;
     139                 :            : }
     140                 :            : 
     141                 :            : static const struct
     142                 :            : {
     143                 :            :   const guint32 ms_mask;
     144                 :            :   const GstAudioChannelPosition gst_pos;
     145                 :            : } layout_mapping[] = {
     146                 :            :   {
     147                 :            :   0x00001, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT}, {
     148                 :            :   0x00002, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, {
     149                 :            :   0x00004, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER}, {
     150                 :            :   0x00008, GST_AUDIO_CHANNEL_POSITION_LFE}, {
     151                 :            :   0x00010, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT}, {
     152                 :            :   0x00020, GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}, {
     153                 :            :   0x00040, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER}, {
     154                 :            :   0x00080, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER}, {
     155                 :            :   0x00100, GST_AUDIO_CHANNEL_POSITION_REAR_CENTER}, {
     156                 :            :   0x00200, GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT}, {
     157                 :            :   0x00400, GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT}, {
     158                 :            :   0x00800, GST_AUDIO_CHANNEL_POSITION_INVALID}, /* TOP_CENTER       */
     159                 :            :   {
     160                 :            :   0x01000, GST_AUDIO_CHANNEL_POSITION_INVALID}, /* TOP_FRONT_LEFT   */
     161                 :            :   {
     162                 :            :   0x02000, GST_AUDIO_CHANNEL_POSITION_INVALID}, /* TOP_FRONT_CENTER */
     163                 :            :   {
     164                 :            :   0x04000, GST_AUDIO_CHANNEL_POSITION_INVALID}, /* TOP_FRONT_RIGHT  */
     165                 :            :   {
     166                 :            :   0x08000, GST_AUDIO_CHANNEL_POSITION_INVALID}, /* TOP_BACK_LEFT    */
     167                 :            :   {
     168                 :            :   0x10000, GST_AUDIO_CHANNEL_POSITION_INVALID}, /* TOP_BACK_CENTER  */
     169                 :            :   {
     170                 :            :   0x20000, GST_AUDIO_CHANNEL_POSITION_INVALID}  /* TOP_BACK_RIGHT   */
     171                 :            : };
     172                 :            : 
     173                 :            : #define MAX_CHANNEL_POSITIONS G_N_ELEMENTS (layout_mapping)
     174                 :            : 
     175                 :            : gboolean
     176                 :          4 : gst_wavpack_set_channel_layout (GstCaps * caps, gint layout)
     177                 :            : {
     178                 :            :   GstAudioChannelPosition pos[MAX_CHANNEL_POSITIONS];
     179                 :            :   GstStructure *s;
     180                 :            :   gint num_channels, i, p;
     181                 :            : 
     182                 :          4 :   s = gst_caps_get_structure (caps, 0);
     183         [ -  + ]:          4 :   if (!gst_structure_get_int (s, "channels", &num_channels))
     184                 :          0 :     g_return_val_if_reached (FALSE);
     185                 :            : 
     186 [ +  - ][ +  - ]:          4 :   if (num_channels == 1 && layout == 0x00004) {
     187                 :          4 :     pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_MONO;
     188                 :          4 :     gst_audio_set_channel_positions (s, pos);
     189                 :          4 :     return TRUE;
     190                 :            :   }
     191                 :            : 
     192                 :          0 :   p = 0;
     193         [ #  # ]:          0 :   for (i = 0; i < MAX_CHANNEL_POSITIONS; ++i) {
     194         [ #  # ]:          0 :     if ((layout & layout_mapping[i].ms_mask) != 0) {
     195         [ #  # ]:          0 :       if (p >= num_channels) {
     196         [ #  # ]:          0 :         GST_WARNING ("More bits set in the channel layout map than there "
     197                 :            :             "are channels! Broken file");
     198                 :          0 :         return FALSE;
     199                 :            :       }
     200         [ #  # ]:          0 :       if (layout_mapping[i].gst_pos == GST_AUDIO_CHANNEL_POSITION_INVALID) {
     201         [ #  # ]:          0 :         GST_WARNING ("Unsupported channel position (mask 0x%08x) in channel "
     202                 :            :             "layout map - ignoring those channels", layout_mapping[i].ms_mask);
     203                 :            :         /* what to do? just ignore it and let downstream deal with a channel
     204                 :            :          * layout that has INVALID positions in it for now ... */
     205                 :            :       }
     206                 :          0 :       pos[p] = layout_mapping[i].gst_pos;
     207                 :          0 :       ++p;
     208                 :            :     }
     209                 :            :   }
     210                 :            : 
     211         [ #  # ]:          0 :   if (p != num_channels) {
     212         [ #  # ]:          0 :     GST_WARNING ("Only %d bits set in the channel layout map, but there are "
     213                 :            :         "supposed to be %d channels! Broken file", p, num_channels);
     214                 :          0 :     return FALSE;
     215                 :            :   }
     216                 :            : 
     217                 :          0 :   gst_audio_set_channel_positions (s, pos);
     218                 :          4 :   return TRUE;
     219                 :            : }
     220                 :            : 
     221                 :            : GstAudioChannelPosition *
     222                 :          0 : gst_wavpack_get_default_channel_positions (gint nchannels)
     223                 :            : {
     224                 :          0 :   GstAudioChannelPosition *pos = g_new (GstAudioChannelPosition, nchannels);
     225                 :            :   gint i;
     226                 :            : 
     227         [ #  # ]:          0 :   if (nchannels == 1) {
     228                 :          0 :     pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
     229                 :          0 :     return pos;
     230                 :            :   }
     231                 :            : 
     232         [ #  # ]:          0 :   for (i = 0; i < nchannels; i++)
     233                 :          0 :     pos[i] = layout_mapping[i].gst_pos;
     234                 :            : 
     235                 :          0 :   return pos;
     236                 :            : }
     237                 :            : 
     238                 :            : gint
     239                 :          2 : gst_wavpack_get_channel_mask_from_positions (GstAudioChannelPosition * pos,
     240                 :            :     gint nchannels)
     241                 :            : {
     242                 :          2 :   gint channel_mask = 0;
     243                 :            :   gint i, j;
     244                 :            : 
     245 [ +  - ][ +  - ]:          2 :   if (nchannels == 1 && pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_MONO) {
     246                 :          2 :     channel_mask = 0x00000004;
     247                 :          2 :     return channel_mask;
     248                 :            :   }
     249                 :            : 
     250                 :            :   /* FIXME: not exactly efficient but otherwise we need an inverse
     251                 :            :    * mapping table too */
     252         [ #  # ]:          0 :   for (i = 0; i < nchannels; i++) {
     253         [ #  # ]:          0 :     for (j = 0; j < MAX_CHANNEL_POSITIONS; j++) {
     254         [ #  # ]:          0 :       if (pos[i] == layout_mapping[j].gst_pos) {
     255                 :          0 :         channel_mask |= layout_mapping[j].ms_mask;
     256                 :          0 :         break;
     257                 :            :       }
     258                 :            :     }
     259                 :            :   }
     260                 :            : 
     261                 :          2 :   return channel_mask;
     262                 :            : }
     263                 :            : 
     264                 :            : gboolean
     265                 :          2 : gst_wavpack_set_channel_mapping (GstAudioChannelPosition * pos, gint nchannels,
     266                 :            :     gint8 * channel_mapping)
     267                 :            : {
     268                 :            :   gint i, j;
     269                 :          2 :   gboolean ret = TRUE;
     270                 :            : 
     271         [ +  + ]:          4 :   for (i = 0; i < nchannels; i++) {
     272         [ +  + ]:         38 :     for (j = 0; j < MAX_CHANNEL_POSITIONS; j++) {
     273         [ -  + ]:         36 :       if (pos[i] == layout_mapping[j].gst_pos) {
     274                 :          0 :         channel_mapping[i] = j;
     275                 :          0 :         ret &= (i == j);
     276                 :          0 :         break;
     277                 :            :       }
     278                 :            :     }
     279                 :            :   }
     280                 :            : 
     281                 :          2 :   return !ret;
     282                 :            : }

Generated by: LCOV version 1.9