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