1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/renderer/media/rtc_video_capturer.h"
8 #include "base/debug/trace_event.h"
12 RtcVideoCapturer::RtcVideoCapturer(const media::VideoCaptureSessionId id,
13 VideoCaptureImplManager* vc_manager,
15 : is_screencast_(is_screencast),
16 delegate_(new RtcVideoCaptureDelegate(id, vc_manager)),
17 state_(VIDEO_CAPTURE_STATE_STOPPED) {}
19 RtcVideoCapturer::~RtcVideoCapturer() {
20 DCHECK(VIDEO_CAPTURE_STATE_STOPPED);
21 DVLOG(3) << " RtcVideoCapturer::dtor";
24 cricket::CaptureState RtcVideoCapturer::Start(
25 const cricket::VideoFormat& capture_format) {
26 DVLOG(3) << " RtcVideoCapturer::Start ";
27 if (state_ == VIDEO_CAPTURE_STATE_STARTED) {
28 DVLOG(1) << "Got a StartCapture when already started!!! ";
29 return cricket::CS_FAILED;
32 media::VideoCaptureParams request;
33 request.requested_format =
34 media::VideoCaptureFormat(capture_format.width,
35 capture_format.height,
36 capture_format.framerate(),
37 media::ConstantResolutionVideoCaptureDevice);
39 SetCaptureFormat(&capture_format);
41 state_ = VIDEO_CAPTURE_STATE_STARTED;
42 first_frame_timestamp_ = media::kNoTimestamp();
43 delegate_->StartCapture(
45 base::Bind(&RtcVideoCapturer::OnFrameCaptured, base::Unretained(this)),
46 base::Bind(&RtcVideoCapturer::OnStateChange, base::Unretained(this)));
47 // Update the desired aspect ratio so that later the video frame can be
48 // cropped to meet the requirement if the camera returns a different
49 // resolution than the |request|.
50 UpdateAspectRatio(capture_format.width, capture_format.height);
51 return cricket::CS_STARTING;
54 void RtcVideoCapturer::Stop() {
55 DVLOG(3) << " RtcVideoCapturer::Stop ";
56 if (state_ == VIDEO_CAPTURE_STATE_STOPPED) {
57 DVLOG(1) << "Got a StopCapture while not started.";
61 SetCaptureFormat(NULL);
62 state_ = VIDEO_CAPTURE_STATE_STOPPED;
63 delegate_->StopCapture();
64 SignalStateChange(this, cricket::CS_STOPPED);
67 bool RtcVideoCapturer::IsRunning() {
68 return state_ == VIDEO_CAPTURE_STATE_STARTED;
71 bool RtcVideoCapturer::GetPreferredFourccs(std::vector<uint32>* fourccs) {
74 fourccs->push_back(cricket::FOURCC_I420);
78 bool RtcVideoCapturer::IsScreencast() const {
79 return is_screencast_;
82 bool RtcVideoCapturer::GetBestCaptureFormat(const cricket::VideoFormat& desired,
83 cricket::VideoFormat* best_format) {
88 // Chrome does not support capability enumeration.
89 // Use the desired format as the best format.
90 best_format->width = desired.width;
91 best_format->height = desired.height;
92 best_format->fourcc = cricket::FOURCC_I420;
93 best_format->interval = desired.interval;
97 void RtcVideoCapturer::OnFrameCaptured(
98 const scoped_refptr<media::VideoFrame>& frame) {
99 if (first_frame_timestamp_ == media::kNoTimestamp())
100 first_frame_timestamp_ = frame->GetTimestamp();
102 // Currently, |fourcc| is always I420.
103 cricket::CapturedFrame captured_frame;
104 captured_frame.width = frame->coded_size().width();
105 captured_frame.height = frame->coded_size().height();
106 captured_frame.fourcc = cricket::FOURCC_I420;
107 // cricket::CapturedFrame time is in nanoseconds.
108 captured_frame.elapsed_time =
109 (frame->GetTimestamp() - first_frame_timestamp_).InMicroseconds() *
110 base::Time::kNanosecondsPerMicrosecond;
111 captured_frame.time_stamp = frame->GetTimestamp().InMicroseconds() *
112 base::Time::kNanosecondsPerMicrosecond;
113 // TODO(sheu): we assume contiguous layout of image planes.
114 captured_frame.data = frame->data(0);
115 captured_frame.data_size =
116 media::VideoFrame::AllocationSize(frame->format(), frame->coded_size());
117 captured_frame.pixel_height = 1;
118 captured_frame.pixel_width = 1;
120 TRACE_EVENT_INSTANT2(
121 "rtc_video_capturer",
123 TRACE_EVENT_SCOPE_THREAD,
125 captured_frame.elapsed_time,
127 captured_frame.time_stamp / talk_base::kNumNanosecsPerMillisec);
129 // This signals to libJingle that a new VideoFrame is available.
130 // libJingle have no assumptions on what thread this signal come from.
131 SignalFrameCaptured(this, &captured_frame);
134 void RtcVideoCapturer::OnStateChange(
135 RtcVideoCaptureDelegate::CaptureState state) {
136 cricket::CaptureState converted_state = cricket::CS_FAILED;
137 DVLOG(3) << " RtcVideoCapturer::OnStateChange " << state;
139 case RtcVideoCaptureDelegate::CAPTURE_STOPPED:
140 converted_state = cricket::CS_STOPPED;
142 case RtcVideoCaptureDelegate::CAPTURE_RUNNING:
143 converted_state = cricket::CS_RUNNING;
145 case RtcVideoCaptureDelegate::CAPTURE_FAILED:
146 // TODO(perkj): Update the comments in the the definition of
147 // cricket::CS_FAILED. According to the comments, cricket::CS_FAILED
148 // means that the capturer failed to start. But here and in libjingle it
149 // is also used if an error occur during capturing.
150 converted_state = cricket::CS_FAILED;
156 SignalStateChange(this, converted_state);
159 } // namespace content