Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 69441650 authored by Igor Murashkin's avatar Igor Murashkin Committed by Android (Google) Code Review
Browse files

Merge "camera2 api: marshal rect, size, string for metadata"

parents c9cc2d0d 3710db80
Loading
Loading
Loading
Loading
+84 −7
Original line number Diff line number Diff line
@@ -16,6 +16,10 @@

package android.hardware.photography;

import android.hardware.photography.impl.MetadataMarshalClass;
import android.hardware.photography.impl.MetadataMarshalRect;
import android.hardware.photography.impl.MetadataMarshalSize;
import android.hardware.photography.impl.MetadataMarshalString;
import android.os.Parcelable;
import android.os.Parcel;
import android.util.Log;
@@ -85,6 +89,11 @@ public class CameraMetadata implements Parcelable, AutoCloseable {
    public <T> void set(Key<T> key, T value) {
        int tag = key.getTag();

        if (value == null) {
            writeValues(tag, null);
            return;
        }

        int nativeType = getNativeType(tag);

        int size = packSingle(value, null, key.mType, nativeType, /* sizeOnly */true);
@@ -265,6 +274,11 @@ public class CameraMetadata implements Parcelable, AutoCloseable {
    private static <T> int packClass(T value, ByteBuffer buffer, Class<T> type, int nativeType,
            boolean sizeOnly) {

        MetadataMarshalClass<T> marshaler = getMarshaler(type, nativeType);
        if (marshaler != null) {
            return marshaler.marshal(value, buffer, nativeType, sizeOnly);
        }

        /**
         * FIXME: This doesn't actually work because getFields() returns fields in an unordered
         * manner. Although we could sort and get the data to come out correctly on the *java* side,
@@ -558,6 +572,11 @@ public class CameraMetadata implements Parcelable, AutoCloseable {

    private static <T> T unpackClass(ByteBuffer buffer, Class<T> type, int nativeType) {

        MetadataMarshalClass<T> marshaler = getMarshaler(type, nativeType);
        if (marshaler != null) {
            return marshaler.unmarshal(buffer, nativeType);
        }

        /**
         * FIXME: This doesn't actually work because getFields() returns fields in an unordered
         * manner. Although we could sort and get the data to come out correctly on the *java* side,
@@ -611,15 +630,45 @@ public class CameraMetadata implements Parcelable, AutoCloseable {
        Class<?> componentType = type.getComponentType();
        Object array;

        int elementSize = getTypeSize(nativeType);

        MetadataMarshalClass<?> marshaler = getMarshaler(componentType, nativeType);
        if (marshaler != null) {
            elementSize = marshaler.getNativeSize(nativeType);
        }

        if (elementSize != MetadataMarshalClass.NATIVE_SIZE_DYNAMIC) {
            int remaining = buffer.remaining();
        // FIXME: Assumes that the rest of the ByteBuffer is part of the array.
        int arraySize = remaining / getTypeSize(nativeType);
            int arraySize = remaining / elementSize;

            Log.v(TAG,
                    String.format(
                            "Attempting to unpack array (count = %d, element size = %d, bytes " +
                                    "remaining = %d) for type %s",
                            arraySize, elementSize, remaining, type));

            array = Array.newInstance(componentType, arraySize);
            for (int i = 0; i < arraySize; ++i) {
               Object elem = unpackSingle(buffer, componentType, nativeType);
               Array.set(array, i, elem);
            }
        } else {
            // Dynamic size, use an array list.
            ArrayList<Object> arrayList = new ArrayList<Object>();

            int primitiveSize = getTypeSize(nativeType);
            while (buffer.remaining() >= primitiveSize) {
                Object elem = unpackSingle(buffer, componentType, nativeType);
                arrayList.add(elem);
            }

            array = arrayList.toArray((T[]) Array.newInstance(componentType, 0));
        }

        if (buffer.remaining() != 0) {
            Log.e(TAG, "Trailing bytes (" + buffer.remaining() + ") left over after unpacking "
                    + type);
        }

        return (T) array;
    }
@@ -927,11 +976,39 @@ public class CameraMetadata implements Parcelable, AutoCloseable {
        return values[ordinal];
    }

    static HashMap<Class<?>, MetadataMarshalClass<?>> sMarshalerMap = new
            HashMap<Class<?>, MetadataMarshalClass<?>>();

    private static <T> void registerMarshaler(MetadataMarshalClass<T> marshaler) {
        sMarshalerMap.put(marshaler.getMarshalingClass(), marshaler);
    }

    @SuppressWarnings("unchecked")
    private static <T> MetadataMarshalClass<T> getMarshaler(Class<T> type, int nativeType) {
        MetadataMarshalClass<T> marshaler = (MetadataMarshalClass<T>) sMarshalerMap.get(type);

        if (marshaler != null && !marshaler.isNativeTypeSupported(nativeType)) {
            throw new UnsupportedOperationException("Unsupported type " + nativeType +
                    " to be marshalled to/from a " + type);
        }

        return marshaler;
    }

    /**
     * We use a class initializer to allow the native code to cache some field offsets
     */
    static {
        System.loadLibrary("media_jni");
        nativeClassInit();

        Log.v(TAG, "Shall register metadata marshalers");

        // load built-in marshallers
        registerMarshaler(new MetadataMarshalRect());
        registerMarshaler(new MetadataMarshalSize());
        registerMarshaler(new MetadataMarshalString());

        Log.v(TAG, "Registered metadata marshalers");
    }
}
+67 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * 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.
 */

package android.hardware.photography.impl;

import java.nio.ByteBuffer;

public interface MetadataMarshalClass<T> {

    /**
     * Marshal the specified object instance (value) into a byte buffer.
     *
     * @param value the value of type T that we wish to write into the byte buffer
     * @param buffer the byte buffer into which the marshalled object will be written
     * @param nativeType the native type, e.g.
     *        {@link android.hardware.photography.CameraMetadata#TYPE_BYTE TYPE_BYTE}.
     *        Guaranteed to be one for which isNativeTypeSupported returns true.
     * @param sizeOnly if this is true, don't write to the byte buffer. calculate the size only.
     * @return the size that needs to be written to the byte buffer
     */
    int marshal(T value, ByteBuffer buffer, int nativeType, boolean sizeOnly);

    /**
     * Unmarshal a new object instance from the byte buffer.
     * @param buffer the byte buffer, from which we will read the object
     * @param nativeType the native type, e.g.
     *        {@link android.hardware.photography.CameraMetadata#TYPE_BYTE TYPE_BYTE}.
     *        Guaranteed to be one for which isNativeTypeSupported returns true.
     * @return a new instance of type T read from the byte buffer
     */
    T unmarshal(ByteBuffer buffer, int nativeType);

    Class<T> getMarshalingClass();

    /**
     * Determines whether or not this marshaller supports this native type. Most marshallers
     * will are likely to only support one type.
     *
     * @param nativeType the native type, e.g.
     *        {@link android.hardware.photography.CameraMetadata#TYPE_BYTE TYPE_BYTE}
     * @return true if it supports, false otherwise
     */
    boolean isNativeTypeSupported(int nativeType);

    public static int NATIVE_SIZE_DYNAMIC = -1;

    /**
     * How many bytes T will take up if marshalled to/from nativeType
     * @param nativeType the native type, e.g.
     *        {@link android.hardware.photography.CameraMetadata#TYPE_BYTE TYPE_BYTE}
     * @return a size in bytes, or NATIVE_SIZE_DYNAMIC if the size is dynamic
     */
    int getNativeSize(int nativeType);
}
+68 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * 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.
 */
package android.hardware.photography.impl;

import android.graphics.Rect;
import android.hardware.photography.CameraMetadata;

import java.nio.ByteBuffer;

public class MetadataMarshalRect implements MetadataMarshalClass<Rect> {
    private static final int SIZE = 16;

    @Override
    public int marshal(Rect value, ByteBuffer buffer, int nativeType, boolean sizeOnly) {
        if (sizeOnly) {
            return SIZE;
        }

        buffer.putInt(value.left);
        buffer.putInt(value.top);
        buffer.putInt(value.width());
        buffer.putInt(value.height());

        return SIZE;
    }

    @Override
    public Rect unmarshal(ByteBuffer buffer, int nativeType) {

        int left = buffer.getInt();
        int top = buffer.getInt();
        int width = buffer.getInt();
        int height = buffer.getInt();

        int right = left + width;
        int bottom = top + height;

        return new Rect(left, top, right, bottom);
    }

    @Override
    public Class<Rect> getMarshalingClass() {
        return Rect.class;
    }

    @Override
    public boolean isNativeTypeSupported(int nativeType) {
        return nativeType == CameraMetadata.TYPE_INT32;
    }

    @Override
    public int getNativeSize(int nativeType) {
        return SIZE;
    }
}
+61 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * 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.
 */
package android.hardware.photography.impl;

import android.hardware.photography.CameraMetadata;
import android.hardware.photography.Size;

import java.nio.ByteBuffer;

public class MetadataMarshalSize implements MetadataMarshalClass<Size> {

    private static final int SIZE = 8;

    @Override
    public int marshal(Size value, ByteBuffer buffer, int nativeType, boolean sizeOnly) {
        if (sizeOnly) {
            return SIZE;
        }

        buffer.putInt(value.getWidth());
        buffer.putInt(value.getHeight());

        return SIZE;
    }

    @Override
    public Size unmarshal(ByteBuffer buffer, int nativeType) {
        int width = buffer.getInt();
        int height = buffer.getInt();

        return new Size(width, height);
    }

    @Override
    public Class<Size> getMarshalingClass() {
        return Size.class;
    }

    @Override
    public boolean isNativeTypeSupported(int nativeType) {
        return nativeType == CameraMetadata.TYPE_INT32;
    }

    @Override
    public int getNativeSize(int nativeType) {
        return SIZE;
    }
}
+81 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * 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.
 */
package android.hardware.photography.impl;

import android.hardware.photography.CameraMetadata;

import java.nio.ByteBuffer;
import java.nio.charset.Charset;

public class MetadataMarshalString implements MetadataMarshalClass<String> {

    private static final Charset UTF8_CHARSET = Charset.forName("UTF-8");

    @Override
    public int marshal(String value, ByteBuffer buffer, int nativeType, boolean sizeOnly) {
        byte[] arr = value.getBytes(UTF8_CHARSET);

        if (!sizeOnly) {
            buffer.put(arr);
            buffer.put((byte)0); // metadata strings are NULL-terminated
        }

        return arr.length + 1;
    }

    @Override
    public String unmarshal(ByteBuffer buffer, int nativeType) {

        buffer.mark(); // save the current position

        boolean foundNull = false;
        int stringLength = 0;
        while (buffer.hasRemaining()) {
            if (buffer.get() == (byte)0) {
                foundNull = true;
                break;
            }

            stringLength++;
        }
        if (!foundNull) {
            throw new IllegalArgumentException("Strings must be null-terminated");
        }

        buffer.reset(); // go back to the previously marked position

        byte[] strBytes = new byte[stringLength + 1];
        buffer.get(strBytes, /*dstOffset*/0, stringLength + 1); // including null character

        // not including null character
        return new String(strBytes, /*offset*/0, stringLength, UTF8_CHARSET);
    }

    @Override
    public Class<String> getMarshalingClass() {
        return String.class;
    }

    @Override
    public boolean isNativeTypeSupported(int nativeType) {
        return nativeType == CameraMetadata.TYPE_BYTE;
    }

    @Override
    public int getNativeSize(int nativeType) {
        return NATIVE_SIZE_DYNAMIC;
    }
}
Loading