sdl + ffmpeg 播放多个mp3

完整代码:


#include <stdio.h>
#include <stdlib.h>
#include <string.h>


#define __STDC_CONSTANT_MACROS
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavdevice/avdevice.h"
#include "libavfilter/avfilter.h"
#include "libavfilter/avfiltergraph.h"
#include "libavfilter/buffersink.h"
#include "libavfilter/buffersrc.h"
#include "libavutil/audio_fifo.h"
#include "libavutil/avutil.h"
#include "libavutil/fifo.h"
#include"sdl\SDL.h"
#include"libswresample/swresample.h"
}


#pragma comment(lib, "avcodec.lib")
#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "avutil.lib")
#pragma comment(lib, "avdevice.lib")
#pragma comment(lib, "avfilter.lib")


#define MAX_MUSIC_DATA 5
#pragma comment(lib, "swscale.lib")




#define MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audio


//Buffer:
//|-----------|-------------|
//chunk-------pos---len-----|




typedef struct _AudioData
{
	Uint8  *audio_chunk;
	Uint32  audio_len;
	Uint8  *audio_pos;
	char filename[256];
	int volume;
	AVFormatContext	*pFormatCtx;
	int				 audioStream;
	AVCodecContext	*pCodecCtx;
	AVCodec			*pCodec;
	AVPacket		*packet;
	uint8_t			*out_buffer;
	AVFrame			*pFrame;
	SDL_AudioSpec wanted_spec;
	uint32_t len ;
	int got_picture;
	int index;
	int64_t in_channel_layout;
	struct SwrContext *au_convert_ctx;
	int out_buffer_size;


}AudioData;
AudioData AData[2];


void  fill_audio(void *udata, Uint8 *stream, int len) {
	//SDL 2.0
	SDL_memset(stream, 0, len);


	for (int m = 0; m < 2; ++m)
	{
		if (AData[m].audio_len == 0)
			continue;
		len = (len>AData[m].audio_len ? AData[m].audio_len : len);	/*  Mix  as  much  data  as  possible  */
		SDL_MixAudio(stream, AData[m].audio_pos, len, int(AData[m].volume*1.28));
		AData[m].audio_pos += len;
		AData[m].audio_len -= len;
	}


}
//-----------------




int main(int argc, char* argv[])
{


	av_register_all();
	avformat_network_init();
	int ret = 0;


	memset(AData[0].filename, 0, 256);
	strcpy(AData[0].filename, "003.mp3");


	memset(AData[1].filename, 0, 256);
	strcpy(AData[1].filename, "004.mp3");
	AData[0].volume = 80;
	AData[1].volume = 30;
	for (int m = 0; m < 2; ++m)
	{
		AData[m].pFormatCtx = avformat_alloc_context();
		//Open
		if (avformat_open_input(&AData[m].pFormatCtx, AData[m].filename, NULL, NULL) != 0) {
			printf("Couldn't open input stream.\n");
			return -1;
		}
		// Retrieve stream information
		if (avformat_find_stream_info(AData[m].pFormatCtx, NULL)<0) {
			printf("Couldn't find stream information.\n");
			return -1;
		}
		// Dump valid information onto standard error


		av_dump_format(AData[m].pFormatCtx, 0, AData[m].filename, false);


		// Find the first audio stream
		AData[m].audioStream = -1;
		for (int i = 0; i < AData[m].pFormatCtx->nb_streams; i++)
			if (AData[m].pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
				AData[m].audioStream = i;
				break;
			}


		if (AData[m].audioStream == -1) {
			printf("Didn't find a audio stream.\n");
			return -1;
		}


		// Get a pointer to the codec context for the audio stream
		AData[m].pCodecCtx = AData[m].pFormatCtx->streams[AData[m].audioStream]->codec;


		// Find the decoder for the audio stream
		AData[m].pCodec = avcodec_find_decoder(AData[m].pCodecCtx->codec_id);
		if (AData[m].pCodec == NULL) {
			printf("Codec not found.\n");
			return -1;
		}


		// Open codec
		if (avcodec_open2(AData[m].pCodecCtx, AData[m].pCodec, NULL)<0) {
			printf("Could not open codec.\n");
			return -1;
		}




		AData[m].packet = (AVPacket *)av_malloc(sizeof(AVPacket));
		av_init_packet(AData[m].packet);




		uint64_t out_channel_layout = AV_CH_LAYOUT_STEREO;
		int out_channels = av_get_channel_layout_nb_channels(out_channel_layout);
		//Out Audio Param
		//nb_samples: AAC-1024 MP3-1152
		int out_sample_rate = 44100;
		int out_nb_samples = AData[m].pCodecCtx->frame_size;
		AVSampleFormat out_sample_fmt = AV_SAMPLE_FMT_S16;


		//Out Buffer Size
		AData[m].out_buffer_size = av_samples_get_buffer_size(NULL, out_channels, out_nb_samples, out_sample_fmt, 1);


		AData[m].out_buffer = (uint8_t *)av_malloc(MAX_AUDIO_FRAME_SIZE * 2);
		AData[m].pFrame = av_frame_alloc();
		//SDL------------------


		//Init
		if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
			printf("Could not initialize SDL - %s\n", SDL_GetError());
			return -1;
		}
	    AData[m].in_channel_layout = av_get_default_channel_layout(AData[m].pCodecCtx->channels);
		//Swr
		AData[m].au_convert_ctx = swr_alloc();
		AData[m].au_convert_ctx = swr_alloc_set_opts(AData[m].au_convert_ctx, out_channel_layout, out_sample_fmt, out_sample_rate,
			AData[m].in_channel_layout, AData[m].pCodecCtx->sample_fmt, AData[m].pCodecCtx->sample_rate, 0, NULL);
		swr_init(AData[m].au_convert_ctx);


		//Play


	}
	int m = 0;
	uint64_t out_channel_layout = AV_CH_LAYOUT_STEREO;
	int out_channels = av_get_channel_layout_nb_channels(out_channel_layout);
	int out_sample_rate = 44100;
	AData[m].wanted_spec.freq = out_sample_rate;
	AData[m].wanted_spec.format = AUDIO_S16SYS;
	AData[m].wanted_spec.channels = out_channels;
	AData[m].wanted_spec.silence = 0;
	AData[m].wanted_spec.samples = AData[m].pCodecCtx->frame_size;
	AData[m].wanted_spec.callback = fill_audio;
	AData[m].wanted_spec.userdata = AData[m].pCodecCtx;


	if (SDL_OpenAudio(&AData[m].wanted_spec, NULL)<0) {
		printf("can't open audio.\n");
		return -1;
	}
	SDL_PauseAudio(0);
	while (true)
	{
		for (int n = 0; n < 2; ++n)
		{
			if (av_read_frame(AData[n].pFormatCtx, AData[n].packet) >= 0)
			{
				if (AData[n].packet->stream_index == AData[n].audioStream)
				{
					ret = avcodec_decode_audio4(AData[n].pCodecCtx, AData[n].pFrame, &AData[n].got_picture, AData[n].packet);
					if (ret < 0) {
						printf("Error in decoding audio frame.\n");
						return -1;
					}
					if (AData[n].got_picture > 0) {
						swr_convert(AData[n].au_convert_ctx, &AData[n].out_buffer, MAX_AUDIO_FRAME_SIZE, (const uint8_t **)AData[n].pFrame->data, AData[n].pFrame->nb_samples);
					}


					while (AData[n].audio_len>0)//Wait until finish
						SDL_Delay(1);


					//Set audio buffer (PCM data)
					AData[n].audio_chunk = (Uint8 *)AData[n].out_buffer;
					//Audio buffer length
					AData[n].audio_len = AData[n].out_buffer_size;
					AData[n].audio_pos = AData[n].audio_chunk;
				}
				av_free_packet(AData[n].packet);
			}
		}
	}


	getchar();
	for (int k = 0; k < 2; ++k)
	{
		swr_free(&AData[k].au_convert_ctx);


		SDL_CloseAudio();//Close SDL
		SDL_Quit();
		av_free(AData[k].out_buffer);
		avcodec_close(AData[k].pCodecCtx);
		avformat_close_input(&AData[k].pFormatCtx);
	}	
	return 0;
}


参考:http://blog.csdn.net/u013080313/article/details/50387244

猜你喜欢

转载自blog.csdn.net/xzpblog/article/details/78769945