Project Address
Https://github.com/979451341/FFmpegOpenslES
This is the FFmpeg decoding MP3, the data to OpenSL es playback, and to be able to pause.
1. Creating an engine
slCreateEngine(&engineObject,0,NULL,0,NULL,NULL);//创建引擎(*engineObject)->Realize(engineObject,SL_BOOLEAN_FALSE);//实现engineObject接口对象(*engineObject)->GetInterface(engineObject,SL_IID_ENGINE,&engineEngine);//通过引擎调用接口初始化SLEngineItf
2. Create a mixer
(*engineEngine)->CreateOutputMix(engineEngine,&outputMixObject,0,0,0);//用引擎对象创建混音器接口对象(*outputMixObject)->Realize(outputMixObject,SL_BOOLEAN_FALSE);//实现混音器接口对象SLresult sLresult = (*outputMixObject)->GetInterface(outputMixObject,SL_IID_ENVIRONMENTALREVERB,&outputMixEnvironmentalReverb);//利用混音器实例对象接口初始化具体的混音器对象//设置if (SL_RESULT_SUCCESS == sLresult) { (*outputMixEnvironmentalReverb)-> SetEnvironmentalReverbProperties(outputMixEnvironmentalReverb, &settings);}
3.FFmpeg Decoding MP3 prep work
av_register_all();char *input = "/storage/emulated/0/pauseRecordDemo/video/a.mp3";pFormatCtx = avformat_alloc_context();LOGE("Lujng %s",input);LOGE("xxx %p",pFormatCtx);int error;char buf[] = "";//打开视频地址并获取里面的内容(解封装)if (error = avformat_open_input(&pFormatCtx, input, NULL, NULL) < 0) { av_strerror(error, buf, 1024); // LOGE("%s" ,inputPath) LOGE("Couldn‘t open file %s: %d(%s)", input, error, buf); // LOGE("%d",error) LOGE("打开视频失败")}//3.获取视频信息if(avformat_find_stream_info(pFormatCtx,NULL) < 0){ LOGE("%s","获取视频信息失败"); return -1;}int i=0;for (int i = 0; i < pFormatCtx->nb_streams; ++i) { if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) { LOGE(" 找到音频id %d", pFormatCtx->streams[i]->codec->codec_type); audio_stream_idx=i; break; }}
MP3 's Decoder
Get Audio Codec
pcodecctx=pformatctx->streams[audio_stream_idx]->codec;
LOGE ("Get Video Encoder context%p", pcodecctx);
pCodex = avcodec_find_decoder(pCodecCtx->codec_id);LOGE("获取视频编码 %p",pCodex);if (avcodec_open2(pCodecCtx, pCodex, NULL)<0) {}packet = (AVPacket *)av_malloc(sizeof(AVPacket));
Av_init_packet (packet);
Audio data
frame = av_frame_alloc();
The encoded format contained in the MP3 is converted into PCM Swccontext
Swrcontext = Swr_alloc ();
int length=0;int got_frame;
441002
Out_buffer = (uint8_t ) av_malloc (44100 * 2);
uint64_t Out_ch_layout=av_ch_layout_stereo;
Output Sample bits 16 bits
Enum Avsampleformat OUT_FORMART=AV_SAMPLE_FMT_S16;
The sample rate of the output must be the same as the input
int out_sample_rate = pcodecctx->sample_rate;
swr_alloc_set_opts(swrContext, out_ch_layout, out_formart, out_sample_rate, pCodecCtx->channel_layout, pCodecCtx->sample_fmt, pCodecCtx->sample_rate, 0, NULL);swr_init(swrContext);
Get the number of channels 2
OUT_CHANNER_NB = Av_get_channel_layout_nb_channels (Av_ch_layout_stereo);
Rate = pcodecctx->sample_rate;
Channel = pcodecctx->channels;
4. Cache Queue Settings
int rate;int channels;createFFmpeg(&rate,&channels);LOGE("RATE %d",rate);LOGE("channels %d",channels);/* * typedef struct SLDataLocator_AndroidBufferQueue_ {SLuint32 locatorType;//缓冲区队列类型SLuint32 numBuffers;//buffer位数
} */
Sldatalocator_androidbufferqueue android_queue = {sl_datalocator_androidsimplebufferqueue,2};/**typedef struct sldataformat_pcm_ {SLuint32 formattype; PCM SLuint32 Numchannels; Number of channels SLuint32 samplespersec; Sampling rate SLuint32 bitspersample; Number of sample bits SLuint32 containersize; Contains the number of bits SLuint32 channelmask; Stereo SLuint32 endianness; End flag bit} SLDATAFORMAT_PCM; */SLDATAFORMAT_PCM PCM = {sl_dataformat_pcm,channels,rate*1000, sl_pcmsampleformat_fixed_16, SL_PCMSAMPLEFOR MAT_FIXED_16, sl_speaker_front_left|sl_speaker_front_right,sl_byteorder_littleendian};/* * typedef struct SLDATASOU rce_ {void *plocator;//buffer queue void *pformat;//data style, configuration information} Sldatasource; * */sldatasource DataSource = {&android_queue,&pcm}; Sldatalocator_outputmix Sldatalocator_outputmix={sl_datalocator_outputmix,outputmixobject}; Sldatasink Sldatasink = {&sldatalocator_outputmix,null};const Slinterfaceid ids[3]={Sl_iid_bufferqueue,sl_iid_effectsend,sl_iid_volume};const Slboolean req[3]={sl_boolean_false,sl_boolean_false, sl_boolean_false};/* * Slresult (*createaudioplayer) (SLENGINEITF self, SLOBJECTITF * Pplayer, SLDataSource *pAu diosrc,//Data Settings Sldatasink *paudiosnk,//associated mixer SLuint32 numinterfaces, const SLINTERFACEID * pinterfaceids, const Slboolean * pinterfacerequired); * */loge ("Execute Here") (*engineengine)->createaudioplayer (engineengine,&audioplayer,&datasource,& Sldatasink,3,ids,req)->realize (audioplayer,sl_boolean_false);(*audioplayer); LOGE ("Execute here 2") (*audioplayer)->getinterface (AUDIOPLAYER,SL_IID_PLAY,&SLPLAYITF);//Initialize player//register buffer, through buffer inside Data for playback (*audioplayer)->getinterface (AUDIOPLAYER,SL_IID_BUFFERQUEUE,&SLBUFFERQUEUEITF);//Set Callback interface (* SLBUFFERQUEUEITF)->registercallback (slbufferqueueitf,getqueuecallback,null);
Finally, give the cache callback function parameters, this callback function is mainly responsible for providing ffmpeg decoded data
//开始播放getQueueCallBack(slBufferQueueItf,NULL);
Let's take a look at what this function says, by enqueue the data into the queue, which is obtained from the GETPCM function.
void Getqueuecallback (SLANDROIDSIMPLEBUFFERQUEUEITF slbufferqueueitf, void context) {
buffersize=0;
GETPCM (&buffer,&buffersize);
if (buffer!=null&&buffersize!=0) {
Adding the resulting data to the queue
(SLBUFFERQUEUEITF)->enqueue (slbufferqueueitf,buffer,buffersize);
}
}
This ffmpeg decoding mp3 to get the PCM data, this is the main decoding a packet data, jump out of the loop, the data to the upper function into the queue, when the queue of data read, The Getqueuecallback function is called again to get the PCM data decoded by the FFmpeg.
int getpcm (void *pcm,size_t pcm_size) {
int framecount=0;
int got_frame;
while (Av_read_frame (pformatctx, packet) >= 0) {
if (Packet->stream_index = = Audio_stream_idx) {
Decode MP3 encoded format frame----PCM frame
Avcodec_decode_audio4 (Pcodecctx, frame, &got_frame, packet);
if (got_frame) {
LOGE ("decoding");
/**
- int Swr_convert (struct swrcontext s, uint8_t out , int out_count,
Const uint8_t in, int in_count);
/
Swr_convert (Swrcontext, &out_buffer, 44100 * 2, (const uint8_t *) Frame->data, frame->nb_samples);
Size of the buffer
int size = Av_samples_get_buffer_size (NULL, OUT_CHANNER_NB, Frame->nb_samples,
AV_SAMPLE_FMT_S16, 1);
PCM = Out_buffer;
*pcm_size = size;
Break
}
}
}
return 0;
}
5. Play Music
(*slPlayItf)->SetPlayState(slPlayItf,SL_PLAYSTATE_PLAYING);
6. Pause Music
(*slPlayItf)->SetPlayState(slPlayItf, SL_PLAYSTATE_PAUSED);
7. Releasing Resources
First release the entity about OpenSL ES
if(audioplayer!=NULL){ (*audioplayer)->Destroy(audioplayer); audioplayer=NULL; slBufferQueueItf=NULL; slPlayItf=NULL;}if(outputMixObject!=NULL){ (*outputMixObject)->Destroy(outputMixObject); outputMixObject=NULL; outputMixEnvironmentalReverb=NULL;}if(engineObject!=NULL){ (*engineObject)->Destroy(engineObject); engineObject=NULL; engineEngine=NULL;}
Then release the resources that FFmpeg occupies
av_free_packet(packet);av_free(out_buffer);av_frame_free(&frame);swr_free(&swrContext);avcodec_close(pCodecCtx);avformat_close_input(&pFormatCtx);
Android Audio Video Depth 14 ffmpeg with OpenSL ES play mp3 music, can pause (attached source