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 34 AssetStream::AssetStream(SkStream* stream) 35 : mStream(stream), mPosition(0) { 36 } 37 38 AssetStream::~AssetStream() { 39 } 40 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 57 BufferedStream::BufferedStream(SkStream* stream) 58 : mStream(stream) { 59 } 60 61 BufferedStream::~BufferedStream() { 62 } 63 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 95 FileStream::FileStream(const int fd) 96 : mPosition(0) { 97 mFile = fdopen(fd, "r"); 98 if (mFile == NULL) { 99 return; 100 } 101 } 102 103 FileStream::FileStream(const String8 filename) 104 : mPosition(0) { 105 mFile = fopen(filename.string(), "r"); 106 if (mFile == NULL) { 107 return; 108 } 109 } 110 111 FileStream::~FileStream() { 112 if (mFile != NULL) { 113 fclose(mFile); 114 mFile = NULL; 115 } 116 } 117 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 141 bool FileStream::exists() const { 142 return mFile != NULL; 143 } 144 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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