[Tizen][MM][Webrtc] Video Capture Port using CAPI
authormsu.koo <msu.koo@samsung.com>
Wed, 12 Nov 2014 10:06:02 +0000 (15:36 +0530)
committerYoungsoo Choi <kenshin.choi@samsung.com>
Tue, 10 Jul 2018 06:57:09 +0000 (06:57 +0000)
This commit is to enable the video capture port on Tizen.

- Implemented VideoCaptureDeviceFactoryTizen.
- Implemented VideoCaptureDeviceTizen using Tizen CAPI.

Together with:I9c48580455d73821b11ae0b358b43544d24bdf1e

Bug: http://107.108.218.239/bugzilla/show_bug.cgi?id=7942
Reviewed by: Laszlo Gombos, Min-Soo Koo, Viatcheslav Ostapenko

Change-Id: I6883a136e2ab253c31f0a0051bf108bfe598da8e
Signed-off-by: msu.koo <msu.koo@samsung.com>
tizen_src/impl/chromium-efl-mm.gypi
tizen_src/impl/chromium-efl.gypi
tizen_src/impl/media/video/capture/tizen/video_capture_device_factory_tizen.cc [new file with mode: 0644]
tizen_src/impl/media/video/capture/tizen/video_capture_device_factory_tizen.h [new file with mode: 0644]
tizen_src/impl/media/video/capture/tizen/video_capture_device_factory_tizen_helper.cc [new file with mode: 0644]
tizen_src/impl/media/video/capture/tizen/video_capture_device_tizen.cc [new file with mode: 0644]
tizen_src/impl/media/video/capture/tizen/video_capture_device_tizen.h [new file with mode: 0644]

index 33cca935728e1b7d381a797f5d0456269231637c..ae70b5236ebdcfa55fb343935b1827b6fcbdf500 100644 (file)
@@ -5,5 +5,22 @@
     'content/browser/media/tizen/webaudio_decoder_browser_gstreamer.h',
     'content/renderer/media/tizen/audio_decoder_gstreamer.cc',
     'content/renderer/media/tizen/audio_decoder_gstreamer.h',
+    'media/video/capture/tizen/video_capture_device_factory_tizen_helper.cc',
+  ],
+  'conditions': [
+    ['building_for_tizen==1', {
+      'defines': [
+       'TIZEN_VIDEO_CAPTURE_SUPPORT=1',
+      ],
+      'sources': [
+        'media/video/capture/tizen/video_capture_device_tizen.h',
+        'media/video/capture/tizen/video_capture_device_tizen.cc',
+        'media/video/capture/tizen/video_capture_device_factory_tizen.h',
+        'media/video/capture/tizen/video_capture_device_factory_tizen.cc',
+      ],
+      'dependencies': [
+        '<(chrome_src_dir)/third_party/libyuv/libyuv.gyp:libyuv',
+      ],
+    }],
   ],
 }
index 92356126fe3ba7fc78cd7ddd54d346c3e7ef3d01..704b142936a2ed940e007d6e7bf3d2a9167d84a6 100644 (file)
@@ -63,7 +63,7 @@
                                      # omxSP_FFTInv_CCSToR_F32_vfp in src/third_party/openmax_dl/dl/sp/api/omxSP.h:2558 .
                                      # Remove this line after a more proper solution is found.
          ],
-        'conditions': [
+         'conditions': [
            ['chromium_efl_tizen_version=="2.3"', {
              'defines': [
                'TIZEN_V_2_3=1',
                'TIZEN_LEGACY_V_2_2_1=1',
              ],
            }],
+           ['tizen_multimedia_support==1', {
+             'sources/': [
+               ['exclude', 'video/capture/linux/video_capture_device_factory_linux.cc$'],
+               ['exclude', 'video/capture/linux/video_capture_device_factory_linux.h$'],
+               ['exclude', 'video/capture/linux/video_capture_device_linux.h$'],
+               ['exclude', 'video/capture/linux/video_capture_device_linux.cc$'],
+             ],
+           }],
          ],
          'sources/': [
            ['exclude', 'browser/device_sensors/data_fetcher_shared_memory_default.cc$'],
diff --git a/tizen_src/impl/media/video/capture/tizen/video_capture_device_factory_tizen.cc b/tizen_src/impl/media/video/capture/tizen/video_capture_device_factory_tizen.cc
new file mode 100644 (file)
index 0000000..7514c18
--- /dev/null
@@ -0,0 +1,224 @@
+// Copyright 2014 The Samsung Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/video/capture/tizen/video_capture_device_factory_tizen.h"
+
+namespace {
+
+media::VideoPixelFormat toChromiumType(camera_pixel_format_e e) {
+  switch (e) {
+    case CAMERA_PIXEL_FORMAT_NV12:
+      return media::PIXEL_FORMAT_NV12;
+    case CAMERA_PIXEL_FORMAT_NV21:
+      return media::PIXEL_FORMAT_NV21;
+    case CAMERA_PIXEL_FORMAT_YUYV:
+      return media::PIXEL_FORMAT_YUY2;
+    case CAMERA_PIXEL_FORMAT_RGB888:
+      return media::PIXEL_FORMAT_RGB24;
+    case CAMERA_PIXEL_FORMAT_UYVY:
+      return media::PIXEL_FORMAT_UYVY;
+    case CAMERA_PIXEL_FORMAT_ARGB:
+      return media::PIXEL_FORMAT_ARGB;
+    case CAMERA_PIXEL_FORMAT_I420:
+      return media::PIXEL_FORMAT_I420;
+    case CAMERA_PIXEL_FORMAT_YV12:
+      return media::PIXEL_FORMAT_YV12;
+    case CAMERA_PIXEL_FORMAT_JPEG:
+      return media::PIXEL_FORMAT_MJPEG;
+    default:
+      NOTREACHED();
+  }
+  return media::PIXEL_FORMAT_UNKNOWN;
+}
+
+bool OnCameraSupportedPreviewResolution(
+   int width, int height, void* user_data) {
+  std::vector<gfx::Size>* sizes =
+      static_cast< std::vector<gfx::Size>* >(user_data);
+  DCHECK(sizes);
+  sizes->push_back(gfx::Size(width, height));
+
+  return true;
+}
+
+bool OnCameraSupportedPreviewFormat(
+    camera_pixel_format_e format, void* user_data) {
+  std::vector<media::VideoPixelFormat>* list_format =
+      static_cast< std::vector<media::VideoPixelFormat>* >(user_data);
+  DCHECK(list_format);
+
+  list_format->push_back(toChromiumType(format));
+
+  return true;
+}
+
+bool OnCameraSupportedFPS(camera_attr_fps_e fps, void* user_data) {
+  std::vector<int>* list_fps = static_cast< std::vector<int>* >(user_data);
+  DCHECK(list_fps);
+  if (CAMERA_ATTR_FPS_AUTO != fps) {
+    // AUTO format is not defined on Chromium, so skip.
+    list_fps->push_back(static_cast<int>(fps));
+  }
+
+  return true;
+}
+
+void GenerateChromiumVideoCaptureFormat(
+    const std::vector<gfx::Size>& frame_sizes,
+    const std::vector<int>& fps,
+    const std::vector<media::VideoPixelFormat>& formats,
+    std::vector<media::VideoCaptureFormat>& outSupportedFormats) {
+  for (auto itrS = frame_sizes.begin(); itrS != frame_sizes.end(); itrS++) {
+    for (auto itrFPS = fps.begin(); itrFPS != fps.end(); itrFPS++) {
+      for (auto itrFMT = formats.begin(); itrFMT != formats.end(); itrFMT++) {
+        media::VideoCaptureFormat format;
+        format.frame_size = *itrS;
+        format.frame_rate = *itrFPS;
+        format.pixel_format = *itrFMT;
+        outSupportedFormats.push_back(format);
+      }
+    }
+  }
+}
+
+class CameraHandle final {
+ public:
+  explicit CameraHandle(const media::VideoCaptureDevice::Name& dev)
+      : camera_handle_(NULL) {
+    if (!dev.id().empty())
+      if (CAMERA_ERROR_NONE != camera_create(
+            media::VideoCaptureDeviceTizen::DeviceNameToCameraId(dev),
+            &camera_handle_)) {
+        camera_handle_ = NULL;
+        LOG(ERROR) << "Cannot create camera";
+      }
+  }
+
+  CameraHandle()
+      : camera_handle_(NULL) {
+    if (CAMERA_ERROR_NONE  != camera_create(CAMERA_DEVICE_CAMERA0, &camera_handle_)) {
+      camera_handle_ = NULL;
+      LOG(ERROR) << "Cannot create camera";
+    }
+  }
+
+  ~CameraHandle() {
+    if (camera_handle_ != NULL)
+      camera_destroy(camera_handle_);
+  }
+
+  bool IsValid() const {
+    return camera_handle_ != NULL;
+  }
+
+  void GetDeviceSupportedFormats(
+      media::VideoCaptureFormats& supported_formats) const {
+    std::vector<gfx::Size> supported_frame_sizes;
+    std::vector<int> supported_frame_rates;
+    std::vector<media::VideoPixelFormat> supported_pixel_formats;
+
+    if (!IsValid()) {
+      LOG(ERROR) << "Cannot use camera";
+      return;
+    }
+
+    if (CAMERA_ERROR_NONE != camera_foreach_supported_preview_resolution(
+          camera_handle_,
+          OnCameraSupportedPreviewResolution,
+          &supported_frame_sizes)) {
+      LOG(ERROR) << "Cannot get the supported resolutions for camera";
+      return;
+    }
+
+    if (CAMERA_ERROR_NONE != camera_foreach_supported_preview_format(
+          camera_handle_,
+          OnCameraSupportedPreviewFormat,
+          &supported_pixel_formats)) {
+      LOG(ERROR) << "Cannot get the supported formats for camera";
+      return;
+    }
+
+    if (CAMERA_ERROR_NONE != camera_attr_foreach_supported_fps(
+          camera_handle_,
+          OnCameraSupportedFPS,
+          &supported_frame_rates)) {
+      LOG(ERROR) << "Cannot get the supported FPS for camera";
+      return;
+    }
+    supported_formats.clear();
+    GenerateChromiumVideoCaptureFormat(supported_frame_sizes,
+                                       supported_frame_rates,
+                                       supported_pixel_formats,
+                                       supported_formats);
+  }
+
+  int GetDeviceCounts() const {
+    int device_count = 0;
+    if (CAMERA_ERROR_NONE !=
+           camera_get_device_count(camera_handle_, &device_count)) {
+      device_count = 0;
+      LOG(ERROR) << "Cannot read camera count";
+    }
+
+    return device_count;
+  }
+
+ private:
+  camera_h camera_handle_;
+};
+
+} // namespace
+
+namespace media {
+
+VideoCaptureDeviceFactoryTizen::VideoCaptureDeviceFactoryTizen(
+    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
+    : ui_task_runner_(ui_task_runner) {
+}
+
+VideoCaptureDeviceFactoryTizen::~VideoCaptureDeviceFactoryTizen() {
+}
+
+scoped_ptr<VideoCaptureDevice> VideoCaptureDeviceFactoryTizen::Create(
+    const VideoCaptureDevice::Name& name) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+
+  return scoped_ptr<VideoCaptureDevice>(new VideoCaptureDeviceTizen(name));
+}
+
+void VideoCaptureDeviceFactoryTizen::GetDeviceNames(
+    VideoCaptureDevice::Names* const device_names) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(device_names->empty());
+  VideoCaptureDevice::Name primary_camera("Primary camera", "0");
+  CameraHandle camera_handle;
+
+  if (!camera_handle.IsValid()) {
+    LOG(ERROR) << "Cannot use camera";
+    return;
+  }
+
+  int device_count = camera_handle.GetDeviceCounts();
+  if (device_count == 0) {
+    LOG(ERROR) << "No camera on this device.";
+    return;
+  }
+
+  device_names->push_back(primary_camera);
+  if (device_count == 2) {
+    VideoCaptureDevice::Name secondary_camera("Secondary camera", "1");
+    device_names->push_back(secondary_camera);
+  }
+}
+
+void VideoCaptureDeviceFactoryTizen::GetDeviceSupportedFormats(
+    const VideoCaptureDevice::Name& device,
+    VideoCaptureFormats* supported_formats) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(supported_formats != NULL);
+  CameraHandle camera_handle;
+  camera_handle.GetDeviceSupportedFormats(*supported_formats);
+}
+
+}  // namespace media
diff --git a/tizen_src/impl/media/video/capture/tizen/video_capture_device_factory_tizen.h b/tizen_src/impl/media/video/capture/tizen/video_capture_device_factory_tizen.h
new file mode 100644 (file)
index 0000000..7dd3da4
--- /dev/null
@@ -0,0 +1,45 @@
+// Copyright 2014 The Samsung Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Implementation of a VideoCaptureDeviceFactoryTizen class.
+
+#ifndef MEDIA_VIDEO_CAPTURE_TIZEN_VIDEO_CAPTURE_DEVICE_FACTORY_TIZEN_H_
+#define MEDIA_VIDEO_CAPTURE_TIZEN_VIDEO_CAPTURE_DEVICE_FACTORY_TIZEN_H_
+
+
+
+#include <camera.h>
+
+#include "media/video/capture/video_capture_device_factory.h"
+#include "media/video/capture/video_capture_device.h"
+#include "media/video/capture/video_capture_types.h"
+#include "media/video/capture/tizen/video_capture_device_tizen.h"
+
+namespace media {
+
+// Extension of VideoCaptureDeviceFactory to create and manipulate Tizen
+// devices.
+class MEDIA_EXPORT VideoCaptureDeviceFactoryTizen
+    : public VideoCaptureDeviceFactory {
+ public:
+  explicit VideoCaptureDeviceFactoryTizen(
+      scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner);
+  ~VideoCaptureDeviceFactoryTizen() override;
+
+  scoped_ptr<VideoCaptureDevice> Create(
+      const VideoCaptureDevice::Name& device_name) override;
+  void GetDeviceNames(VideoCaptureDevice::Names* device_names) override;
+  void GetDeviceSupportedFormats(
+      const VideoCaptureDevice::Name& device,
+      VideoCaptureFormats* supported_formats) override;
+
+ private:
+  scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
+
+  DISALLOW_COPY_AND_ASSIGN(VideoCaptureDeviceFactoryTizen);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_VIDEO_CAPTURE_TIZEN_VIDEO_CAPTURE_DEVICE_FACTORY_TIZEN_H_
diff --git a/tizen_src/impl/media/video/capture/tizen/video_capture_device_factory_tizen_helper.cc b/tizen_src/impl/media/video/capture/tizen/video_capture_device_factory_tizen_helper.cc
new file mode 100644 (file)
index 0000000..0054bed
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2014 The Samsung Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#if defined(TIZEN_VIDEO_CAPTURE_SUPPORT)
+#include "media/video/capture/tizen/video_capture_device_factory_tizen.h"
+#else
+#include "media/video/capture/linux/video_capture_device_factory_linux.h"
+#endif
+
+namespace media {
+
+scoped_ptr<VideoCaptureDeviceFactory> CreateVideoCaptureDeviceFactoryTizen(
+    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) {
+#if defined(TIZEN_VIDEO_CAPTURE_SUPPORT)
+  return scoped_ptr<VideoCaptureDeviceFactory>(
+      new VideoCaptureDeviceFactoryTizen(ui_task_runner));
+#else
+  return scoped_ptr<VideoCaptureDeviceFactory>(
+      new VideoCaptureDeviceFactoryLinux(ui_task_runner));
+#endif
+}
+
+}  // namespace media
diff --git a/tizen_src/impl/media/video/capture/tizen/video_capture_device_tizen.cc b/tizen_src/impl/media/video/capture/tizen/video_capture_device_tizen.cc
new file mode 100644 (file)
index 0000000..74cc96d
--- /dev/null
@@ -0,0 +1,312 @@
+// Copyright (c) 2012 The Samsung Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/video/capture/tizen/video_capture_device_tizen.h"
+
+#include <errno.h>
+#include <string>
+#include <sstream>
+
+#include "eweb_view.h"
+
+#include "base/bind.h"
+#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "media/video/capture/tizen/video_capture_device_factory_tizen.h"
+#include "media/base/yuv_convert.h"
+#include "third_party/libyuv/include/libyuv.h"
+
+#if defined(WEBRTC_DEBUG_METRIC)
+#include "base/time/time.h"
+static base::Time debug_last_newbuf_captured;
+static unsigned int debug_total_frames_captured = 0;
+#endif
+
+namespace {
+
+enum { kMjpegWidth = 640 };
+enum { kMjpegHeight = 480 };
+enum { kTypicalFramerate = 30 };
+enum { kTypicalFormat = CAMERA_PIXEL_FORMAT_NV12 };
+
+camera_pixel_format_e toCapiType(media::VideoPixelFormat e) {
+  switch (e) {
+    case media::PIXEL_FORMAT_NV12:
+      return CAMERA_PIXEL_FORMAT_NV12;
+    case media::PIXEL_FORMAT_NV21:
+      return CAMERA_PIXEL_FORMAT_NV21;
+    case media::PIXEL_FORMAT_YUY2:
+      return CAMERA_PIXEL_FORMAT_YUYV;
+    case media::PIXEL_FORMAT_RGB24:
+      return CAMERA_PIXEL_FORMAT_RGB888;
+    case media::PIXEL_FORMAT_UYVY:
+      return CAMERA_PIXEL_FORMAT_UYVY;
+    case media::PIXEL_FORMAT_ARGB:
+      return CAMERA_PIXEL_FORMAT_ARGB;
+    case media::PIXEL_FORMAT_I420:
+      return CAMERA_PIXEL_FORMAT_I420;
+    case media::PIXEL_FORMAT_YV12:
+      return CAMERA_PIXEL_FORMAT_YV12;
+    case media::PIXEL_FORMAT_MJPEG:
+      return CAMERA_PIXEL_FORMAT_JPEG;
+    default:
+      NOTREACHED();
+  }
+  return CAMERA_PIXEL_FORMAT_INVALID;
+}
+
+} // unnamed namespace
+
+namespace media {
+
+const std::string VideoCaptureDevice::Name::GetModel() const {
+  return "tizen camera";
+}
+
+VideoCaptureDeviceTizen::VideoCaptureDeviceTizen(const Name& device_name)
+    : state_(kIdle),
+      device_name_(device_name),
+      worker_("VideoCapture"),
+      buffer_(),
+      camera_(NULL) {
+#if defined(WEBRTC_DEBUG_METRIC)
+  debug_total_frames_captured = 0;
+  debug_last_newbuf_captured = base::Time();
+#endif
+}
+
+VideoCaptureDeviceTizen::~VideoCaptureDeviceTizen() {
+  state_ = kIdle;
+  DCHECK(!worker_.IsRunning());
+}
+
+void VideoCaptureDeviceTizen::AllocateAndStart(
+    const VideoCaptureParams& params,
+    scoped_ptr<VideoCaptureDevice::Client> client) {
+  DCHECK(!worker_.IsRunning());
+  worker_.Start();
+  worker_.message_loop()->PostTask(
+      FROM_HERE,
+      base::Bind(&VideoCaptureDeviceTizen::OnAllocateAndStart,
+                 base::Unretained(this),
+                 params.requested_format.frame_size.width(),
+                 params.requested_format.frame_size.height(),
+                 params.requested_format.frame_rate,
+                 params.requested_format.pixel_format,
+                 base::Passed(&client)));
+}
+
+void VideoCaptureDeviceTizen::StopAndDeAllocate() {
+  DCHECK(worker_.IsRunning());
+  worker_.message_loop()->PostTask(
+      FROM_HERE,
+      base::Bind(&VideoCaptureDeviceTizen::OnStopAndDeAllocate,
+                 base::Unretained(this)));
+  worker_.Stop();
+  DeAllocateVideoBuffers();
+}
+
+camera_device_e VideoCaptureDeviceTizen::DeviceNameToCameraId(
+    const VideoCaptureDevice::Name& device_name) {
+  if ("0" == device_name.id()) {
+    return CAMERA_DEVICE_CAMERA0;
+  } else if ("1" == device_name.id()) {
+    return CAMERA_DEVICE_CAMERA1;
+  } else {
+    NOTREACHED();
+  }
+  return static_cast<camera_device_e>(-1);
+}
+
+void VideoCaptureDeviceTizen::OnCameraCaptured(camera_preview_data_s* frame,
+                                               void* data) {
+  if ( frame->format != CAMERA_PIXEL_FORMAT_NV12 ) {
+    NOTIMPLEMENTED();
+    return;
+  }
+
+  VideoCaptureDeviceTizen* self = static_cast<VideoCaptureDeviceTizen*>(data);
+  camera_attr_fps_e current_fps =
+      static_cast<camera_attr_fps_e>(kTypicalFramerate);
+  camera_attr_get_preview_fps(self->camera_, &current_fps);
+
+  int destination_width = frame->width;
+  int destination_height = frame->height;
+
+  // FIXME : find a way to get Orientation here.
+  int orientation = 0;
+  libyuv::RotationMode rotation_mode = libyuv::kRotate0;
+#if defined(OS_TIZEN_MOBILE)
+  rotation_mode = libyuv::kRotate270;
+  switch (orientation) {
+    case 0:
+      rotation_mode = libyuv::kRotate270;
+      break;
+    case 90:
+    case -270:
+      rotation_mode = libyuv::kRotate180;
+      break;
+    case 180:
+      rotation_mode = libyuv::kRotate90;
+      break;
+    case 270:
+    case -90:
+      rotation_mode = libyuv::kRotate0;
+      break;
+    default:
+      LOG(ERROR) << " Invalid orientation from RenderViewHostImpl : " << orientation;
+  }
+
+  if (rotation_mode == libyuv::kRotate90 || rotation_mode == libyuv::kRotate270) {
+    destination_width = frame->height;
+    destination_height = frame->width;
+  }
+#endif
+
+  const gfx::Size dimensions(destination_width, destination_height);
+
+  uint8* yplane = reinterpret_cast<uint8*>(self->buffer_->data());
+  uint8* uplane = yplane + VideoFrame::PlaneAllocationSize(VideoFrame::I420,
+                                                           VideoFrame::kYPlane,
+                                                           dimensions);
+  uint8* vplane = uplane + VideoFrame::PlaneAllocationSize(VideoFrame::I420,
+                                                           VideoFrame::kUPlane,
+                                                           dimensions);
+  int yplane_stride = dimensions.width();
+  int uv_plane_stride = yplane_stride / 2;
+  int frame_size =
+      frame->data.double_plane.y_size + frame->data.double_plane.uv_size;
+
+  libyuv::ConvertToI420(frame->data.double_plane.y, frame_size,
+                        yplane, yplane_stride,
+                        uplane, uv_plane_stride,
+                        vplane, uv_plane_stride,
+                        0 /*crop_x*/, 0 /*crop_y*/,
+                        frame->width, frame->height,
+                        frame->width, frame->height,
+                        rotation_mode,
+                        libyuv::FOURCC_NV12);
+
+  VideoCaptureFormat capture_format_;
+  capture_format_.frame_size.SetSize(destination_width, destination_height);
+  capture_format_.frame_rate = current_fps;
+  capture_format_.pixel_format = PIXEL_FORMAT_I420;
+  self->client_->OnIncomingCapturedData(
+      reinterpret_cast<uint8*>(self->buffer_->data()),
+      frame_size,
+      capture_format_,
+      libyuv::kRotate0,
+      base::TimeTicks::Now());
+}
+
+void VideoCaptureDeviceTizen::OnAllocateAndStart(int width,
+                                                 int height,
+                                                 int frame_rate,
+                                                 VideoPixelFormat format,
+                                                 scoped_ptr<Client> client) {
+  DCHECK_EQ(worker_.message_loop(), base::MessageLoop::current());
+
+  client_ = client.Pass();
+  if (CAMERA_ERROR_NONE !=
+      camera_create(DeviceNameToCameraId(device_name_), &camera_)) {
+    LOG(ERROR) << "Fail to create camera";
+    SetErrorState("Fail to create camera");
+    return;
+  }
+
+  if (CAMERA_ERROR_NONE !=
+      camera_set_display(camera_, CAMERA_DISPLAY_TYPE_NONE, NULL)) {
+    LOG(ERROR) << "Fail to set using camera buffer";
+    SetErrorState("Camera internal Error");
+    return;
+  }
+
+  if (CAMERA_ERROR_NONE !=
+      camera_set_preview_resolution(camera_, width, height)) {
+    LOG(WARNING) << "Camera does not support "
+                 << width << " x " << height << " resolution.";
+    LOG(WARNING) << "trying default resolution: "
+                 << kMjpegWidth << " x " << kMjpegHeight;
+    if (CAMERA_ERROR_NONE !=
+        camera_set_preview_resolution(camera_, kMjpegWidth, kMjpegHeight)) {
+      SetErrorState("Camera internal Error");
+      return;
+    }
+  }
+
+  if (CAMERA_ERROR_NONE !=
+      camera_set_preview_format(camera_, toCapiType(format))) {
+    LOG(WARNING) << "Camera does not support file format :"
+                 << toCapiType(format);
+    LOG(WARNING) << "trying default format: " << kTypicalFormat;
+    if (CAMERA_ERROR_NONE != camera_set_preview_format(
+        camera_, (camera_pixel_format_e)kTypicalFormat)) {
+      SetErrorState("Camera internal Error");
+      return;
+    }
+  }
+
+  if (CAMERA_ERROR_NONE !=
+      camera_set_preview_cb(camera_, OnCameraCaptured, this)) {
+    SetErrorState("Camera internal Error");
+    return;
+  }
+
+  if (CAMERA_ERROR_NONE !=
+      camera_attr_set_preview_fps(camera_, (camera_attr_fps_e)frame_rate)) {
+    LOG(WARNING) << "Camera does not support frame rate:" <<  frame_rate;
+    LOG(WARNING) << "trying default frame rate: " << kTypicalFramerate;
+    if (CAMERA_ERROR_NONE !=
+        camera_attr_set_preview_fps(camera_,
+                                    (camera_attr_fps_e)kTypicalFramerate)) {
+      SetErrorState("Camera internal Error");
+      return;
+    }
+  }
+
+  if (!AllocateVideoBuffers(width, height)) {
+    LOG(ERROR) << "Allocate buffer failed";
+    SetErrorState("Camera internal Error");
+    return;
+  }
+
+  state_ = kCapturing;
+
+  if (CAMERA_ERROR_NONE != camera_start_preview(camera_)) {
+    LOG(ERROR) << "Fail to start camera";
+    SetErrorState("Camera internal Error");
+  }
+}
+
+void VideoCaptureDeviceTizen::OnStopAndDeAllocate() {
+  DCHECK_EQ(worker_.message_loop(), base::MessageLoop::current());
+
+  camera_stop_preview(camera_);
+  camera_destroy(camera_);
+  DeAllocateVideoBuffers();
+
+  state_ = kIdle;
+  client_.reset();
+}
+
+bool VideoCaptureDeviceTizen::AllocateVideoBuffers(int width, int height) {
+  buffer_ = client_->ReserveOutputBuffer(media::VideoFrame::I420,
+                                         gfx::Size(width,height) );
+  if ( buffer_.get() != NULL ) {
+    return true;
+  }
+  return false;
+}
+
+void VideoCaptureDeviceTizen::DeAllocateVideoBuffers() {
+  /* Nothing to do */
+}
+
+void VideoCaptureDeviceTizen::SetErrorState(const std::string& reason) {
+  DCHECK(!worker_.IsRunning() ||
+         worker_.message_loop() == base::MessageLoop::current());
+  state_ = kError;
+  client_->OnError(reason);
+}
+
+}  // namespace media
diff --git a/tizen_src/impl/media/video/capture/tizen/video_capture_device_tizen.h b/tizen_src/impl/media/video/capture/tizen/video_capture_device_tizen.h
new file mode 100644 (file)
index 0000000..94f5bda
--- /dev/null
@@ -0,0 +1,66 @@
+// Copyright (c) 2012 The Samsung Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Tizen specific implementation of VideoCaptureDevice.
+// Tizen Core API is used to capture the video frames from the device.
+
+#ifndef MEDIA_VIDEO_CAPTURE_TIZEN_VIDEO_CAPTURE_DEVICE_TIZEN_H_
+#define MEDIA_VIDEO_CAPTURE_TIZEN_VIDEO_CAPTURE_DEVICE_TIZEN_H_
+
+#include <camera.h>
+#include <string>
+
+#include "base/files/file_util.h"
+#include "base/threading/thread.h"
+#include "media/video/capture/video_capture_device.h"
+#include "media/video/capture/video_capture_types.h"
+
+namespace media {
+
+class VideoCaptureDeviceTizen : public VideoCaptureDevice {
+ public:
+  explicit VideoCaptureDeviceTizen(const Name& device_name);
+  virtual ~VideoCaptureDeviceTizen() override;
+
+  virtual void AllocateAndStart(const VideoCaptureParams& params,
+                                scoped_ptr<Client> client) override;
+
+  virtual void StopAndDeAllocate() override;
+
+  static camera_device_e DeviceNameToCameraId(
+    const VideoCaptureDevice::Name& device_name);
+
+ private:
+  enum InternalState {
+    kIdle,  // The device driver is opened but camera is not in use.
+    kCapturing,  // Video is being captured.
+    kError  // Error accessing HW functions.
+            // User needs to recover by destroying the object.
+  };
+
+  static void OnCameraCaptured(camera_preview_data_s* frame, void* data);
+  void OnAllocateAndStart(int width,
+                          int height,
+                          int frame_rate,
+                          VideoPixelFormat format,
+                          scoped_ptr<Client> client);
+  void OnStopAndDeAllocate();
+
+  bool AllocateVideoBuffers(int width, int height);
+  void DeAllocateVideoBuffers();
+  void SetErrorState(const std::string& reason);
+
+  InternalState state_;
+  scoped_ptr<VideoCaptureDevice::Client> client_;
+  Name device_name_;
+  base::Thread worker_;  // Thread used for reading data from the device.
+  scoped_refptr<VideoCaptureDevice::Client::Buffer> buffer_;
+  camera_h camera_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(VideoCaptureDeviceTizen);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_VIDEO_CAPTURE_TIZEN_VIDEO_CAPTURE_DEVICE_TIZEN_H_