/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <errno.h>
#include <fcntl.h>
#include <linux/videodev2.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>

#include <iostream>
#include <new>

#include "webrtc/modules/video_capture/linux/video_capture_linux.h"
#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
#include "webrtc/system_wrappers/include/ref_count.h"
#include "webrtc/system_wrappers/include/trace.h"

namespace webrtc
{
namespace videocapturemodule
{
VideoCaptureModule* VideoCaptureImpl::Create(const int32_t id,
                                             const char* deviceUniqueId)
{
    RefCountImpl<videocapturemodule::VideoCaptureModuleV4L2>* implementation =
        new RefCountImpl<videocapturemodule::VideoCaptureModuleV4L2>(id);

    if (!implementation || implementation->Init(deviceUniqueId) != 0)
    {
        delete implementation;
        implementation = NULL;
    }

    return implementation;
}

VideoCaptureModuleV4L2::VideoCaptureModuleV4L2(const int32_t id)
    : VideoCaptureImpl(id),
      _captureCritSect(CriticalSectionWrapper::CreateCriticalSection()),
      _deviceId(-1),
      _deviceFd(-1),
      _buffersAllocatedByDevice(-1),
      _currentWidth(-1),
      _currentHeight(-1),
      _currentFrameRate(-1),
      _captureStarted(false),
      _captureVideoType(kVideoI420),
      _pool(NULL)
{
}

int32_t VideoCaptureModuleV4L2::Init(const char* deviceUniqueIdUTF8)
{
    int len = strlen((const char*) deviceUniqueIdUTF8);
    _deviceUniqueId = new (std::nothrow) char[len + 1];
    if (_deviceUniqueId)
    {
        memcpy(_deviceUniqueId, deviceUniqueIdUTF8, len + 1);
    }

    int fd;
    char device[32];
    bool found = false;

    /* detect /dev/video [0-63] entries */
    int n;
    for (n = 0; n < 64; n++)
    {
        sprintf(device, "/dev/video%d", n);
        if ((fd = open(device, O_RDONLY)) != -1)
        {
            // query device capabilities
            struct v4l2_capability cap;
            if (ioctl(fd, VIDIOC_QUERYCAP, &cap) == 0)
            {
                if (cap.bus_info[0] != 0)
                {
                    if (strncmp((const char*) cap.bus_info,
                                (const char*) deviceUniqueIdUTF8,
                                strlen((const char*) deviceUniqueIdUTF8)) == 0) //match with device id
                    {
                        close(fd);
                        found = true;
                        break; // fd matches with device unique id supplied
                    }
                }
            }
            close(fd); // close since this is not the matching device
        }
    }
    if (!found)
    {
        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, "no matching device found");
        return -1;
    }
    _deviceId = n; //store the device id
    return 0;
}

VideoCaptureModuleV4L2::~VideoCaptureModuleV4L2()
{
    StopCapture();
    if (_captureCritSect)
    {
        delete _captureCritSect;
    }
    if (_deviceFd != -1)
      close(_deviceFd);
}

int32_t VideoCaptureModuleV4L2::StartCapture(
    const VideoCaptureCapability& capability)
{
    if (_captureStarted)
    {
        if (capability.width == _currentWidth &&
            capability.height == _currentHeight &&
            _captureVideoType == capability.rawType)
        {
            return 0;
        }
        else
        {
            StopCapture();
        }
    }

    CriticalSectionScoped cs(_captureCritSect);
    //first open /dev/video device
    char device[20];
    sprintf(device, "/dev/video%d", (int) _deviceId);

    if ((_deviceFd = open(device, O_RDWR | O_NONBLOCK, 0)) < 0)
    {
        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
                   "error in opening %s errono = %d", device, errno);
        return -1;
    }

    // Supported video formats in preferred order.
    // If the requested resolution is larger than VGA, we prefer MJPEG. Go for
    // I420 otherwise.
    const int nFormats = 5;
    unsigned int fmts[nFormats];
    if (capability.width > 640 || capability.height > 480) {
        fmts[0] = V4L2_PIX_FMT_MJPEG;
        fmts[1] = V4L2_PIX_FMT_YUV420;
        fmts[2] = V4L2_PIX_FMT_YUYV;
        fmts[3] = V4L2_PIX_FMT_UYVY;
        fmts[4] = V4L2_PIX_FMT_JPEG;
    } else {
        fmts[0] = V4L2_PIX_FMT_YUV420;
        fmts[1] = V4L2_PIX_FMT_YUYV;
        fmts[2] = V4L2_PIX_FMT_UYVY;
        fmts[3] = V4L2_PIX_FMT_MJPEG;
        fmts[4] = V4L2_PIX_FMT_JPEG;
    }

    // Enumerate image formats.
    struct v4l2_fmtdesc fmt;
    int fmtsIdx = nFormats;
    memset(&fmt, 0, sizeof(fmt));
    fmt.index = 0;
    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideoCapture, _id,
                 "Video Capture enumerats supported image formats:");
    while (ioctl(_deviceFd, VIDIOC_ENUM_FMT, &fmt) == 0) {
        WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideoCapture, _id,
                     "  { pixelformat = %c%c%c%c, description = '%s' }",
                     fmt.pixelformat & 0xFF, (fmt.pixelformat>>8) & 0xFF,
                     (fmt.pixelformat>>16) & 0xFF, (fmt.pixelformat>>24) & 0xFF,
                     fmt.description);
        // Match the preferred order.
        for (int i = 0; i < nFormats; i++) {
            if (fmt.pixelformat == fmts[i] && i < fmtsIdx)
                fmtsIdx = i;
        }
        // Keep enumerating.
        fmt.index++;
    }

    if (fmtsIdx == nFormats)
    {
        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
                     "no supporting video formats found");
        return -1;
    } else {
        WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideoCapture, _id,
                     "We prefer format %c%c%c%c",
                     fmts[fmtsIdx] & 0xFF, (fmts[fmtsIdx]>>8) & 0xFF,
                     (fmts[fmtsIdx]>>16) & 0xFF, (fmts[fmtsIdx]>>24) & 0xFF);
    }

    struct v4l2_format video_fmt;
    memset(&video_fmt, 0, sizeof(struct v4l2_format));
    video_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    video_fmt.fmt.pix.sizeimage = 0;
    video_fmt.fmt.pix.width = capability.width;
    video_fmt.fmt.pix.height = capability.height;
    video_fmt.fmt.pix.pixelformat = fmts[fmtsIdx];

    if (video_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
        _captureVideoType = kVideoYUY2;
    else if (video_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420)
        _captureVideoType = kVideoI420;
    else if (video_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY)
        _captureVideoType = kVideoUYVY;
    else if (video_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG ||
             video_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_JPEG)
        _captureVideoType = kVideoMJPEG;

    //set format and frame size now
    if (ioctl(_deviceFd, VIDIOC_S_FMT, &video_fmt) < 0)
    {
        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
                   "error in VIDIOC_S_FMT, errno = %d", errno);
        return -1;
    }

    // initialize current width and height
    _currentWidth = video_fmt.fmt.pix.width;
    _currentHeight = video_fmt.fmt.pix.height;
    _captureDelay = 120;

    // Trying to set frame rate, before check driver capability.
    bool driver_framerate_support = true;
    struct v4l2_streamparm streamparms;
    memset(&streamparms, 0, sizeof(streamparms));
    streamparms.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    if (ioctl(_deviceFd, VIDIOC_G_PARM, &streamparms) < 0) {
        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
                   "error in VIDIOC_G_PARM errno = %d", errno);
        driver_framerate_support = false;
      // continue
    } else {
      // check the capability flag is set to V4L2_CAP_TIMEPERFRAME.
      if (streamparms.parm.capture.capability == V4L2_CAP_TIMEPERFRAME) {
        // driver supports the feature. Set required framerate.
        memset(&streamparms, 0, sizeof(streamparms));
        streamparms.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        streamparms.parm.capture.timeperframe.numerator = 1;
        streamparms.parm.capture.timeperframe.denominator = capability.maxFPS;
        if (ioctl(_deviceFd, VIDIOC_S_PARM, &streamparms) < 0) {
          WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
                   "Failed to set the framerate. errno=%d", errno);
          driver_framerate_support = false;
        } else {
          _currentFrameRate = capability.maxFPS;
        }
      }
    }
    // If driver doesn't support framerate control, need to hardcode.
    // Hardcoding the value based on the frame size.
    if (!driver_framerate_support) {
      if(_currentWidth >= 800 && _captureVideoType != kVideoMJPEG) {
        _currentFrameRate = 15;
      } else {
        _currentFrameRate = 30;
      }
    }

    if (!AllocateVideoBuffers())
    {
        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
                   "failed to allocate video capture buffers");
        return -1;
    }

    //start capture thread;
    if (!_captureThread)
    {
        _captureThread = PlatformThread::CreateThread(
            VideoCaptureModuleV4L2::CaptureThread, this, "CaptureThread");
        _captureThread->Start();
        _captureThread->SetPriority(kHighPriority);
    }

    // Needed to start UVC camera - from the uvcview application
    enum v4l2_buf_type type;
    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    if (ioctl(_deviceFd, VIDIOC_STREAMON, &type) == -1)
    {
        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
                     "Failed to turn on stream");
        return -1;
    }

    _captureStarted = true;
    return 0;
}

int32_t VideoCaptureModuleV4L2::StopCapture()
{
    if (_captureThread) {
        // Make sure the capture thread stop stop using the critsect.
        _captureThread->Stop();
        _captureThread.reset();
    }

    CriticalSectionScoped cs(_captureCritSect);
    if (_captureStarted)
    {
        _captureStarted = false;

        DeAllocateVideoBuffers();
        close(_deviceFd);
        _deviceFd = -1;
    }

    return 0;
}

//critical section protected by the caller

bool VideoCaptureModuleV4L2::AllocateVideoBuffers()
{
    struct v4l2_requestbuffers rbuffer;
    memset(&rbuffer, 0, sizeof(v4l2_requestbuffers));

    rbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    rbuffer.memory = V4L2_MEMORY_MMAP;
    rbuffer.count = kNoOfV4L2Bufffers;

    if (ioctl(_deviceFd, VIDIOC_REQBUFS, &rbuffer) < 0)
    {
        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
                   "Could not get buffers from device. errno = %d", errno);
        return false;
    }

    if (rbuffer.count > kNoOfV4L2Bufffers)
        rbuffer.count = kNoOfV4L2Bufffers;

    _buffersAllocatedByDevice = rbuffer.count;

    //Map the buffers
    _pool = new Buffer[rbuffer.count];

    for (unsigned int i = 0; i < rbuffer.count; i++)
    {
        struct v4l2_buffer buffer;
        memset(&buffer, 0, sizeof(v4l2_buffer));
        buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buffer.memory = V4L2_MEMORY_MMAP;
        buffer.index = i;

        if (ioctl(_deviceFd, VIDIOC_QUERYBUF, &buffer) < 0)
        {
            return false;
        }

        _pool[i].start = mmap(NULL, buffer.length, PROT_READ | PROT_WRITE, MAP_SHARED,
                              _deviceFd, buffer.m.offset);

        if (MAP_FAILED == _pool[i].start)
        {
            for (unsigned int j = 0; j < i; j++)
                munmap(_pool[j].start, _pool[j].length);
            return false;
        }

        _pool[i].length = buffer.length;

        if (ioctl(_deviceFd, VIDIOC_QBUF, &buffer) < 0)
        {
            return false;
        }
    }
    return true;
}

bool VideoCaptureModuleV4L2::DeAllocateVideoBuffers()
{
    // unmap buffers
    for (int i = 0; i < _buffersAllocatedByDevice; i++)
        munmap(_pool[i].start, _pool[i].length);

    delete[] _pool;

    // turn off stream
    enum v4l2_buf_type type;
    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    if (ioctl(_deviceFd, VIDIOC_STREAMOFF, &type) < 0)
    {
        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
                   "VIDIOC_STREAMOFF error. errno: %d", errno);
    }

    return true;
}

bool VideoCaptureModuleV4L2::CaptureStarted()
{
    return _captureStarted;
}

bool VideoCaptureModuleV4L2::CaptureThread(void* obj)
{
    return static_cast<VideoCaptureModuleV4L2*> (obj)->CaptureProcess();
}
bool VideoCaptureModuleV4L2::CaptureProcess()
{
    int retVal = 0;
    fd_set rSet;
    struct timeval timeout;

    _captureCritSect->Enter();

    FD_ZERO(&rSet);
    FD_SET(_deviceFd, &rSet);
    timeout.tv_sec = 1;
    timeout.tv_usec = 0;

    retVal = select(_deviceFd + 1, &rSet, NULL, NULL, &timeout);
    if (retVal < 0 && errno != EINTR) // continue if interrupted
    {
        // select failed
        _captureCritSect->Leave();
        return false;
    }
    else if (retVal == 0)
    {
        // select timed out
        _captureCritSect->Leave();
        return true;
    }
    else if (!FD_ISSET(_deviceFd, &rSet))
    {
        // not event on camera handle
        _captureCritSect->Leave();
        return true;
    }

    if (_captureStarted)
    {
        struct v4l2_buffer buf;
        memset(&buf, 0, sizeof(struct v4l2_buffer));
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory = V4L2_MEMORY_MMAP;
        // dequeue a buffer - repeat until dequeued properly!
        while (ioctl(_deviceFd, VIDIOC_DQBUF, &buf) < 0)
        {
            if (errno != EINTR)
            {
                WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
                           "could not sync on a buffer on device %s", strerror(errno));
                _captureCritSect->Leave();
                return true;
            }
        }
        VideoCaptureCapability frameInfo;
        frameInfo.width = _currentWidth;
        frameInfo.height = _currentHeight;
        frameInfo.rawType = _captureVideoType;

        // convert to to I420 if needed
        IncomingFrame((unsigned char*) _pool[buf.index].start,
                      buf.bytesused, frameInfo);
        // enqueue the buffer again
        if (ioctl(_deviceFd, VIDIOC_QBUF, &buf) == -1)
        {
            WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCapture, _id,
                       "Failed to enqueue capture buffer");
        }
    }
    _captureCritSect->Leave();
    usleep(0);
    return true;
}

int32_t VideoCaptureModuleV4L2::CaptureSettings(VideoCaptureCapability& settings)
{
    settings.width = _currentWidth;
    settings.height = _currentHeight;
    settings.maxFPS = _currentFrameRate;
    settings.rawType=_captureVideoType;

    return 0;
}
}  // namespace videocapturemodule
}  // namespace webrtc
