背景
相机拍摄的画面通过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){}
然后反问它
剩下的就是学习和真的答疑解惑了:
到这里应该就结束了
.文章来源:https://www.toymoban.com/news/detail-425299.html
画蛇添足 视频不显示黑屏
我其实画蛇添足还出了一个问题,ChatGPT 没帮我解决我自己找到的,后来我告诉机器人,下次遇到这样的事情,可以提醒一下其他人,看吧:
因为用到OpenGL 所以要加载一些依赖项。
文章来源地址https://www.toymoban.com/news/detail-425299.html
最后感叹科技的更新速度,真的程序员都可能会被替代,下一个时代最大的问题应该是劳动力过剩,导致社会性结构改变,一部分人会被社会性抛弃。
到了这里,关于[chatGPT] 如何通过JNI在Android上显示实时视频流的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!