OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/media/video_track_recorder.h" | 5 #include "content/renderer/media/video_track_recorder.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 12 matching lines...) Expand all Loading... | |
23 #define VPX_CODEC_DISABLE_COMPAT 1 | 23 #define VPX_CODEC_DISABLE_COMPAT 1 |
24 #include "third_party/libvpx/source/libvpx/vpx/vp8cx.h" | 24 #include "third_party/libvpx/source/libvpx/vpx/vp8cx.h" |
25 #include "third_party/libvpx/source/libvpx/vpx/vpx_encoder.h" | 25 #include "third_party/libvpx/source/libvpx/vpx/vpx_encoder.h" |
26 } | 26 } |
27 | 27 |
28 using media::VideoFrame; | 28 using media::VideoFrame; |
29 using media::VideoFrameMetadata; | 29 using media::VideoFrameMetadata; |
30 | 30 |
31 namespace content { | 31 namespace content { |
32 | 32 |
33 // Base class to describe a generic Encoder. This class is used to encapsulate | |
34 // interactions with actual encoders, encoding and delivery of received frames. | |
35 // This class is ref-counted to allow the MediaStreamVideoTrack to hold a | |
36 // reference to it, via the callback that MediaStreamVideoSink passes along. | |
37 // Also, it is quite common that encoders run in a background thread. | |
38 class VideoTrackRecorder::Encoder : public base::RefCountedThreadSafe<Encoder> { | |
39 public: | |
40 Encoder(const OnEncodedVideoCB& on_encoded_video_callback, | |
41 int32_t bits_per_second) | |
42 : paused_(false), | |
43 on_encoded_video_callback_(on_encoded_video_callback), | |
44 bits_per_second_(bits_per_second) {} | |
45 | |
46 virtual void StartFrameEncode(const scoped_refptr<VideoFrame>& frame, | |
emircan
2016/04/15 02:07:10
s/StartFrameEncode/EncodeFrame/?
| |
47 base::TimeTicks capture_timestamp) = 0; | |
48 | |
49 void set_paused(bool paused) { paused_ = paused; } | |
emircan
2016/04/15 02:07:10
I would rather leave this to the implementation, s
| |
50 | |
51 protected: | |
52 friend class base::RefCountedThreadSafe<Encoder>; | |
53 virtual ~Encoder() {} | |
54 | |
55 // While |paused_|, frames are not encoded. | |
56 bool paused_; | |
57 | |
58 // This callback should be exercised on IO thread. | |
59 const OnEncodedVideoCB on_encoded_video_callback_; | |
60 | |
61 // Target bitrate or video encoding. If 0, a standard bitrate is used. | |
62 const int32_t bits_per_second_; | |
63 | |
64 DISALLOW_COPY_AND_ASSIGN(Encoder); | |
65 }; | |
66 | |
33 namespace { | 67 namespace { |
34 | 68 |
35 const vpx_codec_flags_t kNoFlags = 0; | 69 const vpx_codec_flags_t kNoFlags = 0; |
36 | 70 |
37 // Originally from remoting/codec/scoped_vpx_codec.h. | 71 // Originally from remoting/codec/scoped_vpx_codec.h. |
38 // TODO(mcasas): Refactor into a common location. | 72 // TODO(mcasas): Refactor into a common location. |
39 struct VpxCodecDeleter { | 73 struct VpxCodecDeleter { |
40 void operator()(vpx_codec_ctx_t* codec) { | 74 void operator()(vpx_codec_ctx_t* codec) { |
41 if (!codec) | 75 if (!codec) |
42 return; | 76 return; |
43 vpx_codec_err_t ret = vpx_codec_destroy(codec); | 77 vpx_codec_err_t ret = vpx_codec_destroy(codec); |
44 CHECK_EQ(ret, VPX_CODEC_OK); | 78 CHECK_EQ(ret, VPX_CODEC_OK); |
45 delete codec; | 79 delete codec; |
46 } | 80 } |
47 }; | 81 }; |
48 | 82 |
49 typedef std::unique_ptr<vpx_codec_ctx_t, VpxCodecDeleter> ScopedVpxCodecCtxPtr; | 83 typedef std::unique_ptr<vpx_codec_ctx_t, VpxCodecDeleter> ScopedVpxCodecCtxPtr; |
50 | 84 |
51 void OnFrameEncodeCompleted( | 85 void OnFrameEncodeCompleted( |
52 const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_cb, | 86 const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_cb, |
53 const scoped_refptr<VideoFrame>& frame, | 87 const scoped_refptr<VideoFrame>& frame, |
54 std::unique_ptr<std::string> data, | 88 std::unique_ptr<std::string> data, |
55 base::TimeTicks capture_timestamp, | 89 base::TimeTicks capture_timestamp, |
56 bool keyframe) { | 90 bool keyframe) { |
57 DVLOG(1) << (keyframe ? "" : "non ") << "keyframe "<< data->length() << "B, " | 91 DVLOG(1) << (keyframe ? "" : "non ") << "keyframe "<< data->length() << "B, " |
58 << capture_timestamp << " ms"; | 92 << capture_timestamp << " ms"; |
59 on_encoded_video_cb.Run(frame, std::move(data), capture_timestamp, keyframe); | 93 on_encoded_video_cb.Run(frame, std::move(data), capture_timestamp, keyframe); |
60 } | 94 } |
61 | 95 |
62 } // anonymous namespace | 96 // Class encapsulating libvpx interactions, encoding and delivery of received |
63 | 97 // frames. This class: |
64 // Inner class encapsulating all libvpx interactions and the encoding+delivery | |
65 // of received frames. Limitation: Only VP8 is supported for the time being. | |
66 // This class must be ref-counted because the MediaStreamVideoTrack will hold a | |
67 // reference to it, via the callback MediaStreamVideoSink passes along, and it's | |
68 // unknown when exactly it will release that reference. This class: | |
69 // - is created and destroyed on its parent's thread (usually the main Render | 98 // - is created and destroyed on its parent's thread (usually the main Render |
70 // thread); | 99 // thread); |
71 // - receives VideoFrames and Run()s the callbacks on |origin_task_runner_|, | 100 // - receives VideoFrames and Run()s the callbacks on |origin_task_runner_|, |
72 // which is cached on first frame arrival, and is supposed to be the render IO | 101 // which is cached on first frame arrival, and is supposed to be the render IO |
73 // thread, but this is not enforced; | 102 // thread, but this is not enforced; |
74 // - uses an internal |encoding_thread_| for libvpx interactions, notably for | 103 // - uses an internal |encoding_thread_| for libvpx interactions, notably for |
75 // encoding (which might take some time). | 104 // encoding (which might take some time). |
76 class VideoTrackRecorder::VpxEncoder final | 105 class VpxEncoder final : public VideoTrackRecorder::Encoder { |
77 : public base::RefCountedThreadSafe<VpxEncoder> { | |
78 public: | 106 public: |
79 static void ShutdownEncoder(std::unique_ptr<base::Thread> encoding_thread, | 107 static void ShutdownEncoder(std::unique_ptr<base::Thread> encoding_thread, |
80 ScopedVpxCodecCtxPtr encoder); | 108 ScopedVpxCodecCtxPtr encoder); |
81 | 109 |
82 VpxEncoder(bool use_vp9, | 110 VpxEncoder( |
83 const OnEncodedVideoCB& on_encoded_video_callback, | 111 bool use_vp9, |
84 int32_t bits_per_second); | 112 const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback, |
113 int32_t bits_per_second); | |
85 | 114 |
86 void StartFrameEncode(const scoped_refptr<VideoFrame>& frame, | 115 void StartFrameEncode(const scoped_refptr<VideoFrame>& frame, |
87 base::TimeTicks capture_timestamp); | 116 base::TimeTicks capture_timestamp) override; |
88 | |
89 void set_paused(bool paused) { paused_ = paused; } | |
90 | 117 |
91 private: | 118 private: |
92 friend class base::RefCountedThreadSafe<VpxEncoder>; | 119 ~VpxEncoder() override; |
93 ~VpxEncoder(); | |
94 | 120 |
95 void EncodeOnEncodingThread(const scoped_refptr<VideoFrame>& frame, | 121 void EncodeOnEncodingThread(const scoped_refptr<VideoFrame>& frame, |
96 base::TimeTicks capture_timestamp); | 122 base::TimeTicks capture_timestamp); |
97 | 123 |
98 void ConfigureEncoding(const gfx::Size& size); | 124 void ConfigureEncoding(const gfx::Size& size); |
99 | 125 |
100 // Returns true if |codec_config_| has been filled in at least once. | 126 // Returns true if |codec_config_| has been filled in at least once. |
101 bool IsInitialized() const; | 127 bool IsInitialized() const; |
102 | 128 |
103 // Estimate the frame duration from |frame| and |last_frame_timestamp_|. | 129 // Estimate the frame duration from |frame| and |last_frame_timestamp_|. |
104 base::TimeDelta CalculateFrameDuration( | 130 base::TimeDelta CalculateFrameDuration( |
105 const scoped_refptr<VideoFrame>& frame); | 131 const scoped_refptr<VideoFrame>& frame); |
106 | 132 |
107 // While |paused_|, frames are not encoded. | |
108 bool paused_; | |
109 | |
110 // Force usage of VP9 for encoding, instead of VP8 which is the default. | 133 // Force usage of VP9 for encoding, instead of VP8 which is the default. |
111 const bool use_vp9_; | 134 const bool use_vp9_; |
112 | 135 |
113 // This callback should be exercised on IO thread. | |
114 const OnEncodedVideoCB on_encoded_video_callback_; | |
115 | |
116 // Target bitrate or video encoding. If 0, a standard bitrate is used. | |
117 const int32_t bits_per_second_; | |
118 | |
119 // Used to shutdown properly on the same thread we were created. | 136 // Used to shutdown properly on the same thread we were created. |
120 const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; | 137 const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; |
121 | 138 |
122 // Task runner where frames to encode and reply callbacks must happen. | 139 // Task runner where frames to encode and reply callbacks must happen. |
123 scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner_; | 140 scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner_; |
124 | 141 |
125 // Thread for encoding. Active for the lifetime of VpxEncoder. All variables | 142 // Thread for encoding. Active for the lifetime of VpxEncoder. All variables |
126 // below this are used in this thread. | 143 // below this are used in this thread. |
127 std::unique_ptr<base::Thread> encoding_thread_; | 144 std::unique_ptr<base::Thread> encoding_thread_; |
128 // VP8 internal objects: configuration and encoder. | 145 // VP8 internal objects: configuration and encoder. |
129 vpx_codec_enc_cfg_t codec_config_; | 146 vpx_codec_enc_cfg_t codec_config_; |
130 // |encoder_| is a special scoped pointer to guarantee proper destruction. | 147 // |encoder_| is a special scoped pointer to guarantee proper destruction. |
131 // Again, it should only be accessed on |encoding_thread_|. | 148 // Again, it should only be accessed on |encoding_thread_|. |
132 ScopedVpxCodecCtxPtr encoder_; | 149 ScopedVpxCodecCtxPtr encoder_; |
133 | 150 |
134 // The |VideoFrame::timestamp()| of the last encoded frame. This is used to | 151 // The |VideoFrame::timestamp()| of the last encoded frame. This is used to |
135 // predict the duration of the next frame. | 152 // predict the duration of the next frame. |
136 base::TimeDelta last_frame_timestamp_; | 153 base::TimeDelta last_frame_timestamp_; |
137 | 154 |
138 DISALLOW_COPY_AND_ASSIGN(VpxEncoder); | 155 DISALLOW_COPY_AND_ASSIGN(VpxEncoder); |
139 }; | 156 }; |
140 | 157 |
141 // static | 158 // static |
142 void VideoTrackRecorder::VpxEncoder::ShutdownEncoder( | 159 void VpxEncoder::ShutdownEncoder(std::unique_ptr<base::Thread> encoding_thread, |
143 std::unique_ptr<base::Thread> encoding_thread, | 160 ScopedVpxCodecCtxPtr encoder) { |
144 ScopedVpxCodecCtxPtr encoder) { | |
145 DCHECK(encoding_thread->IsRunning()); | 161 DCHECK(encoding_thread->IsRunning()); |
146 encoding_thread->Stop(); | 162 encoding_thread->Stop(); |
147 // Both |encoding_thread| and |encoder| will be destroyed at end-of-scope. | 163 // Both |encoding_thread| and |encoder| will be destroyed at end-of-scope. |
148 } | 164 } |
149 | 165 |
150 VideoTrackRecorder::VpxEncoder::VpxEncoder( | 166 VpxEncoder::VpxEncoder( |
151 bool use_vp9, | 167 bool use_vp9, |
152 const OnEncodedVideoCB& on_encoded_video_callback, | 168 const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback, |
153 int32_t bits_per_second) | 169 int32_t bits_per_second) |
154 : paused_(false), | 170 : Encoder(on_encoded_video_callback, bits_per_second), |
155 use_vp9_(use_vp9), | 171 use_vp9_(use_vp9), |
156 on_encoded_video_callback_(on_encoded_video_callback), | |
157 bits_per_second_(bits_per_second), | |
158 main_task_runner_(base::MessageLoop::current()->task_runner()), | 172 main_task_runner_(base::MessageLoop::current()->task_runner()), |
159 encoding_thread_(new base::Thread("EncodingThread")) { | 173 encoding_thread_(new base::Thread("EncodingThread")) { |
160 DCHECK(!on_encoded_video_callback_.is_null()); | 174 DCHECK(!on_encoded_video_callback_.is_null()); |
161 | 175 |
162 codec_config_.g_timebase.den = 0; // Not initialized. | 176 codec_config_.g_timebase.den = 0; // Not initialized. |
163 | 177 |
164 DCHECK(!encoding_thread_->IsRunning()); | 178 DCHECK(!encoding_thread_->IsRunning()); |
165 encoding_thread_->Start(); | 179 encoding_thread_->Start(); |
166 } | 180 } |
167 | 181 |
168 VideoTrackRecorder::VpxEncoder::~VpxEncoder() { | 182 VpxEncoder::~VpxEncoder() { |
169 main_task_runner_->PostTask(FROM_HERE, | 183 main_task_runner_->PostTask(FROM_HERE, |
170 base::Bind(&VpxEncoder::ShutdownEncoder, | 184 base::Bind(&VpxEncoder::ShutdownEncoder, |
171 base::Passed(&encoding_thread_), | 185 base::Passed(&encoding_thread_), |
172 base::Passed(&encoder_))); | 186 base::Passed(&encoder_))); |
173 } | 187 } |
174 | 188 |
175 void VideoTrackRecorder::VpxEncoder::StartFrameEncode( | 189 void VpxEncoder::StartFrameEncode(const scoped_refptr<VideoFrame>& frame, |
176 const scoped_refptr<VideoFrame>& frame, | 190 base::TimeTicks capture_timestamp) { |
177 base::TimeTicks capture_timestamp) { | |
178 // Cache the thread sending frames on first frame arrival. | 191 // Cache the thread sending frames on first frame arrival. |
179 if (!origin_task_runner_.get()) | 192 if (!origin_task_runner_.get()) |
180 origin_task_runner_ = base::MessageLoop::current()->task_runner(); | 193 origin_task_runner_ = base::MessageLoop::current()->task_runner(); |
181 DCHECK(origin_task_runner_->BelongsToCurrentThread()); | 194 DCHECK(origin_task_runner_->BelongsToCurrentThread()); |
182 if (paused_) | 195 if (paused_) |
183 return; | 196 return; |
184 encoding_thread_->task_runner()->PostTask( | 197 encoding_thread_->task_runner()->PostTask( |
185 FROM_HERE, base::Bind(&VpxEncoder::EncodeOnEncodingThread, | 198 FROM_HERE, base::Bind(&VpxEncoder::EncodeOnEncodingThread, |
186 this, frame, capture_timestamp)); | 199 this, frame, capture_timestamp)); |
187 } | 200 } |
188 | 201 |
189 void VideoTrackRecorder::VpxEncoder::EncodeOnEncodingThread( | 202 void VpxEncoder::EncodeOnEncodingThread( |
190 const scoped_refptr<VideoFrame>& video_frame, | 203 const scoped_refptr<VideoFrame>& video_frame, |
191 base::TimeTicks capture_timestamp) { | 204 base::TimeTicks capture_timestamp) { |
192 TRACE_EVENT0("video", | 205 TRACE_EVENT0("video", "VpxEncoder::EncodeOnEncodingThread"); |
193 "VideoTrackRecorder::VpxEncoder::EncodeOnEncodingThread"); | |
194 DCHECK(encoding_thread_->task_runner()->BelongsToCurrentThread()); | 206 DCHECK(encoding_thread_->task_runner()->BelongsToCurrentThread()); |
195 | 207 |
196 if (!(video_frame->format() == media::PIXEL_FORMAT_I420 || | 208 if (!(video_frame->format() == media::PIXEL_FORMAT_I420 || |
197 video_frame->format() == media::PIXEL_FORMAT_YV12 || | 209 video_frame->format() == media::PIXEL_FORMAT_YV12 || |
198 video_frame->format() == media::PIXEL_FORMAT_YV12A)) { | 210 video_frame->format() == media::PIXEL_FORMAT_YV12A)) { |
199 NOTREACHED(); | 211 NOTREACHED(); |
200 return; | 212 return; |
201 } | 213 } |
202 scoped_refptr<media::VideoFrame> frame = video_frame; | 214 scoped_refptr<media::VideoFrame> frame = video_frame; |
203 // Drop alpha channel since we do not support it yet. | 215 // Drop alpha channel since we do not support it yet. |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
252 } | 264 } |
253 origin_task_runner_->PostTask(FROM_HERE, | 265 origin_task_runner_->PostTask(FROM_HERE, |
254 base::Bind(OnFrameEncodeCompleted, | 266 base::Bind(OnFrameEncodeCompleted, |
255 on_encoded_video_callback_, | 267 on_encoded_video_callback_, |
256 frame, | 268 frame, |
257 base::Passed(&data), | 269 base::Passed(&data), |
258 capture_timestamp, | 270 capture_timestamp, |
259 keyframe)); | 271 keyframe)); |
260 } | 272 } |
261 | 273 |
262 void VideoTrackRecorder::VpxEncoder::ConfigureEncoding(const gfx::Size& size) { | 274 void VpxEncoder::ConfigureEncoding(const gfx::Size& size) { |
263 if (IsInitialized()) { | 275 if (IsInitialized()) { |
264 // TODO(mcasas) VP8 quirk/optimisation: If the new |size| is strictly less- | 276 // TODO(mcasas) VP8 quirk/optimisation: If the new |size| is strictly less- |
265 // than-or-equal than the old size, in terms of area, the existing encoder | 277 // than-or-equal than the old size, in terms of area, the existing encoder |
266 // instance could be reused after changing |codec_config_.{g_w,g_h}|. | 278 // instance could be reused after changing |codec_config_.{g_w,g_h}|. |
267 DVLOG(1) << "Destroying/Re-Creating encoder for new frame size: " | 279 DVLOG(1) << "Destroying/Re-Creating encoder for new frame size: " |
268 << gfx::Size(codec_config_.g_w, codec_config_.g_h).ToString() | 280 << gfx::Size(codec_config_.g_w, codec_config_.g_h).ToString() |
269 << " --> " << size.ToString() << (use_vp9_ ? " vp9" : " vp8"); | 281 << " --> " << size.ToString() << (use_vp9_ ? " vp9" : " vp8"); |
270 encoder_.reset(); | 282 encoder_.reset(); |
271 } | 283 } |
272 | 284 |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
344 // the expense of quality up to a maximum value of 8 for VP9, by tuning the | 356 // the expense of quality up to a maximum value of 8 for VP9, by tuning the |
345 // target time spent encoding the frame. Go from 8 to 5 (values for real | 357 // target time spent encoding the frame. Go from 8 to 5 (values for real |
346 // time encoding) depending on the amount of cores available in the system. | 358 // time encoding) depending on the amount of cores available in the system. |
347 const int kCpuUsed = | 359 const int kCpuUsed = |
348 std::max(5, 8 - base::SysInfo::NumberOfProcessors() / 2); | 360 std::max(5, 8 - base::SysInfo::NumberOfProcessors() / 2); |
349 result = vpx_codec_control(encoder_.get(), VP8E_SET_CPUUSED, kCpuUsed); | 361 result = vpx_codec_control(encoder_.get(), VP8E_SET_CPUUSED, kCpuUsed); |
350 DLOG_IF(WARNING, VPX_CODEC_OK != result) << "VP8E_SET_CPUUSED failed"; | 362 DLOG_IF(WARNING, VPX_CODEC_OK != result) << "VP8E_SET_CPUUSED failed"; |
351 } | 363 } |
352 } | 364 } |
353 | 365 |
354 bool VideoTrackRecorder::VpxEncoder::IsInitialized() const { | 366 bool VpxEncoder::IsInitialized() const { |
355 DCHECK(encoding_thread_->task_runner()->BelongsToCurrentThread()); | 367 DCHECK(encoding_thread_->task_runner()->BelongsToCurrentThread()); |
356 return codec_config_.g_timebase.den != 0; | 368 return codec_config_.g_timebase.den != 0; |
357 } | 369 } |
358 | 370 |
359 base::TimeDelta VideoTrackRecorder::VpxEncoder::CalculateFrameDuration( | 371 base::TimeDelta VpxEncoder::CalculateFrameDuration( |
360 const scoped_refptr<VideoFrame>& frame) { | 372 const scoped_refptr<VideoFrame>& frame) { |
361 DCHECK(encoding_thread_->task_runner()->BelongsToCurrentThread()); | 373 DCHECK(encoding_thread_->task_runner()->BelongsToCurrentThread()); |
362 | 374 |
363 using base::TimeDelta; | 375 using base::TimeDelta; |
364 TimeDelta predicted_frame_duration; | 376 TimeDelta predicted_frame_duration; |
365 if (!frame->metadata()->GetTimeDelta(VideoFrameMetadata::FRAME_DURATION, | 377 if (!frame->metadata()->GetTimeDelta(VideoFrameMetadata::FRAME_DURATION, |
366 &predicted_frame_duration) || | 378 &predicted_frame_duration) || |
367 predicted_frame_duration <= TimeDelta()) { | 379 predicted_frame_duration <= TimeDelta()) { |
368 // The source of the video frame did not provide the frame duration. Use | 380 // The source of the video frame did not provide the frame duration. Use |
369 // the actual amount of time between the current and previous frame as a | 381 // the actual amount of time between the current and previous frame as a |
370 // prediction for the next frame's duration. | 382 // prediction for the next frame's duration. |
371 // TODO(mcasas): This duration estimation could lead to artifacts if the | 383 // TODO(mcasas): This duration estimation could lead to artifacts if the |
372 // cadence of the received stream is compromised (e.g. camera freeze, pause, | 384 // cadence of the received stream is compromised (e.g. camera freeze, pause, |
373 // remote packet loss). Investigate using GetFrameRate() in this case. | 385 // remote packet loss). Investigate using GetFrameRate() in this case. |
374 predicted_frame_duration = frame->timestamp() - last_frame_timestamp_; | 386 predicted_frame_duration = frame->timestamp() - last_frame_timestamp_; |
375 } | 387 } |
376 last_frame_timestamp_ = frame->timestamp(); | 388 last_frame_timestamp_ = frame->timestamp(); |
377 // Make sure |predicted_frame_duration| is in a safe range of values. | 389 // Make sure |predicted_frame_duration| is in a safe range of values. |
378 const TimeDelta kMaxFrameDuration = TimeDelta::FromSecondsD(1.0 / 8); | 390 const TimeDelta kMaxFrameDuration = TimeDelta::FromSecondsD(1.0 / 8); |
379 const TimeDelta kMinFrameDuration = TimeDelta::FromMilliseconds(1); | 391 const TimeDelta kMinFrameDuration = TimeDelta::FromMilliseconds(1); |
380 return std::min(kMaxFrameDuration, std::max(predicted_frame_duration, | 392 return std::min(kMaxFrameDuration, std::max(predicted_frame_duration, |
381 kMinFrameDuration)); | 393 kMinFrameDuration)); |
382 } | 394 } |
383 | 395 |
396 } // anonymous namespace | |
397 | |
384 VideoTrackRecorder::VideoTrackRecorder( | 398 VideoTrackRecorder::VideoTrackRecorder( |
385 CodecId codec, | 399 CodecId codec, |
386 const blink::WebMediaStreamTrack& track, | 400 const blink::WebMediaStreamTrack& track, |
387 const OnEncodedVideoCB& on_encoded_video_callback, | 401 const OnEncodedVideoCB& on_encoded_video_callback, |
388 int32_t bits_per_second) | 402 int32_t bits_per_second) |
389 : track_(track), | 403 : track_(track), |
390 encoder_(new VpxEncoder(codec == CodecId::VP9, | 404 encoder_(new VpxEncoder(codec == CodecId::VP9, |
391 on_encoded_video_callback, | 405 on_encoded_video_callback, |
392 bits_per_second)) { | 406 bits_per_second)) { |
393 DCHECK(main_render_thread_checker_.CalledOnValidThread()); | 407 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
394 DCHECK(!track_.isNull()); | 408 DCHECK(!track_.isNull()); |
395 DCHECK(track_.getExtraData()); | 409 DCHECK(track_.getExtraData()); |
396 | 410 |
397 // StartFrameEncode() will be called on Render IO thread. | 411 // StartFrameEncode() will be called on Render IO thread. |
398 MediaStreamVideoSink::ConnectToTrack( | 412 MediaStreamVideoSink::ConnectToTrack( |
399 track_, | 413 track_, |
400 base::Bind(&VideoTrackRecorder::VpxEncoder::StartFrameEncode, encoder_)); | 414 base::Bind(&VideoTrackRecorder::Encoder::StartFrameEncode, encoder_)); |
401 } | 415 } |
402 | 416 |
403 VideoTrackRecorder::~VideoTrackRecorder() { | 417 VideoTrackRecorder::~VideoTrackRecorder() { |
404 DCHECK(main_render_thread_checker_.CalledOnValidThread()); | 418 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
405 MediaStreamVideoSink::DisconnectFromTrack(); | 419 MediaStreamVideoSink::DisconnectFromTrack(); |
406 track_.reset(); | 420 track_.reset(); |
407 } | 421 } |
408 | 422 |
409 void VideoTrackRecorder::Pause() { | 423 void VideoTrackRecorder::Pause() { |
410 DCHECK(main_render_thread_checker_.CalledOnValidThread()); | 424 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
411 DCHECK(encoder_); | 425 DCHECK(encoder_); |
412 encoder_->set_paused(true); | 426 encoder_->set_paused(true); |
413 } | 427 } |
414 | 428 |
415 void VideoTrackRecorder::Resume() { | 429 void VideoTrackRecorder::Resume() { |
416 DCHECK(main_render_thread_checker_.CalledOnValidThread()); | 430 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
417 DCHECK(encoder_); | 431 DCHECK(encoder_); |
418 encoder_->set_paused(false); | 432 encoder_->set_paused(false); |
419 } | 433 } |
420 | 434 |
421 void VideoTrackRecorder::OnVideoFrameForTesting( | 435 void VideoTrackRecorder::OnVideoFrameForTesting( |
422 const scoped_refptr<media::VideoFrame>& frame, | 436 const scoped_refptr<media::VideoFrame>& frame, |
423 base::TimeTicks timestamp) { | 437 base::TimeTicks timestamp) { |
424 encoder_->StartFrameEncode(frame, timestamp); | 438 encoder_->StartFrameEncode(frame, timestamp); |
425 } | 439 } |
426 | 440 |
427 } // namespace content | 441 } // namespace content |
OLD | NEW |