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
Changed: yurys@chromium.org Mon Jul 6 11:13:23 PDT 2020
1124
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 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() {

View file

@ -158,9 +158,10 @@ void ivf_write_frame_header(FILE *outfile, int64_t pts, size_t frame_size) {
class ScreencastEncoder::VPXFrame {
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_scale(scale)
, m_offsetTop(offsetTop)
{ }
void setDuration(int duration) { m_duration = duration; }
@ -189,15 +190,15 @@ public:
src_width *= image->w / dst_width;
dst_width = image->w;
}
int src_height = src->height();
int src_height = src->height() - m_offsetTop;
double dst_height = src_height * m_scale.value();
if (dst_height > image->h) {
src_height *= image->h / dst_height;
dst_height = image->h;
}
libyuv::I420Scale(src->DataY(), src->StrideY(),
src->DataU(), src->StrideU(),
src->DataV(), src->StrideV(),
libyuv::I420Scale(src->DataY() + m_offsetTop * src->StrideY(), src->StrideY(),
src->DataU() + (m_offsetTop + 1) / 2 * src->StrideU(), src->StrideU(),
src->DataV() + (m_offsetTop + 1) / 2 * src->StrideV(), src->StrideV(),
src_width, src_height,
y_data, y_stride,
u_data, uv_stride,
@ -206,10 +207,11 @@ public:
libyuv::kFilterBilinear);
} else {
int width = std::min<int>(image->w, src->width());
int height = std::min<int>(image->h, src->height());
libyuv::I420Copy(src->DataY(), src->StrideY(),
src->DataU(), src->StrideU(),
src->DataV(), src->StrideV(),
int height = std::min<int>(image->h, src->height() - m_offsetTop);
libyuv::I420Copy(src->DataY() + m_offsetTop * src->StrideY(), src->StrideY(),
src->DataU() + (m_offsetTop + 1) / 2 * src->StrideU(), src->StrideU(),
src->DataV() + (m_offsetTop + 1) / 2 * src->StrideV(), src->StrideV(),
y_data, y_stride,
u_data, uv_stride,
v_data, uv_stride,
@ -220,6 +222,7 @@ public:
private:
rtc::scoped_refptr<webrtc::VideoFrameBuffer> m_frameBuffer;
Maybe<double> m_scale;
int m_offsetTop = 0;
int m_duration = 0;
};
@ -325,11 +328,10 @@ private:
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_width(width)
, m_height(height)
, m_scale(scale)
, m_offsetTop(offsetTop)
{
}
@ -338,10 +340,9 @@ ScreencastEncoder::~ScreencastEncoder()
}
static constexpr uint32_t vp8fourcc = 0x30385056;
static constexpr uint32_t vp9fourcc = 0x30395056;
static constexpr int fps = 30;
static constexpr int fps = 24;
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;
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));
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()
@ -407,7 +408,7 @@ void ScreencastEncoder::encodeFrame(const webrtc::VideoFrame& videoFrame)
fprintf(stderr, "ScreencastEncoder::encodeFrame\n");
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)

View file

@ -21,10 +21,10 @@ class ScreencastEncoder {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ScreencastEncoder)
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;
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);
@ -36,9 +36,8 @@ private:
void flushLastFrame();
std::unique_ptr<VPXCodec> m_vpxCodec;
int m_width;
int m_height;
Maybe<double> m_scale;
int m_offsetTop;
TimeStamp m_lastFrameTimestamp;
class VPXFrame;
std::unique_ptr<VPXFrame> m_lastFrame;

View file

@ -12,6 +12,6 @@ interface nsIDocShell;
[scriptable, uuid(d8c4d9e0-9462-445e-9e43-68d3872ad1de)]
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);
};

View file

@ -33,8 +33,7 @@ StaticRefPtr<nsScreencastService> gScreencastService;
class nsScreencastService::Session : public rtc::VideoSinkInterface<webrtc::VideoFrame> {
public:
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))
, mEncoder(std::move(encoder)) {
}
@ -71,7 +70,6 @@ class nsScreencastService::Session : public rtc::VideoSinkInterface<webrtc::Vide
}
private:
int mSessionId;
rtc::scoped_refptr<webrtc::VideoCaptureModule> mCaptureModule;
RefPtr<ScreencastEncoder> mEncoder;
};
@ -93,7 +91,7 @@ nsScreencastService::nsScreencastService() = default;
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.");
*sessionId = -1;
@ -124,7 +122,7 @@ nsresult nsScreencastService::StartVideoRecording(nsIDocShell* aDocShell, const
Maybe<double> maybeScale;
if (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) {
fprintf(stderr, "Failed to create ScreencastEncoder: %s\n", error.get());
return NS_ERROR_FAILURE;