//
// Copyright (c) APX Labs, Inc. All rights reserved.
//
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Many thanks to Jonathan Pryor from Xamarin for his assistance
using System;
using Android.Hardware;
using Android.Runtime;
namespace ApxLabs.FastAndroidCamera
{
///
/// Extends the class with methods that take
/// instances as parameters instead of raw values.
///
public static class CameraExtensions
{
static IntPtr id_addCallbackBuffer_arrayB;
///
/// Adds a pre-allocated buffer to the preview callback buffer queue. Applications can add one or more buffers
/// to the queue. When a preview frame arrives and there is still at least one available buffer, the buffer will
/// be used and removed from the queue. Then preview callback is invoked with the buffer. If a frame arrives and
/// there is no buffer left, the frame is discarded. Applications should add buffers back when they finish
/// processing the data in them.
///
/// Camera object.
/// The buffer to add to the queue.
public static void AddCallbackBuffer(this Camera self, FastJavaByteArray callbackBuffer)
{
if (id_addCallbackBuffer_arrayB == IntPtr.Zero)
id_addCallbackBuffer_arrayB = JNIEnv.GetMethodID(self.Class.Handle, "addCallbackBuffer", "([B)V");
JNIEnv.CallVoidMethod(self.Handle, id_addCallbackBuffer_arrayB, new JValue(callbackBuffer.Handle));
}
static IntPtr id_setPreviewCallback_Landroid_hardware_Camera_PreviewCallback_;
///
/// Installs a callback to be invoked for every preview frame in addition to displaying them on the screen. The
/// callback will provide a reference to the Java array instead of copying it into a new CLR array. The callback
/// will be repeatedly called for as long as preview is active. This method can be called at any time,
/// even while preview is live. Any other preview callbacks are overridden.
///
/// Camera object.
/// A callback object that receives a copy of each preview frame, or null to stop receiving callbacks.
public static void SetNonMarshalingPreviewCallback(this Camera self, INonMarshalingPreviewCallback cb)
{
if (id_setPreviewCallback_Landroid_hardware_Camera_PreviewCallback_ == IntPtr.Zero)
id_setPreviewCallback_Landroid_hardware_Camera_PreviewCallback_ = JNIEnv.GetMethodID(self.Class.Handle, "setPreviewCallbackWithBuffer", "(Landroid/hardware/Camera$PreviewCallback;)V");
JNIEnv.CallVoidMethod(self.Handle, id_setPreviewCallback_Landroid_hardware_Camera_PreviewCallback_, new JValue(cb));
}
static IntPtr id_setOneShotPreviewCallback_Landroid_hardware_Camera_PreviewCallback_;
///
///
/// Installs a callback to be invoked for every preview frame, using buffers supplied with
/// (FastJavaByteArray), in addition to displaying them on the screen. The
/// callback will be repeatedly called for as long as preview is active and buffers are available. Any other
/// preview callbacks are overridden.
///
///
/// The purpose of this method is to improve preview efficiency and frame rate by allowing preview frame memory
/// reuse.You must call (FastJavaByteArray) at some point -- before or after
/// calling this method -- or no callbacks will received.
///
///
/// The buffer queue will be cleared if this method is called with a null callback, or if
/// (Camera.PreviewCallback),
/// (INonMarshalingPreviewCallback),
/// (Camera.PreviewCallback), or
/// is called.
///
///
/// Camera object.
/// A callback object that receives a copy of the preview frame, or null to stop receiving callbacks and clear the buffer queue.
public static void SetNonMarshalingOneShotPreviewCallback(this Camera self, INonMarshalingPreviewCallback cb)
{
if (id_setOneShotPreviewCallback_Landroid_hardware_Camera_PreviewCallback_ == IntPtr.Zero)
id_setOneShotPreviewCallback_Landroid_hardware_Camera_PreviewCallback_ = JNIEnv.GetMethodID(self.Class.Handle, "setOneShotPreviewCallback", "(Landroid/hardware/Camera$PreviewCallback;)V");
JNIEnv.CallVoidMethod(self.Handle, id_setOneShotPreviewCallback_Landroid_hardware_Camera_PreviewCallback_, new JValue(cb));
}
}
///
/// Callback interface used to deliver references to Java arrays containing preview frames as they are displayed.
///
// Metadata.xml XPath interface reference: path="/api/package[@name='android.hardware']/interface[@name='Camera.PreviewCallback']"
[Register("android/hardware/Camera$PreviewCallback", "", "ApxLabs.FastAndroidCamera.INonMarshalingPreviewCallbackInvoker")]
public interface INonMarshalingPreviewCallback : IJavaObject
{
///
/// Called as preview frames are displayed. This callback is invoked on the event thread was called from.
///
///
/// The contents of the preview frame in the format defined by , which
/// can be queried with . If
/// is never set, the default will be the YCbCr_420_SP (NV21) format.
///
/// The Camera service object.
// Metadata.xml XPath method reference: path="/api/package[@name='android.hardware']/interface[@name='Camera.PreviewCallback']/method[@name='onPreviewFrame' and count(parameter)=2 and parameter[1][@type='byte[]'] and parameter[2][@type='android.hardware.Camera']]"
[Register("onPreviewFrame", "([BLandroid/hardware/Camera;)V", "GetOnPreviewFrame_arrayBLandroid_hardware_Camera_Handler:ApxLabs.FastAndroidCamera.INonMarshalingPreviewCallbackInvoker, FastAndroidCamera, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")]
void OnPreviewFrame(IntPtr data, Camera camera);
}
[Register("android/hardware/Camera$PreviewCallback", DoNotGenerateAcw = true)]
internal class INonMarshalingPreviewCallbackInvoker : Java.Lang.Object, INonMarshalingPreviewCallback
{
static IntPtr java_class_ref = JNIEnv.FindClass("android/hardware/Camera$PreviewCallback");
IntPtr class_ref;
public static INonMarshalingPreviewCallback GetObject(IntPtr handle, JniHandleOwnership transfer)
{
return GetObject(handle, transfer);
}
static IntPtr Validate(IntPtr handle)
{
if (!JNIEnv.IsInstanceOf(handle, java_class_ref))
throw new InvalidCastException(string.Format("Unable to convert instance of type '{0}' to type '{1}'.",
JNIEnv.GetClassNameFromInstance(handle), "android.hardware.Camera.PreviewCallback"));
return handle;
}
protected override void Dispose(bool disposing)
{
if (class_ref != IntPtr.Zero)
JNIEnv.DeleteGlobalRef(class_ref);
class_ref = IntPtr.Zero;
base.Dispose(disposing);
}
public INonMarshalingPreviewCallbackInvoker(IntPtr handle, JniHandleOwnership transfer)
: base(Validate(handle), transfer)
{
IntPtr local_ref = JNIEnv.GetObjectClass(Handle);
class_ref = JNIEnv.NewGlobalRef(local_ref);
JNIEnv.DeleteLocalRef(local_ref);
}
protected override IntPtr ThresholdClass
{
get { return class_ref; }
}
protected override Type ThresholdType
{
get { return typeof(INonMarshalingPreviewCallbackInvoker); }
}
static Delegate cb_onPreviewFrame_arrayBLandroid_hardware_Camera_;
#pragma warning disable 0169
static Delegate GetOnPreviewFrame_arrayBLandroid_hardware_Camera_Handler()
{
if (cb_onPreviewFrame_arrayBLandroid_hardware_Camera_ == null)
cb_onPreviewFrame_arrayBLandroid_hardware_Camera_ = JNINativeWrapper.CreateDelegate((Action)n_OnPreviewFrame_arrayBLandroid_hardware_Camera_);
return cb_onPreviewFrame_arrayBLandroid_hardware_Camera_;
}
static void n_OnPreviewFrame_arrayBLandroid_hardware_Camera_(IntPtr jnienv, IntPtr native__this, IntPtr native_data, IntPtr native_camera)
{
INonMarshalingPreviewCallback __this = GetObject(native__this, JniHandleOwnership.DoNotTransfer);
Camera camera = GetObject(native_camera, JniHandleOwnership.DoNotTransfer);
__this.OnPreviewFrame(native_data, camera);
}
#pragma warning restore 0169
IntPtr id_onPreviewFrame_arrayBLandroid_hardware_Camera_;
public void OnPreviewFrame(IntPtr data, Camera camera)
{
if (id_onPreviewFrame_arrayBLandroid_hardware_Camera_ == IntPtr.Zero)
id_onPreviewFrame_arrayBLandroid_hardware_Camera_ = JNIEnv.GetMethodID(class_ref, "onPreviewFrame", "([BLandroid/hardware/Camera;)V");
JNIEnv.CallVoidMethod(Handle, id_onPreviewFrame_arrayBLandroid_hardware_Camera_, new JValue(data), new JValue(camera));
}
}
}