Commit e2abda24 authored by Zijie He's avatar Zijie He Committed by Commit Bot

[Chromoting] Implement CastSoftwareVideoEncoderAdapter to use cast encoders in Chromoting

CastSoftwareVideoEncoderAdapter implements WebrtcVideoEncoder by using a
media::cast::SoftwareVideoEncoder.

This implementation is now only buildable, we still need several changes to make
it work. E.g. converting the DesktopFrame data from ARGB to I420. I am working
on a WebRTC change for it. Currently this kind of conversions have been
implemented several times across Chromium.

Bug: chromium:781432
Change-Id: Ia259bc0478957d2cef492cbdb418202bfda72a4b
Reviewed-on: https://chromium-review.googlesource.com/754060Reviewed-by: default avatarXiangjun Zhang <xjz@chromium.org>
Reviewed-by: default avatarYuri Wiitala <miu@chromium.org>
Reviewed-by: default avatarLambros Lambrou <lambroslambrou@chromium.org>
Commit-Queue: Zijie He <zijiehe@chromium.org>
Cr-Commit-Position: refs/heads/master@{#517261}
parent 7c1ef68c
......@@ -5,8 +5,6 @@
source_set("encoder") {
sources = [
"audio_encoder.h",
"audio_encoder_opus.cc",
"audio_encoder_opus.h",
"encoder_bitrate_filter.cc",
"encoder_bitrate_filter.h",
"frame_processing_time_estimator.cc",
......@@ -32,8 +30,6 @@ source_set("encoder") {
deps = [
":vpx_codec",
"//base/third_party/dynamic_annotations",
"//media",
"//media:shared_memory_support",
"//remoting/proto",
"//third_party/libvpx",
"//third_party/libyuv",
......@@ -62,14 +58,17 @@ source_set("encoder") {
# Opus depends on //media, which is not a supported include for iOS.
# Also disabled it on Android, to avoid dependency on //media.
# TODO(sergeyu): Cleanup host-only deps in client targets.
if (is_ios || is_android) {
sources -= [
if (!is_ios && !is_android) {
sources += [
"audio_encoder_opus.cc",
"audio_encoder_opus.h",
"cast_software_video_encoder_adapter.cc",
"cast_software_video_encoder_adapter.h",
]
deps -= [
deps += [
"//media",
"//media:shared_memory_support",
"//media/cast:sender",
]
}
}
......
......@@ -6,6 +6,7 @@ include_rules = [
"+third_party/opus",
"+third_party/webrtc",
"+gpu/command_buffer/service/gpu_preferences.h",
"+media/cast",
"+media/video",
"+media/gpu",
"+ui/gfx/geometry",
......
// Copyright 2017 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 "remoting/codec/cast_software_video_encoder_adapter.h"
#include <stdint.h>
#include <utility>
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "media/base/video_frame.h"
#include "media/base/video_types.h"
#include "media/cast/sender/sender_encoded_frame.h"
#include "media/cast/sender/software_video_encoder.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
namespace remoting {
CastSoftwareVideoEncoderAdapter::CastSoftwareVideoEncoderAdapter(
std::unique_ptr<media::cast::SoftwareVideoEncoder> encoder,
webrtc::VideoCodecType codec)
: encoder_(std::move(encoder)),
codec_(codec) {
DCHECK(encoder_);
}
CastSoftwareVideoEncoderAdapter::~CastSoftwareVideoEncoderAdapter() = default;
void CastSoftwareVideoEncoderAdapter::Encode(
std::unique_ptr<webrtc::DesktopFrame> frame,
const FrameParams& params,
EncodeCallback done) {
const base::TimeTicks current_time = base::TimeTicks::Now();
if (start_timestamp_.is_null()) {
encoder_->Initialize();
start_timestamp_ = current_time;
}
if (params.key_frame) {
encoder_->GenerateKeyFrame();
}
if (params.bitrate_kbps > 0) {
encoder_->UpdateRates(params.bitrate_kbps * 1000);
}
media::cast::SenderEncodedFrame encoded_frame;
encoder_->Encode(CreateVideoFrame(*frame),
current_time,
&encoded_frame);
std::move(done).Run(EncodeResult::SUCCEEDED,
CreateEncodedFrame(*frame, std::move(encoded_frame)));
}
scoped_refptr<media::VideoFrame>
CastSoftwareVideoEncoderAdapter::CreateVideoFrame(
const webrtc::DesktopFrame& frame) const {
DCHECK(!start_timestamp_.is_null());
// TODO(zijiehe): According to http://crbug.com/555909, this does not work
// now, media::VideoFrame::WrapExternalData() accepts only I420 or Y16.
return media::VideoFrame::WrapExternalData(
media::PIXEL_FORMAT_ARGB,
gfx::Size(frame.stride() / webrtc::DesktopFrame::kBytesPerPixel,
frame.size().height()),
gfx::Rect(frame.size().width(), frame.size().height()),
gfx::Size(frame.size().width(), frame.size().height()),
frame.data(),
frame.stride() * frame.size().height(),
base::TimeTicks::Now() - start_timestamp_);
}
std::unique_ptr<CastSoftwareVideoEncoderAdapter::EncodedFrame>
CastSoftwareVideoEncoderAdapter::CreateEncodedFrame(
const webrtc::DesktopFrame& frame,
media::cast::SenderEncodedFrame&& media_frame) const {
std::unique_ptr<EncodedFrame> result = base::MakeUnique<EncodedFrame>();
result->size = frame.size();
// TODO(zijiehe): Should INDEPENDENT frames also be considered as key frames?
result->key_frame =
media_frame.dependency == media::cast::EncodedFrame::KEY;
// TODO(zijiehe): Forward quantizer from media::cast::SoftwareVideoEncoder.
// Currently we set this value to INT32_MAX to always trigger top-off.
result->quantizer = INT32_MAX;
result->codec = codec_;
result->data = std::move(media_frame.data);
return result;
}
} // namespace remoting
// Copyright 2017 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.
#ifndef REMOTING_CODEC_CAST_SOFTWARE_VIDEO_ENCODER_ADAPTER_H_
#define REMOTING_CODEC_CAST_SOFTWARE_VIDEO_ENCODER_ADAPTER_H_
#include <memory>
#include "base/memory/scoped_refptr.h"
#include "base/time/time.h"
#include "remoting/codec/webrtc_video_encoder.h"
#include "third_party/webrtc/common_types.h"
namespace media {
class VideoFrame;
namespace cast {
struct SenderEncodedFrame;
class SoftwareVideoEncoder;
} // namespace cast
} // namespace media
namespace webrtc {
class DesktopFrame;
} // namespace webrtc
namespace remoting {
// Implements WebrtcVideoEncoder by using a media::cast::SoftwareVideoEncoder.
class CastSoftwareVideoEncoderAdapter final : public WebrtcVideoEncoder {
public:
CastSoftwareVideoEncoderAdapter(
std::unique_ptr<media::cast::SoftwareVideoEncoder> encoder,
webrtc::VideoCodecType codec);
~CastSoftwareVideoEncoderAdapter() override;
void Encode(std::unique_ptr<webrtc::DesktopFrame> frame,
const FrameParams& param,
EncodeCallback done) override;
private:
scoped_refptr<media::VideoFrame> CreateVideoFrame(
const webrtc::DesktopFrame& frame) const;
std::unique_ptr<EncodedFrame> CreateEncodedFrame(
const webrtc::DesktopFrame& frame,
media::cast::SenderEncodedFrame&& media_frame) const;
const std::unique_ptr<media::cast::SoftwareVideoEncoder> encoder_;
const webrtc::VideoCodecType codec_;
// The timestamp of the first Encode() function call. is_null() also indicates
// that this instance is not initialized.
base::TimeTicks start_timestamp_;
};
} // namespace remoting
#endif // REMOTING_CODEC_CAST_SOFTWARE_VIDEO_ENCODER_ADAPTER_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment