本文共 4454 字,大约阅读时间需要 14 分钟。
ffmpeg版本:ffmpeg-20160413-git-0efafc5
#include#include #include extern "C"{#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"#include "libswresample/swresample.h"#include "SDL.h"};#define MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audioUint32 audio_len;//音频数据大小Uint8 *audio_pos;//指向音频数据的指针//回调函数void fill_audio(void *userdata, Uint8 *stream, int len){ //SDL 2.0 SDL_memset(stream, 0, len); if (audio_len == 0) { return; } len = (len > audio_len ? audio_len : len); SDL_MixAudio(stream, audio_pos, len, SDL_MIX_MAXVOLUME); audio_pos += len; audio_len -= len;}int main(int argc, char* argv[]){ //FFmpeg AVFormatContext *pFormatCtx; AVCodecContext *pCodecCtx; AVCodec *pCodec; AVPacket packet; AVFrame *pFrame; struct SwrContext *au_convert_ctx; int got_picture; int audioIndex; //SDL uint8_t *out_buffer; SDL_AudioSpec wanted_spec; int index = 0; char filepath[1024] = ""; printf("Usage: player.exe *.mp3\n"); if (argc == 2) { strcpy(filepath, argv[1]); } else { printf("Could not find a audio file\n"); return -1; } av_register_all(); pFormatCtx = avformat_alloc_context(); if (avformat_open_input(&pFormatCtx, filepath, NULL, NULL) != 0) { printf("Couldn't open input stream.\n"); return -1; } if (avformat_find_stream_info(pFormatCtx, NULL) < 0) { printf("Couldn't find stream information.\n"); return -1; } av_dump_format(pFormatCtx, -1, filepath, 0); audioIndex = -1; for (unsigned int i = 0; i < pFormatCtx->nb_streams; i++) { //AVStream->codec不推荐使用 if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { audioIndex = i; break; } } if (audioIndex == -1) { printf("Didn't find a audio stream.\n"); return -1; } //------------------------------------------------ //新版本:分配、填充AVCodecContext pCodecCtx = avcodec_alloc_context3(NULL); if (pCodecCtx == NULL) { printf("Could not allocate AVCodecContext\n"); return -1; } if (avcodec_parameters_to_context(pCodecCtx, pFormatCtx->streams[audioIndex]->codecpar) < 0) { printf("Could not initialize AVCodecContext\n"); return -1; } //------------------------------------------------ pCodec = avcodec_find_decoder(pCodecCtx->codec_id); if (pCodec == NULL) { printf("Codec not found.\n"); return -1; } if (avcodec_open2(pCodecCtx, pCodec, NULL)<0) { printf("Could not open codec.\n"); return -1; } //Out Audio Param uint64_t out_channel_layout = AV_CH_LAYOUT_STEREO; //nb_samples: AAC-1024 MP3-1152 int out_nb_samples = pCodecCtx->frame_size; AVSampleFormat out_sample_fmt = AV_SAMPLE_FMT_S16; int out_sample_rate = 44100; 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); out_buffer = (uint8_t *)av_malloc(MAX_AUDIO_FRAME_SIZE * 2); pFrame = av_frame_alloc(); //Init if (SDL_Init(SDL_INIT_AUDIO)) { printf("Could not initialize SDL - %s\n", SDL_GetError()); return -1; } //SDL_AudioSpec wanted_spec.freq = out_sample_rate; wanted_spec.format = AUDIO_S16SYS; wanted_spec.channels = out_channels; wanted_spec.silence = 0; wanted_spec.samples = out_nb_samples; wanted_spec.callback = fill_audio; wanted_spec.userdata = pCodecCtx; if (SDL_OpenAudio(&wanted_spec, NULL) < 0) { printf("can't open audio.\n"); return -1; } au_convert_ctx = swr_alloc(); au_convert_ctx = swr_alloc_set_opts(au_convert_ctx, out_channel_layout, out_sample_fmt, out_sample_rate, pCodecCtx->channel_layout, pCodecCtx->sample_fmt, pCodecCtx->sample_rate, 0, NULL); swr_init(au_convert_ctx); //Play SDL_PauseAudio(0); while (av_read_frame(pFormatCtx, &packet) >= 0) { if (packet.stream_index == audioIndex) { if (avcodec_decode_audio4(pCodecCtx, pFrame, &got_picture, &packet) < 0) { printf("Error in decoding audio frame.\n"); return -1; } if (got_picture) { swr_convert(au_convert_ctx, &out_buffer, MAX_AUDIO_FRAME_SIZE, (const uint8_t **)pFrame->data, pFrame->nb_samples); printf("index:%5d\t pts:%lld\t packet size:%d\n", index, packet.pts, packet.size); index++; } while (audio_len > 0)//Wait until finish { SDL_Delay(1); } //Audio buffer length audio_len = out_buffer_size; audio_pos = (Uint8 *)out_buffer; } av_packet_unref(&packet); } swr_free(&au_convert_ctx); SDL_CloseAudio();//Close SDL SDL_Quit(); av_free(out_buffer); avcodec_free_context(&pCodecCtx); avformat_close_input(&pFormatCtx); return 0;}