Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / content / renderer / media / media_stream_video_source.cc
1 // Copyright 2014 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.
4
5 #include "content/renderer/media/media_stream_video_source.h"
6
7 #include "base/logging.h"
8 #include "content/renderer/media/media_stream_dependency_factory.h"
9 #include "content/renderer/media/rtc_media_constraints.h"
10 #include "media/base/video_frame.h"
11 #include "third_party/libjingle/source/talk/app/webrtc/remotevideocapturer.h"
12 #include "third_party/libjingle/source/talk/media/webrtc/webrtcvideoframe.h"
13
14 namespace content {
15
16 MediaStreamVideoSource::MediaStreamVideoSource(
17     MediaStreamDependencyFactory* factory)
18     : initializing_(false),
19       factory_(factory),
20       width_(0),
21       height_(0),
22       first_frame_timestamp_(media::kNoTimestamp()) {
23   DCHECK(factory_);
24 }
25
26 MediaStreamVideoSource::~MediaStreamVideoSource() {
27   if (initializing_) {
28     adapter_->UnregisterObserver(this);
29   }
30 }
31
32 void MediaStreamVideoSource::AddTrack(
33     const blink::WebMediaStreamTrack& track,
34     const blink::WebMediaConstraints& constraints,
35     const ConstraintsCallback& callback) {
36   if (!adapter_) {
37     // Create the webrtc::MediaStreamVideoSourceInterface adapter.
38     InitAdapter(constraints);
39     DCHECK(adapter_);
40
41     current_constraints_ = constraints;
42     initializing_ = true;
43     // Register to the adapter to get notified when it has been started
44     // successfully.
45     adapter_->RegisterObserver(this);
46   }
47
48   // TODO(perkj): Currently, reconfiguring the source is not supported. For now
49   // we ignore if |constraints| do not match the constraints that was used
50   // when the source was started
51
52   // There might be multiple tracks attaching to the source while it is being
53   // configured.
54   constraints_callbacks_.push_back(callback);
55   TriggerConstraintsCallbackOnStateChange();
56
57   // TODO(perkj): Use the MediaStreamDependencyFactory for now to create the
58   // MediaStreamVideoTrack since creation is currently still depending on
59   // libjingle. The webrtc video track implementation will attach to the
60   // webrtc::VideoSourceInterface returned by GetAdapter() to receive video
61   // frames.
62   factory_->CreateNativeMediaStreamTrack(track);
63 }
64
65 void MediaStreamVideoSource::RemoveTrack(
66     const blink::WebMediaStreamTrack& track) {
67   // TODO(ronghuawu): What should be done here? Do we really need RemoveTrack?
68 }
69
70 void MediaStreamVideoSource::InitAdapter(
71     const blink::WebMediaConstraints& constraints) {
72   DCHECK(!adapter_);
73   RTCMediaConstraints webrtc_constraints(constraints);
74   adapter_ = factory_->CreateVideoSource(new webrtc::RemoteVideoCapturer(),
75                                          &webrtc_constraints);
76 }
77
78 void MediaStreamVideoSource::SetReadyState(
79     blink::WebMediaStreamSource::ReadyState state) {
80   // TODO(ronghuawu): Sets WebMediaStreamSource's ready state and notifies the
81   // ready state to all registered tracks.
82 }
83
84 void MediaStreamVideoSource::DeliverVideoFrame(
85     const scoped_refptr<media::VideoFrame>& frame) {
86   if (first_frame_timestamp_ == media::kNoTimestamp()) {
87     first_frame_timestamp_ = frame->GetTimestamp();
88   }
89
90   cricket::VideoRenderer* input = adapter_->FrameInput();
91   if (width_ != frame->coded_size().width() ||
92       height_ != frame->coded_size().height()) {
93     width_ = frame->coded_size().width();
94     height_ = frame->coded_size().height();
95     const int reserved = 0;
96     input->SetSize(width_, height_, reserved);
97   }
98
99   cricket::WebRtcVideoFrame cricket_frame;
100   const int64 elapsed_time_ns =
101       (frame->GetTimestamp() - first_frame_timestamp_).InMicroseconds() *
102       base::Time::kNanosecondsPerMicrosecond;
103   const int64 time_stamp_ns = frame->GetTimestamp().InMicroseconds() *
104       base::Time::kNanosecondsPerMicrosecond;
105   const size_t size =
106       media::VideoFrame::AllocationSize(frame->format(), frame->coded_size());
107   const size_t pixel_width = 1;
108   const size_t pixel_height = 1;
109   const int rotation = 0;
110   cricket_frame.Alias(frame->data(0), size,
111                       width_, height_,
112                       pixel_width, pixel_height,
113                       elapsed_time_ns, time_stamp_ns,
114                       rotation);
115   input->RenderFrame(&cricket_frame);
116 }
117
118 void MediaStreamVideoSource::OnChanged() {
119   DCHECK(CalledOnValidThread());
120   TriggerConstraintsCallbackOnStateChange();
121 }
122
123 void MediaStreamVideoSource::TriggerConstraintsCallbackOnStateChange() {
124   if (adapter_->state() == webrtc::MediaSourceInterface::kInitializing)
125     return;
126
127   if (initializing_) {
128     adapter_->UnregisterObserver(this);
129     initializing_ = false;
130   }
131
132   std::vector<ConstraintsCallback> callbacks;
133   callbacks.swap(constraints_callbacks_);
134
135   bool success = (adapter_->state() == webrtc::MediaSourceInterface::kLive);
136   for (std::vector<ConstraintsCallback>::iterator it = callbacks.begin();
137        it != callbacks.end(); ++it) {
138     if (!it->is_null())
139       it->Run(this, success);
140   }
141 }
142
143 }  // namespace content