Commit 4e15f003 authored by Zhaoliang Ma's avatar Zhaoliang Ma Committed by Commit Bot

[webcodecs] Enable VP9 profile2 encoding.

This CL enable the vp9 profile2 encoding in VpxVideoEncoder.

Bug: 897297, 1045248
Change-Id: I34dd9ddb3fc49a37136ee864a264e3bb257ded31
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2351623Reviewed-by: default avatarDan Sanders <sandersd@chromium.org>
Commit-Queue: Dan Sanders <sandersd@chromium.org>
Cr-Commit-Position: refs/heads/master@{#797919}
parent 514cf67e
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "media/base/bind_to_current_loop.h" #include "media/base/bind_to_current_loop.h"
#include "media/base/video_frame.h" #include "media/base/video_frame.h"
#include "third_party/libvpx/source/libvpx/vpx/vp8cx.h" #include "third_party/libvpx/source/libvpx/vpx/vp8cx.h"
#include "third_party/libyuv/include/libyuv/convert.h"
namespace media { namespace media {
...@@ -59,6 +60,8 @@ void VpxVideoEncoder::Initialize(VideoCodecProfile profile, ...@@ -59,6 +60,8 @@ void VpxVideoEncoder::Initialize(VideoCodecProfile profile,
return; return;
} }
profile_ = profile;
vpx_codec_iface_t* iface = nullptr; vpx_codec_iface_t* iface = nullptr;
if (profile == media::VP8PROFILE_ANY) { if (profile == media::VP8PROFILE_ANY) {
iface = vpx_codec_vp8_cx(); iface = vpx_codec_vp8_cx();
...@@ -80,20 +83,34 @@ void VpxVideoEncoder::Initialize(VideoCodecProfile profile, ...@@ -80,20 +83,34 @@ void VpxVideoEncoder::Initialize(VideoCodecProfile profile,
std::move(done_cb).Run(status); std::move(done_cb).Run(status);
return; return;
} }
vpx_img_fmt img_fmt = VPX_IMG_FMT_NONE;
unsigned int bits_for_storage = 8;
switch (profile) { switch (profile) {
case media::VP9PROFILE_PROFILE1: case media::VP9PROFILE_PROFILE1:
codec_config_.g_profile = 1; codec_config_.g_profile = 1;
break; break;
case media::VP9PROFILE_PROFILE2: case media::VP9PROFILE_PROFILE2:
codec_config_.g_profile = 2; codec_config_.g_profile = 2;
img_fmt = VPX_IMG_FMT_I42016;
bits_for_storage = 16;
codec_config_.g_bit_depth = VPX_BITS_10;
codec_config_.g_input_bit_depth = 10;
break; break;
case media::VP9PROFILE_PROFILE3: case media::VP9PROFILE_PROFILE3:
codec_config_.g_profile = 3; codec_config_.g_profile = 3;
break; break;
default: default:
codec_config_.g_profile = 0; codec_config_.g_profile = 0;
img_fmt = VPX_IMG_FMT_I420;
bits_for_storage = 8;
codec_config_.g_bit_depth = VPX_BITS_8;
codec_config_.g_input_bit_depth = 8;
break; break;
} }
vpx_image_ =
vpx_img_wrap(nullptr, img_fmt, options.width, options.height, 1, nullptr);
vpx_image_->bit_depth = bits_for_storage;
auto status = SetUpVpxConfig(options, &codec_config_); auto status = SetUpVpxConfig(options, &codec_config_);
if (!status.is_ok()) { if (!status.is_ok()) {
...@@ -102,7 +119,9 @@ void VpxVideoEncoder::Initialize(VideoCodecProfile profile, ...@@ -102,7 +119,9 @@ void VpxVideoEncoder::Initialize(VideoCodecProfile profile,
} }
codec_ = new vpx_codec_ctx_t; codec_ = new vpx_codec_ctx_t;
vpx_error = vpx_codec_enc_init(codec_, iface, &codec_config_, 0 /* flags */); vpx_error = vpx_codec_enc_init(
codec_, iface, &codec_config_,
codec_config_.g_bit_depth == VPX_BITS_8 ? 0 : VPX_CODEC_USE_HIGHBITDEPTH);
if (vpx_error != VPX_CODEC_OK) { if (vpx_error != VPX_CODEC_OK) {
std::string msg = base::StringPrintf("VPX encoder initialization error: %s", std::string msg = base::StringPrintf("VPX encoder initialization error: %s",
vpx_codec_err_to_string(vpx_error)); vpx_codec_err_to_string(vpx_error));
...@@ -154,31 +173,50 @@ void VpxVideoEncoder::Encode(scoped_refptr<VideoFrame> frame, ...@@ -154,31 +173,50 @@ void VpxVideoEncoder::Encode(scoped_refptr<VideoFrame> frame,
return; return;
} }
auto size = frame->visible_rect().size(); switch (profile_) {
auto* img_data = case media::VP9PROFILE_PROFILE1:
const_cast<unsigned char*>(frame->data(media::VideoFrame::kYPlane)); NOTREACHED();
vpx_image_t vpx_image; break;
if (&vpx_image != vpx_img_wrap(&vpx_image, VPX_IMG_FMT_I420, size.width(), case media::VP9PROFILE_PROFILE2:
size.height(), 1 /* align */, img_data)) { libyuv::I420ToI010(
std::move(done_cb).Run(StatusCode::kEncoderFailedEncode); frame->visible_data(media::VideoFrame::kYPlane),
return; frame->stride(media::VideoFrame::kYPlane),
frame->visible_data(media::VideoFrame::kUPlane),
frame->stride(media::VideoFrame::kUPlane),
frame->visible_data(media::VideoFrame::kVPlane),
frame->stride(media::VideoFrame::kVPlane),
reinterpret_cast<uint16_t*>(vpx_image_->planes[VPX_PLANE_Y]),
vpx_image_->stride[VPX_PLANE_Y] / 2,
reinterpret_cast<uint16_t*>(vpx_image_->planes[VPX_PLANE_U]),
vpx_image_->stride[VPX_PLANE_U] / 2,
reinterpret_cast<uint16_t*>(vpx_image_->planes[VPX_PLANE_V]),
vpx_image_->stride[VPX_PLANE_V] / 2, frame->coded_size().width(),
frame->coded_size().height());
break;
case media::VP9PROFILE_PROFILE3:
NOTREACHED();
break;
default:
vpx_image_->planes[VPX_PLANE_Y] =
const_cast<uint8_t*>(frame->visible_data(media::VideoFrame::kYPlane));
vpx_image_->planes[VPX_PLANE_U] =
const_cast<uint8_t*>(frame->visible_data(media::VideoFrame::kUPlane));
vpx_image_->planes[VPX_PLANE_V] =
const_cast<uint8_t*>(frame->visible_data(media::VideoFrame::kVPlane));
vpx_image_->stride[VPX_PLANE_Y] =
frame->stride(media::VideoFrame::kYPlane);
vpx_image_->stride[VPX_PLANE_U] =
frame->stride(media::VideoFrame::kUPlane);
vpx_image_->stride[VPX_PLANE_V] =
frame->stride(media::VideoFrame::kVPlane);
break;
} }
vpx_image.planes[VPX_PLANE_Y] = const_cast<unsigned char*>(
frame->visible_data(media::VideoFrame::kYPlane));
vpx_image.planes[VPX_PLANE_U] = const_cast<unsigned char*>(
frame->visible_data(media::VideoFrame::kUPlane));
vpx_image.planes[VPX_PLANE_V] = const_cast<unsigned char*>(
frame->visible_data(media::VideoFrame::kVPlane));
vpx_image.stride[VPX_PLANE_Y] = frame->stride(media::VideoFrame::kYPlane);
vpx_image.stride[VPX_PLANE_U] = frame->stride(media::VideoFrame::kUPlane);
vpx_image.stride[VPX_PLANE_V] = frame->stride(media::VideoFrame::kVPlane);
auto timestamp = frame->timestamp().InMicroseconds(); auto timestamp = frame->timestamp().InMicroseconds();
auto duration = GetFrameDuration(*frame); auto duration = GetFrameDuration(*frame);
auto deadline = VPX_DL_REALTIME; auto deadline = VPX_DL_REALTIME;
vpx_codec_flags_t flags = key_frame ? VPX_EFLAG_FORCE_KF : 0; vpx_codec_flags_t flags = key_frame ? VPX_EFLAG_FORCE_KF : 0;
auto vpx_error = vpx_codec_encode(codec_, &vpx_image, timestamp, duration, auto vpx_error = vpx_codec_encode(codec_, vpx_image_, timestamp, duration,
flags, deadline); flags, deadline);
if (vpx_error != VPX_CODEC_OK) { if (vpx_error != VPX_CODEC_OK) {
...@@ -235,6 +273,11 @@ VpxVideoEncoder::~VpxVideoEncoder() { ...@@ -235,6 +273,11 @@ VpxVideoEncoder::~VpxVideoEncoder() {
auto error = vpx_codec_destroy(codec_); auto error = vpx_codec_destroy(codec_);
DCHECK_EQ(error, VPX_CODEC_OK); DCHECK_EQ(error, VPX_CODEC_OK);
delete codec_; delete codec_;
if (vpx_image_ != nullptr) {
vpx_img_free(vpx_image_);
vpx_image_ = nullptr;
}
} }
void VpxVideoEncoder::Flush(StatusCB done_cb) { void VpxVideoEncoder::Flush(StatusCB done_cb) {
......
...@@ -37,6 +37,8 @@ class MEDIA_EXPORT VpxVideoEncoder : public VideoEncoder { ...@@ -37,6 +37,8 @@ class MEDIA_EXPORT VpxVideoEncoder : public VideoEncoder {
vpx_codec_ctx_t* codec_ = nullptr; vpx_codec_ctx_t* codec_ = nullptr;
vpx_codec_enc_cfg_t codec_config_ = {}; vpx_codec_enc_cfg_t codec_config_ = {};
vpx_image_t* vpx_image_ = nullptr;
VideoCodecProfile profile_ = VIDEO_CODEC_PROFILE_UNKNOWN;
Options options_; Options options_;
OutputCB output_cb_; OutputCB output_cb_;
}; };
......
...@@ -69,7 +69,10 @@ async function encode_test(codec, profile, acc) { ...@@ -69,7 +69,10 @@ async function encode_test(codec, profile, acc) {
} }
promise_test(encode_test.bind(null, "vp9", "vp09.00.10.08", "allow"), promise_test(encode_test.bind(null, "vp9", "vp09.00.10.08", "allow"),
"encoding vp9"); "encoding vp9 profile0");
promise_test(encode_test.bind(null, "vp9", "vp09.02.10.08", "allow"),
"encoding vp9 profile2");
promise_test(encode_test.bind(null, "vp8", null, "allow"), promise_test(encode_test.bind(null, "vp8", null, "allow"),
"encoding vp8"); "encoding vp8");
......
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