Index: extensions/renderer/api/display_source/wifi_display/wifi_display_media_pipeline.cc |
diff --git a/extensions/renderer/api/display_source/wifi_display/wifi_display_media_pipeline.cc b/extensions/renderer/api/display_source/wifi_display/wifi_display_media_pipeline.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..9d0a2bd3446f86bb1e976e5767eddf892b9c74c4 |
--- /dev/null |
+++ b/extensions/renderer/api/display_source/wifi_display/wifi_display_media_pipeline.cc |
@@ -0,0 +1,150 @@ |
+// Copyright 2016 The Chromium 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 "extensions/renderer/api/display_source/wifi_display/wifi_display_media_pipeline.h" |
+ |
+#include "base/logging.h" |
+#include "content/public/renderer/render_thread.h" |
+#include "content/public/renderer/video_encode_accelerator.h" |
+#include "extensions/renderer/api/display_source/wifi_display/wifi_display_elementary_stream_descriptor.h" |
+#include "extensions/renderer/api/display_source/wifi_display/wifi_display_elementary_stream_info.h" |
+ |
+namespace extensions { |
+ |
+namespace { |
+ |
+const char kErrorVideoEncoderError[] = "Unrepairable video encoder error"; |
+ |
+} // namespace |
+ |
+WiFiDisplayMediaPipeline::WiFiDisplayMediaPipeline( |
+ wds::SessionType type, |
+ const WiFiDisplayVideoEncoder::InitParameters& video_parameters, |
+ const wds::AudioCodec& audio_codec, |
+ const ErrorCallback& error_callback) |
+ : type_(type), |
+ video_parameters_(video_parameters), |
+ audio_codec_(audio_codec), |
+ error_callback_(error_callback), |
+ weak_factory_(this) { |
+} |
+ |
+// static |
+scoped_ptr<WiFiDisplayMediaPipeline> WiFiDisplayMediaPipeline::Create( |
+ wds::SessionType type, |
+ const WiFiDisplayVideoEncoder::InitParameters& video_parameters, |
+ const wds::AudioCodec& audio_codec, |
+ const ErrorCallback& error_callback) { |
+ return scoped_ptr<WiFiDisplayMediaPipeline>( |
+ new WiFiDisplayMediaPipeline(type, |
+ video_parameters, |
+ audio_codec, |
+ error_callback)); |
+} |
+ |
+WiFiDisplayMediaPipeline::~WiFiDisplayMediaPipeline() { |
+} |
+ |
+void WiFiDisplayMediaPipeline::InsertRawVideoFrame( |
+ const scoped_refptr<media::VideoFrame>& video_frame, |
+ base::TimeTicks reference_time) { |
+ DCHECK(video_encoder_); |
+ video_encoder_->InsertRawVideoFrame(video_frame, reference_time); |
+} |
+ |
+void WiFiDisplayMediaPipeline::RequestIDRPicture() { |
+ DCHECK(video_encoder_); |
+ video_encoder_->RequestIDRPicture(); |
+} |
+ |
+void WiFiDisplayMediaPipeline::Initialize( |
+ const InitCompletionCallback& callback) { |
+ DCHECK(init_completion_callback_.is_null()); |
+ init_completion_callback_ = callback; |
+ |
+ CreateMediaPacketizer(); |
+ |
+ if (type_ & wds::VideoSession) { |
+ CreateVideoEncoder(); |
+ return; |
+ } |
+ |
+ init_completion_callback_.Run(true); |
+} |
+ |
+void WiFiDisplayMediaPipeline::CreateVideoEncoder() { |
+ DCHECK(!video_encoder_); |
+ auto result_callback = |
+ base::Bind(&WiFiDisplayMediaPipeline::OnVideoEncoderCreated, |
+ weak_factory_.GetWeakPtr()); |
+ WiFiDisplayVideoEncoder::Create(video_parameters_, |
+ result_callback); |
+} |
+ |
+void WiFiDisplayMediaPipeline::CreateMediaPacketizer() { |
+ DCHECK(!packetizer_); |
+ std::vector<WiFiDisplayElementaryStreamInfo> stream_infos; |
+ if (type_ & wds::VideoSession) { |
+ std::vector<WiFiDisplayElementaryStreamDescriptor> descriptors; |
+ descriptors.emplace_back( |
+ WiFiDisplayElementaryStreamDescriptor::AVCTimingAndHRD::Create()); |
+ stream_infos.emplace_back(WiFiDisplayElementaryStreamInfo::VIDEO_H264, |
+ std::move(descriptors)); |
+ } |
+ |
+ if (type_ & wds::AudioSession) { |
+ using LPCMAudioStreamDescriptor = |
+ WiFiDisplayElementaryStreamDescriptor::LPCMAudioStream; |
+ std::vector<WiFiDisplayElementaryStreamDescriptor> descriptors; |
+ descriptors.emplace_back( |
+ LPCMAudioStreamDescriptor::Create( |
+ audio_codec_.modes.test(wds::LPCM_48K_16B_2CH) |
+ ? LPCMAudioStreamDescriptor::SAMPLING_FREQUENCY_48K |
+ : LPCMAudioStreamDescriptor::SAMPLING_FREQUENCY_44_1K, |
+ LPCMAudioStreamDescriptor::BITS_PER_SAMPLE_16, |
+ false, // emphasis_flag |
+ LPCMAudioStreamDescriptor::NUMBER_OF_CHANNELS_STEREO)); |
+ stream_infos.emplace_back(WiFiDisplayElementaryStreamInfo::AUDIO_LPCM, |
+ std::move(descriptors)); |
+ } |
+ |
+ packetizer_.reset(new WiFiDisplayMediaPacketizer( |
+ base::TimeDelta::FromMilliseconds(200), |
+ std::move(stream_infos), |
+ base::Bind(&WiFiDisplayMediaPipeline::OnPacketizedMediaDatagramPacket, |
+ base::Unretained(this)))); |
+} |
+ |
+void WiFiDisplayMediaPipeline::OnVideoEncoderCreated( |
+ scoped_refptr<WiFiDisplayVideoEncoder> video_encoder) { |
+ if (!video_encoder) { |
+ init_completion_callback_.Run(false); |
+ return; |
+ } |
+ video_encoder_ = std::move(video_encoder); |
+ auto encoded_callback = base::Bind( |
+ &WiFiDisplayMediaPipeline::OnEncodedVideoFrame, |
+ weak_factory_.GetWeakPtr()); |
+ auto error_callback = base::Bind(error_callback_, kErrorVideoEncoderError); |
+ video_encoder_->SetCallbacks(encoded_callback, error_callback); |
+ init_completion_callback_.Run(true); |
+} |
+ |
+void WiFiDisplayMediaPipeline::OnEncodedVideoFrame( |
+ const WiFiDisplayEncodedFrame& frame) { |
+ DCHECK(packetizer_); |
+ if (!packetizer_->EncodeElementaryStreamUnit( |
+ 0u, frame.bytes(), frame.data.size(), frame.key_frame, frame.pts, |
+ frame.dts, true)) { |
+ DVLOG(1) << "Couldn't write video mpegts packet"; |
+ } |
+} |
+ |
+bool WiFiDisplayMediaPipeline::OnPacketizedMediaDatagramPacket( |
+ WiFiDisplayMediaDatagramPacket media_datagram_packet) { |
+ NOTIMPLEMENTED(); |
+ return true; |
+} |
+ |
+} // namespace extensions |