celp.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.  *              Massimo Villari        mvillari@cisco.com
  20.  */
  21. #include "celp.h"
  22. #include "bitstreamStruct.h"
  23. #include "dec_lpc.h"
  24. #include "celp_decoder.h"
  25. //#include "../include/audio.h"
  26. //#include "../include/austream.h"
  27. #include <mp4util/mpeg4_audio_config.h>
  28. #include <mp4util/mpeg4_sdp.h>
  29. #include <mp4v2/mp4.h>
  30. #define DEBUG_SYNC 2
  31. #define bit2byte(a) (((a)+8-1)/8)
  32. const char *celplib="celp";
  33. /*
  34.  * Create CELP Codec class
  35.  */
  36. static codec_data_t *celp_codec_create (format_list_t *media_fmt,
  37. audio_info_t *audio,
  38. const uint8_t *userdata,
  39. uint32_t userdata_size,
  40. audio_vft_t *vft,
  41. void *ifptr)
  42. {
  43.   int i;
  44.   celp_codec_t *celp;
  45.   celp = (celp_codec_t *)malloc(sizeof(celp_codec_t));
  46.   memset(celp, 0, sizeof(celp_codec_t));
  47.   
  48. #if 1   
  49.   celp->m_vft = vft;
  50.   celp->m_ifptr = ifptr;
  51.   fmtp_parse_t *fmtp = NULL;
  52.   BsInit(0, 0, 0);
  53.   
  54.   // Start setting up CELP stuff...
  55.   
  56.   celp->m_resync_with_header = 1;
  57.   celp->m_record_sync_time = 1;
  58.   
  59.   celp->m_celp_inited = 0;
  60.   celp->m_audio_inited = 0;
  61.   //celp->m_temp_buff = (float *)malloc(4096);
  62.   
  63.   // Use media_fmt to indicate that we're streaming.
  64.   if (media_fmt != NULL) {
  65.     // haven't checked for null buffer
  66.     // This is not necessarilly right - it is, for the most part, but
  67.     // we should be reading the fmtp statement, and looking at the config.
  68.     // (like we do below in the userdata section...
  69.     celp->m_freq = media_fmt->rtpmap->clock_rate;
  70.     fmtp = parse_fmtp_for_mpeg4(media_fmt->fmt_param, vft->log_msg);
  71.     if (fmtp != NULL) {
  72.       userdata = fmtp->config_binary;
  73.       userdata_size = fmtp->config_binary_len;
  74.     }
  75.   } else {
  76.     if (audio != NULL) {
  77.       celp->m_freq = audio->freq;
  78.     } else {
  79.       celp->m_freq = 44100;
  80.     }
  81.   }
  82.   //celp->m_chans = 1; // this may be wrong - the isma spec, Appendix A.1.1 of
  83.   // Appendix H says the default is 1 channel...
  84.   //celp->m_output_frame_size = 2048;
  85.   // celp->m_object_type = 8;CELP  AACMAIN;
  86.   mpeg4_audio_config_t audio_config;
  87.   if (userdata != NULL || fmtp != NULL) {
  88.     
  89.     celp_message(LOG_DEBUG, celplib, "config len %d %02x %02x %02x %02x", 
  90.  userdata_size, userdata[0], userdata[1], userdata[2], 
  91.  userdata[3]);
  92.     decode_mpeg4_audio_config(userdata, userdata_size, &audio_config);
  93.     celp->m_object_type = audio_config.audio_object_type;
  94.     celp->m_freq = audio_config.frequency;
  95.     celp->m_chans = audio_config.channels;
  96.   }
  97.   // write 
  98.   BsBitBuffer *bitHeader;
  99.   BsBitStream *hdrStream;
  100.   bitHeader=BsAllocBuffer(userdata_size * 8);
  101.   //wmay removed
  102.   bitHeader->numBit=userdata_size*8;
  103.   bitHeader->size=userdata_size*8;
  104.   memcpy(bitHeader->data,userdata,userdata_size);
  105.   hdrStream = BsOpenBufferRead(bitHeader);
  106.   BsGetSkip (hdrStream,userdata_size*8-audio_config.codec.celp.NumOfBitsInBuffer);
  107.   BsBitBuffer *bBuffer=BsAllocBuffer(userdata_size*8);
  108.   BsGetBuffer (hdrStream, bBuffer,audio_config.codec.celp.NumOfBitsInBuffer);
  109.   int delayNumSample;
  110.   DecLpcInit(celp->m_chans,celp->m_freq,0,NULL,
  111.      bBuffer ,&celp->m_output_frame_size,&delayNumSample);
  112.   celp->m_msec_per_frame *= M_LLU;
  113.   celp->m_msec_per_frame /= celp->m_freq;
  114.   celp->m_last=userdata_size;
  115.   BsFreeBuffer (bitHeader);
  116.   BsFreeBuffer (bBuffer);
  117.   celp->m_sampleBuf=(float**)malloc(celp->m_chans*sizeof(float*));
  118.   for(i=0;i<celp->m_chans;i++)
  119.     // wmay - added 2 times
  120.     celp->m_sampleBuf[i]=(float*)malloc(2*celp->m_output_frame_size*sizeof(float));
  121.   celp->m_bufs = 
  122.     (uint16_t *)malloc(sizeof(uint16_t) * 2 * celp->m_chans * celp->m_output_frame_size);
  123.   //celp->audiFile = AudioOpenWrite("out1.au",".au",
  124.   //   celp->m_chans,celp->m_freq);
  125.   celp_message(LOG_INFO, celplib,"CELP object type is %d", celp->m_object_type);
  126.   //celp_message(LOG_INFO, celplib,"CELP channel are %d", celp->m_chans );
  127.   celp_message(LOG_INFO, celplib, "Setting freq to %d", celp->m_freq);
  128.   celp_message(LOG_INFO, celplib, "output frame size is %d", celp->m_output_frame_size);
  129.   
  130.  
  131. #if DUMP_OUTPUT_TO_FILE
  132.   celp->m_outfile = fopen("temp.raw", "w");
  133. #endif
  134.   if (fmtp != NULL) {
  135.     free_fmtp_parse(fmtp);
  136.   }
  137. #endif  
  138.   celp->m_vft->audio_configure(celp->m_ifptr,
  139.        celp->m_freq, 
  140.        celp->m_chans, 
  141.        AUDIO_S16SYS,
  142.        celp->m_output_frame_size);
  143.   return (codec_data_t *)celp;
  144. }
  145. void celp_close (codec_data_t *ptr)
  146. {
  147.   
  148.   int i;
  149.   if (ptr == NULL) {
  150.     printf("nin celp closen");
  151.     
  152.     return;
  153.   }
  154.  
  155.   celp_codec_t *celp = (celp_codec_t *)ptr;
  156.  
  157.   if(celp->m_bufs) {
  158.     free(celp->m_bufs);
  159.     celp->m_bufs=NULL;
  160.   }
  161.   //AudioClose(celp->audiFile);
  162.   
  163.   // if (celp->m_temp_buff) {
  164.   //    free(celp->m_temp_buff);
  165.   //    celp->m_temp_buff = NULL;
  166.   //  }
  167.   if(celp->m_sampleBuf){
  168.     for(i=0; i<celp->m_chans;i++) {
  169.       free(celp->m_sampleBuf[i]);
  170.       celp->m_sampleBuf[i] = NULL;
  171.     }
  172.     free(celp->m_sampleBuf);
  173.     celp->m_sampleBuf = NULL;
  174.   }
  175.   DecLpcFree();
  176. #if DUMP_OUTPUT_TO_FILE
  177.   fclose(celp->m_outfile);
  178. #endif
  179.   free(celp);
  180.   
  181. /*
  182.  * Handle pause - basically re-init the codec
  183.  */
  184. static void celp_do_pause (codec_data_t *ifptr)
  185. {
  186.   
  187.   celp_codec_t *celp = (celp_codec_t *)ifptr;
  188.   celp->m_resync_with_header = 1;
  189.   celp->m_record_sync_time = 1;
  190.   celp->m_audio_inited = 0;
  191.   celp->m_celp_inited = 0;
  192. }
  193. /*
  194.  * Decode task call for CELP
  195.  */
  196. static int celp_decode (codec_data_t *ptr,
  197. uint64_t ts,
  198. int from_rtp,
  199. int *sync_frame,
  200. uint8_t *buffer,
  201. uint32_t buflen,
  202. void *userdata)
  203. {
  204.   int usedNumBit;
  205.   celp_codec_t *celp = (celp_codec_t *)ptr;
  206.   
  207.   if (celp->m_record_sync_time) {
  208.     celp->m_current_frame = 0;
  209.     celp->m_record_sync_time = 0;
  210.     celp->m_current_time = ts;
  211.     celp->m_last_rtp_ts = ts;
  212.   } else {
  213.     if (celp->m_last_rtp_ts == ts) {
  214.       celp->m_current_time += celp->m_msec_per_frame;
  215.       celp->m_current_frame++;
  216.     } else {
  217.       celp->m_last_rtp_ts = ts;
  218.       celp->m_current_time = ts;
  219.       celp->m_current_frame = 0;
  220.     }
  221.     // Note - here m_current_time should pretty much always be >= rtpts.  
  222.     // If we're not, we most likely want to stop and resync.  We don't
  223.     // need to keep decoding - just decode this frame and indicate we
  224.     // need a resync... That should handle fast forwards...  We need
  225.     // someway to handle reverses - perhaps if we're more than .5 seconds
  226.     // later...
  227.   }
  228.   if (celp->m_celp_inited == 0) {
  229.     
  230.     /*
  231.      * If not initialized, do so.  
  232.      */
  233.     
  234.     //
  235.     celp->m_celp_inited = 1;
  236.   }
  237.   //printf("buflen:%dn",buflen);
  238.   //if ( ((celp->m_last-buflen)/celp->m_last) < 0.2) return (0);
  239.   if ( buflen<5) return (-1);
  240.   
  241.   BsBitBuffer local;
  242.   local.data= (unsigned char *)buffer;
  243.   local.numBit=buflen*8;
  244.   local.size=buflen*8;
  245.   DecLpcFrame(&local,celp->m_sampleBuf,&usedNumBit);
  246.   //AudioWriteData(celp->audiFile,celp->m_sampleBuf,celp->m_output_frame_size);
  247.   int chan,sample;
  248.   uint8_t *now = celp->m_vft->audio_get_buffer(celp->m_ifptr);
  249.   if (now != NULL) {
  250.     uint16_t *buf = (uint16_t *)now;
  251.     
  252.     for(chan=0;chan<celp->m_chans;chan++){
  253.       for(sample=0;sample < celp->m_output_frame_size; sample++){
  254. buf[sample +(chan*celp->m_output_frame_size)]=
  255.   (uint16_t)celp->m_sampleBuf[chan][sample];
  256.       }
  257.     }
  258.   }
  259. #if DUMP_OUTPUT_TO_FILE
  260.   fwrite(buff, celp->m_output_frame_size * 4, 1, celp->m_outfile);
  261. #endif
  262.   celp->m_vft->audio_filled_buffer(celp->m_ifptr,
  263.    celp->m_current_time, 
  264.    celp->m_resync_with_header);
  265.   if (celp->m_resync_with_header == 1) {
  266.     celp->m_resync_with_header = 0;
  267. #ifdef DEBUG_SYNC
  268.     celp_message(LOG_DEBUG, celplib, "Back to good at "LLU, celp->m_current_time);
  269. #endif
  270.   }
  271.       
  272.   return bit2byte(usedNumBit);
  273. }
  274. static const char *celp_compressors[] = {
  275.   "celp ",
  276.   "mp4a",
  277.   NULL
  278. };
  279. static int celp_codec_check (lib_message_func_t message,
  280.      const char *compressor,
  281.      int type,
  282.      int profile,
  283.      format_list_t *fptr, 
  284.      const uint8_t *userdata,
  285.      uint32_t userdata_size)
  286. {
  287.   fmtp_parse_t *fmtp = NULL;
  288.   if (compressor != NULL && 
  289.       strcasecmp(compressor, "MP4 FILE") == 0 &&
  290.       type != -1) {
  291.     switch (type) {
  292.     case MP4_MPEG4_AUDIO_TYPE:
  293.       break;
  294.     default:
  295.       return -1;
  296.     }
  297.   }
  298.   if (fptr != NULL && 
  299.       fptr->rtpmap != NULL &&
  300.       fptr->rtpmap->encode_name != NULL) {
  301.     if (strcasecmp(fptr->rtpmap->encode_name, "mpeg4-generic") != 0) {
  302.       return -1;
  303.     }
  304.     if (userdata == NULL) {
  305.       fmtp = parse_fmtp_for_mpeg4(fptr->fmt_param, message);
  306.       if (fmtp != NULL) {
  307. userdata = fmtp->config_binary;
  308. userdata_size = fmtp->config_binary_len;
  309.       }
  310.     }
  311.   }
  312.   if (userdata != NULL) {
  313.     mpeg4_audio_config_t audio_config;
  314.     decode_mpeg4_audio_config(userdata, userdata_size, &audio_config);
  315.     if (fmtp != NULL) free_fmtp_parse(fmtp);
  316.     if (audio_object_type_is_celp(&audio_config) == 0) {
  317.       return -1;
  318.     }
  319.     return 1;
  320.   }
  321.   if (compressor != NULL) {
  322.     const char **lptr = celp_compressors;
  323.     while (*lptr != NULL) {
  324.       if (strcasecmp(*lptr, compressor) == 0) {
  325. return 1;
  326.       }
  327.       lptr++;
  328.     }
  329.   }
  330.   return -1;
  331. }
  332. AUDIO_CODEC_PLUGIN("celp",
  333.    celp_codec_create,
  334.    celp_do_pause,
  335.    celp_decode,
  336.    NULL,
  337.    celp_close,
  338.    celp_codec_check);
  339. /* end file aa.cpp */