Commit 4bdd0212 authored by Guido Urdaneta's avatar Guido Urdaneta Committed by Commit Bot

Move PushableVideoTrackSource to modules/mediastream

Also rename to PushableMediaStreamVideoSource.
This class is a generic building block that will be used
by Raw Access Insertable Streams (a.k.a. Breakout Box).
This class is very generic, so the mediastream module is a natural
place for it.

Bug: 1142955
Change-Id: Ibceb38dfae8638a49ce87dc735c2114a2e863145
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2503511
Commit-Queue: Guido Urdaneta <guidou@chromium.org>
Reviewed-by: default avatarKent Tamura <tkent@chromium.org>
Reviewed-by: default avatarChrome Cunningham <chcunningham@chromium.org>
Cr-Commit-Position: refs/heads/master@{#821702}
parent 20ae05a6
......@@ -353,6 +353,7 @@ source_set("unit_tests") {
"mediastream/mock_mojo_media_stream_dispatcher_host.cc",
"mediastream/mock_mojo_media_stream_dispatcher_host.h",
"mediastream/processed_local_audio_source_test.cc",
"mediastream/pushable_media_stream_video_source_test.cc",
"mediastream/user_media_client_test.cc",
"mediastream/video_track_adapter_unittest.cc",
"mediastream/webaudio_media_stream_audio_sink_test.cc",
......
......@@ -70,6 +70,8 @@ blink_modules_sources("mediastream") {
"overconstrained_error.h",
"processed_local_audio_source.cc",
"processed_local_audio_source.h",
"pushable_media_stream_video_source.cc",
"pushable_media_stream_video_source.h",
"remote_media_stream_track_adapter.cc",
"remote_media_stream_track_adapter.h",
"track_audio_renderer.cc",
......
// 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/mediastream/pushable_media_stream_video_source.h"
#include "third_party/blink/public/mojom/mediastream/media_stream.mojom-blink.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
namespace blink {
void PushableMediaStreamVideoSource::PushFrame(
scoped_refptr<media::VideoFrame> video_frame,
base::TimeTicks estimated_capture_time) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!running_)
return;
// Note that although use of the IO thread is rare in blink, it's required
// by any implementation of MediaStreamVideoSource, which is made clear by
// the documentation of MediaStreamVideoSource::StartSourceImpl which reads
// "An implementation must call |frame_callback| on the IO thread."
// Also see the DCHECK at VideoTrackAdapter::DeliverFrameOnIO
// and the other of implementations of MediaStreamVideoSource at
// MediaStreamRemoteVideoSource::StartSourceImpl,
// CastReceiverSession::StartVideo,
// CanvasCaptureHandler::SendFrame,
// and HtmlVideoElementCapturerSource::sendNewFrame.
PostCrossThreadTask(
*io_task_runner(), FROM_HERE,
CrossThreadBindOnce(deliver_frame_cb_, std::move(video_frame),
estimated_capture_time));
}
void PushableMediaStreamVideoSource::Stop() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DoStopSource();
running_ = false;
}
void PushableMediaStreamVideoSource::StartSourceImpl(
VideoCaptureDeliverFrameCB frame_callback,
EncodedVideoFrameCB encoded_frame_callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(frame_callback);
running_ = true;
deliver_frame_cb_ = frame_callback;
OnStartDone(mojom::blink::MediaStreamRequestResult::OK);
}
void PushableMediaStreamVideoSource::StopSourceImpl() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
running_ = false;
}
} // namespace blink
// 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.
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_PUSHABLE_MEDIA_STREAM_VIDEO_SOURCE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_PUSHABLE_MEDIA_STREAM_VIDEO_SOURCE_H_
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/public/web/modules/mediastream/media_stream_video_source.h"
#include "third_party/blink/renderer/modules/modules_export.h"
namespace blink {
// Simplifies the creation of video tracks. Just do this:
// auto source = std::make_unique<PushableMediaStreamVideoSource>();
// auto* track = CreateVideoTrackFromSource(script_state, source);
// for each frame:
// source->PushFrame(video_frame, capture_time);
// source->Stop();
class MODULES_EXPORT PushableMediaStreamVideoSource
: public MediaStreamVideoSource {
public:
// See the definition of VideoCaptureDeliverFrameCB in
// media/capture/video_capturer_source.h for the documentation
// of |estimated_capture_time| and the difference with
// media::VideoFrame::timestamp().
void PushFrame(scoped_refptr<media::VideoFrame> video_frame,
base::TimeTicks estimated_capture_time);
// TODO(crbug.com/1142955): Remove this method. StopSource() should be used
// instead.
void Stop();
// MediaStreamVideoSource
void StartSourceImpl(VideoCaptureDeliverFrameCB frame_callback,
EncodedVideoFrameCB encoded_frame_callback) override;
void StopSourceImpl() override;
private:
bool running_ = false;
VideoCaptureDeliverFrameCB deliver_frame_cb_;
THREAD_CHECKER(thread_checker_);
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_PUSHABLE_MEDIA_STREAM_VIDEO_SOURCE_H_
// 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/mediastream/pushable_media_stream_video_source.h"
#include "base/run_loop.h"
#include "media/base/bind_to_current_loop.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/mediastream/media_stream.mojom-blink.h"
#include "third_party/blink/public/web/modules/mediastream/media_stream_video_sink.h"
#include "third_party/blink/public/web/web_heap.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream_video_track.h"
#include "third_party/blink/renderer/modules/mediastream/video_track_adapter_settings.h"
#include "third_party/blink/renderer/platform/mediastream/media_stream_source.h"
#include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
namespace blink {
namespace {
class FakeMediaStreamVideoSink : public MediaStreamVideoSink {
public:
FakeMediaStreamVideoSink(base::TimeTicks* capture_time,
media::VideoFrameMetadata* metadata,
gfx::Size* natural_size,
base::OnceClosure got_frame_cb)
: capture_time_(capture_time),
metadata_(metadata),
natural_size_(natural_size),
got_frame_cb_(std::move(got_frame_cb)) {}
void ConnectToTrack(const WebMediaStreamTrack& track) {
MediaStreamVideoSink::ConnectToTrack(
track,
ConvertToBaseRepeatingCallback(
CrossThreadBindRepeating(&FakeMediaStreamVideoSink::OnVideoFrame,
WTF::CrossThreadUnretained(this))),
true);
}
void DisconnectFromTrack() { MediaStreamVideoSink::DisconnectFromTrack(); }
void OnVideoFrame(scoped_refptr<media::VideoFrame> frame,
base::TimeTicks capture_time) {
*capture_time_ = capture_time;
*metadata_ = *frame->metadata();
*natural_size_ = frame->natural_size();
std::move(got_frame_cb_).Run();
}
private:
base::TimeTicks* const capture_time_;
media::VideoFrameMetadata* const metadata_;
gfx::Size* const natural_size_;
base::OnceClosure got_frame_cb_;
};
} // namespace
class PushableMediaStreamVideoSourceTest : public testing::Test {
public:
PushableMediaStreamVideoSourceTest() {
pushable_video_source_ = new PushableMediaStreamVideoSource();
stream_source_ = MakeGarbageCollected<MediaStreamSource>(
"dummy_source_id", MediaStreamSource::kTypeVideo, "dummy_source_name",
false /* remote */);
stream_source_->SetPlatformSource(base::WrapUnique(pushable_video_source_));
}
void TearDown() override {
stream_source_ = nullptr;
WebHeap::CollectAllGarbageForTesting();
}
WebMediaStreamTrack StartSource() {
return MediaStreamVideoTrack::CreateVideoTrack(
pushable_video_source_,
MediaStreamVideoSource::ConstraintsOnceCallback(),
/*enabled=*/true);
}
protected:
ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform_;
Persistent<MediaStreamSource> stream_source_;
PushableMediaStreamVideoSource* pushable_video_source_;
};
TEST_F(PushableMediaStreamVideoSourceTest, StartAndStop) {
EXPECT_EQ(MediaStreamSource::kReadyStateLive,
stream_source_->GetReadyState());
WebMediaStreamTrack track = StartSource();
EXPECT_EQ(MediaStreamSource::kReadyStateLive,
stream_source_->GetReadyState());
// If the pushable source stops, the MediaStreamSource should stop.
pushable_video_source_->StopSource();
EXPECT_EQ(MediaStreamSource::kReadyStateEnded,
stream_source_->GetReadyState());
}
TEST_F(PushableMediaStreamVideoSourceTest, FramesPropagateToSink) {
WebMediaStreamTrack track = StartSource();
base::RunLoop run_loop;
base::TimeTicks reference_capture_time = base::TimeTicks::Now();
base::TimeTicks capture_time;
media::VideoFrameMetadata metadata;
gfx::Size natural_size;
FakeMediaStreamVideoSink fake_sink(
&capture_time, &metadata, &natural_size,
media::BindToCurrentLoop(run_loop.QuitClosure()));
fake_sink.ConnectToTrack(track);
const scoped_refptr<media::VideoFrame> frame =
media::VideoFrame::CreateBlackFrame(gfx::Size(100, 50));
frame->metadata()->frame_rate = 30.0;
pushable_video_source_->PushFrame(frame, reference_capture_time);
run_loop.Run();
fake_sink.DisconnectFromTrack();
EXPECT_EQ(reference_capture_time, capture_time);
EXPECT_EQ(30.0, *metadata.frame_rate);
EXPECT_EQ(natural_size.width(), 100);
EXPECT_EQ(natural_size.height(), 50);
}
} // namespace blink
......@@ -15,6 +15,7 @@
#include "third_party/blink/renderer/core/streams/writable_stream_default_controller.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream_track.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream_video_track.h"
#include "third_party/blink/renderer/modules/mediastream/pushable_media_stream_video_source.h"
#include "third_party/blink/renderer/modules/webcodecs/video_frame.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
......@@ -24,61 +25,12 @@
namespace blink {
// Simplifies the creation of video tracks. Just do this:
// auto source = std::make_unique<PushableVideoTrackSource>();
// auto* track = CreateVideoTrackFromSource(script_state, source);
// for each frame:
// source->PushFrame(video_frame, capture_time);
// source->Stop();
class PushableVideoTrackSource : public MediaStreamVideoSource {
public:
void PushFrame(scoped_refptr<media::VideoFrame> video_frame,
base::TimeTicks estimated_capture_time) {
if (!running_)
return;
// Note that although use of the IO thread is rare in blink, it's required
// by any implementation of MediaStreamVideoSource, which is made clear by
// the documentation of MediaStreamVideoSource::StartSourceImpl which reads
// "An implementation must call |frame_callback| on the IO thread."
// Also see the DCHECK at VideoTrackAdapter::DeliverFrameOnIO
// and the other of implementations of MediaStreamVideoSource at
// MediaStreamRemoteVideoSource::StartSourceImpl,
// CastReceiverSession::StartVideo,
// CanvasCaptureHandler::SendFrame,
// and HtmlVideoElementCapturerSource::sendNewFrame.
PostCrossThreadTask(
*io_task_runner(), FROM_HERE,
CrossThreadBindOnce(deliver_frame_cb_, std::move(video_frame),
estimated_capture_time));
}
void Stop() {
DoStopSource();
running_ = false;
}
void StartSourceImpl(VideoCaptureDeliverFrameCB frame_callback,
EncodedVideoFrameCB encoded_frame_callback) override {
DCHECK(frame_callback);
running_ = true;
deliver_frame_cb_ = frame_callback;
OnStartDone(mojom::blink::MediaStreamRequestResult::OK);
}
void StopSourceImpl() override { running_ = false; }
private:
bool running_ = false;
VideoCaptureDeliverFrameCB deliver_frame_cb_;
};
// Implements a WritableStream's UnderlyingSinkBase by pushing frames into a
// PushableVideoTrackSource. Also optionally releases the frames.
// PushableMediaStreamVideoSource. Also optionally releases the frames.
class VideoTrackWritableStreamSink final : public UnderlyingSinkBase {
public:
// The source must out live the sink.
VideoTrackWritableStreamSink(PushableVideoTrackSource* source,
VideoTrackWritableStreamSink(PushableMediaStreamVideoSource* source,
bool release_frames)
: source_(source), release_frames_(release_frames) {}
......@@ -123,7 +75,7 @@ class VideoTrackWritableStreamSink final : public UnderlyingSinkBase {
return ScriptPromise::CastUndefined(script_state);
}
PushableVideoTrackSource* source_;
PushableMediaStreamVideoSource* source_;
bool release_frames_;
};
......@@ -158,8 +110,8 @@ VideoTrackWriter* VideoTrackWriter::Create(
return nullptr;
}
std::unique_ptr<PushableVideoTrackSource> track_source =
std::make_unique<PushableVideoTrackSource>();
std::unique_ptr<PushableMediaStreamVideoSource> track_source =
std::make_unique<PushableMediaStreamVideoSource>();
VideoTrackWritableStreamSink* writable_sink =
MakeGarbageCollected<VideoTrackWritableStreamSink>(
track_source.get(), params->releaseFrames());
......
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