/* 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;
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