写一个ffmpeg播放MP3的demo
时间: 2023-07-08 22:29:22 浏览: 110
这里提供一个简单的FFmpeg播放MP3的demo代码,你可以参考一下:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <libavutil/frame.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswresample/swresample.h>
#define AUDIO_BUF_SIZE (192000)
AVFormatContext *pFormatCtx = NULL;
AVCodecContext *pCodecCtx = NULL;
AVCodec *pCodec = NULL;
AVPacket *packet = NULL;
AVFrame *frame = NULL;
SwrContext *swrCtx = NULL;
uint8_t *outBuffer = NULL;
int audioIndex = -1;
int ret = 0;
pthread_t decodeThread;
int quitFlag = 0;
void *decode(void *arg) {
while (!quitFlag) {
if ((ret = av_read_frame(pFormatCtx, packet)) < 0) {
break;
}
if (packet->stream_index == audioIndex) {
if ((ret = avcodec_send_packet(pCodecCtx, packet)) < 0) {
break;
}
while (ret >= 0) {
ret = avcodec_receive_frame(pCodecCtx, frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
break;
} else if (ret < 0) {
break;
}
if (frame->channels > 0 && frame->channel_layout == 0) {
frame->channel_layout = av_get_default_channel_layout(frame->channels);
} else if (frame->channels == 0 && frame->channel_layout > 0) {
frame->channels = av_get_channel_layout_nb_channels(frame->channel_layout);
}
int nbSamples = frame->nb_samples;
int dataSize = av_samples_get_buffer_size(NULL, frame->channels, nbSamples, pCodecCtx->sample_fmt, 1);
if (swrCtx) {
swr_convert(swrCtx, &outBuffer, AUDIO_BUF_SIZE, (const uint8_t **)frame->data, nbSamples);
dataSize = av_samples_get_buffer_size(NULL, pCodecCtx->channels, nbSamples, pCodecCtx->sample_fmt, 1);
} else {
outBuffer = frame->data[0];
}
fwrite(outBuffer, 1, dataSize, stdout);
}
}
av_packet_unref(packet);
}
return NULL;
}
int main(int argc, char **argv) {
if (argc < 2) {
printf("Usage: %s input.mp3\n", argv[0]);
return -1;
}
av_register_all();
avformat_network_init();
if ((ret = avformat_open_input(&pFormatCtx, argv[1], NULL, NULL)) < 0) {
printf("Failed to open input file: %s\n", argv[1]);
return -1;
}
if ((ret = avformat_find_stream_info(pFormatCtx, NULL)) < 0) {
printf("Failed to find stream info\n");
return -1;
}
for (int i = 0; i < pFormatCtx->nb_streams; i++) {
if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
audioIndex = i;
break;
}
}
if (audioIndex == -1) {
printf("Failed to find audio stream\n");
return -1;
}
pCodec = avcodec_find_decoder(pFormatCtx->streams[audioIndex]->codecpar->codec_id);
if (!pCodec) {
printf("Failed to find decoder for codec\n");
return -1;
}
pCodecCtx = avcodec_alloc_context3(pCodec);
if (!pCodecCtx) {
printf("Failed to allocate codec context\n");
return -1;
}
if ((ret = avcodec_parameters_to_context(pCodecCtx, pFormatCtx->streams[audioIndex]->codecpar)) < 0) {
printf("Failed to copy codec parameters to codec context\n");
return -1;
}
if ((ret = avcodec_open2(pCodecCtx, pCodec, NULL)) < 0) {
printf("Failed to open codec\n");
return -1;
}
packet = av_packet_alloc();
frame = av_frame_alloc();
if (!packet || !frame) {
printf("Failed to allocate packet/frame\n");
return -1;
}
if (pCodecCtx->sample_fmt != AV_SAMPLE_FMT_S16) {
swrCtx = swr_alloc_set_opts(NULL, av_get_default_channel_layout(pCodecCtx->channels), AV_SAMPLE_FMT_S16, pCodecCtx->sample_rate,
av_get_default_channel_layout(pCodecCtx->channels), pCodecCtx->sample_fmt, pCodecCtx->sample_rate, 0, NULL);
if (!swrCtx || swr_init(swrCtx) < 0) {
printf("Failed to initialize resampling context\n");
return -1;
}
}
outBuffer = (uint8_t *)av_malloc(AUDIO_BUF_SIZE);
if (!outBuffer) {
printf("Failed to allocate output buffer\n");
return -1;
}
pthread_create(&decodeThread, NULL, decode, NULL);
pthread_detach(decodeThread);
while (1) {
usleep(1000);
}
quitFlag = 1;
pthread_join(decodeThread, NULL);
if (swrCtx) {
swr_free(&swrCtx);
}
avcodec_close(pCodecCtx);
avformat_close_input(&pFormatCtx);
av_packet_free(&packet);
av_frame_free(&frame);
if (outBuffer) {
av_free(outBuffer);
}
return 0;
}
```
这个demo使用了FFmpeg来解码MP3音频文件,并将解码后的音频数据输出到标准输出。你可以通过将标准输出重定向到文件或者管道来实现保存或者传输音频数据。注意:这个demo并没有进行错误处理和异常退出处理,实际使用中需要根据需要进行修改。
阅读全文