写一个ffmpeg播放MP3的demo
时间: 2023-07-08 08:29:16 浏览: 49
以下是一个使用FFmpeg播放MP3文件的示例代码,使用了libavformat和libavcodec库:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswresample/swresample.h>
#define BUFFER_SIZE 4096
int main(int argc, char *argv[]) {
AVFormatContext *format_ctx = NULL;
AVCodecContext *codec_ctx = NULL;
AVCodecParameters *codec_params = NULL;
AVCodec *codec = NULL;
AVFrame *frame = NULL;
AVPacket *packet = NULL;
SwrContext *swr_ctx = NULL;
uint8_t *buffer = NULL;
int buffer_size = BUFFER_SIZE;
int stream_index = -1;
int ret;
if (argc < 2) {
printf("Usage: %s <input_file>\n", argv[0]);
return 1;
}
av_register_all();
avformat_network_init();
format_ctx = avformat_alloc_context();
if (!format_ctx) {
printf("Error: Could not allocate format context.\n");
return 1;
}
ret = avformat_open_input(&format_ctx, argv[1], NULL, NULL);
if (ret < 0) {
printf("Error: Could not open input file '%s'\n", argv[1]);
return 1;
}
ret = avformat_find_stream_info(format_ctx, NULL);
if (ret < 0) {
printf("Error: Could not find stream information.\n");
return 1;
}
av_dump_format(format_ctx, 0, argv[1], 0);
for (int i = 0; i < format_ctx->nb_streams; i++) {
if (format_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
stream_index = i;
break;
}
}
if (stream_index == -1) {
printf("Error: Could not find audio stream.\n");
return 1;
}
codec_params = format_ctx->streams[stream_index]->codecpar;
codec = avcodec_find_decoder(codec_params->codec_id);
if (!codec) {
printf("Error: Unsupported codec.\n");
return 1;
}
codec_ctx = avcodec_alloc_context3(codec);
if (!codec_ctx) {
printf("Error: Could not allocate codec context.\n");
return 1;
}
ret = avcodec_parameters_to_context(codec_ctx, codec_params);
if (ret < 0) {
printf("Error: Could not copy codec parameters to codec context.\n");
return 1;
}
ret = avcodec_open2(codec_ctx, codec, NULL);
if (ret < 0) {
printf("Error: Could not open codec.\n");
return 1;
}
frame = av_frame_alloc();
packet = av_packet_alloc();
if (!frame || !packet) {
printf("Error: Could not allocate frame and packet.\n");
return 1;
}
swr_ctx = swr_alloc();
if (!swr_ctx) {
printf("Error: Could not allocate resampling context.\n");
return 1;
}
av_opt_set_int(swr_ctx, "in_channel_layout", codec_ctx->channel_layout, 0);
av_opt_set_int(swr_ctx, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0);
av_opt_set_int(swr_ctx, "in_sample_rate", codec_ctx->sample_rate, 0);
av_opt_set_int(swr_ctx, "out_sample_rate", 44100, 0);
av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", codec_ctx->sample_fmt, 0);
av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
ret = swr_init(swr_ctx);
if (ret < 0) {
printf("Error: Could not initialize resampling context.\n");
return 1;
}
buffer = av_malloc(buffer_size);
if (!buffer) {
printf("Error: Could not allocate buffer.\n");
return 1;
}
while (av_read_frame(format_ctx, packet) >= 0) {
if (packet->stream_index == stream_index) {
ret = avcodec_send_packet(codec_ctx, packet);
if (ret < 0) {
printf("Error: Could not send packet to decoder.\n");
break;
}
while (ret >= 0) {
ret = avcodec_receive_frame(codec_ctx, frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
break;
else if (ret < 0) {
printf("Error: Could not receive frame from decoder.\n");
goto end;
}
int data_size = av_samples_get_buffer_size(NULL, codec_ctx->channels,
frame->nb_samples, AV_SAMPLE_FMT_S16, 1);
if (data_size > buffer_size) {
buffer_size = data_size;
buffer = av_realloc(buffer, buffer_size);
}
swr_convert(swr_ctx, &buffer, frame->nb_samples,
(const uint8_t **)frame->data, frame->nb_samples);
fwrite(buffer, 1, data_size, stdout);
}
}
av_packet_unref(packet);
}
end:
avformat_close_input(&format_ctx);
avcodec_free_context(&codec_ctx);
avformat_free_context(format_ctx);
av_frame_free(&frame);
av_packet_free(&packet);
swr_free(&swr_ctx);
av_free(buffer);
return 0;
}
```
这个示例代码会打开指定的MP3文件, 解码音频流, 并输出16-bit PCM音频数据到stdout。您可以将输出重定向到另一个程序或使用管道将其传递给ffplay等播放器进行播放。请注意,您需要在编译时链接FFmpeg库。