📄 celp.cpp
字号:
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is MPEG4IP.
*
* The Initial Developer of the Original Code is Cisco Systems Inc.
* Portions created by Cisco Systems Inc. are
* Copyright (C) Cisco Systems Inc. 2000, 2001. All Rights Reserved.
*
* Contributor(s):
* Massimo Villari mvillari@cisco.com
*/
#include "celp.h"
#include "bitstreamStruct.h"
#include "dec_lpc.h"
#include "celp_decoder.h"
//#include "../include/audio.h"
//#include "../include/austream.h"
#include <mp4util/mpeg4_audio_config.h>
#include <mp4util/mpeg4_sdp.h>
#include <mp4v2/mp4.h>
#define DEBUG_SYNC 2
#define bit2byte(a) (((a)+8-1)/8)
const char *celplib="celp";
/*
* Create CELP Codec class
*/
static codec_data_t *celp_codec_create (format_list_t *media_fmt,
audio_info_t *audio,
const uint8_t *userdata,
uint32_t userdata_size,
audio_vft_t *vft,
void *ifptr)
{
int i;
celp_codec_t *celp;
celp = (celp_codec_t *)malloc(sizeof(celp_codec_t));
memset(celp, 0, sizeof(celp_codec_t));
#if 1
celp->m_vft = vft;
celp->m_ifptr = ifptr;
fmtp_parse_t *fmtp = NULL;
BsInit(0, 0, 0);
// Start setting up CELP stuff...
celp->m_resync_with_header = 1;
celp->m_record_sync_time = 1;
celp->m_celp_inited = 0;
celp->m_audio_inited = 0;
//celp->m_temp_buff = (float *)malloc(4096);
// Use media_fmt to indicate that we're streaming.
if (media_fmt != NULL) {
// haven't checked for null buffer
// This is not necessarilly right - it is, for the most part, but
// we should be reading the fmtp statement, and looking at the config.
// (like we do below in the userdata section...
celp->m_freq = media_fmt->rtpmap->clock_rate;
fmtp = parse_fmtp_for_mpeg4(media_fmt->fmt_param, vft->log_msg);
if (fmtp != NULL) {
userdata = fmtp->config_binary;
userdata_size = fmtp->config_binary_len;
}
} else {
if (audio != NULL) {
celp->m_freq = audio->freq;
} else {
celp->m_freq = 44100;
}
}
//celp->m_chans = 1; // this may be wrong - the isma spec, Appendix A.1.1 of
// Appendix H says the default is 1 channel...
//celp->m_output_frame_size = 2048;
// celp->m_object_type = 8;CELP AACMAIN;
mpeg4_audio_config_t audio_config;
if (userdata != NULL || fmtp != NULL) {
celp_message(LOG_DEBUG, celplib, "config len %d %02x %02x %02x %02x",
userdata_size, userdata[0], userdata[1], userdata[2],
userdata[3]);
decode_mpeg4_audio_config(userdata, userdata_size, &audio_config);
celp->m_object_type = audio_config.audio_object_type;
celp->m_freq = audio_config.frequency;
celp->m_chans = audio_config.channels;
}
// write
BsBitBuffer *bitHeader;
BsBitStream *hdrStream;
bitHeader=BsAllocBuffer(userdata_size * 8);
//wmay removed
bitHeader->numBit=userdata_size*8;
bitHeader->size=userdata_size*8;
memcpy(bitHeader->data,userdata,userdata_size);
hdrStream = BsOpenBufferRead(bitHeader);
BsGetSkip (hdrStream,userdata_size*8-audio_config.codec.celp.NumOfBitsInBuffer);
BsBitBuffer *bBuffer=BsAllocBuffer(userdata_size*8);
BsGetBuffer (hdrStream, bBuffer,audio_config.codec.celp.NumOfBitsInBuffer);
int delayNumSample;
DecLpcInit(celp->m_chans,celp->m_freq,0,NULL,
bBuffer ,&celp->m_output_frame_size,&delayNumSample);
celp->m_msec_per_frame *= M_LLU;
celp->m_msec_per_frame /= celp->m_freq;
celp->m_last=userdata_size;
BsFreeBuffer (bitHeader);
BsFreeBuffer (bBuffer);
celp->m_sampleBuf=(float**)malloc(celp->m_chans*sizeof(float*));
for(i=0;i<celp->m_chans;i++)
// wmay - added 2 times
celp->m_sampleBuf[i]=(float*)malloc(2*celp->m_output_frame_size*sizeof(float));
celp->m_bufs =
(uint16_t *)malloc(sizeof(uint16_t) * 2 * celp->m_chans * celp->m_output_frame_size);
//celp->audiFile = AudioOpenWrite("out1.au",".au",
// celp->m_chans,celp->m_freq);
celp_message(LOG_INFO, celplib,"CELP object type is %d", celp->m_object_type);
//celp_message(LOG_INFO, celplib,"CELP channel are %d", celp->m_chans );
celp_message(LOG_INFO, celplib, "Setting freq to %d", celp->m_freq);
celp_message(LOG_INFO, celplib, "output frame size is %d", celp->m_output_frame_size);
#if DUMP_OUTPUT_TO_FILE
celp->m_outfile = fopen("temp.raw", "w");
#endif
if (fmtp != NULL) {
free_fmtp_parse(fmtp);
}
#endif
celp->m_vft->audio_configure(celp->m_ifptr,
celp->m_freq,
celp->m_chans,
AUDIO_S16SYS,
celp->m_output_frame_size);
return (codec_data_t *)celp;
}
void celp_close (codec_data_t *ptr)
{
int i;
if (ptr == NULL) {
printf("\nin celp close\n");
return;
}
celp_codec_t *celp = (celp_codec_t *)ptr;
if(celp->m_bufs) {
free(celp->m_bufs);
celp->m_bufs=NULL;
}
//AudioClose(celp->audiFile);
// if (celp->m_temp_buff) {
// free(celp->m_temp_buff);
// celp->m_temp_buff = NULL;
// }
if(celp->m_sampleBuf){
for(i=0; i<celp->m_chans;i++) {
free(celp->m_sampleBuf[i]);
celp->m_sampleBuf[i] = NULL;
}
free(celp->m_sampleBuf);
celp->m_sampleBuf = NULL;
}
DecLpcFree();
#if DUMP_OUTPUT_TO_FILE
fclose(celp->m_outfile);
#endif
free(celp);
}
/*
* Handle pause - basically re-init the codec
*/
static void celp_do_pause (codec_data_t *ifptr)
{
celp_codec_t *celp = (celp_codec_t *)ifptr;
celp->m_resync_with_header = 1;
celp->m_record_sync_time = 1;
celp->m_audio_inited = 0;
celp->m_celp_inited = 0;
}
/*
* Decode task call for CELP
*/
static int celp_decode (codec_data_t *ptr,
uint64_t ts,
int from_rtp,
int *sync_frame,
uint8_t *buffer,
uint32_t buflen,
void *userdata)
{
int usedNumBit;
celp_codec_t *celp = (celp_codec_t *)ptr;
if (celp->m_record_sync_time) {
celp->m_current_frame = 0;
celp->m_record_sync_time = 0;
celp->m_current_time = ts;
celp->m_last_rtp_ts = ts;
} else {
if (celp->m_last_rtp_ts == ts) {
celp->m_current_time += celp->m_msec_per_frame;
celp->m_current_frame++;
} else {
celp->m_last_rtp_ts = ts;
celp->m_current_time = ts;
celp->m_current_frame = 0;
}
// Note - here m_current_time should pretty much always be >= rtpts.
// If we're not, we most likely want to stop and resync. We don't
// need to keep decoding - just decode this frame and indicate we
// need a resync... That should handle fast forwards... We need
// someway to handle reverses - perhaps if we're more than .5 seconds
// later...
}
if (celp->m_celp_inited == 0) {
/*
* If not initialized, do so.
*/
//
celp->m_celp_inited = 1;
}
//printf("buflen:%d\n",buflen);
//if ( ((celp->m_last-buflen)/celp->m_last) < 0.2) return (0);
if ( buflen<5) return (-1);
BsBitBuffer local;
local.data= (unsigned char *)buffer;
local.numBit=buflen*8;
local.size=buflen*8;
DecLpcFrame(&local,celp->m_sampleBuf,&usedNumBit);
//AudioWriteData(celp->audiFile,celp->m_sampleBuf,celp->m_output_frame_size);
int chan,sample;
uint8_t *now = celp->m_vft->audio_get_buffer(celp->m_ifptr);
if (now != NULL) {
uint16_t *buf = (uint16_t *)now;
for(chan=0;chan<celp->m_chans;chan++){
for(sample=0;sample < celp->m_output_frame_size; sample++){
buf[sample +(chan*celp->m_output_frame_size)]=
(uint16_t)celp->m_sampleBuf[chan][sample];
}
}
}
#if DUMP_OUTPUT_TO_FILE
fwrite(buff, celp->m_output_frame_size * 4, 1, celp->m_outfile);
#endif
celp->m_vft->audio_filled_buffer(celp->m_ifptr,
celp->m_current_time,
celp->m_resync_with_header);
if (celp->m_resync_with_header == 1) {
celp->m_resync_with_header = 0;
#ifdef DEBUG_SYNC
celp_message(LOG_DEBUG, celplib, "Back to good at "LLU, celp->m_current_time);
#endif
}
return bit2byte(usedNumBit);
}
static const char *celp_compressors[] = {
"celp ",
"mp4a",
NULL
};
static int celp_codec_check (lib_message_func_t message,
const char *compressor,
int type,
int profile,
format_list_t *fptr,
const uint8_t *userdata,
uint32_t userdata_size)
{
fmtp_parse_t *fmtp = NULL;
if (compressor != NULL &&
strcasecmp(compressor, "MP4 FILE") == 0 &&
type != -1) {
switch (type) {
case MP4_MPEG4_AUDIO_TYPE:
break;
default:
return -1;
}
}
if (fptr != NULL &&
fptr->rtpmap != NULL &&
fptr->rtpmap->encode_name != NULL) {
if (strcasecmp(fptr->rtpmap->encode_name, "mpeg4-generic") != 0) {
return -1;
}
if (userdata == NULL) {
fmtp = parse_fmtp_for_mpeg4(fptr->fmt_param, message);
if (fmtp != NULL) {
userdata = fmtp->config_binary;
userdata_size = fmtp->config_binary_len;
}
}
}
if (userdata != NULL) {
mpeg4_audio_config_t audio_config;
decode_mpeg4_audio_config(userdata, userdata_size, &audio_config);
if (fmtp != NULL) free_fmtp_parse(fmtp);
if (audio_object_type_is_celp(&audio_config) == 0) {
return -1;
}
return 1;
}
if (compressor != NULL) {
const char **lptr = celp_compressors;
while (*lptr != NULL) {
if (strcasecmp(*lptr, compressor) == 0) {
return 1;
}
lptr++;
}
}
return -1;
}
AUDIO_CODEC_PLUGIN("celp",
celp_codec_create,
celp_do_pause,
celp_decode,
NULL,
celp_close,
celp_codec_check);
/* end file aa.cpp */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -