📄 audio_ffmpeg.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. 2004. All Rights Reserved. * * Contributor(s): * Bill May wmay@cisco.com */#include "mp4live.h"#ifdef HAVE_FFMPEG#include "audio_ffmpeg.h"#include <mp4av.h>#ifdef HAVE_AVRATIONAL#define MAY_HAVE_AMR_CODEC 1#else#undef MAY_HAVE_AMR_CODEC#endif// these are for mpeg2static const uint32_t ffmpeg_sample_rates[] = { 44100, 48000, };static const uint32_t ffmpeg_g711_sample_rates[] = { 8000, };static const uint32_t ffmpeg_bit_rates[] = { 112000, 128000, 160000, 192000, 224000, 256000, 320000};GUI_BOOL(gui_mp3use14, CFG_RTP_USE_MP3_PAYLOAD_14, "Transmit MP3 using RFC-2250");DECLARE_TABLE(ffmpeg_gui_options) = { TABLE_GUI(gui_mp3use14),};DECLARE_TABLE_FUNC(ffmpeg_gui_options);static int get_index_for_samplerate (uint32_t sr){ unsigned int ix; for (ix = 0; ix < NUM_ELEMENTS_IN_ARRAY(ffmpeg_sample_rates); ix ++) { if (sr == ffmpeg_sample_rates[ix]) { return ix; } } return -1;}static uint32_t *ffmpeg_bitrate_for_samplerate (uint32_t samplerate, uint8_t chans, uint32_t *ret_size){ int ix = get_index_for_samplerate(samplerate); if (ix < 0) { return NULL; } uint32_t elements = NUM_ELEMENTS_IN_ARRAY(ffmpeg_bit_rates); elements -= ix; uint32_t *ret = (uint32_t *)malloc(elements * sizeof(uint32_t)); *ret_size = elements; memcpy(ret, &ffmpeg_bit_rates[ix], elements * sizeof(uint32_t)); return ret;}static uint32_t *g711_bitrate_for_samplerate (uint32_t samplerate, uint8_t chans, uint32_t *ret_size){ uint32_t *ret = MALLOC_STRUCTURE(uint32_t); *ret = 64000; *ret_size = 1; return ret;}// right now, use ffmpeg for mpeg1, layer 2, so that we'll work// with mpeg2 and quicktimestatic audio_encoder_table_t ffmpeg_audio_encoder_table = { "MPEG Layer 2 - ffmpeg", VIDEO_ENCODER_FFMPEG, AUDIO_ENCODING_MP3, ffmpeg_sample_rates, NUM_ELEMENTS_IN_ARRAY(ffmpeg_sample_rates), ffmpeg_bitrate_for_samplerate, 2, TABLE_FUNC(ffmpeg_gui_options)};static audio_encoder_table_t ffmpeg_alaw_audio_encoder_table = { "G.711 alaw - ffmpeg", VIDEO_ENCODER_FFMPEG, AUDIO_ENCODING_ALAW, ffmpeg_g711_sample_rates, NUM_ELEMENTS_IN_ARRAY(ffmpeg_g711_sample_rates), g711_bitrate_for_samplerate, 1, NULL,};static audio_encoder_table_t ffmpeg_ulaw_audio_encoder_table = { "G.711 ulaw - ffmpeg", VIDEO_ENCODER_FFMPEG, AUDIO_ENCODING_ULAW, ffmpeg_g711_sample_rates, NUM_ELEMENTS_IN_ARRAY(ffmpeg_g711_sample_rates), g711_bitrate_for_samplerate, 1, NULL,};// these are for AMR static const uint32_t ffmpeg_amr_sample_rates[] = { 8000, 16000, }; static uint32_t *ffmpeg_amr_bitrate_for_samplerate (uint32_t samplerate, uint8_t chans, uint32_t *ret_size){ uint32_t *ret = (uint32_t *)malloc(16 * sizeof(uint32_t)); if (samplerate == 8000) { ret[0] = 4750 * chans; ret[1] = 5150 * chans; ret[2] = 5900 * chans; ret[3] = 6700 * chans; ret[4] = 7400 * chans; ret[5] = 7950 * chans; ret[6] = 10200 * chans; ret[7] = 12200 * chans; *ret_size = 8; } else if (samplerate == 16000) { ret[0] = 6600 * chans; ret[1] = 8850 * chans; ret[2] = 12650 * chans; ret[3] = 14250 * chans; ret[4] = 15850 * chans; ret[5] = 18250 * chans; ret[6] = 19850 * chans; ret[7] = 23050 * chans; ret[8] = 23850 * chans; *ret_size = 9; } else { *ret_size = 0; } return ret;} audio_encoder_table_t ffmpeg_amr_audio_encoder_table = { "AMR", VIDEO_ENCODER_FFMPEG, AUDIO_ENCODING_AMR, ffmpeg_amr_sample_rates, NUM_ELEMENTS_IN_ARRAY(ffmpeg_amr_sample_rates), ffmpeg_amr_bitrate_for_samplerate, 1 }; MediaType ffmpeg_mp4_fileinfo (CAudioProfile *pConfig, bool *mpeg4, bool *isma_compliant, uint8_t *audioProfile, uint8_t **audioConfig, uint32_t *audioConfigLen, uint8_t *mp4AudioType){ const char *encodingName = pConfig->GetStringValue(CFG_AUDIO_ENCODING); if (!strcasecmp(encodingName, AUDIO_ENCODING_MP3)) { *mpeg4 = true; // legal in an mp4 - create an iod *isma_compliant = false; *audioProfile = 0xfe; *audioConfig = NULL; *audioConfigLen = 0; if (mp4AudioType != NULL) { *mp4AudioType = MP4_MPEG1_AUDIO_TYPE; } return MP3AUDIOFRAME; } else { *mpeg4 = false; *isma_compliant = false; *audioProfile = 0; *audioConfig = NULL; *audioConfigLen = 0; if (mp4AudioType != NULL) { *mp4AudioType = 0; } if (!strcasecmp(encodingName, AUDIO_ENCODING_AMR)) { if (pConfig->GetIntegerValue(CFG_AUDIO_SAMPLE_RATE) == 8000) { return AMRNBAUDIOFRAME; } return AMRWBAUDIOFRAME; } else if (!strcasecmp(encodingName, AUDIO_ENCODING_ULAW)) { if (mp4AudioType != NULL) { *mp4AudioType = MP4_ULAW_AUDIO_TYPE; } return ULAWAUDIOFRAME; } else if (!strcasecmp(encodingName, AUDIO_ENCODING_ALAW)) { if (mp4AudioType != NULL) { *mp4AudioType = MP4_ALAW_AUDIO_TYPE; } return ALAWAUDIOFRAME; } } return UNDEFINEDFRAME;}media_desc_t *ffmpeg_create_audio_sdp (CAudioProfile *pConfig, bool *mpeg4, bool *isma_compliant, bool *is3gp, uint8_t *audioProfile, uint8_t **audioConfig, uint32_t *audioConfigLen){ media_desc_t *sdpMediaAudio; format_list_t *sdpMediaAudioFormat; rtpmap_desc_t *sdpAudioRtpMap; MediaType type; type = ffmpeg_mp4_fileinfo(pConfig, mpeg4, isma_compliant, audioProfile, audioConfig, audioConfigLen, NULL); sdpMediaAudio = MALLOC_STRUCTURE(media_desc_t); memset(sdpMediaAudio, 0, sizeof(*sdpMediaAudio)); sdpMediaAudioFormat = MALLOC_STRUCTURE(format_list_t); memset(sdpMediaAudioFormat, 0, sizeof(*sdpMediaAudioFormat)); sdpMediaAudio->fmt = sdpMediaAudioFormat; sdpMediaAudioFormat->media = sdpMediaAudio; if (type == ALAWAUDIOFRAME) { sdpMediaAudioFormat->fmt = strdup("8"); } else if (type == ULAWAUDIOFRAME) { sdpMediaAudioFormat->fmt = strdup("0"); } else { sdpAudioRtpMap = MALLOC_STRUCTURE(rtpmap_desc_t); memset(sdpAudioRtpMap, 0, sizeof(*sdpAudioRtpMap)); if (type == MP3AUDIOFRAME) { if (pConfig->GetBoolValue(CFG_RTP_USE_MP3_PAYLOAD_14)) { sdpMediaAudioFormat->fmt = strdup("14"); sdpAudioRtpMap->clock_rate = 90000; } else { sdpAudioRtpMap->clock_rate = pConfig->GetIntegerValue(CFG_AUDIO_SAMPLE_RATE); sdpMediaAudioFormat->fmt = strdup("97"); sdp_add_string_to_list(&sdpMediaAudio->unparsed_a_lines, "a=mpeg4-esid:10"); } sdpAudioRtpMap->encode_name = strdup("MPA"); } else if (type == AMRNBAUDIOFRAME) { *is3gp = true; sdpAudioRtpMap->encode_name = strdup("AMR"); sdpAudioRtpMap->clock_rate = 8000; sdpMediaAudioFormat->fmt = strdup("97"); sdp_add_string_to_list(&sdpMediaAudio->unparsed_a_lines, strdup("a=fmtp:97 octet-align=1")); sdpAudioRtpMap->encode_param = 1; } else if (type == AMRWBAUDIOFRAME) { *is3gp = true; sdpAudioRtpMap->encode_name = strdup("AMR-WB"); sdpAudioRtpMap->clock_rate = 16000; sdpMediaAudioFormat->fmt = strdup("97"); sdp_add_string_to_list(&sdpMediaAudio->unparsed_a_lines, strdup("a=fmtp:97 octet-align=1")); sdpAudioRtpMap->encode_param = 1; } sdpMediaAudioFormat->rtpmap = sdpAudioRtpMap; } return sdpMediaAudio;}static bool ffmpeg_set_rtp_header (struct iovec *iov, int queue_cnt, void *ud, bool *mbit){ *mbit = 1; *(uint32_t *)ud = 0; iov[0].iov_base = ud; iov[0].iov_len = 4; return true;}static bool ffmpeg_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;} // compile RTP payload from a queue of framesstatic int ffmpeg_amr_set_rtp_payload(CMediaFrame** m_audioQueue, int queue_cnt, struct iovec *iov, void *ud, bool *mbit){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -