#include "stdafx.h"
#include <stdio.h>
#include <iostream>
using namespace std;
extern "C"
{
#include "libavformat/avformat.h"
#include "libavutil/avutil.h"
#include "libavcodec/avcodec.h"
#include "libswresample/swresample.h"
#include "libavutil/frame.h"
#include "libavutil/samplefmt.h"
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"
}
#pragma comment(lib, "avcodec.lib")
#pragma comment(lib, "avdevice.lib")
#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "avutil.lib")
#pragma comment(lib, "swscale.lib")
#pragma comment(lib, "swresample.lib")
uint8_t * out_buf = nullptr;
int AudioResampling(int in_sample_fmt, int in_channels, int in_sample_rate, AVFrame * pAudioDecodeFrame,
int out_sample_fmt, int out_channels, int out_sample_rate )
{
//////////////////////////////////////////////////////////////////////////
SwrContext * swr_ctx = NULL;
int data_size = 0;
int ret = 0;
int64_t src_ch_layout = AV_CH_LAYOUT_STEREO; //初始化这样根据不同文件做调整
int64_t dst_ch_layout = AV_CH_LAYOUT_STEREO; //这里设定ok
int dst_nb_channels = 0;
int dst_linesize = 0;
int src_nb_samples = 0;
int dst_nb_samples = 0;
int max_dst_nb_samples = 0;
uint8_t **dst_data = NULL;
int resampled_data_size = 0;
//重新采样
if (swr_ctx)
{
swr_free(&swr_ctx);
}
swr_ctx = swr_alloc();
if (!swr_ctx)
{
printf("swr_alloc error \n");
return -1;
}
src_ch_layout = AV_CH_LAYOUT_STEREO;
if (out_channels == 1)
{
dst_ch_layout = AV_CH_LAYOUT_MONO;
}
else if (out_channels == 2)
{
dst_ch_layout = AV_CH_LAYOUT_STEREO;
}
else
{
//可扩展
}
if (src_ch_layout <= 0)
{
printf("src_ch_layout error \n");
return -1;
}
src_nb_samples = pAudioDecodeFrame->nb_samples;
if (src_nb_samples <= 0)
{
printf("src_nb_samples error \n");
return -1;
}
swr_ctx = swr_alloc_set_opts(
NULL,
dst_ch_layout,
(AVSampleFormat)out_sample_fmt, //在编码前,我希望的采样格式
out_sample_rate,
src_ch_layout,
(AVSampleFormat)in_sample_fmt, //PCM源文件的采样格式
in_sample_rate,
0, NULL);
swr_init(swr_ctx);
max_dst_nb_samples = dst_nb_samples =
av_rescale_rnd(src_nb_samples, out_sample_rate, in_sample_rate, AV_ROUND_UP);
if (max_dst_nb_samples <= 0)
{
printf("av_rescale_rnd error \n");
return -1;
}
dst_nb_channels = av_get_channel_layout_nb_channels(dst_ch_layout);
ret = av_samples_alloc_array_and_samples(&dst_data, &dst_linesize, dst_nb_channels,
dst_nb_samples, (AVSampleFormat)out_sample_fmt, 0);
if (ret < 0)
{
printf("av_samples_alloc_array_and_samples error \n");
return -1;
}
dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_ctx, in_sample_rate) +
src_nb_samples, out_sample_rate, in_sample_rate, AV_ROUND_UP);
if (dst_nb_samples <= 0)
{
printf("av_rescale_rnd error \n");
return -1;
}
if (dst_nb_samples > max_dst_nb_samples)
{
av_free(dst_data[0]);
ret = av_samples_alloc(dst_data, &dst_linesize, dst_nb_channels,
dst_nb_samples, (AVSampleFormat)out_sample_fmt, 1);
max_dst_nb_samples = dst_nb_samples;
}
data_size = av_samples_get_buffer_size(NULL, in_channels,
pAudioDecodeFrame->nb_samples,
(AVSampleFormat)in_sample_fmt, 1);
if (data_size <= 0)
{
printf("av_samples_get_buffer_size error \n");
return -1;
}
resampled_data_size = data_size;
if (swr_ctx)
{
ret = swr_convert(swr_ctx, dst_data, dst_nb_samples,
(const uint8_t **)pAudioDecodeFrame->data, pAudioDecodeFrame->nb_samples);
if (ret <= 0)
{
printf("swr_convert error \n");
return -1;
}
resampled_data_size = av_samples_get_buffer_size(&dst_linesize, dst_nb_channels,
ret, (AVSampleFormat)out_sample_fmt, 1);
if (resampled_data_size <= 0)
{
printf("av_samples_get_buffer_size error \n");
return -1;
}
}
else
{
printf("swr_ctx null error \n");
return -1;
}
if (!out_buf) {
out_buf = (uint8_t *)av_malloc(resampled_data_size * sizeof(uint8_t));
}
//将值返回去
memcpy(out_buf, dst_data[0], resampled_data_size);
if (dst_data)
{
av_freep(&dst_data[0]);
}
av_freep(&dst_data);
dst_data = NULL;
if (swr_ctx)
{
swr_free(&swr_ctx);
}
return resampled_data_size;
}
int main() {
FILE *fp_in;
FILE *fp_out;
char filename_in[] = "tdjm.pcm";
char filename_out[] = "out.pcm";
AVFrame *pFrame;
fp_in = fopen(filename_in, "rb");
if (!fp_in) {
printf("Could not open %s\n", filename_in);
return -1;
}
fp_out = fopen(filename_out, "wb");
if (!fp_out) {
printf("Could not open %s\n", filename_out);
return -1;
}
pFrame = av_frame_alloc();
pFrame->nb_samples = 1024; //1024
pFrame->format = AV_SAMPLE_FMT_S16;
pFrame->channels = 2;
int size = av_samples_get_buffer_size(NULL, 2, 1024, AV_SAMPLE_FMT_S16, 0);
uint8_t*frame_buf = (uint8_t *)av_malloc(size);
int ret = avcodec_fill_audio_frame(pFrame, 2, AV_SAMPLE_FMT_S16, (const uint8_t*)frame_buf, size, 0);
for (auto i = 0; i < 5000; i++)
{
if (fread(frame_buf, 1, 4096, fp_in) <= 0) {
printf("Failed to read raw data! %d \n", i);
getchar();
return -1;
}
//采样率 44100->8000
//int out_size = AudioResampling(1, 2, 44100, pFrame, 1, 2, 8000);
//采样精度 AV_SAMPLE_FMT_S16->AV_SAMPLE_FMT_FLTP
int out_size = AudioResampling(1, 2, 44100, pFrame, 1, 2, 8000);
fwrite(out_buf, 1, out_size, fp_out);
}
fclose(fp_out);
fclose(fp_in);
av_free(out_buf);
getchar();
return 0;
}
基于ffmpeg重采样、采样精度转换、通道数转换(未测,需要修改部分变量)的例子
猜你喜欢
转载自blog.csdn.net/venice0708/article/details/80797723
今日推荐
周排行