1ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala/* 2ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala * Copyright (C) 2012 The Android Open Source Project 3ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala * 4ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala * Licensed under the Apache License, Version 2.0 (the "License"); 5ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala * you may not use this file except in compliance with the License. 6ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala * You may obtain a copy of the License at 7ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala * 8ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala * http://www.apache.org/licenses/LICENSE-2.0 9ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala * 10ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala * Unless required by applicable law or agreed to in writing, software 11ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala * distributed under the License is distributed on an "AS IS" BASIS, 12ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala * See the License for the specific language governing permissions and 14ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala * limitations under the License. 15ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala */ 16ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 174bb8118816874c696d9f1adab48490df1da365f7Eino-Ville Talvala#define LOG_TAG "Camera2-JpegProcessor" 18ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala#define ATRACE_TAG ATRACE_TAG_CAMERA 19ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala//#define LOG_NDEBUG 0 20ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 21a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray#include <netinet/in.h> 22a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray 2373bbd1f1c493835f191ea2b0b72439292496b40aEino-Ville Talvala#include <binder/MemoryBase.h> 2473bbd1f1c493835f191ea2b0b72439292496b40aEino-Ville Talvala#include <binder/MemoryHeapBase.h> 25ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala#include <utils/Log.h> 26ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala#include <utils/Trace.h> 271a2952aee048ca7b1765e2bc09ebe9aeddaeafa3Mathias Agopian#include <gui/Surface.h> 28ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 297b82efe7a376c882f8f938e1c41b8311a8cdda4aEino-Ville Talvala#include "common/CameraDeviceBase.h" 307b82efe7a376c882f8f938e1c41b8311a8cdda4aEino-Ville Talvala#include "api1/Camera2Client.h" 317b82efe7a376c882f8f938e1c41b8311a8cdda4aEino-Ville Talvala#include "api1/client2/Camera2Heap.h" 327b82efe7a376c882f8f938e1c41b8311a8cdda4aEino-Ville Talvala#include "api1/client2/CaptureSequencer.h" 337b82efe7a376c882f8f938e1c41b8311a8cdda4aEino-Ville Talvala#include "api1/client2/JpegProcessor.h" 34ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 35ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvalanamespace android { 36ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvalanamespace camera2 { 37ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 38da6665cbd06ca58d3357c3002b7366d13e23f152Eino-Ville TalvalaJpegProcessor::JpegProcessor( 39d09801b99503b57c35e321ad9afa7e861e012813Eino-Ville Talvala sp<Camera2Client> client, 40da6665cbd06ca58d3357c3002b7366d13e23f152Eino-Ville Talvala wp<CaptureSequencer> sequencer): 41ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala Thread(false), 42d09801b99503b57c35e321ad9afa7e861e012813Eino-Ville Talvala mDevice(client->getCameraDevice()), 43da6665cbd06ca58d3357c3002b7366d13e23f152Eino-Ville Talvala mSequencer(sequencer), 44d09801b99503b57c35e321ad9afa7e861e012813Eino-Ville Talvala mId(client->getCameraId()), 45b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang mCaptureDone(false), 46b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang mCaptureSuccess(false), 47ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala mCaptureStreamId(NO_STREAM) { 48ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala} 49ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 50da6665cbd06ca58d3357c3002b7366d13e23f152Eino-Ville TalvalaJpegProcessor::~JpegProcessor() { 51ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala ALOGV("%s: Exit", __FUNCTION__); 52cf70d3469332445dc3ffd09729da3538612b1bb2Eino-Ville Talvala deleteStream(); 53ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala} 54ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 5504f101c35eaa90b1f95939afac30674ec1611e6fDan Stozavoid JpegProcessor::onFrameAvailable(const BufferItem& /*item*/) { 56ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala Mutex::Autolock l(mInputMutex); 57b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang ALOGV("%s", __FUNCTION__); 58b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang if (!mCaptureDone) { 59b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang mCaptureDone = true; 60b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang mCaptureSuccess = true; 61b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang mCaptureDoneSignal.signal(); 62b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang } 63b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang} 64b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang 65b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wangvoid JpegProcessor::onBufferAcquired(const BufferInfo& /*bufferInfo*/) { 66b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang // Intentionally left empty 67b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang} 68b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang 69b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wangvoid JpegProcessor::onBufferReleased(const BufferInfo& bufferInfo) { 70b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang ALOGV("%s", __FUNCTION__); 71b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang if (bufferInfo.mError) { 728e73af9bcea96bc90afa7451c6014333fc51b655Eino-Ville Talvala // Only lock in case of error, since we get one of these for each 738e73af9bcea96bc90afa7451c6014333fc51b655Eino-Ville Talvala // onFrameAvailable as well, and scheduling may delay this call late 748e73af9bcea96bc90afa7451c6014333fc51b655Eino-Ville Talvala // enough to run into later preview restart operations, for non-error 758e73af9bcea96bc90afa7451c6014333fc51b655Eino-Ville Talvala // cases. 768e73af9bcea96bc90afa7451c6014333fc51b655Eino-Ville Talvala // b/29524651 778e73af9bcea96bc90afa7451c6014333fc51b655Eino-Ville Talvala ALOGV("%s: JPEG buffer lost", __FUNCTION__); 788e73af9bcea96bc90afa7451c6014333fc51b655Eino-Ville Talvala Mutex::Autolock l(mInputMutex); 79b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang mCaptureDone = true; 80b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang mCaptureSuccess = false; 81b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang mCaptureDoneSignal.signal(); 82ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala } 83ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala} 84ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 85da6665cbd06ca58d3357c3002b7366d13e23f152Eino-Ville Talvalastatus_t JpegProcessor::updateStream(const Parameters ¶ms) { 86ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala ATRACE_CALL(); 87ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala ALOGV("%s", __FUNCTION__); 88ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala status_t res; 89ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 90ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala Mutex::Autolock l(mInputMutex); 91ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 92d09801b99503b57c35e321ad9afa7e861e012813Eino-Ville Talvala sp<CameraDeviceBase> device = mDevice.promote(); 93d09801b99503b57c35e321ad9afa7e861e012813Eino-Ville Talvala if (device == 0) { 94d09801b99503b57c35e321ad9afa7e861e012813Eino-Ville Talvala ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId); 95d09801b99503b57c35e321ad9afa7e861e012813Eino-Ville Talvala return INVALID_OPERATION; 96d09801b99503b57c35e321ad9afa7e861e012813Eino-Ville Talvala } 97ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 98ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala // Find out buffer size for JPEG 9928c9b6f298134624cb52b1af4ed8716dddb983d3Zhijun He ssize_t maxJpegSize = device->getJpegBufferSize(params.pictureWidth, params.pictureHeight); 10028c9b6f298134624cb52b1af4ed8716dddb983d3Zhijun He if (maxJpegSize <= 0) { 10128c9b6f298134624cb52b1af4ed8716dddb983d3Zhijun He ALOGE("%s: Camera %d: Jpeg buffer size (%zu) is invalid ", 10228c9b6f298134624cb52b1af4ed8716dddb983d3Zhijun He __FUNCTION__, mId, maxJpegSize); 103ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala return INVALID_OPERATION; 104ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala } 105ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 106ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala if (mCaptureConsumer == 0) { 107ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala // Create CPU buffer queue endpoint 1088aa0f0619ea867e8fb240cf27913d4f8ae767385Dan Stoza sp<IGraphicBufferProducer> producer; 1098aa0f0619ea867e8fb240cf27913d4f8ae767385Dan Stoza sp<IGraphicBufferConsumer> consumer; 1108aa0f0619ea867e8fb240cf27913d4f8ae767385Dan Stoza BufferQueue::createBufferQueue(&producer, &consumer); 1118aa0f0619ea867e8fb240cf27913d4f8ae767385Dan Stoza mCaptureConsumer = new CpuConsumer(consumer, 1); 112ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala mCaptureConsumer->setFrameAvailableListener(this); 113727d172137b4f32681c098de8e2623c0b65a6406Eino-Ville Talvala mCaptureConsumer->setName(String8("Camera2-JpegConsumer")); 1148aa0f0619ea867e8fb240cf27913d4f8ae767385Dan Stoza mCaptureWindow = new Surface(producer); 1152d077d0acdbb26eeb1357489c999ec875f6ce297Eino-Ville Talvala } 1162d077d0acdbb26eeb1357489c999ec875f6ce297Eino-Ville Talvala 1172d077d0acdbb26eeb1357489c999ec875f6ce297Eino-Ville Talvala // Since ashmem heaps are rounded up to page size, don't reallocate if 1182d077d0acdbb26eeb1357489c999ec875f6ce297Eino-Ville Talvala // the capture heap isn't exactly the same size as the required JPEG buffer 1192d077d0acdbb26eeb1357489c999ec875f6ce297Eino-Ville Talvala const size_t HEAP_SLACK_FACTOR = 2; 1202d077d0acdbb26eeb1357489c999ec875f6ce297Eino-Ville Talvala if (mCaptureHeap == 0 || 1212d077d0acdbb26eeb1357489c999ec875f6ce297Eino-Ville Talvala (mCaptureHeap->getSize() < static_cast<size_t>(maxJpegSize)) || 1222d077d0acdbb26eeb1357489c999ec875f6ce297Eino-Ville Talvala (mCaptureHeap->getSize() > 1232d077d0acdbb26eeb1357489c999ec875f6ce297Eino-Ville Talvala static_cast<size_t>(maxJpegSize) * HEAP_SLACK_FACTOR) ) { 124ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala // Create memory for API consumption 1252d077d0acdbb26eeb1357489c999ec875f6ce297Eino-Ville Talvala mCaptureHeap.clear(); 1262d077d0acdbb26eeb1357489c999ec875f6ce297Eino-Ville Talvala mCaptureHeap = 1272d077d0acdbb26eeb1357489c999ec875f6ce297Eino-Ville Talvala new MemoryHeapBase(maxJpegSize, 0, "Camera2Client::CaptureHeap"); 128a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray if (mCaptureHeap->getSize() == 0) { 129ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala ALOGE("%s: Camera %d: Unable to allocate memory for capture", 130d09801b99503b57c35e321ad9afa7e861e012813Eino-Ville Talvala __FUNCTION__, mId); 131ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala return NO_MEMORY; 132ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala } 133ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala } 134d309fb9c8a2c4564d88fffba19c4e3688e4b862bEino-Ville Talvala ALOGV("%s: Camera %d: JPEG capture heap now %zu bytes; requested %zd bytes", 1352d077d0acdbb26eeb1357489c999ec875f6ce297Eino-Ville Talvala __FUNCTION__, mId, mCaptureHeap->getSize(), maxJpegSize); 136ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 137ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala if (mCaptureStreamId != NO_STREAM) { 138ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala // Check if stream parameters have to change 139ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala uint32_t currentWidth, currentHeight; 140ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala res = device->getStreamInfo(mCaptureStreamId, 141d46a6b9fd8b2a4f9098757384711e2cd03a91651Eino-Ville Talvala ¤tWidth, ¤tHeight, 0, 0); 142ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala if (res != OK) { 143ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala ALOGE("%s: Camera %d: Error querying capture output stream info: " 144ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala "%s (%d)", __FUNCTION__, 145d09801b99503b57c35e321ad9afa7e861e012813Eino-Ville Talvala mId, strerror(-res), res); 146ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala return res; 147ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala } 148ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala if (currentWidth != (uint32_t)params.pictureWidth || 149ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala currentHeight != (uint32_t)params.pictureHeight) { 150ecf17e82505fdb60d59e00b6dd59036df93de655Igor Murashkin ALOGV("%s: Camera %d: Deleting stream %d since the buffer dimensions changed", 151d09801b99503b57c35e321ad9afa7e861e012813Eino-Ville Talvala __FUNCTION__, mId, mCaptureStreamId); 152ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala res = device->deleteStream(mCaptureStreamId); 153dca254aef0c09867e50fe6613c6fad405de72842Igor Murashkin if (res == -EBUSY) { 154dca254aef0c09867e50fe6613c6fad405de72842Igor Murashkin ALOGV("%s: Camera %d: Device is busy, call updateStream again " 155dca254aef0c09867e50fe6613c6fad405de72842Igor Murashkin " after it becomes idle", __FUNCTION__, mId); 156dca254aef0c09867e50fe6613c6fad405de72842Igor Murashkin return res; 157dca254aef0c09867e50fe6613c6fad405de72842Igor Murashkin } else if (res != OK) { 158ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala ALOGE("%s: Camera %d: Unable to delete old output stream " 159ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala "for capture: %s (%d)", __FUNCTION__, 160d09801b99503b57c35e321ad9afa7e861e012813Eino-Ville Talvala mId, strerror(-res), res); 161ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala return res; 162ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala } 163ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala mCaptureStreamId = NO_STREAM; 164ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala } 165ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala } 166ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 167ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala if (mCaptureStreamId == NO_STREAM) { 168ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala // Create stream for HAL production 169ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala res = device->createStream(mCaptureWindow, 170ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala params.pictureWidth, params.pictureHeight, 1712cbf6cea23539bfe99e36d1d221de62255452e86Eino-Ville Talvala HAL_PIXEL_FORMAT_BLOB, HAL_DATASPACE_V0_JFIF, 172b97babb8c08969b55af3b6456d15f764c8873d3fYin-Chia Yeh CAMERA3_STREAM_ROTATION_0, &mCaptureStreamId); 173ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala if (res != OK) { 174ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala ALOGE("%s: Camera %d: Can't create output stream for capture: " 175d09801b99503b57c35e321ad9afa7e861e012813Eino-Ville Talvala "%s (%d)", __FUNCTION__, mId, 176ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala strerror(-res), res); 177ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala return res; 178ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala } 179ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 180b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang res = device->addBufferListenerForStream(mCaptureStreamId, this); 181b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang if (res != OK) { 182b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang ALOGE("%s: Camera %d: Can't add buffer listeneri: %s (%d)", 183b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang __FUNCTION__, mId, strerror(-res), res); 184b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang return res; 185b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang } 186ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala } 187ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala return OK; 188ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala} 189ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 190da6665cbd06ca58d3357c3002b7366d13e23f152Eino-Ville Talvalastatus_t JpegProcessor::deleteStream() { 191ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala ATRACE_CALL(); 192ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 193ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala Mutex::Autolock l(mInputMutex); 194ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 195ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala if (mCaptureStreamId != NO_STREAM) { 196d09801b99503b57c35e321ad9afa7e861e012813Eino-Ville Talvala sp<CameraDeviceBase> device = mDevice.promote(); 197d09801b99503b57c35e321ad9afa7e861e012813Eino-Ville Talvala if (device == 0) { 198d09801b99503b57c35e321ad9afa7e861e012813Eino-Ville Talvala ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId); 199d09801b99503b57c35e321ad9afa7e861e012813Eino-Ville Talvala return INVALID_OPERATION; 200d09801b99503b57c35e321ad9afa7e861e012813Eino-Ville Talvala } 201ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 202ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala device->deleteStream(mCaptureStreamId); 203cf70d3469332445dc3ffd09729da3538612b1bb2Eino-Ville Talvala 204cf70d3469332445dc3ffd09729da3538612b1bb2Eino-Ville Talvala mCaptureHeap.clear(); 205cf70d3469332445dc3ffd09729da3538612b1bb2Eino-Ville Talvala mCaptureWindow.clear(); 206cf70d3469332445dc3ffd09729da3538612b1bb2Eino-Ville Talvala mCaptureConsumer.clear(); 207cf70d3469332445dc3ffd09729da3538612b1bb2Eino-Ville Talvala 208ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala mCaptureStreamId = NO_STREAM; 209ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala } 210ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala return OK; 211ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala} 212ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 213da6665cbd06ca58d3357c3002b7366d13e23f152Eino-Ville Talvalaint JpegProcessor::getStreamId() const { 214ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala Mutex::Autolock l(mInputMutex); 215ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala return mCaptureStreamId; 216ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala} 217ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 218ddf3c5025e2f6f35a4c188c19f30142c64a092c4Igor Murashkinvoid JpegProcessor::dump(int /*fd*/, const Vector<String16>& /*args*/) const { 219ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala} 220ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 221da6665cbd06ca58d3357c3002b7366d13e23f152Eino-Ville Talvalabool JpegProcessor::threadLoop() { 222ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala status_t res; 223ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 224b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang bool captureSuccess = false; 225ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala { 226ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala Mutex::Autolock l(mInputMutex); 227b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang 228b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang while (!mCaptureDone) { 229b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang res = mCaptureDoneSignal.waitRelative(mInputMutex, 230ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala kWaitDuration); 231ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala if (res == TIMED_OUT) return true; 232ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala } 233b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang 234b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang captureSuccess = mCaptureSuccess; 235b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang mCaptureDone = false; 236ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala } 237ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 238b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang res = processNewCapture(captureSuccess); 239ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 240ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala return true; 241ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala} 242ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 243b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wangstatus_t JpegProcessor::processNewCapture(bool captureSuccess) { 244ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala ATRACE_CALL(); 245ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala status_t res; 246ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala sp<Camera2Heap> captureHeap; 247138851bd3cadfb60238f87567e24808925731837Zhijun He sp<MemoryBase> captureBuffer; 248ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 249ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala CpuConsumer::LockedBuffer imgBuffer; 250ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 251b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang if (captureSuccess) { 252138851bd3cadfb60238f87567e24808925731837Zhijun He Mutex::Autolock l(mInputMutex); 253138851bd3cadfb60238f87567e24808925731837Zhijun He if (mCaptureStreamId == NO_STREAM) { 254138851bd3cadfb60238f87567e24808925731837Zhijun He ALOGW("%s: Camera %d: No stream is available", __FUNCTION__, mId); 255138851bd3cadfb60238f87567e24808925731837Zhijun He return INVALID_OPERATION; 256ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala } 257ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 258138851bd3cadfb60238f87567e24808925731837Zhijun He res = mCaptureConsumer->lockNextBuffer(&imgBuffer); 259138851bd3cadfb60238f87567e24808925731837Zhijun He if (res != OK) { 260138851bd3cadfb60238f87567e24808925731837Zhijun He if (res != BAD_VALUE) { 261138851bd3cadfb60238f87567e24808925731837Zhijun He ALOGE("%s: Camera %d: Error receiving still image buffer: " 262138851bd3cadfb60238f87567e24808925731837Zhijun He "%s (%d)", __FUNCTION__, 263138851bd3cadfb60238f87567e24808925731837Zhijun He mId, strerror(-res), res); 264138851bd3cadfb60238f87567e24808925731837Zhijun He } 265138851bd3cadfb60238f87567e24808925731837Zhijun He return res; 266138851bd3cadfb60238f87567e24808925731837Zhijun He } 267ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 268138851bd3cadfb60238f87567e24808925731837Zhijun He ALOGV("%s: Camera %d: Still capture available", __FUNCTION__, 269138851bd3cadfb60238f87567e24808925731837Zhijun He mId); 270ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 271138851bd3cadfb60238f87567e24808925731837Zhijun He if (imgBuffer.format != HAL_PIXEL_FORMAT_BLOB) { 272138851bd3cadfb60238f87567e24808925731837Zhijun He ALOGE("%s: Camera %d: Unexpected format for still image: " 273138851bd3cadfb60238f87567e24808925731837Zhijun He "%x, expected %x", __FUNCTION__, mId, 274138851bd3cadfb60238f87567e24808925731837Zhijun He imgBuffer.format, 275138851bd3cadfb60238f87567e24808925731837Zhijun He HAL_PIXEL_FORMAT_BLOB); 276138851bd3cadfb60238f87567e24808925731837Zhijun He mCaptureConsumer->unlockBuffer(imgBuffer); 277138851bd3cadfb60238f87567e24808925731837Zhijun He return OK; 278138851bd3cadfb60238f87567e24808925731837Zhijun He } 279a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray 280138851bd3cadfb60238f87567e24808925731837Zhijun He // Find size of JPEG image 281138851bd3cadfb60238f87567e24808925731837Zhijun He size_t jpegSize = findJpegSize(imgBuffer.data, imgBuffer.width); 282138851bd3cadfb60238f87567e24808925731837Zhijun He if (jpegSize == 0) { // failed to find size, default to whole buffer 283138851bd3cadfb60238f87567e24808925731837Zhijun He jpegSize = imgBuffer.width; 284138851bd3cadfb60238f87567e24808925731837Zhijun He } 285138851bd3cadfb60238f87567e24808925731837Zhijun He size_t heapSize = mCaptureHeap->getSize(); 286138851bd3cadfb60238f87567e24808925731837Zhijun He if (jpegSize > heapSize) { 287138851bd3cadfb60238f87567e24808925731837Zhijun He ALOGW("%s: JPEG image is larger than expected, truncating " 2885c679d41714e42f153f6aeb492df54510a195bc1Colin Cross "(got %zu, expected at most %zu bytes)", 289138851bd3cadfb60238f87567e24808925731837Zhijun He __FUNCTION__, jpegSize, heapSize); 290138851bd3cadfb60238f87567e24808925731837Zhijun He jpegSize = heapSize; 291138851bd3cadfb60238f87567e24808925731837Zhijun He } 292138851bd3cadfb60238f87567e24808925731837Zhijun He 293138851bd3cadfb60238f87567e24808925731837Zhijun He // TODO: Optimize this to avoid memcopy 294138851bd3cadfb60238f87567e24808925731837Zhijun He captureBuffer = new MemoryBase(mCaptureHeap, 0, jpegSize); 295138851bd3cadfb60238f87567e24808925731837Zhijun He void* captureMemory = mCaptureHeap->getBase(); 296138851bd3cadfb60238f87567e24808925731837Zhijun He memcpy(captureMemory, imgBuffer.data, jpegSize); 297ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 298138851bd3cadfb60238f87567e24808925731837Zhijun He mCaptureConsumer->unlockBuffer(imgBuffer); 299138851bd3cadfb60238f87567e24808925731837Zhijun He } 300ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 301fe580e57081885dd6059e0d407a6cd96a1be7e51Eino-Ville Talvala sp<CaptureSequencer> sequencer = mSequencer.promote(); 302fe580e57081885dd6059e0d407a6cd96a1be7e51Eino-Ville Talvala if (sequencer != 0) { 303b0fdc1ed2182fe851ef7ca98a1b4a552b53b3033Shuzhen Wang sequencer->onCaptureAvailable(imgBuffer.timestamp, captureBuffer, !captureSuccess); 304ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala } 305fe580e57081885dd6059e0d407a6cd96a1be7e51Eino-Ville Talvala 306ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala return OK; 307ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala} 308ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala 309a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray/* 310a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray * JPEG FILE FORMAT OVERVIEW. 311a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray * http://www.jpeg.org/public/jfif.pdf 312a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray * (JPEG is the image compression algorithm, actual file format is called JFIF) 313a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray * 314a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray * "Markers" are 2-byte patterns used to distinguish parts of JFIF files. The 315a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray * first byte is always 0xFF, and the second byte is between 0x01 and 0xFE 316a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray * (inclusive). Because every marker begins with the same byte, they are 317a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray * referred to by the second byte's value. 318a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray * 319a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray * JFIF files all begin with the Start of Image (SOI) marker, which is 0xD8. 320a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray * Following it, "segment" sections begin with other markers, followed by a 321a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray * 2-byte length (in network byte order), then the segment data. 322a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray * 323a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray * For our purposes we will ignore the data, and just use the length to skip to 324a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray * the next segment. This is necessary because the data inside segments are 325a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray * allowed to contain the End of Image marker (0xFF 0xD9), preventing us from 326a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray * naievely scanning until the end. 327a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray * 328a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray * After all the segments are processed, the jpeg compressed image stream begins. 329a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray * This can be considered an opaque format with one requirement: all 0xFF bytes 330a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray * in this stream must be followed with a 0x00 byte. This prevents any of the 331a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray * image data to be interpreted as a segment. The only exception to this is at 332a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray * the end of the image stream there is an End of Image (EOI) marker, which is 333a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray * 0xFF followed by a non-zero (0xD9) byte. 334a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray */ 335a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray 336a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Rayconst uint8_t MARK = 0xFF; // First byte of marker 337a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Rayconst uint8_t SOI = 0xD8; // Start of Image 338a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Rayconst uint8_t EOI = 0xD9; // End of Image 339a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Rayconst size_t MARKER_LENGTH = 2; // length of a marker 340a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray 341a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray#pragma pack(push) 342a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray#pragma pack(1) 343a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Raytypedef struct segment { 344a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray uint8_t marker[MARKER_LENGTH]; 345a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray uint16_t length; 346a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray} segment_t; 347a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray#pragma pack(pop) 348a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray 349a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray/* HELPER FUNCTIONS */ 350a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray 351a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray// check for Start of Image marker 352a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Raybool checkJpegStart(uint8_t* buf) { 353a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray return buf[0] == MARK && buf[1] == SOI; 354a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray} 355a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray// check for End of Image marker 356a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Raybool checkJpegEnd(uint8_t *buf) { 357a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray return buf[0] == MARK && buf[1] == EOI; 358a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray} 359a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray// check for arbitrary marker, returns marker type (second byte) 360a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray// returns 0 if no marker found. Note: 0x00 is not a valid marker type 361a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Rayuint8_t checkJpegMarker(uint8_t *buf) { 362a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray if (buf[0] == MARK && buf[1] > 0 && buf[1] < 0xFF) { 363a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray return buf[1]; 364a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray } 365a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray return 0; 366a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray} 367a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray 368a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray// Return the size of the JPEG, 0 indicates failure 3690fa1e760f7093d025c977e5813e8d3a04c863ce3Alex Raysize_t JpegProcessor::findJpegSize(uint8_t* jpegBuffer, size_t maxSize) { 370a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray size_t size; 371a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray 3720fa1e760f7093d025c977e5813e8d3a04c863ce3Alex Ray // First check for JPEG transport header at the end of the buffer 3730fa1e760f7093d025c977e5813e8d3a04c863ce3Alex Ray uint8_t *header = jpegBuffer + (maxSize - sizeof(struct camera2_jpeg_blob)); 3740fa1e760f7093d025c977e5813e8d3a04c863ce3Alex Ray struct camera2_jpeg_blob *blob = (struct camera2_jpeg_blob*)(header); 375a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray if (blob->jpeg_blob_id == CAMERA2_JPEG_BLOB_ID) { 376a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray size = blob->jpeg_size; 377a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray if (size > 0 && size <= maxSize - sizeof(struct camera2_jpeg_blob)) { 378a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray // Verify SOI and EOI markers 379a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray size_t offset = size - MARKER_LENGTH; 3800fa1e760f7093d025c977e5813e8d3a04c863ce3Alex Ray uint8_t *end = jpegBuffer + offset; 3810fa1e760f7093d025c977e5813e8d3a04c863ce3Alex Ray if (checkJpegStart(jpegBuffer) && checkJpegEnd(end)) { 382e5729fac81c8a984e984fefc90afc64135817d4fColin Cross ALOGV("Found JPEG transport header, img size %zu", size); 383a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray return size; 384a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray } else { 385a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray ALOGW("Found JPEG transport header with bad Image Start/End"); 386a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray } 387a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray } else { 388e5729fac81c8a984e984fefc90afc64135817d4fColin Cross ALOGW("Found JPEG transport header with bad size %zu", size); 389a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray } 390a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray } 391a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray 3920fa1e760f7093d025c977e5813e8d3a04c863ce3Alex Ray // Check Start of Image 3930fa1e760f7093d025c977e5813e8d3a04c863ce3Alex Ray if ( !checkJpegStart(jpegBuffer) ) { 394a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray ALOGE("Could not find start of JPEG marker"); 395a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray return 0; 396a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray } 397a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray 398a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray // Read JFIF segment markers, skip over segment data 399a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray size = 0; 400a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray while (size <= maxSize - MARKER_LENGTH) { 4010fa1e760f7093d025c977e5813e8d3a04c863ce3Alex Ray segment_t *segment = (segment_t*)(jpegBuffer + size); 402a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray uint8_t type = checkJpegMarker(segment->marker); 403a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray if (type == 0) { // invalid marker, no more segments, begin JPEG data 404e5729fac81c8a984e984fefc90afc64135817d4fColin Cross ALOGV("JPEG stream found beginning at offset %zu", size); 405a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray break; 406a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray } 407a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray if (type == EOI || size > maxSize - sizeof(segment_t)) { 408e5729fac81c8a984e984fefc90afc64135817d4fColin Cross ALOGE("Got premature End before JPEG data, offset %zu", size); 409a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray return 0; 410a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray } 411a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray size_t length = ntohs(segment->length); 412e5729fac81c8a984e984fefc90afc64135817d4fColin Cross ALOGV("JFIF Segment, type %x length %zx", type, length); 413a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray size += length + MARKER_LENGTH; 414a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray } 415a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray 416a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray // Find End of Image 417a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray // Scan JPEG buffer until End of Image (EOI) 418a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray bool foundEnd = false; 419ddf3c5025e2f6f35a4c188c19f30142c64a092c4Igor Murashkin for ( ; size <= maxSize - MARKER_LENGTH; size++) { 4200fa1e760f7093d025c977e5813e8d3a04c863ce3Alex Ray if ( checkJpegEnd(jpegBuffer + size) ) { 421a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray foundEnd = true; 422a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray size += MARKER_LENGTH; 423a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray break; 424a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray } 425a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray } 426a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray if (!foundEnd) { 427a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray ALOGE("Could not find end of JPEG marker"); 428a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray return 0; 429a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray } 430a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray 431a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray if (size > maxSize) { 432e5729fac81c8a984e984fefc90afc64135817d4fColin Cross ALOGW("JPEG size %zu too large, reducing to maxSize %zu", size, maxSize); 433a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray size = maxSize; 434a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray } 435e5729fac81c8a984e984fefc90afc64135817d4fColin Cross ALOGV("Final JPEG size %zu", size); 436a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray return size; 437a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray} 438a6b4c40e70eafc5aba16163999de6d3e26667b89Alex Ray 439ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala}; // namespace camera2 440ea0d51b5ed0b474433b02414f9133b835f972569Eino-Ville Talvala}; // namespace android 441