OSDN Git Service

Careful process validation for unaware providers.
[android-x86/frameworks-base.git] / media / jni / android_media_Utils.cpp
1 /*
2  * Copyright 2011, 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 // #define LOG_NDEBUG 0
18 #define LOG_TAG "AndroidMediaUtils"
19
20 #include <utils/Log.h>
21 #include "android_media_Utils.h"
22
23 #include <media/stagefright/foundation/ADebug.h>
24 #include <media/stagefright/foundation/ABuffer.h>
25 #include <media/stagefright/foundation/AMessage.h>
26
27 #include <nativehelper/ScopedLocalRef.h>
28
29 #define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )
30
31 namespace android {
32
33 AssetStream::AssetStream(SkStream* stream)
34     : mStream(stream), mPosition(0) {
35 }
36
37 AssetStream::~AssetStream() {
38 }
39
40 piex::Error AssetStream::GetData(
41         const size_t offset, const size_t length, std::uint8_t* data) {
42     // Seek first.
43     if (mPosition != offset) {
44         if (!mStream->seek(offset)) {
45             return piex::Error::kFail;
46         }
47     }
48
49     // Read bytes.
50     size_t size = mStream->read((void*)data, length);
51     mPosition = offset + size;
52
53     return size == length ? piex::Error::kOk : piex::Error::kFail;
54 }
55
56 BufferedStream::BufferedStream(SkStream* stream)
57     : mStream(stream) {
58 }
59
60 BufferedStream::~BufferedStream() {
61 }
62
63 piex::Error BufferedStream::GetData(
64         const size_t offset, const size_t length, std::uint8_t* data) {
65     // Seek first.
66     if (offset + length > mStreamBuffer.bytesWritten()) {
67         size_t sizeToRead = offset + length - mStreamBuffer.bytesWritten();
68         if (sizeToRead <= kMinSizeToRead) {
69             sizeToRead = kMinSizeToRead;
70         }
71         void* tempBuffer = malloc(sizeToRead);
72         if (tempBuffer != NULL) {
73             size_t bytesRead = mStream->read(tempBuffer, sizeToRead);
74             if (bytesRead != sizeToRead) {
75                 free(tempBuffer);
76                 return piex::Error::kFail;
77             }
78             mStreamBuffer.write(tempBuffer, bytesRead);
79             free(tempBuffer);
80         }
81     }
82
83     // Read bytes.
84     if (mStreamBuffer.read((void*)data, offset, length)) {
85         return piex::Error::kOk;
86     } else {
87         return piex::Error::kFail;
88     }
89 }
90
91 FileStream::FileStream(const int fd)
92     : mPosition(0) {
93     mFile = fdopen(fd, "r");
94     if (mFile == NULL) {
95         return;
96     }
97 }
98
99 FileStream::FileStream(const String8 filename)
100     : mPosition(0) {
101     mFile = fopen(filename.string(), "r");
102     if (mFile == NULL) {
103         return;
104     }
105 }
106
107 FileStream::~FileStream() {
108     if (mFile != NULL) {
109         fclose(mFile);
110         mFile = NULL;
111     }
112 }
113
114 piex::Error FileStream::GetData(
115         const size_t offset, const size_t length, std::uint8_t* data) {
116     if (mFile == NULL) {
117         return piex::Error::kFail;
118     }
119
120     // Seek first.
121     if (mPosition != offset) {
122         fseek(mFile, offset, SEEK_SET);
123     }
124
125     // Read bytes.
126     size_t size = fread((void*)data, sizeof(std::uint8_t), length, mFile);
127     mPosition += size;
128
129     // Handle errors.
130     if (ferror(mFile)) {
131         ALOGV("GetData read failed: (offset: %zu, length: %zu)", offset, length);
132         return piex::Error::kFail;
133     }
134     return piex::Error::kOk;
135 }
136
137 bool FileStream::exists() const {
138     return mFile != NULL;
139 }
140
141 bool GetExifFromRawImage(
142         piex::StreamInterface* stream, const String8& filename,
143         piex::PreviewImageData& image_data) {
144     // Reset the PreviewImageData to its default.
145     image_data = piex::PreviewImageData();
146
147     if (!piex::IsRaw(stream)) {
148         // Format not supported.
149         ALOGV("Format not supported: %s", filename.string());
150         return false;
151     }
152
153     piex::Error err = piex::GetPreviewImageData(stream, &image_data);
154
155     if (err != piex::Error::kOk) {
156         // The input data seems to be broken.
157         ALOGV("Raw image not detected: %s (piex error code: %d)", filename.string(), (int32_t)err);
158         return false;
159     }
160
161     return true;
162 }
163
164 bool ConvertKeyValueArraysToKeyedVector(
165         JNIEnv *env, jobjectArray keys, jobjectArray values,
166         KeyedVector<String8, String8>* keyedVector) {
167
168     int nKeyValuePairs = 0;
169     bool failed = false;
170     if (keys != NULL && values != NULL) {
171         nKeyValuePairs = env->GetArrayLength(keys);
172         failed = (nKeyValuePairs != env->GetArrayLength(values));
173     }
174
175     if (!failed) {
176         failed = ((keys != NULL && values == NULL) ||
177                   (keys == NULL && values != NULL));
178     }
179
180     if (failed) {
181         ALOGE("keys and values arrays have different length");
182         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
183         return false;
184     }
185
186     for (int i = 0; i < nKeyValuePairs; ++i) {
187         // No need to check on the ArrayIndexOutOfBoundsException, since
188         // it won't happen here.
189         jstring key = (jstring) env->GetObjectArrayElement(keys, i);
190         jstring value = (jstring) env->GetObjectArrayElement(values, i);
191
192         const char* keyStr = env->GetStringUTFChars(key, NULL);
193         if (!keyStr) {  // OutOfMemoryError
194             return false;
195         }
196
197         const char* valueStr = env->GetStringUTFChars(value, NULL);
198         if (!valueStr) {  // OutOfMemoryError
199             env->ReleaseStringUTFChars(key, keyStr);
200             return false;
201         }
202
203         keyedVector->add(String8(keyStr), String8(valueStr));
204
205         env->ReleaseStringUTFChars(key, keyStr);
206         env->ReleaseStringUTFChars(value, valueStr);
207         env->DeleteLocalRef(key);
208         env->DeleteLocalRef(value);
209     }
210     return true;
211 }
212
213 static jobject makeIntegerObject(JNIEnv *env, int32_t value) {
214     ScopedLocalRef<jclass> clazz(env, env->FindClass("java/lang/Integer"));
215     CHECK(clazz.get() != NULL);
216
217     jmethodID integerConstructID =
218         env->GetMethodID(clazz.get(), "<init>", "(I)V");
219     CHECK(integerConstructID != NULL);
220
221     return env->NewObject(clazz.get(), integerConstructID, value);
222 }
223
224 static jobject makeLongObject(JNIEnv *env, int64_t value) {
225     ScopedLocalRef<jclass> clazz(env, env->FindClass("java/lang/Long"));
226     CHECK(clazz.get() != NULL);
227
228     jmethodID longConstructID = env->GetMethodID(clazz.get(), "<init>", "(J)V");
229     CHECK(longConstructID != NULL);
230
231     return env->NewObject(clazz.get(), longConstructID, value);
232 }
233
234 static jobject makeFloatObject(JNIEnv *env, float value) {
235     ScopedLocalRef<jclass> clazz(env, env->FindClass("java/lang/Float"));
236     CHECK(clazz.get() != NULL);
237
238     jmethodID floatConstructID =
239         env->GetMethodID(clazz.get(), "<init>", "(F)V");
240     CHECK(floatConstructID != NULL);
241
242     return env->NewObject(clazz.get(), floatConstructID, value);
243 }
244
245 static jobject makeByteBufferObject(
246         JNIEnv *env, const void *data, size_t size) {
247     jbyteArray byteArrayObj = env->NewByteArray(size);
248     env->SetByteArrayRegion(byteArrayObj, 0, size, (const jbyte *)data);
249
250     ScopedLocalRef<jclass> clazz(env, env->FindClass("java/nio/ByteBuffer"));
251     CHECK(clazz.get() != NULL);
252
253     jmethodID byteBufWrapID =
254         env->GetStaticMethodID(
255                 clazz.get(), "wrap", "([B)Ljava/nio/ByteBuffer;");
256     CHECK(byteBufWrapID != NULL);
257
258     jobject byteBufObj = env->CallStaticObjectMethod(
259             clazz.get(), byteBufWrapID, byteArrayObj);
260
261     env->DeleteLocalRef(byteArrayObj); byteArrayObj = NULL;
262
263     return byteBufObj;
264 }
265
266 static void SetMapInt32(
267         JNIEnv *env, jobject hashMapObj, jmethodID hashMapPutID,
268         const char *key, int32_t value) {
269     jstring keyObj = env->NewStringUTF(key);
270     jobject valueObj = makeIntegerObject(env, value);
271
272     env->CallObjectMethod(hashMapObj, hashMapPutID, keyObj, valueObj);
273
274     env->DeleteLocalRef(valueObj); valueObj = NULL;
275     env->DeleteLocalRef(keyObj); keyObj = NULL;
276 }
277
278 status_t ConvertMessageToMap(
279         JNIEnv *env, const sp<AMessage> &msg, jobject *map) {
280     ScopedLocalRef<jclass> hashMapClazz(
281             env, env->FindClass("java/util/HashMap"));
282
283     if (hashMapClazz.get() == NULL) {
284         return -EINVAL;
285     }
286
287     jmethodID hashMapConstructID =
288         env->GetMethodID(hashMapClazz.get(), "<init>", "()V");
289
290     if (hashMapConstructID == NULL) {
291         return -EINVAL;
292     }
293
294     jmethodID hashMapPutID =
295         env->GetMethodID(
296                 hashMapClazz.get(),
297                 "put",
298                 "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
299
300     if (hashMapPutID == NULL) {
301         return -EINVAL;
302     }
303
304     jobject hashMap = env->NewObject(hashMapClazz.get(), hashMapConstructID);
305
306     for (size_t i = 0; i < msg->countEntries(); ++i) {
307         AMessage::Type valueType;
308         const char *key = msg->getEntryNameAt(i, &valueType);
309
310         if (!strncmp(key, "android._", 9)) {
311             // don't expose private keys (starting with android._)
312             continue;
313         }
314
315         jobject valueObj = NULL;
316
317         switch (valueType) {
318             case AMessage::kTypeInt32:
319             {
320                 int32_t val;
321                 CHECK(msg->findInt32(key, &val));
322
323                 valueObj = makeIntegerObject(env, val);
324                 break;
325             }
326
327             case AMessage::kTypeInt64:
328             {
329                 int64_t val;
330                 CHECK(msg->findInt64(key, &val));
331
332                 valueObj = makeLongObject(env, val);
333                 break;
334             }
335
336             case AMessage::kTypeFloat:
337             {
338                 float val;
339                 CHECK(msg->findFloat(key, &val));
340
341                 valueObj = makeFloatObject(env, val);
342                 break;
343             }
344
345             case AMessage::kTypeString:
346             {
347                 AString val;
348                 CHECK(msg->findString(key, &val));
349
350                 valueObj = env->NewStringUTF(val.c_str());
351                 break;
352             }
353
354             case AMessage::kTypeBuffer:
355             {
356                 sp<ABuffer> buffer;
357                 CHECK(msg->findBuffer(key, &buffer));
358
359                 valueObj = makeByteBufferObject(
360                         env, buffer->data(), buffer->size());
361                 break;
362             }
363
364             case AMessage::kTypeRect:
365             {
366                 int32_t left, top, right, bottom;
367                 CHECK(msg->findRect(key, &left, &top, &right, &bottom));
368
369                 SetMapInt32(
370                         env,
371                         hashMap,
372                         hashMapPutID,
373                         AStringPrintf("%s-left", key).c_str(),
374                         left);
375
376                 SetMapInt32(
377                         env,
378                         hashMap,
379                         hashMapPutID,
380                         AStringPrintf("%s-top", key).c_str(),
381                         top);
382
383                 SetMapInt32(
384                         env,
385                         hashMap,
386                         hashMapPutID,
387                         AStringPrintf("%s-right", key).c_str(),
388                         right);
389
390                 SetMapInt32(
391                         env,
392                         hashMap,
393                         hashMapPutID,
394                         AStringPrintf("%s-bottom", key).c_str(),
395                         bottom);
396                 break;
397             }
398
399             default:
400                 break;
401         }
402
403         if (valueObj != NULL) {
404             jstring keyObj = env->NewStringUTF(key);
405
406             env->CallObjectMethod(hashMap, hashMapPutID, keyObj, valueObj);
407
408             env->DeleteLocalRef(keyObj); keyObj = NULL;
409             env->DeleteLocalRef(valueObj); valueObj = NULL;
410         }
411     }
412
413     *map = hashMap;
414
415     return OK;
416 }
417
418 status_t ConvertKeyValueArraysToMessage(
419         JNIEnv *env, jobjectArray keys, jobjectArray values,
420         sp<AMessage> *out) {
421     ScopedLocalRef<jclass> stringClass(env, env->FindClass("java/lang/String"));
422     CHECK(stringClass.get() != NULL);
423     ScopedLocalRef<jclass> integerClass(env, env->FindClass("java/lang/Integer"));
424     CHECK(integerClass.get() != NULL);
425     ScopedLocalRef<jclass> longClass(env, env->FindClass("java/lang/Long"));
426     CHECK(longClass.get() != NULL);
427     ScopedLocalRef<jclass> floatClass(env, env->FindClass("java/lang/Float"));
428     CHECK(floatClass.get() != NULL);
429     ScopedLocalRef<jclass> byteBufClass(env, env->FindClass("java/nio/ByteBuffer"));
430     CHECK(byteBufClass.get() != NULL);
431
432     sp<AMessage> msg = new AMessage;
433
434     jsize numEntries = 0;
435
436     if (keys != NULL) {
437         if (values == NULL) {
438             return -EINVAL;
439         }
440
441         numEntries = env->GetArrayLength(keys);
442
443         if (numEntries != env->GetArrayLength(values)) {
444             return -EINVAL;
445         }
446     } else if (values != NULL) {
447         return -EINVAL;
448     }
449
450     for (jsize i = 0; i < numEntries; ++i) {
451         jobject keyObj = env->GetObjectArrayElement(keys, i);
452
453         if (!env->IsInstanceOf(keyObj, stringClass.get())) {
454             return -EINVAL;
455         }
456
457         const char *tmp = env->GetStringUTFChars((jstring)keyObj, NULL);
458
459         if (tmp == NULL) {
460             return -ENOMEM;
461         }
462
463         AString key = tmp;
464
465         env->ReleaseStringUTFChars((jstring)keyObj, tmp);
466         tmp = NULL;
467
468         if (key.startsWith("android._")) {
469             // don't propagate private keys (starting with android._)
470             continue;
471         }
472
473         jobject valueObj = env->GetObjectArrayElement(values, i);
474
475         if (env->IsInstanceOf(valueObj, stringClass.get())) {
476             const char *value = env->GetStringUTFChars((jstring)valueObj, NULL);
477
478             if (value == NULL) {
479                 return -ENOMEM;
480             }
481
482             msg->setString(key.c_str(), value);
483
484             env->ReleaseStringUTFChars((jstring)valueObj, value);
485             value = NULL;
486         } else if (env->IsInstanceOf(valueObj, integerClass.get())) {
487             jmethodID intValueID =
488                 env->GetMethodID(integerClass.get(), "intValue", "()I");
489             CHECK(intValueID != NULL);
490
491             jint value = env->CallIntMethod(valueObj, intValueID);
492
493             msg->setInt32(key.c_str(), value);
494         } else if (env->IsInstanceOf(valueObj, longClass.get())) {
495             jmethodID longValueID =
496                 env->GetMethodID(longClass.get(), "longValue", "()J");
497             CHECK(longValueID != NULL);
498
499             jlong value = env->CallLongMethod(valueObj, longValueID);
500
501             msg->setInt64(key.c_str(), value);
502         } else if (env->IsInstanceOf(valueObj, floatClass.get())) {
503             jmethodID floatValueID =
504                 env->GetMethodID(floatClass.get(), "floatValue", "()F");
505             CHECK(floatValueID != NULL);
506
507             jfloat value = env->CallFloatMethod(valueObj, floatValueID);
508
509             msg->setFloat(key.c_str(), value);
510         } else if (env->IsInstanceOf(valueObj, byteBufClass.get())) {
511             jmethodID positionID =
512                 env->GetMethodID(byteBufClass.get(), "position", "()I");
513             CHECK(positionID != NULL);
514
515             jmethodID limitID =
516                 env->GetMethodID(byteBufClass.get(), "limit", "()I");
517             CHECK(limitID != NULL);
518
519             jint position = env->CallIntMethod(valueObj, positionID);
520             jint limit = env->CallIntMethod(valueObj, limitID);
521
522             sp<ABuffer> buffer = new ABuffer(limit - position);
523
524             void *data = env->GetDirectBufferAddress(valueObj);
525
526             if (data != NULL) {
527                 memcpy(buffer->data(),
528                        (const uint8_t *)data + position,
529                        buffer->size());
530             } else {
531                 jmethodID arrayID =
532                     env->GetMethodID(byteBufClass.get(), "array", "()[B");
533                 CHECK(arrayID != NULL);
534
535                 jbyteArray byteArray =
536                     (jbyteArray)env->CallObjectMethod(valueObj, arrayID);
537                 CHECK(byteArray != NULL);
538
539                 env->GetByteArrayRegion(
540                         byteArray,
541                         position,
542                         buffer->size(),
543                         (jbyte *)buffer->data());
544
545                 env->DeleteLocalRef(byteArray); byteArray = NULL;
546             }
547
548             msg->setBuffer(key.c_str(), buffer);
549         }
550     }
551
552     *out = msg;
553
554     return OK;
555 }
556
557 // -----------Utility functions used by ImageReader/Writer JNI-----------------
558
559 enum {
560     IMAGE_MAX_NUM_PLANES = 3,
561 };
562
563 bool usingRGBAToJpegOverride(int32_t imageFormat,
564         int32_t containerFormat) {
565     return containerFormat == HAL_PIXEL_FORMAT_BLOB && imageFormat == HAL_PIXEL_FORMAT_RGBA_8888;
566 }
567
568 int32_t applyFormatOverrides(int32_t imageFormat, int32_t containerFormat) {
569     // Using HAL_PIXEL_FORMAT_RGBA_8888 gralloc buffers containing JPEGs to get around SW
570     // write limitations for some platforms (b/17379185).
571     if (usingRGBAToJpegOverride(imageFormat, containerFormat)) {
572         return HAL_PIXEL_FORMAT_BLOB;
573     }
574     return containerFormat;
575 }
576
577 bool isFormatOpaque(int format) {
578     // This is the only opaque format exposed in the ImageFormat public API.
579     // Note that we do support CPU access for HAL_PIXEL_FORMAT_RAW_OPAQUE
580     // (ImageFormat#RAW_PRIVATE) so it doesn't count as opaque here.
581     return format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
582 }
583
584 bool isPossiblyYUV(PixelFormat format) {
585     switch (static_cast<int>(format)) {
586         case HAL_PIXEL_FORMAT_RGBA_8888:
587         case HAL_PIXEL_FORMAT_RGBX_8888:
588         case HAL_PIXEL_FORMAT_RGB_888:
589         case HAL_PIXEL_FORMAT_RGB_565:
590         case HAL_PIXEL_FORMAT_BGRA_8888:
591         case HAL_PIXEL_FORMAT_Y8:
592         case HAL_PIXEL_FORMAT_Y16:
593         case HAL_PIXEL_FORMAT_RAW16:
594         case HAL_PIXEL_FORMAT_RAW10:
595         case HAL_PIXEL_FORMAT_RAW_OPAQUE:
596         case HAL_PIXEL_FORMAT_BLOB:
597         case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
598             return false;
599
600         case HAL_PIXEL_FORMAT_YV12:
601         case HAL_PIXEL_FORMAT_YCbCr_420_888:
602         case HAL_PIXEL_FORMAT_YCrCb_420_SP:
603         default:
604             return true;
605     }
606 }
607
608 uint32_t Image_getJpegSize(LockedImage* buffer, bool usingRGBAOverride) {
609     ALOGV("%s", __FUNCTION__);
610     LOG_ALWAYS_FATAL_IF(buffer == NULL, "Input buffer is NULL!!!");
611     uint32_t size = 0;
612     uint32_t width = buffer->width;
613     uint8_t* jpegBuffer = buffer->data;
614
615     if (usingRGBAOverride) {
616         width = (buffer->width + buffer->stride * (buffer->height - 1)) * 4;
617     }
618
619     // First check for JPEG transport header at the end of the buffer
620     uint8_t* header = jpegBuffer + (width - sizeof(struct camera3_jpeg_blob));
621     struct camera3_jpeg_blob *blob = (struct camera3_jpeg_blob*)(header);
622     if (blob->jpeg_blob_id == CAMERA3_JPEG_BLOB_ID) {
623         size = blob->jpeg_size;
624         ALOGV("%s: Jpeg size = %d", __FUNCTION__, size);
625     }
626
627     // failed to find size, default to whole buffer
628     if (size == 0) {
629         /*
630          * This is a problem because not including the JPEG header
631          * means that in certain rare situations a regular JPEG blob
632          * will be mis-identified as having a header, in which case
633          * we will get a garbage size value.
634          */
635         ALOGW("%s: No JPEG header detected, defaulting to size=width=%d",
636                 __FUNCTION__, width);
637         size = width;
638     }
639
640     return size;
641 }
642
643 status_t getLockedImageInfo(LockedImage* buffer, int idx,
644         int32_t containerFormat, uint8_t **base, uint32_t *size, int *pixelStride, int *rowStride) {
645     ALOGV("%s", __FUNCTION__);
646     LOG_ALWAYS_FATAL_IF(buffer == NULL, "Input buffer is NULL!!!");
647     LOG_ALWAYS_FATAL_IF(base == NULL, "base is NULL!!!");
648     LOG_ALWAYS_FATAL_IF(size == NULL, "size is NULL!!!");
649     LOG_ALWAYS_FATAL_IF(pixelStride == NULL, "pixelStride is NULL!!!");
650     LOG_ALWAYS_FATAL_IF(rowStride == NULL, "rowStride is NULL!!!");
651     LOG_ALWAYS_FATAL_IF((idx >= IMAGE_MAX_NUM_PLANES) || (idx < 0), "idx (%d) is illegal", idx);
652
653     ALOGV("%s: buffer: %p", __FUNCTION__, buffer);
654
655     uint32_t dataSize, ySize, cSize, cStride;
656     uint32_t pStride = 0, rStride = 0;
657     uint8_t *cb, *cr;
658     uint8_t *pData = NULL;
659     int bytesPerPixel = 0;
660
661     dataSize = ySize = cSize = cStride = 0;
662     int32_t fmt = buffer->flexFormat;
663
664     bool usingRGBAOverride = usingRGBAToJpegOverride(fmt, containerFormat);
665     fmt = applyFormatOverrides(fmt, containerFormat);
666     switch (fmt) {
667         case HAL_PIXEL_FORMAT_YCbCr_420_888:
668             pData =
669                 (idx == 0) ?
670                     buffer->data :
671                 (idx == 1) ?
672                     buffer->dataCb :
673                 buffer->dataCr;
674             // only map until last pixel
675             if (idx == 0) {
676                 pStride = 1;
677                 rStride = buffer->stride;
678                 dataSize = buffer->stride * (buffer->height - 1) + buffer->width;
679             } else {
680                 pStride = buffer->chromaStep;
681                 rStride = buffer->chromaStride;
682                 dataSize = buffer->chromaStride * (buffer->height / 2 - 1) +
683                         buffer->chromaStep * (buffer->width / 2 - 1) + 1;
684             }
685             break;
686         // NV21
687         case HAL_PIXEL_FORMAT_YCrCb_420_SP:
688             cr = buffer->data + (buffer->stride * buffer->height);
689             cb = cr + 1;
690             // only map until last pixel
691             ySize = buffer->width * (buffer->height - 1) + buffer->width;
692             cSize = buffer->width * (buffer->height / 2 - 1) + buffer->width - 1;
693
694             pData =
695                 (idx == 0) ?
696                     buffer->data :
697                 (idx == 1) ?
698                     cb:
699                 cr;
700
701             dataSize = (idx == 0) ? ySize : cSize;
702             pStride = (idx == 0) ? 1 : 2;
703             rStride = buffer->width;
704             break;
705         case HAL_PIXEL_FORMAT_YV12:
706             // Y and C stride need to be 16 pixel aligned.
707             LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
708                                 "Stride is not 16 pixel aligned %d", buffer->stride);
709
710             ySize = buffer->stride * buffer->height;
711             cStride = ALIGN(buffer->stride / 2, 16);
712             cr = buffer->data + ySize;
713             cSize = cStride * buffer->height / 2;
714             cb = cr + cSize;
715
716             pData =
717                 (idx == 0) ?
718                     buffer->data :
719                 (idx == 1) ?
720                     cb :
721                 cr;
722             dataSize = (idx == 0) ? ySize : cSize;
723             pStride = 1;
724             rStride = (idx == 0) ? buffer->stride : ALIGN(buffer->stride / 2, 16);
725             break;
726         case HAL_PIXEL_FORMAT_Y8:
727             // Single plane, 8bpp.
728             LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
729
730             pData = buffer->data;
731             dataSize = buffer->stride * buffer->height;
732             pStride = 1;
733             rStride = buffer->stride;
734             break;
735         case HAL_PIXEL_FORMAT_Y16:
736             bytesPerPixel = 2;
737             // Single plane, 16bpp, strides are specified in pixels, not in bytes
738             LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
739
740             pData = buffer->data;
741             dataSize = buffer->stride * buffer->height * bytesPerPixel;
742             pStride = bytesPerPixel;
743             rStride = buffer->stride * 2;
744             break;
745         case HAL_PIXEL_FORMAT_BLOB:
746             // Used for JPEG data, height must be 1, width == size, single plane.
747             LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
748             // When RGBA override is being used, buffer height will be equal to width
749             if (usingRGBAOverride) {
750                 LOG_ALWAYS_FATAL_IF(buffer->height != buffer->width,
751                         "RGBA override BLOB format buffer should have height == width");
752             } else {
753                 LOG_ALWAYS_FATAL_IF(buffer->height != 1,
754                         "BLOB format buffer should have height value 1");
755             }
756
757
758             pData = buffer->data;
759             dataSize = Image_getJpegSize(buffer, usingRGBAOverride);
760             pStride = 0;
761             rStride = 0;
762             break;
763         case HAL_PIXEL_FORMAT_RAW16:
764             // Single plane 16bpp bayer data.
765             bytesPerPixel = 2;
766             LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
767             pData = buffer->data;
768             dataSize = buffer->stride * buffer->height * bytesPerPixel;
769             pStride = bytesPerPixel;
770             rStride = buffer->stride * 2;
771             break;
772         case HAL_PIXEL_FORMAT_RAW_OPAQUE:
773             // Used for RAW_OPAQUE data, height must be 1, width == size, single plane.
774             LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
775             LOG_ALWAYS_FATAL_IF(buffer->height != 1,
776                     "RAW_PRIVATE should has height value one but got %d", buffer->height);
777             pData = buffer->data;
778             dataSize = buffer->width;
779             pStride = 0; // RAW OPAQUE doesn't have pixel stride
780             rStride = 0; // RAW OPAQUE doesn't have row stride
781             break;
782         case HAL_PIXEL_FORMAT_RAW10:
783             // Single plane 10bpp bayer data.
784             LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
785             LOG_ALWAYS_FATAL_IF(buffer->width % 4,
786                                 "Width is not multiple of 4 %d", buffer->width);
787             LOG_ALWAYS_FATAL_IF(buffer->height % 2,
788                                 "Height is not even %d", buffer->height);
789             LOG_ALWAYS_FATAL_IF(buffer->stride < (buffer->width * 10 / 8),
790                                 "stride (%d) should be at least %d",
791                                 buffer->stride, buffer->width * 10 / 8);
792             pData = buffer->data;
793             dataSize = buffer->stride * buffer->height;
794             pStride = 0;
795             rStride = buffer->stride;
796             break;
797         case HAL_PIXEL_FORMAT_RAW12:
798             // Single plane 10bpp bayer data.
799             LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
800             LOG_ALWAYS_FATAL_IF(buffer->width % 4,
801                                 "Width is not multiple of 4 %d", buffer->width);
802             LOG_ALWAYS_FATAL_IF(buffer->height % 2,
803                                 "Height is not even %d", buffer->height);
804             LOG_ALWAYS_FATAL_IF(buffer->stride < (buffer->width * 12 / 8),
805                                 "stride (%d) should be at least %d",
806                                 buffer->stride, buffer->width * 12 / 8);
807             pData = buffer->data;
808             dataSize = buffer->stride * buffer->height;
809             pStride = 0;
810             rStride = buffer->stride;
811             break;
812         case HAL_PIXEL_FORMAT_RGBA_8888:
813         case HAL_PIXEL_FORMAT_RGBX_8888:
814             // Single plane, 32bpp.
815             bytesPerPixel = 4;
816             LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
817             pData = buffer->data;
818             dataSize = buffer->stride * buffer->height * bytesPerPixel;
819             pStride = bytesPerPixel;
820             rStride = buffer->stride * 4;
821             break;
822         case HAL_PIXEL_FORMAT_RGB_565:
823             // Single plane, 16bpp.
824             bytesPerPixel = 2;
825             LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
826             pData = buffer->data;
827             dataSize = buffer->stride * buffer->height * bytesPerPixel;
828             pStride = bytesPerPixel;
829             rStride = buffer->stride * 2;
830             break;
831         case HAL_PIXEL_FORMAT_RGB_888:
832             // Single plane, 24bpp.
833             bytesPerPixel = 3;
834             LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
835             pData = buffer->data;
836             dataSize = buffer->stride * buffer->height * bytesPerPixel;
837             pStride = bytesPerPixel;
838             rStride = buffer->stride * 3;
839             break;
840         default:
841             return BAD_VALUE;
842     }
843
844     *base = pData;
845     *size = dataSize;
846     *pixelStride = pStride;
847     *rowStride = rStride;
848
849     return OK;
850 }
851
852 status_t lockImageFromBuffer(sp<GraphicBuffer> buffer, uint32_t inUsage,
853         const Rect& rect, int fenceFd, LockedImage* outputImage) {
854     ALOGV("%s: Try to lock the GraphicBuffer", __FUNCTION__);
855
856     if (buffer == nullptr || outputImage == nullptr) {
857         ALOGE("Input BufferItem or output LockedImage is NULL!");
858         return BAD_VALUE;
859     }
860     if (isFormatOpaque(buffer->getPixelFormat())) {
861         ALOGE("Opaque format buffer is not lockable!");
862         return BAD_VALUE;
863     }
864
865     void* pData = NULL;
866     android_ycbcr ycbcr = android_ycbcr();
867     status_t res;
868     int format = buffer->getPixelFormat();
869     int flexFormat = format;
870     if (isPossiblyYUV(format)) {
871         res = buffer->lockAsyncYCbCr(inUsage, rect, &ycbcr, fenceFd);
872         pData = ycbcr.y;
873         flexFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
874     }
875
876     // lockAsyncYCbCr for YUV is unsuccessful.
877     if (pData == NULL) {
878         res = buffer->lockAsync(inUsage, rect, &pData, fenceFd);
879         if (res != OK) {
880             ALOGE("Lock buffer failed!");
881             return res;
882         }
883     }
884
885     outputImage->data = reinterpret_cast<uint8_t*>(pData);
886     outputImage->width = buffer->getWidth();
887     outputImage->height = buffer->getHeight();
888     outputImage->format = format;
889     outputImage->flexFormat = flexFormat;
890     outputImage->stride =
891             (ycbcr.y != NULL) ? static_cast<uint32_t>(ycbcr.ystride) : buffer->getStride();
892
893     outputImage->dataCb = reinterpret_cast<uint8_t*>(ycbcr.cb);
894     outputImage->dataCr = reinterpret_cast<uint8_t*>(ycbcr.cr);
895     outputImage->chromaStride = static_cast<uint32_t>(ycbcr.cstride);
896     outputImage->chromaStep = static_cast<uint32_t>(ycbcr.chroma_step);
897     ALOGV("%s: Successfully locked the image from the GraphicBuffer", __FUNCTION__);
898     // Crop, transform, scalingMode, timestamp, and frameNumber should be set by caller,
899     // and cann't be set them here.
900     return OK;
901 }
902
903 status_t lockImageFromBuffer(BufferItem* bufferItem, uint32_t inUsage,
904         int fenceFd, LockedImage* outputImage) {
905     ALOGV("%s: Try to lock the BufferItem", __FUNCTION__);
906     if (bufferItem == nullptr || outputImage == nullptr) {
907         ALOGE("Input BufferItem or output LockedImage is NULL!");
908         return BAD_VALUE;
909     }
910
911     status_t res = lockImageFromBuffer(bufferItem->mGraphicBuffer, inUsage, bufferItem->mCrop,
912             fenceFd, outputImage);
913     if (res != OK) {
914         ALOGE("%s: lock graphic buffer failed", __FUNCTION__);
915         return res;
916     }
917
918     outputImage->crop        = bufferItem->mCrop;
919     outputImage->transform   = bufferItem->mTransform;
920     outputImage->scalingMode = bufferItem->mScalingMode;
921     outputImage->timestamp   = bufferItem->mTimestamp;
922     outputImage->dataSpace   = bufferItem->mDataSpace;
923     outputImage->frameNumber = bufferItem->mFrameNumber;
924     ALOGV("%s: Successfully locked the image from the BufferItem", __FUNCTION__);
925     return OK;
926 }
927
928 int getBufferWidth(BufferItem* buffer) {
929     if (buffer == NULL) return -1;
930
931     if (!buffer->mCrop.isEmpty()) {
932         return buffer->mCrop.getWidth();
933     }
934
935     ALOGV("%s: buffer->mGraphicBuffer: %p", __FUNCTION__, buffer->mGraphicBuffer.get());
936     return buffer->mGraphicBuffer->getWidth();
937 }
938
939 int getBufferHeight(BufferItem* buffer) {
940     if (buffer == NULL) return -1;
941
942     if (!buffer->mCrop.isEmpty()) {
943         return buffer->mCrop.getHeight();
944     }
945
946     ALOGV("%s: buffer->mGraphicBuffer: %p", __FUNCTION__, buffer->mGraphicBuffer.get());
947     return buffer->mGraphicBuffer->getHeight();
948 }
949
950 }  // namespace android
951