Introduction
I have previously worked on a simple audio player: FFMPEG + SDL-based audio player, sdl1.2. Just two days ago, I updated the original "the simplest Video Player Based on FFMPEG + SDL" with sdl2.0, so I also updated the audio player to sdl2.0.
SourceForge project home: https://sourceforge.net/projects/simplestffmpegaudioplayer/
Complete: http://download.csdn.net/detail/leixiaohua1020/7850021
It should be noted that, unlike playing a video, the function of playing audio in sdl2.0 is slightly different from sdl1.2. Basically, it remains unchanged.
In addition to sdl2.0, the following changes are made:
* The project is rebuilt, unnecessary code is deleted, and the code is modified to be more standardized and easy to understand.
* You can use macros to control whether to Use SDL and whether to output PCM.
* Supports multiple formats, such as MP3 and AAC.
Source code
/*** The simplest FFMPEG-Based Audio Player 2 (SDL 2.0) * simplest FFMPEG Audio Player 2 (SDL 2.0) ** this version replaces SDL 2.0 in the first version with SDL 1.0. * Note: The audio decoding API in SDL 2.0 does not change. The only difference is that * the audio buffer in the callback function is not fully initialized and needs to be manually initialized. * In this example, sdl_memset (stream, 0, Len); ** this version Use SDL 2.0 instead of SDL 1.2 in version 1 * Note: The good news for audio is that, with one exception, * it's entirely backwards compatible with 1.2. * That one really important exception: the audio callback * does not start with a fully initialized buffer anymore. * You must fully write to the buffer in all cases. in this * example it is sdl_me Mset (stream, 0, Len ); ** leixiao Lei Xiaohua * [email protected] * China Media University/Digital TV technology * Communication University of China/Digital TV technology * http://blog.csdn.net/leixiaohua1020 ** this program implements audio decoding and play. ** This Software Decode and play audio streams. ** version 2.0 */# include "stdafx. H "# include <stdio. h> # include <stdlib. h> # include <string. h> extern "C" {# include "libavcodec/avcodec. H "# include" libavformat/avformat. H "# include" libswresample/swresample. H "// SDL # include" SDL/SDL. H "# include" SDL/sdl_thread.h "}; # define max_audio_frame_size 192000 // 1 second of 48 khz 32bit audio // output PCM # define outp Ut_pcm 0 // Use SDL # define use_sdl 1 // Buffer: // | ----------- | ------------- | // chunk ------- POS --- Len ----- | static uint8 * audio_chunk; static uint32 audio_len; static uint8 * audio_pos;/* the audio function callback takes the following parameters: * stream: a pointer to the audio buffer to be filled * Len: the length (in bytes) of the audio buffer * callback function */void fill_audio (void * udata, uint8 * stream, int le N) {// SDL 2.0sdl _ memset (stream, 0, Len); If (audio_len = 0)/* only play if we have data left */return; len = (LEN> audio_len? Audio_len: Len);/* mix as much data as possible */sdl_mixaudio (stream, audio_pos, Len, sdl_mix_maxvolume); audio_pos + = Len; audio_len-= Len ;} // ----------------- int _ tmain (INT argc, _ tchar * argv []) {avformatcontext * pformatctx; Inti, audiostream; avcodeccontext * pcodecctx; avcodec * pcodec; char URL [] = "wavinflag. AAC "; av_register_all (); // supports Network Stream Input avformat_network_init (); // initializes pformatctx = avformat_alloc_context (); // Open if (avformat_open_input (& pformatctx, URL, null, null )! = 0) {printf ("couldn't open input stream. \ n "); Return-1;} // retrieve stream informationif (av_find_stream_info (pformatctx) <0) {printf (" couldn't find stream information. \ n "); Return-1;} // dump valid information onto standard errorav_dump_format (pformatctx, 0, URL, false); // find the first audio streamaudiostream =-1; for (I = 0; I <pformatctx-> nb_streams; I ++) if (pformatctx-> streams [I]-> codec-> codec_type = Av Media_type_audio) {audiostream = I; break;} If (audiostream =-1) {printf ("didn't find a audio stream. \ n "); Return-1;} // get a pointer to the codec context for the audio streampcodecctx = pformatctx-> streams [audiostream]-> codec; // find the decoder for the audio streampcodec = avcodec_find_decoder (pcodecctx-> codec_id); If (pcodec = NULL) {printf ("codec not found. \ n "); Return-1;} // open codecif (avcodec_open2 (pcodec CTX, pcodec, null) <0) {printf ("cocould not open codec. \ n "); Return-1;} file * pfile = NULL; # If output_pcmpfile = fopen (" output. PCM "," WB "); # endifavpacket * packet = (avpacket *) malloc (sizeof (avpacket); bytes (packet); // out audio paramuint64_t out_channel_layout = bytes; int out_nb_samples = 1024; avsampleformat out_sample_fmt = av_sample_fmt_s16; int out_sample_rate = 44100; int out_channels = av_get_c Outputs (out_channel_layout); // output memory size int out_buffer_size = bytes (null, out_channels, channels, out_sample_fmt, 1); uint8_t * out_buffer = (uint8_t *) av_malloc (Bytes * 2); avframe * pframe; pframe = avcodec_alloc_frame (); // SDL ---------------- # If use_sdl // initif (sdl_init (sdl_init_video | sdl_init_audio | audio )) {printf ("cocould not initialize SD L-% s \ n ", sdl_geterror (); Return-1;} // define wanted_spec; bandwidth = out_sample_rate; wanted_spec.format = audio_s16sys; bandwidth = out_channels; bandwidth = 0; outputs = 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 ;}# endifprintf ("bitrate: \ t % 3d \ n", pformatctx-> bit_rate); printf ("decoder name: \ t % s \ n ", pcodecctx-> codec-> long_name); printf ("channels: \ t % d \ n", pcodecctx-> channels ); printf ("sample per second \ t % d \ n", pcodecctx-> sample_rate); uint32_t ret, Len = 0; int got_picture; int Index = 0; struct swrcontext * au_convert_ctx; au_convert_ctx = swr_alloc (); au_convert_ctx = swr_alloc_set_opts (au_convert_ctx, out_chan Nel_layout, metrics, metrics, pcodecctx-> channel_layout, pcodecctx-> metrics, pcodecctx-> sample_rate, 0, null); swr_init (au_convert_ctx); While (convert (pformatctx, packet)> = 0) {If (packet-> stream_index = audiostream) {ret = avcodec_decode_audio4 (pcodecctx, pframe, & got_picture, packet); If (Ret <0) {printf ("error in decoding audio frame. \ n "); Return-1;} If (got_picture> 0) {SW R_convert (au_convert_ctx, & out_buffer, max_audio_frame_size, (const uint8_t **) pframe-> data, pframe-> nb_samples); # If 1 printf ("index: % 5d \ t PTS: % 10d \ t packet size: % d \ n ", index, packet-> pts, packet-> size); # endif # If output_pcm // write pcmfwrite (out_buffer, 1, out_linesize, pfile); # endif // fix: FLAC, MP3, AAC different number of samplesif (wanted_spec.samples! = Pframe-> nb_samples) {sdl_closeaudio (); out_nb_samples = pframe-> nb_samples; out_buffer_size = bytes (null, out_channels, channels, buffers, 1); bytes = bytes; sdl_openaudio (& wanted_spec, null);} index ++;} // SDL ---------------- # If use_sdl // set audio data buffer, PCM Data audio_chunk = (uint8 *) out_buffer; // set the Audio Data Length audio_len = out_buffer_size; audio_pos = audio_chunk; // The number of audio records to be played back. Sdl_pauseaudio (0); While (audio_len> 0) // wait until the audio data is played! Sdl_delay (1); # endif} av_free_packet (packet);} swr_free (& au_convert_ctx); # If use_sdlsdl_closeaudio (); // disable the audio device sdl_quit (); # endif // close filefclose (pfile); av_free (out_buffer); // close the codecavcodec_close (pcodecctx); // close the video fileav_close_input_file (pformatctx); Return 0 ;}
The simplest FFMPEG + SDL-based audio player ver2 (using sdl2.0)