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