📄 audio_lame.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): * Dave Mackie dmackie@cisco.com */#include "mp4live.h"#include "audio_lame.h"#include <mp4av.h>MediaType lame_mp4_fileinfo (CLiveConfig *pConfig, bool *mpeg4, bool *isma_compliant, uint8_t *audioProfile, uint8_t **audioConfig, uint32_t *audioConfigLen, uint8_t *mp4AudioType){ *mpeg4 = true; // legal in an mp4 - create an iod *isma_compliant = false; *audioProfile = 0xfe; *audioConfig = NULL; *audioConfigLen = 0; if (mp4AudioType != NULL) { *mp4AudioType = MP4_MP3_AUDIO_TYPE; } return MP3AUDIOFRAME;}media_desc_t *lame_create_audio_sdp (CLiveConfig *pConfig, bool *mpeg4, bool *isma_compliant, uint8_t *audioProfile, uint8_t **audioConfig, uint32_t *audioConfigLen){ media_desc_t *sdpMediaAudio; format_list_t *sdpMediaAudioFormat; rtpmap_desc_t *sdpAudioRtpMap; lame_mp4_fileinfo(pConfig, mpeg4, isma_compliant, audioProfile, audioConfig, audioConfigLen, NULL); sdpMediaAudio = MALLOC_STRUCTURE(media_desc_t); memset(sdpMediaAudio, 0, sizeof(*sdpMediaAudio)); sdp_add_string_to_list(&sdpMediaAudio->unparsed_a_lines, strdup("a=mpeg4-esid:10")); sdpMediaAudioFormat = MALLOC_STRUCTURE(format_list_t); memset(sdpMediaAudioFormat, 0, sizeof(*sdpMediaAudioFormat)); sdpMediaAudio->fmt = sdpMediaAudioFormat; sdpMediaAudioFormat->media = sdpMediaAudio; sdpAudioRtpMap = MALLOC_STRUCTURE(rtpmap_desc_t); memset(sdpAudioRtpMap, 0, sizeof(*sdpAudioRtpMap)); sdpAudioRtpMap->clock_rate = pConfig->GetIntegerValue(CONFIG_AUDIO_SAMPLE_RATE); if (pConfig->GetBoolValue(CONFIG_RTP_USE_MP3_PAYLOAD_14)) { sdpMediaAudioFormat->fmt = strdup("14"); sdpAudioRtpMap->clock_rate = 90000; } else { sdpMediaAudioFormat->fmt = strdup("97"); } sdpAudioRtpMap->encode_name = strdup("MPA"); sdpMediaAudioFormat->rtpmap = sdpAudioRtpMap; return sdpMediaAudio;}static bool lame_set_rtp_header (struct iovec *iov, int queue_cnt, void *ud){ *(uint32_t *)ud = 0; iov[0].iov_base = ud; iov[0].iov_len = 4; return true;}static bool lame_set_rtp_jumbo (struct iovec *iov, uint32_t dataOffset, uint32_t bufferLen, uint32_t rtpPacketMax, bool &mbit, void *ud){ uint8_t *payloadHeader = (uint8_t *)ud; uint32_t send; payloadHeader[0] = 0; payloadHeader[1] = 0; payloadHeader[2] = (dataOffset >> 8); payloadHeader[3] = (dataOffset & 0xff); send = MIN(bufferLen - dataOffset, rtpPacketMax - 4); iov[0].iov_base = payloadHeader; iov[0].iov_len = 4; iov[1].iov_len = send; mbit = (dataOffset == 0); return true;}bool lame_get_audio_rtp_info (CLiveConfig *pConfig, MediaType *audioFrameType, uint32_t *audioTimeScale, uint8_t *audioPayloadNumber, uint8_t *audioPayloadBytesPerPacket, uint8_t *audioPayloadBytesPerFrame, uint8_t *audioQueueMaxCount, audio_set_rtp_header_f *audio_set_header, audio_set_rtp_jumbo_frame_f *audio_set_jumbo, void **ud){ *audioFrameType = MP3AUDIOFRAME; if (pConfig->GetBoolValue(CONFIG_RTP_USE_MP3_PAYLOAD_14)) { *audioPayloadNumber = 14; *audioTimeScale = 90000; } else { *audioPayloadNumber = 97; *audioTimeScale = pConfig->GetIntegerValue(CONFIG_AUDIO_SAMPLE_RATE); } *audioPayloadBytesPerPacket = 4; *audioPayloadBytesPerFrame = 0; *audioQueueMaxCount = 8; *audio_set_header = lame_set_rtp_header; *audio_set_jumbo = lame_set_rtp_jumbo; *ud = malloc(4); memset(*ud, 0, 4); return true;}CLameAudioEncoder::CLameAudioEncoder(){ m_mp3FrameBuffer = NULL;}bool CLameAudioEncoder::Init(CLiveConfig* pConfig, bool realTime){ m_pConfig = pConfig; if ((m_lameParams = lame_init()) == NULL) { error_message("error: failed to get lame_global_flags"); return false; } lame_set_num_channels(m_lameParams, m_pConfig->GetIntegerValue(CONFIG_AUDIO_CHANNELS)); lame_set_in_samplerate(m_lameParams, m_pConfig->GetIntegerValue(CONFIG_AUDIO_SAMPLE_RATE)); lame_set_brate(m_lameParams, m_pConfig->GetIntegerValue(CONFIG_AUDIO_BIT_RATE) / 1000); lame_set_mode(m_lameParams, (m_pConfig->GetIntegerValue(CONFIG_AUDIO_CHANNELS) == 1 ? MONO : STEREO)); lame_set_quality(m_lameParams,2); // no match for silent flag // no match for gtkflag // THIS IS VERY IMPORTANT. MP4PLAYER DOES NOT SEEM TO LIKE VBR lame_set_bWriteVbrTag(m_lameParams,0); if (lame_init_params(m_lameParams) == -1) { error_message("error: failed init lame params"); return false; } if (lame_get_in_samplerate(m_lameParams) != lame_get_out_samplerate(m_lameParams)) { error_message("warning: lame audio sample rate mismatch - wanted %d got %d", lame_get_in_samplerate(m_lameParams), lame_get_out_samplerate(m_lameParams)); m_pConfig->SetIntegerValue(CONFIG_AUDIO_SAMPLE_RATE, lame_get_out_samplerate(m_lameParams)); } m_samplesPerFrame = MP4AV_Mp3GetSamplingWindow( m_pConfig->GetIntegerValue(CONFIG_AUDIO_SAMPLE_RATE)); m_mp3FrameMaxSize = (u_int)(1.25 * m_samplesPerFrame) + 7200; m_mp3FrameBufferSize = 2 * m_mp3FrameMaxSize; m_mp3FrameBufferLength = 0; m_mp3FrameBuffer = (u_int8_t*)malloc(m_mp3FrameBufferSize); if (!m_mp3FrameBuffer) { return false; } return true;}u_int32_t CLameAudioEncoder::GetSamplesPerFrame(){ return m_samplesPerFrame;}bool CLameAudioEncoder::EncodeSamples( int16_t* pSamples, u_int32_t numSamplesPerChannel, u_int8_t numChannels){ if (numChannels != 1 && numChannels != 2) { return false; // invalid numChannels } u_int32_t mp3DataLength = 0; if (pSamples != NULL) { int16_t* pLeftBuffer = NULL; bool mallocedLeft = false; int16_t* pRightBuffer = NULL; bool mallocedRight = false; if (numChannels == 1) { pLeftBuffer = pSamples; // both right and left need to be the same - can't // pass NULL as pRightBuffer pRightBuffer = pSamples; } else { // numChannels == 2 // let lame handle stereo to mono conversion DeinterleaveStereoSamples( pSamples, numSamplesPerChannel, &pLeftBuffer, &pRightBuffer); mallocedLeft = true; mallocedRight = true; } // call lame encoder mp3DataLength = lame_encode_buffer( m_lameParams, pLeftBuffer, pRightBuffer, m_samplesPerFrame, (unsigned char*)&m_mp3FrameBuffer[m_mp3FrameBufferLength], m_mp3FrameBufferSize - m_mp3FrameBufferLength); if (mallocedLeft) { free(pLeftBuffer); pLeftBuffer = NULL; } if (mallocedRight) { free(pRightBuffer); pRightBuffer = NULL; } } else { // pSamples == NULL // signal to stop encoding mp3DataLength = lame_encode_flush( m_lameParams, (unsigned char*)&m_mp3FrameBuffer[m_mp3FrameBufferLength], m_mp3FrameBufferSize - m_mp3FrameBufferLength); } m_mp3FrameBufferLength += mp3DataLength; //debug_message("audio -return from lame_encode_buffer is %d %d", mp3DataLength, m_mp3FrameBufferLength); return (mp3DataLength >= 0);}bool CLameAudioEncoder::GetEncodedFrame( u_int8_t** ppBuffer, u_int32_t* pBufferLength, u_int32_t* pNumSamplesPerChannel){ const u_int8_t* mp3Frame; u_int32_t mp3FrameLength; if (!MP4AV_Mp3GetNextFrame(m_mp3FrameBuffer, m_mp3FrameBufferLength, &mp3Frame, &mp3FrameLength)) { //debug_message("Can't find frame header - len %d", m_mp3FrameBufferLength); return false; } // check if we have all the bytes for the MP3 frame if (mp3FrameLength > m_mp3FrameBufferLength) { //debug_message("Not enough in buffer - %d %d", m_mp3FrameBufferLength, mp3FrameLength); return false; } // need a buffer for this MP3 frame *ppBuffer = (u_int8_t*)malloc(mp3FrameLength); if (*ppBuffer == NULL) { error_message("Cannot alloc memory"); return false; } // copy the MP3 frame memcpy(*ppBuffer, mp3Frame, mp3FrameLength); *pBufferLength = mp3FrameLength; // shift what remains in the buffer down memcpy(m_mp3FrameBuffer, mp3Frame + mp3FrameLength, m_mp3FrameBufferLength - mp3FrameLength); m_mp3FrameBufferLength -= mp3FrameLength; *pNumSamplesPerChannel = m_samplesPerFrame; return true;}void CLameAudioEncoder::Stop(){ free(m_mp3FrameBuffer); m_mp3FrameBuffer = NULL; lame_close(m_lameParams); m_lameParams = NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -