问题
I'm trying to make a Screenshot App using NDK rather than Java (Think of it as some experimentation, I know java code is much simpler, but im thinking of doing it via NDK).
So, I've implemented the code in Java side as follows...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mediaProjectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);
if (mediaProjectionManager != null)
startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(),
420);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
SurfaceTexture surfaceTexture = new SurfaceTexture(420);
Surface mSurface = new Surface(surfaceTexture);
if (requestCode == 420) {
if (resultCode == RESULT_OK) {
MediaProjection mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, data);
VirtualDisplay virtualDisplay = mediaProjection.createVirtualDisplay("MainActivity", 1080, 1920, 100,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
mSurface,
null, null);
init(mSurface);
}
}
}
private native void init(Surface surface); //native call
static {
System.loadLibrary("native-lib");
}
And here is the native code...
#include <ctime>
#include <filesystem>
#include "media/NdkImageReader.h"
#include "media/NdkImage.h"
#include "android/native_window_jni.h"
#include "log.h"
#include "renderer.h"
#define TAG "JNI"
void onImageAvailableCallback(void *context, AImageReader *reader);
void work(JNIEnv* env, jobject surface){
ANativeWindow *nativeWindow = ANativeWindow_fromSurface(env, surface);
ANativeWindow_acquire(nativeWindow);
AImageReader *imageReader;
media_status_t status = AImageReader_new(1080, 1920, AIMAGE_FORMAT_YUV_420_888, 4,
&imageReader);
if (status == AMEDIA_OK) {
LOGD(TAG, "ImageReader successfully initialized!");
if (nativeWindow != NULL) {
LOGD(TAG, "Surface is not null! Continuing...");
status = AImageReader_getWindow(imageReader, &nativeWindow);
if (status == AMEDIA_OK) {
LOGD(TAG, "ImageReader acquired window!");
AImageReader_ImageListener imageListener{
.context = nullptr,
.onImageAvailable = &onImageAvailableCallback
};
AImageReader_setImageListener(imageReader, &imageListener);
} else return;
} else {
LOGD(TAG, "Surface is null, Aborting...");
return;
}
}
}
extern "C" JNIEXPORT void JNICALL
Java_com_test_fps_MainActivity_init( JNIEnv* env,
jobject thiz,
jobject surface) {
LOGD(TAG, "INIT");
work(env, surface);
}
void onImageAvailableCallback(void *context, AImageReader *reader)
{
LOGD(TAG, "Frame Available");
}
and here is the logcat...
2019-06-10 09:54:43.663 8258-8258/com.test.fps W/com.test.fps: JIT profile information will not be recorded: profile file does not exits.
2019-06-10 09:54:43.665 8258-8258/com.test.fps I/chatty: uid=10234(com.test.fps) identical 10 lines
2019-06-10 09:54:43.665 8258-8258/com.test.fps W/com.test.fps: JIT profile information will not be recorded: profile file does not exits.
2019-06-10 09:54:43.688 8258-8258/com.test.fps I/InstantRun: starting instant run server: is main process
2019-06-10 09:54:43.816 8258-8258/com.test.fps W/com.test.fps: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (light greylist, reflection)
2019-06-10 09:54:43.817 8258-8258/com.test.fps W/com.test.fps: Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (light greylist, reflection)
2019-06-10 09:54:43.828 8258-8258/com.test.fps D/OpenGLRenderer: Skia GL Pipeline
2019-06-10 09:54:43.953 8258-8280/com.test.fps I/Adreno: QUALCOMM build : 791494e, Id7006ec082
Build Date : 12/09/18
OpenGL ES Shader Compiler Version: EV031.24.02.00
Local Branch :
Remote Branch : refs/tags/AU_LINUX_ANDROID_LA.UM.7.3.R1.09.00.00.423.045
Remote Branch : NONE
Reconstruct Branch : NOTHING
2019-06-10 09:54:43.953 8258-8280/com.test.fps I/Adreno: Build Config : S P 6.0.7 AArch64
2019-06-10 09:54:43.957 8258-8280/com.test.fps I/Adreno: PFP: 0x016ee180, ME: 0x00000000
2019-06-10 09:54:43.964 8258-8280/com.test.fps I/ConfigStore: android::hardware::configstore::V1_0::ISurfaceFlingerConfigs::hasWideColorDisplay retrieved: 0
2019-06-10 09:54:43.964 8258-8280/com.test.fps I/ConfigStore: android::hardware::configstore::V1_0::ISurfaceFlingerConfigs::hasHDRDisplay retrieved: 0
2019-06-10 09:54:43.964 8258-8280/com.test.fps I/OpenGLRenderer: Initialized EGL, version 1.4
2019-06-10 09:54:43.964 8258-8280/com.test.fps D/OpenGLRenderer: Swap behavior 2
2019-06-10 09:54:44.064 8258-8258/com.test.fps D/JNI: INIT
2019-06-10 09:54:44.065 8258-8258/com.test.fps D/JNI: ImageReader successfully initialized!
2019-06-10 09:54:44.065 8258-8258/com.test.fps D/JNI: Surface is not null! Continuing...
2019-06-10 09:54:44.065 8258-8258/com.test.fps D/JNI: ImageReader acquired window!
2019-06-10 09:54:46.592 8258-8272/com.test.fps I/Gralloc2: Adding additional valid usage bits: 0x8200000
I have tried using the Image Reader in Java and it works fine but not in NDK.
Am I missing something?
回答1:
I think you have mistake in your code:
ANativeWindow *nativeWindow = ANativeWindow_fromSurface(env, surface);
...
status = AImageReader_getWindow(imageReader, &nativeWindow);
In the function "AImageReader_getWindow"
media_status_t AImageReader_getWindow(AImageReader* reader, /*out*/ANativeWindow** window) __INTRODUCED_IN(24);
the window parameter is not in, is out. and your AImageReader is not connected to the java surface.
NOTE
Maybe if you can convert your ANativeWindow (from AImageReader) to surface and use it in java, it's will work.
来源:https://stackoverflow.com/questions/56520729/aimagereaders-onimageavailablecallback-is-not-being-called