Commit c2e5609b authored by Eugene Zemtsov's avatar Eugene Zemtsov Committed by Commit Bot

[webcodecs] Make encoder's framerate optional

Bug: 1139059
Change-Id: I1e142da5f9f1d6c7cfce42294b9022a0fab1e12f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2520080Reviewed-by: default avatarDan Sanders <sandersd@chromium.org>
Commit-Queue: Eugene Zemtsov <eugene@chromium.org>
Cr-Commit-Position: refs/heads/master@{#824706}
parent a025ad91
......@@ -39,7 +39,7 @@ class MEDIA_EXPORT VideoEncoder {
Options(const Options&);
~Options();
base::Optional<uint64_t> bitrate;
double framerate = 30.0;
base::Optional<double> framerate;
int width = 0;
int height = 0;
......
......@@ -27,7 +27,8 @@ Status SetUpOpenH264Params(const VideoEncoder::Options& options,
params->bEnableDenoise = false;
// Set to 1 due to https://crbug.com/583348
params->iMultipleThreadIdc = 1;
params->fMaxFrameRate = options.framerate;
if (options.framerate.has_value())
params->fMaxFrameRate = options.framerate.value();
params->iPicHeight = options.height;
params->iPicWidth = options.width;
......
......@@ -4,6 +4,7 @@
#include "media/video/vpx_video_encoder.h"
#include "base/numerics/ranges.h"
#include "base/strings/stringprintf.h"
#include "base/system/sys_info.h"
#include "base/time/time.h"
......@@ -275,12 +276,13 @@ void VpxVideoEncoder::Encode(scoped_refptr<VideoFrame> frame,
break;
}
auto timestamp = frame->timestamp().InMicroseconds();
auto duration = GetFrameDuration(*frame);
auto duration_us = GetFrameDuration(*frame).InMicroseconds();
auto timestamp_us = frame->timestamp().InMicroseconds();
last_frame_timestamp_ = frame->timestamp();
auto deadline = VPX_DL_REALTIME;
vpx_codec_flags_t flags = key_frame ? VPX_EFLAG_FORCE_KF : 0;
auto vpx_error = vpx_codec_encode(codec_.get(), &vpx_image_, timestamp,
duration, flags, deadline);
auto vpx_error = vpx_codec_encode(codec_.get(), &vpx_image_, timestamp_us,
duration_us, flags, deadline);
if (vpx_error != VPX_CODEC_OK) {
std::string msg = base::StringPrintf("VPX encoding error: %s (%s)",
......@@ -321,12 +323,21 @@ void VpxVideoEncoder::ChangeOptions(const Options& options, StatusCB done_cb) {
return;
}
uint64_t VpxVideoEncoder::GetFrameDuration(const VideoFrame& frame) {
base::TimeDelta default_duration =
base::TimeDelta::FromSecondsD(1.0 / options_.framerate);
return frame.metadata()
->frame_duration.value_or(default_duration)
.InMicroseconds();
base::TimeDelta VpxVideoEncoder::GetFrameDuration(const VideoFrame& frame) {
// Frame has duration in metadata, use it.
if (frame.metadata()->frame_duration.has_value())
return frame.metadata()->frame_duration.value();
// Options have framerate specified, use it.
if (options_.framerate.has_value())
return base::TimeDelta::FromSecondsD(1.0 / options_.framerate.value());
// No real way to figure out duration, use time passed since the last frame
// as an educated guess, but clamp it within a reasonable limits.
constexpr auto min_duration = base::TimeDelta::FromSecondsD(1.0 / 60.0);
constexpr auto max_duration = base::TimeDelta::FromSecondsD(1.0 / 24.0);
auto duration = frame.timestamp() - last_frame_timestamp_;
return base::ClampToRange(duration, min_duration, max_duration);
}
VpxVideoEncoder::~VpxVideoEncoder() {
......
......@@ -32,7 +32,7 @@ class MEDIA_EXPORT VpxVideoEncoder : public VideoEncoder {
void Flush(StatusCB done_cb) override;
private:
uint64_t GetFrameDuration(const VideoFrame& frame);
base::TimeDelta GetFrameDuration(const VideoFrame& frame);
void DrainOutputs();
using vpx_codec_unique_ptr =
......@@ -42,6 +42,7 @@ class MEDIA_EXPORT VpxVideoEncoder : public VideoEncoder {
bool is_vp9_ = false;
vpx_codec_enc_cfg_t codec_config_ = {};
vpx_image_t vpx_image_ = {};
base::TimeDelta last_frame_timestamp_;
VideoCodecProfile profile_ = VIDEO_CODEC_PROFILE_UNKNOWN;
Options options_;
OutputCB output_cb_;
......
......@@ -83,7 +83,8 @@ std::unique_ptr<media::VideoEncoder> CreateAcceleratedVideoEncoder(
double max_supported_framerate =
double{supported_profile.max_framerate_numerator} /
supported_profile.max_framerate_denominator;
if (options.framerate > max_supported_framerate)
if (options.framerate.has_value() &&
options.framerate.value() > max_supported_framerate)
continue;
found_supported_profile = true;
......@@ -198,7 +199,8 @@ std::unique_ptr<VideoEncoder::ParsedConfig> VideoEncoder::ParseConfig(
return nullptr;
}
parsed->options.framerate = config->framerate();
if (config->hasFramerate())
parsed->options.framerate = config->framerate();
if (config->hasBitrate())
parsed->options.bitrate = config->bitrate();
......
......@@ -17,7 +17,7 @@ dictionary VideoEncoderConfig {
unsigned long long bitrate;
required double framerate;
double framerate;
required unsigned long width;
required unsigned long height;
......
......@@ -88,7 +88,6 @@
width: w,
height: h,
bitrate: 5000000,
framerate: 30,
};
let encoder = new VideoEncoder(encoder_init);
......@@ -135,7 +134,7 @@
const init = {
output: process_video_chunk,
error: (e) => {
error++;
errors++;
console.log(e.message);
},
};
......@@ -180,11 +179,11 @@
"encoding and decoding avc1.42001E");
/* Uncomment this for manual testing, before we have GPU tests for that */
// promise_test(encode_test.bind(null, "avc1.42001E", "require"),
//promise_test(encode_test.bind(null, "avc1.42001E", "require"),
// "encoding avc1.42001E");
// promise_test(encode_decode_test.bind(null, "avc1.42001E", "require"),
// "encoding and decoding avc1.42001E");
//promise_test(encode_decode_test.bind(null, "avc1.42001E", "require"),
// "encoding and decoding avc1.42001E req");
</script>
......
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