悠播Hd
- 4. 公司简介 1. 悠米 - 视频播放器 2. 悠米 - 视频聊天 3. 悠米 - 3G可视电话 4. 悠米 - 手机电视 5. 悠米 - 视频游戏 6. 悠米 - 手机网游 7. 悠米 - 3G音乐盒 8. 悠米 - 智能中心 9. 悠米-网络电台 10. 悠米-书屋 智能机 & 非智能机
- 5. 悠播 HD 产品介绍 专门为安卓 3.0 及以上的平板电脑量身打造的高端视频播放器。 1 继承了手机版悠播强劲的解码能力以及良好的播放体验,达到 720P 流畅播放水平; 2 采用两侧弹出式 UI ,并且用户可以根据自身操作习惯进行自定义;真正的为宅男们“ 解放一只手! ” 3 自动多维度筛选视频 & 智能分段 & 快照 & 截屏 4 支持 AVI 、 MP4 、 FLV 、 3GP 、 RMVB 等主流媒体格式 5
- 7. 技术实现概况 1 、音视频解码 支持 Amr Mp3 AAC PCM, H264 H263 RMVB XVID 等主流解码格式 2 、音视频回放 Audiotrack MediaPlayer SurfaceView 4 、上层 UI 搭建 炫酷的界面和良好的操作体验 3 、 JNI 使用 调用音视频解码、音频播放以及视频绘制
- 9. 音频播放 由于音频解码是在 native 层做的,解码后保存在一个缓冲队列里面。一般有两种方法播放: 1 、 java 层播放:上层创建个线程,在线程里面不断的 get native 层的数据, write 到 AudioTrack 。 这里遇到一个问题: 为了做音视频的同步播放,需要知道 AudioTrack 播放了多少数据,剩余多少数据, java 层没有提供接口。通过研究 AudioTrack.c 源码, AudioTrack 类里面有个 getPosition 的方法,可以返回当前播放的数据位置。所以我们采用了第二种方法。 2 、 native 层播放:通过 FindClass , GetMethodId , CallVoidMethod 等 jni 接口,创建 AudioTrack 。使用 pthread 创建播放线程,开启播放,直接取数据 write 进 AudioTrack 。
- 10. 音频播放 如何调用 getPosition 呢? java 调用的接口,一般都是通过 jni ,初始化 c 层的实例,调用其接口。 查看 AudioTrack.java 源码,有个整形变量 mNativeTrackInJavaObj ,这个就是 C 层的 AudioTrack 类的实例了。 在 jni 层 GetIntField 方法可以得到 mNativeTrackInJavaObj ,把这个强转为 AudioTrack* 就可以执行 getPosition 了。 编译的时候,需要用到头文件。
- 11. 视频绘制 视频解码也是在 native 层做的,如何显示出来呢? 1 、把 RGB 数据抛到上层,构建 bitmap ,起一个绘制线程,每次都去取这个 bitmap ,在 SurfaceView 上面绘制 优点: java 层做绘制,比较方便控制放大缩小等效果 缺点:要通过 jni 返回数据,并且上层要构建 bitmap ,效率有所影响。 2 、能不能 jni 层绘制,直接把解码出来的 RGB 做拷贝刷新屏幕?
- 12. 视频绘制 1 、 framebuffer 优点:速度快,直接刷屏 缺点:会破坏 android 绘制机制,不和谐! 2 、 SurfaceView 上层构建 surfaceview ,把 holder 传到 native 层,有数据需要绘制的时候, lock 返回一个指针,然后把 RGB565 数据直接 memcpy , unlockAndPost 就可以刷新到屏幕了。 优点:速度快 缺点:跟系统 so 以及 h 文件有关,不利于兼容性。
- 13. 动态加载 什么是动态加载? 编译时候和程序链接在一起的叫静态加载。 lib a 在程序运行的时候,直接加载运行的,叫动态加载 。 dll, so, bin Android 中如何动态加载? 为了兼容其他平台,编码库是用 rvct 编译的成 bin 的,在 android 平台上需要用到动态加载。 1 、 System.Loadlibrary(); 2 、 dlopen, dlsym… 3 、 flushcache , mprotect
- 14. 动态加载 Test.c #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef __cplusplus extern "C" { #endif typedef struct { void (*TBL_Test)(); }TInTbl; int Dll_Entry(void *pInTbl) { ((TInTbl *)pInTbl)->TBL_Test(); return 1; } #ifdef __cplusplus } #endif
- 15. 动态加载 mk 文件: LINK_ORDER = --first Dll_Entry LFLAGS = --entry Dll_Entry
- 16. 动态加载 Testjni.c void Test() { LOGE("Test Dll Entry"); } void TestCache() { TInTbl tbl = {0}; tbl.TBL_Test = Test; char* pBuf = (char*) malloc(fileSize); FILE* pFile = fopen("test.bin"); int fileSize = GetFileSize(pFile); fread(pFile, 1, fileSize, pBuf, "rb"); fclose(pFile); cacheflush ((long)pBuf, (long)((char*)pBuf + fileSize), 0); mprotect ((void *)pBuf,fileSize, PROT_READ | PROT_EXEC | PROT_WRITE); ((int (*)(void*))pBuf)(&tbl, NULL); free(pBuf); }