1 /* 2 * Copyright (C) 2015 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.ImageFormat; 20 import android.graphics.Point; 21 22 import android.media.cts.CodecImage; 23 import android.media.cts.CodecUtils; 24 25 import java.nio.ByteBuffer; 26 27 public class YUVImage extends CodecImage { 28 private final int mImageWidth; 29 private final int mImageHeight; 30 private final Plane[] mPlanes; 31 YUVImage( Point origin, int imageWidth, int imageHeight, int arrayWidth, int arrayHeight, boolean semiPlanar, ByteBuffer bufferY, ByteBuffer bufferUV)32 public YUVImage( 33 Point origin, 34 int imageWidth, int imageHeight, 35 int arrayWidth, int arrayHeight, 36 boolean semiPlanar, 37 ByteBuffer bufferY, ByteBuffer bufferUV) { 38 mImageWidth = imageWidth; 39 mImageHeight = imageHeight; 40 ByteBuffer dupY = bufferY.duplicate(); 41 ByteBuffer dupUV = bufferUV.duplicate(); 42 mPlanes = new Plane[3]; 43 44 int srcOffsetY = origin.x + origin.y * arrayWidth; 45 46 mPlanes[0] = new YUVPlane( 47 mImageWidth, mImageHeight, arrayWidth, 1, 48 dupY, srcOffsetY); 49 50 if (semiPlanar) { 51 int srcOffsetUV = origin.y / 2 * arrayWidth + origin.x / 2 * 2; 52 53 mPlanes[1] = new YUVPlane( 54 mImageWidth / 2, mImageHeight / 2, arrayWidth, 2, 55 dupUV, srcOffsetUV); 56 mPlanes[2] = new YUVPlane( 57 mImageWidth / 2, mImageHeight / 2, arrayWidth, 2, 58 dupUV, srcOffsetUV + 1); 59 } else { 60 int srcOffsetU = origin.y / 2 * arrayWidth / 2 + origin.x / 2; 61 int srcOffsetV = srcOffsetU + arrayWidth / 2 * arrayHeight / 2; 62 63 mPlanes[1] = new YUVPlane( 64 mImageWidth / 2, mImageHeight / 2, arrayWidth / 2, 1, 65 dupUV, srcOffsetU); 66 mPlanes[2] = new YUVPlane( 67 mImageWidth / 2, mImageHeight / 2, arrayWidth / 2, 1, 68 dupUV, srcOffsetV); 69 } 70 } 71 72 @Override getFormat()73 public int getFormat() { 74 return ImageFormat.YUV_420_888; 75 } 76 77 @Override getWidth()78 public int getWidth() { 79 return mImageWidth; 80 } 81 82 @Override getHeight()83 public int getHeight() { 84 return mImageHeight; 85 } 86 87 @Override getTimestamp()88 public long getTimestamp() { 89 return 0; 90 } 91 92 @Override getPlanes()93 public Plane[] getPlanes() { 94 return mPlanes; 95 } 96 97 @Override close()98 public void close() { 99 mPlanes[0] = null; 100 mPlanes[1] = null; 101 mPlanes[2] = null; 102 } 103 104 class YUVPlane extends CodecImage.Plane { 105 private final int mRowStride; 106 private final int mPixelStride; 107 private final ByteBuffer mByteBuffer; 108 YUVPlane(int w, int h, int rowStride, int pixelStride, ByteBuffer buffer, int offset)109 YUVPlane(int w, int h, int rowStride, int pixelStride, 110 ByteBuffer buffer, int offset) { 111 mRowStride = rowStride; 112 mPixelStride = pixelStride; 113 114 // only safe to access length bytes starting from buffer[offset] 115 int length = (h - 1) * rowStride + (w - 1) * pixelStride + 1; 116 117 buffer.position(offset); 118 mByteBuffer = buffer.slice(); 119 mByteBuffer.limit(length); 120 } 121 122 @Override getRowStride()123 public int getRowStride() { 124 return mRowStride; 125 } 126 127 @Override getPixelStride()128 public int getPixelStride() { 129 return mPixelStride; 130 } 131 132 @Override getBuffer()133 public ByteBuffer getBuffer() { 134 return mByteBuffer; 135 } 136 } 137 } 138 139