JpegProcessor.cpp revision da6665cbd06ca58d3357c3002b7366d13e23f152
1b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber/* 2b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber * Copyright (C) 2012 The Android Open Source Project 3b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber * 4b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 5b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber * you may not use this file except in compliance with the License. 6b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber * You may obtain a copy of the License at 7b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber * 8b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 9b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber * 10b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber * Unless required by applicable law or agreed to in writing, software 11b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 12b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber * See the License for the specific language governing permissions and 14b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber * limitations under the License. 15b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber */ 16b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber 17b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber#define LOG_TAG "Camera2Client::JpegProcessor" 18b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber#define ATRACE_TAG ATRACE_TAG_CAMERA 19b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber//#define LOG_NDEBUG 0 20b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber 21b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber#include <utils/Log.h> 22b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber#include <utils/Trace.h> 23b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber 24b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber#include "JpegProcessor.h" 25b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber#include <gui/SurfaceTextureClient.h> 26b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber#include "../Camera2Device.h" 27b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber#include "../Camera2Client.h" 28b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber 29b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber 30b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Hubernamespace android { 31b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Hubernamespace camera2 { 32b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber 33b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas HuberJpegProcessor::JpegProcessor( 34b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber wp<Camera2Client> client, 35b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber wp<CaptureSequencer> sequencer): 36b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber Thread(false), 37b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber mClient(client), 38b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber mSequencer(sequencer), 39b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber mCaptureAvailable(false), 40b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber mCaptureStreamId(NO_STREAM) { 41b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber} 42b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber 43b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas HuberJpegProcessor::~JpegProcessor() { 44b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber ALOGV("%s: Exit", __FUNCTION__); 45b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber} 46b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber 47b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Hubervoid JpegProcessor::onFrameAvailable() { 48b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber Mutex::Autolock l(mInputMutex); 49b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber if (!mCaptureAvailable) { 50b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber mCaptureAvailable = true; 51b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber mCaptureAvailableSignal.signal(); 52b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber } 53b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber} 54b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber 55b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huberstatus_t JpegProcessor::updateStream(const Parameters ¶ms) { 56b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber ATRACE_CALL(); 57b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber ALOGV("%s", __FUNCTION__); 58b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber status_t res; 59b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber 60b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber Mutex::Autolock l(mInputMutex); 61b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber 62b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber sp<Camera2Client> client = mClient.promote(); 63b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber if (client == 0) return OK; 64b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber sp<Camera2Device> device = client->getCameraDevice(); 65b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber 66b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber // Find out buffer size for JPEG 67b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber camera_metadata_ro_entry_t maxJpegSize = 68b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber params.staticInfo(ANDROID_JPEG_MAX_SIZE); 69b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber if (maxJpegSize.count == 0) { 70b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber ALOGE("%s: Camera %d: Can't find ANDROID_JPEG_MAX_SIZE!", 71b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber __FUNCTION__, client->getCameraId()); 72b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber return INVALID_OPERATION; 73b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber } 74b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber 75b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber if (mCaptureConsumer == 0) { 76b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber // Create CPU buffer queue endpoint 77b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber mCaptureConsumer = new CpuConsumer(1); 78b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber mCaptureConsumer->setFrameAvailableListener(this); 79b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber mCaptureConsumer->setName(String8("Camera2Client::CaptureConsumer")); 80b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber mCaptureWindow = new SurfaceTextureClient( 81b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber mCaptureConsumer->getProducerInterface()); 82b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber // Create memory for API consumption 83b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber mCaptureHeap = new Camera2Heap(maxJpegSize.data.i32[0], 1, 84b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber "Camera2Client::CaptureHeap"); 85b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber if (mCaptureHeap->mHeap->getSize() == 0) { 86b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber ALOGE("%s: Camera %d: Unable to allocate memory for capture", 87b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber __FUNCTION__, client->getCameraId()); 88b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber return NO_MEMORY; 89b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber } 90b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber } 91b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber 92b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber if (mCaptureStreamId != NO_STREAM) { 93b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber // Check if stream parameters have to change 94b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber uint32_t currentWidth, currentHeight; 95b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber res = device->getStreamInfo(mCaptureStreamId, 96b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber ¤tWidth, ¤tHeight, 0); 97b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber if (res != OK) { 98b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber ALOGE("%s: Camera %d: Error querying capture output stream info: " 99b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber "%s (%d)", __FUNCTION__, 100b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber client->getCameraId(), strerror(-res), res); 101b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber return res; 102b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber } 103b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber if (currentWidth != (uint32_t)params.pictureWidth || 104b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber currentHeight != (uint32_t)params.pictureHeight) { 105b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber res = device->deleteStream(mCaptureStreamId); 106b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber if (res != OK) { 107b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber ALOGE("%s: Camera %d: Unable to delete old output stream " 108b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber "for capture: %s (%d)", __FUNCTION__, 109b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber client->getCameraId(), strerror(-res), res); 110b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber return res; 111b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber } 112b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber mCaptureStreamId = NO_STREAM; 113b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber } 114b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber } 115b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber 116b841f14f8e51f2365945281fbfa54ef6a1b1b5a6Andreas Huber if (mCaptureStreamId == NO_STREAM) { 117 // Create stream for HAL production 118 res = device->createStream(mCaptureWindow, 119 params.pictureWidth, params.pictureHeight, 120 HAL_PIXEL_FORMAT_BLOB, maxJpegSize.data.i32[0], 121 &mCaptureStreamId); 122 if (res != OK) { 123 ALOGE("%s: Camera %d: Can't create output stream for capture: " 124 "%s (%d)", __FUNCTION__, client->getCameraId(), 125 strerror(-res), res); 126 return res; 127 } 128 129 } 130 return OK; 131} 132 133status_t JpegProcessor::deleteStream() { 134 ATRACE_CALL(); 135 status_t res; 136 137 Mutex::Autolock l(mInputMutex); 138 139 if (mCaptureStreamId != NO_STREAM) { 140 sp<Camera2Client> client = mClient.promote(); 141 if (client == 0) return OK; 142 sp<Camera2Device> device = client->getCameraDevice(); 143 144 device->deleteStream(mCaptureStreamId); 145 mCaptureStreamId = NO_STREAM; 146 } 147 return OK; 148} 149 150int JpegProcessor::getStreamId() const { 151 Mutex::Autolock l(mInputMutex); 152 return mCaptureStreamId; 153} 154 155void JpegProcessor::dump(int fd, const Vector<String16>& args) const { 156} 157 158bool JpegProcessor::threadLoop() { 159 status_t res; 160 161 { 162 Mutex::Autolock l(mInputMutex); 163 while (!mCaptureAvailable) { 164 res = mCaptureAvailableSignal.waitRelative(mInputMutex, 165 kWaitDuration); 166 if (res == TIMED_OUT) return true; 167 } 168 mCaptureAvailable = false; 169 } 170 171 do { 172 sp<Camera2Client> client = mClient.promote(); 173 if (client == 0) return false; 174 res = processNewCapture(client); 175 } while (res == OK); 176 177 return true; 178} 179 180status_t JpegProcessor::processNewCapture(sp<Camera2Client> &client) { 181 ATRACE_CALL(); 182 status_t res; 183 sp<Camera2Heap> captureHeap; 184 185 CpuConsumer::LockedBuffer imgBuffer; 186 187 res = mCaptureConsumer->lockNextBuffer(&imgBuffer); 188 if (res != OK) { 189 if (res != BAD_VALUE) { 190 ALOGE("%s: Camera %d: Error receiving still image buffer: " 191 "%s (%d)", __FUNCTION__, 192 client->getCameraId(), strerror(-res), res); 193 } 194 return res; 195 } 196 197 ALOGV("%s: Camera %d: Still capture available", __FUNCTION__, 198 client->getCameraId()); 199 200 // TODO: Signal errors here upstream 201 { 202 SharedParameters::Lock l(client->getParameters()); 203 204 switch (l.mParameters.state) { 205 case Parameters::STILL_CAPTURE: 206 case Parameters::VIDEO_SNAPSHOT: 207 break; 208 default: 209 ALOGE("%s: Camera %d: Still image produced unexpectedly " 210 "in state %s!", 211 __FUNCTION__, client->getCameraId(), 212 Parameters::getStateName(l.mParameters.state)); 213 mCaptureConsumer->unlockBuffer(imgBuffer); 214 return BAD_VALUE; 215 } 216 } 217 218 if (imgBuffer.format != HAL_PIXEL_FORMAT_BLOB) { 219 ALOGE("%s: Camera %d: Unexpected format for still image: " 220 "%x, expected %x", __FUNCTION__, client->getCameraId(), 221 imgBuffer.format, 222 HAL_PIXEL_FORMAT_BLOB); 223 mCaptureConsumer->unlockBuffer(imgBuffer); 224 return OK; 225 } 226 227 sp<CaptureSequencer> sequencer = mSequencer.promote(); 228 if (sequencer != 0) { 229 sequencer->onCaptureAvailable(imgBuffer.timestamp); 230 } 231 232 // TODO: Optimize this to avoid memcopy 233 void* captureMemory = mCaptureHeap->mHeap->getBase(); 234 size_t size = mCaptureHeap->mHeap->getSize(); 235 memcpy(captureMemory, imgBuffer.data, size); 236 237 mCaptureConsumer->unlockBuffer(imgBuffer); 238 239 captureHeap = mCaptureHeap; 240 241 Camera2Client::SharedCameraClient::Lock l(client->mSharedCameraClient); 242 ALOGV("%s: Sending still image to client", __FUNCTION__); 243 if (l.mCameraClient != 0) { 244 l.mCameraClient->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, 245 captureHeap->mBuffers[0], NULL); 246 } else { 247 ALOGV("%s: No client!", __FUNCTION__); 248 } 249 return OK; 250} 251 252}; // namespace camera2 253}; // namespace android 254