blob: 6a880a0223bafde5bd258b365bb8e8aca5b27b3a [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/cast/common/openscreen_conversion_helpers.h"
#include "media/base/audio_codecs.h"
#include "media/base/video_codecs.h"
#include "media/cast/cast_config.h"
#include "third_party/openscreen/src/platform/base/span.h"
namespace media::cast {
openscreen::Clock::time_point ToOpenscreenTimePoint(base::TimeTicks ticks) {
static_assert(sizeof(openscreen::Clock::time_point::rep) >=
sizeof(base::TimeTicks::Max()));
return openscreen::Clock::time_point(
std::chrono::microseconds(ticks.since_origin().InMicroseconds()));
}
// Returns the tick count in the given timebase nearest to the base::TimeDelta.
int64_t TimeDeltaToTicks(base::TimeDelta delta, int timebase) {
DCHECK_GT(timebase, 0);
const double ticks = delta.InSecondsF() * timebase + 0.5 /* rounding */;
return base::checked_cast<int64_t>(ticks);
}
openscreen::cast::RtpTimeTicks ToRtpTimeTicks(base::TimeDelta delta,
int timebase) {
return openscreen::cast::RtpTimeTicks(TimeDeltaToTicks(delta, timebase));
}
openscreen::cast::RtpTimeDelta ToRtpTimeDelta(base::TimeDelta delta,
int timebase) {
return openscreen::cast::RtpTimeDelta::FromTicks(
TimeDeltaToTicks(delta, timebase));
}
base::TimeDelta ToTimeDelta(openscreen::cast::RtpTimeDelta rtp_delta,
int timebase) {
DCHECK_GT(timebase, 0);
return base::Microseconds(
rtp_delta.ToDuration<std::chrono::microseconds>(timebase).count());
}
base::TimeDelta ToTimeDelta(openscreen::cast::RtpTimeTicks rtp_ticks,
int timebase) {
DCHECK_GT(timebase, 0);
return ToTimeDelta(rtp_ticks - openscreen::cast::RtpTimeTicks{}, timebase);
}
base::TimeDelta ToTimeDelta(openscreen::Clock::duration tp) {
return base::Microseconds(
std::chrono::duration_cast<std::chrono::microseconds>(tp).count());
}
const openscreen::cast::EncodedFrame ToOpenscreenEncodedFrame(
const SenderEncodedFrame& encoded_frame) {
return openscreen::cast::EncodedFrame(
encoded_frame.dependency, encoded_frame.frame_id,
encoded_frame.referenced_frame_id, encoded_frame.rtp_timestamp,
ToOpenscreenTimePoint(encoded_frame.reference_time),
std::chrono::milliseconds(encoded_frame.new_playout_delay_ms),
openscreen::ByteView(
reinterpret_cast<const uint8_t*>(encoded_frame.data.data()),
encoded_frame.data.size()));
}
openscreen::cast::AudioCodec ToOpenscreenAudioCodec(media::cast::Codec codec) {
switch (codec) {
case Codec::kAudioRemote:
return openscreen::cast::AudioCodec::kNotSpecified;
case Codec::kAudioOpus:
return openscreen::cast::AudioCodec::kOpus;
case Codec::kAudioAac:
return openscreen::cast::AudioCodec::kAac;
default:
NOTREACHED();
return openscreen::cast::AudioCodec::kNotSpecified;
}
}
openscreen::cast::VideoCodec ToOpenscreenVideoCodec(media::cast::Codec codec) {
switch (codec) {
case Codec::kVideoRemote:
return openscreen::cast::VideoCodec::kNotSpecified;
case Codec::kVideoVp8:
return openscreen::cast::VideoCodec::kVp8;
case Codec::kVideoH264:
return openscreen::cast::VideoCodec::kH264;
case Codec::kVideoVp9:
return openscreen::cast::VideoCodec::kVp9;
case Codec::kVideoAv1:
return openscreen::cast::VideoCodec::kAv1;
default:
NOTREACHED();
return openscreen::cast::VideoCodec::kNotSpecified;
}
}
Codec ToCodec(openscreen::cast::AudioCodec codec) {
switch (codec) {
case openscreen::cast::AudioCodec::kNotSpecified:
return Codec::kAudioRemote;
case openscreen::cast::AudioCodec::kOpus:
return Codec::kAudioOpus;
case openscreen::cast::AudioCodec::kAac:
return Codec::kAudioAac;
}
NOTREACHED();
return Codec::kUnknown;
}
Codec ToCodec(openscreen::cast::VideoCodec codec) {
switch (codec) {
case openscreen::cast::VideoCodec::kNotSpecified:
return Codec::kVideoRemote;
case openscreen::cast::VideoCodec::kVp8:
return Codec::kVideoVp8;
case openscreen::cast::VideoCodec::kH264:
return Codec::kVideoH264;
case openscreen::cast::VideoCodec::kVp9:
return Codec::kVideoVp9;
case openscreen::cast::VideoCodec::kAv1:
return Codec::kVideoAv1;
case openscreen::cast::VideoCodec::kHevc:
return Codec::kUnknown;
}
NOTREACHED();
return Codec::kUnknown;
}
AudioCodec ToAudioCodec(openscreen::cast::AudioCodec codec) {
switch (codec) {
case openscreen::cast::AudioCodec::kNotSpecified:
// media::AudioCodec doesn't have a concept of "not specified."
return AudioCodec::kUnknown;
case openscreen::cast::AudioCodec::kOpus:
return AudioCodec::kOpus;
case openscreen::cast::AudioCodec::kAac:
return AudioCodec::kAAC;
}
NOTREACHED();
return AudioCodec::kUnknown;
}
VideoCodec ToVideoCodec(openscreen::cast::VideoCodec codec) {
switch (codec) {
// media::VideoCodec doesn't have a concept of "not specified."
case openscreen::cast::VideoCodec::kNotSpecified:
return VideoCodec::kUnknown;
case openscreen::cast::VideoCodec::kVp8:
return VideoCodec::kVP8;
case openscreen::cast::VideoCodec::kH264:
return VideoCodec::kH264;
case openscreen::cast::VideoCodec::kVp9:
return VideoCodec::kVP9;
case openscreen::cast::VideoCodec::kAv1:
return VideoCodec::kAV1;
case openscreen::cast::VideoCodec::kHevc:
return VideoCodec::kHEVC;
}
NOTREACHED();
return VideoCodec::kUnknown;
}
openscreen::IPAddress ToOpenscreenIPAddress(const net::IPAddress& address) {
const auto version = address.IsIPv6() ? openscreen::IPAddress::Version::kV6
: openscreen::IPAddress::Version::kV4;
return openscreen::IPAddress(version, address.bytes().data());
}
openscreen::cast::AudioCaptureConfig ToOpenscreenAudioConfig(
const FrameSenderConfig& config) {
return openscreen::cast::AudioCaptureConfig{
.codec = media::cast::ToOpenscreenAudioCodec(config.codec),
.channels = config.channels,
.bit_rate = config.max_bitrate,
.sample_rate = config.rtp_timebase,
.target_playout_delay =
std::chrono::milliseconds(config.max_playout_delay.InMilliseconds()),
.codec_parameter = std::string()};
}
openscreen::cast::VideoCaptureConfig ToOpenscreenVideoConfig(
const FrameSenderConfig& config) {
// Currently we just hardcode 1080P as the resolution.
static constexpr openscreen::cast::Resolution kResolutions[] = {{1920, 1080}};
// NOTE: currently we only support a frame rate of 30FPS, so casting
// directly to an integer is fine.
return openscreen::cast::VideoCaptureConfig{
.codec = media::cast::ToOpenscreenVideoCodec(config.codec),
.max_frame_rate =
openscreen::SimpleFraction{static_cast<int>(config.max_frame_rate),
1},
.max_bit_rate = config.max_bitrate,
.resolutions =
std::vector(std::begin(kResolutions), std::end(kResolutions)),
.target_playout_delay =
std::chrono::milliseconds(config.max_playout_delay.InMilliseconds()),
.codec_parameter = std::string()};
}
} // namespace media::cast