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