Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.camera.util;
     18 
     19 import android.hardware.camera2.CameraMetadata;
     20 import android.hardware.camera2.CaptureRequest;
     21 import android.hardware.camera2.CaptureResult;
     22 import android.hardware.camera2.params.ColorSpaceTransform;
     23 import android.hardware.camera2.params.LensShadingMap;
     24 import android.hardware.camera2.params.RggbChannelVector;
     25 import android.hardware.camera2.params.TonemapCurve;
     26 import android.util.Pair;
     27 import android.util.Rational;
     28 
     29 import com.android.camera.debug.Log;
     30 import com.android.camera.debug.Log.Tag;
     31 
     32 import java.io.BufferedWriter;
     33 import java.io.File;
     34 import java.io.FileWriter;
     35 import java.io.IOException;
     36 import java.io.StringWriter;
     37 import java.io.Writer;
     38 import java.lang.reflect.Array;
     39 import java.util.Arrays;
     40 import java.util.List;
     41 
     42 /**
     43  * Can be used for debugging to output details about Camera2 capture request and
     44  * responses.
     45  */
     46 public class CaptureDataSerializer {
     47     private static interface Writeable {
     48         public void write(Writer writer) throws IOException;
     49     }
     50 
     51     private static final Tag TAG = new Tag("CaptureDataSerilzr");
     52 
     53     /**
     54      * Generate a human-readable string of the given capture request and return
     55      * it.
     56      */
     57     public static String toString(String title, CaptureRequest metadata) {
     58         StringWriter writer = new StringWriter();
     59         dumpMetadata(title, metadata, writer);
     60         return writer.toString();
     61     }
     62 
     63     /**
     64      * Generate a human-readable string of the given capture request and write
     65      * it to the given file.
     66      */
     67     public static void toFile(String title, CameraMetadata<?> metadata, File file) {
     68         try {
     69             // Will append if the file already exists.
     70             FileWriter writer = new FileWriter(file, true);
     71             if (metadata instanceof CaptureRequest) {
     72                 dumpMetadata(title, (CaptureRequest) metadata, writer);
     73             } else if (metadata instanceof CaptureResult) {
     74                 dumpMetadata(title, (CaptureResult) metadata, writer);
     75             } else {
     76                 writer.close();
     77                 throw new IllegalArgumentException("Cannot generate debug data from type "
     78                         + metadata.getClass().getName());
     79             }
     80             writer.close();
     81         } catch (IOException ex) {
     82             Log.e(TAG, "Could not write capture data to file.", ex);
     83         }
     84     }
     85 
     86     /**
     87      * Writes the data about the marker and requests to the given folder for
     88      * offline debugging.
     89      */
     90     private static void dumpMetadata(final String title, final CaptureRequest metadata,
     91             Writer writer) {
     92         Writeable writeable = new Writeable() {
     93             @Override
     94             public void write(Writer writer) throws IOException {
     95                 List<CaptureRequest.Key<?>> keys = metadata.getKeys();
     96                 writer.write(title + '\n');
     97 
     98                 // TODO: move to CameraMetadata#toString ?
     99                 for (CaptureRequest.Key<?> key : keys) {
    100                     writer.write(String.format("    %s\n", key.getName()));
    101                     writer.write(String.format("        %s\n",
    102                             metadataValueToString(metadata.get(key))));
    103                 }
    104             }
    105         };
    106         dumpMetadata(writeable, new BufferedWriter(writer));
    107     }
    108 
    109     /**
    110      * Writes the data about the marker and requests to the given folder for
    111      * offline debugging.
    112      */
    113     private static void dumpMetadata(final String title, final CaptureResult metadata,
    114             Writer writer) {
    115         Writeable writeable = new Writeable() {
    116             @Override
    117             public void write(Writer writer) throws IOException {
    118                 List<CaptureResult.Key<?>> keys = metadata.getKeys();
    119                 writer.write(String.format(title) + '\n');
    120 
    121                 // TODO: move to CameraMetadata#toString ?
    122                 for (CaptureResult.Key<?> key : keys) {
    123                     writer.write(String.format("    %s\n", key.getName()));
    124                     writer.write(String.format("        %s\n",
    125                             metadataValueToString(metadata.get(key))));
    126                 }
    127             }
    128         };
    129         dumpMetadata(writeable, new BufferedWriter(writer));
    130     }
    131 
    132     private static String metadataValueToString(Object object) {
    133         if (object == null) {
    134             return "<null>";
    135         }
    136         if (object.getClass().isArray()) {
    137             StringBuilder builder = new StringBuilder();
    138             builder.append("[");
    139 
    140             int length = Array.getLength(object);
    141             for (int i = 0; i < length; ++i) {
    142                 Object item = Array.get(object, i);
    143                 builder.append(metadataValueToString(item));
    144 
    145                 if (i != length - 1) {
    146                     builder.append(", ");
    147                 }
    148             }
    149             builder.append(']');
    150 
    151             return builder.toString();
    152         } else {
    153             // These classes don't have a toString() method yet
    154             // See: http://b/16899576
    155             if (object instanceof LensShadingMap) {
    156                 return toString((LensShadingMap) object);
    157             } else if (object instanceof Pair) {
    158                 return toString((Pair<?, ?>) object);
    159             }
    160             return object.toString();
    161         }
    162     }
    163 
    164     private static void dumpMetadata(Writeable metadata, Writer writer) {
    165         /**
    166          * Save metadata to file, appending if another metadata is already in
    167          * that file.
    168          */
    169         try {
    170             metadata.write(writer);
    171         } catch (IOException e) {
    172             Log.e(TAG, "dumpMetadata - Failed to dump metadata", e);
    173         } finally {
    174             try {
    175                 if (writer != null) {
    176                     writer.close();
    177                 }
    178             } catch (IOException e) {
    179                 Log.e(TAG, "dumpMetadata - Failed to close writer.", e);
    180             }
    181         }
    182     }
    183 
    184     private static String toString(LensShadingMap lensShading) {
    185         StringBuilder str = new StringBuilder();
    186         str.append("LensShadingMap{");
    187 
    188         String channelName[] = {"R", "G_even", "G_odd", "B"};
    189         int numRows = lensShading.getRowCount();
    190         int numCols = lensShading.getColumnCount();
    191         int numChannels = RggbChannelVector.COUNT;
    192 
    193         for (int ch = 0; ch < numChannels; ch++) {
    194             str.append(channelName[ch]);
    195             str.append(":(");
    196 
    197             for (int r = 0; r < numRows; r++) {
    198                 str.append("[");
    199                 for (int c = 0; c < numCols; c++) {
    200                     float gain = lensShading.getGainFactor(ch, c, r);
    201                     str.append(gain);
    202                     if (c < numCols - 1) {
    203                         str.append(", ");
    204                     }
    205                 }
    206                 str.append("]");
    207                 if (r < numRows - 1) {
    208                     str.append(", ");
    209                 }
    210             }
    211 
    212             str.append(")");
    213             if (ch < numChannels - 1) {
    214                 str.append(", ");
    215             }
    216         }
    217 
    218         str.append("}");
    219         return str.toString();
    220     }
    221 
    222     private static String toString(Pair<?, ?> pair) {
    223         return "Pair: " + metadataValueToString(pair.first) + " / "
    224                 + metadataValueToString(pair.second);
    225     }
    226 }
    227