1 /*
2  * Copyright 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 android.media.cts;
18 
19 import android.graphics.Bitmap;
20 import android.graphics.Color;
21 import android.graphics.Rect;
22 import android.media.cts.CodecImage;
23 import android.media.Image;
24 import android.media.MediaCodec.BufferInfo;
25 import android.os.Environment;
26 import android.util.Log;
27 
28 import java.io.File;
29 import java.io.FileDescriptor;
30 import java.io.FileOutputStream;
31 import java.io.InputStream;
32 import java.io.OutputStream;
33 import java.nio.ByteBuffer;
34 
35 public class CodecUtils  {
36     private static final String TAG = "CodecUtils";
37 
38     /** Load jni on initialization */
39     static {
Log.i(TAG, "before loadlibrary")40         Log.i(TAG, "before loadlibrary");
41         System.loadLibrary("ctscodecutils_jni");
Log.i(TAG, "after loadlibrary")42         Log.i(TAG, "after loadlibrary");
43     }
44 
45     private static class ImageWrapper extends CodecImage {
46         private final Image mImage;
47         private final Plane[] mPlanes;
48 
ImageWrapper(Image image)49         private ImageWrapper(Image image) {
50             mImage = image;
51             Image.Plane[] planes = mImage.getPlanes();
52 
53             mPlanes = new Plane[planes.length];
54             for (int i = 0; i < planes.length; i++) {
55                 mPlanes[i] = new PlaneWrapper(planes[i]);
56             }
57         }
58 
createFromImage(Image image)59         public static ImageWrapper createFromImage(Image image) {
60             return new ImageWrapper(image);
61         }
62 
63         @Override
getFormat()64         public int getFormat() {
65             return mImage.getFormat();
66         }
67 
68         @Override
getWidth()69         public int getWidth() {
70             return mImage.getWidth();
71         }
72 
73         @Override
getHeight()74         public int getHeight() {
75             return mImage.getHeight();
76         }
77 
78         @Override
getTimestamp()79         public long getTimestamp() {
80             return mImage.getTimestamp();
81         }
82 
83         @Override
getPlanes()84         public Plane[] getPlanes() {
85             return mPlanes;
86         }
87 
88         @Override
close()89         public void close() {
90             mImage.close();
91         }
92 
93         private static class PlaneWrapper extends CodecImage.Plane {
94             private final Image.Plane mPlane;
95 
PlaneWrapper(Image.Plane plane)96             PlaneWrapper(Image.Plane plane) {
97                 mPlane = plane;
98             }
99 
100             @Override
getRowStride()101             public int getRowStride() {
102                 return mPlane.getRowStride();
103             }
104 
105            @Override
getPixelStride()106             public int getPixelStride() {
107                return mPlane.getPixelStride();
108             }
109 
110             @Override
getBuffer()111             public ByteBuffer getBuffer() {
112                 return mPlane.getBuffer();
113             }
114         }
115     }
116 
117     /* two native image checksum functions */
getImageChecksumAdler32(CodecImage image)118     public native static int getImageChecksumAdler32(CodecImage image);
getImageChecksumMD5(CodecImage image)119     public native static String getImageChecksumMD5(CodecImage image);
120 
copyFlexYUVImage(CodecImage target, CodecImage source)121     public native static void copyFlexYUVImage(CodecImage target, CodecImage source);
122 
copyFlexYUVImage(Image target, CodecImage source)123     public static void copyFlexYUVImage(Image target, CodecImage source) {
124         copyFlexYUVImage(ImageWrapper.createFromImage(target), source);
125     }
copyFlexYUVImage(Image target, Image source)126     public static void copyFlexYUVImage(Image target, Image source) {
127         copyFlexYUVImage(
128                 ImageWrapper.createFromImage(target),
129                 ImageWrapper.createFromImage(source));
130     }
131 
fillImageRectWithYUV( CodecImage image, Rect area, int y, int u, int v)132     public native static void fillImageRectWithYUV(
133             CodecImage image, Rect area, int y, int u, int v);
134 
fillImageRectWithYUV(Image image, Rect area, int y, int u, int v)135     public static void fillImageRectWithYUV(Image image, Rect area, int y, int u, int v) {
136         fillImageRectWithYUV(ImageWrapper.createFromImage(image), area, y, u, v);
137     }
138 
getRawStats(CodecImage image, Rect area)139     public native static long[] getRawStats(CodecImage image, Rect area);
140 
getRawStats(Image image, Rect area)141     public static long[] getRawStats(Image image, Rect area) {
142         return getRawStats(ImageWrapper.createFromImage(image), area);
143     }
144 
getYUVStats(CodecImage image, Rect area)145     public native static float[] getYUVStats(CodecImage image, Rect area);
146 
getYUVStats(Image image, Rect area)147     public static float[] getYUVStats(Image image, Rect area) {
148         return getYUVStats(ImageWrapper.createFromImage(image), area);
149     }
150 
Raw2YUVStats(long[] rawStats)151     public native static float[] Raw2YUVStats(long[] rawStats);
152 
153     /**
154      * This method reads the binarybar code on the top row of a bitmap. Each 16x16
155      * block is one digit, with black=0 and white=1. LSB is on the left.
156      */
readBinaryCounterFromBitmap(Bitmap bitmap)157     public static int readBinaryCounterFromBitmap(Bitmap bitmap) {
158         int numDigits = bitmap.getWidth() / 16;
159         int counter = 0;
160         for (int i = 0; i < numDigits; i++) {
161             int rgb = bitmap.getPixel(i * 16 + 8, 8);
162             if (Color.red(rgb) > 128) {
163                 counter |= (1 << i);
164             }
165         }
166         return counter;
167     }
168 
saveBitmapToFile(Bitmap bitmap, String filename)169     public static void saveBitmapToFile(Bitmap bitmap, String filename) {
170         try {
171             File outputFile = new File(Environment.getExternalStorageDirectory(), filename);
172 
173             Log.d(TAG, "Saving bitmap to: " + outputFile);
174             FileOutputStream outputStream = new FileOutputStream(outputFile);
175             bitmap.compress(Bitmap.CompressFormat.JPEG, 90, outputStream);
176             outputStream.flush();
177             outputStream.close();
178         } catch(Exception e) {
179             Log.e(TAG, "Failed to save to file: " + e);
180         }
181     }
182 }
183 
184