aac.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. #include "aac.h"
  22. #include <mp4util/mpeg4_audio_config.h>
  23. #include <mp4util/mpeg4_sdp.h>
  24. #include <mp4v2/mp4.h>
  25. #define DEBUG_SYNC 2
  26. const char *aaclib="aac";
  27. /*
  28.  * Create CAACodec class
  29.  */
  30. static codec_data_t *aac_codec_create (format_list_t *media_fmt,
  31.        audio_info_t *audio,
  32.        const uint8_t *userdata,
  33.        uint32_t userdata_size,
  34.        audio_vft_t *vft,
  35.        void *ifptr)
  36. {
  37.   aac_codec_t *aac;
  38.   aac = (aac_codec_t *)malloc(sizeof(aac_codec_t));
  39.   memset(aac, 0, sizeof(aac_codec_t));
  40.   aac->m_vft = vft;
  41.   aac->m_ifptr = ifptr;
  42.   fmtp_parse_t *fmtp = NULL;
  43.   // Start setting up FAAC stuff...
  44.   aac->m_resync_with_header = 1;
  45.   aac->m_record_sync_time = 1;
  46.   
  47.   aac->m_faad_inited = 0;
  48.   aac->m_audio_inited = 0;
  49.   aac->m_temp_buff = (uint8_t *)malloc(4096);
  50.   // Use media_fmt to indicate that we're streaming.
  51.   if (media_fmt != NULL) {
  52.     // haven't checked for null buffer
  53.     // This is not necessarilly right - it is, for the most part, but
  54.     // we should be reading the fmtp statement, and looking at the config.
  55.     // (like we do below in the userdata section...
  56.     aac->m_freq = media_fmt->rtpmap->clock_rate;
  57.     fmtp = parse_fmtp_for_mpeg4(media_fmt->fmt_param, vft->log_msg);
  58.     if (fmtp != NULL) {
  59.       userdata = fmtp->config_binary;
  60.       userdata_size = fmtp->config_binary_len;
  61.     }
  62.   } else {
  63.     if (audio != NULL) {
  64.       aac->m_freq = audio->freq;
  65.     } else {
  66.       aac->m_freq = 44100;
  67.     }
  68.   }
  69.   aac->m_chans = 2; // this may be wrong - the isma spec, Appendix A.1.1 of
  70.   // Appendix H says the default is 1 channel...
  71.   aac->m_output_frame_size = 1024;
  72.   aac->m_object_type = AACMAIN;
  73.   if (userdata != NULL || fmtp != NULL) {
  74.     mpeg4_audio_config_t audio_config;
  75.     decode_mpeg4_audio_config(userdata, userdata_size, &audio_config);
  76.     aac->m_object_type = audio_config.audio_object_type;
  77.     aac->m_freq = audio_config.frequency;
  78.     aac->m_chans = audio_config.channels;
  79.     if (audio_config.codec.aac.frame_len_1024 == 0) {
  80.       aac->m_output_frame_size = 960;
  81.     }
  82.   }
  83.   aa_message(LOG_INFO, aaclib,"AAC object type is %d", aac->m_object_type);
  84.   aac->m_info = faacDecOpen();
  85.   faacDecConfiguration config;
  86.   config.defObjectType = aac->m_object_type;
  87.   config.defSampleRate = aac->m_freq;
  88.   faacDecSetConfiguration(aac->m_info, &config);
  89.   aac->m_msec_per_frame = aac->m_output_frame_size;
  90.   aac->m_msec_per_frame *= M_LLU;
  91.   aac->m_msec_per_frame /= aac->m_freq;
  92.   //  faad_init_bytestream(&m_info->ld, c_read_byte, c_bookmark, m_bytestream);
  93.   aa_message(LOG_INFO, aaclib, "Setting freq to %d", aac->m_freq);
  94. #if DUMP_OUTPUT_TO_FILE
  95.   aac->m_outfile = fopen("temp.raw", "w");
  96. #endif
  97.   if (fmtp != NULL) {
  98.     free_fmtp_parse(fmtp);
  99.   }
  100.   return (codec_data_t *)aac;
  101. }
  102. void aac_close (codec_data_t *ptr)
  103. {
  104.   if (ptr == NULL) {
  105.     printf("nin aac closen");
  106.     return;
  107.   }
  108.   aac_codec_t *aac = (aac_codec_t *)ptr;
  109.   faacDecClose(aac->m_info);
  110.   aac->m_info = NULL;
  111.   if (aac->m_temp_buff) {
  112.     free(aac->m_temp_buff);
  113.     aac->m_temp_buff = NULL;
  114.   }
  115. #if DUMP_OUTPUT_TO_FILE
  116.   fclose(aac->m_outfile);
  117. #endif
  118.   free(aac);
  119. }
  120. /*
  121.  * Handle pause - basically re-init the codec
  122.  */
  123. static void aac_do_pause (codec_data_t *ifptr)
  124. {
  125.   aac_codec_t *aac = (aac_codec_t *)ifptr;
  126.   aac->m_resync_with_header = 1;
  127.   aac->m_record_sync_time = 1;
  128.   aac->m_audio_inited = 0;
  129.   aac->m_faad_inited = 0;
  130.   if (aac->m_temp_buff == NULL) 
  131.     aac->m_temp_buff = (uint8_t *)malloc(4096);
  132. }
  133. /*
  134.  * Decode task call for FAAC
  135.  */
  136. static int aac_decode (codec_data_t *ptr,
  137.        uint64_t ts,
  138.        int from_rtp,
  139.        int *sync_frame,
  140.        uint8_t *buffer,
  141.        uint32_t buflen, 
  142.        void *userdata)
  143. {
  144.   aac_codec_t *aac = (aac_codec_t *)ptr;
  145.   unsigned long bytes_consummed;
  146.   int bits = -1;
  147.   //  struct timezone tz;
  148.   if (aac->m_record_sync_time) {
  149.     aac->m_current_frame = 0;
  150.     aac->m_record_sync_time = 0;
  151.     aac->m_current_time = ts;
  152.     aac->m_last_rtp_ts = ts;
  153.   } else {
  154.     if (aac->m_last_rtp_ts == ts) {
  155.       aac->m_current_time += aac->m_msec_per_frame;
  156.       aac->m_current_frame++;
  157.     } else {
  158.       aac->m_last_rtp_ts = ts;
  159.       aac->m_current_time = ts;
  160.       aac->m_current_frame = 0;
  161.     }
  162.     // Note - here m_current_time should pretty much always be >= rtpts.  
  163.     // If we're not, we most likely want to stop and resync.  We don't
  164.     // need to keep decoding - just decode this frame and indicate we
  165.     // need a resync... That should handle fast forwards...  We need
  166.     // someway to handle reverses - perhaps if we're more than .5 seconds
  167.     // later...
  168.   }
  169.     if (aac->m_faad_inited == 0) {
  170.       /*
  171.        * If not initialized, do so.  
  172.      */
  173.       unsigned long freq, chans;
  174.       faacDecInit(aac->m_info,
  175.   (unsigned char *)buffer,
  176.   &freq,
  177.   &chans);
  178.       aac->m_freq = freq;
  179.       aac->m_chans = chans;
  180.       aac->m_faad_inited = 1;
  181.     }
  182.     uint8_t *buff;
  183.     /* 
  184.      * Get an audio buffer
  185.      */
  186.     if (aac->m_audio_inited == 0) {
  187.       buff = aac->m_temp_buff;
  188.     } else {
  189.       buff = aac->m_vft->audio_get_buffer(aac->m_ifptr);
  190.     }
  191.     if (buff == NULL) {
  192.       //player_debug_message("Can't get buffer in aa");
  193.       return (0);
  194.     }
  195.     unsigned long samples;
  196.     bytes_consummed = buflen;
  197.     bits = faacDecDecode(aac->m_info,
  198.  (unsigned char *)buffer, 
  199.  &bytes_consummed,
  200.  (short *)buff, 
  201.  &samples);
  202.     switch (bits) {
  203.     case FAAD_OK_CHUPDATE:
  204.       if (aac->m_audio_inited != 0) {
  205. int tempchans = faacDecGetProgConfig(aac->m_info, NULL);
  206. if (tempchans != aac->m_chans) {
  207.   aa_message(LOG_NOTICE, aaclib, "chupdate - chans from data is %d", 
  208.        tempchans);
  209. }
  210.       }
  211.       // fall through...
  212.     case FAAD_OK:
  213.       if (aac->m_audio_inited == 0) {
  214. int tempchans = faacDecGetProgConfig(aac->m_info, NULL);
  215. if (tempchans == 0) {
  216.   aac->m_resync_with_header = 1;
  217.   aac->m_record_sync_time = 1;
  218.   return bytes_consummed;
  219. }
  220. if (tempchans != aac->m_chans) {
  221.   aa_message(LOG_NOTICE, aaclib, "chans from data is %d conf %d", 
  222.      tempchans, aac->m_chans);
  223.   aac->m_chans = tempchans;
  224. }
  225. aac->m_vft->audio_configure(aac->m_ifptr,
  226.      aac->m_freq, 
  227.      aac->m_chans, 
  228.      AUDIO_S16SYS, 
  229.      aac->m_output_frame_size);
  230. uint8_t *now = aac->m_vft->audio_get_buffer(aac->m_ifptr);
  231. if (now != NULL) {
  232.   memcpy(now, buff, tempchans * aac->m_output_frame_size * sizeof(int16_t));
  233. }
  234. aac->m_audio_inited = 1;
  235.       }
  236.       /*
  237.        * good result - give it to audio sync class
  238.        */
  239. #if DUMP_OUTPUT_TO_FILE
  240.       fwrite(buff, aac->m_output_frame_size * 4, 1, aac->m_outfile);
  241. #endif
  242.       aac->m_vft->audio_filled_buffer(aac->m_ifptr,
  243.       aac->m_current_time, 
  244.       aac->m_resync_with_header);
  245.       if (aac->m_resync_with_header == 1) {
  246. aac->m_resync_with_header = 0;
  247. #ifdef DEBUG_SYNC
  248. aa_message(LOG_DEBUG, aaclib, "Back to good at "LLU, aac->m_current_time);
  249. #endif
  250.       }
  251.       break;
  252.     default:
  253.       aa_message(LOG_ERR, aaclib, "Bits return is %d", bits);
  254.       aac->m_resync_with_header = 1;
  255. #ifdef DEBUG_SYNC
  256.       aa_message(LOG_ERR, aaclib, "Audio decode problem - at "LLU, 
  257.  aac->m_current_time);
  258. #endif
  259.       break;
  260.     }
  261.   return (bytes_consummed);
  262. }
  263. static const char *aac_compressors[] = {
  264.   "aac ",
  265.   "mp4a",
  266.   NULL
  267. };
  268. static int aac_codec_check (lib_message_func_t message,
  269.     const char *compressor,
  270.     int type,
  271.     int profile,
  272.     format_list_t *fptr, 
  273.     const uint8_t *userdata,
  274.     uint32_t userdata_size)
  275. {
  276.   fmtp_parse_t *fmtp = NULL;
  277.   if (compressor != NULL && 
  278.       strcasecmp(compressor, "MP4 FILE") == 0 &&
  279.       type != -1) {
  280.     switch (type) {
  281.     case MP4_MPEG2_AAC_MAIN_AUDIO_TYPE:
  282.     case MP4_MPEG2_AAC_LC_AUDIO_TYPE:
  283.     case MP4_MPEG2_AAC_SSR_AUDIO_TYPE:
  284.     case MP4_MPEG4_AUDIO_TYPE:
  285.       break;
  286.     default:
  287.       return -1;
  288.     }
  289.   }
  290.   if (fptr != NULL && 
  291.       fptr->rtpmap != NULL &&
  292.       fptr->rtpmap->encode_name != NULL) {
  293.     if (strcasecmp(fptr->rtpmap->encode_name, "mpeg4-generic") != 0) {
  294.       return -1;
  295.     }
  296.     if (userdata == NULL) {
  297.       fmtp = parse_fmtp_for_mpeg4(fptr->fmt_param, message);
  298.       if (fmtp != NULL) {
  299. userdata = fmtp->config_binary;
  300. userdata_size = fmtp->config_binary_len;
  301.       }
  302.     }
  303.   }
  304.   if (userdata != NULL) {
  305.     mpeg4_audio_config_t audio_config;
  306.     decode_mpeg4_audio_config(userdata, userdata_size, &audio_config);
  307.     if (fmtp != NULL) free_fmtp_parse(fmtp);
  308.     if (audio_object_type_is_aac(&audio_config) == 0) {
  309.       return -1;
  310.     }
  311.     return 1;
  312.   }
  313.   if (compressor != NULL) {
  314.     const char **lptr = aac_compressors;
  315.     while (*lptr != NULL) {
  316.       if (strcasecmp(*lptr, compressor) == 0) {
  317. return 1;
  318.       }
  319.       lptr++;
  320.     }
  321.   }
  322.   return -1;
  323. }
  324. AUDIO_CODEC_WITH_RAW_FILE_PLUGIN("aac",
  325.  aac_codec_create,
  326.  aac_do_pause,
  327.  aac_decode,
  328.  NULL, 
  329.  aac_close,
  330.  aac_codec_check,
  331.  aac_file_check,
  332.  aac_file_next_frame,
  333.  aac_file_used_for_frame,
  334.  aac_raw_file_seek_to,
  335.  aac_file_eof);
  336. /* end file aa.cpp */