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