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