open sl java audio_ijkplayer源码分析之audio与opensl es初始化

ijkplayer源码分析之opengl与surface关联初始化

=====================================================

ijkplayer源码分析系列文章列表:

======================================================

audio的初始化

IjkVideoView.java

// OPT_CATEGORY_PLAYER = 4;

if (mSettings.getUsingOpenSLES())

|--ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "opensles", 1);

|--_setOption(category, name, value);

goto Ijkplayer_jni.c

将键值对保存到ffp->player_opts中

IjkMediaPlayer_setOptionLong(JNIEnv *env, jobject thiz, jint category, jobject name, jlong value)

|--ijkmp_set_option_int(mp, category, c_name, value);

|--ffp_set_option_int(mp->ffplayer, opt_category, name, value);

|--AVDictionary **dict = ffp_get_opt_dict(ffp, opt_category);

| |--&ffp->player_opts; // AVDictionary *player_opts;

|--av_dict_set_int(dict, name, value, 0); //将键值对保存到`ffp->player_opts`中

|--av_dict_set(pm, key, valuestr, flags);

//pipeline->func_open_audio_output = func_open_audio_output;

IjkMediaPlayer_prepareAsync //Ijkplayer_jni.c

|--ijkmp_prepare_async

|--ijkmp_prepare_async_l(IjkMediaPlayer *mp) //Ijkplayer.c

|--ffp_prepare_async_l(FFPlayer *ffp, const char *file_name) //Ff_ffplay.c

|--ffp->aout = ffpipeline_open_audio_output(ffp->pipeline, ffp);

|--pipeline->func_open_audio_output(pipeline, ffp); //

|--func_open_audio_output

|--if (ffp->opensles)

| |--SDL_AoutAndroid_CreateForOpenSLES();

|--else

|--SDL_AoutAndroid_CreateForAudioTrack();

这里先分析使用OpenSLES的情况

1.创建OpenSL引擎并将引擎及回调信息填充到FFPlayer->aout中(SDL_Aout *aout;)

SDL_AoutAndroid_CreateForOpenSLES

|--SDL_Aout *aout = SDL_Aout_CreateInternal(sizeof(SDL_Aout_Opaque));

|--slCreateEngine(&slObject, 0, NULL, 0, NULL, NULL);

|--SDL_Aout_Opaque *opaque = aout->opaque;

|--opaque->slObject = slObject;

|--opaque->slEngine = slEngine;

|--opaque->slOutputMixObject = slOutputMixObject;

|--aout->free_l = aout_free_l;

|--aout->opaque_class = &g_opensles_class;

|--aout->open_audio = aout_open_audio;

|--aout->pause_audio = aout_pause_audio;

|--aout->flush_audio = aout_flush_audio;

|--aout->close_audio = aout_close_audio;

|--aout->set_volume = aout_set_volume;

|--aout->func_get_latency_seconds = aout_get_latency_seconds;

Audio Spec

typedef struct SDL_AudioSpec

{

int freq; /**< DSP frequency -- samples per second */

SDL_AudioFormat format; /**< Audio data format */

Uint8 channels; /**< Number of channels: 1 mono, 2 stereo */

Uint8 silence; /**< Audio buffer silence value (calculated) */

Uint16 samples; /**< Audio buffer size in samples (power of 2) */

Uint16 padding; /**< NOT USED. Necessary for some compile environments */

Uint32 size; /**< Audio buffer size in bytes (calculated) */

SDL_AudioCallback callback;

void *userdata;

} SDL_AudioSpec;

typedef struct SDL_Aout_Opaque {

SDL_cond *wakeup_cond;

SDL_mutex *wakeup_mutex;

SDL_Thread *audio_tid;

SDL_Thread _audio_tid;

SDL_AudioSpec spec;

SLDataFormat_PCM format_pcm;

int bytes_per_frame;

int milli_per_buffer;

int frames_per_buffer;

int bytes_per_buffer;

SLObjectItf slObject;

SLEngineItf slEngine;

SLObjectItf slOutputMixObject;

SLObjectItf slPlayerObject;

SLAndroidSimpleBufferQueueItf slBufferQueueItf;

SLVolumeItf slVolumeItf;

SLPlayItf slPlayItf;

volatile bool need_set_volume;

volatile float left_volume;

volatile float right_volume;

volatile bool abort_request;

volatile bool pause_on;

volatile bool need_flush;

volatile bool is_running;

uint8_t *buffer;

size_t buffer_capacity;

} SDL_Aout_Opaque;

2.打开音频

#define OPENSLES_BUFFERS 255 /* maximum number of buffers */

#define OPENSLES_BUFLEN 10 /* ms */

read_thread //Ff_ffplay.c

|--stream_component_open(ffp, st_index[AVMEDIA_TYPE_AUDIO]);

|--audio_open(ffp, channel_layout, nb_channels, sample_rate, &is->audio_tgt)

|--wanted_spec.format = AUDIO_S16SYS;

|--wanted_spec.silence = 0;

|--wanted_spec.callback = sdl_audio_callback;

|--wanted_spec.userdata = opaque;

|--SDL_AoutOpenAudio(ffp->aout, &wanted_spec, &spec)

|--aout->open_audio(aout, desired, obtained);

|--aout_open_audio(SDL_Aout *aout, const SDL_AudioSpec *desired, SDL_AudioSpec *obtained)

|--SDL_Aout_Opaque *opaque = aout->opaque;

|--opaque->spec = *desired;

|--(*opaque->slBufferQueueItf)->RegisterCallback(opaque->slBufferQueueItf, aout_opensles_callback, (void*)aout); //添加音频播放完成回调

|--opaque->bytes_per_frame = format_pcm->numChannels * format_pcm->bitsPerSample / 8;

| //每一帧占用几个字节

|--opaque->milli_per_buffer = OPENSLES_BUFLEN;

| //每个buffer要占用多少毫秒

|--opaque->frames_per_buffer = opaque->milli_per_buffer * format_pcm->samplesPerSec / 1000000; // samplesPerSec is in milli

| //每个buffer有几帧

|--opaque->bytes_per_buffer = opaque->bytes_per_frame * opaque->frames_per_buffer;

|--opaque->buffer_capacity = OPENSLES_BUFFERS * opaque->bytes_per_buffer;

|--for(int i = 0; i < OPENSLES_BUFFERS; ++i)

| |--(*opaque->slBufferQueueItf)->Enqueue(opaque->slBufferQueueItf, opaque->buffer + i * opaque->bytes_per_buffer, opaque->bytes_per_buffer);

| // 将数据添加到播放队列

|--SDL_CreateThreadEx(&opaque->_audio_tid, aout_thread, aout, "ff_aout_opensles");

|--aout_thread_n(arg);

|--SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);

时序图

b8fea3ddd8c9566907d44865f1c5ca75.png

时序图.jpg

音频输出线程分析(aout_thread_n)

85d1af25500abe46b2aabf77975cbd97.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值