Commit f44a870b authored by Markus Handell's avatar Markus Handell Committed by Commit Bot

CanvasCaptureHandler: stop producing nonmonotonic timestamps.

This changes fixes a problem where the CanvasCaptureHandler
would produce nonmonotonic timestamps when RequestRefreshFrame
is called while there are outstanding calls to
ReadARGBPixelsAsync.

Bug: 618407
Change-Id: I649f7454aec6be8444b58244e19bb23bc2d175c5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2035893
Commit-Queue: Markus Handell <handellm@google.com>
Reviewed-by: default avatarGuido Urdaneta <guidou@chromium.org>
Cr-Commit-Position: refs/heads/master@{#738807}
parent ac78981a
......@@ -240,12 +240,15 @@ void CanvasCaptureHandler::RequestRefreshFrame() {
DVLOG(3) << __func__;
DCHECK_CALLED_ON_VALID_THREAD(main_render_thread_checker_);
if (last_frame_ && delegate_) {
io_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&CanvasCaptureHandler::CanvasCaptureHandlerDelegate::
SendNewFrameOnIOThread,
delegate_->GetWeakPtrForIOThread(), last_frame_,
base::TimeTicks::Now()));
// If we're currently reading out pixels from GL memory, we risk
// emitting frames with non-incrementally increasing timestamps.
// Defer sending the refresh frame until we have completed those async
// reads.
if (num_ongoing_async_pixel_readouts_ > 0) {
deferred_request_refresh_frame_ = true;
return;
}
SendRefreshFrame();
}
}
......@@ -310,6 +313,8 @@ void CanvasCaptureHandler::ReadARGBPixelsAsync(
const bool result = backend_texture.getGLTextureInfo(&texture_info);
DCHECK(result);
DCHECK(context_provider->GetGLHelper());
IncrementOngoingAsyncPixelReadouts();
context_provider->GetGLHelper()->ReadbackTextureAsync(
texture_info.fID, texture_info.fTarget, image_size,
temp_argb_frame->visible_data(VideoFrame::kARGBPlane), kN32_SkColorType,
......@@ -390,6 +395,7 @@ void CanvasCaptureHandler::OnARGBPixelsReadAsync(
bool flip,
bool success) {
DCHECK_CALLED_ON_VALID_THREAD(main_render_thread_checker_);
DecrementOngoingAsyncPixelReadouts();
if (!success) {
DLOG(ERROR) << "Couldn't read SkImage using async callback";
// Async reading is not supported on some platforms, see
......@@ -409,6 +415,8 @@ void CanvasCaptureHandler::OnARGBPixelsReadAsync(
temp_argb_frame->stride(VideoFrame::kARGBPlane),
kN32_SkColorType),
this_frame_ticks, color_space);
if (num_ongoing_async_pixel_readouts_ == 0 && deferred_request_refresh_frame_)
SendRefreshFrame();
}
void CanvasCaptureHandler::OnYUVPixelsReadAsync(
......@@ -542,4 +550,29 @@ void CanvasCaptureHandler::AddVideoCapturerSourceToVideoTrack(
blink::MediaStreamVideoSource::ConstraintsOnceCallback(), true));
}
void CanvasCaptureHandler::IncrementOngoingAsyncPixelReadouts() {
DCHECK_CALLED_ON_VALID_THREAD(main_render_thread_checker_);
++num_ongoing_async_pixel_readouts_;
}
void CanvasCaptureHandler::DecrementOngoingAsyncPixelReadouts() {
DCHECK_CALLED_ON_VALID_THREAD(main_render_thread_checker_);
--num_ongoing_async_pixel_readouts_;
DCHECK_GE(num_ongoing_async_pixel_readouts_, 0);
}
void CanvasCaptureHandler::SendRefreshFrame() {
DCHECK_CALLED_ON_VALID_THREAD(main_render_thread_checker_);
DCHECK_EQ(num_ongoing_async_pixel_readouts_, 0);
if (last_frame_ && delegate_) {
io_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&CanvasCaptureHandler::CanvasCaptureHandlerDelegate::
SendNewFrameOnIOThread,
delegate_->GetWeakPtrForIOThread(), last_frame_,
base::TimeTicks::Now()));
}
deferred_request_refresh_frame_ = false;
}
} // namespace blink
......@@ -117,6 +117,14 @@ class MODULES_EXPORT CanvasCaptureHandler {
std::unique_ptr<media::VideoCapturerSource> source,
blink::WebMediaStreamTrack* web_track);
// Helper methods to increment/decrement the number of ongoing async pixel
// readouts currently happening.
void IncrementOngoingAsyncPixelReadouts();
void DecrementOngoingAsyncPixelReadouts();
// Send a refresh frame.
void SendRefreshFrame();
// Object that does all the work of running |new_frame_callback_|.
// Destroyed on |frame_callback_task_runner_| after the class is destroyed.
class CanvasCaptureHandlerDelegate;
......@@ -127,6 +135,11 @@ class MODULES_EXPORT CanvasCaptureHandler {
base::Optional<base::TimeTicks> first_frame_ticks_;
scoped_refptr<media::VideoFrame> last_frame_;
// The following attributes ensure that CanvasCaptureHandler emits
// frames with monotonically increasing timestamps.
bool deferred_request_refresh_frame_ = false;
int num_ongoing_async_pixel_readouts_ = 0;
const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
std::unique_ptr<CanvasCaptureHandlerDelegate> delegate_;
......
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