FFmpeg decodes the data into PCM. SDL outputs the PCM data.
Initialize to find the appropriate decoder, open the decoder to open the audio device (available sdl_openaudiodriver () instead), here will be the thread run callback function. Sets the relevant parameters. The 2,3,4 parameter is output and 5,6,7 is the input parameter. Read a avpacket. Decoding. Make transformations such as some format. Output.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define __STDC_CONSTANT_MACROS // ffmpeg required
#ifdef __cplusplus
extern "C"
{
#endif
#include <libavcodec / avcodec.h>
#include <libavformat / avformat.h>
#include <libswresample / swresample.h>
#include <SDL2 / SDL.h>
#ifdef __cplusplus
}
#endif
#define MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audio
#define FILE_NAME "/home/isshe/Music/WavinFlag.aac"
#define ERR_STREAM stderr
#define OUT_SAMPLE_RATE 44100
static uint8_t * audio_buf;
static int audio_len;
static long long audio_buf_index;
void get_file_name (char * filename, int argc, char * argv []);
void open_and_find_inputfile_info (AVFormatContext ** pformat_ctx, char * filename);
int get_audio_stream_index (AVFormatContext * pformat_ctx);
void fill_audio (void * udata, Uint8 * stream, int len);
int main (int argc, char * argv [])
{
AVFrame out_frame;
AVFormatContext * pformat_ctx = NULL;
int audio_stream = 0;
AVCodecContext * pcodec_ctx = NULL;
AVCodec * pcodec = NULL;
AVPacket * ppacket = NULL; //!
AVFrame * pframe = NULL;
uint8_t * out_buffer = NULL; //
int decode_len = 0;
uint32_t len = 0;
int got_picture = 0;
int index = 0;
int64_t in_channel_layout = 0;
struct SwrContext * swr_ctx = NULL;
char filename [256] = FILE_NAME;
FILE * output_fp = NULL;
int convert_len = 0;
int data_size = 0;
// SDL
SDL_AudioSpec wanted_spec;
get_file_name (filename, argc, argv);
fprintf (ERR_STREAM, "file name:% s \ n", filename);
// about ffmpeg
// init
av_register_all ();
// SDL
if (SDL_Init (SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER))
{
fprintf (ERR_STREAM, "Couldn't init SDL:% s \ n", SDL_GetError ());
exit (-1);
}
// open input file
// pformat_ctx = avformat_alloc_context ();
open_and_find_inputfile_info (& pformat_ctx, filename);
av_dump_format (pformat_ctx, 0, filename, false); // Output file information, a very useful function
audio_stream = get_audio_stream_index (pformat_ctx);
pcodec_ctx = pformat_ctx-> streams [audio_stream]-> codec;
// find a corresponding decoder
pcodec = avcodec_find_decoder (pcodec_ctx-> codec_id);
if (pcodec == NULL)
{
fprintf (ERR_STREAM, "Codec not found \ n");
exit (-1);
}
out_buffer = (uint8_t *) av_malloc (MAX_AUDIO_FRAME_SIZE * 2);
audio_buf = out_buffer;
pframe = av_frame_alloc ();
// SDL_AudioSpec, setting parameters for turning on the audio device
// nb_samples: AAC-1024 MP3-1152
// AV_CH_LAYOUT_STEREO: stereo
// Sample format. In an enum
// Sampling rate: 44100, there are 44100 samples per second.
// Number of channels: 1-mono, 2-stereo, 4-quad, 6 -...
wanted_spec.freq = pcodec_ctx-> sample_rate; // sample rate 44100
wanted_spec.format = AUDIO_S16SYS; // Sample format
wanted_spec.channels = pcodec_ctx-> channels; // 1-mono, 2-stereo
wanted_spec.silence = 0; // silence value
wanted_spec.samples = 1024; // Number of output samples
wanted_spec.callback = fill_audio; // callback function
wanted_spec.userdata = pcodec_ctx; // user data
// Open the audio device, return 0 if successful, use SDL_OpenAudioDriver instead
if (SDL_OpenAudio (& wanted_spec, NULL) <0)
{
fprintf (ERR_STREAM, "Couldn't open Audio \ n");
exit (-1);
}
// Set the following parameters for swr_alloc_set_opts after decoding.
out_frame.format = AV_SAMPLE_FMT_S16;
out_frame.sample_rate = wanted_spec.freq;
out_frame.channels = wanted_spec.channels;
out_frame.channel_layout = av_get_default_channel_layout (wanted_spec.channels);
// Open the decoder
if (avcodec_open2 (pcodec_ctx, pcodec, NULL) <0)
{
fprintf (ERR_STREAM, "Couldn't open decoder \ n");
exit (-1);
}
fprintf (ERR_STREAM, "Bit rate:% d \ n", pformat_ctx-> bit_rate);
fprintf (ERR_STREAM, "Decoder Name =% s \ n", pcodec_ctx-> codec-> long_name);
fprintf (ERR_STREAM, "Channels:% d \ n", pcodec_ctx-> channels);
fprintf (ERR_STREAM, "Sample per Second:% d \ n", pcodec_ctx-> sample_rate);
ppacket = (AVPacket *) av_malloc (sizeof (AVPacket));
av_init_packet (ppacket);
// play
SDL_PauseAudio (0); // ???
while (av_read_frame (pformat_ctx, ppacket)> = 0)
{
if (ppacket-> stream_index == audio_stream)
{
decode_len = avcodec_decode_audio4 (pcodec_ctx, pframe, & got_picture, ppacket);
if (decode_len <0)
{
fprintf (ERR_STREAM, "Couldn't decode audio frame \ n");
continue; //
}
if (got_picture)
{
if (swr_ctx! = NULL)
{
swr_free (& swr_ctx);
swr_ctx = NULL;
}
swr_ctx = swr_alloc_set_opts (NULL, out_frame.channel_layout,(AVSampleFormat) out_frame.format, out_frame.sample_rate,
pframe-> channel_layout, (AVSampleFormat) pframe-> format,
pframe-> sample_rate, 0, NULL);
//initialization
if (swr_ctx == NULL || swr_init (swr_ctx) <0)
{
fprintf (ERR_STREAM, "swr_init error \ n");
break;
}
convert_len = swr_convert (swr_ctx, & audio_buf,
MAX_AUDIO_FRAME_SIZE,
(const uint8_t **) pframe-> data,
pframe-> nb_samples);
}
printf ("decode len =% d, convert_len =% d \ n", decode_len, convert_len);
// Back to the buffer head and continue playing data
audio_buf_index = 0;
audio_buf = out_buffer;
// number of channels * length of conversion * length of each sample
audio_len = out_frame.channels * convert_len * av_get_bytes_per_sample ((AVSampleFormat) out_frame.format);
while (audio_len> 0)
{
SDL_Delay (1); // Stop for 1 microsecond
}
}
av_init_packet (ppacket);
// av_free_packet (ppacket);
}
swr_free (& swr_ctx);
SDL_CloseAudio ();
SDL_Quit ();
fclose (output_fp);
av_free (out_buffer);
avcodec_close (pcodec_ctx);
avformat_close_input (& pformat_ctx);
return 0;
}
void fill_audio (void * udata, Uint8 * stream, int len)
{
SDL_memset (stream, 0, len);
if (audio_len == 0)
{
return;
}
len = len> audio_len? audio_len: len;
SDL_MixAudio (stream, (uint8_t *) audio_buf + audio_buf_index, len, SDL_MIX_MAXVOLUME);
audio_buf_index + = len;
audio_len-= len;
stream + = len;
}
void get_file_name (char * filename, int argc, char * argv [])
{
if (argc == 2)
{
memcpy (filename, argv [1], strlen (argv [1]) + 1);
}
else if (argc> 2)
{
fprintf (ERR_STREAM, "Usage: ./*.out audio_file.mp3 \ n");
exit (-1);
}
}
void open_and_find_inputfile_info (AVFormatContext ** pformat_ctx, char * filename)
{
if (avformat_open_input (pformat_ctx, filename, NULL, NULL)! = 0)
{
fprintf (ERR_STREAM, "Couldn 'open input file \ n");
exit (-1);
}
if (avformat_find_stream_info (* pformat_ctx, NULL) <0)
{
fprintf (ERR_STREAM, "Couldn 'find stream info \ n");
exit (-1);
}
}
int get_audio_stream_index (AVFormatContext * pformat_ctx)
{
int i = 0;
int audio_stream = -1;
for (i = 0; i <pformat_ctx-> nb_streams; i ++)
{
if (pformat_ctx-> streams [i]-> codec-> codec_type == AVMEDIA_TYPE_AUDIO)
{
audio_stream = i;
break;
}
}
if (audio_stream == -1)
{
fprintf (ERR_STREAM, "Didn't find audio stream \ n");
exit (-1);
}
return audio_stream;
}
The audio of the ubuntu16.04 output is noisy. Windows did not hear a murmur. Windows uses VS2010 to run. Specific operating methods, see the Thor video.
Raytheon Blog: http://blog.csdn.net/leixiaohua1020/article/details/38979615?locationNum=2 code Download