音频编码器为packed(非planar)格式时的说明

本人之前写过一些用ffmpeg录制系统声音,麦克风声音的博客;比如ffmpeg录制系统声音
,由于采取的是ffmpeg自带的aac音频编码器,故最终的音频编码的格式一直是AV_SAMPLE_FMT_FLTP,即float平面模式,故在编码时,经常需要声音样例从packed模式转化为planar模式,故本人写过不少这样的代码:

uint8_t *audio_buf[2] = {
   
    0 };
audio_buf[0] = (uint8_t *)frame_mic_encode->data[0];
audio_buf[1] = (uint8_t *)frame_mic_encode->data[1];

int nb = swr_convert(m_pAudioConvertCtx, audio_buf, dst_nb_samples, (const uint8_t**)frame_mix->data, frame_mix->nb_samples);

现如今,janus里面的音频采取OPUS编码,采样位数为16,本人欲用ffmpeg将音频录制下来,若依然用AV_SAMPLE_FMT_FLTP,则由于此种格式采样位数为32,无疑增加了文件大小。故本人决定采取AV_SAMPLE_FMT_S16P格式,但是ffmpeg自带的aac音频编码器不支持这种格式,报下列错误:

aac @ 0x7fffb8072b30] [0m[1;31mSpecified sample format s16p is invalid or not supported

显然编码器不支持此种采样格式,编码器支持的采样格式可以通过下列代码进行枚举

int i = 0;
enum AVSampleFormat sampleFmt;
sampleFmt = m_pCodecEncode_Audio->sample_fmts[i];
while (sampleFmt != AV_SAMPLE_FMT_NONE)
{
   
   
	i++;
	sampleFmt = m_pCodecEncode_Audio->sample_fmts[i];
}

后面本人采取fdk_aac作为音频编码格式,发现其不支持AV_SAMPLE_FMT_S16P,而是支持AV_SAMPLE_FMT_S16,这个可以通过如下代码验证:

m_pCodecEncode_Audio = (AVCodec *)avcodec_find_encoder_by_name("libfdk_aac");

m_pCodecEncodeCtx_Audio = avcodec_alloc_context3(m_pCodecEncode_Audio);
if (!m_pCodecEncodeCtx_Audio)
{
   
   
	break;
}

int i = 0;
enum AVSampleFormat sampleFmt;
sampleFmt = m_pCodecEncode_Audio->sample_fmts[i];
while (sampleFmt != AV_SAMPLE_FMT_NONE)
{
   
   
	i++;
	sampleFmt = m_pCodecEncode_Audio->sample_fmts[i];
}

fdk_aac仅支持AV_SAMPLE_FMT_S16这一种样例格式。
很明显这是非平面模式,故对应的转换代码如下:

uint8_t *audio_buf[1] = {
   
    0 };
audio_buf[0] = (uint8_t *)frame_mic_encode->data[0];

int nb = swr_convert(m_pAudioConvertCtx, audio_buf, num_frames_to_read, (const uint8_t**)&p_audio_data, num_frames_to_read);

可以看到这里面的audio_buf的数组长度为1.

下面本人将重写系统音频的录制,将最终的编码格式由AV_SAMPLE_FMT_FLTP转换成AV_SAMPLE_FMT_S16,注意用windows api采取系统声音时,声音格式是AV_SAMPLE_FMT_S32,如果系统声音是AV_SAMPLE_FMT_S16,则无需进行重采样。

代码如下:
main函数所在文件FfmpegGetSystemAudio.cpp

#include <iostream>
#include "GetSystemAudio.h"

int main()
{
   
   
	CGetSystemAudio cCGetSystemAudio;
	cCGetSystemAudio.SetSavePath("E:\\learn\\ffmpeg\\FfmpegTest\\x64\\Release");
	cCGetSystemAudio.StartCapture();
	Sleep(30000);
	cCGetSystemAudio.StopCapture();
	return 0;
}

GetSystemAudio.h文件内容如下:

#pragma once
#include <string>
#include <combaseapi.h>
#include <mmdeviceapi.h>
#include <audioclient.h>


#ifdef	__cplusplus
extern "C"
{
   
   
#endif
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libswresample/swresample.h"
#include "libavdevice/avdevice.h"
#include "libavutil/audio_fifo.h"
#include "libavutil/avutil.h"
#include "libavutil/fifo.h"
#include "libavutil/frame.h"
#include "libavutil/imgutils.h"

#include "libavfilter/avfilter.h"
#include "libavfilter/buffersink.h"
#include "libavfilter/buffersrc.h"


#pragma comment(lib, "avcodec.lib")
#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "avutil.lib")
#pragma comment(lib, "avdevice.lib")
#pragma comment(lib, "avfilter.lib")
#pragma comment(lib, "postproc.lib")
#pragma comment(lib, "swresample.lib")
#pragma comment(lib, "swscale.lib")


#ifdef __cplusplus
};
#endif

class CGetSystemAudio
{
   
   
public:
	CGetSystemAudio();
	~CGetSystemAudio();
public:
	void SetSavePath(std::string st
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值