android_media_Utils.cpp revision 2584cda885964370f612a2b9251f7d6cf9ebf29a
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), mPosition(0) { 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 = offset + 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 if (!strncmp(key, "android._", 9)) { 311 // don't expose private keys (starting with android._) 312 continue; 313 } 314 315 jobject valueObj = NULL; 316 317 switch (valueType) { 318 case AMessage::kTypeInt32: 319 { 320 int32_t val; 321 CHECK(msg->findInt32(key, &val)); 322 323 valueObj = makeIntegerObject(env, val); 324 break; 325 } 326 327 case AMessage::kTypeInt64: 328 { 329 int64_t val; 330 CHECK(msg->findInt64(key, &val)); 331 332 valueObj = makeLongObject(env, val); 333 break; 334 } 335 336 case AMessage::kTypeFloat: 337 { 338 float val; 339 CHECK(msg->findFloat(key, &val)); 340 341 valueObj = makeFloatObject(env, val); 342 break; 343 } 344 345 case AMessage::kTypeString: 346 { 347 AString val; 348 CHECK(msg->findString(key, &val)); 349 350 valueObj = env->NewStringUTF(val.c_str()); 351 break; 352 } 353 354 case AMessage::kTypeBuffer: 355 { 356 sp<ABuffer> buffer; 357 CHECK(msg->findBuffer(key, &buffer)); 358 359 valueObj = makeByteBufferObject( 360 env, buffer->data(), buffer->size()); 361 break; 362 } 363 364 case AMessage::kTypeRect: 365 { 366 int32_t left, top, right, bottom; 367 CHECK(msg->findRect(key, &left, &top, &right, &bottom)); 368 369 SetMapInt32( 370 env, 371 hashMap, 372 hashMapPutID, 373 AStringPrintf("%s-left", key).c_str(), 374 left); 375 376 SetMapInt32( 377 env, 378 hashMap, 379 hashMapPutID, 380 AStringPrintf("%s-top", key).c_str(), 381 top); 382 383 SetMapInt32( 384 env, 385 hashMap, 386 hashMapPutID, 387 AStringPrintf("%s-right", key).c_str(), 388 right); 389 390 SetMapInt32( 391 env, 392 hashMap, 393 hashMapPutID, 394 AStringPrintf("%s-bottom", key).c_str(), 395 bottom); 396 break; 397 } 398 399 default: 400 break; 401 } 402 403 if (valueObj != NULL) { 404 jstring keyObj = env->NewStringUTF(key); 405 406 env->CallObjectMethod(hashMap, hashMapPutID, keyObj, valueObj); 407 408 env->DeleteLocalRef(keyObj); keyObj = NULL; 409 env->DeleteLocalRef(valueObj); valueObj = NULL; 410 } 411 } 412 413 *map = hashMap; 414 415 return OK; 416} 417 418status_t ConvertKeyValueArraysToMessage( 419 JNIEnv *env, jobjectArray keys, jobjectArray values, 420 sp<AMessage> *out) { 421 ScopedLocalRef<jclass> stringClass(env, env->FindClass("java/lang/String")); 422 CHECK(stringClass.get() != NULL); 423 ScopedLocalRef<jclass> integerClass(env, env->FindClass("java/lang/Integer")); 424 CHECK(integerClass.get() != NULL); 425 ScopedLocalRef<jclass> longClass(env, env->FindClass("java/lang/Long")); 426 CHECK(longClass.get() != NULL); 427 ScopedLocalRef<jclass> floatClass(env, env->FindClass("java/lang/Float")); 428 CHECK(floatClass.get() != NULL); 429 ScopedLocalRef<jclass> byteBufClass(env, env->FindClass("java/nio/ByteBuffer")); 430 CHECK(byteBufClass.get() != NULL); 431 432 sp<AMessage> msg = new AMessage; 433 434 jsize numEntries = 0; 435 436 if (keys != NULL) { 437 if (values == NULL) { 438 return -EINVAL; 439 } 440 441 numEntries = env->GetArrayLength(keys); 442 443 if (numEntries != env->GetArrayLength(values)) { 444 return -EINVAL; 445 } 446 } else if (values != NULL) { 447 return -EINVAL; 448 } 449 450 for (jsize i = 0; i < numEntries; ++i) { 451 jobject keyObj = env->GetObjectArrayElement(keys, i); 452 453 if (!env->IsInstanceOf(keyObj, stringClass.get())) { 454 return -EINVAL; 455 } 456 457 const char *tmp = env->GetStringUTFChars((jstring)keyObj, NULL); 458 459 if (tmp == NULL) { 460 return -ENOMEM; 461 } 462 463 AString key = tmp; 464 465 env->ReleaseStringUTFChars((jstring)keyObj, tmp); 466 tmp = NULL; 467 468 if (key.startsWith("android._")) { 469 // don't propagate private keys (starting with android._) 470 continue; 471 } 472 473 jobject valueObj = env->GetObjectArrayElement(values, i); 474 475 if (env->IsInstanceOf(valueObj, stringClass.get())) { 476 const char *value = env->GetStringUTFChars((jstring)valueObj, NULL); 477 478 if (value == NULL) { 479 return -ENOMEM; 480 } 481 482 msg->setString(key.c_str(), value); 483 484 env->ReleaseStringUTFChars((jstring)valueObj, value); 485 value = NULL; 486 } else if (env->IsInstanceOf(valueObj, integerClass.get())) { 487 jmethodID intValueID = 488 env->GetMethodID(integerClass.get(), "intValue", "()I"); 489 CHECK(intValueID != NULL); 490 491 jint value = env->CallIntMethod(valueObj, intValueID); 492 493 msg->setInt32(key.c_str(), value); 494 } else if (env->IsInstanceOf(valueObj, longClass.get())) { 495 jmethodID longValueID = 496 env->GetMethodID(longClass.get(), "longValue", "()J"); 497 CHECK(longValueID != NULL); 498 499 jlong value = env->CallLongMethod(valueObj, longValueID); 500 501 msg->setInt64(key.c_str(), value); 502 } else if (env->IsInstanceOf(valueObj, floatClass.get())) { 503 jmethodID floatValueID = 504 env->GetMethodID(floatClass.get(), "floatValue", "()F"); 505 CHECK(floatValueID != NULL); 506 507 jfloat value = env->CallFloatMethod(valueObj, floatValueID); 508 509 msg->setFloat(key.c_str(), value); 510 } else if (env->IsInstanceOf(valueObj, byteBufClass.get())) { 511 jmethodID positionID = 512 env->GetMethodID(byteBufClass.get(), "position", "()I"); 513 CHECK(positionID != NULL); 514 515 jmethodID limitID = 516 env->GetMethodID(byteBufClass.get(), "limit", "()I"); 517 CHECK(limitID != NULL); 518 519 jint position = env->CallIntMethod(valueObj, positionID); 520 jint limit = env->CallIntMethod(valueObj, limitID); 521 522 sp<ABuffer> buffer = new ABuffer(limit - position); 523 524 void *data = env->GetDirectBufferAddress(valueObj); 525 526 if (data != NULL) { 527 memcpy(buffer->data(), 528 (const uint8_t *)data + position, 529 buffer->size()); 530 } else { 531 jmethodID arrayID = 532 env->GetMethodID(byteBufClass.get(), "array", "()[B"); 533 CHECK(arrayID != NULL); 534 535 jbyteArray byteArray = 536 (jbyteArray)env->CallObjectMethod(valueObj, arrayID); 537 CHECK(byteArray != NULL); 538 539 env->GetByteArrayRegion( 540 byteArray, 541 position, 542 buffer->size(), 543 (jbyte *)buffer->data()); 544 545 env->DeleteLocalRef(byteArray); byteArray = NULL; 546 } 547 548 msg->setBuffer(key.c_str(), buffer); 549 } 550 } 551 552 *out = msg; 553 554 return OK; 555} 556 557// -----------Utility functions used by ImageReader/Writer JNI----------------- 558 559enum { 560 IMAGE_MAX_NUM_PLANES = 3, 561}; 562 563bool usingRGBAToJpegOverride(int32_t imageFormat, 564 int32_t containerFormat) { 565 return containerFormat == HAL_PIXEL_FORMAT_BLOB && imageFormat == HAL_PIXEL_FORMAT_RGBA_8888; 566} 567 568int32_t applyFormatOverrides(int32_t imageFormat, int32_t containerFormat) { 569 // Using HAL_PIXEL_FORMAT_RGBA_8888 gralloc buffers containing JPEGs to get around SW 570 // write limitations for some platforms (b/17379185). 571 if (usingRGBAToJpegOverride(imageFormat, containerFormat)) { 572 return HAL_PIXEL_FORMAT_BLOB; 573 } 574 return containerFormat; 575} 576 577bool isFormatOpaque(int format) { 578 // This is the only opaque format exposed in the ImageFormat public API. 579 // Note that we do support CPU access for HAL_PIXEL_FORMAT_RAW_OPAQUE 580 // (ImageFormat#RAW_PRIVATE) so it doesn't count as opaque here. 581 return format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED; 582} 583 584bool isPossiblyYUV(PixelFormat format) { 585 switch (static_cast<int>(format)) { 586 case HAL_PIXEL_FORMAT_RGBA_8888: 587 case HAL_PIXEL_FORMAT_RGBX_8888: 588 case HAL_PIXEL_FORMAT_RGB_888: 589 case HAL_PIXEL_FORMAT_RGB_565: 590 case HAL_PIXEL_FORMAT_BGRA_8888: 591 case HAL_PIXEL_FORMAT_Y8: 592 case HAL_PIXEL_FORMAT_Y16: 593 case HAL_PIXEL_FORMAT_RAW16: 594 case HAL_PIXEL_FORMAT_RAW10: 595 case HAL_PIXEL_FORMAT_RAW_OPAQUE: 596 case HAL_PIXEL_FORMAT_BLOB: 597 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED: 598 return false; 599 600 case HAL_PIXEL_FORMAT_YV12: 601 case HAL_PIXEL_FORMAT_YCbCr_420_888: 602 case HAL_PIXEL_FORMAT_YCrCb_420_SP: 603 default: 604 return true; 605 } 606} 607 608uint32_t Image_getJpegSize(LockedImage* buffer, bool usingRGBAOverride) { 609 ALOGV("%s", __FUNCTION__); 610 LOG_ALWAYS_FATAL_IF(buffer == NULL, "Input buffer is NULL!!!"); 611 uint32_t size = 0; 612 uint32_t width = buffer->width; 613 uint8_t* jpegBuffer = buffer->data; 614 615 if (usingRGBAOverride) { 616 width = (buffer->width + buffer->stride * (buffer->height - 1)) * 4; 617 } 618 619 // First check for JPEG transport header at the end of the buffer 620 uint8_t* header = jpegBuffer + (width - sizeof(struct camera3_jpeg_blob)); 621 struct camera3_jpeg_blob *blob = (struct camera3_jpeg_blob*)(header); 622 if (blob->jpeg_blob_id == CAMERA3_JPEG_BLOB_ID) { 623 size = blob->jpeg_size; 624 ALOGV("%s: Jpeg size = %d", __FUNCTION__, size); 625 } 626 627 // failed to find size, default to whole buffer 628 if (size == 0) { 629 /* 630 * This is a problem because not including the JPEG header 631 * means that in certain rare situations a regular JPEG blob 632 * will be mis-identified as having a header, in which case 633 * we will get a garbage size value. 634 */ 635 ALOGW("%s: No JPEG header detected, defaulting to size=width=%d", 636 __FUNCTION__, width); 637 size = width; 638 } 639 640 return size; 641} 642 643status_t getLockedImageInfo(LockedImage* buffer, int idx, 644 int32_t containerFormat, uint8_t **base, uint32_t *size, int *pixelStride, int *rowStride) { 645 ALOGV("%s", __FUNCTION__); 646 LOG_ALWAYS_FATAL_IF(buffer == NULL, "Input buffer is NULL!!!"); 647 LOG_ALWAYS_FATAL_IF(base == NULL, "base is NULL!!!"); 648 LOG_ALWAYS_FATAL_IF(size == NULL, "size is NULL!!!"); 649 LOG_ALWAYS_FATAL_IF(pixelStride == NULL, "pixelStride is NULL!!!"); 650 LOG_ALWAYS_FATAL_IF(rowStride == NULL, "rowStride is NULL!!!"); 651 LOG_ALWAYS_FATAL_IF((idx >= IMAGE_MAX_NUM_PLANES) || (idx < 0), "idx (%d) is illegal", idx); 652 653 ALOGV("%s: buffer: %p", __FUNCTION__, buffer); 654 655 uint32_t dataSize, ySize, cSize, cStride; 656 uint32_t pStride = 0, rStride = 0; 657 uint8_t *cb, *cr; 658 uint8_t *pData = NULL; 659 int bytesPerPixel = 0; 660 661 dataSize = ySize = cSize = cStride = 0; 662 int32_t fmt = buffer->flexFormat; 663 664 bool usingRGBAOverride = usingRGBAToJpegOverride(fmt, containerFormat); 665 fmt = applyFormatOverrides(fmt, containerFormat); 666 switch (fmt) { 667 case HAL_PIXEL_FORMAT_YCbCr_420_888: 668 pData = 669 (idx == 0) ? 670 buffer->data : 671 (idx == 1) ? 672 buffer->dataCb : 673 buffer->dataCr; 674 // only map until last pixel 675 if (idx == 0) { 676 pStride = 1; 677 rStride = buffer->stride; 678 dataSize = buffer->stride * (buffer->height - 1) + buffer->width; 679 } else { 680 pStride = buffer->chromaStep; 681 rStride = buffer->chromaStride; 682 dataSize = buffer->chromaStride * (buffer->height / 2 - 1) + 683 buffer->chromaStep * (buffer->width / 2 - 1) + 1; 684 } 685 break; 686 // NV21 687 case HAL_PIXEL_FORMAT_YCrCb_420_SP: 688 cr = buffer->data + (buffer->stride * buffer->height); 689 cb = cr + 1; 690 // only map until last pixel 691 ySize = buffer->width * (buffer->height - 1) + buffer->width; 692 cSize = buffer->width * (buffer->height / 2 - 1) + buffer->width - 1; 693 694 pData = 695 (idx == 0) ? 696 buffer->data : 697 (idx == 1) ? 698 cb: 699 cr; 700 701 dataSize = (idx == 0) ? ySize : cSize; 702 pStride = (idx == 0) ? 1 : 2; 703 rStride = buffer->width; 704 break; 705 case HAL_PIXEL_FORMAT_YV12: 706 // Y and C stride need to be 16 pixel aligned. 707 LOG_ALWAYS_FATAL_IF(buffer->stride % 16, 708 "Stride is not 16 pixel aligned %d", buffer->stride); 709 710 ySize = buffer->stride * buffer->height; 711 cStride = ALIGN(buffer->stride / 2, 16); 712 cr = buffer->data + ySize; 713 cSize = cStride * buffer->height / 2; 714 cb = cr + cSize; 715 716 pData = 717 (idx == 0) ? 718 buffer->data : 719 (idx == 1) ? 720 cb : 721 cr; 722 dataSize = (idx == 0) ? ySize : cSize; 723 pStride = 1; 724 rStride = (idx == 0) ? buffer->stride : ALIGN(buffer->stride / 2, 16); 725 break; 726 case HAL_PIXEL_FORMAT_Y8: 727 // Single plane, 8bpp. 728 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx); 729 730 pData = buffer->data; 731 dataSize = buffer->stride * buffer->height; 732 pStride = 1; 733 rStride = buffer->stride; 734 break; 735 case HAL_PIXEL_FORMAT_Y16: 736 bytesPerPixel = 2; 737 // Single plane, 16bpp, strides are specified in pixels, not in bytes 738 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx); 739 740 pData = buffer->data; 741 dataSize = buffer->stride * buffer->height * bytesPerPixel; 742 pStride = bytesPerPixel; 743 rStride = buffer->stride * 2; 744 break; 745 case HAL_PIXEL_FORMAT_BLOB: 746 // Used for JPEG data, height must be 1, width == size, single plane. 747 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx); 748 // When RGBA override is being used, buffer height will be equal to width 749 if (usingRGBAOverride) { 750 LOG_ALWAYS_FATAL_IF(buffer->height != buffer->width, 751 "RGBA override BLOB format buffer should have height == width"); 752 } else { 753 LOG_ALWAYS_FATAL_IF(buffer->height != 1, 754 "BLOB format buffer should have height value 1"); 755 } 756 757 758 pData = buffer->data; 759 dataSize = Image_getJpegSize(buffer, usingRGBAOverride); 760 pStride = 0; 761 rStride = 0; 762 break; 763 case HAL_PIXEL_FORMAT_RAW16: 764 // Single plane 16bpp bayer data. 765 bytesPerPixel = 2; 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 * 2; 771 break; 772 case HAL_PIXEL_FORMAT_RAW_OPAQUE: 773 // Used for RAW_OPAQUE data, height must be 1, width == size, single plane. 774 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx); 775 LOG_ALWAYS_FATAL_IF(buffer->height != 1, 776 "RAW_PRIVATE should has height value one but got %d", buffer->height); 777 pData = buffer->data; 778 dataSize = buffer->width; 779 pStride = 0; // RAW OPAQUE doesn't have pixel stride 780 rStride = 0; // RAW OPAQUE doesn't have row stride 781 break; 782 case HAL_PIXEL_FORMAT_RAW10: 783 // Single plane 10bpp bayer data. 784 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx); 785 LOG_ALWAYS_FATAL_IF(buffer->width % 4, 786 "Width is not multiple of 4 %d", buffer->width); 787 LOG_ALWAYS_FATAL_IF(buffer->height % 2, 788 "Height is not even %d", buffer->height); 789 LOG_ALWAYS_FATAL_IF(buffer->stride < (buffer->width * 10 / 8), 790 "stride (%d) should be at least %d", 791 buffer->stride, buffer->width * 10 / 8); 792 pData = buffer->data; 793 dataSize = buffer->stride * buffer->height; 794 pStride = 0; 795 rStride = buffer->stride; 796 break; 797 case HAL_PIXEL_FORMAT_RAW12: 798 // Single plane 10bpp bayer data. 799 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx); 800 LOG_ALWAYS_FATAL_IF(buffer->width % 4, 801 "Width is not multiple of 4 %d", buffer->width); 802 LOG_ALWAYS_FATAL_IF(buffer->height % 2, 803 "Height is not even %d", buffer->height); 804 LOG_ALWAYS_FATAL_IF(buffer->stride < (buffer->width * 12 / 8), 805 "stride (%d) should be at least %d", 806 buffer->stride, buffer->width * 12 / 8); 807 pData = buffer->data; 808 dataSize = buffer->stride * buffer->height; 809 pStride = 0; 810 rStride = buffer->stride; 811 break; 812 case HAL_PIXEL_FORMAT_RGBA_8888: 813 case HAL_PIXEL_FORMAT_RGBX_8888: 814 // Single plane, 32bpp. 815 bytesPerPixel = 4; 816 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx); 817 pData = buffer->data; 818 dataSize = buffer->stride * buffer->height * bytesPerPixel; 819 pStride = bytesPerPixel; 820 rStride = buffer->stride * 4; 821 break; 822 case HAL_PIXEL_FORMAT_RGB_565: 823 // Single plane, 16bpp. 824 bytesPerPixel = 2; 825 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx); 826 pData = buffer->data; 827 dataSize = buffer->stride * buffer->height * bytesPerPixel; 828 pStride = bytesPerPixel; 829 rStride = buffer->stride * 2; 830 break; 831 case HAL_PIXEL_FORMAT_RGB_888: 832 // Single plane, 24bpp. 833 bytesPerPixel = 3; 834 LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx); 835 pData = buffer->data; 836 dataSize = buffer->stride * buffer->height * bytesPerPixel; 837 pStride = bytesPerPixel; 838 rStride = buffer->stride * 3; 839 break; 840 default: 841 return BAD_VALUE; 842 } 843 844 *base = pData; 845 *size = dataSize; 846 *pixelStride = pStride; 847 *rowStride = rStride; 848 849 return OK; 850} 851 852status_t lockImageFromBuffer(sp<GraphicBuffer> buffer, uint32_t inUsage, 853 const Rect& rect, int fenceFd, LockedImage* outputImage) { 854 ALOGV("%s: Try to lock the GraphicBuffer", __FUNCTION__); 855 856 if (buffer == nullptr || outputImage == nullptr) { 857 ALOGE("Input BufferItem or output LockedImage is NULL!"); 858 return BAD_VALUE; 859 } 860 if (isFormatOpaque(buffer->getPixelFormat())) { 861 ALOGE("Opaque format buffer is not lockable!"); 862 return BAD_VALUE; 863 } 864 865 void* pData = NULL; 866 android_ycbcr ycbcr = android_ycbcr(); 867 status_t res; 868 int format = buffer->getPixelFormat(); 869 int flexFormat = format; 870 if (isPossiblyYUV(format)) { 871 res = buffer->lockAsyncYCbCr(inUsage, rect, &ycbcr, fenceFd); 872 pData = ycbcr.y; 873 flexFormat = HAL_PIXEL_FORMAT_YCbCr_420_888; 874 } 875 876 // lockAsyncYCbCr for YUV is unsuccessful. 877 if (pData == NULL) { 878 res = buffer->lockAsync(inUsage, rect, &pData, fenceFd); 879 if (res != OK) { 880 ALOGE("Lock buffer failed!"); 881 return res; 882 } 883 } 884 885 outputImage->data = reinterpret_cast<uint8_t*>(pData); 886 outputImage->width = buffer->getWidth(); 887 outputImage->height = buffer->getHeight(); 888 outputImage->format = format; 889 outputImage->flexFormat = flexFormat; 890 outputImage->stride = 891 (ycbcr.y != NULL) ? static_cast<uint32_t>(ycbcr.ystride) : buffer->getStride(); 892 893 outputImage->dataCb = reinterpret_cast<uint8_t*>(ycbcr.cb); 894 outputImage->dataCr = reinterpret_cast<uint8_t*>(ycbcr.cr); 895 outputImage->chromaStride = static_cast<uint32_t>(ycbcr.cstride); 896 outputImage->chromaStep = static_cast<uint32_t>(ycbcr.chroma_step); 897 ALOGV("%s: Successfully locked the image from the GraphicBuffer", __FUNCTION__); 898 // Crop, transform, scalingMode, timestamp, and frameNumber should be set by caller, 899 // and cann't be set them here. 900 return OK; 901} 902 903status_t lockImageFromBuffer(BufferItem* bufferItem, uint32_t inUsage, 904 int fenceFd, LockedImage* outputImage) { 905 ALOGV("%s: Try to lock the BufferItem", __FUNCTION__); 906 if (bufferItem == nullptr || outputImage == nullptr) { 907 ALOGE("Input BufferItem or output LockedImage is NULL!"); 908 return BAD_VALUE; 909 } 910 911 status_t res = lockImageFromBuffer(bufferItem->mGraphicBuffer, inUsage, bufferItem->mCrop, 912 fenceFd, outputImage); 913 if (res != OK) { 914 ALOGE("%s: lock graphic buffer failed", __FUNCTION__); 915 return res; 916 } 917 918 outputImage->crop = bufferItem->mCrop; 919 outputImage->transform = bufferItem->mTransform; 920 outputImage->scalingMode = bufferItem->mScalingMode; 921 outputImage->timestamp = bufferItem->mTimestamp; 922 outputImage->dataSpace = bufferItem->mDataSpace; 923 outputImage->frameNumber = bufferItem->mFrameNumber; 924 ALOGV("%s: Successfully locked the image from the BufferItem", __FUNCTION__); 925 return OK; 926} 927 928int getBufferWidth(BufferItem* buffer) { 929 if (buffer == NULL) return -1; 930 931 if (!buffer->mCrop.isEmpty()) { 932 return buffer->mCrop.getWidth(); 933 } 934 935 ALOGV("%s: buffer->mGraphicBuffer: %p", __FUNCTION__, buffer->mGraphicBuffer.get()); 936 return buffer->mGraphicBuffer->getWidth(); 937} 938 939int getBufferHeight(BufferItem* buffer) { 940 if (buffer == NULL) return -1; 941 942 if (!buffer->mCrop.isEmpty()) { 943 return buffer->mCrop.getHeight(); 944 } 945 946 ALOGV("%s: buffer->mGraphicBuffer: %p", __FUNCTION__, buffer->mGraphicBuffer.get()); 947 return buffer->mGraphicBuffer->getHeight(); 948} 949 950} // namespace android 951 952