browser(firefox): exclude browser controls from screencast (#2855)

This commit is contained in:
Yury Semikhatsky 2020-07-07 09:40:09 -07:00 committed by GitHub
parent 39144dd5b2
commit 9640dbf2a6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 30 additions and 30 deletions

View file

@ -1,2 +1,2 @@
1123 1124
Changed: yurys@chromium.org Mon Jul 6 11:13:23 PDT 2020 Changed: yurys@chromium.org Mon Jul 6 17:16:56 PDT 2020

View file

@ -294,7 +294,9 @@ class PageHandler {
const screencast = Cc['@mozilla.org/juggler/screencast;1'].getService(Ci.nsIScreencastService); const screencast = Cc['@mozilla.org/juggler/screencast;1'].getService(Ci.nsIScreencastService);
const docShell = this._pageTarget._gBrowser.ownerGlobal.docShell; const docShell = this._pageTarget._gBrowser.ownerGlobal.docShell;
this._videoSessionId = screencast.startVideoRecording(docShell, file, width, height, scale || 0); // Exclude address bar and navigation control from the video.
const rect = this._pageTarget.linkedBrowser().getBoundingClientRect();
this._videoSessionId = screencast.startVideoRecording(docShell, file, width, height, scale || 0, rect.top);
} }
stopVideoRecording() { stopVideoRecording() {

View file

@ -158,9 +158,10 @@ void ivf_write_frame_header(FILE *outfile, int64_t pts, size_t frame_size) {
class ScreencastEncoder::VPXFrame { class ScreencastEncoder::VPXFrame {
public: public:
VPXFrame(rtc::scoped_refptr<webrtc::VideoFrameBuffer>&& buffer, Maybe<double> scale) VPXFrame(rtc::scoped_refptr<webrtc::VideoFrameBuffer>&& buffer, Maybe<double> scale, int offsetTop)
: m_frameBuffer(std::move(buffer)) : m_frameBuffer(std::move(buffer))
, m_scale(scale) , m_scale(scale)
, m_offsetTop(offsetTop)
{ } { }
void setDuration(int duration) { m_duration = duration; } void setDuration(int duration) { m_duration = duration; }
@ -189,15 +190,15 @@ public:
src_width *= image->w / dst_width; src_width *= image->w / dst_width;
dst_width = image->w; dst_width = image->w;
} }
int src_height = src->height(); int src_height = src->height() - m_offsetTop;
double dst_height = src_height * m_scale.value(); double dst_height = src_height * m_scale.value();
if (dst_height > image->h) { if (dst_height > image->h) {
src_height *= image->h / dst_height; src_height *= image->h / dst_height;
dst_height = image->h; dst_height = image->h;
} }
libyuv::I420Scale(src->DataY(), src->StrideY(), libyuv::I420Scale(src->DataY() + m_offsetTop * src->StrideY(), src->StrideY(),
src->DataU(), src->StrideU(), src->DataU() + (m_offsetTop + 1) / 2 * src->StrideU(), src->StrideU(),
src->DataV(), src->StrideV(), src->DataV() + (m_offsetTop + 1) / 2 * src->StrideV(), src->StrideV(),
src_width, src_height, src_width, src_height,
y_data, y_stride, y_data, y_stride,
u_data, uv_stride, u_data, uv_stride,
@ -206,10 +207,11 @@ public:
libyuv::kFilterBilinear); libyuv::kFilterBilinear);
} else { } else {
int width = std::min<int>(image->w, src->width()); int width = std::min<int>(image->w, src->width());
int height = std::min<int>(image->h, src->height()); int height = std::min<int>(image->h, src->height() - m_offsetTop);
libyuv::I420Copy(src->DataY(), src->StrideY(),
src->DataU(), src->StrideU(), libyuv::I420Copy(src->DataY() + m_offsetTop * src->StrideY(), src->StrideY(),
src->DataV(), src->StrideV(), src->DataU() + (m_offsetTop + 1) / 2 * src->StrideU(), src->StrideU(),
src->DataV() + (m_offsetTop + 1) / 2 * src->StrideV(), src->StrideV(),
y_data, y_stride, y_data, y_stride,
u_data, uv_stride, u_data, uv_stride,
v_data, uv_stride, v_data, uv_stride,
@ -220,6 +222,7 @@ public:
private: private:
rtc::scoped_refptr<webrtc::VideoFrameBuffer> m_frameBuffer; rtc::scoped_refptr<webrtc::VideoFrameBuffer> m_frameBuffer;
Maybe<double> m_scale; Maybe<double> m_scale;
int m_offsetTop = 0;
int m_duration = 0; int m_duration = 0;
}; };
@ -325,11 +328,10 @@ private:
std::unique_ptr<vpx_image_t> m_image; std::unique_ptr<vpx_image_t> m_image;
}; };
ScreencastEncoder::ScreencastEncoder(std::unique_ptr<VPXCodec>&& vpxCodec, int width, int height, Maybe<double> scale) ScreencastEncoder::ScreencastEncoder(std::unique_ptr<VPXCodec>&& vpxCodec, Maybe<double> scale, int offsetTop)
: m_vpxCodec(std::move(vpxCodec)) : m_vpxCodec(std::move(vpxCodec))
, m_width(width)
, m_height(height)
, m_scale(scale) , m_scale(scale)
, m_offsetTop(offsetTop)
{ {
} }
@ -338,10 +340,9 @@ ScreencastEncoder::~ScreencastEncoder()
} }
static constexpr uint32_t vp8fourcc = 0x30385056; static constexpr uint32_t vp8fourcc = 0x30385056;
static constexpr uint32_t vp9fourcc = 0x30395056; static constexpr int fps = 24;
static constexpr int fps = 30;
RefPtr<ScreencastEncoder> ScreencastEncoder::create(nsCString& errorString, const nsCString& filePath, int width, int height, Maybe<double> scale) RefPtr<ScreencastEncoder> ScreencastEncoder::create(nsCString& errorString, const nsCString& filePath, int width, int height, Maybe<double> scale, int offsetTop)
{ {
const uint32_t fourcc = vp8fourcc; const uint32_t fourcc = vp8fourcc;
vpx_codec_iface_t* codec_interface = vpx_codec_vp8_cx(); vpx_codec_iface_t* codec_interface = vpx_codec_vp8_cx();
@ -383,7 +384,7 @@ RefPtr<ScreencastEncoder> ScreencastEncoder::create(nsCString& errorString, cons
std::unique_ptr<VPXCodec> vpxCodec(new VPXCodec(fourcc, codec, cfg, file)); std::unique_ptr<VPXCodec> vpxCodec(new VPXCodec(fourcc, codec, cfg, file));
fprintf(stderr, "ScreencastEncoder initialized with: %s\n", vpx_codec_iface_name(codec_interface)); fprintf(stderr, "ScreencastEncoder initialized with: %s\n", vpx_codec_iface_name(codec_interface));
return new ScreencastEncoder(std::move(vpxCodec), width, height, scale); return new ScreencastEncoder(std::move(vpxCodec), scale, offsetTop);
} }
void ScreencastEncoder::flushLastFrame() void ScreencastEncoder::flushLastFrame()
@ -407,7 +408,7 @@ void ScreencastEncoder::encodeFrame(const webrtc::VideoFrame& videoFrame)
fprintf(stderr, "ScreencastEncoder::encodeFrame\n"); fprintf(stderr, "ScreencastEncoder::encodeFrame\n");
flushLastFrame(); flushLastFrame();
m_lastFrame = std::make_unique<VPXFrame>(videoFrame.video_frame_buffer(), m_scale); m_lastFrame = std::make_unique<VPXFrame>(videoFrame.video_frame_buffer(), m_scale, m_offsetTop);
} }
void ScreencastEncoder::finish(std::function<void()>&& callback) void ScreencastEncoder::finish(std::function<void()>&& callback)

View file

@ -21,10 +21,10 @@ class ScreencastEncoder {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ScreencastEncoder) NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ScreencastEncoder)
public: public:
static RefPtr<ScreencastEncoder> create(nsCString& errorString, const nsCString& filePath, int width, int height, Maybe<double> scale); static RefPtr<ScreencastEncoder> create(nsCString& errorString, const nsCString& filePath, int width, int height, Maybe<double> scale, int offsetTop);
class VPXCodec; class VPXCodec;
ScreencastEncoder(std::unique_ptr<VPXCodec>&&, int width, int height, Maybe<double> scale); ScreencastEncoder(std::unique_ptr<VPXCodec>&&, Maybe<double> scale, int offsetTop);
void encodeFrame(const webrtc::VideoFrame& videoFrame); void encodeFrame(const webrtc::VideoFrame& videoFrame);
@ -36,9 +36,8 @@ private:
void flushLastFrame(); void flushLastFrame();
std::unique_ptr<VPXCodec> m_vpxCodec; std::unique_ptr<VPXCodec> m_vpxCodec;
int m_width;
int m_height;
Maybe<double> m_scale; Maybe<double> m_scale;
int m_offsetTop;
TimeStamp m_lastFrameTimestamp; TimeStamp m_lastFrameTimestamp;
class VPXFrame; class VPXFrame;
std::unique_ptr<VPXFrame> m_lastFrame; std::unique_ptr<VPXFrame> m_lastFrame;

View file

@ -12,6 +12,6 @@ interface nsIDocShell;
[scriptable, uuid(d8c4d9e0-9462-445e-9e43-68d3872ad1de)] [scriptable, uuid(d8c4d9e0-9462-445e-9e43-68d3872ad1de)]
interface nsIScreencastService : nsISupports interface nsIScreencastService : nsISupports
{ {
long startVideoRecording(in nsIDocShell docShell, in ACString fileName, in uint32_t width, in uint32_t height, in double scale); long startVideoRecording(in nsIDocShell docShell, in ACString fileName, in uint32_t width, in uint32_t height, in double scale, in int32_t offset_top);
void stopVideoRecording(in long sessionId); void stopVideoRecording(in long sessionId);
}; };

View file

@ -33,8 +33,7 @@ StaticRefPtr<nsScreencastService> gScreencastService;
class nsScreencastService::Session : public rtc::VideoSinkInterface<webrtc::VideoFrame> { class nsScreencastService::Session : public rtc::VideoSinkInterface<webrtc::VideoFrame> {
public: public:
Session(int sessionId, const nsCString& windowId, RefPtr<ScreencastEncoder>&& encoder) Session(int sessionId, const nsCString& windowId, RefPtr<ScreencastEncoder>&& encoder)
: mSessionId(sessionId) : mCaptureModule(webrtc::DesktopCaptureImpl::Create(
, mCaptureModule(webrtc::DesktopCaptureImpl::Create(
sessionId, windowId.get(), webrtc::CaptureDeviceType::Window)) sessionId, windowId.get(), webrtc::CaptureDeviceType::Window))
, mEncoder(std::move(encoder)) { , mEncoder(std::move(encoder)) {
} }
@ -71,7 +70,6 @@ class nsScreencastService::Session : public rtc::VideoSinkInterface<webrtc::Vide
} }
private: private:
int mSessionId;
rtc::scoped_refptr<webrtc::VideoCaptureModule> mCaptureModule; rtc::scoped_refptr<webrtc::VideoCaptureModule> mCaptureModule;
RefPtr<ScreencastEncoder> mEncoder; RefPtr<ScreencastEncoder> mEncoder;
}; };
@ -93,7 +91,7 @@ nsScreencastService::nsScreencastService() = default;
nsScreencastService::~nsScreencastService() { nsScreencastService::~nsScreencastService() {
} }
nsresult nsScreencastService::StartVideoRecording(nsIDocShell* aDocShell, const nsACString& aFileName, uint32_t width, uint32_t height, double scale, int32_t* sessionId) { nsresult nsScreencastService::StartVideoRecording(nsIDocShell* aDocShell, const nsACString& aFileName, uint32_t width, uint32_t height, double scale, int32_t offsetTop, int32_t* sessionId) {
MOZ_RELEASE_ASSERT(NS_IsMainThread(), "Screencast service must be started on the Main thread."); MOZ_RELEASE_ASSERT(NS_IsMainThread(), "Screencast service must be started on the Main thread.");
*sessionId = -1; *sessionId = -1;
@ -124,7 +122,7 @@ nsresult nsScreencastService::StartVideoRecording(nsIDocShell* aDocShell, const
Maybe<double> maybeScale; Maybe<double> maybeScale;
if (scale) if (scale)
maybeScale = Some(scale); maybeScale = Some(scale);
RefPtr<ScreencastEncoder> encoder = ScreencastEncoder::create(error, PromiseFlatCString(aFileName), width, height, maybeScale); RefPtr<ScreencastEncoder> encoder = ScreencastEncoder::create(error, PromiseFlatCString(aFileName), width, height, maybeScale, offsetTop);
if (!encoder) { if (!encoder) {
fprintf(stderr, "Failed to create ScreencastEncoder: %s\n", error.get()); fprintf(stderr, "Failed to create ScreencastEncoder: %s\n", error.get());
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;