diff options
author | mcasas <mcasas@chromium.org> | 2015-09-09 16:32:06 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-09-09 23:32:47 +0000 |
commit | 1567842287b4097350d33c14e5f795559fa008b5 (patch) | |
tree | f50a9f48f649abf87a84590681bf9516026ee812 /media/capture | |
parent | 7606f64ba73cbc175f2dbffe2d20714bab299de2 (diff) | |
download | chromium_src-1567842287b4097350d33c14e5f795559fa008b5.zip chromium_src-1567842287b4097350d33c14e5f795559fa008b5.tar.gz chromium_src-1567842287b4097350d33c14e5f795559fa008b5.tar.bz2 |
MediaRecorderHandler (video part) and unittests
MediaRecorderHandler is Blink-orchestrated class implementing
MediaRecorder API (see below). It plugs together an existing
MediaStreamVideoTrack to a new VideoTrackRecorder-WebmMuxer
pair. When MSVTrack passes frames, these get encoded, muxed,
and the result is sent to Blink.
A *note on threading*: As is customary in MediaStream* and
derived classes, all configuration happens on Main Render thread
while frame manipulation and forwarding happens on Render IO
thread [1]. Moreover, all objects can be, and often are, destroyed in
asynchronous and unexpected ways from Blink. This forces
ref-counting for VideoTrackRecorder::VpxEncoder. This is the
also the reason behind the change in WebmMuxer to 2-threaded.
See DD @ https://goo.gl/vSjzC5 (*) for the plan.
(*) Used to be https://goo.gl/kreaQj
[1] https://code.google.com/p/chromium/codesearch#chromium/src/content/renderer/media/media_stream_video_track.cc&sq=package:chromium&type=cs&l=155&rcl=1440530828
BUG=262211
Review URL: https://codereview.chromium.org/1313603004
Cr-Commit-Position: refs/heads/master@{#348037}
Diffstat (limited to 'media/capture')
-rw-r--r-- | media/capture/webm_muxer.cc | 25 | ||||
-rw-r--r-- | media/capture/webm_muxer.h | 10 | ||||
-rw-r--r-- | media/capture/webm_muxer_unittest.cc | 8 |
3 files changed, 27 insertions, 16 deletions
diff --git a/media/capture/webm_muxer.cc b/media/capture/webm_muxer.cc index b3f8e74..b913fa7 100644 --- a/media/capture/webm_muxer.cc +++ b/media/capture/webm_muxer.cc @@ -28,19 +28,14 @@ WebmMuxer::WebmMuxer(const WriteDataCB& write_data_callback) : track_index_(0), write_data_callback_(write_data_callback), position_(0) { - DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(!write_data_callback_.is_null()); - segment_.Init(this); - segment_.set_mode(mkvmuxer::Segment::kLive); - segment_.OutputCues(false); - - mkvmuxer::SegmentInfo* const info = segment_.GetSegmentInfo(); - info->set_writing_app("Chrome"); - info->set_muxing_app("Chrome"); + // Creation is done on a different thread than main activities. + thread_checker_.DetachFromThread(); } WebmMuxer::~WebmMuxer() { - DCHECK(thread_checker_.CalledOnValidThread()); + // No need to segment_.Finalize() since is not Seekable(), i.e. a live stream, + // but is good practice. segment_.Finalize(); } @@ -48,6 +43,7 @@ void WebmMuxer::OnEncodedVideo(const scoped_refptr<VideoFrame>& video_frame, const base::StringPiece& encoded_data, base::TimeTicks timestamp, bool is_key_frame) { + DVLOG(1) << __FUNCTION__ << " - " << encoded_data.size() << "B"; DCHECK(thread_checker_.CalledOnValidThread()); if (!track_index_) { // |track_index_|, cannot be zero (!), initialize WebmMuxer in that case. @@ -66,7 +62,16 @@ void WebmMuxer::OnEncodedVideo(const scoped_refptr<VideoFrame>& video_frame, void WebmMuxer::AddVideoTrack(const gfx::Size& frame_size, double frame_rate) { DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK_EQ(track_index_, 0u); + DCHECK_EQ(track_index_, 0u) << "WebmMuxer can only be initialised once."; + + segment_.Init(this); + segment_.set_mode(mkvmuxer::Segment::kLive); + segment_.OutputCues(false); + + mkvmuxer::SegmentInfo* const info = segment_.GetSegmentInfo(); + info->set_writing_app("Chrome"); + info->set_muxing_app("Chrome"); + track_index_ = segment_.AddVideoTrack(frame_size.width(), frame_size.height(), 0); DCHECK_GT(track_index_, 0u); diff --git a/media/capture/webm_muxer.h b/media/capture/webm_muxer.h index 153e14f..3fec647 100644 --- a/media/capture/webm_muxer.h +++ b/media/capture/webm_muxer.h @@ -27,8 +27,9 @@ class VideoFrame; // containing a single encoded video frame. WebM container has no Trailer. // Clients will push encoded VPx video frames one by one via the // OnEncodedVideo(). libwebm will eventually ping the WriteDataCB passed on -// contructor with the wrapped encoded data. All operations must happen in a -// single thread, where WebmMuxer is created and destroyed. +// contructor with the wrapped encoded data. +// WebmMuxer is created/destroyed on a thread, usually the Main Render thread, +// and receives OnEncodedVideo()s on another thread, usually Render IO. // [1] http://www.webmproject.org/docs/container/ // [2] http://www.matroska.org/technical/specs/index.html // TODO(mcasas): Add support for Audio muxing. @@ -56,8 +57,7 @@ class MEDIA_EXPORT WebmMuxer : public NON_EXPORTED_BASE(mkvmuxer::IMkvWriter) { // Creates and adds a new video track. Called upon receiving the first // frame of a given Track, adds |frame_size| and |frame_rate| to the Segment // info, although individual frames passed to OnEncodedVideo() can have any - // frame size. Returns OnEncodedVideo() callback with a |track_number| bound - // in the callback. + // frame size. void AddVideoTrack(const gfx::Size& frame_size, double frame_rate); // IMkvWriter interface. @@ -68,7 +68,7 @@ class MEDIA_EXPORT WebmMuxer : public NON_EXPORTED_BASE(mkvmuxer::IMkvWriter) { void ElementStartNotify(mkvmuxer::uint64 element_id, mkvmuxer::int64 position) override; - // Used to DCHECK that we are called on the correct thread. + // Used to DCHECK that we are called on the correct thread (usually IO) base::ThreadChecker thread_checker_; // A caller-side identifier to interact with |segment_|, initialised upon diff --git a/media/capture/webm_muxer_unittest.cc b/media/capture/webm_muxer_unittest.cc index e3fd4d4..bde9b4f 100644 --- a/media/capture/webm_muxer_unittest.cc +++ b/media/capture/webm_muxer_unittest.cc @@ -34,8 +34,9 @@ class WebmMuxerTest : public testing::Test, public EventHandlerInterface { last_encoded_length_(0), accumulated_position_(0) { EXPECT_EQ(webm_muxer_.Position(), 0); + const mkvmuxer::int64 kRandomNewPosition = 333; + EXPECT_EQ(webm_muxer_.Position(kRandomNewPosition), -1); EXPECT_FALSE(webm_muxer_.Seekable()); - EXPECT_EQ(webm_muxer_.segment_.mode(), mkvmuxer::Segment::kLive); } MOCK_METHOD1(WriteCallback, void(const base::StringPiece&)); @@ -49,6 +50,10 @@ class WebmMuxerTest : public testing::Test, public EventHandlerInterface { return webm_muxer_.Position(); } + mkvmuxer::Segment::Mode GetWebmSegmentMode() const { + return webm_muxer_.segment_.mode(); + } + mkvmuxer::int32 WebmMuxerWrite(const void* buf, mkvmuxer::uint32 len) { return webm_muxer_.Write(buf, len); } @@ -95,6 +100,7 @@ TEST_F(WebmMuxerTest, OnEncodedVideoTwoFrames) { EXPECT_EQ(last_encoded_length_, encoded_data.size()); EXPECT_EQ(GetWebmMuxerPosition(), accumulated_position_); EXPECT_GE(GetWebmMuxerPosition(), static_cast<int64_t>(last_encoded_length_)); + EXPECT_EQ(GetWebmSegmentMode(), mkvmuxer::Segment::kLive); const int64_t begin_of_second_block = accumulated_position_; EXPECT_CALL(*this, WriteCallback(_)) |