summaryrefslogtreecommitdiffstats
path: root/camera/V4LCameraAdapter/V4LCameraAdapter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'camera/V4LCameraAdapter/V4LCameraAdapter.cpp')
-rwxr-xr-x[-rw-r--r--]camera/V4LCameraAdapter/V4LCameraAdapter.cpp625
1 files changed, 468 insertions, 157 deletions
diff --git a/camera/V4LCameraAdapter/V4LCameraAdapter.cpp b/camera/V4LCameraAdapter/V4LCameraAdapter.cpp
index 29c71c7..2c641ce 100644..100755
--- a/camera/V4LCameraAdapter/V4LCameraAdapter.cpp
+++ b/camera/V4LCameraAdapter/V4LCameraAdapter.cpp
@@ -37,11 +37,10 @@
#include <sys/mman.h>
#include <sys/select.h>
#include <linux/videodev.h>
+#include <cutils/properties.h>
-#include <ui/GraphicBuffer.h>
-#include <ui/GraphicBufferMapper.h>
+#include "DecoderFactory.h"
-#include <cutils/properties.h>
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
static int mDebugFps = 0;
@@ -55,11 +54,6 @@ namespace Camera {
//frames skipped before recalculating the framerate
#define FPS_PERIOD 30
-//define this macro to save first few raw frames when starting the preview.
-//#define SAVE_RAW_FRAMES 1
-//#define DUMP_CAPTURE_FRAME 1
-//#define PPM_PER_FRAME_CONVERSION 1
-
//Proto Types
static void convertYUV422i_yuyvTouyvy(uint8_t *src, uint8_t *dest, size_t size );
static void convertYUV422ToNV12Tiler(unsigned char *src, unsigned char *dest, int width, int height );
@@ -68,14 +62,40 @@ static void convertYUV422ToNV12(unsigned char *src, unsigned char *dest, int wid
android::Mutex gV4LAdapterLock;
char device[15];
+static void debugShowFPS()
+{
+ static int mFrameCount = 0;
+ static int mLastFrameCount = 0;
+ static nsecs_t mLastFpsTime = 0;
+ static float mFps = 0;
+ if(mDebugFps) {
+ mFrameCount++;
+ if ((mFrameCount % 30 == 0)) {
+ nsecs_t now = systemTime();
+ nsecs_t diff = now - mLastFpsTime;
+ mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
+ mLastFpsTime = now;
+ mLastFrameCount = mFrameCount;
+ CAMHAL_LOGE("Camera %d Frames, %f FPS", mFrameCount, mFps);
+ }
+ }
+}
+
/*--------------------Camera Adapter Class STARTS here-----------------------------*/
/*--------------------V4L wrapper functions -------------------------------*/
+
+bool V4LCameraAdapter::isNeedToUseDecoder() const {
+ return mPixelFormat != V4L2_PIX_FMT_YUYV;
+}
+
status_t V4LCameraAdapter::v4lIoctl (int fd, int req, void* argp) {
status_t ret = NO_ERROR;
errno = 0;
+ android::AutoMutex lock(mV4LLock);
+
do {
ret = ioctl (fd, req, argp);
}while (-1 == ret && EINTR == errno);
@@ -86,6 +106,11 @@ status_t V4LCameraAdapter::v4lIoctl (int fd, int req, void* argp) {
status_t V4LCameraAdapter::v4lInitMmap(int& count) {
status_t ret = NO_ERROR;
+ LOG_FUNCTION_NAME;
+
+ int width, height;
+ mParams.getPreviewSize(&width, &height);
+
//First allocate adapter internal buffers at V4L level for USB Cam
//These are the buffers from which we will copy the data into overlay buffers
/* Check if camera can handle NB_BUFFER buffers */
@@ -100,6 +125,10 @@ status_t V4LCameraAdapter::v4lInitMmap(int& count) {
}
count = mVideoInfo->rb.count;
+
+ //Since we will do mapping of new In buffers - clear input MediaBuffer storage
+ mInBuffers.clear();
+
for (int i = 0; i < count; i++) {
memset (&mVideoInfo->buf, 0, sizeof (struct v4l2_buffer));
@@ -126,7 +155,26 @@ status_t V4LCameraAdapter::v4lInitMmap(int& count) {
CAMHAL_LOGEB("Unable to map buffer [%d]. (%s)", i, strerror(errno));
return -1;
}
+
+ MediaBuffer* buffer = new MediaBuffer(i, mVideoInfo->mem[i], mVideoInfo->buf.length);
+ mInBuffers.push_back(buffer);
}
+
+ if (isNeedToUseDecoder()) {
+ mDecoder->registerInputBuffers(&mInBuffers);
+ DecoderParameters params;
+ params.width = width;
+ params.height = height;
+ params.inputBufferCount = count;
+ params.outputBufferCount = count;
+ mDecoder->configure(params);
+ }
+
+
+
+
+ LOG_FUNCTION_NAME_EXIT;
+
return ret;
}
@@ -151,9 +199,14 @@ status_t V4LCameraAdapter::v4lStartStreaming () {
status_t ret = NO_ERROR;
enum v4l2_buf_type bufType;
+ LOG_FUNCTION_NAME;
+
if (!mVideoInfo->isStreaming) {
bufType = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
+ ret = applyFpsValue();
+ if (ret != NO_ERROR) {
+ return ret;
+ }
ret = v4lIoctl (mCameraHandle, VIDIOC_STREAMON, &bufType);
if (ret < 0) {
CAMHAL_LOGEB("StartStreaming: Unable to start capture: %s", strerror(errno));
@@ -161,6 +214,8 @@ status_t V4LCameraAdapter::v4lStartStreaming () {
}
mVideoInfo->isStreaming = true;
}
+
+ LOG_FUNCTION_NAME_EXIT;
return ret;
}
@@ -168,6 +223,8 @@ status_t V4LCameraAdapter::v4lStopStreaming (int nBufferCount) {
status_t ret = NO_ERROR;
enum v4l2_buf_type bufType;
+ LOG_FUNCTION_NAME;
+
if (mVideoInfo->isStreaming) {
bufType = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -199,12 +256,15 @@ status_t V4LCameraAdapter::v4lStopStreaming (int nBufferCount) {
}
}
EXIT:
+ LOG_FUNCTION_NAME_EXIT;
return ret;
}
status_t V4LCameraAdapter::v4lSetFormat (int width, int height, uint32_t pix_format) {
status_t ret = NO_ERROR;
+ LOG_FUNCTION_NAME;
+
mVideoInfo->format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ret = v4lIoctl(mCameraHandle, VIDIOC_G_FMT, &mVideoInfo->format);
if (ret < 0) {
@@ -214,7 +274,7 @@ status_t V4LCameraAdapter::v4lSetFormat (int width, int height, uint32_t pix_for
mVideoInfo->width = width;
mVideoInfo->height = height;
mVideoInfo->framesizeIn = (width * height << 1);
- mVideoInfo->formatIn = DEFAULT_PIXEL_FORMAT;
+ mVideoInfo->formatIn = pix_format;
mVideoInfo->format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
mVideoInfo->format.fmt.pix.width = width;
@@ -228,6 +288,9 @@ status_t V4LCameraAdapter::v4lSetFormat (int width, int height, uint32_t pix_for
}
v4lIoctl(mCameraHandle, VIDIOC_G_FMT, &mVideoInfo->format);
CAMHAL_LOGDB("VIDIOC_G_FMT : WxH = %dx%d", mVideoInfo->format.fmt.pix.width, mVideoInfo->format.fmt.pix.height);
+ CAMHAL_LOGD("### Using: WxH = %dx%d pixelformat=0x%x ", mVideoInfo->format.fmt.pix.width, mVideoInfo->format.fmt.pix.height, mVideoInfo->format.fmt.pix.pixelformat);
+ CAMHAL_LOGD("### Using: bytesperline=%d sizeimage=%d colorspace=0x%x", mVideoInfo->format.fmt.pix.bytesperline, mVideoInfo->format.fmt.pix.sizeimage, mVideoInfo->format.fmt.pix.colorspace);
+ LOG_FUNCTION_NAME_EXIT;
return ret;
}
@@ -238,10 +301,12 @@ status_t V4LCameraAdapter::restartPreview ()
int height = 0;
struct v4l2_streamparm streamParams;
+ LOG_FUNCTION_NAME;
+
//configure for preview size and pixel format.
mParams.getPreviewSize(&width, &height);
- ret = v4lSetFormat (width, height, DEFAULT_PIXEL_FORMAT);
+ ret = v4lSetFormat (width, height, mPixelFormat);
if (ret < 0) {
CAMHAL_LOGEB("v4lSetFormat Failed: %s", strerror(errno));
goto EXIT;
@@ -253,25 +318,14 @@ status_t V4LCameraAdapter::restartPreview ()
goto EXIT;
}
- //set frame rate
- streamParams.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- streamParams.parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
- streamParams.parm.capture.capturemode = V4L2_MODE_HIGHQUALITY;
- streamParams.parm.capture.timeperframe.denominator = FPS_PERIOD;
- streamParams.parm.capture.timeperframe.numerator= 1;
- ret = v4lIoctl(mCameraHandle, VIDIOC_S_PARM, &streamParams);
- if (ret < 0) {
- CAMHAL_LOGEB("VIDIOC_S_PARM Failed: %s", strerror(errno));
- goto EXIT;
- }
-
for (int i = 0; i < mPreviewBufferCountQueueable; i++) {
- mVideoInfo->buf.index = i;
- mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;
+ v4l2_buffer buf;
+ buf.index = i;
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
- ret = v4lIoctl(mCameraHandle, VIDIOC_QBUF, &mVideoInfo->buf);
+ ret = v4lIoctl(mCameraHandle, VIDIOC_QBUF, &buf);
if (ret < 0) {
CAMHAL_LOGEA("VIDIOC_QBUF Failed");
goto EXIT;
@@ -282,6 +336,7 @@ status_t V4LCameraAdapter::restartPreview ()
ret = v4lStartStreaming();
CAMHAL_LOGDA("Ready for preview....");
EXIT:
+ LOG_FUNCTION_NAME_EXIT;
return ret;
}
@@ -291,6 +346,9 @@ status_t V4LCameraAdapter::initialize(CameraProperties::Properties* caps)
char value[PROPERTY_VALUE_MAX];
LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mLock);
+
property_get("debug.camera.showfps", value, "0");
mDebugFps = atoi(value);
@@ -303,7 +361,7 @@ status_t V4LCameraAdapter::initialize(CameraProperties::Properties* caps)
goto EXIT;
}
- if ((mCameraHandle = open(device, O_RDWR) ) == -1) {
+ if ((mCameraHandle = open(device, O_RDWR | O_NONBLOCK) ) == -1) {
CAMHAL_LOGEB("Error while opening handle to V4L2 Camera: %s", strerror(errno));
ret = BAD_VALUE;
goto EXIT;
@@ -342,73 +400,121 @@ status_t V4LCameraAdapter::fillThisBuffer(CameraBuffer *frameBuf, CameraFrame::F
{
status_t ret = NO_ERROR;
int idx = 0;
+
LOG_FUNCTION_NAME;
+ android::AutoMutex lock(mLock);
+
if ( frameType == CameraFrame::IMAGE_FRAME) { //(1 > mCapturedFrames)
// Signal end of image capture
if ( NULL != mEndImageCaptureCallback) {
CAMHAL_LOGDB("===========Signal End Image Capture==========");
+ mLock.unlock();
mEndImageCaptureCallback(mEndCaptureData);
+ mLock.lock();
}
- goto EXIT;
+ return ret;
}
+
if ( !mVideoInfo->isStreaming ) {
- goto EXIT;
+ return ret;
}
- idx = mPreviewBufs.valueFor(frameBuf);
+ for (int xx = 0; xx < NB_BUFFER; xx++){
+ if (mPreviewBufs[xx] == frameBuf){
+ idx = xx;
+ break;
+ }
+ }
+ if (idx == NB_BUFFER){
+ CAMHAL_LOGEB("Wrong index = %d. What do i do? What do i do?",idx);
+ return ret;
+ }
if(idx < 0) {
CAMHAL_LOGEB("Wrong index = %d",idx);
- goto EXIT;
+ return ret;
}
+ if (isNeedToUseDecoder()) {
+ for (int i = 0; i < mOutBuffers.size(); i++) {
+ android::sp<MediaBuffer>& outBuffer = mOutBuffers.editItemAt(i);
+ CameraBuffer* buffer = static_cast<CameraBuffer*>(outBuffer->buffer);
+ if (buffer == frameBuf) {
+ mDecoder->queueOutputBuffer(outBuffer->bufferId);
+ break;
+ }
+ }
- mVideoInfo->buf.index = idx;
- mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;
+ int inIndex = -1;
+ ret = mDecoder->dequeueInputBuffer(inIndex);
- ret = v4lIoctl(mCameraHandle, VIDIOC_QBUF, &mVideoInfo->buf);
- if (ret < 0) {
- CAMHAL_LOGEA("VIDIOC_QBUF Failed");
- goto EXIT;
+ if (ret == NO_ERROR) {
+ ret = returnBufferToV4L(inIndex);
+ }
+
+ } else {
+ v4l2_buffer buf;
+ buf.index = idx;
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
+ CAMHAL_LOGD("Will return buffer to V4L with id=%d", idx);
+ ret = v4lIoctl(mCameraHandle, VIDIOC_QBUF, &buf);
+ if (ret < 0) {
+ CAMHAL_LOGEA("VIDIOC_QBUF Failed");
+ goto EXIT;
+ }
+
+ nQueued++;
}
- nQueued++;
+
EXIT:
LOG_FUNCTION_NAME_EXIT;
return ret;
}
+status_t V4LCameraAdapter::applyFpsValue() {
+ struct v4l2_streamparm streamParams;
+ status_t ret = NO_ERROR;
+ streamParams.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ streamParams.parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
+ streamParams.parm.capture.capturemode = V4L2_MODE_HIGHQUALITY;
+ streamParams.parm.capture.timeperframe.denominator = mFrameRate / CameraHal::VFR_SCALE;
+ streamParams.parm.capture.timeperframe.numerator= 1;
+ ret = v4lIoctl(mCameraHandle, VIDIOC_S_PARM, &streamParams);
+ if (ret < 0) {
+ CAMHAL_LOGEB(" VIDIOC_S_PARM Failed: %s", strerror(errno));
+ return ret;
+ }
+ int actualFps = streamParams.parm.capture.timeperframe.denominator / streamParams.parm.capture.timeperframe.numerator;
+ CAMHAL_LOGDB("Actual FPS set is : %d.", actualFps);
+ return NO_ERROR;
+}
+
status_t V4LCameraAdapter::setParameters(const android::CameraParameters &params)
{
status_t ret = NO_ERROR;
int width, height;
- struct v4l2_streamparm streamParams;
+ int minFps = 0, maxFps = 0;
LOG_FUNCTION_NAME;
+ android::AutoMutex lock(mLock);
+
if(!mPreviewing && !mCapturing) {
params.getPreviewSize(&width, &height);
- CAMHAL_LOGDB("Width * Height %d x %d format 0x%x", width, height, DEFAULT_PIXEL_FORMAT);
-
- ret = v4lSetFormat( width, height, DEFAULT_PIXEL_FORMAT);
+ CAMHAL_LOGDB("Width * Height %d x %d format 0x%x", width, height, mPixelFormat);
+ ret = v4lSetFormat( width, height, mPixelFormat);
if (ret < 0) {
CAMHAL_LOGEB(" VIDIOC_S_FMT Failed: %s", strerror(errno));
goto EXIT;
}
- //set frame rate
- // Now its fixed to 30 FPS
- streamParams.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- streamParams.parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
- streamParams.parm.capture.capturemode = V4L2_MODE_HIGHQUALITY;
- streamParams.parm.capture.timeperframe.denominator = FPS_PERIOD;
- streamParams.parm.capture.timeperframe.numerator= 1;
- ret = v4lIoctl(mCameraHandle, VIDIOC_S_PARM, &streamParams);
- if (ret < 0) {
- CAMHAL_LOGEB(" VIDIOC_S_PARM Failed: %s", strerror(errno));
- goto EXIT;
+
+ params.getPreviewFpsRange(&minFps, &maxFps);
+ CAMHAL_LOGD("Current fps is %d new fps is (%d,%d)", mFrameRate, minFps, maxFps);
+ if (maxFps != mFrameRate) {
+ mFrameRate = maxFps;
}
- int actualFps = streamParams.parm.capture.timeperframe.denominator / streamParams.parm.capture.timeperframe.numerator;
- CAMHAL_LOGDB("Actual FPS set is : %d.", actualFps);
+
}
// Udpate the current parameter set
@@ -424,6 +530,7 @@ void V4LCameraAdapter::getParameters(android::CameraParameters& params)
{
LOG_FUNCTION_NAME;
+ android::AutoMutex lock(mLock);
// Return the current parameter set
params = mParams;
@@ -485,6 +592,17 @@ status_t V4LCameraAdapter::UseBuffersCapture(CameraBuffer *bufArr, int num) {
CAMHAL_LOGDB("capture- buff [%d] = 0x%x ",i, mCaptureBufs.keyAt(i));
}
+ mCaptureBuffersAvailable.clear();
+ for (int i = 0; i < mCaptureBufferCountQueueable; i++ ) {
+ mCaptureBuffersAvailable.add(&mCaptureBuffers[i], 0);
+ }
+
+ // initial ref count for undeqeueued buffers is 1 since buffer provider
+ // is still holding on to it
+ for (int i = mCaptureBufferCountQueueable; i < num; i++ ) {
+ mCaptureBuffersAvailable.add(&mCaptureBuffers[i], 1);
+ }
+
// Update the preview buffer count
mCaptureBufferCount = num;
EXIT:
@@ -504,13 +622,20 @@ status_t V4LCameraAdapter::UseBuffersPreview(CameraBuffer *bufArr, int num)
}
ret = v4lInitMmap(num);
+
+ mOutBuffers.clear();
+
if (ret == NO_ERROR) {
for (int i = 0; i < num; i++) {
//Associate each Camera internal buffer with the one from Overlay
- mPreviewBufs.add(&bufArr[i], i);
- CAMHAL_LOGDB("Preview- buff [%d] = 0x%x ",i, mPreviewBufs.keyAt(i));
+ mPreviewBufs[i] = &bufArr[i];
+ MediaBuffer* buffer = new MediaBuffer(i, mPreviewBufs[i]);
+ mOutBuffers.push_back(buffer);
+ CAMHAL_LOGDB("Preview- buff [%d] = 0x%x length=%d",i, mPreviewBufs[i], mFrameQueue.valueFor(mPreviewBufs[i])->mLength);
+ }
+ if (isNeedToUseDecoder()) {
+ mDecoder->registerOutputBuffers(&mOutBuffers);
}
-
// Update the preview buffer count
mPreviewBufferCount = num;
}
@@ -531,7 +656,7 @@ status_t V4LCameraAdapter::takePicture() {
LOG_FUNCTION_NAME;
- android::AutoMutex lock(mCaptureBufsLock);
+ android::AutoMutex lock(mLock);
if(mCapturing) {
CAMHAL_LOGEA("Already Capture in Progress...");
@@ -554,7 +679,7 @@ status_t V4LCameraAdapter::takePicture() {
CAMHAL_LOGDB("Image Capture Size WxH = %dx%d",width,height);
yuv422i_buff_size = width * height * 2;
- ret = v4lSetFormat (width, height, DEFAULT_PIXEL_FORMAT);
+ ret = v4lSetFormat (width, height, DEFAULT_CAPTURE_FORMAT);
if (ret < 0) {
CAMHAL_LOGEB("v4lSetFormat Failed: %s", strerror(errno));
goto EXIT;
@@ -568,11 +693,12 @@ status_t V4LCameraAdapter::takePicture() {
for (int i = 0; i < mCaptureBufferCountQueueable; i++) {
- mVideoInfo->buf.index = i;
- mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;
+ v4l2_buffer buf;
+ buf.index = i;
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
- ret = v4lIoctl(mCameraHandle, VIDIOC_QBUF, &mVideoInfo->buf);
+ ret = v4lIoctl(mCameraHandle, VIDIOC_QBUF, &buf);
if (ret < 0) {
CAMHAL_LOGEA("VIDIOC_QBUF Failed");
ret = BAD_VALUE;
@@ -590,7 +716,9 @@ status_t V4LCameraAdapter::takePicture() {
CAMHAL_LOGDA("Streaming started for Image Capture");
//get the frame and send to encode as JPG
- fp = this->GetFrame(index);
+ int filledLen;
+ CAMHAL_LOGD("*********Will dequeue frame for Image Capture***********");
+ fp = this->GetFrame(index, filledLen);
if(!fp) {
CAMHAL_LOGEA("!!! Captured frame is NULL !!!!");
ret = BAD_VALUE;
@@ -599,7 +727,7 @@ status_t V4LCameraAdapter::takePicture() {
CAMHAL_LOGDA("::Capture Frame received from V4L::");
buffer = mCaptureBufs.keyAt(index);
- CAMHAL_LOGVB("## captureBuf[%d] = 0x%x, yuv422i_buff_size=%d", index, buffer->opaque, yuv422i_buff_size);
+ CAMHAL_LOGVB("## captureBuf[%d] = 0x%x, yuv422i_buff_size=%d fill_length=%d", index, buffer->opaque, yuv422i_buff_size, filledLen);
//copy the yuv422i data to the image buffer.
memcpy(buffer->opaque, fp, yuv422i_buff_size);
@@ -659,6 +787,8 @@ status_t V4LCameraAdapter::stopImageCapture()
status_t ret = NO_ERROR;
LOG_FUNCTION_NAME;
+ android::AutoMutex lock(mLock);
+
//Release image buffers
if ( NULL != mReleaseImageBuffersCallback ) {
mReleaseImageBuffersCallback(mReleaseData);
@@ -686,7 +816,8 @@ status_t V4LCameraAdapter::startPreview()
status_t ret = NO_ERROR;
LOG_FUNCTION_NAME;
- android::AutoMutex lock(mPreviewBufsLock);
+
+ android::AutoMutex lock(mLock);
if(mPreviewing) {
ret = BAD_VALUE;
@@ -695,18 +826,25 @@ status_t V4LCameraAdapter::startPreview()
for (int i = 0; i < mPreviewBufferCountQueueable; i++) {
- mVideoInfo->buf.index = i;
- mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;
+ v4l2_buffer buf;
+ buf.index = i;
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
- ret = v4lIoctl(mCameraHandle, VIDIOC_QBUF, &mVideoInfo->buf);
+ ret = v4lIoctl(mCameraHandle, VIDIOC_QBUF, &buf);
if (ret < 0) {
CAMHAL_LOGEA("VIDIOC_QBUF Failed");
goto EXIT;
}
nQueued++;
}
-
+ if (isNeedToUseDecoder()) {
+ for (int i = 0; i < mPreviewBufferCountQueueable; i++) {
+ mDecoder->queueOutputBuffer(i);
+ CAMHAL_LOGV("Queued output buffer with id=%d ", i);
+ }
+ mDecoder->start();
+ }
ret = v4lStartStreaming();
// Create and start preview thread for receiving buffers from V4L Camera
@@ -730,13 +868,19 @@ status_t V4LCameraAdapter::stopPreview()
int ret = NO_ERROR;
LOG_FUNCTION_NAME;
- android::AutoMutex lock(mStopPreviewLock);
+
+ android::AutoMutex lock(mLock);
if(!mPreviewing) {
return NO_INIT;
}
mPreviewing = false;
-
+ if (isNeedToUseDecoder()) {
+ android::AutoMutex lock(mStopLock);
+ mStopCondition.waitRelative(mStopLock, 100000000);
+ mDecoder->stop();
+ mDecoder->flush();
+ }
ret = v4lStopStreaming(mPreviewBufferCount);
if (ret < 0) {
CAMHAL_LOGEB("StopStreaming: FAILED: %s", strerror(errno));
@@ -746,37 +890,90 @@ status_t V4LCameraAdapter::stopPreview()
nDequeued = 0;
mFramesWithEncoder = 0;
- mPreviewBufs.clear();
+ mLock.unlock();
mPreviewThread->requestExitAndWait();
mPreviewThread.clear();
+
LOG_FUNCTION_NAME_EXIT;
return ret;
}
-char * V4LCameraAdapter::GetFrame(int &index)
+
+void saveFile(unsigned char* buff, int buff_size) {
+ static int counter = 1;
+ int fd = -1;
+ char fn[256];
+
+ LOG_FUNCTION_NAME;
+ if (counter > 30) {
+ return;
+ }
+ //dump nv12 buffer
+ counter++;
+ sprintf(fn, "/data/tmp/dump_%03d.h264", counter);
+ CAMHAL_LOGEB("Dumping h264 frame to a file : %s.", fn);
+
+ fd = open(fn, O_CREAT | O_WRONLY | O_SYNC | O_TRUNC, 0777);
+ if(fd < 0) {
+ CAMHAL_LOGE("Unable to open file %s: %s", fn, strerror(fd));
+ return;
+ }
+
+ write(fd, buff, buff_size );
+ close(fd);
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+char * V4LCameraAdapter::GetFrame(int &index, int &filledLen)
{
int ret = NO_ERROR;
LOG_FUNCTION_NAME;
- mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;
+ v4l2_buffer buf;
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
/* DQ */
- ret = v4lIoctl(mCameraHandle, VIDIOC_DQBUF, &mVideoInfo->buf);
+ // Some V4L drivers, notably uvc, protect each incoming call with
+ // a driver-wide mutex. If we use poll() or blocking VIDIOC_DQBUF ioctl
+ // here then we sometimes would run into a deadlock on VIDIO_QBUF ioctl.
+ while(true) {
+ if(!mVideoInfo->isStreaming) {
+ return NULL;
+ }
+
+ ret = v4lIoctl(mCameraHandle, VIDIOC_DQBUF, &buf);
+ if((ret == 0) || (errno != EAGAIN)) {
+ break;
+ }
+ }
+
if (ret < 0) {
CAMHAL_LOGEA("GetFrame: VIDIOC_DQBUF Failed");
return NULL;
}
- nDequeued++;
- index = mVideoInfo->buf.index;
+ index = buf.index;
+ filledLen = buf.bytesused;
+ android::sp<MediaBuffer>& inBuffer = mInBuffers.editItemAt(index);
+ {
+ android::AutoMutex bufferLock(inBuffer->getLock());
+ inBuffer->setTimestamp(systemTime(SYSTEM_TIME_MONOTONIC));
+ inBuffer->filledLen = buf.bytesused;
+ }
+ debugShowFPS();
LOG_FUNCTION_NAME_EXIT;
- return (char *)mVideoInfo->mem[mVideoInfo->buf.index];
+ return (char *)mVideoInfo->mem[index];
}
+
+
+
+
//API to get the frame size required to be allocated. This size is used to override the size passed
//by camera service when VSTAB/VNF is turned ON for example
status_t V4LCameraAdapter::getFrameSize(size_t &width, size_t &height)
@@ -784,9 +981,15 @@ status_t V4LCameraAdapter::getFrameSize(size_t &width, size_t &height)
status_t ret = NO_ERROR;
LOG_FUNCTION_NAME;
+ android::AutoMutex lock(mLock);
+
// Just return the current preview size, nothing more to do here.
- mParams.getPreviewSize(( int * ) &width,
- ( int * ) &height);
+ mParams.getPreviewSize(( int * ) &width,( int * ) &height);
+
+ // TODO: This will reside until correct port reconfiguration handling will done.
+ if (isNeedToUseDecoder()) {
+ mDecoder->getPaddedDimensions(width, height);
+ }
LOG_FUNCTION_NAME_EXIT;
@@ -795,11 +998,12 @@ status_t V4LCameraAdapter::getFrameSize(size_t &width, size_t &height)
status_t V4LCameraAdapter::getFrameDataSize(size_t &dataFrameSize, size_t bufferCount)
{
+ android::AutoMutex lock(mLock);
// We don't support meta data, so simply return
return NO_ERROR;
}
-status_t V4LCameraAdapter::getPictureBufferSize(CameraFrame *frame, size_t bufferCount)
+status_t V4LCameraAdapter::getPictureBufferSize(CameraFrame &frame, size_t bufferCount)
{
int width = 0;
int height = 0;
@@ -807,41 +1011,20 @@ status_t V4LCameraAdapter::getPictureBufferSize(CameraFrame *frame, size_t buffe
LOG_FUNCTION_NAME;
- if (frame == NULL) {
- return BAD_VALUE;
- }
+ android::AutoMutex lock(mLock);
mParams.getPictureSize( &width, &height );
- frame->mLength = width * height * bytesPerPixel;
- frame->mWidth = width;
- frame->mHeight = height;
- frame->mAlignment = width * bytesPerPixel;
+ frame.mLength = width * height * bytesPerPixel;
+ frame.mWidth = width;
+ frame.mHeight = height;
+ frame.mAlignment = width * bytesPerPixel;
CAMHAL_LOGDB("Picture size: W x H = %u x %u (size=%u bytes, alignment=%u bytes)",
- frame->mWidth, frame->mHeight, frame->mLength, frame->mAlignment);
+ frame.mWidth, frame.mHeight, frame.mLength, frame.mAlignment);
LOG_FUNCTION_NAME_EXIT;
return NO_ERROR;
}
-static void debugShowFPS()
-{
- static int mFrameCount = 0;
- static int mLastFrameCount = 0;
- static nsecs_t mLastFpsTime = 0;
- static float mFps = 0;
- if(mDebugFps) {
- mFrameCount++;
- if (!(mFrameCount & 0x1F)) {
- nsecs_t now = systemTime();
- nsecs_t diff = now - mLastFpsTime;
- mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
- mLastFpsTime = now;
- mLastFrameCount = mFrameCount;
- CAMHAL_LOGD("Camera %d Frames, %f FPS", mFrameCount, mFps);
- }
- }
-}
-
status_t V4LCameraAdapter::recalculateFPS()
{
float currentFPS;
@@ -877,16 +1060,70 @@ void V4LCameraAdapter::onOrientationEvent(uint32_t orientation, uint32_t tilt)
{
LOG_FUNCTION_NAME;
+ android::AutoMutex lock(mLock);
+
LOG_FUNCTION_NAME_EXIT;
}
+void V4LCameraAdapter::setupWorkingMode() {
+ char value[PROPERTY_VALUE_MAX];
+ int v4lMode = 0;
-V4LCameraAdapter::V4LCameraAdapter(size_t sensor_index)
+ property_get("camera.v4l.mode", value, "3");
+ v4lMode = atoi(value);
+
+ if (mDecoder) {
+ delete mDecoder;
+ mDecoder = NULL;
+ }
+
+ switch (v4lMode) {
+ case 0 : {
+ mPixelFormat = V4L2_PIX_FMT_MJPEG;
+ mCameraHal->setExternalLocking(true);
+ mDecoder = DecoderFactory::createDecoderByType(DecoderType_MJPEG, false);
+ CAMHAL_LOGI("Using V4L preview format: V4L2_PIX_FMT_MJPEG with HW decoding");
+ break;
+ }
+
+ case 1 : {
+ mPixelFormat = V4L2_PIX_FMT_MJPEG;
+ mCameraHal->setExternalLocking(false);
+ mDecoder = DecoderFactory::createDecoderByType(DecoderType_MJPEG, true);
+ CAMHAL_LOGI("Using V4L preview format: V4L2_PIX_FMT_MJPEG with SW decoding");
+ break;
+ }
+
+ case 2 : {
+ // This is WA for Kernel 3.0 - till correct h264 parsing come.
+ mPixelFormat = 0;//V4L2_PIX_FMT_H264
+ mCameraHal->setExternalLocking(true);
+ mDecoder = DecoderFactory::createDecoderByType(DecoderType_H264, false);
+ CAMHAL_LOGI("Using V4L preview format: V4L2_PIX_FMT_H264");
+ break;
+ }
+ default:
+ case 3 : {
+ mCameraHal->setExternalLocking(false);
+ mPixelFormat = V4L2_PIX_FMT_YUYV;
+ CAMHAL_LOGI("Using V4L preview format: V4L2_PIX_FMT_YUYV");
+ }
+
+ }
+}
+
+V4LCameraAdapter::V4LCameraAdapter(size_t sensor_index, CameraHal* hal)
+ :mPixelFormat(DEFAULT_PIXEL_FORMAT), mFrameRate(0), mCameraHal(hal)
{
LOG_FUNCTION_NAME;
// Nothing useful to do in the constructor
mFramesWithEncoder = 0;
+ mDecoder = 0;
+ nQueued = 0;
+ nDequeued = 0;
+
+ setupWorkingMode();
LOG_FUNCTION_NAME_EXIT;
}
@@ -904,6 +1141,11 @@ V4LCameraAdapter::~V4LCameraAdapter()
mVideoInfo = NULL;
}
+ delete mDecoder;
+
+ mInBuffers.clear();
+ mOutBuffers.clear();
+
LOG_FUNCTION_NAME_EXIT;
}
@@ -1075,36 +1317,73 @@ static void convertYUV422ToNV12(unsigned char *src, unsigned char *dest, int wid
LOG_FUNCTION_NAME_EXIT;
}
-#ifdef SAVE_RAW_FRAMES
-void saveFile(unsigned char* buff, int buff_size) {
- static int counter = 1;
- int fd = -1;
- char fn[256];
+
+
+
+/* Preview Thread */
+// ---------------------------------------------------------------------------
+
+void V4LCameraAdapter::returnOutputBuffer(int index)
+{
LOG_FUNCTION_NAME;
- if (counter > 3) {
- return;
- }
- //dump nv12 buffer
- counter++;
- sprintf(fn, "/data/misc/camera/raw/nv12_dump_%03d.yuv", counter);
- CAMHAL_LOGEB("Dumping nv12 frame to a file : %s.", fn);
- fd = open(fn, O_CREAT | O_WRONLY | O_SYNC | O_TRUNC, 0777);
- if(fd < 0) {
- CAMHAL_LOGE("Unable to open file %s: %s", fn, strerror(fd));
- return;
+ size_t width, height;
+ int stride = 4096;
+ CameraFrame frame;
+
+ getFrameSize(width, height);
+
+ android::Mutex::Autolock slock(mSubscriberLock);
+
+ android::sp<MediaBuffer>& buffer = mOutBuffers.editItemAt(index);
+
+ CameraBuffer* cbuffer = static_cast<CameraBuffer*>(buffer->buffer);
+
+ frame.mFrameType = CameraFrame::PREVIEW_FRAME_SYNC;
+ frame.mBuffer = cbuffer;
+ if (isNeedToUseDecoder()) {
+ //We always get NV12 on out, when using decoder.
+ frame.mLength = height * stride * 3 / 2;
+ } else {
+ frame.mLength = CameraHal::calculateBufferSize(mParams.getPreviewFormat(), width, height);
}
+ frame.mAlignment = stride;
+ frame.mOffset = buffer->getOffset();
+ frame.mTimestamp = buffer->getTimestamp();
+ frame.mFrameMask = (unsigned int)CameraFrame::PREVIEW_FRAME_SYNC;
- write(fd, buff, buff_size );
- close(fd);
+ if (mRecording)
+ {
+ frame.mFrameMask |= (unsigned int)CameraFrame::VIDEO_FRAME_SYNC;
+ mFramesWithEncoder++;
+ }
+ int ret = setInitFrameRefCount(frame.mBuffer, frame.mFrameMask);
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGDB("Error in setInitFrameRefCount %d", ret);
+ } else {
+ ret = sendFrameToSubscribers(&frame);
+ }
+ //debugShowFPS();
LOG_FUNCTION_NAME_EXIT;
}
-#endif
-/* Preview Thread */
-// ---------------------------------------------------------------------------
+status_t V4LCameraAdapter::returnBufferToV4L(int id) {
+ status_t ret = NO_ERROR;
+ v4l2_buffer buf;
+ buf.index = id;
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
+
+ ret = v4lIoctl(mCameraHandle, VIDIOC_QBUF, &buf);
+ if (ret < 0) {
+ CAMHAL_LOGEA("VIDIOC_QBUF Failed 0x%x", ret);
+ return FAILED_TRANSACTION;
+ }
+
+ return NO_ERROR;
+}
int V4LCameraAdapter::previewThread()
{
@@ -1113,36 +1392,65 @@ int V4LCameraAdapter::previewThread()
CameraFrame frame;
void *y_uv[2];
int index = 0;
+ int filledLen = 0;
int stride = 4096;
char *fp = NULL;
mParams.getPreviewSize(&width, &height);
- if (mPreviewing) {
+ {
+ android::AutoMutex lock(mLock);
+ if (!mPreviewing) {
+ //If stop preview is called - it can now go on.
+ android::AutoMutex stopLock(mStopLock);
+ mStopCondition.signal();
+ return ret;
+ }
+ }
- fp = this->GetFrame(index);
- if(!fp) {
- ret = BAD_VALUE;
- goto EXIT;
+ {
+ android::Mutex::Autolock lock(mSubscriberLock);
+ if ( mFrameSubscribers.size() == 0 ) {
+ return BAD_VALUE;
}
- CameraBuffer *buffer = mPreviewBufs.keyAt(index);
- CameraFrame *lframe = (CameraFrame *)mFrameQueue.valueFor(buffer);
- if (!lframe) {
- ret = BAD_VALUE;
- goto EXIT;
+ }
+
+ if (isNeedToUseDecoder()){
+
+ CAMHAL_LOGV("########### Decoder ###########");
+ int inIndex = -1, outIndex = -1;
+
+ if (GetFrame(index, filledLen) != NULL) {
+ CAMHAL_LOGD("Dequeued buffer from V4L with ID=%d", index);
+ mDecoder->queueInputBuffer(index);
}
- debugShowFPS();
+ while (NO_ERROR == mDecoder->dequeueInputBuffer(inIndex)) {
+ returnBufferToV4L(inIndex);
+ }
- if ( mFrameSubscribers.size() == 0 ) {
- ret = BAD_VALUE;
- goto EXIT;
+ while (NO_ERROR == mDecoder->dequeueOutputBuffer(outIndex)) {
+ returnOutputBuffer(outIndex);
}
- y_uv[0] = (void*) lframe->mYuv[0];
- //y_uv[1] = (void*) lframe->mYuv[1];
- //y_uv[1] = (void*) (lframe->mYuv[0] + height*stride);
- convertYUV422ToNV12Tiler ( (unsigned char*)fp, (unsigned char*)y_uv[0], width, height);
- CAMHAL_LOGVB("##...index= %d.;camera buffer= 0x%x; y= 0x%x; UV= 0x%x.",index, buffer, y_uv[0], y_uv[1] );
+
+ CAMHAL_LOGV("########### End Decode ###########");
+ goto EXIT;
+ }
+ else
+ {
+ fp = GetFrame(index, filledLen);
+
+ if(!fp) {
+ ret = BAD_VALUE;
+ goto EXIT;
+ }
+ CAMHAL_LOGD("GOT IN frame with ID=%d",index);
+
+ CameraBuffer *buffer = mPreviewBufs[index];
+ if (mPixelFormat == V4L2_PIX_FMT_YUYV) {
+ convertYUV422ToNV12Tiler(reinterpret_cast<unsigned char*>(fp), reinterpret_cast<unsigned char*>(buffer->mapped), width, height);
+ }
+ CAMHAL_LOGVB("##...index= %d.;camera buffer= 0x%x; mapped= 0x%x.",index, buffer, buffer->mapped);
#ifdef SAVE_RAW_FRAMES
unsigned char* nv12_buff = (unsigned char*) malloc(width*height*3/2);
@@ -1152,6 +1460,8 @@ int V4LCameraAdapter::previewThread()
free (nv12_buff);
#endif
+ android::Mutex::Autolock lock(mSubscriberLock);
+
frame.mFrameType = CameraFrame::PREVIEW_FRAME_SYNC;
frame.mBuffer = buffer;
frame.mLength = width*height*3/2;
@@ -1173,6 +1483,7 @@ int V4LCameraAdapter::previewThread()
ret = sendFrameToSubscribers(&frame);
}
}
+
EXIT:
return ret;
@@ -1208,14 +1519,14 @@ void detectVideoDevice(char** video_device_list, int& num_device) {
}
}
-extern "C" CameraAdapter* V4LCameraAdapter_Factory(size_t sensor_index)
+extern "C" CameraAdapter* V4LCameraAdapter_Factory(size_t sensor_index, CameraHal* hal)
{
CameraAdapter *adapter = NULL;
android::AutoMutex lock(gV4LAdapterLock);
LOG_FUNCTION_NAME;
- adapter = new V4LCameraAdapter(sensor_index);
+ adapter = new V4LCameraAdapter(sensor_index, hal);
if ( adapter ) {
CAMHAL_LOGDB("New V4L Camera adapter instance created for sensor %d",sensor_index);
} else {