X-Git-Url: https://gerrit.akraino.org/r/gitweb?a=blobdiff_plain;f=src%2Ftype3_AndroidCloud%2Fanbox-master%2Fandroid%2Fcamera%2FPreviewWindow.cpp;fp=src%2Ftype3_AndroidCloud%2Fanbox-master%2Fandroid%2Fcamera%2FPreviewWindow.cpp;h=4101ed965db7423a9944d200595b33195cf1e63b;hb=e26c1ec581be598521517829adba8c8dd23a768f;hp=0000000000000000000000000000000000000000;hpb=6699c1aea74eeb0eb400e6299079f0c7576f716f;p=iec.git diff --git a/src/type3_AndroidCloud/anbox-master/android/camera/PreviewWindow.cpp b/src/type3_AndroidCloud/anbox-master/android/camera/PreviewWindow.cpp new file mode 100644 index 0000000..4101ed9 --- /dev/null +++ b/src/type3_AndroidCloud/anbox-master/android/camera/PreviewWindow.cpp @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Contains implementation of a class PreviewWindow that encapsulates + * functionality of a preview window set via set_preview_window camera HAL API. + */ + +#define LOG_NDEBUG 0 +#define LOG_TAG "EmulatedCamera_Preview" +#include +#include +#include +#include "EmulatedCameraDevice.h" +#include "PreviewWindow.h" + +namespace android { + +PreviewWindow::PreviewWindow() + : mPreviewWindow(NULL), + mLastPreviewed(0), + mPreviewFrameWidth(0), + mPreviewFrameHeight(0), + mPreviewEnabled(false) +{ +} + +PreviewWindow::~PreviewWindow() +{ +} + +/**************************************************************************** + * Camera API + ***************************************************************************/ + +status_t PreviewWindow::setPreviewWindow(struct preview_stream_ops* window, + int preview_fps) +{ + ALOGV("%s: current: %p -> new: %p", __FUNCTION__, mPreviewWindow, window); + + status_t res = NO_ERROR; + Mutex::Autolock locker(&mObjectLock); + + /* Reset preview info. */ + mPreviewFrameWidth = mPreviewFrameHeight = 0; + mPreviewAfter = 0; + mLastPreviewed = 0; + + if (window != NULL) { + /* The CPU will write each frame to the preview window buffer. + * Note that we delay setting preview window buffer geometry until + * frames start to come in. */ + res = window->set_usage(window, GRALLOC_USAGE_SW_WRITE_OFTEN); + if (res == NO_ERROR) { + /* Set preview frequency. */ + mPreviewAfter = 1000000 / preview_fps; + } else { + window = NULL; + res = -res; // set_usage returns a negative errno. + ALOGE("%s: Error setting preview window usage %d -> %s", + __FUNCTION__, res, strerror(res)); + } + } + mPreviewWindow = window; + + return res; +} + +status_t PreviewWindow::startPreview() +{ + ALOGV("%s", __FUNCTION__); + + Mutex::Autolock locker(&mObjectLock); + mPreviewEnabled = true; + + return NO_ERROR; +} + +void PreviewWindow::stopPreview() +{ + ALOGV("%s", __FUNCTION__); + + Mutex::Autolock locker(&mObjectLock); + mPreviewEnabled = false; +} + +/**************************************************************************** + * Public API + ***************************************************************************/ + +void PreviewWindow::onNextFrameAvailable(const void* frame, + nsecs_t timestamp, + EmulatedCameraDevice* camera_dev) +{ + int res; + Mutex::Autolock locker(&mObjectLock); + + if (!isPreviewEnabled() || mPreviewWindow == NULL || !isPreviewTime()) { + return; + } + + /* Make sure that preview window dimensions are OK with the camera device */ + if (adjustPreviewDimensions(camera_dev)) { + /* Need to set / adjust buffer geometry for the preview window. + * Note that in the emulator preview window uses only RGB for pixel + * formats. */ + ALOGV("%s: Adjusting preview windows %p geometry to %dx%d", + __FUNCTION__, mPreviewWindow, mPreviewFrameWidth, + mPreviewFrameHeight); + res = mPreviewWindow->set_buffers_geometry(mPreviewWindow, + mPreviewFrameWidth, + mPreviewFrameHeight, + HAL_PIXEL_FORMAT_RGBA_8888); + if (res != NO_ERROR) { + ALOGE("%s: Error in set_buffers_geometry %d -> %s", + __FUNCTION__, -res, strerror(-res)); + return; + } + } + + /* + * Push new frame to the preview window. + */ + + /* Dequeue preview window buffer for the frame. */ + buffer_handle_t* buffer = NULL; + int stride = 0; + res = mPreviewWindow->dequeue_buffer(mPreviewWindow, &buffer, &stride); + if (res != NO_ERROR || buffer == NULL) { + ALOGE("%s: Unable to dequeue preview window buffer: %d -> %s", + __FUNCTION__, -res, strerror(-res)); + return; + } + + /* Let the preview window to lock the buffer. */ + res = mPreviewWindow->lock_buffer(mPreviewWindow, buffer); + if (res != NO_ERROR) { + ALOGE("%s: Unable to lock preview window buffer: %d -> %s", + __FUNCTION__, -res, strerror(-res)); + mPreviewWindow->cancel_buffer(mPreviewWindow, buffer); + return; + } + + /* Now let the graphics framework to lock the buffer, and provide + * us with the framebuffer data address. */ + void* img = NULL; + const Rect rect(mPreviewFrameWidth, mPreviewFrameHeight); + GraphicBufferMapper& grbuffer_mapper(GraphicBufferMapper::get()); + res = grbuffer_mapper.lock(*buffer, GRALLOC_USAGE_SW_WRITE_OFTEN, rect, &img); + if (res != NO_ERROR) { + ALOGE("%s: grbuffer_mapper.lock failure: %d -> %s", + __FUNCTION__, res, strerror(res)); + mPreviewWindow->cancel_buffer(mPreviewWindow, buffer); + return; + } + + /* Frames come in in YV12/NV12/NV21 format. Since preview window doesn't + * supports those formats, we need to obtain the frame in RGB565. */ + res = camera_dev->getCurrentPreviewFrame(img); + if (res == NO_ERROR) { + /* Show it. */ + mPreviewWindow->set_timestamp(mPreviewWindow, timestamp); + mPreviewWindow->enqueue_buffer(mPreviewWindow, buffer); + } else { + ALOGE("%s: Unable to obtain preview frame: %d", __FUNCTION__, res); + mPreviewWindow->cancel_buffer(mPreviewWindow, buffer); + } + grbuffer_mapper.unlock(*buffer); +} + +/*************************************************************************** + * Private API + **************************************************************************/ + +bool PreviewWindow::adjustPreviewDimensions(EmulatedCameraDevice* camera_dev) +{ + /* Match the cached frame dimensions against the actual ones. */ + if (mPreviewFrameWidth == camera_dev->getFrameWidth() && + mPreviewFrameHeight == camera_dev->getFrameHeight()) { + /* They match. */ + return false; + } + + /* They don't match: adjust the cache. */ + mPreviewFrameWidth = camera_dev->getFrameWidth(); + mPreviewFrameHeight = camera_dev->getFrameHeight(); + + return true; +} + +bool PreviewWindow::isPreviewTime() +{ + timeval cur_time; + gettimeofday(&cur_time, NULL); + const uint64_t cur_mks = cur_time.tv_sec * 1000000LL + cur_time.tv_usec; + if ((cur_mks - mLastPreviewed) >= mPreviewAfter) { + mLastPreviewed = cur_mks; + return true; + } + return false; +} + +}; /* namespace android */