使用FFmpeg将S16格式音频数据重采样为FLTP格式

代码对一些数据没做判断,仅仅是做个备忘!请谨慎参考!

#include <libavutil/opt.h>
#include <libavutil/samplefmt.h>
#include <libswresample/swresample.h>
#include <stdio.h>

#include "libavcodec/avcodec.h"
#include "libavutil/imgutils.h"
#include "libswresample/swresample.h"

/**
 * @brief 音频重采样 AV_SAMPLE_FMT_S16-->AV_SAMPLE_FMT_FLTP
 * @param argc
 * @param argv
 * @return
 */
int main(int argc, char **argv) {
  SwrContext *swr_context = NULL;
  uint8_t *in_buf = NULL;
  uint8_t **in_data = NULL;
  int in_size = 0;
  uint8_t **out_data = NULL;
  int out_size = 0;
  int line_size = 0;
  int in_nb_samples = 1024;
  int in_channel_count = 2;
  int out_channel_count = 2;
  int64_t in_ch_layout = AV_CH_LAYOUT_STEREO;
  int64_t out_ch_layout = AV_CH_LAYOUT_STEREO;
  int in_sample_rate = 44100, out_sample_rate = 44100;
  int out_nb_samples = 0, max_out_nb_samples = 0;
  enum AVSampleFormat in_sample_fmt = AV_SAMPLE_FMT_S16;
  enum AVSampleFormat out_sample_fmt = AV_SAMPLE_FMT_FLTP;
  FILE *in_file;
  FILE *out_file;
  int read_size;
  int ret;

  in_file = fopen(argv[1], "rb");
  out_file = fopen(argv[2], "wb");
  swr_context = swr_alloc();
  if (!swr_context) {
    printf("error 1\n");
    exit(1);
  }
  av_opt_set_int(swr_context, "in_sample_rate", in_sample_rate, 0);
  av_opt_set_int(swr_context, "in_channel_layout", in_ch_layout, 0);
  av_opt_set_sample_fmt(swr_context, "in_sample_fmt", in_sample_fmt, 0);
  av_opt_set_int(swr_context, "out_sample_rate", out_sample_rate, 0);
  av_opt_set_int(swr_context, "out_channel_layout", out_ch_layout, 0);
  av_opt_set_sample_fmt(swr_context, "out_sample_fmt", out_sample_fmt, 0);
  ret = swr_init(swr_context);
  if (ret < 0) {
    printf("error 2\n");
    exit(1);
  }
  ret = av_samples_alloc_array_and_samples(&in_data, &in_size, in_channel_count,
                                           in_nb_samples, in_sample_fmt, 0);
  if (ret < 0) {
    printf("error 6\n");
    exit(1);
  }

  out_nb_samples = max_out_nb_samples = av_rescale_rnd(
      in_nb_samples, out_sample_rate, in_sample_rate, AV_ROUND_UP);

  ret = av_samples_alloc_array_and_samples(&out_data, &out_size,
                                           out_channel_count, out_nb_samples,
                                           out_sample_fmt, 0);
  if (ret < 0) {
    printf("error 7\n");
    exit(1);
  }
  //一次重采样多少数据
  int bytes_per_frame = av_samples_get_buffer_size(
      &line_size, in_channel_count, in_nb_samples, in_sample_fmt, 0);
  in_buf = av_malloc(bytes_per_frame);
  while ((read_size = fread(in_buf, 1, bytes_per_frame, in_file)) ==
         bytes_per_frame) {
    ret = av_samples_fill_arrays(in_data, &in_size, in_buf, in_channel_count,
                                 in_nb_samples, in_sample_fmt, 0);
    if (ret < 0) {
      printf("error 3\n");
      exit(1);
    }

    int64_t delay = swr_get_delay(swr_context, in_sample_rate);
    out_nb_samples = av_rescale_rnd(in_nb_samples + delay, out_sample_rate,
                                    in_sample_rate, AV_ROUND_UP);
    if (out_nb_samples > max_out_nb_samples) {
      av_freep(&out_data[0]);
      av_freep(&out_data[1]);
      ret = av_samples_alloc(out_data, out_size, out_channel_count,
                             out_nb_samples, out_sample_fmt, 0);
      if (ret < 0) break;
      max_out_nb_samples = out_nb_samples;
    }
    printf("out_nb_samples:%i\n", out_nb_samples);

    ret = swr_convert(swr_context, out_data, out_nb_samples,
                      (const uint8_t **)in_data, in_nb_samples);
    int bytes_per_sample = av_get_bytes_per_sample(AV_SAMPLE_FMT_FLTP);
    // FLTP写成packeted样式
    //    for (int i = 0; i < ret; i++) {
    //      for (int j = 0; j < out_channel_count; j++) {
    //        fwrite(out_data[j] + i * bytes_per_sample, 1, bytes_per_sample,
    //               out_file);
    //      }
    //    }
    // FLTP写成planar样式
    int each_planr_size =
        bytes_per_sample * ret;
    for (int j = 0; j < out_channel_count; j++) {
      fwrite(out_data[j], 1, each_planr_size, out_file);
    }
  }
end:
  fclose(in_file);
  fclose(out_file);
  av_freep(&in_buf);
  av_freep(&in_data[0]);
  av_freep(&in_data);
  av_freep(&out_data[0]);
  av_freep(&out_data[1]);
  av_freep(&out_data);
  swr_free(&swr_context);
  printf("Hello World!\n");
  return 0;
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值