• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.RggbChannelVector;
24 import android.hardware.camera2.params.TonemapCurve;
25 import android.util.Pair;
26 import android.util.Rational;
27 
28 import com.android.camera.debug.Log;
29 import com.android.camera.debug.Log.Tag;
30 
31 import java.io.BufferedWriter;
32 import java.io.File;
33 import java.io.FileWriter;
34 import java.io.IOException;
35 import java.io.StringWriter;
36 import java.io.Writer;
37 import java.lang.reflect.Array;
38 import java.util.Arrays;
39 import java.util.List;
40 
41 /**
42  * Can be used for debugging to output details about Camera2 capture request and
43  * responses.
44  */
45 public class CaptureDataSerializer {
46     private static interface Writeable {
write(Writer writer)47         public void write(Writer writer) throws IOException;
48     }
49 
50     private static final Tag TAG = new Tag("CaptureDataSerilzr");
51 
52     /**
53      * Generate a human-readable string of the given capture request and return
54      * it.
55      */
toString(String title, CaptureRequest metadata)56     public static String toString(String title, CaptureRequest metadata) {
57         StringWriter writer = new StringWriter();
58         dumpMetadata(title, metadata, writer);
59         return writer.toString();
60     }
61 
62     /**
63      * Generate a human-readable string of the given capture request and write
64      * it to the given file.
65      */
toFile(String title, CameraMetadata<?> metadata, File file)66     public static void toFile(String title, CameraMetadata<?> metadata, File file) {
67         try {
68             // Will append if the file already exists.
69             FileWriter writer = new FileWriter(file, true);
70             if (metadata instanceof CaptureRequest) {
71                 dumpMetadata(title, (CaptureRequest) metadata, writer);
72             } else if (metadata instanceof CaptureResult) {
73                 dumpMetadata(title, (CaptureResult) metadata, writer);
74             } else {
75                 writer.close();
76                 throw new IllegalArgumentException("Cannot generate debug data from type "
77                         + metadata.getClass().getName());
78             }
79             writer.close();
80         } catch (IOException ex) {
81             Log.e(TAG, "Could not write capture data to file.", ex);
82         }
83     }
84 
85     /**
86      * Writes the data about the marker and requests to the given folder for
87      * offline debugging.
88      */
dumpMetadata(final String title, final CaptureRequest metadata, Writer writer)89     private static void dumpMetadata(final String title, final CaptureRequest metadata,
90             Writer writer) {
91         Writeable writeable = new Writeable() {
92             @Override
93             public void write(Writer writer) throws IOException {
94                 List<CaptureRequest.Key<?>> keys = metadata.getKeys();
95                 writer.write(title + '\n');
96 
97                 // TODO: move to CameraMetadata#toString ?
98                 for (CaptureRequest.Key<?> key : keys) {
99                     writer.write(String.format("    %s\n", key.getName()));
100                     writer.write(String.format("        %s\n",
101                             metadataValueToString(metadata.get(key))));
102                 }
103             }
104         };
105         dumpMetadata(writeable, new BufferedWriter(writer));
106     }
107 
108     /**
109      * Writes the data about the marker and requests to the given folder for
110      * offline debugging.
111      */
dumpMetadata(final String title, final CaptureResult metadata, Writer writer)112     private static void dumpMetadata(final String title, final CaptureResult metadata,
113             Writer writer) {
114         Writeable writeable = new Writeable() {
115             @Override
116             public void write(Writer writer) throws IOException {
117                 List<CaptureResult.Key<?>> keys = metadata.getKeys();
118                 writer.write(String.format(title));
119 
120                 // TODO: move to CameraMetadata#toString ?
121                 for (CaptureResult.Key<?> key : keys) {
122                     writer.write(String.format("    %s\n", key.getName()));
123                     writer.write(String.format("        %s\n",
124                             metadataValueToString(metadata.get(key))));
125                 }
126             }
127         };
128         dumpMetadata(writeable, new BufferedWriter(writer));
129     }
130 
metadataValueToString(Object object)131     private static String metadataValueToString(Object object) {
132         if (object == null) {
133             return "<null>";
134         }
135         if (object.getClass().isArray()) {
136             StringBuilder builder = new StringBuilder();
137             builder.append("[");
138 
139             int length = Array.getLength(object);
140             for (int i = 0; i < length; ++i) {
141                 Object item = Array.get(object, i);
142                 builder.append(metadataValueToString(item));
143 
144                 if (i != length - 1) {
145                     builder.append(", ");
146                 }
147             }
148             builder.append(']');
149 
150             return builder.toString();
151         } else {
152             // These classes don't have a toString() method yet
153             // See: http://b/16899576
154             if (object instanceof RggbChannelVector) {
155                 return toString((RggbChannelVector) object);
156             } else if (object instanceof ColorSpaceTransform) {
157                 return toString((ColorSpaceTransform) object);
158             } else if (object instanceof TonemapCurve) {
159                 return toString((TonemapCurve) object);
160             } else if (object instanceof Pair) {
161                 return toString((Pair<?, ?>) object);
162             }
163             return object.toString();
164         }
165     }
166 
dumpMetadata(Writeable metadata, Writer writer)167     private static void dumpMetadata(Writeable metadata, Writer writer) {
168         /**
169          * Save metadata to file, appending if another metadata is already in
170          * that file.
171          */
172         try {
173             metadata.write(writer);
174         } catch (IOException e) {
175             Log.e(TAG, "dumpMetadata - Failed to dump metadata", e);
176         } finally {
177             try {
178                 if (writer != null) {
179                     writer.close();
180                 }
181             } catch (IOException e) {
182                 Log.e(TAG, "dumpMetadata - Failed to close writer.", e);
183             }
184         }
185     }
186 
toString(RggbChannelVector vector)187     private static String toString(RggbChannelVector vector) {
188         StringBuilder str = new StringBuilder();
189         str.append("RggbChannelVector:");
190         str.append(" R:");
191         str.append(vector.getRed());
192         str.append(" G(even):");
193         str.append(vector.getGreenEven());
194         str.append(" G(odd):");
195         str.append(vector.getGreenOdd());
196         str.append(" B:");
197         str.append(vector.getBlue());
198 
199         return str.toString();
200     }
201 
toString(ColorSpaceTransform transform)202     private static String toString(ColorSpaceTransform transform) {
203         StringBuilder str = new StringBuilder();
204         Rational[] rationals = new Rational[9];
205         transform.copyElements(rationals, 0);
206         str.append("ColorSpaceTransform: ");
207         str.append(Arrays.toString(rationals));
208         return str.toString();
209     }
210 
toString(TonemapCurve curve)211     private static String toString(TonemapCurve curve) {
212         StringBuilder str = new StringBuilder();
213         str.append("TonemapCurve:");
214 
215         float[] reds = new float[curve.getPointCount(TonemapCurve.CHANNEL_RED)
216                 * TonemapCurve.POINT_SIZE];
217         curve.copyColorCurve(TonemapCurve.CHANNEL_RED, reds, 0);
218         float[] greens = new float[curve.getPointCount(TonemapCurve.CHANNEL_GREEN)
219                 * TonemapCurve.POINT_SIZE];
220         curve.copyColorCurve(TonemapCurve.CHANNEL_GREEN, greens, 0);
221         float[] blues = new float[curve.getPointCount(TonemapCurve.CHANNEL_BLUE)
222                 * TonemapCurve.POINT_SIZE];
223         curve.copyColorCurve(TonemapCurve.CHANNEL_BLUE, blues, 0);
224 
225         str.append("\n\nReds: ");
226         str.append(Arrays.toString(reds));
227         str.append("\n\nGreens: ");
228         str.append(Arrays.toString(greens));
229         str.append("\n\nBlues: ");
230         str.append(Arrays.toString(blues));
231 
232         return str.toString();
233     }
234 
toString(Pair<?, ?> pair)235     private static String toString(Pair<?, ?> pair) {
236         return "Pair: " + metadataValueToString(pair.first) + " / "
237                 + metadataValueToString(pair.second);
238     }
239 }
240