基於ffmpeg重取樣、取樣精度轉換、通道數轉換(未測,需要修改部分變數)的例子
阿新 • • 發佈:2018-12-22
#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; }