Commit 5fa4f0df authored by Xiaohan Wang's avatar Xiaohan Wang Committed by Commit Bot

media: Add high bit depth support to library CDMs

- Update cdm type converters to support high bit depth video formats.
- Update ClearKeyCdm to support more video formats.
- Add a new MojoSharedBufferVideoFrameTest to test high bit depth video
  frames.
- Add a browser test to test end-to-end playback of encrypted 10-bit VP9
  video.

Bug: 707127
Test: New tests added.
Change-Id: I2459454a36b44c0427458c903237d3872acfaa54
Reviewed-on: https://chromium-review.googlesource.com/c/1261970
Commit-Queue: Xiaohan Wang <xhwang@chromium.org>
Reviewed-by: default avatarDale Curtis <dalecurtis@chromium.org>
Reviewed-by: default avatarJohn Rummell <jrummell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#597366}
parent 530ad69b
...@@ -555,6 +555,12 @@ IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoClearAudio_WebM_Opus) { ...@@ -555,6 +555,12 @@ IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoClearAudio_WebM_Opus) {
TestSimplePlayback("bear-320x240-opus-av_enc-v.webm", kWebMOpusAudioVp9Video); TestSimplePlayback("bear-320x240-opus-av_enc-v.webm", kWebMOpusAudioVp9Video);
} }
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VP9Profile2Video_WebM) {
// TODO(crbug.com/707127): Support VP9 Profile2 query and update mime type.
TestSimplePlayback("bear-320x240-v-vp9_profile2_subsample_cenc-v.webm",
kWebMVp9VideoOnly);
}
// TODO(xhwang): Test is flaky. https://crbug.com/890124. // TODO(xhwang): Test is flaky. https://crbug.com/890124.
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, IN_PROC_BROWSER_TEST_P(EncryptedMediaTest,
DISABLED_Playback_Multiple_VideoAudio_WebM) { DISABLED_Playback_Multiple_VideoAudio_WebM) {
...@@ -583,6 +589,17 @@ IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoOnly_MP4_VP9) { ...@@ -583,6 +589,17 @@ IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoOnly_MP4_VP9) {
TestSimplePlayback("bear-320x240-v_frag-vp9-cenc.mp4", kMp4Vp9VideoOnly); TestSimplePlayback("bear-320x240-v_frag-vp9-cenc.mp4", kMp4Vp9VideoOnly);
} }
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoOnly_MP4_VP9Profile2) {
// MP4 without MSE is not support yet, http://crbug.com/170793.
if (CurrentSourceType() != SrcType::MSE) {
DVLOG(0) << "Skipping test; Can only play MP4 encrypted streams by MSE.";
return;
}
// TODO(crbug.com/707127): Support VP9 Profile2 query and update mime type.
TestSimplePlayback("bear-320x240-v-vp9_profile2_subsample_cenc-v.mp4",
kMp4Vp9VideoOnly);
}
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, InvalidResponseKeyError) { IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, InvalidResponseKeyError) {
RunInvalidResponseTest(); RunInvalidResponseTest();
} }
......
...@@ -272,6 +272,15 @@ IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoClearAudio_WebM_Opus) { ...@@ -272,6 +272,15 @@ IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoClearAudio_WebM_Opus) {
TestSimplePlayback("bear-320x240-opus-av_enc-v.webm", kWebMOpusAudioVp9Video); TestSimplePlayback("bear-320x240-opus-av_enc-v.webm", kWebMOpusAudioVp9Video);
} }
// TODO(crbug.com/707127): Decide when it's supported on Android. Also support
// VP9 Profile2 query and update the mime type.
#if !defined(OS_ANDROID)
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VP9Profile2Video_WebM) {
TestSimplePlayback("bear-320x240-v-vp9_profile2_subsample_cenc-v.webm",
kWebMVp9VideoOnly);
}
#endif
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioOnly_MP4_FLAC) { IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioOnly_MP4_FLAC) {
RunMultipleFileTest(std::string(), std::string(), "bear-flac-cenc.mp4", RunMultipleFileTest(std::string(), std::string(), "bear-flac-cenc.mp4",
kMp4FlacAudioOnly, media::kEnded); kMp4FlacAudioOnly, media::kEnded);
...@@ -286,6 +295,20 @@ IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoOnly_MP4_VP9) { ...@@ -286,6 +295,20 @@ IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoOnly_MP4_VP9) {
TestSimplePlayback("bear-320x240-v_frag-vp9-cenc.mp4", kMp4Vp9VideoOnly); TestSimplePlayback("bear-320x240-v_frag-vp9-cenc.mp4", kMp4Vp9VideoOnly);
} }
// TODO(crbug.com/707127): Decide when it's supported on Android. Also support
// VP9 Profile2 query and update the mime type.
#if !defined(OS_ANDROID)
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoOnly_MP4_VP9Profile2) {
// MP4 without MSE is not support yet, http://crbug.com/170793.
if (CurrentSourceType() != SrcType::MSE) {
DVLOG(0) << "Skipping test; Can only play MP4 encrypted streams by MSE.";
return;
}
TestSimplePlayback("bear-320x240-v-vp9_profile2_subsample_cenc-v.mp4",
kMp4Vp9VideoOnly);
}
#endif
// Strictly speaking this is not an "encrypted" media test. Keep it here for // Strictly speaking this is not an "encrypted" media test. Keep it here for
// completeness. // completeness.
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, ConfigChangeVideo_ClearToClear) { IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, ConfigChangeVideo_ClearToClear) {
......
...@@ -82,16 +82,16 @@ bool AudioDecoderConfig::Matches(const AudioDecoderConfig& config) const { ...@@ -82,16 +82,16 @@ bool AudioDecoderConfig::Matches(const AudioDecoderConfig& config) const {
std::string AudioDecoderConfig::AsHumanReadableString() const { std::string AudioDecoderConfig::AsHumanReadableString() const {
std::ostringstream s; std::ostringstream s;
s << "codec: " << GetCodecName(codec()) s << "codec: " << GetCodecName(codec())
<< " bytes_per_channel: " << bytes_per_channel() << ", bytes_per_channel: " << bytes_per_channel()
<< " channel_layout: " << channel_layout() << " channels: " << channels() << ", channel_layout: " << channel_layout() << ", channels: " << channels()
<< " samples_per_second: " << samples_per_second() << ", samples_per_second: " << samples_per_second()
<< " sample_format: " << sample_format() << ", sample_format: " << sample_format()
<< " bytes_per_frame: " << bytes_per_frame() << ", bytes_per_frame: " << bytes_per_frame()
<< " seek_preroll: " << seek_preroll().InMilliseconds() << "ms" << ", seek_preroll: " << seek_preroll().InMicroseconds() << "us"
<< " codec_delay: " << codec_delay() << " has extra data? " << ", codec_delay: " << codec_delay()
<< (extra_data().empty() ? "false" : "true") << ", has extra data: " << (extra_data().empty() ? "false" : "true")
<< " encryption scheme: " << encryption_scheme() << ", encryption scheme: " << encryption_scheme()
<< " discard decoder delay? " << ", discard decoder delay: "
<< (should_discard_decoder_delay() ? "true" : "false"); << (should_discard_decoder_delay() ? "true" : "false");
return s.str(); return s.str();
} }
......
...@@ -160,16 +160,16 @@ bool VideoDecoderConfig::Matches(const VideoDecoderConfig& config) const { ...@@ -160,16 +160,16 @@ bool VideoDecoderConfig::Matches(const VideoDecoderConfig& config) const {
std::string VideoDecoderConfig::AsHumanReadableString() const { std::string VideoDecoderConfig::AsHumanReadableString() const {
std::ostringstream s; std::ostringstream s;
s << "codec: " << GetCodecName(codec()) << " format: " << format() s << "codec: " << GetCodecName(codec()) << ", format: " << format()
<< " profile: " << GetProfileName(profile()) << " coded size: [" << ", profile: " << GetProfileName(profile()) << ", coded size: ["
<< coded_size().width() << "," << coded_size().height() << "]" << coded_size().width() << "," << coded_size().height() << "]"
<< " visible rect: [" << visible_rect().x() << "," << visible_rect().y() << ", visible rect: [" << visible_rect().x() << "," << visible_rect().y()
<< "," << visible_rect().width() << "," << visible_rect().height() << "]" << "," << visible_rect().width() << "," << visible_rect().height() << "]"
<< " natural size: [" << natural_size().width() << "," << ", natural size: [" << natural_size().width() << ","
<< natural_size().height() << "]" << natural_size().height() << "]"
<< " has extra data? " << (extra_data().empty() ? "false" : "true") << ", has extra data: " << (extra_data().empty() ? "false" : "true")
<< " encryption scheme: " << encryption_scheme() << ", encryption scheme: " << encryption_scheme()
<< " rotation: " << VideoRotationToString(video_rotation()); << ", rotation: " << VideoRotationToString(video_rotation());
return s.str(); return s.str();
} }
......
...@@ -68,6 +68,11 @@ std::string VideoPixelFormatToString(VideoPixelFormat format) { ...@@ -68,6 +68,11 @@ std::string VideoPixelFormatToString(VideoPixelFormat format) {
return ""; return "";
} }
std::ostream& operator<<(std::ostream& os, VideoPixelFormat format) {
os << VideoPixelFormatToString(format);
return os;
}
std::string FourccToString(uint32_t fourcc) { std::string FourccToString(uint32_t fourcc) {
std::string result = "0000"; std::string result = "0000";
for (size_t i = 0; i < 4; ++i, fourcc >>= 8) { for (size_t i = 0; i < 4; ++i, fourcc >>= 8) {
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define MEDIA_BASE_VIDEO_TYPES_H_ #define MEDIA_BASE_VIDEO_TYPES_H_
#include <stdint.h> #include <stdint.h>
#include <iosfwd>
#include <string> #include <string>
#include "build/build_config.h" #include "build/build_config.h"
...@@ -88,6 +89,10 @@ enum ColorSpace { ...@@ -88,6 +89,10 @@ enum ColorSpace {
// Returns the name of a Format as a string. // Returns the name of a Format as a string.
MEDIA_EXPORT std::string VideoPixelFormatToString(VideoPixelFormat format); MEDIA_EXPORT std::string VideoPixelFormatToString(VideoPixelFormat format);
// Stream operator of Format for logging etc.
MEDIA_EXPORT std::ostream& operator<<(std::ostream& os,
VideoPixelFormat format);
// Returns human readable fourcc string. // Returns human readable fourcc string.
// If any of the four characters is non-printable, it outputs // If any of the four characters is non-printable, it outputs
// "0x<32-bit integer in hex>", e.g. FourccToString(0x66616b00) returns // "0x<32-bit integer in hex>", e.g. FourccToString(0x66616b00) returns
......
...@@ -463,8 +463,15 @@ void CdmAdapter::InitializeAudioDecoder(const AudioDecoderConfig& config, ...@@ -463,8 +463,15 @@ void CdmAdapter::InitializeAudioDecoder(const AudioDecoderConfig& config,
DCHECK(task_runner_->BelongsToCurrentThread()); DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(!audio_init_cb_); DCHECK(!audio_init_cb_);
cdm::Status status = auto cdm_config = ToCdmAudioDecoderConfig(config);
cdm_->InitializeAudioDecoder(ToCdmAudioDecoderConfig(config)); if (cdm_config.codec == cdm::kUnknownAudioCodec) {
DVLOG(1) << __func__
<< ": Unsupported config: " << config.AsHumanReadableString();
init_cb.Run(false);
return;
}
cdm::Status status = cdm_->InitializeAudioDecoder(cdm_config);
if (status != cdm::kSuccess && status != cdm::kDeferredInitialization) { if (status != cdm::kSuccess && status != cdm::kDeferredInitialization) {
DCHECK(status == cdm::kInitializationError); DCHECK(status == cdm::kInitializationError);
DVLOG(1) << __func__ << ": status = " << status; DVLOG(1) << __func__ << ": status = " << status;
...@@ -490,8 +497,18 @@ void CdmAdapter::InitializeVideoDecoder(const VideoDecoderConfig& config, ...@@ -490,8 +497,18 @@ void CdmAdapter::InitializeVideoDecoder(const VideoDecoderConfig& config,
DCHECK(task_runner_->BelongsToCurrentThread()); DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(!video_init_cb_); DCHECK(!video_init_cb_);
cdm::Status status = // cdm::kUnknownVideoCodecProfile and cdm::kUnknownVideoFormat are not checked
cdm_->InitializeVideoDecoder(ToCdmVideoDecoderConfig(config)); // because it's possible the container has wrong information or the demuxer
// doesn't parse them correctly.
auto cdm_config = ToCdmVideoDecoderConfig(config);
if (cdm_config.codec == cdm::kUnknownVideoCodec) {
DVLOG(1) << __func__
<< ": Unsupported config: " << config.AsHumanReadableString();
init_cb.Run(false);
return;
}
cdm::Status status = cdm_->InitializeVideoDecoder(cdm_config);
if (status != cdm::kSuccess && status != cdm::kDeferredInitialization) { if (status != cdm::kSuccess && status != cdm::kDeferredInitialization) {
DCHECK(status == cdm::kInitializationError); DCHECK(status == cdm::kInitializationError);
DVLOG(1) << __func__ << ": status = " << status; DVLOG(1) << __func__ << ": status = " << status;
......
...@@ -481,13 +481,30 @@ VideoCodecProfile ToMediaVideoCodecProfile(cdm::VideoCodecProfile profile) { ...@@ -481,13 +481,30 @@ VideoCodecProfile ToMediaVideoCodecProfile(cdm::VideoCodecProfile profile) {
return VIDEO_CODEC_PROFILE_UNKNOWN; return VIDEO_CODEC_PROFILE_UNKNOWN;
} }
// TODO(xhwang): Support all media video formats.
cdm::VideoFormat ToCdmVideoFormat(VideoPixelFormat format) { cdm::VideoFormat ToCdmVideoFormat(VideoPixelFormat format) {
switch (format) { switch (format) {
case PIXEL_FORMAT_YV12: case PIXEL_FORMAT_YV12:
return cdm::kYv12; return cdm::kYv12;
case PIXEL_FORMAT_I420: case PIXEL_FORMAT_I420:
return cdm::kI420; return cdm::kI420;
case PIXEL_FORMAT_YUV420P9:
return cdm::kYUV420P9;
case PIXEL_FORMAT_YUV420P10:
return cdm::kYUV420P10;
case PIXEL_FORMAT_YUV422P9:
return cdm::kYUV422P9;
case PIXEL_FORMAT_YUV422P10:
return cdm::kYUV422P10;
case PIXEL_FORMAT_YUV444P9:
return cdm::kYUV444P9;
case PIXEL_FORMAT_YUV444P10:
return cdm::kYUV444P10;
case PIXEL_FORMAT_YUV420P12:
return cdm::kYUV420P12;
case PIXEL_FORMAT_YUV422P12:
return cdm::kYUV422P12;
case PIXEL_FORMAT_YUV444P12:
return cdm::kYUV444P12;
default: default:
DVLOG(1) << "Unsupported VideoPixelFormat " << format; DVLOG(1) << "Unsupported VideoPixelFormat " << format;
return cdm::kUnknownVideoFormat; return cdm::kUnknownVideoFormat;
...@@ -500,6 +517,24 @@ VideoPixelFormat ToMediaVideoFormat(cdm::VideoFormat format) { ...@@ -500,6 +517,24 @@ VideoPixelFormat ToMediaVideoFormat(cdm::VideoFormat format) {
return PIXEL_FORMAT_YV12; return PIXEL_FORMAT_YV12;
case cdm::kI420: case cdm::kI420:
return PIXEL_FORMAT_I420; return PIXEL_FORMAT_I420;
case cdm::kYUV420P9:
return PIXEL_FORMAT_YUV420P9;
case cdm::kYUV420P10:
return PIXEL_FORMAT_YUV420P10;
case cdm::kYUV422P9:
return PIXEL_FORMAT_YUV422P9;
case cdm::kYUV422P10:
return PIXEL_FORMAT_YUV422P10;
case cdm::kYUV444P9:
return PIXEL_FORMAT_YUV444P9;
case cdm::kYUV444P10:
return PIXEL_FORMAT_YUV444P10;
case cdm::kYUV420P12:
return PIXEL_FORMAT_YUV420P12;
case cdm::kYUV422P12:
return PIXEL_FORMAT_YUV422P12;
case cdm::kYUV444P12:
return PIXEL_FORMAT_YUV444P12;
default: default:
DVLOG(1) << "Unsupported cdm::VideoFormat " << format; DVLOG(1) << "Unsupported cdm::VideoFormat " << format;
return PIXEL_FORMAT_UNKNOWN; return PIXEL_FORMAT_UNKNOWN;
......
...@@ -61,63 +61,69 @@ bool ToCdmVideoFrame(const VideoFrame& video_frame, ...@@ -61,63 +61,69 @@ bool ToCdmVideoFrame(const VideoFrame& video_frame,
CdmVideoDecoder::CdmVideoFrame* cdm_video_frame) { CdmVideoDecoder::CdmVideoFrame* cdm_video_frame) {
DCHECK(cdm_video_frame); DCHECK(cdm_video_frame);
// TODO(xhwang): Support more pixel formats. if (!video_frame.IsMappable()) {
if (!video_frame.IsMappable() || DVLOG(1) << "VideoFrame is not mappable";
video_frame.format() != media::PIXEL_FORMAT_I420) {
DVLOG(1) << "VideoFrame is not mappable or has unsupported format";
return false; return false;
} }
const int width = video_frame.coded_size().width(); if (!IsYuvPlanar(video_frame.format())) {
const int height = video_frame.coded_size().height(); DVLOG(1) << "Only YUV planar format supported";
DCHECK_EQ(width % 2, 0); return false;
DCHECK_EQ(height % 2, 0); }
const int width_uv = width / 2;
const int height_uv = height / 2; if (VideoFrame::NumPlanes(video_frame.format()) != 3u) {
const int dst_stride_y = width; DVLOG(1) << "Only 3-plane format supported";
const int dst_stride_uv = width_uv; return false;
const int y_size = dst_stride_y * height; }
const int uv_size = dst_stride_uv * height_uv;
const int space_required = y_size + (uv_size * 2);
auto cdm_video_format = ToCdmVideoFormat(video_frame.format());
if (cdm_video_format == cdm::kUnknownVideoFormat) {
DVLOG(1) << "VideoFrame has unsupported format: " << video_frame.format();
return false;
}
// Get required allocation size for a tightly packed frame.
auto space_required = VideoFrame::AllocationSize(video_frame.format(),
video_frame.coded_size());
auto* buffer = cdm_host_proxy->Allocate(space_required); auto* buffer = cdm_host_proxy->Allocate(space_required);
if (!buffer) { if (!buffer) {
LOG(ERROR) << __func__ << ": Buffer allocation failed."; LOG(ERROR) << __func__ << ": Buffer allocation failed.";
return false; return false;
} }
// Values from the source |video_frame|. buffer->SetSize(base::checked_cast<uint32_t>(space_required));
const auto* src_y = video_frame.data(VideoFrame::kYPlane);
const auto* src_u = video_frame.data(VideoFrame::kUPlane);
const auto* src_v = video_frame.data(VideoFrame::kVPlane);
auto src_stride_y = video_frame.stride(VideoFrame::kYPlane);
auto src_stride_u = video_frame.stride(VideoFrame::kUPlane);
auto src_stride_v = video_frame.stride(VideoFrame::kVPlane);
// Values for the destinaton frame buffer.
uint8_t* dst_y = buffer->Data();
uint8_t* dst_u = dst_y + y_size;
uint8_t* dst_v = dst_u + uv_size;
// Actually copy video frame planes.
using libyuv::CopyPlane;
CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
CopyPlane(src_u, src_stride_u, dst_u, dst_stride_uv, width_uv, height_uv);
CopyPlane(src_v, src_stride_v, dst_v, dst_stride_uv, width_uv, height_uv);
buffer->SetSize(space_required);
cdm_video_frame->SetFrameBuffer(buffer); cdm_video_frame->SetFrameBuffer(buffer);
cdm_video_frame->SetFormat(cdm_video_format);
cdm_video_frame->SetFormat(cdm::kI420); cdm_video_frame->SetSize(
cdm_video_frame->SetSize({width, height}); {video_frame.coded_size().width(), video_frame.coded_size().height()});
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::kYPlane, dst_stride_y);
cdm_video_frame->SetStride(cdm::kUPlane, dst_stride_uv);
cdm_video_frame->SetStride(cdm::kVPlane, dst_stride_uv);
cdm_video_frame->SetTimestamp(video_frame.timestamp().InMicroseconds()); cdm_video_frame->SetTimestamp(video_frame.timestamp().InMicroseconds());
// TODO(crbug.com/707127): Set ColorSpace here. It's not trivial to convert
// a gfx::ColorSpace (from VideoFrame) to another other ColorSpace like
// cdm::ColorSpace.
static_assert(VideoFrame::kYPlane == cdm::kYPlane && cdm::kYPlane == 0, "");
static_assert(VideoFrame::kUPlane == cdm::kUPlane && cdm::kUPlane == 1, "");
static_assert(VideoFrame::kVPlane == cdm::kVPlane && cdm::kVPlane == 2, "");
uint8_t* dst = buffer->Data();
uint32_t offset = 0;
for (int plane = 0; plane < 3; ++plane) {
const uint8_t* src = video_frame.data(plane);
int src_stride = video_frame.stride(plane);
int row_bytes = video_frame.row_bytes(plane);
int rows = video_frame.rows(plane);
auto cdm_plane = static_cast<cdm::VideoPlane>(plane);
cdm_video_frame->SetPlaneOffset(cdm_plane, offset);
// Since it's tightly packed, the stride is the same as row bytes.
cdm_video_frame->SetStride(cdm_plane, row_bytes);
libyuv::CopyPlane(src, src_stride, dst, row_bytes, row_bytes, rows);
dst += row_bytes * rows;
offset += row_bytes * rows;
}
DCHECK_GE(space_required, offset) << ": Space mismatch";
return true; return true;
} }
......
...@@ -267,7 +267,8 @@ Encrypted Bear video with VP9 codec (profile 2) in WebM container, using key ID ...@@ -267,7 +267,8 @@ Encrypted Bear video with VP9 codec (profile 2) in WebM container, using key ID
[1] and key [2]. Codec string: `vp09.02.10.10.01.02.02.02.00`. [1] and key [2]. Codec string: `vp09.02.10.10.01.02.02.02.00`.
Generated with [Shaka Packager] at 4ba5bec66054cfd4af13c07ac62a97f1a1a2e5f9: Generated with [Shaka Packager] at 4ba5bec66054cfd4af13c07ac62a97f1a1a2e5f9:
``` ```
packager in=bear-320x240-vp9_profile2.webm,stream=video,out=bear-320x240-v-vp9_profile2_subsample_cenc-v.web--enable_fixed_key_encryption --key_id 30313233343536373839303132333435 packager in=bear-320x240-vp9_profile2.webm,stream=video,out=bear-320x240-v-vp9_profile2_subsample_cenc-v.webm
--enable_fixed_key_encryption --key_id 30313233343536373839303132333435
--key ebdd62f16814d27b68ef122afce4ae3c --clear_lead 0 --key ebdd62f16814d27b68ef122afce4ae3c --clear_lead 0
--pssh 0000003470737368010000001077EFECC0B24D02ACE33C1E52E2FB4B000000013031323334353637383930313233343500000000000000467073736800000000EDEF8BA979D64ACEA3C827DCD51D21ED000000261210303132333435363738393031323334351A00221030313233343536373839303132333435 --pssh 0000003470737368010000001077EFECC0B24D02ACE33C1E52E2FB4B000000013031323334353637383930313233343500000000000000467073736800000000EDEF8BA979D64ACEA3C827DCD51D21ED000000261210303132333435363738393031323334351A00221030313233343536373839303132333435
``` ```
...@@ -276,7 +277,8 @@ packager in=bear-320x240-vp9_profile2.webm,stream=video,out=bear-320x240-v-vp9_p ...@@ -276,7 +277,8 @@ packager in=bear-320x240-vp9_profile2.webm,stream=video,out=bear-320x240-v-vp9_p
Same as above, in MP4 container. Codec string: vp09.02.10.10.01.02.02.02.00. Same as above, in MP4 container. Codec string: vp09.02.10.10.01.02.02.02.00.
Generated with [Shaka Packager] at 4ba5bec66054cfd4af13c07ac62a97f1a1a2e5f9: Generated with [Shaka Packager] at 4ba5bec66054cfd4af13c07ac62a97f1a1a2e5f9:
``` ```
packager in=bear-320x240-vp9_profile2.webm,stream=video,out=bear-320x240-v-vp9_profile2_subsample_cenc-v.mp--enable_fixed_key_encryption --key_id 30313233343536373839303132333435 packager in=bear-320x240-vp9_profile2.webm,stream=video,out=bear-320x240-v-vp9_profile2_subsample_cenc-v.mp4
--enable_fixed_key_encryption --key_id 30313233343536373839303132333435
--key ebdd62f16814d27b68ef122afce4ae3c --clear_lead 0 --key ebdd62f16814d27b68ef122afce4ae3c --clear_lead 0
--pssh 0000003470737368010000001077EFECC0B24D02ACE33C1E52E2FB4B000000013031323334353637383930313233343500000000000000467073736800000000EDEF8BA979D64ACEA3C827DCD51D21ED000000261210303132333435363738393031323334351A00221030313233343536373839303132333435 --pssh 0000003470737368010000001077EFECC0B24D02ACE33C1E52E2FB4B000000013031323334353637383930313233343500000000000000467073736800000000EDEF8BA979D64ACEA3C827DCD51D21ED000000261210303132333435363738393031323334351A00221030313233343536373839303132333435
``` ```
......
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