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