Android基础--利用ANativeWindow显示视频
利用Android 写视频显示应用时,经常会用到SurfaceView等控件来显示视频。 在前面的文章Android基础--SurfaceView, Surface, SurfaceHolder中,也简单得提了一下SurfaceView和Surface的关系:SurfaceView提供了一个专门用于绘制的surface。java层实际上是利用SurfaceView将视频数据渲染到Surface上。
而Native层要渲染视频可以通过ANativeWindow来渲染。
Surface, ANativeWindow
先来看下官网的解释
The public surface class is implemented in the Java programming language. The equivalent in C/C++ is the ANativeWindow class, semi-exposed by the Android NDK. You can get the ANativeWindow from a surface with the ANativeWindow_fromSurface () call. Just like its Java-language cousin, you can lock it, render in software, and unlock-and-post.
可以看到 native层的ANativeWindow 就等价于Java层的Surface,可以通过接口ANativeWindow_fromSurface ()从surface对象中获取到,可以通过软件对其进行lock, render, unlock-and-post等操作
ANativeWindow的用法
看一下大体的流程图
ANativeWindow.png
主要流程是下面几点
- java层将Surface传递给native层
- 获取ANativeWindow对象
- 将显示数据写到ANativeWindow的buffer中,注意需要将显示的数据格式转换成ANativeWindow设置的数据格式
- 释放ANativeWindow
涉及到的类和接口: https://developer.android.google.cn/ndk/reference/group/a-native-window?hl=zh-cn
Typedefs |
|
---|---|
ANativeWindow |
typedef struct ANativeWindow Opaque type that provides access to a native window. |
ANativeWindow_Buffer |
typedef struct ANativeWindow_Buffer Struct that represents a windows buffer. |
- 获取ANativeWindow
ANativeWindow* ANativeWindow_fromSurface(JNIEnv* env, jobject surface)
- 释放ANativeWindow引用
void ANativeWindow_release(ANativeWindow* window);
- 设置窗口buffer的格式和大小
int32_t ANativeWindow_setBuffersGeometry(ANativeWindow* window,
int32_t width, int32_t height, int32_t format);
- 锁定窗口的写surface并获取下一个可写的显示缓冲区
int32_t ANativeWindow_lock(ANativeWindow* window, ANativeWindow_Buffer* outBuffer,
ARect* inOutDirtyBounds);
- 释放窗口的写surface,并将新的缓冲buffer发送给显示模块
int32_t ANativeWindow_unlockAndPost(ANativeWindow* window)
代码节选
static int com_iview_camera_native_setSurface(JNIEnv *env, jobject thiz, jobject surface) {
if (v4l2Camera == 0) {
return ERROR_CAPABILITY_UNSUPPORT;
}
ANativeWindow *window = ANativeWindow_fromSurface(env, surface);
v4l2Camera->setSurface(window);
return 0;
}
void V4L2Camera::setSurface(ANativeWindow *window) {
std::lock_guard<std::mutex> lock(windowLock);
if (this->window != 0) {
ANativeWindow_release(this->window);
}
this->window = window;
}
void V4L2Camera::renderVideo(unsigned char *preview) {
std::lock_guard<std::mutex> lock(windowLock);
if (window == 0) {
return;
}
ALOGE("RenderVideoElement width:%d, height:%d", width,height);
ANativeWindow_setBuffersGeometry(window, width,
height,
WINDOW_FORMAT_RGBA_8888);
ANativeWindow_Buffer window_buffer;
if (ANativeWindow_lock(window, &window_buffer, 0)) {
ANativeWindow_release(window);
window = 0;
return;
}
//把buffer中的数据进行赋值(修改)
uint8_t *dst_data = static_cast<uint8_t *>(window_buffer.bits);
memcpy(dst_data, preview, width*height*4);
ANativeWindow_unlockAndPost(window);
}
完整的代码可以去参考: 利用ffmpeg实现的Android播放器 https://github.com/yizhongliu/FFMediaPlayer
利用V4L2接口操作Android usb摄像头 https://github.com/yizhongliu/AnV4L2Camera
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法