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 setCropRect(image.getCropRect()); 59 } 60 createFromImage(Image image)61 public static ImageWrapper createFromImage(Image image) { 62 return new ImageWrapper(image); 63 } 64 65 @Override getFormat()66 public int getFormat() { 67 return mImage.getFormat(); 68 } 69 70 @Override getWidth()71 public int getWidth() { 72 return mImage.getWidth(); 73 } 74 75 @Override getHeight()76 public int getHeight() { 77 return mImage.getHeight(); 78 } 79 80 @Override getTimestamp()81 public long getTimestamp() { 82 return mImage.getTimestamp(); 83 } 84 85 @Override getPlanes()86 public Plane[] getPlanes() { 87 return mPlanes; 88 } 89 90 @Override close()91 public void close() { 92 mImage.close(); 93 } 94 95 private static class PlaneWrapper extends CodecImage.Plane { 96 private final Image.Plane mPlane; 97 PlaneWrapper(Image.Plane plane)98 PlaneWrapper(Image.Plane plane) { 99 mPlane = plane; 100 } 101 102 @Override getRowStride()103 public int getRowStride() { 104 return mPlane.getRowStride(); 105 } 106 107 @Override getPixelStride()108 public int getPixelStride() { 109 return mPlane.getPixelStride(); 110 } 111 112 @Override getBuffer()113 public ByteBuffer getBuffer() { 114 return mPlane.getBuffer(); 115 } 116 } 117 } 118 119 /* two native image checksum functions */ getImageChecksumAdler32(CodecImage image)120 public native static int getImageChecksumAdler32(CodecImage image); getImageChecksumMD5(CodecImage image)121 public native static String getImageChecksumMD5(CodecImage image); 122 copyFlexYUVImage(CodecImage target, CodecImage source)123 public native static void copyFlexYUVImage(CodecImage target, CodecImage source); 124 copyFlexYUVImage(Image target, CodecImage source)125 public static void copyFlexYUVImage(Image target, CodecImage source) { 126 copyFlexYUVImage(ImageWrapper.createFromImage(target), source); 127 } copyFlexYUVImage(Image target, Image source)128 public static void copyFlexYUVImage(Image target, Image source) { 129 copyFlexYUVImage( 130 ImageWrapper.createFromImage(target), 131 ImageWrapper.createFromImage(source)); 132 } 133 fillImageRectWithYUV( CodecImage image, Rect area, int y, int u, int v)134 public native static void fillImageRectWithYUV( 135 CodecImage image, Rect area, int y, int u, int v); 136 fillImageRectWithYUV(Image image, Rect area, int y, int u, int v)137 public static void fillImageRectWithYUV(Image image, Rect area, int y, int u, int v) { 138 fillImageRectWithYUV(ImageWrapper.createFromImage(image), area, y, u, v); 139 } 140 getRawStats(CodecImage image, Rect area)141 public native static long[] getRawStats(CodecImage image, Rect area); 142 getRawStats(Image image, Rect area)143 public static long[] getRawStats(Image image, Rect area) { 144 return getRawStats(ImageWrapper.createFromImage(image), area); 145 } 146 getYUVStats(CodecImage image, Rect area)147 public native static float[] getYUVStats(CodecImage image, Rect area); 148 getYUVStats(Image image, Rect area)149 public static float[] getYUVStats(Image image, Rect area) { 150 return getYUVStats(ImageWrapper.createFromImage(image), area); 151 } 152 Raw2YUVStats(long[] rawStats)153 public native static float[] Raw2YUVStats(long[] rawStats); 154 155 /** 156 * This method reads the binarybar code on the top row of a bitmap. Each 16x16 157 * block is one digit, with black=0 and white=1. LSB is on the left. 158 */ readBinaryCounterFromBitmap(Bitmap bitmap)159 public static int readBinaryCounterFromBitmap(Bitmap bitmap) { 160 int numDigits = bitmap.getWidth() / 16; 161 int counter = 0; 162 for (int i = 0; i < numDigits; i++) { 163 int rgb = bitmap.getPixel(i * 16 + 8, 8); 164 if (Color.red(rgb) > 128) { 165 counter |= (1 << i); 166 } 167 } 168 return counter; 169 } 170 saveBitmapToFile(Bitmap bitmap, String filename)171 public static void saveBitmapToFile(Bitmap bitmap, String filename) { 172 try { 173 File outputFile = new File(Environment.getExternalStorageDirectory(), filename); 174 175 Log.d(TAG, "Saving bitmap to: " + outputFile); 176 FileOutputStream outputStream = new FileOutputStream(outputFile); 177 bitmap.compress(Bitmap.CompressFormat.JPEG, 90, outputStream); 178 outputStream.flush(); 179 outputStream.close(); 180 } catch(Exception e) { 181 Log.e(TAG, "Failed to save to file: " + e); 182 } 183 } 184 } 185 186