summaryrefslogtreecommitdiffstats
path: root/media/capture
diff options
context:
space:
mode:
authormcasas <mcasas@chromium.org>2015-09-09 16:32:06 -0700
committerCommit bot <commit-bot@chromium.org>2015-09-09 23:32:47 +0000
commit1567842287b4097350d33c14e5f795559fa008b5 (patch)
treef50a9f48f649abf87a84590681bf9516026ee812 /media/capture
parent7606f64ba73cbc175f2dbffe2d20714bab299de2 (diff)
downloadchromium_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.cc25
-rw-r--r--media/capture/webm_muxer.h10
-rw-r--r--media/capture/webm_muxer_unittest.cc8
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(_))