我是靠谱客的博主 小巧羽毛,最近开发中收集的这篇文章主要介绍ffmpeg decode resample,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

关于FFMPEG API编程。

解码,我们需要先找到解码器,如何找到解码器,根据文件格式找到解码器,然后解码出PCM裸数据,如果想要生成的数据采样率通道和采样大小不一样,就需要再进行重采样。

根据文件格式找到解码器 open_format, new codec_ctx, copy params from input format to codec_ctx, send packet, receivce fram, swr_convert, write packet pcm

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
extern "C"
{
#include <libavutil/frame.h>
#include <libavutil/mem.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswresample/swresample.h>
}
#define AUDIO_INBUF_SIZE 20480
#define AUDIO_REFILL_THRESH 4096
#define MAX_AUDIO_FRAME_SIZE 192000
int main(int argc, char **argv)
{
const char *outfilename, *filename;
int i, ret;
int err_code;
char errors[1024];
int audiostream_index = -1;
AVFormatContext *pFormatCtx = NULL;
const AVCodec *codec;
AVCodecContext *codec_ctx = NULL;
int len;
FILE *f, *outfile;
uint8_t inbuf[AUDIO_INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
AVPacket avpkt;
AVFrame *decoded_frame = NULL;
filename = "Y:\Audio\ttt.mp3";
outfilename = "Y:\Audio\test.pcm";
/* register all the codecs */
av_register_all();
av_init_packet(&avpkt);
/* open input file, and allocate format context */
if ((err_code = avformat_open_input(&pFormatCtx, filename, NULL, NULL)) < 0) {
av_strerror(err_code, errors, 1024);
fprintf(stderr, "Could not open source file %s, %d(%s)n", filename, err_code, errors);
return -1;
}
// Retrieve stream information
if (avformat_find_stream_info(pFormatCtx, NULL)<0)
return -1; // Couldn't find stream information
// Dump information about file onto standard error
av_dump_format(pFormatCtx, 0, filename, 0);
for (i = 0; i<pFormatCtx->nb_streams; i++) {
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
audiostream_index = i;
}
}
/* find the MPEG audio decoder */
//codec = avcodec_find_decoder_by_name("libfdk_aac");
//codec = avcodec_find_decoder(pFormatCtx->streams[audiostream_index]->codec->codec_id/*AV_CODEC_ID_MP2*/);
/*
if (!codec) {
fprintf(stderr, "Codec not foundn");
exit(1);
}
*/
codec_ctx = avcodec_alloc_context3(NULL);
if (!codec_ctx) {
fprintf(stderr, "Could not allocate audio codec contextn");
exit(1);
}
ret = avcodec_parameters_to_context(codec_ctx, pFormatCtx->streams[audiostream_index]->codecpar);
if (ret < 0) {
return -1;
}
codec = avcodec_find_decoder(codec_ctx->codec_id);
if (!codec) {
fprintf(stderr, "Codec not foundn");
exit(1);
}
//Out Audio Param
uint64_t out_channel_layout = AV_CH_LAYOUT_STEREO;
//AAC:1024
MP3:1152
int out_nb_samples = codec_ctx->frame_size;
AVSampleFormat out_sample_fmt = AV_SAMPLE_FMT_S16;
int out_sample_rate = 32000;
int out_channels = av_get_channel_layout_nb_channels(out_channel_layout);
//Out Buffer Size
int out_buffer_size = av_samples_get_buffer_size(NULL,
out_channels,
out_nb_samples,
out_sample_fmt,
1);
uint8_t *out_buffer = (uint8_t *)av_malloc(MAX_AUDIO_FRAME_SIZE * 2);
int64_t in_channel_layout = av_get_default_channel_layout(codec_ctx->channels);
struct SwrContext *audio_convert_ctx;
audio_convert_ctx = swr_alloc();
audio_convert_ctx = swr_alloc_set_opts(audio_convert_ctx,
out_channel_layout,
AV_SAMPLE_FMT_S16,
out_sample_rate,
in_channel_layout,
codec_ctx->sample_fmt,
codec_ctx->sample_rate,
0,
NULL);
swr_init(audio_convert_ctx);
/* open it */
if (avcodec_open2(codec_ctx, codec, NULL) < 0) {
fprintf(stderr, "Could not open codecn");
exit(1);
}
/*
f = fopen(filename, "rb");
if (!f) {
fprintf(stderr, "Could not open %sn", filename);
exit(1);
}
*/
outfile = fopen(outfilename, "wb");
if (!outfile) {
av_free(codec_ctx);
exit(1);
}
/* decode until eof */
/*
avpkt.data = inbuf;
avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f);
*/
while (1) {
int i, ch;
int got_frame = 0;
if (!decoded_frame) {
if (!(decoded_frame = av_frame_alloc())) {
fprintf(stderr, "Could not allocate audio framen");
exit(1);
}
}
if (av_read_frame(pFormatCtx, &avpkt) < 0) {
if (pFormatCtx->pb->error == 0) {
Sleep(100); /* no error; wait for user input */
continue;
}
else {
break;
}
}
if (avpkt.stream_index != audiostream_index){
av_free_packet(&avpkt);
continue;
}
len = avcodec_decode_audio4(codec_ctx, decoded_frame, &got_frame, &avpkt);
if (len < 0) {
av_strerror(len, errors, 1024);
fprintf(stderr, "Error while decoding, err_code:%d, err:%sn", len, errors);
exit(1);
}
if (got_frame) {
/* if a frame has been decoded, output it */
int data_size = av_get_bytes_per_sample(codec_ctx->sample_fmt);
if (data_size < 0) {
/* This should not occur, checking just for paranoia */
fprintf(stderr, "Failed to calculate data sizen");
exit(1);
}
int src_rate = codec_ctx->sample_rate;
int src_nb_samples = codec_ctx->frame_size;
/* compute destination number of samples */
int dst_nb_samples = av_rescale_rnd(swr_get_delay(audio_convert_ctx, src_rate) + src_nb_samples, out_sample_rate, src_rate, AV_ROUND_UP);
int convert_samples = swr_convert(audio_convert_ctx,
&out_buffer,
dst_nb_samples,
(const uint8_t **)decoded_frame->data,
decoded_frame->nb_samples);
int dst_bufsize = av_samples_get_buffer_size(NULL, out_channels, convert_samples, out_sample_fmt, 1);
fwrite(out_buffer, 1, dst_bufsize, outfile);
/*
for (i = 0; i < decoded_frame->nb_samples; i++)
for (ch = 0; ch < codec_ctx->channels; ch++)
fwrite(decoded_frame->data[ch] + data_size*i, 1, data_size, outfile);
*/
}
//avpkt.size -= len;
//avpkt.data += len;
avpkt.dts =
avpkt.pts = AV_NOPTS_VALUE;
//if (avpkt.size < AUDIO_REFILL_THRESH) {
/* Refill the input buffer, to avoid trying to decode
* incomplete frames. Instead of this, one could also use
* a parser, or use a proper container format through
* libavformat. */
/*
memmove(inbuf, avpkt.data, avpkt.size);
avpkt.data = inbuf;
len = fread(avpkt.data + avpkt.size, 1,
AUDIO_INBUF_SIZE - avpkt.size, f);
if (len > 0)
avpkt.size += len;
}
*/
}
fclose(outfile);
//fclose(f);
avcodec_free_context(&codec_ctx);
av_frame_free(&decoded_frame);
return 0;
}

 

最后

以上就是小巧羽毛为你收集整理的ffmpeg decode resample的全部内容,希望文章能够帮你解决ffmpeg decode resample所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(50)

评论列表共有 0 条评论

立即
投稿
返回
顶部