String8 threadName;
mStreamingProcessor = new StreamingProcessor(this);
+ threadName = String8::format("C2-%d-StreamProc",
+ mCameraId);
+ mStreamingProcessor->run(threadName.string());
mFrameProcessor = new FrameProcessor(mDevice, this);
threadName = String8::format("C2-%d-FrameProc",
mCallbackProcessor->deleteStream();
mZslProcessor->deleteStream();
+ mStreamingProcessor->requestExit();
mFrameProcessor->requestExit();
mCaptureSequencer->requestExit();
mJpegProcessor->requestExit();
ALOGV("Camera %d: Waiting for threads", mCameraId);
+ mStreamingProcessor->join();
mFrameProcessor->join();
mCaptureSequencer->join();
mJpegProcessor->join();
mPreviewStreamId(NO_STREAM),
mRecordingRequestId(Camera2Client::kRecordingRequestIdStart),
mRecordingStreamId(NO_STREAM),
+ mRecordingFrameAvailable(false),
mRecordingHeapCount(kDefaultRecordingHeapCount)
{
}
void StreamingProcessor::onFrameAvailable() {
ATRACE_CALL();
+ Mutex::Autolock l(mMutex);
+ if (!mRecordingFrameAvailable) {
+ mRecordingFrameAvailable = true;
+ mRecordingFrameAvailableSignal.signal();
+ }
+
+}
+
+bool StreamingProcessor::threadLoop() {
+ status_t res;
+
+ {
+ Mutex::Autolock l(mMutex);
+ while (!mRecordingFrameAvailable) {
+ res = mRecordingFrameAvailableSignal.waitRelative(
+ mMutex, kWaitDuration);
+ if (res == TIMED_OUT) return true;
+ }
+ mRecordingFrameAvailable = false;
+ }
+
+ do {
+ res = processRecordingFrame();
+ } while (res == OK);
+
+ return true;
+}
+
+status_t StreamingProcessor::processRecordingFrame() {
+ ATRACE_CALL();
status_t res;
sp<Camera2Heap> recordingHeap;
size_t heapIdx = 0;
BufferItemConsumer::BufferItem imgBuffer;
res = mRecordingConsumer->acquireBuffer(&imgBuffer);
if (res != OK) {
- ALOGE("%s: Camera %d: Error receiving recording buffer: %s (%d)",
- __FUNCTION__, mId, strerror(-res), res);
- return;
+ if (res != BufferItemConsumer::NO_BUFFER_AVAILABLE) {
+ ALOGE("%s: Camera %d: Can't acquire recording buffer: %s (%d)",
+ __FUNCTION__, mId, strerror(-res), res);
+ }
+ return res;
}
mRecordingConsumer->releaseBuffer(imgBuffer);
- return;
+ return OK;
}
{
BufferItemConsumer::BufferItem imgBuffer;
res = mRecordingConsumer->acquireBuffer(&imgBuffer);
if (res != OK) {
- ALOGE("%s: Camera %d: Error receiving recording buffer: %s (%d)",
- __FUNCTION__, mId, strerror(-res), res);
- return;
+ if (res != BufferItemConsumer::NO_BUFFER_AVAILABLE) {
+ ALOGE("%s: Camera %d: Can't acquire recording buffer: %s (%d)",
+ __FUNCTION__, mId, strerror(-res), res);
+ }
+ return res;
}
timestamp = imgBuffer.mTimestamp;
mRecordingFrameCount++;
ALOGV("OnRecordingFrame: Frame %d", mRecordingFrameCount);
- // TODO: Signal errors here upstream
if (l.mParameters.state != Parameters::RECORD &&
l.mParameters.state != Parameters::VIDEO_SNAPSHOT) {
ALOGV("%s: Camera %d: Discarding recording image buffers "
"received after recording done", __FUNCTION__,
mId);
mRecordingConsumer->releaseBuffer(imgBuffer);
- return;
+ return INVALID_OPERATION;
}
if (mRecordingHeap == 0) {
ALOGE("%s: Camera %d: Unable to allocate memory for recording",
__FUNCTION__, mId);
mRecordingConsumer->releaseBuffer(imgBuffer);
- return;
+ return NO_MEMORY;
}
for (size_t i = 0; i < mRecordingBuffers.size(); i++) {
if (mRecordingBuffers[i].mBuf !=
ALOGE("%s: Camera %d: No free recording buffers, dropping frame",
__FUNCTION__, mId);
mRecordingConsumer->releaseBuffer(imgBuffer);
- return;
+ return NO_MEMORY;
}
heapIdx = mRecordingHeapHead;
CAMERA_MSG_VIDEO_FRAME,
recordingHeap->mBuffers[heapIdx]);
}
+ return OK;
}
void StreamingProcessor::releaseRecordingFrame(const sp<IMemory>& mem) {
/**
* Management and processing for preview and recording streams
*/
-class StreamingProcessor: public BufferItemConsumer::FrameAvailableListener {
+class StreamingProcessor:
+ public Thread, public BufferItemConsumer::FrameAvailableListener {
public:
StreamingProcessor(sp<Camera2Client> client);
~StreamingProcessor();
sp<ANativeWindow> mPreviewWindow;
// Recording-related members
+ static const nsecs_t kWaitDuration = 50000000; // 50 ms
+
int32_t mRecordingRequestId;
int mRecordingStreamId;
int mRecordingFrameCount;
CameraMetadata mRecordingRequest;
sp<camera2::Camera2Heap> mRecordingHeap;
+ bool mRecordingFrameAvailable;
+ Condition mRecordingFrameAvailableSignal;
+
static const size_t kDefaultRecordingHeapCount = 8;
size_t mRecordingHeapCount;
Vector<BufferItemConsumer::BufferItem> mRecordingBuffers;
size_t mRecordingHeapHead, mRecordingHeapFree;
+ virtual bool threadLoop();
+
+ status_t processRecordingFrame();
};