前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android基础--利用ANativeWindow显示视频

Android基础--利用ANativeWindow显示视频

作者头像
小蚂蚁与大象
发布2020-09-16 14:19:38
7.7K0
发布2020-09-16 14:19:38
举报
文章被收录于专栏:构建FFmpeg Android播放器

利用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
代码语言:javascript
复制
ANativeWindow* ANativeWindow_fromSurface(JNIEnv* env, jobject surface)
  • 释放ANativeWindow引用
代码语言:javascript
复制
void ANativeWindow_release(ANativeWindow* window);
  • 设置窗口buffer的格式和大小
代码语言:javascript
复制
int32_t ANativeWindow_setBuffersGeometry(ANativeWindow* window,
        int32_t width, int32_t height, int32_t format);
  • 锁定窗口的写surface并获取下一个可写的显示缓冲区
代码语言:javascript
复制
int32_t ANativeWindow_lock(ANativeWindow* window, ANativeWindow_Buffer* outBuffer,
        ARect* inOutDirtyBounds);
  • 释放窗口的写surface,并将新的缓冲buffer发送给显示模块
代码语言:javascript
复制
int32_t ANativeWindow_unlockAndPost(ANativeWindow* window)

代码节选

代码语言:javascript
复制
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;
}
代码语言:javascript
复制
void V4L2Camera::setSurface(ANativeWindow *window) {
    std::lock_guard<std::mutex> lock(windowLock);
    if (this->window != 0) {
        ANativeWindow_release(this->window);
    }

    this->window = window;
}
代码语言:javascript
复制
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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Surface, ANativeWindow
  • ANativeWindow的用法
  • 代码节选
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档