blob: 8051a819d8726ebbc2958c68ad1b3d53c0b4e5e9 [file] [log] [blame]
// 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 "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 = std::make_unique<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