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