mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
Bug 1296744 - Make cameraCallbackBridge use new native JNI bindings; r=snorp
Make the GeckoAppShell.cameraCallbackBridge callback use the new native JNI bindings. Also refactor the relevant code in GeckoAppShell and CameraStreamImpl.
This commit is contained in:
parent
d924b1c615
commit
ab92abb418
@ -70,6 +70,7 @@ import android.graphics.RectF;
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.hardware.Camera;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
@ -1826,13 +1827,30 @@ public class GeckoAppShell
|
||||
sGeckoInterface = aGeckoInterface;
|
||||
}
|
||||
|
||||
public static android.hardware.Camera sCamera;
|
||||
/* package */ static Camera sCamera;
|
||||
|
||||
static native void cameraCallbackBridge(byte[] data);
|
||||
private static final int kPreferredFPS = 25;
|
||||
private static byte[] sCameraBuffer;
|
||||
|
||||
static final int kPreferredFPS = 25;
|
||||
static byte[] sCameraBuffer;
|
||||
private static class CameraCallback implements Camera.PreviewCallback {
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private static native void onFrameData(int camera, byte[] data);
|
||||
|
||||
private final int mCamera;
|
||||
|
||||
public CameraCallback(int camera) {
|
||||
mCamera = camera;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPreviewFrame(byte[] data, Camera camera) {
|
||||
onFrameData(mCamera, data);
|
||||
|
||||
if (sCamera != null) {
|
||||
sCamera.addCallbackBuffer(sCameraBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
static int[] initCamera(String aContentType, int aCamera, int aWidth, int aHeight) {
|
||||
@ -1853,14 +1871,14 @@ public class GeckoAppShell
|
||||
int[] result = new int[4];
|
||||
result[0] = 0;
|
||||
|
||||
if (android.hardware.Camera.getNumberOfCameras() == 0) {
|
||||
if (Camera.getNumberOfCameras() == 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
try {
|
||||
sCamera = android.hardware.Camera.open(aCamera);
|
||||
sCamera = Camera.open(aCamera);
|
||||
|
||||
android.hardware.Camera.Parameters params = sCamera.getParameters();
|
||||
Camera.Parameters params = sCamera.getParameters();
|
||||
params.setPreviewFormat(ImageFormat.NV21);
|
||||
|
||||
// use the preview fps closest to 25 fps.
|
||||
@ -1879,11 +1897,11 @@ public class GeckoAppShell
|
||||
}
|
||||
|
||||
// set up the closest preview size available
|
||||
Iterator<android.hardware.Camera.Size> sit = params.getSupportedPreviewSizes().iterator();
|
||||
Iterator<Camera.Size> sit = params.getSupportedPreviewSizes().iterator();
|
||||
int sizeDelta = 10000000;
|
||||
int bufferSize = 0;
|
||||
while (sit.hasNext()) {
|
||||
android.hardware.Camera.Size size = sit.next();
|
||||
Camera.Size size = sit.next();
|
||||
if (Math.abs(size.width * size.height - aWidth * aHeight) < sizeDelta) {
|
||||
sizeDelta = Math.abs(size.width * size.height - aWidth * aHeight);
|
||||
params.setPreviewSize(size.width, size.height);
|
||||
@ -1907,14 +1925,7 @@ public class GeckoAppShell
|
||||
sCamera.setParameters(params);
|
||||
sCameraBuffer = new byte[(bufferSize * 12) / 8];
|
||||
sCamera.addCallbackBuffer(sCameraBuffer);
|
||||
sCamera.setPreviewCallbackWithBuffer(new android.hardware.Camera.PreviewCallback() {
|
||||
@Override
|
||||
public void onPreviewFrame(byte[] data, android.hardware.Camera camera) {
|
||||
cameraCallbackBridge(data);
|
||||
if (sCamera != null)
|
||||
sCamera.addCallbackBuffer(sCameraBuffer);
|
||||
}
|
||||
});
|
||||
sCamera.setPreviewCallbackWithBuffer(new CameraCallback(aCamera));
|
||||
sCamera.startPreview();
|
||||
params = sCamera.getParameters();
|
||||
result[0] = 1;
|
||||
|
@ -3,26 +3,12 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "CameraStreamImpl.h"
|
||||
#include "GeneratedJNINatives.h"
|
||||
#include "nsCRTGlue.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "mozilla/Monitor.h"
|
||||
|
||||
/**
|
||||
* JNI part & helper runnable
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_cameraCallbackBridge(JNIEnv *, jclass, jbyteArray data);
|
||||
}
|
||||
|
||||
NS_EXPORT void JNICALL
|
||||
Java_org_mozilla_gecko_GeckoAppShell_cameraCallbackBridge(JNIEnv *env, jclass, jbyteArray data) {
|
||||
mozilla::net::CameraStreamImpl* impl = mozilla::net::CameraStreamImpl::GetInstance(0);
|
||||
|
||||
impl->transmitFrame(env, &data);
|
||||
}
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
namespace mozilla {
|
||||
@ -31,20 +17,40 @@ namespace net {
|
||||
static CameraStreamImpl* mCamera0 = nullptr;
|
||||
static CameraStreamImpl* mCamera1 = nullptr;
|
||||
|
||||
class CameraStreamImpl::Callback
|
||||
: public java::GeckoAppShell::CameraCallback::Natives<Callback>
|
||||
{
|
||||
public:
|
||||
static void OnFrameData(int32_t aCamera, jni::ByteArray::Param aData)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
CameraStreamImpl* impl = GetInstance(uint32_t(aCamera));
|
||||
if (impl) {
|
||||
impl->TransmitFrame(aData);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* CameraStreamImpl
|
||||
*/
|
||||
|
||||
void CameraStreamImpl::transmitFrame(JNIEnv *env, jbyteArray *data) {
|
||||
if (!mCallback)
|
||||
return;
|
||||
jboolean isCopy;
|
||||
jbyte* jFrame = env->GetByteArrayElements(*data, &isCopy);
|
||||
uint32_t length = env->GetArrayLength(*data);
|
||||
if (length > 0) {
|
||||
mCallback->ReceiveFrame((char*)jFrame, length);
|
||||
void CameraStreamImpl::TransmitFrame(jni::ByteArray::Param aData) {
|
||||
if (!mCallback) {
|
||||
return;
|
||||
}
|
||||
env->ReleaseByteArrayElements(*data, jFrame, 0);
|
||||
|
||||
JNIEnv* const env = jni::GetGeckoThreadEnv();
|
||||
const size_t length = size_t(env->GetArrayLength(aData.Get()));
|
||||
|
||||
if (!length) {
|
||||
return;
|
||||
}
|
||||
|
||||
jbyte* const data = env->GetByteArrayElements(aData.Get(), nullptr);
|
||||
mCallback->ReceiveFrame(reinterpret_cast<char*>(data), length);
|
||||
env->ReleaseByteArrayElements(aData.Get(), data, JNI_ABORT);
|
||||
}
|
||||
|
||||
CameraStreamImpl* CameraStreamImpl::GetInstance(uint32_t aCamera) {
|
||||
@ -86,7 +92,17 @@ bool CameraStreamImpl::Init(const nsCString& contentType, const uint32_t& camera
|
||||
mCallback = aCallback;
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
return AndroidBridge::Bridge()->InitCamera(contentType, camera, &mWidth, &mHeight, &mFps);
|
||||
|
||||
Callback::Init();
|
||||
jni::IntArray::LocalRef retArray = java::GeckoAppShell::InitCamera(
|
||||
contentType, int32_t(camera), int32_t(width), int32_t(height));
|
||||
nsTArray<int32_t> ret = retArray->GetElements();
|
||||
|
||||
mWidth = uint32_t(ret[1]);
|
||||
mHeight = uint32_t(ret[2]);
|
||||
mFps = uint32_t(ret[3]);
|
||||
|
||||
return !!ret[0];
|
||||
}
|
||||
|
||||
void CameraStreamImpl::Close() {
|
||||
|
@ -5,8 +5,9 @@
|
||||
#ifndef __CAMERASTREAMIMPL_H__
|
||||
#define __CAMERASTREAMIMPL_H__
|
||||
|
||||
#include "mozilla/jni/Refs.h"
|
||||
|
||||
#include "nsString.h"
|
||||
#include "AndroidBridge.h"
|
||||
|
||||
/**
|
||||
* This singleton class handles communication with the Android camera
|
||||
@ -15,45 +16,47 @@
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
|
||||
class CameraStreamImpl {
|
||||
public:
|
||||
class FrameCallback {
|
||||
public:
|
||||
virtual void ReceiveFrame(char* frame, uint32_t length) = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* instance bound to a given camera
|
||||
*/
|
||||
static CameraStreamImpl* GetInstance(uint32_t aCamera);
|
||||
|
||||
|
||||
bool initNeeded() {
|
||||
return !mInit;
|
||||
}
|
||||
|
||||
|
||||
FrameCallback* GetFrameCallback() {
|
||||
return mCallback;
|
||||
}
|
||||
|
||||
|
||||
bool Init(const nsCString& contentType, const uint32_t& camera, const uint32_t& width, const uint32_t& height, FrameCallback* callback);
|
||||
void Close();
|
||||
|
||||
|
||||
uint32_t GetWidth() { return mWidth; }
|
||||
uint32_t GetHeight() { return mHeight; }
|
||||
uint32_t GetFps() { return mFps; }
|
||||
|
||||
|
||||
void takePicture(const nsAString& aFileName);
|
||||
|
||||
void transmitFrame(JNIEnv *env, jbyteArray *data);
|
||||
|
||||
|
||||
private:
|
||||
class Callback;
|
||||
|
||||
CameraStreamImpl(uint32_t aCamera);
|
||||
CameraStreamImpl(const CameraStreamImpl&);
|
||||
CameraStreamImpl& operator=(const CameraStreamImpl&);
|
||||
|
||||
~CameraStreamImpl();
|
||||
|
||||
void TransmitFrame(jni::ByteArray::Param aData);
|
||||
|
||||
bool mInit;
|
||||
uint32_t mCamera;
|
||||
uint32_t mWidth;
|
||||
|
@ -682,29 +682,6 @@ namespace mozilla {
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
AndroidBridge::InitCamera(const nsCString& contentType, uint32_t camera, uint32_t *width, uint32_t *height, uint32_t *fps)
|
||||
{
|
||||
auto arr = GeckoAppShell::InitCamera
|
||||
(NS_ConvertUTF8toUTF16(contentType), (int32_t) camera, (int32_t) *width, (int32_t) *height);
|
||||
|
||||
if (!arr)
|
||||
return false;
|
||||
|
||||
JNIEnv* const env = arr.Env();
|
||||
jint *elements = env->GetIntArrayElements(arr.Get(), 0);
|
||||
|
||||
*width = elements[1];
|
||||
*height = elements[2];
|
||||
*fps = elements[3];
|
||||
|
||||
bool res = elements[0] == 1;
|
||||
|
||||
env->ReleaseIntArrayElements(arr.Get(), elements, 0);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
AndroidBridge::GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInfo)
|
||||
{
|
||||
|
@ -192,8 +192,6 @@ public:
|
||||
|
||||
void HandleGeckoMessage(JSContext* cx, JS::HandleObject message);
|
||||
|
||||
bool InitCamera(const nsCString& contentType, uint32_t camera, uint32_t *width, uint32_t *height, uint32_t *fps);
|
||||
|
||||
void GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInfo);
|
||||
|
||||
nsresult GetSegmentInfoForText(const nsAString& aText,
|
||||
|
Loading…
Reference in New Issue
Block a user