Commit 106f5d97 authored by Xiaohan Wang's avatar Xiaohan Wang Committed by Commit Bot

media: Support updated CDM_11 that supports ColorSpace

Conversion code is added to support multiple CDM interfaces that use
different version of cdm::VideoDecoderConfig and cdm::VideoFrame.

Bug: 854943
Change-Id: I235c12805aea3191f8a5153c9a124f6fe3b26a31
Reviewed-on: https://chromium-review.googlesource.com/1227489
Commit-Queue: Xiaohan Wang <xhwang@chromium.org>
Reviewed-by: default avatarFredrik Hubinette <hubbe@chromium.org>
Cr-Commit-Position: refs/heads/master@{#591940}
parent da8cf24a
......@@ -363,7 +363,7 @@ deps = {
},
'src/media/cdm/api':
Var('chromium_git') + '/chromium/cdm.git' + '@' + '2c580d1532f354556c05b09512e64eeab938b01e',
Var('chromium_git') + '/chromium/cdm.git' + '@' + '6f92d7c0e62b135511744ce6bcf0dd2ff364df09',
'src/native_client': {
'url': Var('chromium_git') + '/native_client/src/native_client.git' + '@' + Var('nacl_revision'),
......
......@@ -13,6 +13,7 @@
#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
......@@ -35,6 +36,7 @@
#include "media/cdm/cdm_auxiliary_helper.h"
#include "media/cdm/cdm_helpers.h"
#include "media/cdm/cdm_wrapper.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/rect.h"
#include "url/origin.h"
......@@ -239,6 +241,29 @@ cdm::VideoFormat ToCdmVideoFormat(VideoPixelFormat format) {
}
}
cdm::ColorRange ToCdmColorRange(gfx::ColorSpace::RangeID range) {
switch (range) {
case gfx::ColorSpace::RangeID::LIMITED:
return cdm::ColorRange::kLimited;
case gfx::ColorSpace::RangeID::FULL:
return cdm::ColorRange::kFull;
case gfx::ColorSpace::RangeID::DERIVED:
return cdm::ColorRange::kDerived;
default:
DVLOG(1) << "Invalid color range";
return cdm::ColorRange::kInvalid;
}
}
cdm::ColorSpace ToCdmColorSpace(const VideoColorSpace& color_space) {
// Cast is okay because both VideoColorSpace and cdm::ColorSpace follow the
// standard ISO 23001-8:2016.
return {base::checked_cast<uint8_t>(color_space.primaries),
base::checked_cast<uint8_t>(color_space.transfer),
base::checked_cast<uint8_t>(color_space.matrix),
ToCdmColorRange(color_space.range)};
}
cdm::StreamType ToCdmStreamType(Decryptor::StreamType stream_type) {
switch (stream_type) {
case Decryptor::kAudio:
......@@ -791,10 +816,11 @@ void CdmAdapter::InitializeVideoDecoder(const VideoDecoderConfig& config,
DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(video_init_cb_.is_null());
cdm::VideoDecoderConfig_2 cdm_decoder_config = {};
cdm::VideoDecoderConfig_3 cdm_decoder_config = {};
cdm_decoder_config.codec = ToCdmVideoCodec(config.codec());
cdm_decoder_config.profile = ToCdmVideoCodecProfile(config.profile());
cdm_decoder_config.format = ToCdmVideoFormat(config.format());
cdm_decoder_config.color_space = ToCdmColorSpace(config.color_space_info());
cdm_decoder_config.coded_size.width = config.coded_size().width();
cdm_decoder_config.coded_size.height = config.coded_size().height();
cdm_decoder_config.extra_data =
......
......@@ -5,9 +5,32 @@
#include "media/cdm/cdm_helpers.h"
#include "base/logging.h"
#include "ui/gfx/color_space.h"
namespace media {
namespace {
// See ISO 23001-8:2016, section 7. Value 2 means "Unspecified".
constexpr cdm::ColorSpace kUnspecifiedColorSpace = {2, 2, 2,
cdm::ColorRange::kInvalid};
gfx::ColorSpace::RangeID ToGfxColorSpaceRange(cdm::ColorRange range) {
switch (range) {
case cdm::ColorRange::kLimited:
return gfx::ColorSpace::RangeID::LIMITED;
case cdm::ColorRange::kFull:
return gfx::ColorSpace::RangeID::FULL;
case cdm::ColorRange::kDerived:
return gfx::ColorSpace::RangeID::DERIVED;
default:
DVLOG(1) << "Invalid color range";
return gfx::ColorSpace::RangeID::INVALID;
}
}
} // namespace
DecryptedBlockImpl::DecryptedBlockImpl() : buffer_(nullptr), timestamp_(0) {}
DecryptedBlockImpl::~DecryptedBlockImpl() {
......@@ -32,8 +55,11 @@ int64_t DecryptedBlockImpl::Timestamp() const {
}
VideoFrameImpl::VideoFrameImpl()
: format_(cdm::kUnknownVideoFormat), frame_buffer_(nullptr), timestamp_(0) {
for (uint32_t i = 0; i < kMaxPlanes; ++i) {
: format_(cdm::kUnknownVideoFormat),
color_space_(kUnspecifiedColorSpace),
frame_buffer_(nullptr),
timestamp_(0) {
for (uint32_t i = 0; i < cdm::kMaxPlanes; ++i) {
plane_offsets_[i] = 0;
strides_[i] = 0;
}
......@@ -68,24 +94,23 @@ cdm::Buffer* VideoFrameImpl::FrameBuffer() {
return frame_buffer_;
}
void VideoFrameImpl::SetPlaneOffset(cdm::VideoFrame::VideoPlane plane,
uint32_t offset) {
DCHECK(plane < kMaxPlanes);
void VideoFrameImpl::SetPlaneOffset(cdm::VideoPlane plane, uint32_t offset) {
DCHECK(plane < cdm::kMaxPlanes);
plane_offsets_[plane] = offset;
}
uint32_t VideoFrameImpl::PlaneOffset(VideoPlane plane) {
DCHECK(plane < kMaxPlanes);
uint32_t VideoFrameImpl::PlaneOffset(cdm::VideoPlane plane) {
DCHECK(plane < cdm::kMaxPlanes);
return plane_offsets_[plane];
}
void VideoFrameImpl::SetStride(VideoPlane plane, uint32_t stride) {
DCHECK(plane < kMaxPlanes);
void VideoFrameImpl::SetStride(cdm::VideoPlane plane, uint32_t stride) {
DCHECK(plane < cdm::kMaxPlanes);
strides_[plane] = stride;
}
uint32_t VideoFrameImpl::Stride(VideoPlane plane) {
DCHECK(plane < kMaxPlanes);
uint32_t VideoFrameImpl::Stride(cdm::VideoPlane plane) {
DCHECK(plane < cdm::kMaxPlanes);
return strides_[plane];
}
......@@ -97,6 +122,16 @@ int64_t VideoFrameImpl::Timestamp() const {
return timestamp_;
}
void VideoFrameImpl::SetColorSpace(cdm::ColorSpace color_space) {
color_space_ = color_space;
}
media::VideoColorSpace VideoFrameImpl::MediaColorSpace() const {
return media::VideoColorSpace(
color_space_.primary_id, color_space_.transfer_id, color_space_.matrix_id,
ToGfxColorSpaceRange(color_space_.range));
}
AudioFramesImpl::AudioFramesImpl()
: buffer_(nullptr), format_(cdm::kUnknownAudioFormat) {}
......
......@@ -11,6 +11,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "media/base/media_export.h"
#include "media/base/video_color_space.h"
#include "media/cdm/api/content_decryption_module.h"
#include "ui/gfx/geometry/size.h"
......@@ -36,25 +37,32 @@ class DecryptedBlockImpl : public cdm::DecryptedBlock {
DISALLOW_COPY_AND_ASSIGN(DecryptedBlockImpl);
};
class MEDIA_EXPORT VideoFrameImpl : public cdm::VideoFrame {
class MEDIA_EXPORT VideoFrameImpl : public cdm::VideoFrame,
public cdm::VideoFrame_2 {
public:
VideoFrameImpl();
~VideoFrameImpl() override;
// cdm::VideoFrame implementation.
// cdm::VideoFrame and cdm::VideoFrame_2 common implementation.
void SetFormat(cdm::VideoFormat format) final;
cdm::VideoFormat Format() const final;
void SetSize(cdm::Size size) final;
cdm::Size Size() const final;
void SetFrameBuffer(cdm::Buffer* frame_buffer) final;
cdm::Buffer* FrameBuffer() final;
void SetPlaneOffset(cdm::VideoFrame::VideoPlane plane, uint32_t offset) final;
uint32_t PlaneOffset(VideoPlane plane) final;
void SetStride(VideoPlane plane, uint32_t stride) final;
uint32_t Stride(VideoPlane plane) final;
void SetPlaneOffset(cdm::VideoPlane plane, uint32_t offset) final;
uint32_t PlaneOffset(cdm::VideoPlane plane) final;
void SetStride(cdm::VideoPlane plane, uint32_t stride) final;
uint32_t Stride(cdm::VideoPlane plane) final;
void SetTimestamp(int64_t timestamp) final;
int64_t Timestamp() const final;
// cdm::VideoFrame_2 specific implementation.
void SetColorSpace(cdm::ColorSpace color_space) final;
// Helper functions to get the ColorSpace.
media::VideoColorSpace MediaColorSpace() const;
// Create a media::VideoFrame based on the data contained in this object.
// |natural_size| is the visible portion of the video frame, and is
// provided separately as it comes from the configuration, not the CDM.
......@@ -71,6 +79,8 @@ class MEDIA_EXPORT VideoFrameImpl : public cdm::VideoFrame {
// The video buffer format.
cdm::VideoFormat format_;
cdm::ColorSpace color_space_;
// Width and height of the video frame.
cdm::Size size_;
......@@ -78,12 +88,12 @@ class MEDIA_EXPORT VideoFrameImpl : public cdm::VideoFrame {
cdm::Buffer* frame_buffer_;
// Array of data pointers to each plane in the video frame buffer.
uint32_t plane_offsets_[kMaxPlanes];
uint32_t plane_offsets_[cdm::kMaxPlanes];
// Array of strides for each plane, typically greater or equal to the width
// of the surface divided by the horizontal sampling period. Note that
// strides can be negative.
uint32_t strides_[kMaxPlanes];
uint32_t strides_[cdm::kMaxPlanes];
// Presentation timestamp in microseconds.
int64_t timestamp_;
......
......@@ -15,6 +15,7 @@
#include "base/macros.h"
#include "media/base/media_switches.h"
#include "media/cdm/api/content_decryption_module.h"
#include "media/cdm/cdm_helpers.h"
#include "media/cdm/supported_cdm_versions.h"
namespace media {
......@@ -39,11 +40,22 @@ cdm::AudioDecoderConfig_1 ToAudioDecoderConfig_1(
}
cdm::VideoDecoderConfig_1 ToVideoDecoderConfig_1(
const cdm::VideoDecoderConfig_2& config) {
const cdm::VideoDecoderConfig_3& config) {
return {config.codec, config.profile, config.format,
config.coded_size, config.extra_data, config.extra_data_size};
}
cdm::VideoDecoderConfig_2 ToVideoDecoderConfig_2(
const cdm::VideoDecoderConfig_3& config) {
return {config.codec,
config.profile,
config.format,
config.coded_size,
config.extra_data,
config.extra_data_size,
config.encryption_scheme};
}
cdm::InputBuffer_1 ToInputBuffer_1(const cdm::InputBuffer_2& buffer) {
return {buffer.data, buffer.data_size,
buffer.key_id, buffer.key_id_size,
......@@ -141,12 +153,12 @@ class CdmWrapper {
virtual cdm::Status InitializeAudioDecoder(
const cdm::AudioDecoderConfig_2& audio_decoder_config) = 0;
virtual cdm::Status InitializeVideoDecoder(
const cdm::VideoDecoderConfig_2& video_decoder_config) = 0;
const cdm::VideoDecoderConfig_3& video_decoder_config) = 0;
virtual void DeinitializeDecoder(cdm::StreamType decoder_type) = 0;
virtual void ResetDecoder(cdm::StreamType decoder_type) = 0;
virtual cdm::Status DecryptAndDecodeFrame(
const cdm::InputBuffer_2& encrypted_buffer,
cdm::VideoFrame* video_frame) = 0;
media::VideoFrameImpl* video_frame) = 0;
virtual cdm::Status DecryptAndDecodeSamples(
const cdm::InputBuffer_2& encrypted_buffer,
cdm::AudioFrames* audio_frames) = 0;
......@@ -268,7 +280,7 @@ class CdmWrapperImpl : public CdmWrapper {
}
cdm::Status InitializeVideoDecoder(
const cdm::VideoDecoderConfig_2& video_decoder_config) override {
const cdm::VideoDecoderConfig_3& video_decoder_config) override {
return cdm_->InitializeVideoDecoder(video_decoder_config);
}
......@@ -280,8 +292,9 @@ class CdmWrapperImpl : public CdmWrapper {
cdm_->ResetDecoder(decoder_type);
}
cdm::Status DecryptAndDecodeFrame(const cdm::InputBuffer_2& encrypted_buffer,
cdm::VideoFrame* video_frame) override {
cdm::Status DecryptAndDecodeFrame(
const cdm::InputBuffer_2& encrypted_buffer,
media::VideoFrameImpl* video_frame) override {
return cdm_->DecryptAndDecodeFrame(encrypted_buffer, video_frame);
}
......@@ -341,7 +354,7 @@ cdm::Status CdmWrapperImpl<9>::InitializeAudioDecoder(
template <>
cdm::Status CdmWrapperImpl<9>::InitializeVideoDecoder(
const cdm::VideoDecoderConfig_2& video_decoder_config) {
const cdm::VideoDecoderConfig_3& video_decoder_config) {
if (!IsEncryptionSchemeSupportedByLegacyCdms(
video_decoder_config.encryption_scheme))
return cdm::kInitializationError;
......@@ -364,7 +377,7 @@ cdm::Status CdmWrapperImpl<9>::Decrypt(
template <>
cdm::Status CdmWrapperImpl<9>::DecryptAndDecodeFrame(
const cdm::InputBuffer_2& encrypted_buffer,
cdm::VideoFrame* video_frame) {
media::VideoFrameImpl* video_frame) {
if (!IsEncryptionSchemeSupportedByLegacyCdms(
encrypted_buffer.encryption_scheme))
return cdm::kDecryptError;
......@@ -385,6 +398,15 @@ cdm::Status CdmWrapperImpl<9>::DecryptAndDecodeSamples(
audio_frames);
}
// Specialization for cdm::ContentDecryptionModule_10 methods.
template <>
cdm::Status CdmWrapperImpl<10>::InitializeVideoDecoder(
const cdm::VideoDecoderConfig_3& video_decoder_config) {
return cdm_->InitializeVideoDecoder(
ToVideoDecoderConfig_2(video_decoder_config));
}
// static
CdmWrapper* CdmWrapper::Create(CreateCdmFunc create_cdm_func,
const char* key_system,
......
......@@ -16,7 +16,7 @@ namespace media {
std::unique_ptr<CdmVideoDecoder> CreateVideoDecoder(
CdmHostProxy* cdm_host_proxy,
const cdm::VideoDecoderConfig_2& config) {
const cdm::VideoDecoderConfig_3& config) {
std::unique_ptr<CdmVideoDecoder> video_decoder;
#if defined(CLEAR_KEY_CDM_USE_LIBVPX_DECODER)
......
......@@ -17,8 +17,10 @@ class CdmHostProxy;
class CdmVideoDecoder {
public:
using CdmVideoFrame = cdm::VideoFrame_2;
virtual ~CdmVideoDecoder() {}
virtual bool Initialize(const cdm::VideoDecoderConfig_2& config) = 0;
virtual bool Initialize(const cdm::VideoDecoderConfig_3& config) = 0;
virtual void Deinitialize() = 0;
virtual void Reset() = 0;
virtual bool is_initialized() const = 0;
......@@ -33,7 +35,7 @@ class CdmVideoDecoder {
virtual cdm::Status DecodeFrame(const uint8_t* compressed_frame,
int32_t compressed_frame_size,
int64_t timestamp,
cdm::VideoFrame* decoded_frame) = 0;
CdmVideoFrame* decoded_frame) = 0;
};
// Initializes the appropriate video decoder based on build flags and the value
......@@ -41,7 +43,7 @@ class CdmVideoDecoder {
// CdmVideoDecoder pointer upon success.
std::unique_ptr<CdmVideoDecoder> CreateVideoDecoder(
CdmHostProxy* cdm_host_proxy,
const cdm::VideoDecoderConfig_2& config);
const cdm::VideoDecoderConfig_3& config);
} // namespace media
......
......@@ -390,6 +390,63 @@ cdm::InputBuffer_2 ToInputBuffer_2(cdm::InputBuffer_1 encrypted_buffer) {
return buffer;
}
// See ISO 23001-8:2016, section 7. Value 2 means "Unspecified".
constexpr cdm::ColorSpace kUnspecifiedColorSpace = {2, 2, 2,
cdm::ColorRange::kInvalid};
cdm::VideoDecoderConfig_3 ToVideoDecoderConfig_3(
cdm::VideoDecoderConfig_1 config) {
// VideoDecoderConfig_1 doesn't specify the encryption scheme, but only
// supports 'cenc' or unencrypted media, so expect encrypted video.
cdm::VideoDecoderConfig_3 result = {
config.codec, config.profile,
config.format, kUnspecifiedColorSpace,
config.coded_size, config.extra_data,
config.extra_data_size, cdm::EncryptionScheme::kCenc};
return result;
}
cdm::VideoDecoderConfig_3 ToVideoDecoderConfig_3(
cdm::VideoDecoderConfig_2 config) {
cdm::VideoDecoderConfig_3 result = {
config.codec, config.profile, config.format,
kUnspecifiedColorSpace, config.coded_size, config.extra_data,
config.extra_data_size, config.encryption_scheme};
return result;
}
// Adapting a cdm::VideoFrame to a cdm::VideoFrame_2 interface. Simply pass all
// calls through except for SetColorSpace() and ColorSpace().
class CdmVideoFrameAdapter : public cdm::VideoFrame_2 {
public:
explicit CdmVideoFrameAdapter(cdm::VideoFrame* video_frame)
: video_frame_(video_frame) {}
// cdm::VideoFrame_2 implementation.
void SetFormat(cdm::VideoFormat format) final {
video_frame_->SetFormat(format);
}
void SetSize(cdm::Size size) final { video_frame_->SetSize(size); }
void SetFrameBuffer(cdm::Buffer* frame_buffer) final {
video_frame_->SetFrameBuffer(frame_buffer);
}
void SetPlaneOffset(cdm::VideoPlane plane, uint32_t offset) final {
video_frame_->SetPlaneOffset(plane, offset);
}
void SetStride(cdm::VideoPlane plane, uint32_t stride) final {
video_frame_->SetStride(plane, stride);
}
void SetTimestamp(int64_t timestamp) final {
video_frame_->SetTimestamp(timestamp);
}
void SetColorSpace(cdm::ColorSpace color_space) final {
// Do nothing since cdm::VideoFrame does not support colorspace.
}
private:
cdm::VideoFrame* const video_frame_ = nullptr;
};
} // namespace
template <typename HostInterface>
......@@ -714,18 +771,16 @@ cdm::Status ClearKeyCdm::InitializeAudioDecoder(
cdm::Status ClearKeyCdm::InitializeVideoDecoder(
const cdm::VideoDecoderConfig_1& video_decoder_config) {
// VideoDecoderConfig_1 doesn't specify the encryption scheme, but only
// supports 'cenc' or unencrypted media, so expect encrypted video.
cdm::VideoDecoderConfig_2 video_config = {
video_decoder_config.codec, video_decoder_config.profile,
video_decoder_config.format, video_decoder_config.coded_size,
video_decoder_config.extra_data, video_decoder_config.extra_data_size,
cdm::EncryptionScheme::kCenc};
return InitializeVideoDecoder(video_config);
return InitializeVideoDecoder(ToVideoDecoderConfig_3(video_decoder_config));
}
cdm::Status ClearKeyCdm::InitializeVideoDecoder(
const cdm::VideoDecoderConfig_2& video_decoder_config) {
return InitializeVideoDecoder(ToVideoDecoderConfig_3(video_decoder_config));
}
cdm::Status ClearKeyCdm::InitializeVideoDecoder(
const cdm::VideoDecoderConfig_3& video_decoder_config) {
if (key_system_ == kExternalClearKeyDecryptOnlyKeySystem ||
key_system_ == kExternalClearKeyCdmProxyKeySystem) {
return cdm::kInitializationError;
......@@ -787,6 +842,13 @@ cdm::Status ClearKeyCdm::DecryptAndDecodeFrame(
cdm::Status ClearKeyCdm::DecryptAndDecodeFrame(
const cdm::InputBuffer_2& encrypted_buffer,
cdm::VideoFrame* decoded_frame) {
CdmVideoFrameAdapter adapted_frame(decoded_frame);
return DecryptAndDecodeFrame(encrypted_buffer, &adapted_frame);
}
cdm::Status ClearKeyCdm::DecryptAndDecodeFrame(
const cdm::InputBuffer_2& encrypted_buffer,
cdm::VideoFrame_2* decoded_frame) {
DVLOG(1) << __func__;
TRACE_EVENT0("media", "ClearKeyCdm::DecryptAndDecodeFrame");
......
......@@ -55,18 +55,26 @@ class ClearKeyCdm : public cdm::ContentDecryptionModule_9,
const cdm::InputBuffer_1& encrypted_buffer,
cdm::AudioFrames* audio_frames) override;
// cdm::ContentDecryptionModule_10/11 implementation.
// cdm::ContentDecryptionModule_10 implementation.
cdm::Status InitializeVideoDecoder(
const cdm::VideoDecoderConfig_2& video_decoder_config) override;
cdm::Status DecryptAndDecodeFrame(const cdm::InputBuffer_2& encrypted_buffer,
cdm::VideoFrame* video_frame) override;
// cdm::ContentDecryptionModule_11 implementation.
cdm::Status InitializeVideoDecoder(
const cdm::VideoDecoderConfig_3& video_decoder_config) override;
cdm::Status DecryptAndDecodeFrame(const cdm::InputBuffer_2& encrypted_buffer,
cdm::VideoFrame_2* video_frame) override;
// Common cdm::ContentDecryptionModule_10/11 implementation.
void Initialize(bool allow_distinctive_identifier,
bool allow_persistent_state,
bool use_hw_secure_codecs) override;
cdm::Status InitializeAudioDecoder(
const cdm::AudioDecoderConfig_2& audio_decoder_config) override;
cdm::Status InitializeVideoDecoder(
const cdm::VideoDecoderConfig_2& video_decoder_config) override;
cdm::Status Decrypt(const cdm::InputBuffer_2& encrypted_buffer,
cdm::DecryptedBlock* decrypted_block) override;
cdm::Status DecryptAndDecodeFrame(const cdm::InputBuffer_2& encrypted_buffer,
cdm::VideoFrame* video_frame) override;
cdm::Status DecryptAndDecodeSamples(
const cdm::InputBuffer_2& encrypted_buffer,
cdm::AudioFrames* audio_frames) override;
......
......@@ -84,7 +84,7 @@ static int CdmVideoCodecProfileToProfileID(cdm::VideoCodecProfile profile) {
}
static void CdmVideoDecoderConfigToAVCodecContext(
const cdm::VideoDecoderConfig_2& config,
const cdm::VideoDecoderConfig_3& config,
AVCodecContext* codec_context) {
codec_context->codec_type = AVMEDIA_TYPE_VIDEO;
codec_context->codec_id = CdmVideoCodecToCodecID(config.codec);
......@@ -132,7 +132,7 @@ FFmpegCdmVideoDecoder::~FFmpegCdmVideoDecoder() {
}
bool FFmpegCdmVideoDecoder::Initialize(
const cdm::VideoDecoderConfig_2& config) {
const cdm::VideoDecoderConfig_3& config) {
DVLOG(1) << "Initialize()";
if (!IsValidOutputConfig(config.format, config.coded_size)) {
......@@ -199,7 +199,7 @@ bool FFmpegCdmVideoDecoder::IsValidOutputConfig(cdm::VideoFormat format,
cdm::Status FFmpegCdmVideoDecoder::DecodeFrame(const uint8_t* compressed_frame,
int32_t compressed_frame_size,
int64_t timestamp,
cdm::VideoFrame* decoded_frame) {
CdmVideoFrame* decoded_frame) {
DVLOG(1) << "DecodeFrame()";
DCHECK(decoded_frame);
......@@ -244,9 +244,8 @@ bool FFmpegCdmVideoDecoder::is_initialized() const {
bool FFmpegCdmVideoDecoder::OnNewFrame(AVFrame* frame) {
// The decoder is in a bad state and not decoding correctly.
// Checking for NULL avoids a crash.
if (!frame->data[cdm::VideoFrame::kYPlane] ||
!frame->data[cdm::VideoFrame::kUPlane] ||
!frame->data[cdm::VideoFrame::kVPlane]) {
if (!frame->data[cdm::kYPlane] || !frame->data[cdm::kUPlane] ||
!frame->data[cdm::kVPlane]) {
LOG(ERROR) << "DecodeFrame(): Video frame has invalid frame data.";
return false;
}
......@@ -256,7 +255,7 @@ bool FFmpegCdmVideoDecoder::OnNewFrame(AVFrame* frame) {
}
bool FFmpegCdmVideoDecoder::CopyAvFrameTo(AVFrame* frame,
cdm::VideoFrame* cdm_video_frame) {
CdmVideoFrame* cdm_video_frame) {
DCHECK(cdm_video_frame);
DCHECK_EQ(frame->format, AV_PIX_FMT_YUV420P);
DCHECK_EQ(frame->width % 2, 0);
......@@ -266,42 +265,37 @@ bool FFmpegCdmVideoDecoder::CopyAvFrameTo(AVFrame* frame,
const int uv_size = y_size / 2;
const int space_required = y_size + (uv_size * 2);
DCHECK(!cdm_video_frame->FrameBuffer());
cdm_video_frame->SetFrameBuffer(cdm_host_proxy_->Allocate(space_required));
if (!cdm_video_frame->FrameBuffer()) {
LOG(ERROR) << "CopyAvFrameTo() ClearKeyCdmHost::Allocate failed.";
auto* frame_buffer = cdm_host_proxy_->Allocate(space_required);
if (!frame_buffer) {
LOG(ERROR) << __func__ << ": Buffer allocation failed.";
return false;
}
cdm_video_frame->FrameBuffer()->SetSize(space_required);
CopyPlane(frame->data[cdm::VideoFrame::kYPlane],
frame->linesize[cdm::VideoFrame::kYPlane], frame->width,
frame->height, frame->width,
cdm_video_frame->FrameBuffer()->Data());
// Prepare and set the frame buffer.
const int uv_stride = frame->width / 2;
const int uv_rows = frame->height / 2;
CopyPlane(frame->data[cdm::VideoFrame::kUPlane],
frame->linesize[cdm::VideoFrame::kUPlane], uv_stride, uv_rows,
uv_stride, cdm_video_frame->FrameBuffer()->Data() + y_size);
CopyPlane(frame->data[cdm::VideoFrame::kVPlane],
frame->linesize[cdm::VideoFrame::kVPlane], uv_stride, uv_rows,
uv_stride,
cdm_video_frame->FrameBuffer()->Data() + y_size + uv_size);
uint8_t* data = frame_buffer->Data();
CopyPlane(frame->data[cdm::kYPlane], frame->linesize[cdm::kYPlane],
frame->width, frame->height, frame->width, data);
CopyPlane(frame->data[cdm::kUPlane], frame->linesize[cdm::kUPlane], uv_stride,
uv_rows, uv_stride, data + y_size);
CopyPlane(frame->data[cdm::kVPlane], frame->linesize[cdm::kVPlane], uv_stride,
uv_rows, uv_stride, data + y_size + uv_size);
frame_buffer->SetSize(space_required);
cdm_video_frame->SetFrameBuffer(frame_buffer);
AVPixelFormat format = static_cast<AVPixelFormat>(frame->format);
cdm_video_frame->SetFormat(AVPixelFormatToCdmVideoFormat(format));
cdm_video_frame->SetSize({frame->width, frame->height});
cdm_video_frame->SetPlaneOffset(cdm::VideoFrame::kYPlane, 0);
cdm_video_frame->SetPlaneOffset(cdm::VideoFrame::kUPlane, y_size);
cdm_video_frame->SetPlaneOffset(cdm::VideoFrame::kVPlane, y_size + uv_size);
cdm_video_frame->SetPlaneOffset(cdm::kYPlane, 0);
cdm_video_frame->SetPlaneOffset(cdm::kUPlane, y_size);
cdm_video_frame->SetPlaneOffset(cdm::kVPlane, y_size + uv_size);
cdm_video_frame->SetStride(cdm::VideoFrame::kYPlane, frame->width);
cdm_video_frame->SetStride(cdm::VideoFrame::kUPlane, uv_stride);
cdm_video_frame->SetStride(cdm::VideoFrame::kVPlane, uv_stride);
cdm_video_frame->SetStride(cdm::kYPlane, frame->width);
cdm_video_frame->SetStride(cdm::kUPlane, uv_stride);
cdm_video_frame->SetStride(cdm::kVPlane, uv_stride);
cdm_video_frame->SetTimestamp(frame->reordered_opaque);
......
......@@ -29,13 +29,13 @@ class FFmpegCdmVideoDecoder : public CdmVideoDecoder {
~FFmpegCdmVideoDecoder() override;
// CdmVideoDecoder implementation.
bool Initialize(const cdm::VideoDecoderConfig_2& config) override;
bool Initialize(const cdm::VideoDecoderConfig_3& config) override;
void Deinitialize() override;
void Reset() override;
cdm::Status DecodeFrame(const uint8_t* compressed_frame,
int32_t compressed_frame_size,
int64_t timestamp,
cdm::VideoFrame* decoded_frame) override;
CdmVideoFrame* decoded_frame) override;
bool is_initialized() const override;
// Returns true when |format| and |data_size| specify a supported video
......@@ -48,7 +48,7 @@ class FFmpegCdmVideoDecoder : public CdmVideoDecoder {
// Allocates storage, then copies video frame stored in |frame| to
// |cdm_video_frame|. Returns true when allocation and copy succeed.
bool CopyAvFrameTo(AVFrame* frame, cdm::VideoFrame* cdm_video_frame);
bool CopyAvFrameTo(AVFrame* frame, CdmVideoFrame* cdm_video_frame);
void ReleaseFFmpegResources();
......
......@@ -26,7 +26,7 @@ LibvpxCdmVideoDecoder::~LibvpxCdmVideoDecoder() {
}
bool LibvpxCdmVideoDecoder::Initialize(
const cdm::VideoDecoderConfig_2& config) {
const cdm::VideoDecoderConfig_3& config) {
DVLOG(1) << "Initialize()";
if (!IsValidOutputConfig(config.format, config.coded_size)) {
......@@ -89,7 +89,7 @@ bool LibvpxCdmVideoDecoder::IsValidOutputConfig(cdm::VideoFormat format,
cdm::Status LibvpxCdmVideoDecoder::DecodeFrame(const uint8_t* compressed_frame,
int32_t compressed_frame_size,
int64_t timestamp,
cdm::VideoFrame* decoded_frame) {
CdmVideoFrame* decoded_frame) {
DVLOG(3) << __func__ << ": frame size = " << compressed_frame_size;
DCHECK(decoded_frame);
......@@ -128,7 +128,7 @@ bool LibvpxCdmVideoDecoder::is_initialized() const {
return is_initialized_;
}
bool LibvpxCdmVideoDecoder::CopyVpxImageTo(cdm::VideoFrame* cdm_video_frame) {
bool LibvpxCdmVideoDecoder::CopyVpxImageTo(CdmVideoFrame* cdm_video_frame) {
DCHECK(cdm_video_frame);
DCHECK_EQ(vpx_image_->fmt, VPX_IMG_FMT_I420);
DCHECK_EQ(vpx_image_->d_w % 2, 0U);
......@@ -140,20 +140,19 @@ bool LibvpxCdmVideoDecoder::CopyVpxImageTo(cdm::VideoFrame* cdm_video_frame) {
const int v_size = vpx_image_->stride[VPX_PLANE_V] * uv_rows;
const int space_required = y_size + u_size + v_size;
DCHECK(!cdm_video_frame->FrameBuffer());
cdm_video_frame->SetFrameBuffer(cdm_host_proxy_->Allocate(space_required));
if (!cdm_video_frame->FrameBuffer()) {
LOG(ERROR) << "CopyVpxImageTo() CdmHost::Allocate failed.";
auto* frame_buffer = cdm_host_proxy_->Allocate(space_required);
if (!frame_buffer) {
LOG(ERROR) << __func__ << ": Buffer allocation failed.";
return false;
}
cdm_video_frame->FrameBuffer()->SetSize(space_required);
memcpy(cdm_video_frame->FrameBuffer()->Data(),
vpx_image_->planes[VPX_PLANE_Y], y_size);
memcpy(cdm_video_frame->FrameBuffer()->Data() + y_size,
vpx_image_->planes[VPX_PLANE_U], u_size);
memcpy(cdm_video_frame->FrameBuffer()->Data() + y_size + u_size,
vpx_image_->planes[VPX_PLANE_V], v_size);
// Prepare and set the frame buffer.
uint8_t* data = frame_buffer->Data();
memcpy(data, vpx_image_->planes[VPX_PLANE_Y], y_size);
memcpy(data + y_size, vpx_image_->planes[VPX_PLANE_U], u_size);
memcpy(data + y_size + u_size, vpx_image_->planes[VPX_PLANE_V], v_size);
frame_buffer->SetSize(space_required);
cdm_video_frame->SetFrameBuffer(frame_buffer);
cdm_video_frame->SetFormat(cdm::kYv12);
......@@ -162,16 +161,13 @@ bool LibvpxCdmVideoDecoder::CopyVpxImageTo(cdm::VideoFrame* cdm_video_frame) {
video_frame_size.height = vpx_image_->d_h;
cdm_video_frame->SetSize(video_frame_size);
cdm_video_frame->SetPlaneOffset(cdm::VideoFrame::kYPlane, 0);
cdm_video_frame->SetPlaneOffset(cdm::VideoFrame::kUPlane, y_size);
cdm_video_frame->SetPlaneOffset(cdm::VideoFrame::kVPlane, y_size + u_size);
cdm_video_frame->SetPlaneOffset(cdm::kYPlane, 0);
cdm_video_frame->SetPlaneOffset(cdm::kUPlane, y_size);
cdm_video_frame->SetPlaneOffset(cdm::kVPlane, y_size + u_size);
cdm_video_frame->SetStride(cdm::VideoFrame::kYPlane,
vpx_image_->stride[VPX_PLANE_Y]);
cdm_video_frame->SetStride(cdm::VideoFrame::kUPlane,
vpx_image_->stride[VPX_PLANE_U]);
cdm_video_frame->SetStride(cdm::VideoFrame::kVPlane,
vpx_image_->stride[VPX_PLANE_V]);
cdm_video_frame->SetStride(cdm::kYPlane, vpx_image_->stride[VPX_PLANE_Y]);
cdm_video_frame->SetStride(cdm::kUPlane, vpx_image_->stride[VPX_PLANE_U]);
cdm_video_frame->SetStride(cdm::kVPlane, vpx_image_->stride[VPX_PLANE_V]);
return true;
}
......
......@@ -25,13 +25,13 @@ class LibvpxCdmVideoDecoder : public CdmVideoDecoder {
~LibvpxCdmVideoDecoder() override;
// CdmVideoDecoder implementation.
bool Initialize(const cdm::VideoDecoderConfig_2& config) override;
bool Initialize(const cdm::VideoDecoderConfig_3& config) override;
void Deinitialize() override;
void Reset() override;
cdm::Status DecodeFrame(const uint8_t* compressed_frame,
int32_t compressed_frame_size,
int64_t timestamp,
cdm::VideoFrame* decoded_frame) override;
CdmVideoFrame* decoded_frame) override;
bool is_initialized() const override;
// Returns true when |format| and |data_size| specify a supported video
......@@ -42,7 +42,7 @@ class LibvpxCdmVideoDecoder : public CdmVideoDecoder {
private:
// Allocates storage, then copies video frame stored in |vpx_image_| to
// |cdm_video_frame|. Returns true when allocation and copy succeed.
bool CopyVpxImageTo(cdm::VideoFrame* cdm_video_frame);
bool CopyVpxImageTo(CdmVideoFrame* cdm_video_frame);
bool is_initialized_ = false;
......
......@@ -53,6 +53,22 @@ class MockLibraryCdm : public cdm::ContentDecryptionModule_9,
cdm::Status(const cdm::InputBuffer_1& encrypted_buffer,
cdm::AudioFrames* audio_frames));
// cdm::ContentDecryptionModule_10 implementation.
MOCK_METHOD1(
InitializeVideoDecoder,
cdm::Status(const cdm::VideoDecoderConfig_2& video_decoder_config));
MOCK_METHOD2(DecryptAndDecodeFrame,
cdm::Status(const cdm::InputBuffer_2& encrypted_buffer,
cdm::VideoFrame* video_frame));
// cdm::ContentDecryptionModule_11 implementation.
MOCK_METHOD1(
InitializeVideoDecoder,
cdm::Status(const cdm::VideoDecoderConfig_3& video_decoder_config));
MOCK_METHOD2(DecryptAndDecodeFrame,
cdm::Status(const cdm::InputBuffer_2& encrypted_buffer,
cdm::VideoFrame_2* video_frame));
// cdm::ContentDecryptionModule_10/11 implementation.
void Initialize(bool allow_distinctive_identifier,
bool allow_persistent_state,
......@@ -60,15 +76,9 @@ class MockLibraryCdm : public cdm::ContentDecryptionModule_9,
MOCK_METHOD1(
InitializeAudioDecoder,
cdm::Status(const cdm::AudioDecoderConfig_2& audio_decoder_config));
MOCK_METHOD1(
InitializeVideoDecoder,
cdm::Status(const cdm::VideoDecoderConfig_2& video_decoder_config));
MOCK_METHOD2(Decrypt,
cdm::Status(const cdm::InputBuffer_2& encrypted_buffer,
cdm::DecryptedBlock* decrypted_block));
MOCK_METHOD2(DecryptAndDecodeFrame,
cdm::Status(const cdm::InputBuffer_2& encrypted_buffer,
cdm::VideoFrame* video_frame));
MOCK_METHOD2(DecryptAndDecodeSamples,
cdm::Status(const cdm::InputBuffer_2& encrypted_buffer,
cdm::AudioFrames* audio_frames));
......
......@@ -32,12 +32,14 @@ class SimpleCdmVideoFrame : public VideoFrameImpl {
scoped_refptr<media::VideoFrame> frame =
media::VideoFrame::WrapExternalYuvData(
PIXEL_FORMAT_I420, frame_size, gfx::Rect(frame_size), natural_size,
Stride(kYPlane), Stride(kUPlane), Stride(kVPlane),
buffer->Data() + PlaneOffset(kYPlane),
buffer->Data() + PlaneOffset(kUPlane),
buffer->Data() + PlaneOffset(kVPlane),
Stride(cdm::kYPlane), Stride(cdm::kUPlane), Stride(cdm::kVPlane),
buffer->Data() + PlaneOffset(cdm::kYPlane),
buffer->Data() + PlaneOffset(cdm::kUPlane),
buffer->Data() + PlaneOffset(cdm::kVPlane),
base::TimeDelta::FromMicroseconds(Timestamp()));
frame->set_color_space(MediaColorSpace().ToGfxColorSpace());
// The FrameBuffer needs to remain around until |frame| is destroyed.
frame->AddDestructionObserver(
base::Bind(&cdm::Buffer::Destroy, base::Unretained(buffer)));
......
......@@ -145,10 +145,13 @@ class MojoCdmVideoFrame : public VideoFrameImpl {
media::MojoSharedBufferVideoFrame::Create(
CdmVideoFormatToVideoPixelFormat(Format()), frame_size,
gfx::Rect(frame_size), natural_size, std::move(handle), buffer_size,
PlaneOffset(kYPlane), PlaneOffset(kUPlane), PlaneOffset(kVPlane),
Stride(kYPlane), Stride(kUPlane), Stride(kVPlane),
PlaneOffset(cdm::kYPlane), PlaneOffset(cdm::kUPlane),
PlaneOffset(cdm::kVPlane), Stride(cdm::kYPlane),
Stride(cdm::kUPlane), Stride(cdm::kVPlane),
base::TimeDelta::FromMicroseconds(Timestamp()));
frame->set_color_space(MediaColorSpace().ToGfxColorSpace());
// |frame| could fail to be created if the memory can't be mapped into
// this address space.
if (frame)
......
......@@ -95,15 +95,15 @@ TEST_F(MojoCdmAllocatorTest, CreateCdmVideoFrame) {
std::unique_ptr<VideoFrameImpl> video_frame = CreateCdmVideoFrame();
video_frame->SetFormat(cdm::kI420);
video_frame->SetSize({kWidth, kHeight});
video_frame->SetStride(VideoFrameImpl::kYPlane,
static_cast<uint32_t>(VideoFrame::RowBytes(
VideoFrame::kYPlane, kFormat, kWidth)));
video_frame->SetStride(VideoFrameImpl::kUPlane,
static_cast<uint32_t>(VideoFrame::RowBytes(
VideoFrame::kUPlane, kFormat, kWidth)));
video_frame->SetStride(VideoFrameImpl::kVPlane,
static_cast<uint32_t>(VideoFrame::RowBytes(
VideoFrame::kVPlane, kFormat, kWidth)));
video_frame->SetStride(
cdm::kYPlane, static_cast<uint32_t>(
VideoFrame::RowBytes(cdm::kYPlane, kFormat, kWidth)));
video_frame->SetStride(
cdm::kUPlane, static_cast<uint32_t>(
VideoFrame::RowBytes(cdm::kUPlane, kFormat, kWidth)));
video_frame->SetStride(
cdm::kVPlane, static_cast<uint32_t>(
VideoFrame::RowBytes(cdm::kVPlane, kFormat, kWidth)));
EXPECT_EQ(nullptr, video_frame->FrameBuffer());
// Now create a buffer to hold the frame and assign it to the VideoFrameImpl.
......
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