以下是使用ffmpeg4.1.8版本库实现音频解码为wav格式的代码:
```
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/avutil.h>
#include <libavutil/opt.h>
#include <libswresample/swresample.h>
int main(int argc, char **argv)
{
AVFormatContext *fmt_ctx = NULL;
AVCodecContext *dec_ctx = NULL;
AVCodec *dec = NULL;
AVPacket pkt;
AVFrame *frame = NULL;
int stream_idx = -1;
int ret = 0;
int got_frame = 0;
char *input_file = NULL;
char *output_file = NULL;
FILE *outfile = NULL;
SwrContext *swr_ctx = NULL;
uint8_t **dst_data = NULL;
int dst_linesize;
int dst_nb_samples;
int max_dst_nb_samples;
int dst_bufsize;
int nb_channels;
int dst_nb_channels;
int src_rate, dst_rate;
int src_layout, dst_layout;
int src_nb_samples, dst_nb_samples_per_channel;
int64_t src_ch_layout, dst_ch_layout;
if (argc != 3) {
fprintf(stderr, "Usage: %s <input file> <output file>\n", argv[0]);
exit(1);
}
input_file = argv[1];
output_file = argv[2];
av_register_all();
if ((ret = avformat_open_input(&fmt_ctx, input_file, NULL, NULL)) < 0) {
fprintf(stderr, "Could not open input file '%s': %s\n", input_file, av_err2str(ret));
exit(1);
}
if ((ret = avformat_find_stream_info(fmt_ctx, NULL)) < 0) {
fprintf(stderr, "Could not find stream information: %s\n", av_err2str(ret));
exit(1);
}
av_dump_format(fmt_ctx, 0, input_file, 0);
for (int i = 0; i < fmt_ctx->nb_streams; i++) {
if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
stream_idx = i;
break;
}
}
if (stream_idx == -1) {
fprintf(stderr, "Could not find audio stream in the input file\n");
exit(1);
}
dec = avcodec_find_decoder(fmt_ctx->streams[stream_idx]->codecpar->codec_id);
if (!dec) {
fprintf(stderr, "Failed to find codec\n");
exit(1);
}
dec_ctx = avcodec_alloc_context3(dec);
if (!dec_ctx) {
fprintf(stderr, "Failed to allocate codec context\n");
exit(1);
}
if ((ret = avcodec_parameters_to_context(dec_ctx, fmt_ctx->streams[stream_idx]->codecpar)) < 0) {
fprintf(stderr, "Failed to copy codec parameters to codec context: %s\n", av_err2str(ret));
exit(1);
}
if ((ret = avcodec_open2(dec_ctx, dec, NULL)) < 0) {
fprintf(stderr, "Failed to open codec: %s\n", av_err2str(ret));
exit(1);
}
frame = av_frame_alloc();
if (!frame) {
fprintf(stderr, "Failed to allocate frame\n");
exit(1);
}
av_init_packet(&pkt);
if ((ret = avformat_seek_file(fmt_ctx, -1, INT64_MIN, 0, INT64_MAX, 0)) < 0) {
fprintf(stderr, "Failed to seek to beginning of file: %s\n", av_err2str(ret));
exit(1);
}
if (!(outfile = fopen(output_file, "wb"))) {
fprintf(stderr, "Could not open output file '%s': %s\n", output_file, strerror(errno));
exit(1);
}
nb_channels = av_get_channel_layout_nb_channels(dec_ctx->channel_layout);
src_rate = dec_ctx->sample_rate;
src_layout = dec_ctx->channel_layout;
src_nb_samples = dec_ctx->frame_size;
dst_rate = src_rate;
dst_layout = AV_CH_LAYOUT_STEREO;
dst_nb_channels = av_get_channel_layout_nb_channels(dst_layout);
dst_nb_samples_per_channel = av_rescale_rnd(src_nb_samples, dst_rate, src_rate, AV_ROUND_UP);
max_dst_nb_samples = dst_nb_samples_per_channel;
dst_bufsize = av_samples_get_buffer_size(&dst_linesize, dst_nb_channels, max_dst_nb_samples, AV_SAMPLE_FMT_S16, 1);
dst_data = (uint8_t **)calloc(dst_nb_channels, sizeof(*dst_data));
if (!dst_data) {
fprintf(stderr, "Failed to allocate memory for destination data\n");
exit(1);
}
if ((ret = av_samples_alloc(dst_data, &dst_linesize, dst_nb_channels, max_dst_nb_samples, AV_SAMPLE_FMT_S16, 1)) < 0) {
fprintf(stderr, "Failed to allocate destination samples: %s\n", av_err2str(ret));
exit(1);
}
swr_ctx = swr_alloc_set_opts(NULL, dst_layout, AV_SAMPLE_FMT_S16, dst_rate, src_layout, dec_ctx->sample_fmt, src_rate, 0, NULL);
if (!swr_ctx) {
fprintf(stderr, "Failed to allocate resampler context\n");
exit(1);
}
if ((ret = swr_init(swr_ctx)) < 0) {
fprintf(stderr, "Failed to initialize resampler context: %s\n", av_err2str(ret));
exit(1);
}
while (av_read_frame(fmt_ctx, &pkt) >= 0) {
if (pkt.stream_index == stream_idx) {
ret = avcodec_send_packet(dec_ctx, &pkt);
if (ret < 0) {
fprintf(stderr, "Error sending a packet for decoding: %s\n", av_err2str(ret));
exit(1);
}
while (ret >= 0) {
ret = avcodec_receive_frame(dec_ctx, frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
break;
} else if (ret < 0) {
fprintf(stderr, "Error during decoding: %s\n", av_err2str(ret));
exit(1);
}
if (frame->channels != nb_channels || frame->sample_rate != src_rate || frame->format != dec_ctx->sample_fmt) {
fprintf(stderr, "Error: input audio parameters have changed\n");
exit(1);
}
dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_ctx, src_rate) + frame->nb_samples, dst_rate, src_rate, AV_ROUND_UP);
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, AV_SAMPLE_FMT_S16, 1);
if (ret < 0) {
fprintf(stderr, "Failed to allocate destination samples: %s\n", av_err2str(ret));
exit(1);
}
max_dst_nb_samples = dst_nb_samples;
dst_bufsize = av_samples_get_buffer_size(&dst_linesize, dst_nb_channels, max_dst_nb_samples, AV_SAMPLE_FMT_S16, 1);
}
ret = swr_convert(swr_ctx, dst_data, dst_nb_samples, (const uint8_t **)frame->data, frame->nb_samples);
if (ret < 0) {
fprintf(stderr, "Error while converting\n");
exit(1);
}
fwrite(dst_data[0], 1, dst_bufsize, outfile);
}
}
av_packet_unref(&pkt);
}
fclose(outfile);
avcodec_free_context(&dec_ctx);
avformat_close_input(&fmt_ctx);
av_frame_free(&frame);
swr_free(&swr_ctx);
av_free(dst_data[0]);
free(dst_data);
return 0;
}
```
这段代码可以将音频解码为WAV格式。