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