Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(169)

Side by Side Diff: extensions/renderer/api/display_source/wifi_display/wifi_display_media_manager.cc

Issue 1860083002: [chrome.displaySource][WiFi Display] Media pipeline infrastructure (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed session Id generation Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "extensions/renderer/api/display_source/wifi_display/wifi_display_media _manager.h" 5 #include "extensions/renderer/api/display_source/wifi_display/wifi_display_media _manager.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/rand_util.h" 8 #include "base/rand_util.h"
9 #include "base/task_runner_util.h"
9 #include "content/public/renderer/media_stream_utils.h" 10 #include "content/public/renderer/media_stream_utils.h"
11 #include "content/public/renderer/media_stream_video_sink.h"
12 #include "content/public/renderer/render_thread.h"
13 #include "content/public/renderer/video_encode_accelerator.h"
14 #include "extensions/common/mojo/wifi_display_session_service.mojom.h"
15 #include "extensions/renderer/api/display_source/wifi_display/wifi_display_eleme ntary_stream_info.h"
16 #include "extensions/renderer/api/display_source/wifi_display/wifi_display_media _pipeline.h"
17 #include "media/base/bind_to_current_loop.h"
10 18
11 namespace extensions { 19 namespace extensions {
12 20
13 namespace { 21 namespace {
14 22
15 const char kErrorNoVideoFormatData[] = 23 const char kErrorNoVideoFormatData[] =
16 "Failed to get video format data from the given MediaStreamTrack object"; 24 "Failed to get video format data from the given MediaStreamTrack object";
17 const char kErrorSinkCannotPlayVideo[] = 25 const char kErrorSinkCannotPlayVideo[] =
18 "The sink cannot play video from the given MediaStreamTrack object"; 26 "The sink cannot play video from the given MediaStreamTrack object";
19 const char kErrorSinkCannotPlayAudio[] = 27 const char kErrorSinkCannotPlayAudio[] =
20 "The sink cannot play audio from the given MediaStreamTrack object"; 28 "The sink cannot play audio from the given MediaStreamTrack object";
29 const char kErrorMediaPipelineFailure[] =
30 "Failed to initialize media pipeline for the session";
21 } // namespace 31 } // namespace
22 32
33 class WiFiDisplayVideoSink : public content::MediaStreamVideoSink {
34 public:
35 WiFiDisplayVideoSink(
36 const blink::WebMediaStreamTrack& track,
37 const content::VideoCaptureDeliverFrameCB& callback)
38 : track_(track),
39 sink_added_(false),
40 callback_(callback) {
41 }
42
43 ~WiFiDisplayVideoSink() override {
44 Stop();
45 }
46
47 void Start() {
48 DCHECK(!sink_added_);
49 sink_added_ = true;
50 // Callback is invoked on IO thread.
51 AddToVideoTrack(this, callback_, track_);
52 }
53
54 void Stop() {
55 if (sink_added_)
56 RemoveFromVideoTrack(this, track_);
57 }
58
59 private:
60 blink::WebMediaStreamTrack track_;
61 bool sink_added_;
62 content::VideoCaptureDeliverFrameCB callback_;
63 DISALLOW_COPY_AND_ASSIGN(WiFiDisplayVideoSink);
64 };
65
23 WiFiDisplayMediaManager::WiFiDisplayMediaManager( 66 WiFiDisplayMediaManager::WiFiDisplayMediaManager(
24 const blink::WebMediaStreamTrack& video_track, 67 const blink::WebMediaStreamTrack& video_track,
25 const blink::WebMediaStreamTrack& audio_track, 68 const blink::WebMediaStreamTrack& audio_track,
26 const ErrorCallback& error_callback) 69 const ErrorCallback& error_callback)
27 : video_track_(video_track), 70 : video_track_(video_track),
28 audio_track_(audio_track), 71 audio_track_(audio_track),
29 error_callback_(error_callback) { 72 player_(nullptr),
73 io_task_runner_(content::RenderThread::Get()->GetIOMessageLoopProxy()),
74 error_callback_(error_callback),
75 is_playing_(false),
76 is_initialized_(false),
77 weak_factory_(this) {
30 DCHECK(!video_track.isNull() || !audio_track.isNull()); 78 DCHECK(!video_track.isNull() || !audio_track.isNull());
31 DCHECK(!error_callback_.is_null()); 79 DCHECK(!error_callback_.is_null());
32 } 80 }
33 81
34 WiFiDisplayMediaManager::~WiFiDisplayMediaManager() { 82 WiFiDisplayMediaManager::~WiFiDisplayMediaManager() {
83 Teardown();
35 } 84 }
36 85
37 void WiFiDisplayMediaManager::Play() { 86 void WiFiDisplayMediaManager::Play() {
38 NOTIMPLEMENTED(); 87 is_playing_ = true;
88 if (!player_) {
89 base::PostTaskAndReplyWithResult(io_task_runner_.get(), FROM_HERE,
90 base::Bind(
91 &WiFiDisplayMediaPipeline::Create,
92 GetSessionType(),
93 video_encoder_parameters_,
94 optimal_audio_codec_,
95 media::BindToCurrentLoop(error_callback_)),
96 base::Bind(&WiFiDisplayMediaManager::OnPlayerCreated,
97 weak_factory_.GetWeakPtr()));
98 return;
99 }
100
101 if (!is_initialized_) {
102 return; // Waiting for initialization being completed.
103 }
104
105 if (!video_track_.isNull()) {
106 // To be called on IO thread.
107 auto on_raw_video_frame = base::Bind(
108 &WiFiDisplayMediaPipeline::InsertRawVideoFrame,
109 base::Unretained(player_));
110 video_sink_.reset(
111 new WiFiDisplayVideoSink(video_track_, on_raw_video_frame));
112 video_sink_->Start();
113 LOG(ERROR) << "video sink started";
114 }
39 } 115 }
40 116
41 void WiFiDisplayMediaManager::Teardown() { 117 void WiFiDisplayMediaManager::Teardown() {
42 NOTIMPLEMENTED(); 118 Pause();
119 if (player_) {
120 io_task_runner_->DeleteSoon(FROM_HERE, player_);
121 player_ = nullptr;
122 }
123 is_initialized_ = false;
124 session_id_.clear();
43 } 125 }
44 126
45 void WiFiDisplayMediaManager::Pause() { 127 void WiFiDisplayMediaManager::Pause() {
46 NOTIMPLEMENTED(); 128 is_playing_ = false;
129 video_sink_.reset();
47 } 130 }
48 131
49 bool WiFiDisplayMediaManager::IsPaused() const { 132 bool WiFiDisplayMediaManager::IsPaused() const {
50 NOTIMPLEMENTED(); 133 return !is_playing_;
51 return true;
52 } 134 }
53 135
54 wds::SessionType WiFiDisplayMediaManager::GetSessionType() const { 136 wds::SessionType WiFiDisplayMediaManager::GetSessionType() const {
55 uint16_t session_type = 0; 137 uint16_t session_type = 0;
56 if (!video_track_.isNull()) 138 if (!video_track_.isNull())
57 session_type |= wds::VideoSession; 139 session_type |= wds::VideoSession;
58 140
59 if (!audio_track_.isNull()) 141 if (!audio_track_.isNull())
60 session_type |= wds::AudioSession; 142 session_type |= wds::AudioSession;
61 143
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 } 268 }
187 return false; 269 return false;
188 } 270 }
189 271
190 } // namespace 272 } // namespace
191 273
192 wds::H264VideoFormat WiFiDisplayMediaManager::GetOptimalVideoFormat() const { 274 wds::H264VideoFormat WiFiDisplayMediaManager::GetOptimalVideoFormat() const {
193 return optimal_video_format_; 275 return optimal_video_format_;
194 } 276 }
195 277
196 void WiFiDisplayMediaManager::SendIDRPicture() { 278 namespace {
197 NOTIMPLEMENTED(); 279
280 int GetBitRate(const gfx::Size& frame_size) {
281 DCHECK_GE(frame_size.height(), 360);
282 if (frame_size.height() < 720)
283 return 2500000;
284 if (frame_size.height() < 1080)
285 return 5000000;
286 return 8000000;
198 } 287 }
199 288
200 std::string WiFiDisplayMediaManager::GetSessionId() const { 289 void CreateVideoEncodeMemory(
201 return base::RandBytesAsString(8); 290 size_t size,
291 const WiFiDisplayVideoEncoder::ReceiveEncodeMemoryCallback& callback) {
292 DCHECK(content::RenderThread::Get());
293
294 scoped_ptr<base::SharedMemory> shm =
295 content::RenderThread::Get()->HostAllocateSharedMemoryBuffer(size);
296 DCHECK(shm) << "Failed to allocate shared memory";
asargent_no_longer_on_chrome 2016/04/06 20:53:21 Maybe this should just be a CHECK? Alternately, m
Mikhail 2016/04/07 09:07:25 We can just pass nullptr to encoder that will be a
297 if (!shm->Map(size)) {
298 NOTREACHED() << "Map failed";
299 }
300 callback.Run(std::move(shm));
202 } 301 }
203 302
303 } // namespace
304
204 bool WiFiDisplayMediaManager::InitOptimalVideoFormat( 305 bool WiFiDisplayMediaManager::InitOptimalVideoFormat(
205 const wds::NativeVideoFormat& sink_native_format, 306 const wds::NativeVideoFormat& sink_native_format,
206 const std::vector<wds::H264VideoCodec>& sink_supported_codecs) { 307 const std::vector<wds::H264VideoCodec>& sink_supported_codecs) {
207 const media::VideoCaptureFormat* capture_format = 308 const media::VideoCaptureFormat* capture_format =
208 content::GetCurrentVideoTrackFormat(video_track_); 309 content::GetCurrentVideoTrackFormat(video_track_);
209 if (!capture_format) { 310 if (!capture_format) {
210 error_callback_.Run(kErrorNoVideoFormatData); 311 error_callback_.Run(kErrorNoVideoFormatData);
211 return false; 312 return false;
212 } 313 }
213 314
214 if (!FindOptimalFormat( 315 if (!FindOptimalFormat(
215 capture_format, sink_supported_codecs, &optimal_video_format_)) { 316 capture_format, sink_supported_codecs, &optimal_video_format_)) {
216 error_callback_.Run(kErrorSinkCannotPlayVideo); 317 error_callback_.Run(kErrorSinkCannotPlayVideo);
217 return false; 318 return false;
218 } 319 }
320 video_encoder_parameters_.frame_size = capture_format->frame_size;
321 video_encoder_parameters_.frame_rate =
322 static_cast<int>(capture_format->frame_rate);
323 video_encoder_parameters_.bit_rate = GetBitRate(capture_format->frame_size);
324 video_encoder_parameters_.profile = optimal_video_format_.profile;
325 video_encoder_parameters_.level = optimal_video_format_.level;
326 video_encoder_parameters_.create_memory_callback =
327 media::BindToCurrentLoop(base::Bind(&CreateVideoEncodeMemory));
328 video_encoder_parameters_.vea_create_callback =
329 media::BindToCurrentLoop(
330 base::Bind(&content::CreateVideoEncodeAccelerator));
219 331
220 return true; 332 return true;
221 } 333 }
222 334
223 bool WiFiDisplayMediaManager::InitOptimalAudioFormat( 335 bool WiFiDisplayMediaManager::InitOptimalAudioFormat(
224 const std::vector<wds::AudioCodec>& sink_codecs) { 336 const std::vector<wds::AudioCodec>& sink_codecs) {
225 for (const wds::AudioCodec& codec : sink_codecs) { 337 for (const wds::AudioCodec& codec : sink_codecs) {
226 // MediaStreamTrack contains LPCM audio. 338 // MediaStreamTrack contains LPCM audio.
227 if (codec.format == wds::LPCM) { 339 if (codec.format == wds::LPCM) {
228 optimal_audio_codec_ = codec; 340 optimal_audio_codec_ = codec;
229 // Picking a single mode. 341 // Picking a single mode.
230 wds::AudioModes optimal_mode; 342 wds::AudioModes optimal_mode;
231 if (codec.modes.test(wds::LPCM_44_1K_16B_2CH)) 343 if (codec.modes.test(wds::LPCM_44_1K_16B_2CH))
232 optimal_mode.set(wds::LPCM_44_1K_16B_2CH); 344 optimal_mode.set(wds::LPCM_44_1K_16B_2CH);
233 else 345 else
234 optimal_mode.set(wds::LPCM_48K_16B_2CH); 346 optimal_mode.set(wds::LPCM_48K_16B_2CH);
235 optimal_audio_codec_.modes = optimal_mode; 347 optimal_audio_codec_.modes = optimal_mode;
236 return true; 348 return true;
237 } 349 }
238 } 350 }
239 error_callback_.Run(kErrorSinkCannotPlayAudio); 351 error_callback_.Run(kErrorSinkCannotPlayAudio);
240 return false; 352 return false;
241 } 353 }
242 354
243 wds::AudioCodec WiFiDisplayMediaManager::GetOptimalAudioFormat() const { 355 wds::AudioCodec WiFiDisplayMediaManager::GetOptimalAudioFormat() const {
244 return optimal_audio_codec_; 356 return optimal_audio_codec_;
245 } 357 }
246 358
359 void WiFiDisplayMediaManager::SendIDRPicture() {
360 DCHECK(player_);
361 io_task_runner_->PostTask(FROM_HERE,
362 base::Bind(&WiFiDisplayMediaPipeline::RequestIDRPicture,
363 base::Unretained(player_)));
364 }
365
366 std::string WiFiDisplayMediaManager::GetSessionId() const {
367 if (session_id_.empty())
368 session_id_ = base::RandBytesAsString(8);
369 return session_id_;
370 }
371
372 void WiFiDisplayMediaManager::OnPlayerCreated(
373 scoped_ptr<WiFiDisplayMediaPipeline> player) {
374 DCHECK(player);
375 DCHECK(content::RenderThread::Get());
376 player_ = player.release();
377
378 auto completion_callback = base::Bind(
379 &WiFiDisplayMediaManager::OnMediaPipelineInitialized,
380 weak_factory_.GetWeakPtr());
381
382 io_task_runner_->PostTask(FROM_HERE,
383 base::Bind(&WiFiDisplayMediaPipeline::Initialize,
384 base::Unretained(player_),
385 media::BindToCurrentLoop(completion_callback)));
386 }
387
388 void WiFiDisplayMediaManager::OnMediaPipelineInitialized(bool success) {
389 DCHECK(content::RenderThread::Get());
390 is_initialized_ = success;
391
392 if (!is_initialized_) {
393 error_callback_.Run(kErrorMediaPipelineFailure);
394 return;
395 }
396
397 if (is_playing_)
398 Play();
399 }
400
401
247 } // namespace extensions 402 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698