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(
13 const media::VideoCaptureSessionId id
,
14 VideoCaptureImplManager
* vc_manager
,
16 : is_screencast_(is_screencast
),
17 delegate_(new RtcVideoCaptureDelegate(id
, vc_manager
)),
18 state_(VIDEO_CAPTURE_STATE_STOPPED
) {
19 base::Time::Exploded exploded
= {};
22 exploded
.day_of_week
= 0;
23 exploded
.day_of_month
= 1;
27 exploded
.millisecond
= 0;
28 DCHECK(exploded
.HasValidValues());
29 ntp_epoch_
= base::Time::FromUTCExploded(exploded
);
32 RtcVideoCapturer::~RtcVideoCapturer() {
33 DCHECK(VIDEO_CAPTURE_STATE_STOPPED
);
34 DVLOG(3) << " RtcVideoCapturer::dtor";
37 cricket::CaptureState
RtcVideoCapturer::Start(
38 const cricket::VideoFormat
& capture_format
) {
39 DVLOG(3) << " RtcVideoCapturer::Start ";
40 if (state_
== VIDEO_CAPTURE_STATE_STARTED
) {
41 DVLOG(1) << "Got a StartCapture when already started!!! ";
42 return cricket::CS_FAILED
;
45 media::VideoCaptureCapability cap
;
46 cap
.width
= capture_format
.width
;
47 cap
.height
= capture_format
.height
;
48 cap
.frame_rate
= capture_format
.framerate();
49 cap
.color
= media::VideoCaptureCapability::kI420
;
51 state_
= VIDEO_CAPTURE_STATE_STARTED
;
52 start_time_
= base::Time::Now();
53 delegate_
->StartCapture(cap
,
54 base::Bind(&RtcVideoCapturer::OnFrameCaptured
, base::Unretained(this)),
55 base::Bind(&RtcVideoCapturer::OnStateChange
, base::Unretained(this)));
56 // Update the desired aspect ratio so that later the video frame can be
57 // cropped to meet the requirement if the camera returns a different
58 // resolution than the |cap|.
59 UpdateAspectRatio(cap
.width
, cap
.height
);
60 return cricket::CS_STARTING
;
63 void RtcVideoCapturer::Stop() {
64 DVLOG(3) << " RtcVideoCapturer::Stop ";
65 if (state_
== VIDEO_CAPTURE_STATE_STOPPED
) {
66 DVLOG(1) << "Got a StopCapture while not started.";
69 state_
= VIDEO_CAPTURE_STATE_STOPPED
;
70 delegate_
->StopCapture();
71 SignalStateChange(this, cricket::CS_STOPPED
);
74 bool RtcVideoCapturer::IsRunning() {
75 return state_
== VIDEO_CAPTURE_STATE_STARTED
;
78 bool RtcVideoCapturer::GetPreferredFourccs(std::vector
<uint32
>* fourccs
) {
81 fourccs
->push_back(cricket::FOURCC_I420
);
85 bool RtcVideoCapturer::IsScreencast() const {
86 return is_screencast_
;
89 bool RtcVideoCapturer::GetBestCaptureFormat(const cricket::VideoFormat
& desired
,
90 cricket::VideoFormat
* best_format
) {
95 // Chrome does not support capability enumeration.
96 // Use the desired format as the best format.
97 best_format
->width
= desired
.width
;
98 best_format
->height
= desired
.height
;
99 best_format
->fourcc
= cricket::FOURCC_I420
;
100 best_format
->interval
= desired
.interval
;
104 void RtcVideoCapturer::OnFrameCaptured(
105 const media::VideoCapture::VideoFrameBuffer
& buf
) {
106 // Currently, |fourcc| is always I420.
107 cricket::CapturedFrame frame
;
108 frame
.width
= buf
.width
;
109 frame
.height
= buf
.height
;
110 frame
.fourcc
= cricket::FOURCC_I420
;
111 frame
.data_size
= buf
.buffer_size
;
112 // cricket::CapturedFrame time is in nanoseconds.
113 frame
.elapsed_time
= (buf
.timestamp
- start_time_
).InMicroseconds() *
114 base::Time::kNanosecondsPerMicrosecond
;
115 // Timestamp in NTP time (seconds since 0:00 UTC 1 January 1900) in ms.
116 frame
.time_stamp
= (buf
.timestamp
- ntp_epoch_
).InMilliseconds();
117 frame
.data
= buf
.memory_pointer
;
118 frame
.pixel_height
= 1;
119 frame
.pixel_width
= 1;
121 TRACE_EVENT_INSTANT2("rtc_video_capturer",
123 TRACE_EVENT_SCOPE_THREAD
,
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, &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