mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
browser(firefox): fix screencast timescale precision (#4196)
This commit is contained in:
parent
54e05ac83e
commit
092c9905e6
@ -1,2 +1,2 @@
|
|||||||
1194
|
1195
|
||||||
Changed: joel.einbinder@gmail.com Fri 16 Oct 2020 01:52:53 AM PDT
|
Changed: yurys@chromium.org Tue Oct 20 13:36:31 PDT 2020
|
||||||
|
|||||||
@ -43,6 +43,10 @@
|
|||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
namespace {
|
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
|
// Defines the dimension of a macro block. This is used to compute the active
|
||||||
// map for the encoder.
|
// map for the encoder.
|
||||||
const int kMacroBlockSize = 16;
|
const int kMacroBlockSize = 16;
|
||||||
@ -111,8 +115,8 @@ public:
|
|||||||
, m_margin(margin)
|
, m_margin(margin)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
void setDuration(int duration) { m_duration = duration; }
|
void setDuration(TimeDuration duration) { m_duration = duration; }
|
||||||
int duration() const { return m_duration; }
|
TimeDuration duration() const { return m_duration; }
|
||||||
|
|
||||||
void convertToVpxImage(vpx_image_t* image)
|
void convertToVpxImage(vpx_image_t* image)
|
||||||
{
|
{
|
||||||
@ -171,7 +175,7 @@ private:
|
|||||||
rtc::scoped_refptr<webrtc::VideoFrameBuffer> m_frameBuffer;
|
rtc::scoped_refptr<webrtc::VideoFrameBuffer> m_frameBuffer;
|
||||||
Maybe<double> m_scale;
|
Maybe<double> m_scale;
|
||||||
gfx::IntMargin m_margin;
|
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)] {
|
m_encoderQueue->Dispatch(NS_NewRunnableFunction("VPXCodec::encodeFrameAsync", [this, frame = std::move(frame)] {
|
||||||
memset(m_imageBuffer.get(), 128, m_imageBufferSize);
|
memset(m_imageBuffer.get(), 128, m_imageBufferSize);
|
||||||
frame->convertToVpxImage(m_image.get());
|
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)
|
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();
|
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_w = width;
|
||||||
cfg.g_h = height;
|
cfg.g_h = height;
|
||||||
cfg.g_timebase.num = 1;
|
cfg.g_timebase.num = 1;
|
||||||
cfg.g_timebase.den = fps;
|
cfg.g_timebase.den = fps * timeScale;
|
||||||
cfg.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT;
|
cfg.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT;
|
||||||
|
|
||||||
vpx_codec_ctx_t codec;
|
vpx_codec_ctx_t codec;
|
||||||
@ -330,9 +339,7 @@ void ScreencastEncoder::flushLastFrame()
|
|||||||
if (!m_lastFrame)
|
if (!m_lastFrame)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
TimeDuration seconds = now - m_lastFrameTimestamp;
|
m_lastFrame->setDuration(now - m_lastFrameTimestamp);
|
||||||
int duration = 1 + seconds.ToSeconds() * fps; // Duration in timebase units
|
|
||||||
m_lastFrame->setDuration(duration);
|
|
||||||
m_vpxCodec->encodeFrameAsync(std::move(m_lastFrame));
|
m_vpxCodec->encodeFrameAsync(std::move(m_lastFrame));
|
||||||
}
|
}
|
||||||
m_lastFrameTimestamp = now;
|
m_lastFrameTimestamp = now;
|
||||||
|
|||||||
@ -21,6 +21,7 @@ namespace mozilla {
|
|||||||
class ScreencastEncoder {
|
class ScreencastEncoder {
|
||||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ScreencastEncoder)
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ScreencastEncoder)
|
||||||
public:
|
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);
|
static RefPtr<ScreencastEncoder> create(nsCString& errorString, const nsCString& filePath, int width, int height, Maybe<double> scale, const gfx::IntMargin& margin);
|
||||||
|
|
||||||
|
|||||||
@ -92,7 +92,7 @@ class nsScreencastService::Session : public rtc::VideoSinkInterface<webrtc::Vide
|
|||||||
// The size is ignored in fact.
|
// The size is ignored in fact.
|
||||||
capability.width = 1280;
|
capability.width = 1280;
|
||||||
capability.height = 960;
|
capability.height = 960;
|
||||||
capability.maxFPS = 24;
|
capability.maxFPS = ScreencastEncoder::fps;
|
||||||
capability.videoType = webrtc::VideoType::kI420;
|
capability.videoType = webrtc::VideoType::kI420;
|
||||||
int error = mCaptureModule->StartCapture(capability);
|
int error = mCaptureModule->StartCapture(capability);
|
||||||
if (error) {
|
if (error) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user