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