Chromium Code Reviews| Index: content/renderer/media/video_track_recorder.cc |
| diff --git a/content/renderer/media/video_track_recorder.cc b/content/renderer/media/video_track_recorder.cc |
| index 60b919c5a3fa9129053996d82d526d93cb4fae76..6a2e68f42a56c7bb8b374015fed6b9c4a70ba211 100644 |
| --- a/content/renderer/media/video_track_recorder.cc |
| +++ b/content/renderer/media/video_track_recorder.cc |
| @@ -30,6 +30,40 @@ using media::VideoFrameMetadata; |
| namespace content { |
| +// Base class to describe a generic Encoder. This class is used to encapsulate |
| +// interactions with actual encoders, encoding and delivery of received frames. |
| +// This class is ref-counted to allow the MediaStreamVideoTrack to hold a |
| +// reference to it, via the callback that MediaStreamVideoSink passes along. |
| +// Also, it is quite common that encoders run in a background thread. |
| +class VideoTrackRecorder::Encoder : public base::RefCountedThreadSafe<Encoder> { |
| + public: |
| + Encoder(const OnEncodedVideoCB& on_encoded_video_callback, |
| + int32_t bits_per_second) |
| + : paused_(false), |
| + on_encoded_video_callback_(on_encoded_video_callback), |
| + bits_per_second_(bits_per_second) {} |
| + |
| + virtual void StartFrameEncode(const scoped_refptr<VideoFrame>& frame, |
|
emircan
2016/04/15 02:07:10
s/StartFrameEncode/EncodeFrame/?
|
| + base::TimeTicks capture_timestamp) = 0; |
| + |
| + void set_paused(bool paused) { paused_ = paused; } |
|
emircan
2016/04/15 02:07:10
I would rather leave this to the implementation, s
|
| + |
| + protected: |
| + friend class base::RefCountedThreadSafe<Encoder>; |
| + virtual ~Encoder() {} |
| + |
| + // While |paused_|, frames are not encoded. |
| + bool paused_; |
| + |
| + // This callback should be exercised on IO thread. |
| + const OnEncodedVideoCB on_encoded_video_callback_; |
| + |
| + // Target bitrate or video encoding. If 0, a standard bitrate is used. |
| + const int32_t bits_per_second_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(Encoder); |
| +}; |
| + |
| namespace { |
| const vpx_codec_flags_t kNoFlags = 0; |
| @@ -59,13 +93,8 @@ void OnFrameEncodeCompleted( |
| on_encoded_video_cb.Run(frame, std::move(data), capture_timestamp, keyframe); |
| } |
| -} // anonymous namespace |
| - |
| -// Inner class encapsulating all libvpx interactions and the encoding+delivery |
| -// of received frames. Limitation: Only VP8 is supported for the time being. |
| -// This class must be ref-counted because the MediaStreamVideoTrack will hold a |
| -// reference to it, via the callback MediaStreamVideoSink passes along, and it's |
| -// unknown when exactly it will release that reference. This class: |
| +// Class encapsulating libvpx interactions, encoding and delivery of received |
| +// frames. This class: |
| // - is created and destroyed on its parent's thread (usually the main Render |
| // thread); |
| // - receives VideoFrames and Run()s the callbacks on |origin_task_runner_|, |
| @@ -73,24 +102,21 @@ void OnFrameEncodeCompleted( |
| // thread, but this is not enforced; |
| // - uses an internal |encoding_thread_| for libvpx interactions, notably for |
| // encoding (which might take some time). |
| -class VideoTrackRecorder::VpxEncoder final |
| - : public base::RefCountedThreadSafe<VpxEncoder> { |
| +class VpxEncoder final : public VideoTrackRecorder::Encoder { |
| public: |
| static void ShutdownEncoder(std::unique_ptr<base::Thread> encoding_thread, |
| ScopedVpxCodecCtxPtr encoder); |
| - VpxEncoder(bool use_vp9, |
| - const OnEncodedVideoCB& on_encoded_video_callback, |
| - int32_t bits_per_second); |
| + VpxEncoder( |
| + bool use_vp9, |
| + const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback, |
| + int32_t bits_per_second); |
| void StartFrameEncode(const scoped_refptr<VideoFrame>& frame, |
| - base::TimeTicks capture_timestamp); |
| - |
| - void set_paused(bool paused) { paused_ = paused; } |
| + base::TimeTicks capture_timestamp) override; |
| private: |
| - friend class base::RefCountedThreadSafe<VpxEncoder>; |
| - ~VpxEncoder(); |
| + ~VpxEncoder() override; |
| void EncodeOnEncodingThread(const scoped_refptr<VideoFrame>& frame, |
| base::TimeTicks capture_timestamp); |
| @@ -104,18 +130,9 @@ class VideoTrackRecorder::VpxEncoder final |
| base::TimeDelta CalculateFrameDuration( |
| const scoped_refptr<VideoFrame>& frame); |
| - // While |paused_|, frames are not encoded. |
| - bool paused_; |
| - |
| // Force usage of VP9 for encoding, instead of VP8 which is the default. |
| const bool use_vp9_; |
| - // This callback should be exercised on IO thread. |
| - const OnEncodedVideoCB on_encoded_video_callback_; |
| - |
| - // Target bitrate or video encoding. If 0, a standard bitrate is used. |
| - const int32_t bits_per_second_; |
| - |
| // Used to shutdown properly on the same thread we were created. |
| const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; |
| @@ -139,22 +156,19 @@ class VideoTrackRecorder::VpxEncoder final |
| }; |
| // static |
| -void VideoTrackRecorder::VpxEncoder::ShutdownEncoder( |
| - std::unique_ptr<base::Thread> encoding_thread, |
| - ScopedVpxCodecCtxPtr encoder) { |
| +void VpxEncoder::ShutdownEncoder(std::unique_ptr<base::Thread> encoding_thread, |
| + ScopedVpxCodecCtxPtr encoder) { |
| DCHECK(encoding_thread->IsRunning()); |
| encoding_thread->Stop(); |
| // Both |encoding_thread| and |encoder| will be destroyed at end-of-scope. |
| } |
| -VideoTrackRecorder::VpxEncoder::VpxEncoder( |
| +VpxEncoder::VpxEncoder( |
| bool use_vp9, |
| - const OnEncodedVideoCB& on_encoded_video_callback, |
| + const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback, |
| int32_t bits_per_second) |
| - : paused_(false), |
| + : Encoder(on_encoded_video_callback, bits_per_second), |
| use_vp9_(use_vp9), |
| - on_encoded_video_callback_(on_encoded_video_callback), |
| - bits_per_second_(bits_per_second), |
| main_task_runner_(base::MessageLoop::current()->task_runner()), |
| encoding_thread_(new base::Thread("EncodingThread")) { |
| DCHECK(!on_encoded_video_callback_.is_null()); |
| @@ -165,16 +179,15 @@ VideoTrackRecorder::VpxEncoder::VpxEncoder( |
| encoding_thread_->Start(); |
| } |
| -VideoTrackRecorder::VpxEncoder::~VpxEncoder() { |
| +VpxEncoder::~VpxEncoder() { |
| main_task_runner_->PostTask(FROM_HERE, |
| base::Bind(&VpxEncoder::ShutdownEncoder, |
| base::Passed(&encoding_thread_), |
| base::Passed(&encoder_))); |
| } |
| -void VideoTrackRecorder::VpxEncoder::StartFrameEncode( |
| - const scoped_refptr<VideoFrame>& frame, |
| - base::TimeTicks capture_timestamp) { |
| +void VpxEncoder::StartFrameEncode(const scoped_refptr<VideoFrame>& frame, |
| + base::TimeTicks capture_timestamp) { |
| // Cache the thread sending frames on first frame arrival. |
| if (!origin_task_runner_.get()) |
| origin_task_runner_ = base::MessageLoop::current()->task_runner(); |
| @@ -186,11 +199,10 @@ void VideoTrackRecorder::VpxEncoder::StartFrameEncode( |
| this, frame, capture_timestamp)); |
| } |
| -void VideoTrackRecorder::VpxEncoder::EncodeOnEncodingThread( |
| +void VpxEncoder::EncodeOnEncodingThread( |
| const scoped_refptr<VideoFrame>& video_frame, |
| base::TimeTicks capture_timestamp) { |
| - TRACE_EVENT0("video", |
| - "VideoTrackRecorder::VpxEncoder::EncodeOnEncodingThread"); |
| + TRACE_EVENT0("video", "VpxEncoder::EncodeOnEncodingThread"); |
| DCHECK(encoding_thread_->task_runner()->BelongsToCurrentThread()); |
| if (!(video_frame->format() == media::PIXEL_FORMAT_I420 || |
| @@ -259,7 +271,7 @@ void VideoTrackRecorder::VpxEncoder::EncodeOnEncodingThread( |
| keyframe)); |
| } |
| -void VideoTrackRecorder::VpxEncoder::ConfigureEncoding(const gfx::Size& size) { |
| +void VpxEncoder::ConfigureEncoding(const gfx::Size& size) { |
| if (IsInitialized()) { |
| // TODO(mcasas) VP8 quirk/optimisation: If the new |size| is strictly less- |
| // than-or-equal than the old size, in terms of area, the existing encoder |
| @@ -351,12 +363,12 @@ void VideoTrackRecorder::VpxEncoder::ConfigureEncoding(const gfx::Size& size) { |
| } |
| } |
| -bool VideoTrackRecorder::VpxEncoder::IsInitialized() const { |
| +bool VpxEncoder::IsInitialized() const { |
| DCHECK(encoding_thread_->task_runner()->BelongsToCurrentThread()); |
| return codec_config_.g_timebase.den != 0; |
| } |
| -base::TimeDelta VideoTrackRecorder::VpxEncoder::CalculateFrameDuration( |
| +base::TimeDelta VpxEncoder::CalculateFrameDuration( |
| const scoped_refptr<VideoFrame>& frame) { |
| DCHECK(encoding_thread_->task_runner()->BelongsToCurrentThread()); |
| @@ -381,6 +393,8 @@ base::TimeDelta VideoTrackRecorder::VpxEncoder::CalculateFrameDuration( |
| kMinFrameDuration)); |
| } |
| +} // anonymous namespace |
| + |
| VideoTrackRecorder::VideoTrackRecorder( |
| CodecId codec, |
| const blink::WebMediaStreamTrack& track, |
| @@ -397,7 +411,7 @@ VideoTrackRecorder::VideoTrackRecorder( |
| // StartFrameEncode() will be called on Render IO thread. |
| MediaStreamVideoSink::ConnectToTrack( |
| track_, |
| - base::Bind(&VideoTrackRecorder::VpxEncoder::StartFrameEncode, encoder_)); |
| + base::Bind(&VideoTrackRecorder::Encoder::StartFrameEncode, encoder_)); |
| } |
| VideoTrackRecorder::~VideoTrackRecorder() { |