⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 faad2.cpp

📁 完整的RTP RTSP代码库
💻 CPP
字号:
/*** MPEG4IP plugin for FAAD2** Copyright (C) 2003 Bill May wmay@cisco.com**** This program is free software; you can redistribute it and/or modify** it under the terms of the GNU General Public License as published by** the Free Software Foundation; either version 2 of the License, or** (at your option) any later version.**** This program is distributed in the hope that it will be useful,** but WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the** GNU General Public License for more details.**** You should have received a copy of the GNU General Public License** along with this program; if not, write to the Free Software** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.**** $Id: faad2.cpp,v 1.11 2006/08/07 18:27:06 wmaycisco Exp $**/#include "faad2.h"#include <mpeg4_audio_config.h>#include <mpeg4_sdp.h>#include <mp4.h>#include <mp4av.h>#include <SDL/SDL.h>#define DEBUG_SYNC 2#ifndef M_LLU#define M_LLU M_64#define LLU U64#endifconst char *aaclib="faad2";/* * Create CAACodec class */static codec_data_t *aac_codec_create (const char *stream_type,				       const char *compressor,				       int type,				       int profile,				       format_list_t *media_fmt,				       audio_info_t *audio,				       const uint8_t *userdata,				       uint32_t userdata_size,				       audio_vft_t *vft,				       void *ifptr){  aac_codec_t *aac;  aac = (aac_codec_t *)malloc(sizeof(aac_codec_t));  memset(aac, 0, sizeof(aac_codec_t));  aac->m_vft = vft;  aac->m_ifptr = ifptr;  fmtp_parse_t *fmtp = NULL;  // Start setting up FAAC stuff...  aac->m_record_sync_time = 1;  aac->m_audio_inited = 0;  // 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...    aac->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;    }  }  aac->m_info = faacDecOpen();  unsigned long srate;  unsigned char chan;  if ((userdata == NULL && fmtp == NULL) ||      (faacDecInit2(aac->m_info,             (uint8_t *)userdata,             userdata_size,            &srate,             &chan) < 0)) {      if (fmtp != NULL) free_fmtp_parse(fmtp);      return NULL;  }  mp4AudioSpecificConfig mp4ASC;  aac->m_output_frame_size = 1024;  if (AudioSpecificConfig((unsigned char *)userdata,              userdata_size,              &mp4ASC)) {    if (mp4ASC.frameLengthFlag) {      aac->m_output_frame_size = 960;    }  }  aac->m_freq = srate;  aac->m_chans = chan;  aac->m_faad_inited = 1;  aac->m_msec_per_frame = aac->m_output_frame_size;  aac->m_msec_per_frame *= M_LLU;  aac->m_msec_per_frame /= aac->m_freq;  //  faad_init_bytestream(&m_info->ld, c_read_byte, c_bookmark, m_bytestream);  aa_message(LOG_INFO, aaclib, "Setting freq to %d chans %d", aac->m_freq,	     aac->m_chans);#if DUMP_OUTPUT_TO_FILE  aac->m_outfile = fopen("temp.raw", "w");#endif  if (fmtp != NULL) {    free_fmtp_parse(fmtp);  }  return (codec_data_t *)aac;}void aac_close (codec_data_t *ptr){  if (ptr == NULL) {    return;  }  aac_codec_t *aac = (aac_codec_t *)ptr;  faacDecClose(aac->m_info);  aac->m_info = NULL;#if DUMP_OUTPUT_TO_FILE  fclose(aac->m_outfile);#endif  free(aac);}/* * Handle pause - basically re-init the codec */static void aac_do_pause (codec_data_t *ifptr){  aac_codec_t *aac = (aac_codec_t *)ifptr;  aac->m_record_sync_time = 1;  aac->m_audio_inited = 0;  aac->m_ignore_first_sample = 0;  faacDecPostSeekReset(aac->m_info, 0);}/* * Decode task call for FAAC */static int aac_decode (codec_data_t *ptr,		       frame_timestamp_t *ts,		       int from_rtp,		       int *sync_frame,		       uint8_t *buffer,		       uint32_t buflen,		       void *userdata){  aac_codec_t *aac = (aac_codec_t *)ptr;  unsigned long bytes_consummed;  int bits = -1;  uint32_t freq_timestamp;  freq_timestamp = ts->audio_freq_timestamp;  if (ts->audio_freq != aac->m_freq) {    freq_timestamp = convert_timescale(freq_timestamp,				       ts->audio_freq,				       aac->m_freq);  }  if (aac->m_record_sync_time) {    aac->m_current_frame = 0;    aac->m_record_sync_time = 0;    aac->m_current_time = ts->msec_timestamp;    aac->m_last_rtp_ts = ts->msec_timestamp;  } else {    if (aac->m_last_rtp_ts == ts->msec_timestamp) {      aac->m_current_frame++;      aac->m_current_time = aac->m_last_rtp_ts;      aac->m_current_time += aac->m_output_frame_size * aac->m_current_frame * 	1000 / aac->m_freq;      freq_timestamp += aac->m_output_frame_size * aac->m_current_frame;    } else {      aac->m_last_rtp_ts = ts->msec_timestamp;      aac->m_current_time = ts->msec_timestamp;      aac->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 (aac->m_faad_inited == 0) {    /*     * If not initialized, do so.     */    abort();    unsigned long freq;    unsigned char chans;    faacDecInit(aac->m_info,        (unsigned char *)buffer,        buflen,        &freq,        &chans);    aac->m_freq = freq;    aac->m_chans = chans;    aac->m_faad_inited = 1;  }  uint8_t *buff;  unsigned long samples;  bytes_consummed = buflen;  //aa_message(LOG_DEBUG, aaclib, "decoding %d bits", buflen * 8);  faacDecFrameInfo frame_info;  buff = (uint8_t *)faacDecDecode(aac->m_info,                  &frame_info,                  buffer,                  buflen);  if (buff != NULL) {    bytes_consummed = frame_info.bytesconsumed;#if 0    aa_message(LOG_DEBUG, aaclib, LLU" bytes %d samples %d",           ts, bytes_consummed, frame_info.samples);#endif    if (aac->m_audio_inited != 0) {      int tempchans = frame_info.channels;      if (tempchans != aac->m_chans) {	aa_message(LOG_NOTICE, aaclib, "chupdate - chans from data is %d",		   tempchans);      }    } else {      int tempchans = frame_info.channels;      if (tempchans == 0) {	aa_message(LOG_ERR, aaclib, "initializing aac, returned channels are 0");	aac->m_record_sync_time = 1;	return bytes_consummed;      }      if (frame_info.num_lfe_channels > 0) {	aac->m_chans = 6;      } else {	aac->m_chans = frame_info.num_front_channels + 	  frame_info.num_back_channels;      }      aac->m_freq = frame_info.samplerate;      aac->m_vft->audio_configure(aac->m_ifptr,				  aac->m_freq,				  aac->m_chans,				  AUDIO_FMT_S16,				  aac->m_output_frame_size);      uint8_t *now = aac->m_vft->audio_get_buffer(aac->m_ifptr,						  aac->m_cached_freq_ts,						  aac->m_cached_ts);      aac->m_audio_inited = 1;    }    /*     * good result - give it to audio sync class     */#if DUMP_OUTPUT_TO_FILE    fwrite(buff, aac->m_output_frame_size * 4, 1, aac->m_outfile);#endif    if (frame_info.samples != 0) {      if (aac->m_chans <= 2) {	aac->m_vft->audio_load_buffer(aac->m_ifptr,				      buff,				      frame_info.samples * 2,				      aac->m_cached_freq_ts,				      aac->m_cached_ts);      } else {	int16_t *now = 	  (int16_t *)aac->m_vft->audio_get_buffer(aac->m_ifptr,						  aac->m_cached_freq_ts,						  aac->m_cached_ts);	uint32_t samples = frame_info.samples / aac->m_chans;	int16_t *inptr = (int16_t *)buff;	if (now == NULL) return bytes_consummed;	memset(now, 0, frame_info.samples * sizeof(int16_t));	for (uint32_t ix = 0; ix < samples; ix++) {	  for (unsigned char chx = 0; chx < frame_info.channels; chx++) {	    switch (frame_info.channel_position[chx]) {	    case FRONT_CHANNEL_CENTER:	      now[4] = *inptr++;	      break;	    case FRONT_CHANNEL_LEFT:	      now[0] = *inptr++;	      break;	    case FRONT_CHANNEL_RIGHT:	      now[1] = *inptr++;	      break;	    case SIDE_CHANNEL_LEFT:	    case SIDE_CHANNEL_RIGHT:	    case BACK_CHANNEL_CENTER:	      inptr++;	      break;	    case BACK_CHANNEL_LEFT:	      now[2] = *inptr++;	      break;	    case BACK_CHANNEL_RIGHT:	      now[3] = *inptr++;	      break;	    case LFE_CHANNEL:	      now[5] = *inptr++;	      break;	    }	  }	  now += 6;	}	aac->m_vft->audio_filled_buffer(aac->m_ifptr);      }    }  } else {    aa_message(LOG_ERR, aaclib, "error return is %d %s", frame_info.error,	       faacDecGetErrorMessage(frame_info.error));#ifdef DEBUG_SYNC    aa_message(LOG_ERR, aaclib, "Audio decode problem - at "LLU,           aac->m_current_time);#endif  }  aac->m_cached_freq_ts = freq_timestamp;  aac->m_cached_ts = aac->m_current_time;  return (bytes_consummed);}static int aac_codec_check (lib_message_func_t message,			    const char *stream_type,			    const char *compressor,			    int type,			    int profile,			    format_list_t *fptr, 			    const uint8_t *userdata,			    uint32_t userdata_size,			    CConfigSet *pConfig){  fmtp_parse_t *fmtp = NULL;  if (compressor != NULL &&       strcasecmp(stream_type, "MP4 FILE") == 0 &&      type != -1) {    if (!(MP4_IS_AAC_AUDIO_TYPE(type))) {      return -1;    }  }  if (strcasecmp(stream_type, STREAM_TYPE_RTP) == 0 &&      fptr != NULL &&       fptr->rtpmap_name != NULL) {    if ((strcasecmp(fptr->rtpmap_name, "mpeg4-generic") != 0) &&        (strcasecmp(fptr->rtpmap_name, "enc-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, false);    //    message(LOG_DEBUG, "aac", "audio type is %d", audio_config.audio_object_type);    if (fmtp != NULL) free_fmtp_parse(fmtp);        if (audio_object_type_is_aac(&audio_config) == 0) {      return -1;    }#if 0    // we're going to go ahead with ERR_AAC for now    if (audio_config.audio_object_type == 17) {      message(LOG_INFO, "aac", "audio type is legal ISMA, but not supported");      return -1;    }#endif    return 3;  }  return -1;}AUDIO_CODEC_WITH_RAW_FILE_PLUGIN("faad2",               aac_codec_create,               aac_do_pause,               aac_decode,               NULL,               aac_close,               aac_codec_check,               aac_file_check,               aac_file_next_frame,               aac_file_used_for_frame,               aac_raw_file_seek_to,               aac_file_eof,               NULL,               0               );/* end file aa.cpp */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -