最简单的基于FFMPEG+SDL的音频播放器:拆分

本文补充记录《最简单的基于FFMPEG+SDL的音频播放器》中的两个例子:FFmpeg音频解码器和SDL音频采样数据播放器。这两个部分是从音频播放器中拆分出来的两个例子。FFmpeg音频解码器实现了视频数据到PCM采样数据的解码,而SDL音频采样数据播放器实现了PCM数据到音频设备的播放。简而言之,原先的FFmpeg+SDL音频播放器实现了:

音频数据->PCM->音频设备

FFmpeg音频解码器实现了:

音频数据->PCM

SDL音频采样数据播放器实现了:

PCM->音频设备

FFmpeg音频解码器源代码/** * 最简单的基于FFmpeg的音频解码器 * Simplest FFmpeg Audio Decoder * * 雷霄骅 Lei Xiaohua * leixiaohua1020@126.com * 中国传媒大学/数字电视技术 * Communication University of China / Digital TV Technology * * * 本程序可以将音频码流(mp3,AAC等)解码为PCM采样数据。 * 是最简单的FFmpeg音频解码方面的教程。 * 通过学习本例子可以了解FFmpeg的解码流程。 * * This software decode audio streams (AAC,MP3 …) to PCM data. * Suitable for beginner of FFmpeg. * */#include <stdio.h>#include <stdlib.h>#include <string.h>#define __STDC_CONSTANT_MACROS#ifdef _WIN32//Windowsextern "C"{#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"#include "libswresample/swresample.h"};#else//Linux…#ifdef __cplusplusextern "C"{#endif#include <libavcodec/avcodec.h>#include <libavformat/avformat.h>#include <libswresample/swresample.h>#ifdef __cplusplus};#endif#endif#define MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audioint main(int argc, char* argv[]){AVFormatContext*pFormatCtx;inti, audioStream;AVCodecContext*pCodecCtx;AVCodec*pCodec;AVPacket*packet;uint8_t*out_buffer;AVFrame*pFrame;int ret;uint32_t len = 0;int got_picture;int index = 0;int64_t in_channel_layout;struct SwrContext *au_convert_ctx;FILE *pFile=fopen("output.pcm", "wb");char url[]="skycity1.mp3";av_register_all();avformat_network_init();pFormatCtx = avformat_alloc_context();//Openif(avformat_open_input(&pFormatCtx,url,NULL,NULL)!=0){printf("Couldn’t open input stream.\n");return -1;}// Retrieve stream informationif(avformat_find_stream_info(pFormatCtx,NULL)<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==AVMEDIA_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(pCodecCtx, pCodec,NULL)<0){printf("Could not open codec.\n");return -1;}packet=(AVPacket *)av_malloc(sizeof(AVPacket));av_init_packet(packet);//Out Audio Paramuint64_t out_channel_layout=AV_CH_LAYOUT_STEREO;//nb_samples: AAC-1024 MP3-1152int 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 Sizeint 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();//FIX:Some Codec’s Context Information is missingin_channel_layout=av_get_default_channel_layout(pCodecCtx->channels);//Swrau_convert_ctx = swr_alloc();au_convert_ctx=swr_alloc_set_opts(au_convert_ctx,out_channel_layout, out_sample_fmt, out_sample_rate,in_channel_layout,pCodecCtx->sample_fmt , pCodecCtx->sample_rate,0, NULL);swr_init(au_convert_ctx);while(av_read_frame(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 ){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);//Write PCMfwrite(out_buffer, 1, out_buffer_size, pFile);index++;}}av_free_packet(packet);}swr_free(&au_convert_ctx);fclose(pFile);av_free(out_buffer);// Close the codecavcodec_close(pCodecCtx);// Close the video fileavformat_close_input(&pFormatCtx);return 0;}运行结果程序运行后,会解码下面的音频文件。

解码后的PCM采样数据被保存成了一个文件。使用Adobe Audition设置采样率等信息后可以查看PCM的内容。我的眼泪流了下来,浇灌了下面柔软的小草,

最简单的基于FFMPEG+SDL的音频播放器:拆分

相关文章:

你感兴趣的文章:

标签云: