browser(firefox): fix screencast timescale precision (#4196)

This commit is contained in:
Yury Semikhatsky 2020-10-20 13:39:56 -07:00 committed by GitHub
parent 54e05ac83e
commit 092c9905e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 21 additions and 13 deletions

View File

@ -1,2 +1,2 @@
1194
Changed: joel.einbinder@gmail.com Fri 16 Oct 2020 01:52:53 AM PDT
1195
Changed: yurys@chromium.org Tue Oct 20 13:36:31 PDT 2020

View File

@ -43,6 +43,10 @@
namespace mozilla {
namespace {
// Number of timebase unints per one frame.
constexpr int timeScale = 1000;
// Defines the dimension of a macro block. This is used to compute the active
// map for the encoder.
const int kMacroBlockSize = 16;
@ -111,8 +115,8 @@ public:
, m_margin(margin)
{ }
void setDuration(int duration) { m_duration = duration; }
int duration() const { return m_duration; }
void setDuration(TimeDuration duration) { m_duration = duration; }
TimeDuration duration() const { return m_duration; }
void convertToVpxImage(vpx_image_t* image)
{
@ -171,7 +175,7 @@ private:
rtc::scoped_refptr<webrtc::VideoFrameBuffer> m_frameBuffer;
Maybe<double> m_scale;
gfx::IntMargin m_margin;
int m_duration = 0;
TimeDuration m_duration;
};
@ -202,7 +206,14 @@ public:
m_encoderQueue->Dispatch(NS_NewRunnableFunction("VPXCodec::encodeFrameAsync", [this, frame = std::move(frame)] {
memset(m_imageBuffer.get(), 128, m_imageBufferSize);
frame->convertToVpxImage(m_image.get());
encodeFrame(m_image.get(), frame->duration());
double frameCount = frame->duration().ToSeconds() * fps;
// For long duration repeat frame at 1 fps to ensure last frame duration is short enough.
// TODO: figure out why simply passing duration doesn't work well.
for (;frameCount > 1.5; frameCount -= 1) {
encodeFrame(m_image.get(), timeScale);
}
encodeFrame(m_image.get(), std::max<int>(1, frameCount * timeScale));
}));
}
@ -276,8 +287,6 @@ ScreencastEncoder::~ScreencastEncoder()
{
}
static constexpr int fps = 24;
RefPtr<ScreencastEncoder> ScreencastEncoder::create(nsCString& errorString, const nsCString& filePath, int width, int height, Maybe<double> scale, const gfx::IntMargin& margin)
{
vpx_codec_iface_t* codec_interface = vpx_codec_vp8_cx();
@ -302,7 +311,7 @@ RefPtr<ScreencastEncoder> ScreencastEncoder::create(nsCString& errorString, cons
cfg.g_w = width;
cfg.g_h = height;
cfg.g_timebase.num = 1;
cfg.g_timebase.den = fps;
cfg.g_timebase.den = fps * timeScale;
cfg.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT;
vpx_codec_ctx_t codec;
@ -330,9 +339,7 @@ void ScreencastEncoder::flushLastFrame()
if (!m_lastFrame)
return;
TimeDuration seconds = now - m_lastFrameTimestamp;
int duration = 1 + seconds.ToSeconds() * fps; // Duration in timebase units
m_lastFrame->setDuration(duration);
m_lastFrame->setDuration(now - m_lastFrameTimestamp);
m_vpxCodec->encodeFrameAsync(std::move(m_lastFrame));
}
m_lastFrameTimestamp = now;

View File

@ -21,6 +21,7 @@ namespace mozilla {
class ScreencastEncoder {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ScreencastEncoder)
public:
static constexpr int fps = 25;
static RefPtr<ScreencastEncoder> create(nsCString& errorString, const nsCString& filePath, int width, int height, Maybe<double> scale, const gfx::IntMargin& margin);

View File

@ -92,7 +92,7 @@ class nsScreencastService::Session : public rtc::VideoSinkInterface<webrtc::Vide
// The size is ignored in fact.
capability.width = 1280;
capability.height = 960;
capability.maxFPS = 24;
capability.maxFPS = ScreencastEncoder::fps;
capability.videoType = webrtc::VideoType::kI420;
int error = mCaptureModule->StartCapture(capability);
if (error) {