aboutsummaryrefslogtreecommitdiff
path: root/camera/QCamera2/HAL/test
diff options
context:
space:
mode:
authorPrateek Chaubey <chaubeyprateek@gmail.com>2018-01-07 20:55:14 +0530
committerDavide Garberi <dade.garberi@gmail.com>2018-01-19 14:09:15 +0100
commit6616278131edd80a12545085e06ee6b0e0a0a788 (patch)
tree0aef88ed11809a9d67f6abe4dc2ff782a14737e2 /camera/QCamera2/HAL/test
parentcc4ccf34871da343111bf68d16ba4e4c67cac1dc (diff)
msm8996-common: zuk: Import OSS Camera HAL
Tag: LA.HB.1.3.2-32600-8x96.0 Signed-off-by: Davide Garberi <dade.garberi@gmail.com>
Diffstat (limited to 'camera/QCamera2/HAL/test')
-rw-r--r--camera/QCamera2/HAL/test/Android.mk64
-rw-r--r--camera/QCamera2/HAL/test/qcamera_test.cpp3710
-rw-r--r--camera/QCamera2/HAL/test/qcamera_test.h361
3 files changed, 4135 insertions, 0 deletions
diff --git a/camera/QCamera2/HAL/test/Android.mk b/camera/QCamera2/HAL/test/Android.mk
new file mode 100644
index 0000000..3744034
--- /dev/null
+++ b/camera/QCamera2/HAL/test/Android.mk
@@ -0,0 +1,64 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ qcamera_test.cpp \
+
+LOCAL_SHARED_LIBRARIES:= \
+ libdl \
+ libui \
+ libutils \
+ libcutils \
+ libbinder \
+ libmedia \
+ libui \
+ libgui \
+ libcamera_client \
+ libskia \
+ libstagefright \
+ libstagefright_foundation \
+
+ifneq (1,$(filter 1,$(shell echo "$$(( $(PLATFORM_SDK_VERSION) >= 18 ))" )))
+
+LOCAL_SHARED_LIBRARIES += \
+ libmedia_native \
+
+LOCAL_32_BIT_ONLY := $(BOARD_QTI_CAMERA_32BIT_ONLY)
+LOCAL_CFLAGS += -DUSE_JB_MR1
+
+endif
+
+LOCAL_C_INCLUDES += \
+ frameworks/base/include/ui \
+ frameworks/base/include/surfaceflinger \
+ frameworks/base/include/camera \
+ frameworks/base/include/media \
+ external/skia/include/core \
+ external/skia/include/images \
+ $(TARGET_OUT_HEADERS)/qcom/display \
+ hardware/qcom/camera/QCamera2/stack/common \
+ hardware/qcom/camera/QCamera2/stack/mm-camera-interface/inc \
+ frameworks/av/include/media/stagefright \
+ frameworks/native/include/media/openmax \
+ $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+
+LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+
+LOCAL_MODULE:= camera_test
+LOCAL_MODULE_TAGS:= tests
+
+LOCAL_CFLAGS += -Wall -Wextra -Werror -Wno-unused-parameter
+LOCAL_CFLAGS += -O0
+
+ifeq (1,$(filter 1,$(shell echo "$$(( $(PLATFORM_SDK_VERSION) >= 20 ))" )))
+
+LOCAL_CFLAGS += -DUSE_SDK_20_OR_HIGHER
+
+ifeq ($(TARGET_USES_AOSP),true)
+LOCAL_CFLAGS += -DVANILLA_HAL
+endif
+
+endif
+
+include $(BUILD_EXECUTABLE)
diff --git a/camera/QCamera2/HAL/test/qcamera_test.cpp b/camera/QCamera2/HAL/test/qcamera_test.cpp
new file mode 100644
index 0000000..dd06c67
--- /dev/null
+++ b/camera/QCamera2/HAL/test/qcamera_test.cpp
@@ -0,0 +1,3710 @@
+/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <time.h>
+#include <semaphore.h>
+#include <pthread.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <ui/DisplayInfo.h>
+#include <gui/Surface.h>
+#include <gui/SurfaceComposerClient.h>
+#include <gui/ISurfaceComposer.h>
+
+#include <system/camera.h>
+
+#include <camera/Camera.h>
+#include <camera/ICamera.h>
+#include <camera/CameraParameters.h>
+#include <media/mediarecorder.h>
+
+#include <utils/RefBase.h>
+#include <utils/Mutex.h>
+#include <utils/Condition.h>
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
+#include <cutils/properties.h>
+#include <cutils/memory.h>
+#include <SkImageDecoder.h>
+#include <SkImageEncoder.h>
+#include <MediaCodec.h>
+#include <OMX_IVCommon.h>
+#include <foundation/AMessage.h>
+#include <media/ICrypto.h>
+#include <MediaMuxer.h>
+#include <foundation/ABuffer.h>
+#include <MediaErrors.h>
+#include <gralloc_priv.h>
+#include <math.h>
+
+#include "qcamera_test.h"
+#include "cam_types.h"
+#include "mm_camera_dbg.h"
+
+#define VIDEO_BUF_ALLIGN(size, allign) \
+ (((size) + (allign-1)) & (typeof(size))(~(allign-1)))
+
+namespace qcamera {
+
+using namespace android;
+
+int CameraContext::JpegIdx = 0;
+int CameraContext::mPiPIdx = 0;
+const char CameraContext::KEY_ZSL[] = "zsl";
+
+/*===========================================================================
+ * FUNCTION : previewCallback
+ *
+ * DESCRIPTION: preview callback preview mesages are enabled
+ *
+ * PARAMETERS :
+ * @mem : preview buffer
+ *
+ * RETURN : None
+ *==========================================================================*/
+void CameraContext::previewCallback(const sp<IMemory>& mem)
+{
+ printf("PREVIEW Callback %p", mem->pointer());
+ uint8_t *ptr = (uint8_t*) mem->pointer();
+ if (NULL != ptr) {
+ printf("PRV_CB: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
+ ptr[0],
+ ptr[1],
+ ptr[2],
+ ptr[3],
+ ptr[4],
+ ptr[5],
+ ptr[6],
+ ptr[7],
+ ptr[8],
+ ptr[9]);
+ } else {
+ ALOGE(" no preview for NULL CB\n");
+ }
+}
+
+/*===========================================================================
+ * FUNCTION : useLock
+ *
+ * DESCRIPTION: Mutex lock for CameraContext
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+void CameraContext::useLock()
+{
+ Mutex::Autolock l(mLock);
+ while (mInUse) {
+ mCond.wait(mLock);
+ }
+ mInUse = true;
+}
+
+/*===========================================================================
+ * FUNCTION : signalFinished
+ *
+ * DESCRIPTION: Mutex unlock CameraContext
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+void CameraContext::signalFinished()
+{
+ Mutex::Autolock l(mLock);
+ mInUse = false;
+ mCond.signal();
+}
+
+/*===========================================================================
+ * FUNCTION : saveFile
+ *
+ * DESCRIPTION: helper function for saving buffers on filesystem
+ *
+ * PARAMETERS :
+ * @mem : buffer to save to filesystem
+ * @path: File path
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+status_t CameraContext::saveFile(const sp<IMemory>& mem, String8 path)
+{
+ unsigned char *buff = NULL;
+ ssize_t size;
+ int fd = -1;
+
+ if (mem == NULL) {
+ return BAD_VALUE;
+ }
+
+ fd = open(path, O_CREAT | O_WRONLY | O_TRUNC, 0655);
+ if(fd < 0) {
+ printf("Unable to open file %s %s\n", path.string(), strerror(fd));
+ return -errno;
+ }
+
+ size = (ssize_t)mem->size();
+ if (size <= 0) {
+ printf("IMemory object is of zero size\n");
+ close(fd);
+ return BAD_VALUE;
+ }
+
+ buff = (unsigned char *)mem->pointer();
+ if (!buff) {
+ printf("Buffer pointer is invalid\n");
+ close(fd);
+ return BAD_VALUE;
+ }
+
+ if (size != write(fd, buff, (size_t)size)) {
+ printf("Bad Write error (%d)%s\n", errno, strerror(errno));
+ close(fd);
+ return INVALID_OPERATION;
+ }
+
+ printf("%s: buffer=%p, size=%lld stored at %s\n",
+ __FUNCTION__, buff, (long long int) size, path.string());
+
+ if (fd >= 0)
+ close(fd);
+
+ return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION : PiPCopyToOneFile
+ *
+ * DESCRIPTION: Copy the smaller picture to the bigger one
+ *
+ * PARAMETERS :
+ * @bitmap0 : Decoded image buffer 0
+ * @bitmap1 : Decoded image buffer 1
+ *
+ * RETURN : decoded picture in picture in SkBitmap
+ *==========================================================================*/
+SkBitmap * CameraContext::PiPCopyToOneFile(
+ SkBitmap *bitmap0, SkBitmap *bitmap1)
+{
+ size_t size0;
+ size_t size1;
+ SkBitmap *src;
+ SkBitmap *dst;
+ unsigned int dstOffset;
+ unsigned int srcOffset;
+
+ if (bitmap0 == NULL || bitmap1 == NULL) {
+ ALOGE(" bitmap0 : %p, bitmap1 : %p\n", bitmap0, bitmap1);
+ return NULL;
+ }
+
+ size0 = bitmap0->getSize();
+ if (size0 <= 0) {
+ printf("Decoded image 0 is of zero size\n");
+ return NULL;
+ }
+
+ size1 = bitmap1->getSize();
+ if (size1 <= 0) {
+ printf("Decoded image 1 is of zero size\n");
+ return NULL;
+ }
+
+ if (size0 > size1) {
+ dst = bitmap0;
+ src = bitmap1;
+ } else if (size1 > size0){
+ dst = bitmap1;
+ src = bitmap0;
+ } else {
+ printf("Picture size should be with different size!\n");
+ return NULL;
+ }
+
+ for (unsigned int i = 0; i < (unsigned int)src->height(); i++) {
+ dstOffset = i * (unsigned int)dst->width() * mfmtMultiplier;
+ srcOffset = i * (unsigned int)src->width() * mfmtMultiplier;
+ memcpy(((unsigned char *)dst->getPixels()) + dstOffset,
+ ((unsigned char *)src->getPixels()) + srcOffset,
+ (unsigned int)src->width() * mfmtMultiplier);
+ }
+
+ return dst;
+}
+
+/*===========================================================================
+ * FUNCTION : decodeJPEG
+ *
+ * DESCRIPTION: decode jpeg input buffer.
+ *
+ * PARAMETERS :
+ * @mem : buffer to decode
+ * @skBM : decoded buffer
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+
+ *==========================================================================*/
+status_t CameraContext::decodeJPEG(const sp<IMemory>& mem, SkBitmap *skBM)
+{
+#ifndef USE_SDK_20_OR_HIGHER
+ SkBitmap::Config prefConfig = SkBitmap::kARGB_8888_Config;
+ const void *buff = NULL;
+ size_t size;
+
+ buff = (const void *)mem->pointer();
+ size= mem->size();
+
+ switch(prefConfig) {
+ case SkBitmap::kARGB_8888_Config:
+ {
+ mfmtMultiplier = 4;
+ }
+ break;
+
+ case SkBitmap::kARGB_4444_Config:
+ {
+ mfmtMultiplier = 2;
+ }
+ break;
+
+ case SkBitmap::kRGB_565_Config:
+ {
+ mfmtMultiplier = 2;
+ }
+ break;
+
+ case SkBitmap::kIndex8_Config:
+ {
+ mfmtMultiplier = 4;
+ }
+ break;
+
+ case SkBitmap::kA8_Config:
+ {
+ mfmtMultiplier = 4;
+ }
+ break;
+
+ default:
+ {
+ mfmtMultiplier = 0;
+ printf("Decode format is not correct!\n");
+ }
+ break;
+ }
+
+ if (SkImageDecoder::DecodeMemory(buff, size, skBM, prefConfig,
+ SkImageDecoder::kDecodePixels_Mode) == false) {
+ printf("%s():%d:: Failed during jpeg decode\n",__FUNCTION__,__LINE__);
+ return BAD_VALUE;
+ }
+#else
+ SkColorType prefConfig = kRGBA_8888_SkColorType;
+ const void *buff = NULL;
+ size_t size;
+
+ buff = (const void *)mem->pointer();
+ size= mem->size();
+
+ switch(prefConfig) {
+ case kRGBA_8888_SkColorType:
+ {
+ mfmtMultiplier = 4;
+ }
+ break;
+
+ case kBGRA_8888_SkColorType:
+ {
+ mfmtMultiplier = 4;
+ }
+ break;
+
+ case kARGB_4444_SkColorType:
+ {
+ mfmtMultiplier = 2;
+ }
+ break;
+
+ case kRGB_565_SkColorType:
+ {
+ mfmtMultiplier = 2;
+ }
+ break;
+
+ case kIndex_8_SkColorType:
+ {
+ mfmtMultiplier = 4;
+ }
+ break;
+
+ case kAlpha_8_SkColorType:
+ {
+ mfmtMultiplier = 4;
+ }
+ break;
+
+ default:
+ {
+ mfmtMultiplier = 0;
+ printf("Decode format is not correct!\n");
+ }
+ break;
+ }
+
+ if (SkImageDecoder::DecodeMemory(buff, size, skBM, prefConfig,
+ SkImageDecoder::kDecodePixels_Mode) == false) {
+ printf("%s():%d:: Failed during jpeg decode\n",__FUNCTION__,__LINE__);
+ return BAD_VALUE;
+ }
+
+#endif
+ return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION : encodeJPEG
+ *
+ * DESCRIPTION: encode the decoded input buffer.
+ *
+ * PARAMETERS :
+ * @stream : SkWStream
+ * @bitmap : SkBitmap decoded image to encode
+ * @path : File path
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+
+ *==========================================================================*/
+status_t CameraContext::encodeJPEG(SkWStream * stream,
+ const SkBitmap *bitmap, String8 path)
+{
+ int qFactor = 100;
+
+ skJpegEnc = SkImageEncoder::Create(SkImageEncoder::kJPEG_Type);
+ if (!skJpegEnc) {
+ ALOGE(" skJpegEnc is NULL\n");
+ return BAD_VALUE;
+ }
+
+ if (skJpegEnc->encodeStream(stream, *bitmap, qFactor) == false) {
+ return BAD_VALUE;
+ }
+
+ FILE *fh = fopen(path.string(), "r+");
+ if ( !fh ) {
+ printf("Could not open file %s\n", path.string());
+ return BAD_VALUE;
+ }
+
+ fseek(fh, 0, SEEK_END);
+ size_t len = (size_t)ftell(fh);
+ rewind(fh);
+
+ if( !len ) {
+ printf("File %s is empty !\n", path.string());
+ fclose(fh);
+ return BAD_VALUE;
+ }
+
+ unsigned char *buff = (unsigned char*)malloc(len);
+ if (!buff) {
+ printf("Cannot allocate memory for buffer reading!\n");
+ return BAD_VALUE;
+ }
+
+ size_t readSize = fread(buff, 1, len, fh);
+ if (readSize != len) {
+ printf("Reading error\n");
+ return BAD_VALUE;
+ }
+
+ status_t ret = ReadSectionsFromBuffer(buff, len, READ_ALL);
+ if (ret != NO_ERROR) {
+ printf("Cannot read sections from buffer\n");
+ DiscardData();
+ DiscardSections();
+ return BAD_VALUE;
+ }
+ free(buff);
+ rewind(fh);
+
+ unsigned char temp = 0xff;
+ size_t writeSize = fwrite(&temp, sizeof(unsigned char), 1, fh);
+ if (1 != writeSize) {
+ printf("Writing error\n");
+ }
+ temp = 0xd8;
+ fwrite(&temp, sizeof(unsigned char), 1, fh);
+
+ for (size_t i = 0; i < mSectionsRead; i++) {
+ switch((mSections[i].Type)) {
+
+ case 0x123:
+ fwrite(mSections[i].Data, sizeof(unsigned char),
+ mSections[i].Size, fh);
+ break;
+
+ case 0xe0:
+ temp = 0xff;
+ fwrite(&temp, sizeof(unsigned char), 1, fh);
+ temp = 0xe1;
+ fwrite(&temp, sizeof(unsigned char), 1, fh);
+ fwrite(mJEXIFSection.Data, sizeof(unsigned char),
+ mJEXIFSection.Size, fh);
+ break;
+
+ default:
+ temp = 0xff;
+ fwrite(&temp, sizeof(unsigned char), 1, fh);
+ fwrite(&mSections[i].Type, sizeof(unsigned char), 1, fh);
+ fwrite(mSections[i].Data, sizeof(unsigned char),
+ mSections[i].Size, fh);
+ break;
+ }
+ }
+ fseek(fh, 0, SEEK_END);
+ len = (size_t)ftell(fh);
+ rewind(fh);
+ printf("%s: buffer=%p, size=%zu stored at %s\n",
+ __FUNCTION__, bitmap->getPixels(), len, path.string());
+
+ free(mJEXIFSection.Data);
+ DiscardData();
+ DiscardSections();
+ fclose(fh);
+ ret = NO_ERROR;
+
+ return ret;
+}
+
+/*===========================================================================
+ * FUNCTION : readSectionsFromBuffer
+ *
+ * DESCRIPTION: read all jpeg sections of input buffer.
+ *
+ * PARAMETERS :
+ * @mem : buffer to read from Metadata Sections
+ * @buffer_size: buffer size
+ * @ReadMode: Read mode - all, jpeg or exif
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+status_t CameraContext::ReadSectionsFromBuffer (unsigned char *buffer,
+ size_t buffer_size, ReadMode_t ReadMode)
+{
+ int a;
+ size_t pos = 0;
+ int HaveCom = 0;
+ mSectionsAllocated = 10;
+
+ mSections = (Sections_t *)malloc(sizeof(Sections_t) * mSectionsAllocated);
+ if (!mSections) {
+ printf(" not enough memory\n");
+ return BAD_VALUE;
+ }
+
+ if (!buffer) {
+ printf("Input buffer is null\n");
+ return BAD_VALUE;
+ }
+
+ if (buffer_size < 1) {
+ printf("Input size is 0\n");
+ return BAD_VALUE;
+ }
+
+ a = (int) buffer[pos++];
+
+ if (a != 0xff || buffer[pos++] != M_SOI){
+ printf("No valid image\n");
+ return BAD_VALUE;
+ }
+
+ for(;;){
+ size_t itemlen;
+ int marker = 0;
+ size_t ll,lh;
+ unsigned char * Data;
+
+ CheckSectionsAllocated();
+
+ // The call to CheckSectionsAllocated() may reallocate mSections
+ // so need to check for NULL again.
+ if (mSections == NULL) {
+ printf(" not enough memory\n");
+ return BAD_VALUE;
+ }
+
+ for (a = 0; a <= 16; a++){
+ marker = buffer[pos++];
+ if (marker != 0xff) break;
+
+ if (a >= 16){
+ fprintf(stderr,"too many padding bytes\n");
+ return BAD_VALUE;
+ }
+ }
+
+ mSections[mSectionsRead].Type = marker;
+
+ // Read the length of the section.
+ lh = buffer[pos++];
+ ll = buffer[pos++];
+
+ itemlen = (lh << 8) | ll;
+
+ if (itemlen < 2) {
+ ALOGE("invalid marker");
+ return BAD_VALUE;
+ }
+
+ mSections[mSectionsRead].Size = itemlen;
+
+ Data = (unsigned char *)malloc(itemlen);
+ if (Data == NULL) {
+ ALOGE("Could not allocate memory");
+ return NO_MEMORY;
+ }
+ mSections[mSectionsRead].Data = Data;
+
+ // Store first two pre-read bytes.
+ Data[0] = (unsigned char)lh;
+ Data[1] = (unsigned char)ll;
+
+ if (pos+itemlen-2 > buffer_size) {
+ ALOGE("Premature end of file?");
+ return BAD_VALUE;
+ }
+
+ memcpy(Data+2, buffer+pos, itemlen-2); // Read the whole section.
+ pos += itemlen-2;
+
+ mSectionsRead += 1;
+
+ switch(marker){
+
+ case M_SOS: // stop before hitting compressed data
+ // If reading entire image is requested, read the rest of the
+ // data.
+ if (ReadMode & READ_IMAGE){
+ size_t size;
+ // Determine how much file is left.
+ size = buffer_size - pos;
+
+ if (size < 1) {
+ ALOGE("could not read the rest of the image");
+ return BAD_VALUE;
+ }
+ Data = (unsigned char *)malloc(size);
+ if (Data == NULL) {
+ ALOGE("%d: could not allocate data for entire "
+ "image size: %d", __LINE__, size);
+ return BAD_VALUE;
+ }
+
+ memcpy(Data, buffer+pos, size);
+
+ CheckSectionsAllocated();
+
+ // The call to CheckSectionsAllocated()
+ // may reallocate mSections
+ // so need to check for NULL again.
+ if (mSections == NULL) {
+ printf(" not enough memory\n");
+ return BAD_VALUE;
+ }
+
+ mSections[mSectionsRead].Data = Data;
+ mSections[mSectionsRead].Size = size;
+ mSections[mSectionsRead].Type = PSEUDO_IMAGE_MARKER;
+ mSectionsRead ++;
+ mHaveAll = 1;
+ }
+ return NO_ERROR;
+
+ case M_EOI: // in case it's a tables-only JPEG stream
+ ALOGE("No image in jpeg!\n");
+ return BAD_VALUE;
+
+ case M_COM: // Comment section
+ if (HaveCom || ((ReadMode & READ_METADATA) == 0)){
+ // Discard this section.
+ free(mSections[--mSectionsRead].Data);
+ }
+ break;
+
+ case M_JFIF:
+ // Regular jpegs always have this tag, exif images have the
+ // exif marker instead, althogh ACDsee will write images
+ // with both markers.
+ // this program will re-create this marker on absence of exif
+ // marker.
+ // hence no need to keep the copy from the file.
+ if (ReadMode & READ_METADATA){
+ if (memcmp(Data+2, "JFIF", 4) == 0) {
+ break;
+ }
+ free(mSections[--mSectionsRead].Data);
+ }
+ break;
+
+ case M_EXIF:
+ // There can be different section using the same marker.
+ if (ReadMode & READ_METADATA){
+ if (memcmp(Data+2, "Exif", 4) == 0){
+ break;
+ }else if (memcmp(Data+2, "http:", 5) == 0){
+ // Change tag for internal purposes.
+ mSections[mSectionsRead-1].Type = M_XMP;
+ break;
+ }
+ }
+ // Oterwise, discard this section.
+ free(mSections[--mSectionsRead].Data);
+ break;
+
+ case M_IPTC:
+ if (ReadMode & READ_METADATA){
+ // Note: We just store the IPTC section.
+ // Its relatively straightforward
+ // and we don't act on any part of it,
+ // so just display it at parse time.
+ }else{
+ free(mSections[--mSectionsRead].Data);
+ }
+ break;
+
+ case M_SOF0:
+ case M_SOF1:
+ case M_SOF2:
+ case M_SOF3:
+ case M_SOF5:
+ case M_SOF6:
+ case M_SOF7:
+ case M_SOF9:
+ case M_SOF10:
+ case M_SOF11:
+ case M_SOF13:
+ case M_SOF14:
+ case M_SOF15:
+ break;
+ default:
+ // Skip any other sections.
+ break;
+ }
+ }
+ return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION : CheckSectionsAllocated
+ *
+ * DESCRIPTION: Check allocated jpeg sections.
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+
+ *==========================================================================*/
+void CameraContext::CheckSectionsAllocated(void)
+{
+ if (mSectionsRead > mSectionsAllocated){
+ ALOGE("allocation screw up");
+ }
+ if (mSectionsRead >= mSectionsAllocated){
+ mSectionsAllocated += mSectionsAllocated +1;
+ mSections = (Sections_t *)realloc(mSections,
+ sizeof(Sections_t) * mSectionsAllocated);
+ if (mSections == NULL){
+ ALOGE("could not allocate data for entire image");
+ }
+ }
+}
+
+/*===========================================================================
+ * FUNCTION : findSection
+ *
+ * DESCRIPTION: find the desired Section of the JPEG buffer.
+ *
+ * PARAMETERS :
+ * @SectionType: Section type
+ *
+ * RETURN : return the found section
+
+ *==========================================================================*/
+CameraContext::Sections_t *CameraContext::FindSection(int SectionType)
+{
+ for (unsigned int a = 0; a < mSectionsRead; a++) {
+ if (mSections[a].Type == SectionType){
+ return &mSections[a];
+ }
+ }
+ // Could not be found.
+ return NULL;
+}
+
+
+/*===========================================================================
+ * FUNCTION : DiscardData
+ *
+ * DESCRIPTION: DiscardData
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+
+ *==========================================================================*/
+void CameraContext::DiscardData()
+{
+ for (unsigned int a = 0; a < mSectionsRead; a++) {
+ free(mSections[a].Data);
+ }
+
+ mSectionsRead = 0;
+ mHaveAll = 0;
+}
+
+/*===========================================================================
+ * FUNCTION : DiscardSections
+ *
+ * DESCRIPTION: Discard allocated sections
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+
+ *==========================================================================*/
+void CameraContext::DiscardSections()
+{
+ free(mSections);
+ mSectionsAllocated = 0;
+ mHaveAll = 0;
+}
+
+/*===========================================================================
+ * FUNCTION : notify
+ *
+ * DESCRIPTION: notify callback
+ *
+ * PARAMETERS :
+ * @msgType : type of callback
+ * @ext1: extended parameters
+ * @ext2: extended parameters
+ *
+ * RETURN : None
+ *==========================================================================*/
+void CameraContext::notify(int32_t msgType, int32_t ext1, int32_t ext2)
+{
+ printf("Notify cb: %d %d %d\n", msgType, ext1, ext2);
+
+ if (( msgType & CAMERA_MSG_PREVIEW_FRAME)
+#ifndef VANILLA_HAL
+ && (ext1 == CAMERA_FRAME_DATA_FD)
+#endif
+ )
+ {
+ int fd = dup(ext2);
+ printf("notify Preview Frame fd: %d dup fd: %d\n", ext2, fd);
+ close(fd);
+ }
+
+ if ( msgType & CAMERA_MSG_FOCUS ) {
+ printf("AutoFocus %s \n",
+ (ext1) ? "OK" : "FAIL");
+ }
+
+ if ( msgType & CAMERA_MSG_SHUTTER ) {
+ printf("Shutter done \n");
+ }
+
+ if ( msgType & CAMERA_MSG_ERROR) {
+ printf("Camera Test CAMERA_MSG_ERROR\n");
+ stopPreview();
+ closeCamera();
+ }
+}
+
+/*===========================================================================
+ * FUNCTION : postData
+ *
+ * DESCRIPTION: handles data callbacks
+ *
+ * PARAMETERS :
+ * @msgType : type of callback
+ * @dataPtr: buffer data
+ * @metadata: additional metadata where available
+ *
+ * RETURN : None
+ *==========================================================================*/
+void CameraContext::postData(int32_t msgType,
+ const sp<IMemory>& dataPtr,
+ camera_frame_metadata_t *metadata)
+{
+ mInterpr->PiPLock();
+ Size currentPictureSize = mSupportedPictureSizes.itemAt(
+ mCurrentPictureSizeIdx);
+ unsigned char *buff = NULL;
+ size_t size;
+ status_t ret = 0;
+
+ memset(&mJEXIFSection, 0, sizeof(mJEXIFSection)),
+
+ printf("Data cb: %d\n", msgType);
+
+ if ( msgType & CAMERA_MSG_PREVIEW_FRAME ) {
+ previewCallback(dataPtr);
+ }
+
+ if ( msgType & CAMERA_MSG_RAW_IMAGE ) {
+ printf("RAW done \n");
+ }
+
+ if (msgType & CAMERA_MSG_POSTVIEW_FRAME) {
+ printf("Postview frame \n");
+ }
+
+ if (msgType & CAMERA_MSG_COMPRESSED_IMAGE ) {
+ String8 jpegPath;
+ jpegPath = jpegPath.format(QCAMERA_DUMP_FRM_LOCATION"img_%d.jpg",
+ JpegIdx);
+ if (!mPiPCapture) {
+ // Normal capture case
+ printf("JPEG done\n");
+ saveFile(dataPtr, jpegPath);
+ JpegIdx++;
+ } else {
+ // PiP capture case
+ SkFILEWStream *wStream;
+ ret = decodeJPEG(dataPtr, &skBMtmp);
+ if (NO_ERROR != ret) {
+ printf("Error in decoding JPEG!\n");
+ mInterpr->PiPUnlock();
+ return;
+ }
+
+ mWidthTmp = currentPictureSize.width;
+ mHeightTmp = currentPictureSize.height;
+ PiPPtrTmp = dataPtr;
+ // If there are two jpeg buffers
+ if (mPiPIdx == 1) {
+ printf("PiP done\n");
+
+ // Find the the capture with higher width and height and read
+ // its jpeg sections
+ if ((mInterpr->camera[0]->mWidthTmp * mInterpr->camera[0]->mHeightTmp) >
+ (mInterpr->camera[1]->mWidthTmp * mInterpr->camera[1]->mHeightTmp)) {
+ buff = (unsigned char *)PiPPtrTmp->pointer();
+ size= PiPPtrTmp->size();
+ } else if ((mInterpr->camera[0]->mWidthTmp * mInterpr->camera[0]->mHeightTmp) <
+ (mInterpr->camera[1]->mWidthTmp * mInterpr->camera[1]->mHeightTmp)) {
+ buff = (unsigned char *)PiPPtrTmp->pointer();
+ size= PiPPtrTmp->size();
+ } else {
+ printf("Cannot take PiP. Images are with the same width"
+ " and height size!!!\n");
+ mInterpr->PiPUnlock();
+ return;
+ }
+
+ if (buff != NULL && size != 0) {
+ ret = ReadSectionsFromBuffer(buff, size, READ_ALL);
+ if (ret != NO_ERROR) {
+ printf("Cannot read sections from buffer\n");
+ DiscardData();
+ DiscardSections();
+ mInterpr->PiPUnlock();
+ return;
+ }
+
+ mJEXIFTmp = FindSection(M_EXIF);
+ if (!mJEXIFTmp) {
+ ALOGE("skBMDec is null\n");
+ DiscardData();
+ DiscardSections();
+ return;
+ }
+ mJEXIFSection = *mJEXIFTmp;
+ mJEXIFSection.Data = (unsigned char*)malloc(mJEXIFTmp->Size);
+ if (!mJEXIFSection.Data) {
+ ALOGE(" Not enough memory\n");
+ DiscardData();
+ DiscardSections();
+ return;
+ }
+ memcpy(mJEXIFSection.Data,
+ mJEXIFTmp->Data, mJEXIFTmp->Size);
+ DiscardData();
+ DiscardSections();
+
+ wStream = new SkFILEWStream(jpegPath.string());
+ skBMDec = PiPCopyToOneFile(&mInterpr->camera[0]->skBMtmp,
+ &mInterpr->camera[1]->skBMtmp);
+ if (!skBMDec) {
+ ALOGE("skBMDec is null\n");
+ delete wStream;
+ return;
+ }
+
+ if (encodeJPEG(wStream, skBMDec, jpegPath) != false) {
+ printf("%s():%d:: Failed during jpeg encode\n",
+ __FUNCTION__,__LINE__);
+ mInterpr->PiPUnlock();
+ return;
+ }
+ mPiPIdx = 0;
+ JpegIdx++;
+ delete wStream;
+ }
+ } else {
+ mPiPIdx++;
+ }
+ disablePiPCapture();
+ }
+ }
+
+ if ((msgType & CAMERA_MSG_PREVIEW_METADATA) && (NULL != metadata)) {
+ printf("Face detected %d \n", metadata->number_of_faces);
+ }
+ mInterpr->PiPUnlock();
+
+}
+
+/*===========================================================================
+ * FUNCTION : postDataTimestamp
+ *
+ * DESCRIPTION: handles recording callbacks
+ *
+ * PARAMETERS :
+ * @timestamp : timestamp of buffer
+ * @msgType : type of buffer
+ * @dataPtr : buffer data
+ *
+ * RETURN : None
+ *==========================================================================*/
+void CameraContext::postDataTimestamp(nsecs_t timestamp,
+ int32_t msgType,
+ const sp<IMemory>& dataPtr)
+{
+ printf("Recording cb: %d %lld %p\n",
+ msgType, (long long int)timestamp, dataPtr.get());
+}
+
+/*===========================================================================
+ * FUNCTION : dataCallbackTimestamp
+ *
+ * DESCRIPTION: handles recording callbacks. Used for ViV recording
+ *
+ * PARAMETERS :
+ * @timestamp : timestamp of buffer
+ * @msgType : type of buffer
+ * @dataPtr : buffer data
+ *
+ * RETURN : None
+ *==========================================================================*/
+void CameraContext::dataCallbackTimestamp(nsecs_t timestamp,
+ int32_t msgType,
+ const sp<IMemory>& dataPtr)
+{
+ mInterpr->ViVLock();
+ // Not needed check. Just avoiding warnings of not used variables.
+ if (timestamp > 0)
+ timestamp = 0;
+ // Not needed check. Just avoiding warnings of not used variables.
+ if (msgType > 0)
+ msgType = 0;
+ size_t i = 0;
+ void * srcBuff = NULL;
+ void * dstBuff = NULL;
+
+ size_t srcYStride = 0, dstYStride = 0;
+ size_t srcUVStride = 0, dstUVStride = 0;
+ size_t srcYScanLines = 0, dstYScanLines = 0;
+ size_t srcUVScanLines = 0, dstUVScanLines = 0;
+ size_t srcOffset = 0, dstOffset = 0;
+ size_t srcBaseOffset = 0;
+ size_t dstBaseOffset = 0;
+ Size currentVideoSize = mSupportedVideoSizes.itemAt(mCurrentVideoSizeIdx);
+ status_t err = NO_ERROR;
+ ANativeWindowBuffer* anb = NULL;
+
+ dstBuff = (void *) dataPtr->pointer();
+ if (NULL == dstBuff) {
+ printf("Cannot access destination buffer!!!\n");
+ mInterpr->ViVUnlock();
+ return;
+ }
+
+ if (mCameraIndex == mInterpr->mViVVid.sourceCameraID) {
+ srcYStride = calcStride(currentVideoSize.width);
+ srcUVStride = calcStride(currentVideoSize.width);
+ srcYScanLines = calcYScanLines(currentVideoSize.height);
+ srcUVScanLines = calcUVScanLines(currentVideoSize.height);
+ mInterpr->mViVBuff.srcWidth = (size_t)currentVideoSize.width;
+ mInterpr->mViVBuff.srcHeight = (size_t)currentVideoSize.height;
+
+
+ mInterpr->mViVBuff.YStride = srcYStride;
+ mInterpr->mViVBuff.UVStride = srcUVStride;
+ mInterpr->mViVBuff.YScanLines = srcYScanLines;
+ mInterpr->mViVBuff.UVScanLines = srcUVScanLines;
+
+ memcpy( mInterpr->mViVBuff.buff, dstBuff,
+ mInterpr->mViVBuff.buffSize);
+
+ mInterpr->mViVVid.isBuffValid = true;
+ } else if (mCameraIndex == mInterpr->mViVVid.destinationCameraID) {
+ if(mInterpr->mViVVid.isBuffValid == true) {
+ dstYStride = calcStride(currentVideoSize.width);
+ dstUVStride = calcStride(currentVideoSize.width);
+ dstYScanLines = calcYScanLines(currentVideoSize.height);
+ dstUVScanLines = calcUVScanLines(currentVideoSize.height);
+
+ srcYStride = mInterpr->mViVBuff.YStride;
+ srcUVStride = mInterpr->mViVBuff.UVStride;
+ srcYScanLines = mInterpr->mViVBuff.YScanLines;
+ srcUVScanLines = mInterpr->mViVBuff.UVScanLines;
+
+
+ for (i = 0; i < mInterpr->mViVBuff.srcHeight; i++) {
+ srcOffset = i*srcYStride;
+ dstOffset = i*dstYStride;
+ memcpy((unsigned char *) dstBuff + dstOffset,
+ (unsigned char *) mInterpr->mViVBuff.buff +
+ srcOffset, mInterpr->mViVBuff.srcWidth);
+ }
+ srcBaseOffset = srcYStride * srcYScanLines;
+ dstBaseOffset = dstYStride * dstYScanLines;
+ for (i = 0; i < mInterpr->mViVBuff.srcHeight / 2; i++) {
+ srcOffset = i*srcUVStride + srcBaseOffset;
+ dstOffset = i*dstUVStride + dstBaseOffset;
+ memcpy((unsigned char *) dstBuff + dstOffset,
+ (unsigned char *) mInterpr->mViVBuff.buff +
+ srcOffset, mInterpr->mViVBuff.srcWidth);
+ }
+
+ err = native_window_dequeue_buffer_and_wait(
+ mInterpr->mViVVid.ANW.get(),&anb);
+ if (err != NO_ERROR) {
+ printf("Cannot dequeue anb for sensor %d!!!\n", mCameraIndex);
+ mInterpr->ViVUnlock();
+ return;
+ }
+ mInterpr->mViVVid.graphBuf = new GraphicBuffer(anb, false);
+ if(NULL == mInterpr->mViVVid.graphBuf.get()) {
+ printf("Invalid Graphic buffer\n");
+ mInterpr->ViVUnlock();
+ return;
+ }
+ err = mInterpr->mViVVid.graphBuf->lock(
+ GRALLOC_USAGE_SW_WRITE_OFTEN,
+ (void**)(&mInterpr->mViVVid.mappedBuff));
+ if (err != NO_ERROR) {
+ printf("Graphic buffer could not be locked %d!!!\n", err);
+ mInterpr->ViVUnlock();
+ return;
+ }
+
+ srcYStride = dstYStride;
+ srcUVStride = dstUVStride;
+ srcYScanLines = dstYScanLines;
+ srcUVScanLines = dstUVScanLines;
+ srcBuff = dstBuff;
+
+ for (i = 0; i < (size_t)currentVideoSize.height; i++) {
+ srcOffset = i*srcYStride;
+ dstOffset = i*dstYStride;
+ memcpy((unsigned char *) mInterpr->mViVVid.mappedBuff +
+ dstOffset, (unsigned char *) srcBuff +
+ srcOffset, (size_t)currentVideoSize.width);
+ }
+
+ srcBaseOffset = srcYStride * srcYScanLines;
+ dstBaseOffset = dstUVStride * (size_t)currentVideoSize.height;
+
+ for (i = 0; i < (size_t)currentVideoSize.height / 2; i++) {
+ srcOffset = i*srcUVStride + srcBaseOffset;
+ dstOffset = i*dstUVStride + dstBaseOffset;
+ memcpy((unsigned char *) mInterpr->mViVVid.mappedBuff +
+ dstOffset, (unsigned char *) srcBuff +
+ srcOffset, (size_t)currentVideoSize.width);
+ }
+
+
+ mInterpr->mViVVid.graphBuf->unlock();
+
+ err = mInterpr->mViVVid.ANW->queueBuffer(
+ mInterpr->mViVVid.ANW.get(), anb, -1);
+ if(err)
+ printf("Failed to enqueue buffer to recorder!!!\n");
+ }
+ }
+ mCamera->releaseRecordingFrame(dataPtr);
+
+ mInterpr->ViVUnlock();
+}
+
+/*===========================================================================
+ * FUNCTION : ViVEncoderThread
+ *
+ * DESCRIPTION: Creates a separate thread for ViV recording
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : None
+ *==========================================================================*/
+status_t Interpreter::ViVEncoderThread()
+{
+ int ret = NO_ERROR;
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+
+ ret = pthread_create(&mViVEncThread, &attr, ThreadWrapper, this);
+ ret = pthread_attr_destroy(&attr);
+
+ return ret;
+}
+
+/*===========================================================================
+ * FUNCTION : ThreadWrapper
+ *
+ * DESCRIPTION: Helper function for for ViV recording thread
+ *
+ * PARAMETERS : Interpreter context
+ *
+ * RETURN : None
+ *==========================================================================*/
+void *Interpreter::ThreadWrapper(void *context) {
+ Interpreter *writer = static_cast<Interpreter *>(context);
+ writer->ViVEncode();
+ return NULL;
+}
+
+/*===========================================================================
+ * FUNCTION : ViVEncode
+ *
+ * DESCRIPTION: Thread for ViV encode. Buffers from video codec are sent to
+ * muxer and saved in a file.
+ *
+ * PARAMETERS : Interpreter context
+ *
+ * RETURN : None
+ *==========================================================================*/
+void Interpreter::ViVEncode()
+{
+ status_t err = NO_ERROR;
+ ssize_t trackIdx = -1;
+ uint32_t debugNumFrames = 0;
+
+ size_t bufIndex, offset, size;
+ int64_t ptsUsec;
+ uint32_t flags;
+ bool DoRecording = true;
+
+
+ err = mTestContext->mViVVid.codec->getOutputBuffers(
+ &mTestContext->mViVVid.buffers);
+ if (err != NO_ERROR) {
+ printf("Unable to get output buffers (err=%d)\n", err);
+ }
+
+ while (DoRecording) {
+ err = mTestContext->mViVVid.codec->dequeueOutputBuffer(
+ &bufIndex,
+ &offset,
+ &size,
+ &ptsUsec,
+ &flags, -1);
+
+ switch (err) {
+
+ case NO_ERROR:
+ // got a buffer
+ if ((flags & MediaCodec::BUFFER_FLAG_CODECCONFIG) != 0) {
+ // ignore this -- we passed the CSD into MediaMuxer when
+ // we got the format change notification
+ size = 0;
+ }
+ if (size != 0) {
+ // If the virtual display isn't providing us with timestamps,
+ // use the current time.
+ if (ptsUsec == 0) {
+ ptsUsec = systemTime(SYSTEM_TIME_MONOTONIC) / 1000;
+ }
+
+ // The MediaMuxer docs are unclear, but it appears that we
+ // need to pass either the full set of BufferInfo flags, or
+ // (flags & BUFFER_FLAG_SYNCFRAME).
+ err = mTestContext->mViVVid.muxer->writeSampleData(
+ mTestContext->mViVVid.buffers[bufIndex],
+ (size_t)trackIdx,
+ ptsUsec,
+ flags);
+ if (err != NO_ERROR) {
+ fprintf(stderr, "Failed writing data to muxer (err=%d)\n",
+ err);
+ }
+ debugNumFrames++;
+ }
+ err = mTestContext->mViVVid.codec->releaseOutputBuffer(bufIndex);
+ if (err != NO_ERROR) {
+ fprintf(stderr, "Unable to release output buffer (err=%d)\n",
+ err);
+ }
+ if ((flags & MediaCodec::BUFFER_FLAG_EOS) != 0) {
+ // Not expecting EOS from SurfaceFlinger. Go with it.
+ printf("Received end-of-stream\n");
+ //DoRecording = false;
+ }
+ break;
+ case -EAGAIN: // INFO_TRY_AGAIN_LATER
+ ALOGV("Got -EAGAIN, looping");
+ break;
+ case INFO_FORMAT_CHANGED: // INFO_OUTPUT_FORMAT_CHANGED
+ {
+ // format includes CSD, which we must provide to muxer
+ sp<AMessage> newFormat;
+ mTestContext->mViVVid.codec->getOutputFormat(&newFormat);
+ trackIdx = mTestContext->mViVVid.muxer->addTrack(newFormat);
+ err = mTestContext->mViVVid.muxer->start();
+ if (err != NO_ERROR) {
+ printf("Unable to start muxer (err=%d)\n", err);
+ }
+ }
+ break;
+ case INFO_OUTPUT_BUFFERS_CHANGED: // INFO_OUTPUT_BUFFERS_CHANGED
+ // not expected for an encoder; handle it anyway
+ ALOGV("Encoder buffers changed");
+ err = mTestContext->mViVVid.codec->getOutputBuffers(
+ &mTestContext->mViVVid.buffers);
+ if (err != NO_ERROR) {
+ printf("Unable to get new output buffers (err=%d)\n", err);
+ }
+ break;
+ case INVALID_OPERATION:
+ DoRecording = false;
+ break;
+ default:
+ printf("Got weird result %d from dequeueOutputBuffer\n", err);
+ break;
+ }
+ }
+
+ return;
+}
+
+/*===========================================================================
+ * FUNCTION : calcBufferSize
+ *
+ * DESCRIPTION: Temp buffer size calculation. Temp buffer is used to store
+ * the buffer from the camera with smaller resolution. It is
+ * copied to the buffer from camera with higher resolution.
+ *
+ * PARAMETERS :
+ * @width : video size width
+ * @height : video size height
+ *
+ * RETURN : size_t
+ *==========================================================================*/
+size_t CameraContext::calcBufferSize(int width, int height)
+{
+ size_t size = 0;
+ size_t UVAlignment;
+ size_t YPlane, UVPlane, YStride, UVStride, YScanlines, UVScanlines;
+ if (!width || !height) {
+ return size;
+ }
+ UVAlignment = 4096;
+ YStride = calcStride(width);
+ UVStride = calcStride(width);
+ YScanlines = calcYScanLines(height);
+ UVScanlines = calcUVScanLines(height);
+ YPlane = YStride * YScanlines;
+ UVPlane = UVStride * UVScanlines + UVAlignment;
+ size = YPlane + UVPlane;
+ size = VIDEO_BUF_ALLIGN(size, 4096);
+
+ return size;
+}
+
+/*===========================================================================
+ * FUNCTION : calcStride
+ *
+ * DESCRIPTION: Temp buffer stride calculation.
+ *
+ * PARAMETERS :
+ * @width : video size width
+ *
+ * RETURN : size_t
+ *==========================================================================*/
+size_t CameraContext::calcStride(int width)
+{
+ size_t alignment, stride = 0;
+ if (!width) {
+ return stride;
+ }
+ alignment = 128;
+ stride = VIDEO_BUF_ALLIGN((size_t)width, alignment);
+
+ return stride;
+}
+
+/*===========================================================================
+ * FUNCTION : calcYScanLines
+ *
+ * DESCRIPTION: Temp buffer scanlines calculation for Y plane.
+ *
+ * PARAMETERS :
+ * @width : video size height
+ *
+ * RETURN : size_t
+ *==========================================================================*/
+size_t CameraContext::calcYScanLines(int height)
+{
+ size_t alignment, scanlines = 0;
+ if (!height) {
+ return scanlines;
+ }
+ alignment = 32;
+ scanlines = VIDEO_BUF_ALLIGN((size_t)height, alignment);
+
+ return scanlines;
+}
+
+/*===========================================================================
+ * FUNCTION : calcUVScanLines
+ *
+ * DESCRIPTION: Temp buffer scanlines calculation for UV plane.
+ *
+ * PARAMETERS :
+ * @width : video size height
+ *
+ * RETURN : size_t
+ *==========================================================================*/
+size_t CameraContext::calcUVScanLines(int height)
+{
+ size_t alignment, scanlines = 0;
+ if (!height) {
+ return scanlines;
+ }
+ alignment = 16;
+ scanlines = VIDEO_BUF_ALLIGN((size_t)((height + 1) >> 1), alignment);
+
+ return scanlines;
+}
+
+/*===========================================================================
+ * FUNCTION : printSupportedParams
+ *
+ * DESCRIPTION: dump common supported parameters
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : None
+ *==========================================================================*/
+void CameraContext::printSupportedParams()
+{
+ const char *camera_ids = mParams.get("camera-indexes");
+ const char *pic_sizes = mParams.get(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES);
+ const char *pic_formats = mParams.get(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS);
+ const char *preview_sizes = mParams.get(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES);
+ const char *video_sizes = mParams.get(CameraParameters::KEY_SUPPORTED_VIDEO_SIZES);
+ const char *preview_formats = mParams.get(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS);
+ const char *frame_rates = mParams.get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES);
+ const char *thumb_sizes = mParams.get(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES);
+ const char *wb_modes = mParams.get(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE);
+ const char *effects = mParams.get(CameraParameters::KEY_SUPPORTED_EFFECTS);
+ const char *scene_modes = mParams.get(CameraParameters::KEY_SUPPORTED_SCENE_MODES);
+ const char *focus_modes = mParams.get(CameraParameters::KEY_SUPPORTED_FOCUS_MODES);
+ const char *antibanding_modes = mParams.get(CameraParameters::KEY_SUPPORTED_ANTIBANDING);
+ const char *flash_modes = mParams.get(CameraParameters::KEY_SUPPORTED_FLASH_MODES);
+ int focus_areas = mParams.getInt(CameraParameters::KEY_MAX_NUM_FOCUS_AREAS);
+ const char *fps_ranges = mParams.get(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE);
+ const char *focus_distances = mParams.get(CameraParameters::KEY_FOCUS_DISTANCES);
+
+ printf("\n\r\tSupported Cameras: %s",
+ (camera_ids != NULL)? camera_ids : "NULL");
+ printf("\n\r\tSupported Picture Sizes: %s",
+ (pic_sizes != NULL)? pic_sizes : "NULL");
+ printf("\n\r\tSupported Picture Formats: %s",
+ (pic_formats != NULL)? pic_formats : "NULL");
+ printf("\n\r\tSupported Preview Sizes: %s",
+ (preview_sizes != NULL)? preview_sizes : "NULL");
+ printf("\n\r\tSupported Video Sizes: %s",
+ (video_sizes != NULL)? video_sizes : "NULL");
+ printf("\n\r\tSupported Preview Formats: %s",
+ (preview_formats != NULL)? preview_formats : "NULL");
+ printf("\n\r\tSupported Preview Frame Rates: %s",
+ (frame_rates != NULL)? frame_rates : "NULL");
+ printf("\n\r\tSupported Thumbnail Sizes: %s",
+ (thumb_sizes != NULL)? thumb_sizes : "NULL");
+ printf("\n\r\tSupported Whitebalance Modes: %s",
+ (wb_modes != NULL)? wb_modes : "NULL");
+ printf("\n\r\tSupported Effects: %s",
+ (effects != NULL)? effects : "NULL");
+ printf("\n\r\tSupported Scene Modes: %s",
+ (scene_modes != NULL)? scene_modes : "NULL");
+ printf("\n\r\tSupported Focus Modes: %s",
+ (focus_modes != NULL)? focus_modes : "NULL");
+ printf("\n\r\tSupported Antibanding Options: %s",
+ (antibanding_modes != NULL)? antibanding_modes : "NULL");
+ printf("\n\r\tSupported Flash Modes: %s",
+ (flash_modes != NULL)? flash_modes : "NULL");
+ printf("\n\r\tSupported Focus Areas: %d", focus_areas);
+ printf("\n\r\tSupported FPS ranges : %s",
+ (fps_ranges != NULL)? fps_ranges : "NULL");
+ printf("\n\r\tFocus Distances: %s \n",
+ (focus_distances != NULL)? focus_distances : "NULL");
+}
+
+/*===========================================================================
+ * FUNCTION : createPreviewSurface
+ *
+ * DESCRIPTION: helper function for creating preview surfaces
+ *
+ * PARAMETERS :
+ * @width : preview width
+ * @height: preview height
+ * @pixFormat : surface pixelformat
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+status_t CameraContext::createPreviewSurface(int width, int height, int32_t pixFormat)
+{
+ int ret = NO_ERROR;
+ DisplayInfo dinfo;
+ sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(
+ ISurfaceComposer::eDisplayIdMain));
+ SurfaceComposerClient::getDisplayInfo(display, &dinfo);
+ uint32_t previewWidth, previewHeight;
+
+ if ((0 >= width) || (0 >= height)) {
+ printf("Bad preview surface size %dx%d\n", width, height);
+ return BAD_VALUE;
+ }
+
+ if ((int)dinfo.w < width) {
+ previewWidth = dinfo.w;
+ } else {
+ previewWidth = (unsigned int)width;
+ }
+
+ if ((int)dinfo.h < height) {
+ previewHeight = dinfo.h;
+ } else {
+ previewHeight = (unsigned int)height;
+ }
+
+ mClient = new SurfaceComposerClient();
+
+ if ( NULL == mClient.get() ) {
+ printf("Unable to establish connection to Surface Composer \n");
+ return NO_INIT;
+ }
+
+ mSurfaceControl = mClient->createSurface(String8("QCamera_Test"),
+ previewWidth,
+ previewHeight,
+ pixFormat,
+ 0);
+ if ( NULL == mSurfaceControl.get() ) {
+ printf("Unable to create preview surface \n");
+ return NO_INIT;
+ }
+
+ mPreviewSurface = mSurfaceControl->getSurface();
+ if ( NULL != mPreviewSurface.get() ) {
+ mClient->openGlobalTransaction();
+ ret |= mSurfaceControl->setLayer(0x7fffffff);
+ if ( mCameraIndex == 0 )
+ ret |= mSurfaceControl->setPosition(0, 0);
+ else
+ ret |= mSurfaceControl->setPosition((float)(dinfo.w - previewWidth),
+ (float)(dinfo.h - previewHeight));
+
+ ret |= mSurfaceControl->setSize(previewWidth, previewHeight);
+ ret |= mSurfaceControl->show();
+ mClient->closeGlobalTransaction();
+
+ if ( NO_ERROR != ret ) {
+ printf("Preview surface configuration failed! \n");
+ }
+ } else {
+ ret = NO_INIT;
+ }
+
+ return ret;
+}
+
+/*===========================================================================
+ * FUNCTION : destroyPreviewSurface
+ *
+ * DESCRIPTION: closes previously open preview surface
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+status_t CameraContext::destroyPreviewSurface()
+{
+ if ( NULL != mPreviewSurface.get() ) {
+ mPreviewSurface.clear();
+ }
+
+ if ( NULL != mSurfaceControl.get() ) {
+ mSurfaceControl->clear();
+ mSurfaceControl.clear();
+ }
+
+ if ( NULL != mClient.get() ) {
+ mClient->dispose();
+ mClient.clear();
+ }
+
+ return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION : CameraContext
+ *
+ * DESCRIPTION: camera context constructor
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : None
+ *==========================================================================*/
+CameraContext::CameraContext(int cameraIndex) :
+ mCameraIndex(cameraIndex),
+ mResizePreview(true),
+ mHardwareActive(false),
+ mPreviewRunning(false),
+ mRecordRunning(false),
+ mVideoFd(-1),
+ mVideoIdx(0),
+ mRecordingHint(false),
+ mDoPrintMenu(true),
+ mPiPCapture(false),
+ mfmtMultiplier(1),
+ mSectionsRead(false),
+ mSectionsAllocated(0),
+ mSections(NULL),
+ mJEXIFTmp(NULL),
+ mHaveAll(false),
+ mCamera(NULL),
+ mClient(NULL),
+ mSurfaceControl(NULL),
+ mPreviewSurface(NULL),
+ mInUse(false)
+{
+ mRecorder = new MediaRecorder(String16("camera"));
+}
+
+/*===========================================================================
+ * FUNCTION : setTestCtxInstance
+ *
+ * DESCRIPTION : Sends TestContext instance to CameraContext
+ *
+ * PARAMETERS :
+ * @instance : TestContext instance
+ *
+ * RETURN : None
+ *==========================================================================*/
+void CameraContext::setTestCtxInstance(TestContext *instance)
+{
+ mInterpr = instance;
+}
+
+/*===========================================================================
+ * FUNCTION : setTestCtxInst
+ *
+ * DESCRIPTION : Sends TestContext instance to Interpreter
+ *
+ * PARAMETERS :
+ * @instance : TestContext instance
+ *
+ * RETURN : None
+ *==========================================================================*/
+void Interpreter::setTestCtxInst(TestContext *instance)
+{
+ mTestContext = instance;
+}
+
+/*===========================================================================
+ * FUNCTION : ~CameraContext
+ *
+ * DESCRIPTION: camera context destructor
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : None
+ *==========================================================================*/
+CameraContext::~CameraContext()
+{
+ stopPreview();
+ closeCamera();
+}
+
+/*===========================================================================
+ * FUNCTION : openCamera
+ *
+ * DESCRIPTION: connects to and initializes camera
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+status_t CameraContext::openCamera()
+{
+ useLock();
+ const char *ZSLStr = NULL;
+ size_t ZSLStrSize = 0;
+
+ if ( NULL != mCamera.get() ) {
+ printf("Camera already open! \n");
+ signalFinished();
+ return NO_ERROR;
+ }
+
+ printf("openCamera(camera_index=%d)\n", mCameraIndex);
+
+#ifndef USE_JB_MR1
+
+ String16 packageName("CameraTest");
+
+ mCamera = Camera::connect(mCameraIndex,
+ packageName,
+ Camera::USE_CALLING_UID);
+
+#else
+
+ mCamera = Camera::connect(mCameraIndex);
+
+#endif
+
+ if ( NULL == mCamera.get() ) {
+ printf("Unable to connect to CameraService\n");
+ signalFinished();
+ return NO_INIT;
+ }
+
+ mParams = mCamera->getParameters();
+ mParams.getSupportedPreviewSizes(mSupportedPreviewSizes);
+ mParams.getSupportedPictureSizes(mSupportedPictureSizes);
+ mParams.getSupportedVideoSizes(mSupportedVideoSizes);
+
+ mCurrentPictureSizeIdx = mSupportedPictureSizes.size() / 2;
+ mCurrentPreviewSizeIdx = mSupportedPreviewSizes.size() / 2;
+ mCurrentVideoSizeIdx = mSupportedVideoSizes.size() / 2;
+
+ mCamera->setListener(this);
+ mHardwareActive = true;
+
+ mInterpr->setViVSize((Size) mSupportedVideoSizes.itemAt(
+ mCurrentVideoSizeIdx),
+ mCameraIndex);
+
+ ZSLStr = mParams.get(CameraContext::KEY_ZSL);
+ if (NULL != ZSLStr) {
+ ZSLStrSize = strlen(ZSLStr);
+ if (!strncmp(ZSLStr, "on", ZSLStrSize)) {
+ mInterpr->mIsZSLOn = true;
+ } else if (!strncmp(ZSLStr, "off", ZSLStrSize)) {
+ mInterpr->mIsZSLOn = false;
+ } else {
+ printf("zsl value is not valid!\n");
+ }
+ } else {
+ printf("zsl is NULL\n");
+ }
+
+ signalFinished();
+
+ return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION : onAsBinder
+ *
+ * DESCRIPTION: onAsBinder
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : Pointer to IBinder
+ *==========================================================================*/
+IBinder* CameraContext::onAsBinder() {
+ return NULL;
+}
+
+/*===========================================================================
+ * FUNCTION : getNumberOfCameras
+ *
+ * DESCRIPTION: returns the number of supported camera by the system
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : supported camera count
+ *==========================================================================*/
+int CameraContext::getNumberOfCameras()
+{
+ int ret = -1;
+
+ if ( NULL != mCamera.get() ) {
+ ret = mCamera->getNumberOfCameras();
+ }
+
+ return ret;
+}
+
+/*===========================================================================
+ * FUNCTION : closeCamera
+ *
+ * DESCRIPTION: closes a previously the initialized camera reference
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+status_t CameraContext::closeCamera()
+{
+ useLock();
+ if ( NULL == mCamera.get() ) {
+ return NO_INIT;
+ }
+
+ mCamera->disconnect();
+ mCamera.clear();
+
+ mRecorder->init();
+ mRecorder->close();
+ mRecorder->release();
+ mRecorder.clear();
+
+ mHardwareActive = false;
+ mPreviewRunning = false;
+ mRecordRunning = false;
+
+ signalFinished();
+ return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION : startPreview
+ *
+ * DESCRIPTION: starts camera preview
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+status_t CameraContext::startPreview()
+{
+ useLock();
+
+ int ret = NO_ERROR;
+ int previewWidth, previewHeight;
+ Size calculatedPreviewSize;
+ Size currentPreviewSize = mSupportedPreviewSizes.itemAt(
+ mCurrentPreviewSizeIdx);
+ Size currentPictureSize = mSupportedPictureSizes.itemAt(
+ mCurrentPictureSizeIdx);
+ Size currentVideoSize = mSupportedVideoSizes.itemAt(
+ mCurrentVideoSizeIdx);
+
+#ifndef USE_JB_MR1
+
+ sp<IGraphicBufferProducer> gbp;
+
+#endif
+
+ if (!mHardwareActive ) {
+ printf("Camera not active! \n");
+ return NO_INIT;
+ }
+
+ if (mPreviewRunning) {
+ printf("Preview is already running! \n");
+ signalFinished();
+ return NO_ERROR;
+ }
+
+ if (mResizePreview) {
+ mPreviewRunning = false;
+
+ if ( mRecordingHint ) {
+ calculatedPreviewSize =
+ getPreviewSizeFromVideoSizes(currentVideoSize);
+ previewWidth = calculatedPreviewSize.width;
+ previewHeight = calculatedPreviewSize.height;
+ } else {
+ previewWidth = currentPreviewSize.width;
+ previewHeight = currentPreviewSize.height;
+ }
+
+ ret = createPreviewSurface(previewWidth,
+ previewHeight,
+ HAL_PIXEL_FORMAT_YCrCb_420_SP);
+ if ( NO_ERROR != ret ) {
+ printf("Error while creating preview surface\n");
+ return ret;
+ }
+
+ // set rdi mode if system prop is set for front camera
+ if (mCameraIndex == 1) {
+ char value[32];
+ property_get("persist.camera.rdimode", value, "0");
+ int rdimode = atoi(value);
+ printf("rdi mode = %d\n", rdimode);
+ if (rdimode == 1) {
+ mParams.set("rdi-mode", "enable");
+ } else {
+ mParams.set("rdi-mode", "disable");
+ }
+ } else {
+ mParams.set("rdi-mode", "disable");
+ }
+
+ //mParams.set("rdi-mode", "enable");
+ mParams.set("recording-hint", "true");
+ mParams.setPreviewSize(previewWidth, previewHeight);
+ mParams.setPictureSize(currentPictureSize.width,
+ currentPictureSize.height);
+ mParams.setVideoSize(
+ currentVideoSize.width, currentVideoSize.height);
+
+ ret |= mCamera->setParameters(mParams.flatten());
+
+#ifndef USE_JB_MR1
+
+ gbp = mPreviewSurface->getIGraphicBufferProducer();
+ ret |= mCamera->setPreviewTarget(gbp);
+
+#else
+
+ ret |= mCamera->setPreviewDisplay(mPreviewSurface);
+
+#endif
+ mResizePreview = false;
+ }
+
+ if ( !mPreviewRunning ) {
+ ret |= mCamera->startPreview();
+ if ( NO_ERROR != ret ) {
+ printf("Preview start failed! \n");
+ return ret;
+ }
+
+ mPreviewRunning = true;
+ }
+
+ signalFinished();
+
+ return ret;
+}
+
+/*===========================================================================
+ * FUNCTION : getPreviewSizeFromVideoSizes
+ *
+ * DESCRIPTION: Get the preview size from video size. Find all resolutions with
+ * the same aspect ratio and choose the same or the closest
+ * from them.
+ *
+ * PARAMETERS :
+ * @currentVideoSize: current video size
+
+ *
+ * RETURN : PreviewSize
+ *==========================================================================*/
+Size CameraContext::getPreviewSizeFromVideoSizes(Size currentVideoSize)
+{
+
+ Size tmpPreviewSize;
+ Size PreviewSize;
+ Size PreviewSizes[mSupportedPreviewSizes.size()];
+ double tolerance = 0.00001;
+ double videoRatio;
+ double previewRatio;
+ size_t i = 0;
+ size_t j = 0;
+ int delta;
+
+ // Find all the resolutions with the same aspect ratio and choose the
+ // same or the closest resolution from them. Choose the closest resolution
+ // in case same aspect ratio is not found
+ if (currentVideoSize.width * currentVideoSize.height > 0 &&
+ mSupportedPreviewSizes.size() > 0) {
+ videoRatio = (float)currentVideoSize.width /
+ (float)currentVideoSize.height;
+ for (i=0; i<mSupportedPreviewSizes.size(); i++) {
+ tmpPreviewSize = mSupportedPreviewSizes.itemAt(i);
+ previewRatio = (float)tmpPreviewSize.width /
+ (float)tmpPreviewSize.height;
+ if (fabs(videoRatio - previewRatio) < tolerance) {
+ PreviewSizes[j] = tmpPreviewSize;
+ j++;
+ }
+ }
+
+ if ( j > 0 ) {
+ delta = abs((currentVideoSize.width *currentVideoSize.height)-
+ (PreviewSizes[0].width * PreviewSizes[0].height));
+ PreviewSize = PreviewSizes[0];
+ for (i=0; i<j; i++) {
+ if(abs(currentVideoSize.width * currentVideoSize.height) -
+ (PreviewSizes[i].width * PreviewSizes[i].height) <
+ delta) {
+ PreviewSize = PreviewSizes[i];
+ delta = abs((currentVideoSize.width *
+ currentVideoSize.height) -
+ (PreviewSizes[i].width * PreviewSizes[i].height));
+ }
+ }
+ } else {
+ // Choose the closest resolution in case same aspect ratio is
+ // not found
+ tmpPreviewSize = mSupportedPreviewSizes.itemAt(j);
+ PreviewSize = tmpPreviewSize;
+ delta = abs(
+ (currentVideoSize.width * currentVideoSize.height)-
+ (tmpPreviewSize.width * tmpPreviewSize.height));
+ for (i=0; i<mSupportedPreviewSizes.size(); i++) {
+ tmpPreviewSize = mSupportedPreviewSizes.itemAt(i);
+ if(abs(
+ (currentVideoSize.width * currentVideoSize.height)-
+ (tmpPreviewSize.width * tmpPreviewSize.height)) <
+ delta) {
+ PreviewSize = tmpPreviewSize;
+ delta = abs(
+ (currentVideoSize.width * currentVideoSize.height)-
+ (tmpPreviewSize.width * tmpPreviewSize.height));
+ }
+ }
+ }
+ } else {
+ memset(&PreviewSize, 0, sizeof(PreviewSize));
+ }
+ return PreviewSize;
+}
+
+/*===========================================================================
+ * FUNCTION : autoFocus
+ *
+ * DESCRIPTION: Triggers autofocus
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+status_t CameraContext::autoFocus()
+{
+ useLock();
+ status_t ret = NO_ERROR;
+
+ if ( mPreviewRunning ) {
+ ret = mCamera->autoFocus();
+ }
+
+ signalFinished();
+ return ret;
+}
+
+/*===========================================================================
+ * FUNCTION : enablePreviewCallbacks
+ *
+ * DESCRIPTION: Enables preview callback messages
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+status_t CameraContext::enablePreviewCallbacks()
+{
+ useLock();
+ if ( mHardwareActive ) {
+ mCamera->setPreviewCallbackFlags(
+ CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK);
+ }
+
+ signalFinished();
+ return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION : takePicture
+ *
+ * DESCRIPTION: triggers image capture
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+status_t CameraContext::takePicture()
+{
+ status_t ret = NO_ERROR;
+ useLock();
+ if ( mPreviewRunning ) {
+ ret = mCamera->takePicture(
+ CAMERA_MSG_COMPRESSED_IMAGE|
+ CAMERA_MSG_RAW_IMAGE);
+ if (!mRecordingHint && !mInterpr->mIsZSLOn) {
+ mPreviewRunning = false;
+ }
+ } else {
+ printf("Please resume/start the preview before taking a picture!\n");
+ }
+ signalFinished();
+ return ret;
+}
+
+/*===========================================================================
+ * FUNCTION : configureRecorder
+ *
+ * DESCRIPTION: Configure video recorder
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+status_t CameraContext::configureRecorder()
+{
+ useLock();
+ status_t ret = NO_ERROR;
+
+ mResizePreview = true;
+ mParams.set("recording-hint", "true");
+ mRecordingHint = true;
+ mCamera->setParameters(mParams.flatten());
+
+ Size videoSize = mSupportedVideoSizes.itemAt(mCurrentVideoSizeIdx);
+ ret = mRecorder->setParameters(
+ String8("video-param-encoding-bitrate=64000"));
+ if ( ret != NO_ERROR ) {
+ LOGE("Could not configure recorder (%d)", ret);
+ return ret;
+ }
+
+ ret = mRecorder->setCamera(
+ mCamera->remote(), mCamera->getRecordingProxy());
+ if ( ret != NO_ERROR ) {
+ LOGE("Could not set camera (%d)", ret);
+ return ret;
+ }
+ ret = mRecorder->setVideoSource(VIDEO_SOURCE_CAMERA);
+ if ( ret != NO_ERROR ) {
+ LOGE("Could not set video soruce (%d)", ret);
+ return ret;
+ }
+ ret = mRecorder->setAudioSource(AUDIO_SOURCE_DEFAULT);
+ if ( ret != NO_ERROR ) {
+ LOGE("Could not set audio source (%d)", ret);
+ return ret;
+ }
+ ret = mRecorder->setOutputFormat(OUTPUT_FORMAT_DEFAULT);
+ if ( ret != NO_ERROR ) {
+ LOGE("Could not set output format (%d)", ret);
+ return ret;
+ }
+
+ ret = mRecorder->setVideoEncoder(VIDEO_ENCODER_DEFAULT);
+ if ( ret != NO_ERROR ) {
+ LOGE("Could not set video encoder (%d)", ret);
+ return ret;
+ }
+
+ char fileName[100];
+
+ snprintf(fileName, sizeof(fileName) / sizeof(char),
+ "/sdcard/vid_cam%d_%dx%d_%d.mpeg", mCameraIndex,
+ videoSize.width, videoSize.height, mVideoIdx++);
+
+ if ( mVideoFd < 0 ) {
+ mVideoFd = open(fileName, O_CREAT | O_RDWR );
+ }
+
+ if ( mVideoFd < 0 ) {
+ LOGE("Could not open video file for writing %s!", fileName);
+ return UNKNOWN_ERROR;
+ }
+
+ ret = mRecorder->setOutputFile(mVideoFd, 0, 0);
+ if ( ret != NO_ERROR ) {
+ LOGE("Could not set output file (%d)", ret);
+ return ret;
+ }
+
+ ret = mRecorder->setVideoSize(videoSize.width, videoSize.height);
+ if ( ret != NO_ERROR ) {
+ LOGE("Could not set video size %dx%d", videoSize.width,
+ videoSize.height);
+ return ret;
+ }
+
+ ret = mRecorder->setVideoFrameRate(30);
+ if ( ret != NO_ERROR ) {
+ LOGE("Could not set video frame rate (%d)", ret);
+ return ret;
+ }
+
+ ret = mRecorder->setAudioEncoder(AUDIO_ENCODER_DEFAULT);
+ if ( ret != NO_ERROR ) {
+ LOGE("Could not set audio encoder (%d)", ret);
+ return ret;
+ }
+
+ signalFinished();
+ return ret;
+}
+
+/*===========================================================================
+ * FUNCTION : unconfigureViVRecording
+ *
+ * DESCRIPTION: Unconfigures video in video recording
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+status_t CameraContext::unconfigureRecorder()
+{
+ useLock();
+
+ if ( !mRecordRunning ) {
+ mResizePreview = true;
+ mParams.set("recording-hint", "false");
+ mRecordingHint = false;
+ mCamera->setParameters(mParams.flatten());
+ }
+
+ signalFinished();
+ return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION : configureViVRecording
+ *
+ * DESCRIPTION: Configures video in video recording
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+status_t CameraContext::configureViVRecording()
+{
+ status_t ret = NO_ERROR;
+
+ mResizePreview = true;
+ mParams.set("recording-hint", "true");
+ mRecordingHint = true;
+ mCamera->setParameters(mParams.flatten());
+ mCamera->setRecordingProxyListener(this);
+
+ signalFinished();
+ return ret;
+}
+
+/*===========================================================================
+ * FUNCTION : startRecording
+ *
+ * DESCRIPTION: triggers start recording
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+status_t CameraContext::startRecording()
+{
+ useLock();
+ status_t ret = NO_ERROR;
+
+
+ if ( mPreviewRunning ) {
+
+ mCamera->unlock();
+
+ ret = mRecorder->prepare();
+ if ( ret != NO_ERROR ) {
+ LOGE("Could not prepare recorder");
+ return ret;
+ }
+
+ ret = mRecorder->start();
+ if ( ret != NO_ERROR ) {
+ LOGE("Could not start recorder");
+ return ret;
+ }
+
+ mRecordRunning = true;
+ }
+ signalFinished();
+ return ret;
+}
+
+/*===========================================================================
+ * FUNCTION : stopRecording
+ *
+ * DESCRIPTION: triggers start recording
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+status_t CameraContext::stopRecording()
+{
+ useLock();
+ status_t ret = NO_ERROR;
+
+ if ( mRecordRunning ) {
+ mRecorder->stop();
+ close(mVideoFd);
+ mVideoFd = -1;
+
+ mRecordRunning = false;
+ }
+
+ signalFinished();
+
+ return ret;
+}
+
+/*===========================================================================
+ * FUNCTION : startViVRecording
+ *
+ * DESCRIPTION: Starts video in video recording
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+status_t CameraContext::startViVRecording()
+{
+ useLock();
+ status_t ret;
+
+ if (mInterpr->mViVVid.VideoSizes[0].width *
+ mInterpr->mViVVid.VideoSizes[0].height >=
+ mInterpr->mViVVid.VideoSizes[1].width *
+ mInterpr->mViVVid.VideoSizes[1].height) {
+ mInterpr->mViVBuff.buffSize = calcBufferSize(
+ mInterpr->mViVVid.VideoSizes[1].width,
+ mInterpr->mViVVid.VideoSizes[1].height);
+ if (mInterpr->mViVBuff.buff == NULL) {
+ mInterpr->mViVBuff.buff =
+ (void *)malloc(mInterpr->mViVBuff.buffSize);
+ }
+ mInterpr->mViVVid.sourceCameraID = 1;
+ mInterpr->mViVVid.destinationCameraID = 0;
+
+ } else {
+ mInterpr->mViVBuff.buffSize = calcBufferSize(
+ mInterpr->mViVVid.VideoSizes[0].width,
+ mInterpr->mViVVid.VideoSizes[0].height);
+ if (mInterpr->mViVBuff.buff == NULL) {
+ mInterpr->mViVBuff.buff =
+ (void *)malloc(mInterpr->mViVBuff.buffSize);
+ }
+ mInterpr->mViVVid.sourceCameraID = 0;
+ mInterpr->mViVVid.destinationCameraID = 1;
+ }
+
+ ret = mCamera->startRecording();
+
+ signalFinished();
+ return ret;
+}
+
+/*===========================================================================
+ * FUNCTION : stopViVRecording
+ *
+ * DESCRIPTION: Stops video in video recording
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+status_t CameraContext::stopViVRecording()
+{
+ useLock();
+ status_t ret = NO_ERROR;
+
+ mCamera->stopRecording();
+
+ signalFinished();
+ return ret;
+}
+
+/*===========================================================================
+ * FUNCTION : stopPreview
+ *
+ * DESCRIPTION: stops camera preview
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+status_t CameraContext::stopPreview()
+{
+ useLock();
+ status_t ret = NO_ERROR;
+
+ if ( mHardwareActive ) {
+ mCamera->stopPreview();
+ ret = destroyPreviewSurface();
+ }
+
+ mPreviewRunning = false;
+ mResizePreview = true;
+
+ signalFinished();
+
+ return ret;
+}
+
+/*===========================================================================
+ * FUNCTION : resumePreview
+ *
+ * DESCRIPTION: resumes camera preview after image capture
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+status_t CameraContext::resumePreview()
+{
+ useLock();
+ status_t ret = NO_ERROR;
+
+ if ( mHardwareActive ) {
+ ret = mCamera->startPreview();
+ mPreviewRunning = true;
+ } else {
+ ret = NO_INIT;
+ }
+
+ signalFinished();
+ return ret;
+}
+
+/*===========================================================================
+ * FUNCTION : nextPreviewSize
+ *
+ * DESCRIPTION: Iterates through all supported preview sizes.
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+status_t CameraContext::nextPreviewSize()
+{
+ useLock();
+ if ( mHardwareActive ) {
+ mCurrentPreviewSizeIdx += 1;
+ mCurrentPreviewSizeIdx %= mSupportedPreviewSizes.size();
+ Size previewSize = mSupportedPreviewSizes.itemAt(
+ mCurrentPreviewSizeIdx);
+ mParams.setPreviewSize(previewSize.width,
+ previewSize.height);
+ mResizePreview = true;
+
+ if ( mPreviewRunning ) {
+ mCamera->stopPreview();
+ mCamera->setParameters(mParams.flatten());
+ mCamera->startPreview();
+ } else {
+ mCamera->setParameters(mParams.flatten());
+ }
+ }
+
+ signalFinished();
+ return NO_ERROR;
+}
+
+
+/*===========================================================================
+ * FUNCTION : setPreviewSize
+ *
+ * DESCRIPTION: Sets exact preview size if supported
+ *
+ * PARAMETERS : format size in the form of WIDTHxHEIGHT
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+status_t CameraContext::setPreviewSize(const char *format)
+{
+ useLock();
+ if ( mHardwareActive ) {
+ int newHeight;
+ int newWidth;
+ sscanf(format, "%dx%d", &newWidth, &newHeight);
+
+ unsigned int i;
+ for (i = 0; i < mSupportedPreviewSizes.size(); ++i) {
+ Size previewSize = mSupportedPreviewSizes.itemAt(i);
+ if ( newWidth == previewSize.width &&
+ newHeight == previewSize.height )
+ {
+ break;
+ }
+
+ }
+ if ( i == mSupportedPreviewSizes.size())
+ {
+ printf("Preview size %dx%d not supported !\n",
+ newWidth, newHeight);
+ return INVALID_OPERATION;
+ }
+
+ mParams.setPreviewSize(newWidth,
+ newHeight);
+ mResizePreview = true;
+
+ if ( mPreviewRunning ) {
+ mCamera->stopPreview();
+ mCamera->setParameters(mParams.flatten());
+ mCamera->startPreview();
+ } else {
+ mCamera->setParameters(mParams.flatten());
+ }
+ }
+
+ signalFinished();
+ return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION : getCurrentPreviewSize
+ *
+ * DESCRIPTION: queries the currently configured preview size
+ *
+ * PARAMETERS :
+ * @previewSize : preview size currently configured
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+status_t CameraContext::getCurrentPreviewSize(Size &previewSize)
+{
+ useLock();
+ if ( mHardwareActive ) {
+ previewSize = mSupportedPreviewSizes.itemAt(mCurrentPreviewSizeIdx);
+ }
+ signalFinished();
+ return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION : nextPictureSize
+ *
+ * DESCRIPTION: Iterates through all supported picture sizes.
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+status_t CameraContext::nextPictureSize()
+{
+ useLock();
+ if ( mHardwareActive ) {
+ mCurrentPictureSizeIdx += 1;
+ mCurrentPictureSizeIdx %= mSupportedPictureSizes.size();
+ Size pictureSize = mSupportedPictureSizes.itemAt(
+ mCurrentPictureSizeIdx);
+ mParams.setPictureSize(pictureSize.width,
+ pictureSize.height);
+ mCamera->setParameters(mParams.flatten());
+ }
+ signalFinished();
+ return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION : setPictureSize
+ *
+ * DESCRIPTION: Sets exact preview size if supported
+ *
+ * PARAMETERS : format size in the form of WIDTHxHEIGHT
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+status_t CameraContext::setPictureSize(const char *format)
+{
+ useLock();
+ if ( mHardwareActive ) {
+ int newHeight;
+ int newWidth;
+ sscanf(format, "%dx%d", &newWidth, &newHeight);
+
+ unsigned int i;
+ for (i = 0; i < mSupportedPictureSizes.size(); ++i) {
+ Size PictureSize = mSupportedPictureSizes.itemAt(i);
+ if ( newWidth == PictureSize.width &&
+ newHeight == PictureSize.height )
+ {
+ break;
+ }
+
+ }
+ if ( i == mSupportedPictureSizes.size())
+ {
+ printf("Preview size %dx%d not supported !\n",
+ newWidth, newHeight);
+ return INVALID_OPERATION;
+ }
+
+ mParams.setPictureSize(newWidth,
+ newHeight);
+ mCamera->setParameters(mParams.flatten());
+ }
+
+ signalFinished();
+ return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION : nextVideoSize
+ *
+ * DESCRIPTION: Select the next available video size
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+status_t CameraContext::nextVideoSize()
+{
+ useLock();
+ if ( mHardwareActive ) {
+ mCurrentVideoSizeIdx += 1;
+ mCurrentVideoSizeIdx %= mSupportedVideoSizes.size();
+ Size videoSize = mSupportedVideoSizes.itemAt(mCurrentVideoSizeIdx);
+ mParams.setVideoSize(videoSize.width,
+ videoSize.height);
+ mCamera->setParameters(mParams.flatten());
+ mInterpr->setViVSize((Size) mSupportedVideoSizes.itemAt(
+ mCurrentVideoSizeIdx), mCameraIndex);
+ }
+ signalFinished();
+ return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION : setVideoSize
+ *
+ * DESCRIPTION: Set video size
+ *
+ * PARAMETERS :
+ * @format : format
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+status_t CameraContext::setVideoSize(const char *format)
+{
+ useLock();
+ if ( mHardwareActive ) {
+ int newHeight;
+ int newWidth;
+ sscanf(format, "%dx%d", &newWidth, &newHeight);
+
+ unsigned int i;
+ for (i = 0; i < mSupportedVideoSizes.size(); ++i) {
+ Size PictureSize = mSupportedVideoSizes.itemAt(i);
+ if ( newWidth == PictureSize.width &&
+ newHeight == PictureSize.height )
+ {
+ break;
+ }
+
+ }
+ if ( i == mSupportedVideoSizes.size())
+ {
+ printf("Preview size %dx%d not supported !\n",
+ newWidth, newHeight);
+ return INVALID_OPERATION;
+ }
+
+ mParams.setVideoSize(newWidth,
+ newHeight);
+ mCamera->setParameters(mParams.flatten());
+ }
+
+ signalFinished();
+ return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION : getCurrentVideoSize
+ *
+ * DESCRIPTION : Get current video size
+ *
+ * PARAMETERS :
+ * @videoSize: video Size
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+status_t CameraContext::getCurrentVideoSize(Size &videoSize)
+{
+ useLock();
+ if ( mHardwareActive ) {
+ videoSize = mSupportedVideoSizes.itemAt(mCurrentVideoSizeIdx);
+ }
+ signalFinished();
+ return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION : getCurrentPictureSize
+ *
+ * DESCRIPTION: queries the currently configured picture size
+ *
+ * PARAMETERS :
+ * @pictureSize : picture size currently configured
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+status_t CameraContext::getCurrentPictureSize(Size &pictureSize)
+{
+ useLock();
+ if ( mHardwareActive ) {
+ pictureSize = mSupportedPictureSizes.itemAt(mCurrentPictureSizeIdx);
+ }
+ signalFinished();
+ return NO_ERROR;
+}
+
+}; //namespace qcamera ends here
+
+using namespace qcamera;
+
+/*===========================================================================
+ * FUNCTION : printMenu
+ *
+ * DESCRIPTION: prints the available camera options
+ *
+ * PARAMETERS :
+ * @currentCamera : camera context currently being used
+ *
+ * RETURN : None
+ *==========================================================================*/
+void CameraContext::printMenu(sp<CameraContext> currentCamera)
+{
+ if ( !mDoPrintMenu ) return;
+ Size currentPictureSize, currentPreviewSize, currentVideoSize;
+ const char *zsl_mode = mParams.get(CameraContext::KEY_ZSL);
+
+ assert(currentCamera.get());
+
+ currentCamera->getCurrentPictureSize(currentPictureSize);
+ currentCamera->getCurrentPreviewSize(currentPreviewSize);
+ currentCamera->getCurrentVideoSize(currentVideoSize);
+
+ printf("\n\n=========== FUNCTIONAL TEST MENU ===================\n\n");
+
+ printf(" \n\nSTART / STOP / GENERAL SERVICES \n");
+ printf(" -----------------------------\n");
+ printf(" %c. Switch camera - Current Index: %d\n",
+ Interpreter::SWITCH_CAMERA_CMD,
+ currentCamera->getCameraIndex());
+ printf(" %c. Resume Preview after capture \n",
+ Interpreter::RESUME_PREVIEW_CMD);
+ printf(" %c. Quit \n",
+ Interpreter::EXIT_CMD);
+ printf(" %c. Camera Capability Dump",
+ Interpreter::DUMP_CAPS_CMD);
+
+ printf(" \n\n PREVIEW SUB MENU \n");
+ printf(" -----------------------------\n");
+ printf(" %c. Start Preview\n",
+ Interpreter::START_PREVIEW_CMD);
+ printf(" %c. Stop Preview\n",
+ Interpreter::STOP_PREVIEW_CMD);
+ printf(" %c. Preview size: %dx%d\n",
+ Interpreter::CHANGE_PREVIEW_SIZE_CMD,
+ currentPreviewSize.width,
+ currentPreviewSize.height);
+ printf(" %c. Video size: %dx%d\n",
+ Interpreter::CHANGE_VIDEO_SIZE_CMD,
+ currentVideoSize.width,
+ currentVideoSize.height);
+ printf(" %c. Start Recording\n",
+ Interpreter::START_RECORD_CMD);
+ printf(" %c. Stop Recording\n",
+ Interpreter::STOP_RECORD_CMD);
+ printf(" %c. Start ViV Recording\n",
+ Interpreter::START_VIV_RECORD_CMD);
+ printf(" %c. Stop ViV Recording\n",
+ Interpreter::STOP_VIV_RECORD_CMD);
+ printf(" %c. Enable preview frames\n",
+ Interpreter::ENABLE_PRV_CALLBACKS_CMD);
+ printf(" %c. Trigger autofocus \n",
+ Interpreter::AUTOFOCUS_CMD);
+
+ printf(" \n\n IMAGE CAPTURE SUB MENU \n");
+ printf(" -----------------------------\n");
+ printf(" %c. Take picture/Full Press\n",
+ Interpreter::TAKEPICTURE_CMD);
+ printf(" %c. Take picture in picture\n",
+ Interpreter::TAKEPICTURE_IN_PICTURE_CMD);
+ printf(" %c. Picture size: %dx%d\n",
+ Interpreter::CHANGE_PICTURE_SIZE_CMD,
+ currentPictureSize.width,
+ currentPictureSize.height);
+ printf(" %c. zsl: %s\n", Interpreter::ZSL_CMD,
+ (zsl_mode != NULL) ? zsl_mode : "NULL");
+
+ printf("\n Choice: ");
+}
+
+/*===========================================================================
+ * FUNCTION : enablePrintPreview
+ *
+ * DESCRIPTION: Enables printing the preview
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : None
+ *==========================================================================*/
+void CameraContext::enablePrintPreview()
+{
+ mDoPrintMenu = true;
+}
+
+/*===========================================================================
+ * FUNCTION : disablePrintPreview
+ *
+ * DESCRIPTION: Disables printing the preview
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : None
+ *==========================================================================*/
+void CameraContext::disablePrintPreview()
+{
+ mDoPrintMenu = false;
+}
+
+/*===========================================================================
+ * FUNCTION : enablePiPCapture
+ *
+ * DESCRIPTION: Enables picture in picture capture
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : None
+ *==========================================================================*/
+void CameraContext::enablePiPCapture()
+{
+ mPiPCapture = true;
+}
+
+/*===========================================================================
+ * FUNCTION : disablePiPCapture
+ *
+ * DESCRIPTION: Disables picture in picture capture
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : None
+ *==========================================================================*/
+void CameraContext::disablePiPCapture()
+{
+ mPiPCapture = false;
+}
+
+/*===========================================================================
+ * FUNCTION : getZSL
+ *
+ * DESCRIPTION: get ZSL value of current camera
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : current zsl value
+ *==========================================================================*/
+const char *CameraContext::getZSL()
+{
+ return mParams.get(CameraContext::KEY_ZSL);
+}
+
+/*===========================================================================
+ * FUNCTION : setZSL
+ *
+ * DESCRIPTION: set ZSL value of current camera
+ *
+ * PARAMETERS : zsl value to be set
+ *
+ * RETURN : None
+ *==========================================================================*/
+void CameraContext::setZSL(const char *value)
+{
+ mParams.set(CameraContext::KEY_ZSL, value);
+ mCamera->setParameters(mParams.flatten());
+}
+
+/*===========================================================================
+ * FUNCTION : configureViVCodec
+ *
+ * DESCRIPTION: Configures video in video codec
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+status_t Interpreter::configureViVCodec()
+{
+ status_t ret = NO_ERROR;
+ char fileName[100];
+ sp<AMessage> format = new AMessage;
+ sp<ALooper> looper = new ALooper;
+
+ if (mTestContext->mViVVid.VideoSizes[0].width *
+ mTestContext->mViVVid.VideoSizes[0].height >=
+ mTestContext->mViVVid.VideoSizes[1].width *
+ mTestContext->mViVVid.VideoSizes[1].height) {
+ snprintf(fileName, sizeof(fileName) / sizeof(char), "/sdcard/ViV_vid_%dx%d_%d.mp4",
+ mTestContext->mViVVid.VideoSizes[0].width,
+ mTestContext->mViVVid.VideoSizes[0].height,
+ mTestContext->mViVVid.ViVIdx++);
+ format->setInt32("width", mTestContext->mViVVid.VideoSizes[0].width);
+ format->setInt32("height", mTestContext->mViVVid.VideoSizes[0].height);
+ } else {
+ snprintf(fileName, sizeof(fileName) / sizeof(char), "/sdcard/ViV_vid_%dx%d_%d.mp4",
+ mTestContext->mViVVid.VideoSizes[1].width,
+ mTestContext->mViVVid.VideoSizes[1].height,
+ mTestContext->mViVVid.ViVIdx++);
+ format->setInt32("width", mTestContext->mViVVid.VideoSizes[1].width);
+ format->setInt32("height", mTestContext->mViVVid.VideoSizes[1].height);
+ }
+ int fd = open(fileName, O_CREAT | O_RDWR );
+ if (fd < 0) {
+ LOGE("Error opening file");
+ return UNKNOWN_ERROR;
+ }
+ mTestContext->mViVVid.muxer = new MediaMuxer(
+ fd, MediaMuxer::OUTPUT_FORMAT_MPEG_4);
+
+ format->setString("mime", "video/avc");
+ format->setInt32("color-format", OMX_COLOR_FormatAndroidOpaque);
+
+ format->setInt32("bitrate", 1000000);
+ format->setFloat("frame-rate", 30);
+ format->setInt32("i-frame-interval", 10);
+
+ looper->setName("ViV_recording_looper");
+ looper->start();
+ ALOGV("Creating codec");
+ mTestContext->mViVVid.codec = MediaCodec::CreateByType(
+ looper, "video/avc", true);
+ if (mTestContext->mViVVid.codec == NULL) {
+ fprintf(stderr, "ERROR: unable to create video/avc codec instance\n");
+ return UNKNOWN_ERROR;
+ }
+ ret = mTestContext->mViVVid.codec->configure(format, NULL, NULL,
+ MediaCodec::CONFIGURE_FLAG_ENCODE);
+ if (ret != NO_ERROR) {
+ mTestContext->mViVVid.codec->release();
+ mTestContext->mViVVid.codec.clear();
+
+ fprintf(stderr, "ERROR: unable to configure codec (err=%d)\n", ret);
+ return ret;
+ }
+
+ ALOGV("Creating buffer producer");
+ ret = mTestContext->mViVVid.codec->createInputSurface(
+ &mTestContext->mViVVid.bufferProducer);
+ if (ret != NO_ERROR) {
+ mTestContext->mViVVid.codec->release();
+ mTestContext->mViVVid.codec.clear();
+
+ fprintf(stderr,
+ "ERROR: unable to create encoder input surface (err=%d)\n", ret);
+ return ret;
+ }
+
+ ret = mTestContext->mViVVid.codec->start();
+ if (ret != NO_ERROR) {
+ mTestContext->mViVVid.codec->release();
+ mTestContext->mViVVid.codec.clear();
+
+ fprintf(stderr, "ERROR: unable to start codec (err=%d)\n", ret);
+ return ret;
+ }
+ ALOGV("Codec prepared");
+
+ mTestContext->mViVVid.surface = new Surface(
+ mTestContext->mViVVid.bufferProducer);
+ mTestContext->mViVVid.ANW = mTestContext->mViVVid.surface;
+ ret = native_window_api_connect(mTestContext->mViVVid.ANW.get(),
+ NATIVE_WINDOW_API_CPU);
+ if (mTestContext->mViVVid.VideoSizes[0].width *
+ mTestContext->mViVVid.VideoSizes[0].height >=
+ mTestContext->mViVVid.VideoSizes[1].width *
+ mTestContext->mViVVid.VideoSizes[1].height) {
+ native_window_set_buffers_format(mTestContext->mViVVid.ANW.get(),
+ HAL_PIXEL_FORMAT_NV12_ENCODEABLE);
+ native_window_set_buffers_dimensions(mTestContext->mViVVid.ANW.get(),
+ mTestContext->mViVVid.VideoSizes[0].width,
+ mTestContext->mViVVid.VideoSizes[0].height);
+ } else {
+ native_window_set_buffers_format(mTestContext->mViVVid.ANW.get(),
+ HAL_PIXEL_FORMAT_NV12_ENCODEABLE);
+ native_window_set_buffers_dimensions(mTestContext->mViVVid.ANW.get(),
+ mTestContext->mViVVid.VideoSizes[1].width,
+ mTestContext->mViVVid.VideoSizes[1].height);
+ }
+ native_window_set_usage(mTestContext->mViVVid.ANW.get(),
+ GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
+ native_window_set_buffer_count(mTestContext->mViVVid.ANW.get(),
+ mTestContext->mViVVid.buff_cnt);
+
+ ViVEncoderThread();
+
+ return ret;
+}
+
+/*===========================================================================
+ * FUNCTION : unconfigureViVCodec
+ *
+ * DESCRIPTION: Unconfigures video in video codec
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+status_t Interpreter::unconfigureViVCodec()
+{
+ status_t ret = NO_ERROR;
+
+ ret = native_window_api_disconnect(mTestContext->mViVVid.ANW.get(),
+ NATIVE_WINDOW_API_CPU);
+ mTestContext->mViVVid.bufferProducer = NULL;
+ mTestContext->mViVVid.codec->stop();
+ pthread_join(mViVEncThread, NULL);
+ mTestContext->mViVVid.muxer->stop();
+ mTestContext->mViVVid.codec->release();
+ mTestContext->mViVVid.codec.clear();
+ mTestContext->mViVVid.muxer.clear();
+ mTestContext->mViVVid.surface.clear();
+ return ret;
+}
+
+/*===========================================================================
+ * FUNCTION : Interpreter
+ *
+ * DESCRIPTION: Interpreter constructor
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+Interpreter::Interpreter(const char *file)
+ : mCmdIndex(0)
+ , mScript(NULL)
+{
+ if (!file){
+ printf("no File Given\n");
+ mUseScript = false;
+ return;
+ }
+
+ FILE *fh = fopen(file, "r");
+ if ( !fh ) {
+ printf("Could not open file %s\n", file);
+ mUseScript = false;
+ return;
+ }
+
+ fseek(fh, 0, SEEK_END);
+ size_t len = (size_t)ftell(fh);
+ rewind(fh);
+
+ if( !len ) {
+ printf("Script file %s is empty !\n", file);
+ fclose(fh);
+ return;
+ }
+
+ mScript = new char[len + 1];
+ if ( !mScript ) {
+ fclose(fh);
+ return;
+ }
+
+ fread(mScript, sizeof(char), len, fh);
+ mScript[len] = '\0'; // ensure null terminated;
+ fclose(fh);
+
+
+ char *p1;
+ char *p2;
+ p1 = p2 = mScript;
+
+ do {
+ switch (*p1) {
+ case '\0':
+ case '|':
+ p1++;
+ break;
+ case SWITCH_CAMERA_CMD:
+ case RESUME_PREVIEW_CMD:
+ case START_PREVIEW_CMD:
+ case STOP_PREVIEW_CMD:
+ case CHANGE_PREVIEW_SIZE_CMD:
+ case CHANGE_PICTURE_SIZE_CMD:
+ case START_RECORD_CMD:
+ case STOP_RECORD_CMD:
+ case START_VIV_RECORD_CMD:
+ case STOP_VIV_RECORD_CMD:
+ case DUMP_CAPS_CMD:
+ case AUTOFOCUS_CMD:
+ case TAKEPICTURE_CMD:
+ case TAKEPICTURE_IN_PICTURE_CMD:
+ case ENABLE_PRV_CALLBACKS_CMD:
+ case EXIT_CMD:
+ case ZSL_CMD:
+ case DELAY:
+ p2 = p1;
+ while( (p2 != (mScript + len)) && (*p2 != '|')) {
+ p2++;
+ }
+ *p2 = '\0';
+ if (p2 == (p1 + 1))
+ mCommands.push_back(Command(
+ static_cast<Interpreter::Commands_e>(*p1)));
+ else
+ mCommands.push_back(Command(
+ static_cast<Interpreter::Commands_e>(*p1), (p1 + 1)));
+ p1 = p2;
+ break;
+ default:
+ printf("Invalid cmd %c \n", *p1);
+ do {
+ p1++;
+
+ } while(*p1 != '|' && p1 != (mScript + len));
+
+ }
+ } while(p1 != (mScript + len));
+ mUseScript = true;
+}
+
+/*===========================================================================
+ * FUNCTION : ~Interpreter
+ *
+ * DESCRIPTION: Interpreter destructor
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+Interpreter::~Interpreter()
+{
+ if ( mScript )
+ delete[] mScript;
+
+ mCommands.clear();
+}
+
+/*===========================================================================
+ * FUNCTION : getCommand
+ *
+ * DESCRIPTION : Get a command from interpreter
+ *
+ * PARAMETERS :
+ * @currentCamera: Current camera context
+ *
+ * RETURN : command
+ *==========================================================================*/
+Interpreter::Command Interpreter::getCommand(
+ sp<CameraContext> currentCamera)
+{
+ if( mUseScript ) {
+ return mCommands[mCmdIndex++];
+ } else {
+ currentCamera->printMenu(currentCamera);
+ return Interpreter::Command(
+ static_cast<Interpreter::Commands_e>(getchar()));
+ }
+}
+
+/*===========================================================================
+ * FUNCTION : TestContext
+ *
+ * DESCRIPTION : TestContext constructor
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : None
+ *==========================================================================*/
+TestContext::TestContext()
+{
+ int i = 0;
+ mTestRunning = false;
+ mInterpreter = NULL;
+ mViVVid.ViVIdx = 0;
+ mViVVid.buff_cnt = 9;
+ mViVVid.graphBuf = 0;
+ mViVVid.mappedBuff = NULL;
+ mViVVid.isBuffValid = false;
+ mViVVid.sourceCameraID = -1;
+ mViVVid.destinationCameraID = -1;
+ mPiPinUse = false;
+ mViVinUse = false;
+ mIsZSLOn = false;
+ memset(&mViVBuff, 0, sizeof(ViVBuff_t));
+
+ ProcessState::self()->startThreadPool();
+
+ do {
+ camera[i] = new CameraContext(i);
+ if ( NULL == camera[i].get() ) {
+ break;
+ }
+ camera[i]->setTestCtxInstance(this);
+
+ //by default open only back camera
+ if (i==0) {
+ status_t stat = camera[i]->openCamera();
+ if ( NO_ERROR != stat ) {
+ printf("Error encountered Openging camera id : %d\n", i);
+ break;
+ }
+ }
+ mAvailableCameras.add(camera[i]);
+ i++;
+ } while ( i < camera[0]->getNumberOfCameras() ) ;
+
+ if (i < camera[0]->getNumberOfCameras() ) {
+ for (size_t j = 0; j < mAvailableCameras.size(); j++) {
+ camera[j] = mAvailableCameras.itemAt(j);
+ camera[j]->closeCamera();
+ camera[j].clear();
+ }
+
+ mAvailableCameras.clear();
+ }
+}
+
+/*===========================================================================
+ * FUNCTION : ~TestContext
+ *
+ * DESCRIPTION : TestContext destructor
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : None
+ *==========================================================================*/
+TestContext::~TestContext()
+{
+ delete mInterpreter;
+
+ for (size_t j = 0; j < mAvailableCameras.size(); j++) {
+ camera[j] = mAvailableCameras.itemAt(j);
+ camera[j]->closeCamera();
+ camera[j].clear();
+ }
+
+ mAvailableCameras.clear();
+}
+
+/*===========================================================================
+ * FUNCTION : GetCamerasNum
+ *
+ * DESCRIPTION : Get the number of available cameras
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : Number of cameras
+ *==========================================================================*/
+size_t TestContext::GetCamerasNum()
+{
+ return mAvailableCameras.size();
+}
+
+/*===========================================================================
+ * FUNCTION : AddScriptFromFile
+ *
+ * DESCRIPTION : Add script from file
+ *
+ * PARAMETERS :
+ * @scriptFile : Script file
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+status_t TestContext::AddScriptFromFile(const char *scriptFile)
+{
+ mInterpreter = new Interpreter(scriptFile);
+ mInterpreter->setTestCtxInst(this);
+
+ return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION : releasePiPBuff
+ *
+ * DESCRIPTION : Release video in video temp buffer
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : None
+ *==========================================================================*/
+void Interpreter::releasePiPBuff() {
+ free(mTestContext->mViVBuff.buff);
+ mTestContext->mViVBuff.buff = NULL;
+}
+
+/*===========================================================================
+ * FUNCTION : functionalTest
+ *
+ * DESCRIPTION: queries and executes client supplied commands for testing a
+ * particular camera.
+ *
+ * PARAMETERS :
+ * @availableCameras : List with all cameras supported
+ *
+ * RETURN : status_t type of status
+ * NO_ERROR -- continue testing
+ * none-zero -- quit test
+ *==========================================================================*/
+status_t TestContext::FunctionalTest()
+{
+ status_t stat = NO_ERROR;
+ const char *ZSLStr = NULL;
+ size_t ZSLStrSize = 0;
+
+ assert(mAvailableCameras.size());
+
+ if ( !mInterpreter ) {
+ mInterpreter = new Interpreter();
+ mInterpreter->setTestCtxInst(this);
+ }
+
+ if (mAvailableCameras.size() == 0) {
+ printf("no cameras supported... exiting test app\n");
+ } else {
+ mTestRunning = true;
+ }
+
+ while (mTestRunning) {
+ sp<CameraContext> currentCamera =
+ mAvailableCameras.itemAt(mCurrentCameraIndex);
+ Interpreter::Command command =
+ mInterpreter->getCommand(currentCamera);
+ currentCamera->enablePrintPreview();
+
+ switch (command.cmd) {
+ case Interpreter::SWITCH_CAMERA_CMD:
+ {
+ mCurrentCameraIndex++;
+ mCurrentCameraIndex %= mAvailableCameras.size();
+ currentCamera = mAvailableCameras.itemAt(mCurrentCameraIndex);
+ stat = currentCamera->openCamera();
+ }
+ break;
+
+ case Interpreter::RESUME_PREVIEW_CMD:
+ {
+ stat = currentCamera->resumePreview();
+ }
+ break;
+
+ case Interpreter::START_PREVIEW_CMD:
+ {
+ stat = currentCamera->startPreview();
+ }
+ break;
+
+ case Interpreter::STOP_PREVIEW_CMD:
+ {
+ stat = currentCamera->stopPreview();
+ }
+ break;
+
+ case Interpreter::CHANGE_VIDEO_SIZE_CMD:
+ {
+ if ( command.arg )
+ stat = currentCamera->setVideoSize(command.arg);
+ else
+ stat = currentCamera->nextVideoSize();
+ }
+ break;
+
+ case Interpreter::CHANGE_PREVIEW_SIZE_CMD:
+ {
+ if ( command.arg )
+ stat = currentCamera->setPreviewSize(command.arg);
+ else
+ stat = currentCamera->nextPreviewSize();
+ }
+ break;
+
+ case Interpreter::CHANGE_PICTURE_SIZE_CMD:
+ {
+ if ( command.arg )
+ stat = currentCamera->setPictureSize(command.arg);
+ else
+ stat = currentCamera->nextPictureSize();
+ }
+ break;
+
+ case Interpreter::DUMP_CAPS_CMD:
+ {
+ currentCamera->printSupportedParams();
+ }
+ break;
+
+ case Interpreter::AUTOFOCUS_CMD:
+ {
+ stat = currentCamera->autoFocus();
+ }
+ break;
+
+ case Interpreter::TAKEPICTURE_CMD:
+ {
+ stat = currentCamera->takePicture();
+ }
+ break;
+
+ case Interpreter::TAKEPICTURE_IN_PICTURE_CMD:
+ {
+ if (mAvailableCameras.size() == 2) {
+ mSaveCurrentCameraIndex = mCurrentCameraIndex;
+ for (size_t i = 0; i < mAvailableCameras.size(); i++) {
+ mCurrentCameraIndex = i;
+ currentCamera = mAvailableCameras.itemAt(mCurrentCameraIndex);
+ currentCamera->enablePiPCapture();
+ stat = currentCamera->takePicture();
+ }
+ mCurrentCameraIndex = mSaveCurrentCameraIndex;
+ } else {
+ printf("Number of available sensors should be 2\n");
+ }
+ }
+ break;
+
+ case Interpreter::ENABLE_PRV_CALLBACKS_CMD:
+ {
+ stat = currentCamera->enablePreviewCallbacks();
+ }
+ break;
+
+ case Interpreter::START_RECORD_CMD:
+ {
+ stat = currentCamera->stopPreview();
+ stat = currentCamera->configureRecorder();
+ stat = currentCamera->startPreview();
+ stat = currentCamera->startRecording();
+ }
+ break;
+
+ case Interpreter::STOP_RECORD_CMD:
+ {
+ stat = currentCamera->stopRecording();
+
+ stat = currentCamera->stopPreview();
+ stat = currentCamera->unconfigureRecorder();
+ stat = currentCamera->startPreview();
+ }
+ break;
+
+ case Interpreter::START_VIV_RECORD_CMD:
+ {
+
+ if (mAvailableCameras.size() == 2) {
+ mSaveCurrentCameraIndex = mCurrentCameraIndex;
+ stat = mInterpreter->configureViVCodec();
+ for ( size_t i = 0; i < mAvailableCameras.size(); i++ ) {
+ mCurrentCameraIndex = i;
+ currentCamera = mAvailableCameras.itemAt(
+ mCurrentCameraIndex);
+ stat = currentCamera->stopPreview();
+ stat = currentCamera->configureViVRecording();
+ stat = currentCamera->startPreview();
+ stat = currentCamera->startViVRecording();
+ }
+ mCurrentCameraIndex = mSaveCurrentCameraIndex;
+ } else {
+ printf("Number of available sensors should be 2\n");
+ }
+
+ }
+ break;
+
+ case Interpreter::STOP_VIV_RECORD_CMD:
+ {
+ if (mAvailableCameras.size() == 2) {
+ mSaveCurrentCameraIndex = mCurrentCameraIndex;
+ for ( size_t i = 0; i < mAvailableCameras.size(); i++ ) {
+ mCurrentCameraIndex = i;
+ currentCamera = mAvailableCameras.itemAt(
+ mCurrentCameraIndex);
+ stat = currentCamera->stopViVRecording();
+ stat = currentCamera->stopPreview();
+ stat = currentCamera->unconfigureRecorder();
+ stat = currentCamera->startPreview();
+ }
+ stat = mInterpreter->unconfigureViVCodec();
+ mCurrentCameraIndex = mSaveCurrentCameraIndex;
+
+ mInterpreter->releasePiPBuff();
+ } else {
+ printf("Number of available sensors should be 2\n");
+ }
+ }
+ break;
+
+ case Interpreter::EXIT_CMD:
+ {
+ currentCamera->stopPreview();
+ mTestRunning = false;
+ }
+ break;
+
+ case Interpreter::DELAY:
+ {
+ if ( command.arg ) {
+ int delay = atoi(command.arg);
+ if (0 < delay) {
+ usleep(1000U * (unsigned int)delay);
+ }
+ }
+ }
+ break;
+
+ case Interpreter::ZSL_CMD:
+ {
+ currentCamera = mAvailableCameras.itemAt(
+ mCurrentCameraIndex);
+ ZSLStr = currentCamera->getZSL();
+
+ if (NULL != ZSLStr) {
+ ZSLStrSize = strlen(ZSLStr);
+ if (!strncmp(ZSLStr, "off", ZSLStrSize)) {
+ currentCamera->setZSL("on");
+ mIsZSLOn = true;
+ } else if (!strncmp(ZSLStr, "on", ZSLStrSize)) {
+ currentCamera->setZSL("off");
+ mIsZSLOn = false;
+ } else {
+ printf("Set zsl failed!\n");
+ }
+ } else {
+ printf("zsl is NULL\n");
+ }
+ }
+ break;
+
+ default:
+ {
+ currentCamera->disablePrintPreview();
+ }
+ break;
+ }
+ printf("Command status 0x%x \n", stat);
+ }
+
+ return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION : PiPLock
+ *
+ * DESCRIPTION: Mutex lock for PiP capture
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+void TestContext::PiPLock()
+{
+ Mutex::Autolock l(mPiPLock);
+ while (mPiPinUse) {
+ mPiPCond.wait(mPiPLock);
+ }
+ mPiPinUse = true;
+}
+
+/*===========================================================================
+ * FUNCTION : PiPUnLock
+ *
+ * DESCRIPTION: Mutex unlock for PiP capture
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+void TestContext::PiPUnlock()
+{
+ Mutex::Autolock l(mPiPLock);
+ mPiPinUse = false;
+ mPiPCond.signal();
+}
+
+/*===========================================================================
+ * FUNCTION : ViVLock
+ *
+ * DESCRIPTION: Mutex lock for ViV Video
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+void TestContext::ViVLock()
+{
+ Mutex::Autolock l(mViVLock);
+ while (mViVinUse) {
+ mViVCond.wait(mViVLock);
+ }
+ mViVinUse = true;
+}
+
+/*===========================================================================
+ * FUNCTION : ViVUnlock
+ *
+ * DESCRIPTION: Mutex unlock for ViV Video
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+void TestContext::ViVUnlock()
+{
+ Mutex::Autolock l(mViVLock);
+ mViVinUse = false;
+ mViVCond.signal();
+}
+
+/*===========================================================================
+ * FUNCTION : setViVSize
+ *
+ * DESCRIPTION : Set video in video size
+ *
+ * PARAMETERS :
+ * @VideoSize : video size
+ * @camIndex : camera index
+ *
+ * RETURN : none
+ *==========================================================================*/
+void TestContext::setViVSize(Size VideoSize, int camIndex)
+{
+ mViVVid.VideoSizes[camIndex] = VideoSize;
+}
+
+/*===========================================================================
+ * FUNCTION : main
+ *
+ * DESCRIPTION : main function
+ *
+ * PARAMETERS :
+ * @argc : argc
+ * @argv : argv
+ *
+ * RETURN : int status
+ *==========================================================================*/
+int main(int argc, char *argv[])
+{
+ TestContext ctx;
+
+ if (argc > 1) {
+ if ( ctx.AddScriptFromFile((const char *)argv[1]) ) {
+ printf("Could not add script file... "
+ "continuing in normal menu mode! \n");
+ }
+ }
+
+ ctx.FunctionalTest();
+
+ return 0;
+}
diff --git a/camera/QCamera2/HAL/test/qcamera_test.h b/camera/QCamera2/HAL/test/qcamera_test.h
new file mode 100644
index 0000000..b8c5998
--- /dev/null
+++ b/camera/QCamera2/HAL/test/qcamera_test.h
@@ -0,0 +1,361 @@
+/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef QCAMERA_TEST_H
+#define QCAMERA_TEST_H
+
+#include <SkData.h>
+#include <SkBitmap.h>
+#include <SkStream.h>
+
+namespace qcamera {
+
+using namespace android;
+
+#define MAX_CAM_INSTANCES 3
+
+class TestContext;
+
+class CameraContext : public CameraListener,
+ public ICameraRecordingProxyListener{
+public:
+ typedef enum {
+ READ_METADATA = 1,
+ READ_IMAGE = 2,
+ READ_ALL = 3
+ } ReadMode_t;
+
+ // This structure is used to store jpeg file sections in memory.
+ typedef struct {
+ unsigned char * Data;
+ int Type;
+ size_t Size;
+ } Sections_t;
+
+public:
+ static const char KEY_ZSL[];
+
+ CameraContext(int cameraIndex);
+ virtual ~CameraContext();
+
+
+
+ status_t openCamera();
+ status_t closeCamera();
+
+ status_t startPreview();
+ status_t stopPreview();
+ status_t resumePreview();
+ status_t autoFocus();
+ status_t enablePreviewCallbacks();
+ status_t takePicture();
+ status_t startRecording();
+ status_t stopRecording();
+ status_t startViVRecording();
+ status_t stopViVRecording();
+ status_t configureViVRecording();
+
+ status_t nextPreviewSize();
+ status_t setPreviewSize(const char *format);
+ status_t getCurrentPreviewSize(Size &previewSize);
+
+ status_t nextPictureSize();
+ status_t getCurrentPictureSize(Size &pictureSize);
+ status_t setPictureSize(const char *format);
+
+ status_t nextVideoSize();
+ status_t setVideoSize(const char *format);
+ status_t getCurrentVideoSize(Size &videoSize);
+ status_t configureRecorder();
+ status_t unconfigureRecorder();
+ Sections_t *FindSection(int SectionType);
+ status_t ReadSectionsFromBuffer (unsigned char *buffer,
+ size_t buffer_size, ReadMode_t ReadMode);
+ virtual IBinder* onAsBinder();
+ void setTestCtxInstance(TestContext *instance);
+
+ void printMenu(sp<CameraContext> currentCamera);
+ void printSupportedParams();
+ const char *getZSL();
+ void setZSL(const char *value);
+
+
+ int getCameraIndex() { return mCameraIndex; }
+ int getNumberOfCameras();
+ void enablePrintPreview();
+ void disablePrintPreview();
+ void enablePiPCapture();
+ void disablePiPCapture();
+ void CheckSectionsAllocated();
+ void DiscardData();
+ void DiscardSections();
+ size_t calcBufferSize(int width, int height);
+ size_t calcStride(int width);
+ size_t calcYScanLines(int height);
+ size_t calcUVScanLines(int height);
+
+ virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2);
+ virtual void postData(int32_t msgType,
+ const sp<IMemory>& dataPtr,
+ camera_frame_metadata_t *metadata);
+
+ virtual void postDataTimestamp(nsecs_t timestamp,
+ int32_t msgType,
+ const sp<IMemory>& dataPtr);
+ virtual void dataCallbackTimestamp(nsecs_t timestamp,
+ int32_t msgType,
+ const sp<IMemory>& dataPtr);
+
+private:
+
+ status_t createPreviewSurface(int width, int height, int32_t pixFormat);
+ status_t destroyPreviewSurface();
+
+ status_t saveFile(const sp<IMemory>& mem, String8 path);
+ SkBitmap * PiPCopyToOneFile(SkBitmap *bitmap0, SkBitmap *bitmap1);
+ status_t decodeJPEG(const sp<IMemory>& mem, SkBitmap *skBM);
+ status_t encodeJPEG(SkWStream * stream, const SkBitmap *bitmap,
+ String8 path);
+ void previewCallback(const sp<IMemory>& mem);
+
+ static int JpegIdx;
+ int mCameraIndex;
+ bool mResizePreview;
+ bool mHardwareActive;
+ bool mPreviewRunning;
+ bool mRecordRunning;
+ int mVideoFd;
+ int mVideoIdx;
+ bool mRecordingHint;
+ bool mDoPrintMenu;
+ bool mPiPCapture;
+ static int mPiPIdx;
+ unsigned int mfmtMultiplier;
+ int mWidthTmp;
+ int mHeightTmp;
+ size_t mSectionsRead;
+ size_t mSectionsAllocated;
+ Sections_t * mSections;
+ Sections_t * mJEXIFTmp;
+ Sections_t mJEXIFSection;
+ int mHaveAll;
+ TestContext *mInterpr;
+
+ sp<Camera> mCamera;
+ sp<SurfaceComposerClient> mClient;
+ sp<SurfaceControl> mSurfaceControl;
+ sp<Surface> mPreviewSurface;
+ sp<MediaRecorder> mRecorder;
+ CameraParameters mParams;
+ SkBitmap *skBMDec;
+ SkImageEncoder* skJpegEnc;
+ SkBitmap skBMtmp;
+ sp<IMemory> PiPPtrTmp;
+
+ size_t mCurrentPreviewSizeIdx;
+ Size getPreviewSizeFromVideoSizes(Size currentVideoSize);
+ size_t mCurrentPictureSizeIdx;
+ size_t mCurrentVideoSizeIdx;
+ Vector<Size> mSupportedPreviewSizes;
+ Vector<Size> mSupportedPictureSizes;
+ Vector<Size> mSupportedVideoSizes;
+
+ bool mInUse;
+ Mutex mLock;
+ Condition mCond;
+
+ void useLock();
+ void signalFinished();
+
+ //------------------------------------------------------------------------
+ // JPEG markers consist of one or more 0xFF bytes, followed by a marker
+ // code byte (which is not an FF). Here are the marker codes of interest
+ // in this program. (See jdmarker.c for a more complete list.)
+ //------------------------------------------------------------------------
+ #define M_SOF0 0xC0 // Start Of Frame N
+ #define M_SOF1 0xC1 // N indicates which compression process
+ #define M_SOF2 0xC2 // Only SOF0-SOF2 are now in common use
+ #define M_SOF3 0xC3
+ #define M_SOF5 0xC5 // NB: codes C4 and CC are NOT SOF markers
+ #define M_SOF6 0xC6
+ #define M_SOF7 0xC7
+ #define M_SOF9 0xC9
+ #define M_SOF10 0xCA
+ #define M_SOF11 0xCB
+ #define M_SOF13 0xCD
+ #define M_SOF14 0xCE
+ #define M_SOF15 0xCF
+ #define M_SOI 0xD8 // Start Of Image (beginning of datastream)
+ #define M_EOI 0xD9 // End Of Image (end of datastream)
+ #define M_SOS 0xDA // Start Of Scan (begins compressed data)
+ #define M_JFIF 0xE0 // Jfif marker
+ #define M_EXIF 0xE1 // Exif marker. Also used for XMP data!
+ #define M_XMP 0x10E1 // Not a real tag same value as Exif!
+ #define M_COM 0xFE // COMment
+ #define M_DQT 0xDB
+ #define M_DHT 0xC4
+ #define M_DRI 0xDD
+ #define M_IPTC 0xED // IPTC marker
+ #define PSEUDO_IMAGE_MARKER 0x123; // Extra value.
+};
+
+class Interpreter
+{
+public:
+ enum Commands_e {
+ SWITCH_CAMERA_CMD = 'A',
+ RESUME_PREVIEW_CMD = '[',
+ START_PREVIEW_CMD = '1',
+ STOP_PREVIEW_CMD = '2',
+ CHANGE_VIDEO_SIZE_CMD = '3',
+ CHANGE_PREVIEW_SIZE_CMD = '4',
+ CHANGE_PICTURE_SIZE_CMD = '5',
+ START_RECORD_CMD = '6',
+ STOP_RECORD_CMD = '7',
+ START_VIV_RECORD_CMD = '8',
+ STOP_VIV_RECORD_CMD = '9',
+ DUMP_CAPS_CMD = 'E',
+ AUTOFOCUS_CMD = 'f',
+ TAKEPICTURE_CMD = 'p',
+ TAKEPICTURE_IN_PICTURE_CMD = 'P',
+ ENABLE_PRV_CALLBACKS_CMD = '&',
+ EXIT_CMD = 'q',
+ DELAY = 'd',
+ ZSL_CMD = 'z',
+ INVALID_CMD = '0'
+ };
+
+ struct Command {
+ Command( Commands_e cmd_, char *arg_ = NULL)
+ : cmd(cmd_)
+ , arg(arg_) {}
+ Command()
+ : cmd(INVALID_CMD)
+ , arg(NULL) {}
+ Commands_e cmd;
+ char *arg;
+ };
+
+ /* API */
+ Interpreter()
+ : mUseScript(false)
+ , mScript(NULL) {}
+
+ Interpreter(const char *file);
+ ~Interpreter();
+
+ Command getCommand(sp<CameraContext> currentCamera);
+ void releasePiPBuff();
+ status_t configureViVCodec();
+ void setViVSize(Size VideoSize, int camIndex);
+ void setTestCtxInst(TestContext *instance);
+ status_t unconfigureViVCodec();
+ status_t ViVEncoderThread();
+ void ViVEncode();
+ static void *ThreadWrapper(void *context);
+
+private:
+ static const int numberOfCommands;
+
+ bool mUseScript;
+ size_t mCmdIndex;
+ char *mScript;
+ Vector<Command> mCommands;
+ TestContext *mTestContext;
+ pthread_t mViVEncThread;
+};
+
+class TestContext
+{
+ friend class CameraContext;
+ friend class Interpreter;
+public:
+ TestContext();
+ ~TestContext();
+
+ size_t GetCamerasNum();
+ status_t FunctionalTest();
+ status_t AddScriptFromFile(const char *scriptFile);
+ void setViVSize(Size VideoSize, int camIndex);
+ void PiPLock();
+ void PiPUnlock();
+ void ViVLock();
+ void ViVUnlock();
+
+private:
+ sp<CameraContext> camera[MAX_CAM_INSTANCES];
+ char GetNextCmd(sp<qcamera::CameraContext> currentCamera);
+ size_t mCurrentCameraIndex;
+ size_t mSaveCurrentCameraIndex;
+ Vector< sp<qcamera::CameraContext> > mAvailableCameras;
+ bool mTestRunning;
+ Interpreter *mInterpreter;
+ Mutex mPiPLock;
+ Condition mPiPCond;
+ bool mPiPinUse;
+ Mutex mViVLock;
+ Condition mViVCond;
+ bool mViVinUse;
+ bool mIsZSLOn;
+
+ typedef struct ViVBuff_t{
+ void *buff;
+ size_t buffSize;
+ size_t YStride;
+ size_t UVStride;
+ size_t YScanLines;
+ size_t UVScanLines;
+ size_t srcWidth;
+ size_t srcHeight;
+ } ViVBuff_t;
+
+ typedef struct ViVVid_t{
+ sp<IGraphicBufferProducer> bufferProducer;
+ sp<Surface> surface;
+ sp<MediaCodec> codec;
+ sp<MediaMuxer> muxer;
+ sp<ANativeWindow> ANW;
+ Vector<sp<ABuffer> > buffers;
+ Size VideoSizes[2];
+ int ViVIdx;
+ size_t buff_cnt;
+ sp<GraphicBuffer> graphBuf;
+ void * mappedBuff;
+ bool isBuffValid;
+ int sourceCameraID;
+ int destinationCameraID;
+ } vidPiP_t;
+
+ ViVVid_t mViVVid;
+ ViVBuff_t mViVBuff;
+};
+
+}; //namespace qcamera
+
+#endif