[chatGPT] 如何通过JNI在Android上显示实时视频流

news2024/9/23 15:19:58

目录

  • 背景
    • 正文
        • layout xml
        • java
        • C++
        • java
      • 总结一:
    • 追问:
        • C++
        • C++
      • 总结二:
      • 答疑解惑
        • C++
    • 画蛇添足 视频不显示黑屏
  • 最后感叹科技的更新速度,真的程序员都可能会被替代,下一个时代最大的问题应该是劳动力过剩,导致社会性结构改变,一部分人会被社会性抛弃。

背景

相机拍摄的画面通过local socket 获取,所以C++的代码可以轻易的获取到每一帧视频数据,需要通过JNI 让 Android显示出来,方法有两种,一种是在Android内创建回调函数使用Bitmap 和ImageView 进行赋值显示,另一种也就是ChatGPT完成的,Android将surface 传递到JNI层内,C++来完成赋值和渲染,后者效率更高。
本文通过和ChatGPT的对话来描述代码的实现过程。

正文

礼貌性问候一下。
在这里插入图片描述
开始吧:
在这里插入图片描述

MediaPlayer mediaPlayer = new MediaPlayer();
SurfaceView surfaceView = findViewById(R.id.surface_view);
SurfaceHolder surfaceHolder = surfaceView.getHolder();

mediaPlayer.setDataSource("http://your_video_stream.mp4");
mediaPlayer.setDisplay(surfaceHolder);
mediaPlayer.prepare();
mediaPlayer.start();

在这里插入图片描述
在这里插入图片描述

layout xml

<SurfaceView
    android:id="@+id/surface_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

java

SurfaceView surfaceView = findViewById(R.id.surface_view);
SurfaceHolder surfaceHolder = surfaceView.getHolder();

C++

#include <jni.h>
#include <android/native_window_jni.h>
#include <android/native_window.h>
#include <unistd.h>

// ...

extern "C"
JNIEXPORT void JNICALL
Java_com_example_NativeVideoPlayer_playVideo(JNIEnv *env, jobject instance, jobject surface) {
    ANativeWindow *window = ANativeWindow_fromSurface(env, surface);
    ANativeWindow_setBuffersGeometry(window, 720, 480, WINDOW_FORMAT_RGBA_8888);

    while (true) {
        // Capture and decode the video stream
        // ...

        // Render the decoded video frame to the surface
        // ...

        // Sleep for a short period of time
        usleep(16000);
    }

    ANativeWindow_release(window);
}

java

public class NativeVideoPlayer {
    static {
        System.loadLibrary("native-video-player");
    }

    public native void playVideo(SurfaceHolder surfaceHolder);
}

// ...

NativeVideoPlayer player = new NativeVideoPlayer();
player.playVideo(surfaceHolder);

总结一:

整体思路是创建一个surface 然后将surface 的 surface holder 传递到 JNI。
但是没有写如何赋值给surface holder 那我们继续问。

追问:

在这里插入图片描述

C++

jobject surface = env->GetObjectField(surfaceHolder, surfaceFieldID);
// ...
ANativeWindow *nativeWindow = ANativeWindow_fromSurface(env, surface);
//...
ANativeWindow_setBuffersGeometry(nativeWindow, width, height, format);
//...
ANativeWindow_Buffer buffer;
if (ANativeWindow_lock(nativeWindow, &buffer, NULL) == 0) {
  // Assign video stream buffer to the ANativeWindow
  // ...

  ANativeWindow_unlockAndPost(nativeWindow);
}

在这里插入图片描述

C++

if (ANativeWindow_lock(nativeWindow, &buffer, NULL) == 0) {
  // Assign video stream buffer to the ANativeWindow
  uint8_t *dst = static_cast<uint8_t *>(buffer.bits);
  memcpy(dst, yuvBuffer, buffer.stride * buffer.height);

  ANativeWindow_unlockAndPost(nativeWindow);
}

总结二:

到这里基本的代码已经全部写出来了,只需要每次把图像数据写入 到 window 的buffer 中就好。
但是难免有什么不理解或者不对的地方,那我们就继续让它答疑解惑吧。

答疑解惑

首先有一个问题,就是我没有从surfaceHolder找到surface。

C++

jclass surfaceHolderClass = env->GetObjectClass(surfaceHolder);
jfieldID surfaceFieldID = env->GetFieldID(surfaceHolderClass, "mSurface", "Landroid/view/Surface;");

jobject surface = env->GetObjectField(surfaceHolder, surfaceFieldID);

在这里插入图片描述

在这里插入图片描述
然后我就去找新的接口,发现一个getSurface的接口。我自己做了下面的调整:

jmethodID getSurfaceMethodID = env->GetMethodID(surface_hoder_class, "getSurface", "()Landroid/view/Surface;");
jobject surface = env->CallObjectMethod(surface_holder, getSurfaceMethodID);
if(surface == nullptr){}

然后反问它
在这里插入图片描述
剩下的就是学习和真的答疑解惑了:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
到这里应该就结束了
.

画蛇添足 视频不显示黑屏

我其实画蛇添足还出了一个问题,ChatGPT 没帮我解决我自己找到的,后来我告诉机器人,下次遇到这样的事情,可以提醒一下其他人,看吧:
在这里插入图片描述
因为用到OpenGL 所以要加载一些依赖项。
在这里插入图片描述

最后感叹科技的更新速度,真的程序员都可能会被替代,下一个时代最大的问题应该是劳动力过剩,导致社会性结构改变,一部分人会被社会性抛弃。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/342740.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Hudi-集成 Hive

集成 Hive Hudi 源表对应一份 HDFS 数据&#xff0c;通过 Spark&#xff0c;Flink 组件或者 Hudi CLI&#xff0c;可以将 Hudi 表的数据映射为 *Hive 外部表*&#xff0c;基于该外部表&#xff0c; Hive可以方便的进行实时视图&#xff0c;读优化视图以及增量视图的查询。 集…

【软件相关】文献管理工具——Zotero

文章目录0 前期教程1 前言2 一些说明3 下载安装4 功能一&#xff1a;插入文献引用格式5 功能二&#xff1a;从网页下载文献pdf和题录6 功能三&#xff1a;数据多平台同步7 功能四&#xff1a;通过DOI添加条目及添加订阅8 安装xpi插件9 功能五&#xff1a;智能识别中英文文献10 …

The Number Of ThreadPoolExecutor

序言整理下Java 线程池中线程数量如何设置的依据巨人肩膀:https://blog.csdn.net/weilaizhixing007/article/details/125955693https://blog.csdn.net/yuyan_jia/article/details/120298564#:~:text%E4%B8%80%E4%B8%AA%E7%BA%BF%E7%A8%8B%E6%B1%A0%E5%A4%84%E7%90%86%E8%AE%A1,…

MongoDB--》文档查询的详细具体操作

目录 统计查询 分页列表查询 排序查询 正则的复杂条件查询 比较查询 包含查询 条件连接查询 统计查询 统计查询使用count()方法&#xff0c;其语法格式如下&#xff1a; db.collection.count(query,options) ParameterTypeDescriptionquerydocument查询选择条件optio…

int和Integer有什么区别?

第7讲 | int和Integer有什么区别&#xff1f; Java 虽然号称是面向对象的语言&#xff0c;但是原始数据类型仍然是重要的组成元素&#xff0c;所以在面试中&#xff0c;经常考察原始数据类型和包装类等 Java 语言特性。 今天我要问你的问题是&#xff0c;int 和 Integer 有什么…

JUC并发编程 Ⅱ -- 共享模型之管程(下)

文章目录wait notifywait / notify的原理API 介绍sleep与wait辨析优雅地使用wait/notify保护性暂停模式超时版 GuardedObjectjoin原理多任务版GuardedObject生产者-消费者模式定义实现Park & Unpark基本使用特点原理重新理解线程状态转换线程的活跃性死锁定位死锁活锁饥饿R…

vs2019 winform安装包,安装完成后默认启动

vs2019 winform安装包&#xff0c;安装完成后默认启动在要打包的项目中&#xff0c;新建安装类选中打包项目&#xff0c;右键&#xff0c;进入文件系统![在这里插入图片描述](https://img-blog.csdnimg.cn/62647c550ffa4d489f1d19f19bbd99b1.png)选中application folder 右键&a…

java微信小程序校园二手闲置商品交易跳蚤市场

基于跳蚤市场小程序的设计基于现有的手机,可以实现个人中心、用户管理、卖家管理、商品类型管理、商品信息管理、购物车管理、私聊信息管理、聊天回复管理、留言板管理、我的收藏管理、系统管理等功能。方便用户对商品信息等详细的了解及统计分析。根据系统功能需求建立的模块关…

后量子 KEM 方案:Kyber

参考文献&#xff1a; Bos J, Ducas L, Kiltz E, et al. CRYSTALS-Kyber: a CCA-secure module-lattice-based KEM[C]//2018 IEEE European Symposium on Security and Privacy (EuroS&P). IEEE, 2018: 353-367.Avanzi R, Bos J, Ducas L, et al. Crystals-kyber[J]. NIST…

AlphaFold 2 处理蛋白质折叠问题

蛋白质是一个较长的氨基酸序列&#xff0c;比如100个氨基酸的规模&#xff0c;如此长的氨基酸序列连在一起是不稳定的&#xff0c;它们会卷在一起&#xff0c;形成一个独特的3D结构&#xff0c;这个3D结构的形状决定了蛋白质的功能。 蛋白质结构预测&#xff08;蛋白质折叠问题…

Android 一体机研发之修改系统设置————屏幕亮度

Android 一体机研发之修改系统设置————屏幕亮度 Android 一体机研发之修改系统设置————声音 Android 一体机研发之修改系统设置————自动锁屏 前言 最近工作略微有点儿空闲&#xff0c;抽空给大家总结一下&#xff1a;近期一直搞得一体机app研发&#xff0c;适用…

recv和明文收包分析

我们CTRLg 跳到recv 分析收包函数 发现函数会断并且收包函数返回值(收包包长)也会不断变化 那么证明recv是真正的收包函数&#xff0c;游戏没有重新实现该函数 我们只要分析该函数即可 在recv函数执行完毕以后下断 eax是包长,esi28是包指针 我们上2个号&#xff0c;让另外…

项目(今日指数之环境搭建)

一 项目架构1.1 今日指数技术选型【1】前端技术【2】后端技术栈【3】整体概览1.2 核心业务介绍【1】业务结构预览【2】业务结构预览1.定时任务调度服务XXL-JOB通过RestTemplate多线程动态拉去股票接口数据&#xff0c;刷入数据库&#xff1b; 2.国内指数服务 3.板块指数服务 4.…

清晰理解并解决二分问题

文章目录二分问题常规解法&#xff1a;使用CSTL自带算法解决二分问题&#xff1a;小数二分二分问题常规解法&#xff1a; 二分问题注意事项&#xff1a; 题目可能无解&#xff0c;但二分一定有解&#xff08;也就是二分问题会得到一个结果&#xff0c;但是该结果可能不符合题目…

RabbitMQ-集群

一、搭建1、创建三个虚拟机2、修改三台主机的hostname,分别为node1,node2,node3,分别重启vi /etc/hostname reboot3、配置各个主机的hosts文件&#xff0c;让各个节点都能互相识别对方vi /etc/hosts #添加下面配置 192.168.xxx.165 node1 192.168.xxx.167 node2 192.168.xxx.16…

Django by Example·第三章|Extending Your Blog Application@笔记

Django by Example第三章|Extending Your Blog Application笔记 之前已经写过两章内容了&#xff0c;继续第三章。第三章继续对博客系统的功能进行拓展&#xff0c;其中将会穿插一些重要的技术要点。 部分内容引用自原书&#xff0c;如果大家对这本书感兴趣 请支持原版Django …

基于模块联邦的微前端实现方案

一、 微前端应用案例概述 当前案例中包含三个微应用&#xff0c;分别为 Marketing、Authentication 和 Dashboard Marketing&#xff1a;营销微应用&#xff0c;包含首页组件和价格组件 Authentication&#xff1a;身份验证微应用&#xff0c;包含登录组件 Dashboard&#x…

B站发帖软件哪个好用?好用的哔哩哔哩发帖工具

B站发帖软件哪个好用?好用的哔哩哔哩发帖工具#发帖软件#哔哩哔哩发帖#视频发布软件 登录成功之后&#xff0c;进入到这样一个界面&#xff0c;默认情况下是这个样子的&#xff0c;我们在这里输入一下我们的一个文件夹的路径&#xff0c;输入到这里&#xff0c;点击添加账号&a…

kettle开发-Day36-循环驱动作业

前言&#xff1a;在日常数据处理时&#xff0c;我们通过变量传参来完成某个日期的数据转换。但可能因程序或者网络原因导致某个时间段的数据抽取失败。常见导致kettle作业失败的原因大概分为三大类&#xff0c;数据源异常、数据库异常、程序异常。因此面对这些异常时&#xff0…

Not available OpenAI s services are not available in your country.

一、准备阶段 1、邮箱账号(qq、网易、谷歌等等) 2、你能够科学上网(下边详细介绍) 3、拥有一个GW手机号&#xff0c;用于接收注册验证码。&#xff08;下边详细介绍&#xff09; 二、开始注册 1、官方注册网址https://beta.openai.com/signup&#xff08;按照步骤注册&am…