mp3_file.cpp
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:10k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is MPEG4IP.
  13.  * 
  14.  * The Initial Developer of the Original Code is Cisco Systems Inc.
  15.  * Portions created by Cisco Systems Inc. are
  16.  * Copyright (C) Cisco Systems Inc. 2000, 2001.  All Rights Reserved.
  17.  * 
  18.  * Contributor(s): 
  19.  *              Bill May        wmay@cisco.com
  20.  */
  21. /*
  22.  * mp3_file.cpp - create media structure for mp3 files
  23.  */
  24. #include "mp3if.h"
  25. // from mplib-0.6
  26. #define GLL 148
  27. const static char *genre_list[GLL] = 
  28. { "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge", "Hip-Hop", "Jazz",
  29.   "Metal", "New Age", "Oldies", "Other", "Pop", "R&B", "Rap", "Reggae", "Rock", "Techno",
  30.   "Industrial", "Alternative", "Ska", "Death Metal", "Pranks", "Soundtrack", "Euro-Techno",
  31.   "Ambient", "Trip-Hop", "Vocal", "Jazz+Funk", "Fusion", "Trance", "Classical", "Instrumental",
  32.   "Acid", "House", "Game", "Sound Clip", "Gospel", "Noise", "Alternative Rock", "Bass", "Soul", "Punk",
  33.   "Space", "Meditative", "Instrumental Pop", "Instrumental Rock", "Ethnic", "Gothic", "Darkwave",
  34.   "Techno-Industrial", "Electronic", "Pop-Folk", "Eurodance", "Dream", "Southern Rock", "Comedy", 
  35.   "Cult", "Gangsta Rap", "Top 40", "Christian Rap", "Pop/Funk", "Jungle", "Native American", "Cabaret",
  36.   "New Wave", "Psychedelic", "Rave", "Showtunes", "Trailer", "Lo-Fi", "Tribal", "Acid Punk",
  37.   "Acid Jazz", "Polka", "Retro", "Musical", "Rock & Roll", "Hard Rock", "Folk", "Folk/Rock", 
  38.   "National Folk", "Swing", "Fast-Fusion", "Bebob", "Latin", "Revival", "Celtic", "Bluegrass",
  39.   "Avantgarde", "Gothic Rock", "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", "Slow Rock",
  40.   "Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech", "Chanson", "Opera",
  41.   "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus", "Porn Groove", "Satire", "Slow Jam",
  42.   "Club", "Tango", "Samba", "Folklore", "Ballad", "Power Ballad", "Rythmic Soul", "Freestyle",
  43.   "Duet", "Punk Rock", "Drum Solo", "A Cappella", "Euro-House", "Dance Hall", "Goa", "Drum & Bass",
  44.   "Club-House", "Hardcore", "Terror", "Indie", "BritPop", "Negerpunk", "Polsk Punk", "Beat",
  45.   "Christian Gangsta Rap", "Heavy Metal", "Black Metal", "Crossover", "Contemporary Christian",
  46.   "Christian Rock", "Merengue", "Salsa", "Trash Metal", "Anime", "JPop", "Synthpop" };
  47. static void read_mp3_file_for_tag (mp3_codec_t *mp3,
  48.    char *descptr[3])
  49. {
  50.   char buffer[128];
  51.   char desc[80];
  52.   char temp;
  53.   int ix;
  54.   if (fseek(mp3->m_ifile, -128, SEEK_END) != 0) {
  55.     return;
  56.   }
  57.   fread(buffer, 1, 128, mp3->m_ifile);
  58.   if (strncasecmp(buffer, "tag", 3) != 0) {
  59.     return;
  60.   }
  61.   temp = buffer[33];
  62.   buffer[33] = '';
  63.   ix = 32;
  64.   while (isspace(buffer[ix]) && ix > 0) {
  65.     buffer[ix] = '';
  66.     ix--;
  67.   }
  68.   snprintf(desc, sizeof(desc), "%s", &buffer[3]);
  69.   descptr[0] = strdup(desc);
  70.   buffer[33] = temp;
  71.   temp = buffer[63];
  72.   buffer[63] = '';
  73.   ix = 62;
  74.   while (isspace(buffer[ix]) && ix > 33) {
  75.     buffer[ix] = '';
  76.     ix--;
  77.   }
  78.   snprintf(desc, sizeof(desc), "By: %s", &buffer[33]);
  79.   descptr[1] = strdup(desc);
  80.   buffer[63] = temp;
  81.   temp = buffer[93];
  82.   buffer[93] = '';
  83.   ix = 92;
  84.   while (isspace(buffer[ix]) && ix > 63) {
  85.     buffer[ix] = '';
  86.     ix--;
  87.   }
  88.   if (buffer[125] == '' && buffer[126] != '') {
  89.     snprintf(desc, sizeof(desc), "On: %s - track %d (%c%c%c%c)",
  90.      &buffer[63], buffer[126], temp, buffer[94], buffer[95],
  91.      buffer[96]);
  92.   } else {
  93.     snprintf(desc, sizeof(desc), "On: %s (%c%c%c%c)",
  94.      &buffer[63], temp, buffer[94], buffer[95],
  95.      buffer[96]);
  96.   }
  97.   descptr[2] = strdup(desc);
  98.   unsigned char index = (unsigned char)buffer[127];
  99.   if (index <= GLL) {
  100.     snprintf(desc, sizeof(desc), "Genre: %s", genre_list[index]);
  101.     descptr[3] = strdup(desc);
  102.   }
  103. }
  104. codec_data_t *mp3_file_check (lib_message_func_t message,
  105.       const char *name, 
  106.       double *max,
  107.       char *desc[4])
  108. {
  109.   int freq = 0, samplesperframe = 0;
  110.   int len;
  111.   mp3_codec_t *mp3;
  112.   int first = 0;
  113.   int framecount = 0;
  114.   int bytes;
  115.   uint32_t framesize;
  116.   len = strlen(name);
  117.   if (strcasecmp(name + len - 4, ".mp3") != 0) {
  118.     return (NULL);
  119.   }
  120.   message(LOG_DEBUG, "mp3", "Begin reading mp3 file");
  121.   mp3 = (mp3_codec_t *)malloc(sizeof(mp3_codec_t));
  122.   memset(mp3, 0, sizeof(mp3_codec_t));
  123.   mp3->m_ifile = fopen(name, FOPEN_READ_BINARY);
  124.   if (mp3->m_ifile == NULL) {
  125.     free(mp3);
  126.     return NULL;
  127.   }
  128.   mp3->m_buffer = (uint8_t *)malloc(1024);
  129.   if (mp3->m_buffer == NULL) {
  130.     fclose(mp3->m_ifile);
  131.     free(mp3);
  132.     return NULL;
  133.   }
  134.   mp3->m_buffer_size_max = 1024;
  135.   
  136.   mp3->m_mp3_info = new MPEGaudio();
  137.   mp3->m_fpos = new CFilePosRecorder;
  138.   while (feof(mp3->m_ifile) == 0) {
  139.     if (mp3->m_buffer_on + 3 >= mp3->m_buffer_size) {
  140.       uint32_t diff = mp3->m_buffer_size - mp3->m_buffer_on;
  141.       if (diff > 0) {
  142. memcpy(mp3->m_buffer,
  143.        &mp3->m_buffer[mp3->m_buffer_on],
  144.        diff);
  145.       }
  146.       mp3->m_buffer_size = diff;
  147.       int value = fread(mp3->m_buffer,
  148. 1,  
  149. mp3->m_buffer_size_max - diff,
  150. mp3->m_ifile);
  151.       if (value <= 0) {
  152. message(LOG_DEBUG, "mp3file", "fread returned %d %d", value, diff);
  153. continue;
  154.       }
  155.       mp3->m_buffer_size += value;
  156.       mp3->m_buffer_on = 0;
  157.     }
  158.     
  159.     bytes = 
  160.       mp3->m_mp3_info->findheader(&mp3->m_buffer[mp3->m_buffer_on], 
  161.   mp3->m_buffer_size - mp3->m_buffer_on, 
  162.   &framesize);
  163.     if (bytes < 0) {
  164.       mp3->m_buffer_on = mp3->m_buffer_size - 3;
  165.     } else {
  166.       mp3->m_buffer_on += bytes;  // skipped bytes
  167.       // check framesize as compared to m_buffersize_max
  168.       if (mp3->m_buffer_on + framesize > mp3->m_buffer_size) {
  169. int extra = mp3->m_buffer_on + framesize - mp3->m_buffer_size;
  170. int val = fseek(mp3->m_ifile, extra, SEEK_CUR);
  171. mp3->m_buffer_on = 0;
  172. mp3->m_buffer_size = 0;
  173. if (val < 0) {
  174.   message(LOG_DEBUG, "mp3", "fseek returned %d errno %d", val, errno);
  175.   continue;
  176. }
  177.       } else {
  178. mp3->m_buffer_on += framesize;
  179.       }
  180.   
  181.       if (first == 0) {
  182. first = 1;
  183. freq = mp3->m_mp3_info->getfrequency();
  184. samplesperframe = 32;
  185. if (mp3->m_mp3_info->getlayer() == 3) {
  186.   samplesperframe *= 18;
  187.   if (mp3->m_mp3_info->getversion() == 0) {
  188.     samplesperframe *= 2;
  189.   }
  190. } else {
  191.   samplesperframe *= SCALEBLOCK;
  192.   if (mp3->m_mp3_info->getlayer() == 2) {
  193.     samplesperframe *= 3;
  194.   }
  195. }
  196. mp3->m_samplesperframe = samplesperframe;
  197. mp3->m_freq = freq;
  198.       }
  199.       if ((framecount % 16) == 0) {
  200. long current;
  201. current = ftell(mp3->m_ifile);
  202. current -= framesize;
  203. current -= mp3->m_buffer_size - mp3->m_buffer_on;
  204. uint64_t calc;
  205. calc = framecount * mp3->m_samplesperframe * M_LLU;
  206. calc /= mp3->m_freq;
  207. mp3->m_fpos->record_point(current, calc, framecount);
  208.       }
  209.       framecount++;
  210.     }
  211.   }
  212.   message(LOG_INFO, "mp3", "freq %d samples %d fps %d", freq, samplesperframe, 
  213.       freq / samplesperframe);
  214.   double maxtime;
  215.   maxtime = (double) samplesperframe * (double)framecount;
  216.   maxtime /= (double)freq;
  217.   message(LOG_INFO, "mp3", "max playtime %g", maxtime);
  218.   *max = maxtime;
  219.   read_mp3_file_for_tag(mp3, desc);
  220.   rewind(mp3->m_ifile);
  221.   return ((codec_data_t *)mp3);
  222. }
  223. int mp3_file_next_frame (codec_data_t *your_data,
  224.  uint8_t **buffer,
  225.  uint64_t *ts)
  226. {
  227.   mp3_codec_t *mp3;
  228.   int bytes_skipped;
  229.   uint32_t framesize;
  230.   mp3 = (mp3_codec_t *)your_data;
  231.   while (1) {
  232.     if (mp3->m_buffer_on + 3 >= mp3->m_buffer_size) {
  233.       int32_t diff = mp3->m_buffer_size - mp3->m_buffer_on;
  234.       if (diff < 0) {
  235. mp3->m_buffer_size = 0;
  236. mp3->m_buffer_on = 0;
  237. return 0;
  238.       }
  239.       if (diff > 0) {
  240. memcpy(mp3->m_buffer,
  241.        &mp3->m_buffer[mp3->m_buffer_on],
  242.        diff);
  243.       } 
  244.       mp3->m_buffer_size = diff;
  245.       int readbytes = fread(mp3->m_buffer, 
  246.     1, 
  247.     mp3->m_buffer_size_max - diff,
  248.     mp3->m_ifile);
  249.       mp3->m_buffer_on = 0;
  250.       if (readbytes <= 0) {
  251. mp3->m_buffer_size = 0;
  252. return 0;
  253.       }
  254.       mp3->m_buffer_size += readbytes;
  255.     }
  256.       
  257.     bytes_skipped = 
  258.       mp3->m_mp3_info->findheader(&mp3->m_buffer[mp3->m_buffer_on], 
  259.   mp3->m_buffer_size - mp3->m_buffer_on, 
  260.   &framesize);
  261.     if (bytes_skipped < 0) {
  262.       mp3->m_buffer_on = mp3->m_buffer_size;
  263.       continue;
  264.     }
  265.     
  266.     mp3->m_buffer_on += bytes_skipped;  // skipped bytes
  267.     
  268.     // check framesize as compared to m_buffersize_max
  269.     if (mp3->m_buffer_on + framesize > mp3->m_buffer_size) {
  270.       uint32_t left_in_buffer;
  271.       left_in_buffer = mp3->m_buffer_size - mp3->m_buffer_on;
  272.       memmove(mp3->m_buffer,
  273.       mp3->m_buffer + mp3->m_buffer_on,
  274.       left_in_buffer);
  275.       
  276.       int temp = fread(mp3->m_buffer + left_in_buffer,
  277.        1, 
  278.        mp3->m_buffer_on,
  279.        mp3->m_ifile);
  280.       mp3->m_buffer_size = temp + left_in_buffer;
  281.       mp3->m_buffer_on = 0;
  282.     } 
  283.     // We have a buffer.  Make sure m_buffer_on points past the
  284.     // buffer.
  285.     *buffer = mp3->m_buffer + mp3->m_buffer_on;
  286.     mp3->m_buffer_on += framesize;
  287.     // Calculate the current time
  288.     uint64_t calc;
  289.     calc = mp3->m_framecount * mp3->m_samplesperframe * M_LLU;
  290.     calc /= mp3->m_freq;
  291.     *ts = calc;
  292.     mp3->m_framecount++;
  293.     return (framesize);
  294.   }
  295. }
  296. int mp3_raw_file_seek_to (codec_data_t *ptr, uint64_t ts)
  297. {
  298.   mp3_codec_t *mp3 = (mp3_codec_t *)ptr;
  299.   const frame_file_pos_t *fpos = mp3->m_fpos->find_closest_point(ts);
  300.   mp3->m_framecount = fpos->frames;
  301.   mp3->m_buffer_on = 0;
  302.   mp3->m_buffer_size = 0;
  303.   fseek(mp3->m_ifile, fpos->file_position, SEEK_SET);
  304.   return 0;
  305. }
  306.   
  307.   
  308. /* end file mp3_file.cpp */