blob: 510bcf3e54f61882881d18138d00196293a4d739 [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/modules/webcodecs/video_frame_handle.h"
#include "base/synchronization/lock.h"
#include "media/base/video_frame.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/webcodecs/video_frame_monitor.h"
#include "third_party/blink/renderer/modules/webcodecs/webcodecs_logger.h"
#include "third_party/skia/include/core/SkImage.h"
namespace blink {
VideoFrameHandle::VideoFrameHandle(scoped_refptr<media::VideoFrame> frame,
ExecutionContext* context,
std::string monitoring_source_id)
: frame_(std::move(frame)),
monitoring_source_id_(std::move(monitoring_source_id)) {
DCHECK(frame_);
DCHECK(context);
close_auditor_ = WebCodecsLogger::From(*context).GetCloseAuditor();
DCHECK(close_auditor_);
MaybeMonitorOpenFrame();
}
VideoFrameHandle::VideoFrameHandle(scoped_refptr<media::VideoFrame> frame,
sk_sp<SkImage> sk_image,
ExecutionContext* context,
std::string monitoring_source_id)
: VideoFrameHandle(std::move(frame),
context,
std::move(monitoring_source_id)) {
sk_image_ = std::move(sk_image);
}
VideoFrameHandle::VideoFrameHandle(
scoped_refptr<media::VideoFrame> frame,
sk_sp<SkImage> sk_image,
scoped_refptr<WebCodecsLogger::VideoFrameCloseAuditor> close_auditor,
std::string monitoring_source_id)
: sk_image_(std::move(sk_image)),
frame_(std::move(frame)),
close_auditor_(std::move(close_auditor)),
monitoring_source_id_(std::move(monitoring_source_id)) {
DCHECK(frame_);
DCHECK(close_auditor_);
MaybeMonitorOpenFrame();
}
VideoFrameHandle::VideoFrameHandle(scoped_refptr<media::VideoFrame> frame,
sk_sp<SkImage> sk_image,
std::string monitoring_source_id)
: sk_image_(std::move(sk_image)),
frame_(std::move(frame)),
monitoring_source_id_(std::move(monitoring_source_id)) {
DCHECK(frame_);
MaybeMonitorOpenFrame();
}
VideoFrameHandle::~VideoFrameHandle() {
MaybeMonitorCloseFrame();
// If we still have a valid |close_auditor_|, Invalidate() was never
// called and corresponding frames never received a call to close() before
// being garbage collected.
if (close_auditor_)
close_auditor_->ReportUnclosedFrame();
}
scoped_refptr<media::VideoFrame> VideoFrameHandle::frame() {
base::AutoLock locker(lock_);
return frame_;
}
sk_sp<SkImage> VideoFrameHandle::sk_image() {
base::AutoLock locker(lock_);
return sk_image_;
}
void VideoFrameHandle::Invalidate() {
base::AutoLock locker(lock_);
InvalidateLocked();
}
void VideoFrameHandle::SetCloseOnClone() {
base::AutoLock locker(lock_);
close_on_clone_ = true;
}
scoped_refptr<VideoFrameHandle> VideoFrameHandle::Clone() {
base::AutoLock locker(lock_);
auto cloned_handle =
frame_ ? base::MakeRefCounted<VideoFrameHandle>(
frame_, sk_image_, close_auditor_, monitoring_source_id_)
: nullptr;
if (close_on_clone_)
InvalidateLocked();
return cloned_handle;
}
scoped_refptr<VideoFrameHandle> VideoFrameHandle::CloneForInternalUse() {
base::AutoLock locker(lock_);
return frame_ ? base::MakeRefCounted<VideoFrameHandle>(frame_, sk_image_,
monitoring_source_id_)
: nullptr;
}
void VideoFrameHandle::InvalidateLocked() {
MaybeMonitorCloseFrame();
frame_.reset();
sk_image_.reset();
close_auditor_.reset();
NotifyExpiredLocked();
}
void VideoFrameHandle::MaybeMonitorOpenFrame() {
if (frame_ && !monitoring_source_id_.empty()) {
VideoFrameMonitor::Instance().OnOpenFrame(monitoring_source_id_,
frame_->unique_id());
}
}
void VideoFrameHandle::MaybeMonitorCloseFrame() {
if (frame_ && !monitoring_source_id_.empty()) {
VideoFrameMonitor::Instance().OnCloseFrame(monitoring_source_id_,
frame_->unique_id());
}
}
bool VideoFrameHandle::WebGPURegisterExternalTextureExpireCallback(
WebGPUExternalTextureExpireCallback
webgpu_external_texture_expire_callback) {
base::AutoLock locker(lock_);
if (!frame_)
return false;
webgpu_external_texture_expire_callbacks_.push_back(
std::move(webgpu_external_texture_expire_callback));
return true;
}
void VideoFrameHandle::NotifyExpiredLocked() {
DCHECK(!frame_);
Vector<WebGPUExternalTextureExpireCallback>
webgpu_external_texture_expire_callbacks =
std::move(webgpu_external_texture_expire_callbacks_);
for (auto& callback : webgpu_external_texture_expire_callbacks) {
std::move(callback).Run();
}
}
} // namespace blink