最近在移植一个音频特效功能,因项目老代码使用SDL 2.0实现了简单的视频播放器。新增功能是根据音频变化改变视频渲染结果,音频处理算法由Java实现,为了快速验证效果,故在Java中进行音频相关计算。
SDL 2.0的启动流程
以继承SDLActivity为例。
1、实现SurfaceView回调
onCreate(Bundle savedInstanceState)
|- addVideoView();
|- mSurface = new SDLSurface(getApplication());
|- getHolder().addCallback(this);
2、在回调中继续执行初始化
surfaceChanged(SurfaceHolder holder, int format, int width, int height)
|- SDLActivity.playMovieVideo();
|- SDLActivity.mSingleton.OnPlayMovieVideo();
|- SDLActivity.mSingleton.OnPlayMovieVideo(); // 子类覆盖
|- super.startPlayThread()
|- startSDLThread();
|- SDLActivity.mSDLThread = new Thread(new SDLMain(ffmpegString), "SDLThread");
|- SDLActivity.mSDLThread.start();
|- SDLActivity.nativeInit(); // 开始JNI调用
JNI——————————————————————————
[SDL_android_main.c]void Java_org_libsdl_app_SDLActivity_nativeInit(JNIEnv *, jclass, jobject)
|- [SDL_android.c]void SDL_Android_Init(JNIEnv *, jclass)
|- [SDL_android.c]int Android_JNI_SetupThread()
|- [SDL_android.c]JNIEnv *Android_JNI_GetEnv()
|- pthread_setspecific(mThreadKey, (void*) env); // 保存env到SDL线程,方便后续调用Java方法
|- SDL_SetMainReady();
// 预编译后实际方法名为void SDL_SetMainReady_REAL(),对于Android,具体实现为SDL.c文件的void SDL_SetMainReady(void)
|- int SDL_main(int, char **)
// 具体实现为main.cpp文件的int main(int argc, char *argv[]),在此启动SDL消息处理线程开始不断的SDL_PollEvent(&event),类似Win32开发中的WndProc。
音频播放前的处理
为了在音频播放前进行声音的计算,可在SDL 2.0传递数据到AudioTrack前处理。
从SDL的C代码上看,最后会调用SDLActivity类中的方法,比如音频初始化public static int audioInit(int sampleRate, boolean is16Bit, boolean isStereo, int desiredFrames)
,所以Java相关的处理可放在此函数中进行。
当配置成16位整数PCM时,最终调用public static void audioWriteShortBuffer(short[] buffer)
,故对PCM数据的计算可在此进行。
网友评论