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

流媒体/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. #include "mp3if.h"
  22. #include <mp4av/mp4av.h>
  23. #include <mp4v2/mp4.h>
  24. #define mp3_message mp3->m_vft->log_msg
  25. #define DEBUG_SYNC 1
  26. /*
  27.  * Create CMP3Codec class
  28.  */
  29. static codec_data_t *mp3_codec_create (format_list_t *media_fmt,
  30.        audio_info_t *audio,
  31.        const uint8_t *userdata,
  32.        uint32_t userdata_size,
  33.        audio_vft_t *vft,
  34.        void *ifptr)
  35. {
  36.   mp3_codec_t *mp3;
  37.   mp3 = (mp3_codec_t *)malloc(sizeof(mp3_codec_t));
  38.   if (mp3 == NULL) return NULL;
  39.   memset(mp3, 0, sizeof(mp3_codec_t));
  40.   mp3->m_vft = vft;
  41.   mp3->m_ifptr = ifptr;
  42. #ifdef OUTPUT_TO_FILE
  43.   mp3->m_output_file = fopen("smpeg.raw", "w");
  44. #endif
  45.   mp3->m_mp3_info = new MPEGaudio();
  46.   mp3->m_resync_with_header = 1;
  47.   mp3->m_record_sync_time = 1;
  48.   mp3->m_audio_inited = 0;
  49.   // Use media_fmt to indicate that we're streaming.
  50.   // create a CInByteStreamMem that will be used to copy from the
  51.   // streaming packet for use locally.  This will allow us, if we need
  52.   // to skip, to get the next frame.
  53.   // we really shouldn't need to set this here...
  54.   if (media_fmt && media_fmt->rtpmap) 
  55.     mp3->m_freq = media_fmt->rtpmap->clock_rate;
  56.   else if (audio)
  57.     mp3->m_freq = audio->freq;
  58.   else 
  59.     mp3->m_freq = 44100;
  60.   return ((codec_data_t *)mp3);
  61. }
  62. static void mp3_close (codec_data_t *ptr)
  63. {
  64.   mp3_codec_t *mp3 = (mp3_codec_t *)ptr;
  65.   if (mp3->m_mp3_info) {
  66.     delete mp3->m_mp3_info;
  67.     mp3->m_mp3_info = NULL;
  68.   }
  69. #ifdef OUTPUT_TO_FILE
  70.   fclose(mp3->m_output_file);
  71. #endif
  72.   if (mp3->m_ifile != NULL) {
  73.     fclose(mp3->m_ifile);
  74.     mp3->m_ifile = NULL;
  75.   }
  76.   if (mp3->m_buffer != NULL) {
  77.     free(mp3->m_buffer);
  78.     mp3->m_buffer = NULL;
  79.   }
  80.   if (mp3->m_fpos != NULL) {
  81.     delete mp3->m_fpos;
  82.     mp3->m_fpos = NULL;
  83.   }
  84.   free(mp3);
  85. }
  86. /*
  87.  * Handle pause - basically re-init the codec
  88.  */
  89. static void mp3_do_pause (codec_data_t *ifptr)
  90. {
  91.   mp3_codec_t *mp3 = (mp3_codec_t *)ifptr;
  92.   mp3->m_resync_with_header = 1;
  93.   mp3->m_record_sync_time = 1;
  94.   mp3->m_audio_inited = 0;
  95. }
  96. /*
  97.  * Decode task call for MP3
  98.  */
  99. static int mp3_decode (codec_data_t *ptr,
  100.        uint64_t ts, 
  101.        int from_rtp, 
  102.        int *sync_frame,
  103.        uint8_t *buffer,
  104.        uint32_t buflen,
  105.        void *userdata)
  106. {
  107.   int bits = -1;
  108.   mp3_codec_t *mp3 = (mp3_codec_t *)ptr;
  109.   if (mp3->m_audio_inited == 0) {
  110.     // handle initialization here...
  111.     // Make sure that we read the header to make sure that
  112.     // the frequency/number of channels goes through...
  113.     bits = mp3->m_mp3_info->findheader(buffer, buflen);
  114.     if (bits < 0) {
  115.       mp3_message(LOG_DEBUG, "libmp3", "Couldn't load mp3 header");
  116.       return (-1);
  117.     }
  118.       
  119.     buffer += bits;
  120.     mp3->m_chans = mp3->m_mp3_info->isstereo() ? 2 : 1;
  121.     mp3->m_freq = mp3->m_mp3_info->getfrequency();
  122.     
  123.     mp3->m_samplesperframe = 
  124.       MP4AV_Mp3GetHdrSamplingWindow(MP4AV_Mp3HeaderFromBytes(buffer));
  125.     mp3_message(LOG_DEBUG, "libmp3", "chans %d freq %d samples %d", 
  126. mp3->m_chans, mp3->m_freq, mp3->m_samplesperframe);
  127.     mp3->m_vft->audio_configure(mp3->m_ifptr,
  128. mp3->m_freq, 
  129. mp3->m_chans, 
  130. AUDIO_S16SYS, 
  131. mp3->m_samplesperframe);
  132.     mp3->m_audio_inited = 1;
  133.     mp3->m_last_rtp_ts = ts - 1; // so we meet the critera below
  134.   }
  135.       
  136.   uint8_t *buff;
  137.     /* 
  138.      * Get an audio buffer
  139.      */
  140.   buff = mp3->m_vft->audio_get_buffer(mp3->m_ifptr);
  141.   if (buff == NULL) {
  142.     //mp3_message(LOG_DEBUG, "mp3", "Can't get buffer in mp3 ts" LLU, ts);
  143.     return (-1);
  144.   }
  145.   bits = mp3->m_mp3_info->decodeFrame(buff, buffer, buflen);
  146.   if (bits > 4) {
  147.     if (mp3->m_last_rtp_ts == ts) {
  148. #if 0
  149.       mp3_message(LOG_DEBUG, "mp3",
  150.   "ts %llu current time %llu spf %d freq %d", 
  151.   ts, mp3->m_current_time, mp3->m_samplesperframe, 
  152.   mp3->m_freq);
  153. #endif
  154.       mp3->m_current_time += ((mp3->m_samplesperframe * 1000) / mp3->m_freq);
  155.     } else {
  156.       mp3->m_last_rtp_ts = ts;
  157.       mp3->m_current_time = ts;
  158.     }
  159. #ifdef OUTPUT_TO_FILE
  160.     fwrite(buff, mp3->m_chans * mp3->m_samplesperframe * sizeof(ushort), 1, mp3->m_output_file);
  161. #endif
  162.     /*
  163.      * good result - give it to audio sync class
  164.      * May want to check frequency, number of channels here...
  165.      */
  166.     mp3->m_vft->audio_filled_buffer(mp3->m_ifptr, 
  167.     mp3->m_current_time, 
  168.     mp3->m_resync_with_header);
  169.     if (mp3->m_resync_with_header == 1) {
  170.       mp3->m_resync_with_header = 0;
  171. #ifdef DEBUG_SYNC
  172.       mp3_message(LOG_DEBUG, "libmp3", 
  173.   "Back to good at %llu", mp3->m_current_time);
  174. #endif
  175.     }
  176.       
  177.   } else {
  178.     mp3->m_resync_with_header = 1;
  179.     mp3_message(LOG_DEBUG, "libmp3", "decode problem %d - at "LLU, 
  180. bits, mp3->m_current_time);
  181.     bits = -1;
  182.   }
  183.   return (bits);
  184. }
  185. static const char *mp3_compressors[] = {
  186.   "mp3 ",
  187.   "mp3", 
  188.   "ms",
  189.   NULL
  190. };
  191. static int mp3_codec_check (lib_message_func_t message,
  192.     const char *compressor,
  193.     int audio_type,
  194.     int profile,
  195.     format_list_t *fptr,
  196.     const uint8_t *userdata,
  197.     uint32_t userdata_size)
  198. {
  199.   if (compressor != NULL && 
  200.       (strcasecmp(compressor, "MP4 FILE") == 0) &&
  201.       (audio_type != -1)) {
  202.     switch (audio_type) {
  203.     case MP4_MPEG1_AUDIO_TYPE:
  204.     case MP4_MPEG2_AUDIO_TYPE:
  205.       return 1;
  206.     default:
  207.       return -1;
  208.     }
  209.   }
  210.   if (compressor != NULL) {
  211.     if ((strcasecmp(compressor, "AVI FILE") == 0) &&
  212. (audio_type == 85)) {
  213.       return 1;
  214.     }
  215.     if ((strcasecmp(compressor, "MPEG FILE") == 0) &&
  216. (audio_type == 1)) { // AUDIO_MPEG def from libmpeg3
  217.       return 1;
  218.     }
  219.   }
  220.   if (fptr != NULL) {
  221.     if (strcmp(fptr->fmt, "14") == 0) {
  222.       return 1;
  223.     }
  224.     if (fptr->rtpmap != NULL && fptr->rtpmap->encode_name != NULL) {
  225.       if (strcasecmp(fptr->rtpmap->encode_name, "MPA") == 0) {
  226. return 1;
  227.       }
  228.       if (strcasecmp(fptr->rtpmap->encode_name, "mpa-robust") == 0) {
  229. return 1;
  230.       }
  231.     }
  232.     return -1;
  233.   }
  234.   if (compressor != NULL) {
  235.     const char **lptr = mp3_compressors;
  236.     while (*lptr != NULL) {
  237.       if (strcasecmp(*lptr, compressor) == 0) {
  238. return 1;
  239.       }
  240.       lptr++;
  241.     }
  242.   }
  243.   return -1;
  244. }
  245. static int mp3_file_eof (codec_data_t *ifptr)
  246. {
  247.   mp3_codec_t *mp3 = (mp3_codec_t *)ifptr;
  248.   return mp3->m_buffer_on == mp3->m_buffer_size && feof(mp3->m_ifile);
  249. }
  250. AUDIO_CODEC_WITH_RAW_FILE_PLUGIN("mp3", 
  251.  mp3_codec_create,
  252.  mp3_do_pause,
  253.  mp3_decode,
  254.  NULL,
  255.  mp3_close,
  256.  mp3_codec_check,
  257.  mp3_file_check,
  258.  mp3_file_next_frame,
  259.  NULL,
  260.  mp3_raw_file_seek_to,
  261.  mp3_file_eof);
  262. /* end file mp3.cpp */