libextractor

GNU libextractor
Log | Files | Refs | Submodules | README | LICENSE

mp3_extractor.c (12255B)


      1 /*
      2      This file is part of libextractor.
      3      Copyright (C) 2002, 2003, 2004, 2006, 2009 Vidyut Samanta and Christian Grothoff
      4 
      5      libextractor is free software; you can redistribute it and/or modify
      6      it under the terms of the GNU General Public License as published
      7      by the Free Software Foundation; either version 2, or (at your
      8      option) any later version.
      9 
     10      libextractor is distributed in the hope that it will be useful, but
     11      WITHOUT ANY WARRANTY; without even the implied warranty of
     12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13      General Public License for more details.
     14 
     15      You should have received a copy of the GNU General Public License
     16      along with libextractor; see the file COPYING.  If not, write to the
     17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18      Boston, MA 02110-1301, USA.
     19 
     20 
     21      Some of this code is based on AVInfo 1.0 alpha 11
     22      (c) George Shuklin, gs]AT[shounen.ru, 2002-2004
     23      http://shounen.ru/soft/avinfo/
     24 
     25  */
     26 
     27 #define DEBUG_EXTRACT_MP3 0
     28 
     29 #include "platform.h"
     30 #include "extractor.h"
     31 #include "convert.h"
     32 #include <string.h>
     33 #include <stdio.h>
     34 #include <sys/types.h>
     35 #include <sys/stat.h>
     36 #include <unistd.h>
     37 #include <stdlib.h>
     38 
     39 #include "extractor_plugins.h"
     40 
     41 #include "le_architecture.h"
     42 
     43 #define LARGEST_FRAME_SIZE 8065
     44 
     45 enum
     46 { MPEG_ERR = 0, MPEG_V1 = 1, MPEG_V2 = 2, MPEG_V25 = 3 };
     47 
     48 enum
     49 { LAYER_ERR = 0, LAYER_1 = 1, LAYER_2 = 2, LAYER_3 = 3 };
     50 
     51 #define MPA_SYNC_MASK          ((unsigned int) 0xFFE00000)
     52 #if __BYTE_ORDER == __BIG_ENDIAN
     53 #define MPA_SYNC_MASK_MEM      ((unsigned int) 0xFFE00000)
     54 #else
     55 #define MPA_SYNC_MASK_MEM      ((unsigned int) 0x0000E0FF)
     56 #endif
     57 #define MPA_LAST_SYNC_BIT_MASK ((unsigned int) 0x00100000)
     58 #define MPA_VERSION_MASK       ((unsigned int) 0x00080000)
     59 #define MPA_LAYER_MASK         ((unsigned int) 0x3)
     60 #define MPA_LAYER_SHIFT        17
     61 #define MPA_BITRATE_MASK       ((unsigned int) 0xF)
     62 #define MPA_BITRATE_SHIFT      12
     63 #define MPA_FREQ_MASK          ((unsigned int) 0x3)
     64 #define MPA_FREQ_SHIFT         10
     65 #define MPA_CHMODE_MASK        ((unsigned int) 0x3)
     66 #define MPA_CHMODE_SHIFT       6
     67 #define MPA_PADDING_SHIFT      9
     68 #define MPA_COPYRIGHT_SHIFT    3
     69 #define MPA_ORIGINAL_SHIFT     2
     70 
     71 static const unsigned int bitrate_table[16][6] = {
     72   {0,   0,   0,   0,   0,   0},
     73   {32,  32,  32,  32,  8,   8},
     74   {64,  48,  40,  48,  16,  16},
     75   {96,  56,  48,  56,  24,  24},
     76   {128, 64,  56,  64,  32,  32},
     77   {160, 80,  64,  80,  40,  40},
     78   {192, 96,  80,  96,  48,  48},
     79   {224, 112, 96,  112, 56,  56},
     80   {256, 128, 112, 128, 64,  64},
     81   {288, 160, 128, 144, 80,  80},
     82   {320, 192, 160, 160, 96,  96},
     83   {352, 224, 192, 176, 112, 112},
     84   {384, 256, 224, 192, 128, 128},
     85   {416, 320, 256, 224, 144, 144},
     86   {448, 384, 320, 256, 160, 160},
     87   {-1, -1, -1, -1, -1, -1}
     88 };
     89 static const int freq_table[4][3] = {
     90   {44100, 22050, 11025},
     91   {48000, 24000, 12000},
     92   {32000, 16000, 8000}
     93 };
     94 static const char *const channel_modes[4] = {
     95   gettext_noop ("stereo"),
     96   gettext_noop ("joint stereo"),
     97   gettext_noop ("dual channel"),
     98   gettext_noop ("mono")
     99 };
    100 static const char *const mpeg_versions[3] = {
    101   gettext_noop ("MPEG-1"),
    102   gettext_noop ("MPEG-2"),
    103   gettext_noop ("MPEG-2.5")
    104 };
    105 static const char *const layer_names[3] = {
    106   gettext_noop ("Layer I"),
    107   gettext_noop ("Layer II"),
    108   gettext_noop ("Layer III")
    109 };
    110 
    111 
    112 #define OK         0
    113 #define SYSERR     1
    114 #define INVALID_ID3 2
    115 
    116 #define ADDR(s,t) do { if (0 != proc (proc_cls, "mp3", t, \
    117                                       EXTRACTOR_METAFORMAT_UTF8, "text/plain", \
    118                                       s, strlen (s) + 1)) return 1; \
    119 } while (0)
    120 
    121 struct mp3_state
    122 {
    123   int state;
    124 
    125   uint32_t header;
    126   int sample_rate;
    127   char mpeg_ver;
    128   char layer;
    129   char vbr_flag;
    130   int ch;
    131   char copyright_flag;
    132   char original_flag;
    133   int avg_bps;
    134   int bitrate;
    135 
    136   int64_t number_of_frames;
    137   int64_t number_of_valid_frames;
    138 };
    139 
    140 enum MP3State
    141 {
    142   MP3_LOOKING_FOR_FRAME = 0,
    143   MP3_READING_FRAME = 1,
    144 };
    145 
    146 static struct mp3_state *
    147 EXTRACTOR_mp3_init_state_method ()
    148 {
    149   struct mp3_state *state;
    150   state = malloc (sizeof (struct mp3_state));
    151   if (state == NULL)
    152     return NULL;
    153   state->header = 0;
    154   state->sample_rate = 0;
    155   state->number_of_frames = 0;
    156   state->number_of_valid_frames = 0;
    157   state->mpeg_ver = 0;
    158   state->layer = 0;
    159   state->vbr_flag = 0;
    160   state->ch = 0;
    161   state->copyright_flag = 0;
    162   state->original_flag = 0;
    163   state->avg_bps = 0;
    164   state->bitrate = 0;
    165   state->state = 0;
    166   return state;
    167 }
    168 
    169 
    170 static int
    171 EXTRACTOR_mp3_discard_state_method (struct mp3_state *state)
    172 {
    173   if (state != NULL)
    174   {
    175     free (state);
    176   }
    177   return 1;
    178 }
    179 
    180 
    181 static int
    182 calculate_frame_statistics_and_maybe_report_it (struct
    183                                                 EXTRACTOR_PluginList *plugin,
    184                                                 struct mp3_state *state,
    185                                                 EXTRACTOR_MetaDataProcessor proc,
    186                                                 void *proc_cls)
    187 {
    188   int length;
    189   char format[512];
    190 
    191   if ((((double) state->number_of_valid_frames
    192         / (double) state->number_of_frames) < 0.8) ||
    193       (state->number_of_valid_frames <= 2) )
    194     /* Unlikely to be an mp3 file */
    195     return 0;
    196   ADDR ("audio/mpeg", EXTRACTOR_METATYPE_MIMETYPE);
    197   state->avg_bps = state->avg_bps / state->number_of_valid_frames;
    198   if (state->sample_rate > 0)
    199     length = 1152 * state->number_of_valid_frames / state->sample_rate;
    200   else if ((state->avg_bps > 0) || (state->bitrate > 0))
    201     length = plugin->fsize / (state->avg_bps ? state->avg_bps : state->bitrate ?
    202                               state->bitrate : 1) / 125;
    203   else
    204     length = 0;
    205 
    206   ADDR (mpeg_versions[state->mpeg_ver - 1], EXTRACTOR_METATYPE_FORMAT_VERSION);
    207   snprintf (format,
    208             sizeof (format),
    209             "%s %s audio, %d kbps (%s), %d Hz, %s, %s, %s",
    210             mpeg_versions[state->mpeg_ver - 1],
    211             layer_names[state->layer - 1],
    212             state->avg_bps,
    213             state->vbr_flag ? _ ("VBR") : _ ("CBR"),
    214             state->sample_rate,
    215             channel_modes[state->ch],
    216             state->copyright_flag ? _ ("copyright") : _ ("no copyright"),
    217             state->original_flag ? _ ("original") : _ ("copy") );
    218 
    219   ADDR (format, EXTRACTOR_METATYPE_RESOURCE_TYPE);
    220   snprintf (format,
    221             sizeof (format), "%dm%02d",
    222             length / 60, length % 60);
    223   ADDR (format, EXTRACTOR_METATYPE_DURATION);
    224   return 0;
    225 }
    226 
    227 
    228 int
    229 EXTRACTOR_mp3_extract_method (struct EXTRACTOR_PluginList *plugin,
    230                               EXTRACTOR_MetaDataProcessor proc,
    231                               void *proc_cls)
    232 {
    233   int64_t offset = 0;
    234   int64_t round_offset;
    235   int64_t read_result;
    236   int64_t i;
    237   unsigned char *data;
    238   struct mp3_state *state;
    239 
    240   int start_anew = 0;
    241 
    242   char mpeg_ver = 0;
    243   char layer = 0;
    244   int idx_num = 0;
    245   int bitrate = 0;              /*used for each frame */
    246   int copyright_flag = 0;
    247   int original_flag = 0;
    248   int sample_rate = 0;
    249   int ch = 0;
    250   int frame_size;
    251 
    252   if (plugin == NULL)
    253     return 1;
    254 
    255   state = EXTRACTOR_mp3_init_state_method ();
    256   if (state == NULL)
    257     return 1;
    258 
    259   while (1)
    260   {
    261     switch (state->state)
    262     {
    263     case MP3_LOOKING_FOR_FRAME:
    264       /* Look for a frame header */
    265       round_offset = offset = pl_get_pos (plugin);
    266       while (1)
    267       {
    268         pl_seek (plugin, offset, SEEK_SET);
    269         read_result = pl_read (plugin, &data, 1024 * 1024);
    270         if (read_result < 4)
    271         {
    272           calculate_frame_statistics_and_maybe_report_it (plugin, state, proc,
    273                                                           proc_cls);
    274           return EXTRACTOR_mp3_discard_state_method (state);
    275         }
    276         for (i = 0; i + 3 < read_result; i++)
    277           if (((*((uint32_t *) &data[i])) & MPA_SYNC_MASK_MEM) ==
    278               MPA_SYNC_MASK_MEM)
    279             break;
    280         if (i + 3 >= 1024 * 1024)
    281           offset += read_result - 3;
    282         else
    283           break;
    284         if (offset > round_offset + 31 * 1024 * 1024)
    285         {
    286           if (((state->number_of_valid_frames > 2) &&
    287                ( ((double) state->number_of_valid_frames
    288                   / (double) state->number_of_frames) < 0.8) ))
    289           {
    290             calculate_frame_statistics_and_maybe_report_it (plugin, state, proc,
    291                                                             proc_cls);
    292           }
    293           return EXTRACTOR_mp3_discard_state_method (state);
    294         }
    295       }
    296       pl_seek (plugin, offset + i, SEEK_SET);
    297       if (4 != pl_read (plugin, &data, 4))
    298       {
    299         calculate_frame_statistics_and_maybe_report_it (plugin, state, proc,
    300                                                         proc_cls);
    301         return EXTRACTOR_mp3_discard_state_method (state);
    302       }
    303       state->header = (data[0] << 24) | (data[1] << 16)
    304                       | (data[2] << 8) | data[3];
    305       if ((state->header & MPA_SYNC_MASK) == MPA_SYNC_MASK)
    306       {
    307         state->state = MP3_READING_FRAME;
    308         break;
    309       }
    310       break;
    311     case MP3_READING_FRAME:
    312       state->number_of_frames += 1;
    313       start_anew = 0;
    314       switch (state->header & (MPA_LAST_SYNC_BIT_MASK | MPA_VERSION_MASK))
    315       {
    316       case (MPA_LAST_SYNC_BIT_MASK | MPA_VERSION_MASK):
    317         mpeg_ver = MPEG_V1;
    318         break;
    319       case (MPA_LAST_SYNC_BIT_MASK):
    320         mpeg_ver = MPEG_V2;
    321         break;
    322       case 0:
    323         mpeg_ver = MPEG_V25;
    324         break;
    325       case (MPA_VERSION_MASK):
    326       default:
    327         state->state = MP3_LOOKING_FOR_FRAME;
    328         offset += 1;
    329         start_anew = 1;
    330       }
    331       if (start_anew)
    332         break;
    333       switch (state->header & (MPA_LAYER_MASK << MPA_LAYER_SHIFT))
    334       {
    335       case (0x1 << MPA_LAYER_SHIFT):
    336         layer = LAYER_3;
    337         break;
    338       case (0x2 << MPA_LAYER_SHIFT):
    339         layer = LAYER_2;
    340         break;
    341       case (0x3 << MPA_LAYER_SHIFT):
    342         layer = LAYER_1;
    343         break;
    344       case 0x0:
    345       default:
    346         state->state = MP3_LOOKING_FOR_FRAME;
    347         offset += 1;
    348         start_anew = 1;
    349       }
    350       if (start_anew)
    351         break;
    352       if (mpeg_ver < MPEG_V25)
    353         idx_num = (mpeg_ver - 1) * 3 + layer - 1;
    354       else
    355         idx_num = 2 + layer;
    356       bitrate = 1000 * bitrate_table[(state->header >> MPA_BITRATE_SHIFT)
    357                                      & MPA_BITRATE_MASK][idx_num];
    358       if (bitrate < 0)
    359       {
    360         /*error in header */
    361         state->state = MP3_LOOKING_FOR_FRAME;
    362         offset += 1;
    363         break;
    364       }
    365       sample_rate = freq_table[(state->header >> MPA_FREQ_SHIFT)
    366                                & MPA_FREQ_MASK][mpeg_ver - 1];
    367       if (sample_rate <= 0)
    368       {
    369         /*error in header */
    370         state->state = MP3_LOOKING_FOR_FRAME;
    371         offset += 1;
    372         break;
    373       }
    374       ch = ((state->header >> MPA_CHMODE_SHIFT) & MPA_CHMODE_MASK);
    375       copyright_flag = (state->header >> MPA_COPYRIGHT_SHIFT) & 0x1;
    376       original_flag = (state->header >> MPA_ORIGINAL_SHIFT) & 0x1;
    377       if (layer == LAYER_1)
    378         frame_size = (12 * bitrate / sample_rate + ((state->header
    379                                                      >> MPA_PADDING_SHIFT)
    380                                                     & 0x1)) * 4;
    381       else
    382         frame_size = 144 * bitrate / sample_rate + ((state->header
    383                                                      >> MPA_PADDING_SHIFT)
    384                                                     & 0x1);
    385       if (frame_size < 8)
    386       {
    387         /*error in header */
    388         state->state = MP3_LOOKING_FOR_FRAME;
    389         offset += 1;
    390         break;
    391       }
    392 
    393       /* Only save data from valid frames in the state */
    394       state->avg_bps += bitrate / 1000;
    395       state->sample_rate = sample_rate;
    396       state->mpeg_ver = mpeg_ver;
    397       state->layer = layer;
    398       state->ch = ch;
    399       state->copyright_flag = copyright_flag;
    400       state->original_flag = original_flag;
    401       state->bitrate = bitrate;
    402 
    403       state->number_of_valid_frames += 1;
    404       if (state->avg_bps / state->number_of_valid_frames != bitrate / 1000)
    405         state->vbr_flag = 1;
    406       pl_seek (plugin, frame_size - 4, SEEK_CUR);
    407       state->state = MP3_LOOKING_FOR_FRAME;
    408       break;
    409     }
    410   }
    411   return 1;
    412 }
    413 
    414 
    415 /* end of mp3_extractor.c */