Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(309)

Side by Side Diff: content/renderer/media/video_track_recorder.cc

Issue 1313603004: MediaRecorderHandler (video part) and unittests (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase, gyp and MediaRecorderHandlerTest Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "base/bind.h" 7 #include "base/bind.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/sys_info.h" 9 #include "base/sys_info.h"
10 #include "base/threading/thread.h" 10 #include "base/threading/thread.h"
11 #include "base/time/time.h" 11 #include "base/time/time.h"
12 #include "base/trace_event/trace_event.h" 12 #include "base/trace_event/trace_event.h"
13 #include "content/child/child_process.h"
14 #include "media/base/bind_to_current_loop.h"
15 #include "media/base/video_frame.h" 13 #include "media/base/video_frame.h"
16 14
17 extern "C" { 15 extern "C" {
18 // VPX_CODEC_DISABLE_COMPAT excludes parts of the libvpx API that provide 16 // VPX_CODEC_DISABLE_COMPAT excludes parts of the libvpx API that provide
19 // backwards compatibility for legacy applications using the library. 17 // backwards compatibility for legacy applications using the library.
20 #define VPX_CODEC_DISABLE_COMPAT 1 18 #define VPX_CODEC_DISABLE_COMPAT 1
21 #include "third_party/libvpx/source/libvpx/vpx/vp8cx.h" 19 #include "third_party/libvpx/source/libvpx/vpx/vp8cx.h"
22 #include "third_party/libvpx/source/libvpx/vpx/vpx_encoder.h" 20 #include "third_party/libvpx/source/libvpx/vpx/vpx_encoder.h"
23 } 21 }
24 22
25 using media::VideoFrame; 23 using media::VideoFrame;
26 using media::VideoFrameMetadata; 24 using media::VideoFrameMetadata;
27 25
28 namespace content { 26 namespace content {
29 27
30 namespace { 28 namespace {
29
31 const vpx_codec_flags_t kNoFlags = 0; 30 const vpx_codec_flags_t kNoFlags = 0;
32 31
32 // Originally from remoting/codec/scoped_vpx_codec.h.
33 // TODO(mcasas): Refactor into a common location.
34 struct VpxCodecDeleter {
35 void operator()(vpx_codec_ctx_t* codec) {
36 if (!codec)
37 return;
38 vpx_codec_err_t ret = vpx_codec_destroy(codec);
39 CHECK_EQ(ret, VPX_CODEC_OK) << "Failed to destroy codec";
miu 2015/09/02 21:28:13 nit: No need for the logging string.
mcasas 2015/09/04 02:16:30 Done.
40 delete codec;
41 }
42 };
43
44 typedef scoped_ptr<vpx_codec_ctx_t, VpxCodecDeleter> ScopedVpxCodec;
45
33 void OnFrameEncodeCompleted( 46 void OnFrameEncodeCompleted(
34 const content::VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_cb, 47 const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_cb,
35 const scoped_refptr<VideoFrame>& frame, 48 const scoped_refptr<VideoFrame>& frame,
36 scoped_ptr<std::string> data, 49 scoped_ptr<std::string> data,
37 base::TimeTicks capture_timestamp, 50 base::TimeTicks capture_timestamp,
38 bool keyframe) { 51 bool keyframe) {
39 DVLOG(1) << (keyframe ? "" : "non ") << "keyframe " 52 DVLOG(1) << (keyframe ? "" : "non ") << "keyframe "<< data->length() << "B, "
40 << capture_timestamp << " ms - " << data->length() << "B "; 53 << capture_timestamp << " ms";
41 on_encoded_video_cb.Run(frame, base::StringPiece(*data), capture_timestamp, 54 on_encoded_video_cb.Run(frame, base::StringPiece(*data), capture_timestamp,
42 keyframe); 55 keyframe);
43 } 56 }
44 57
45 } // anonymous namespace 58 } // anonymous namespace
46 59
47 // Inner class encapsulating all libvpx interactions and the encoding+delivery 60 // Inner class encapsulating all libvpx interactions and the encoding+delivery
48 // of received frames. This class is: 61 // of received frames. Limitation: Only VP8 is supported for the time being.
49 // - created and destroyed on its parent's thread (usually the main render 62 // This class needs to be ref-counted to avoid destruction (of |encoder_| in
50 // thread), 63 // particular) while there's still a frame being processed in either IO or
51 // - receives VideoFrames and Run()s the callbacks on another thread (supposedly 64 // encode threads. This class:
52 // the render IO thread), which is cached on first frame arrival, 65 // - is created and destroyed on its parent's thread, usually the main Render
66 // thread;
67 // - receives VideoFrames and Run()s the callbacks on |origin_task_runner_|,
68 // which is cached on first frame arrival, usually this thread is to be the
69 // render IO thread, but this is not enforced;
53 // - uses an internal |encoding_thread_| for libvpx interactions, notably for 70 // - uses an internal |encoding_thread_| for libvpx interactions, notably for
54 // encoding (which might take some time). 71 // encoding (which might take some time).
55 // Only VP8 is supported for the time being. 72 class VideoTrackRecorder::VpxEncoder final
56 class VideoTrackRecorder::VpxEncoder final { 73 : public base::RefCountedThreadSafe<VpxEncoder> {
57 public: 74 public:
58 explicit VpxEncoder(const OnEncodedVideoCB& on_encoded_video_callback); 75 explicit VpxEncoder(const OnEncodedVideoCB& on_encoded_video_callback);
59 ~VpxEncoder();
60 76
61 void StartFrameEncode(const scoped_refptr<VideoFrame>& frame, 77 void StartFrameEncode(const scoped_refptr<VideoFrame>& frame,
62 base::TimeTicks capture_timestamp); 78 base::TimeTicks capture_timestamp);
63 79
64 private: 80 private:
81 friend class base::RefCountedThreadSafe<VpxEncoder>;
82 ~VpxEncoder();
83
65 void EncodeOnEncodingThread(const scoped_refptr<VideoFrame>& frame, 84 void EncodeOnEncodingThread(const scoped_refptr<VideoFrame>& frame,
66 base::TimeTicks capture_timestamp); 85 base::TimeTicks capture_timestamp);
67 86
68 void ConfigureVp8Encoding(const gfx::Size& size); 87 void ConfigureVp8Encoding(const gfx::Size& size);
69 88
70 // Returns true if |codec_config_| has been filled in at least once. 89 // Returns true if |codec_config_| has been filled in at least once.
71 bool IsInitialized() const; 90 bool IsInitialized() const;
72 91
73 // Estimate the frame duration from |frame| and |last_frame_timestamp_|. 92 // Estimate the frame duration from |frame| and |last_frame_timestamp_|.
74 base::TimeDelta CalculateFrameDuration( 93 base::TimeDelta CalculateFrameDuration(
75 const scoped_refptr<VideoFrame>& frame); 94 const scoped_refptr<VideoFrame>& frame);
76 95
77 // Used to check that we are destroyed on the same thread we were created. 96 // Used to check that we are destroyed on the same thread we were created.
78 base::ThreadChecker main_render_thread_checker_; 97 base::ThreadChecker main_render_thread_checker_;
79 98
80 // Task runner where frames to encode and reply callbacks must happen. 99 // Task runner where frames to encode and reply callbacks must happen.
81 scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner_; 100 scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner_;
82 101
83 // This callback should be exercised on IO thread. 102 // This callback should be exercised on IO thread.
84 const OnEncodedVideoCB on_encoded_video_callback_; 103 const OnEncodedVideoCB on_encoded_video_callback_;
85 104
86 // Thread for encoding. Active as long as VpxEncoder exists. All variables 105 // Thread for encoding. Active as long as VpxEncoder exists. All variables
87 // below this are used in this thread. 106 // below this are used in this thread.
88 base::Thread encoding_thread_; 107 base::Thread encoding_thread_;
89 // VP8 internal objects: configuration, encoder and Vpx Image wrapper. 108 // VP8 internal objects: configuration and encoder.
90 vpx_codec_enc_cfg_t codec_config_; 109 vpx_codec_enc_cfg_t codec_config_;
91 vpx_codec_ctx_t encoder_; 110 // |encoder_| is a special scoped pointer to guarantee proper destruction.
111 ScopedVpxCodec encoder_;
92 112
93 // The |VideoFrame::timestamp()| of the last encoded frame. This is used to 113 // The |VideoFrame::timestamp()| of the last encoded frame. This is used to
94 // predict the duration of the next frame. 114 // predict the duration of the next frame.
95 base::TimeDelta last_frame_timestamp_; 115 base::TimeDelta last_frame_timestamp_;
96 116
97 DISALLOW_COPY_AND_ASSIGN(VpxEncoder); 117 DISALLOW_COPY_AND_ASSIGN(VpxEncoder);
98 }; 118 };
99 119
100 VideoTrackRecorder::VpxEncoder::VpxEncoder( 120 VideoTrackRecorder::VpxEncoder::VpxEncoder(
101 const OnEncodedVideoCB& on_encoded_video_callback) 121 const OnEncodedVideoCB& on_encoded_video_callback)
102 : on_encoded_video_callback_(on_encoded_video_callback), 122 : on_encoded_video_callback_(on_encoded_video_callback),
103 encoding_thread_("EncodingThread") { 123 encoding_thread_("EncodingThread") {
104 DCHECK(!on_encoded_video_callback_.is_null()); 124 DCHECK(!on_encoded_video_callback_.is_null());
105 125
106 codec_config_.g_timebase.den = 0; // Not initialized. 126 codec_config_.g_timebase.den = 0; // Not initialized.
107 127
108 DCHECK(!encoding_thread_.IsRunning()); 128 DCHECK(!encoding_thread_.IsRunning());
109 encoding_thread_.Start(); 129 encoding_thread_.Start();
110 } 130 }
111 131
112 VideoTrackRecorder::VpxEncoder::~VpxEncoder() { 132 VideoTrackRecorder::VpxEncoder::~VpxEncoder() {
113 DCHECK(main_render_thread_checker_.CalledOnValidThread()); 133 DCHECK(main_render_thread_checker_.CalledOnValidThread());
miu 2015/09/02 21:28:13 Because this is now ref-counted, there is no guara
mcasas 2015/09/04 02:16:30 You're right. I've checked other MediaStreamVideo
miu 2015/09/04 21:48:52 Seem to me that you can write a dtor that is able
mcasas 2015/09/05 02:43:01 Done.
114 DCHECK(encoding_thread_.IsRunning()); 134 DCHECK(encoding_thread_.IsRunning());
115 encoding_thread_.Stop(); 135 encoding_thread_.Stop();
116 vpx_codec_destroy(&encoder_);
117 } 136 }
118 137
119 void VideoTrackRecorder::VpxEncoder::StartFrameEncode( 138 void VideoTrackRecorder::VpxEncoder::StartFrameEncode(
120 const scoped_refptr<VideoFrame>& frame, 139 const scoped_refptr<VideoFrame>& frame,
121 base::TimeTicks capture_timestamp) { 140 base::TimeTicks capture_timestamp) {
122 // Cache the thread sending frames on first frame arrival. 141 // Cache the thread sending frames on first frame arrival.
123 if (!origin_task_runner_.get()) 142 if (!origin_task_runner_.get())
124 origin_task_runner_ = base::MessageLoop::current()->task_runner(); 143 origin_task_runner_ = base::MessageLoop::current()->task_runner();
125 DCHECK(origin_task_runner_->BelongsToCurrentThread()); 144 DCHECK(origin_task_runner_->BelongsToCurrentThread());
126 145
127 encoding_thread_.task_runner()->PostTask( 146 encoding_thread_.task_runner()->PostTask(
128 FROM_HERE, base::Bind(&VpxEncoder::EncodeOnEncodingThread, 147 FROM_HERE, base::Bind(&VpxEncoder::EncodeOnEncodingThread,
129 base::Unretained(this), frame, capture_timestamp)); 148 this, frame, capture_timestamp));
130 } 149 }
131 150
132 void VideoTrackRecorder::VpxEncoder::EncodeOnEncodingThread( 151 void VideoTrackRecorder::VpxEncoder::EncodeOnEncodingThread(
133 const scoped_refptr<VideoFrame>& frame, 152 const scoped_refptr<VideoFrame>& frame,
134 base::TimeTicks capture_timestamp) { 153 base::TimeTicks capture_timestamp) {
135 TRACE_EVENT0("video", 154 TRACE_EVENT0("video",
136 "VideoTrackRecorder::VpxEncoder::EncodeOnEncodingThread"); 155 "VideoTrackRecorder::VpxEncoder::EncodeOnEncodingThread");
137 DCHECK(encoding_thread_.task_runner()->BelongsToCurrentThread()); 156 DCHECK(encoding_thread_.task_runner()->BelongsToCurrentThread());
138 157
139 const gfx::Size frame_size = frame->visible_rect().size(); 158 const gfx::Size frame_size = frame->visible_rect().size();
(...skipping 14 matching lines...) Expand all
154 vpx_image.planes[VPX_PLANE_U] = frame->visible_data(VideoFrame::kUPlane); 173 vpx_image.planes[VPX_PLANE_U] = frame->visible_data(VideoFrame::kUPlane);
155 vpx_image.planes[VPX_PLANE_V] = frame->visible_data(VideoFrame::kVPlane); 174 vpx_image.planes[VPX_PLANE_V] = frame->visible_data(VideoFrame::kVPlane);
156 vpx_image.stride[VPX_PLANE_Y] = frame->stride(VideoFrame::kYPlane); 175 vpx_image.stride[VPX_PLANE_Y] = frame->stride(VideoFrame::kYPlane);
157 vpx_image.stride[VPX_PLANE_U] = frame->stride(VideoFrame::kUPlane); 176 vpx_image.stride[VPX_PLANE_U] = frame->stride(VideoFrame::kUPlane);
158 vpx_image.stride[VPX_PLANE_V] = frame->stride(VideoFrame::kVPlane); 177 vpx_image.stride[VPX_PLANE_V] = frame->stride(VideoFrame::kVPlane);
159 178
160 const base::TimeDelta duration = CalculateFrameDuration(frame); 179 const base::TimeDelta duration = CalculateFrameDuration(frame);
161 // Encode the frame. The presentation time stamp argument here is fixed to 180 // Encode the frame. The presentation time stamp argument here is fixed to
162 // zero to force the encoder to base its single-frame bandwidth calculations 181 // zero to force the encoder to base its single-frame bandwidth calculations
163 // entirely on |predicted_frame_duration|. 182 // entirely on |predicted_frame_duration|.
164 const vpx_codec_err_t ret = vpx_codec_encode(&encoder_, 183 const vpx_codec_err_t ret = vpx_codec_encode(encoder_.get(),
165 &vpx_image, 184 &vpx_image,
166 0 /* pts */, 185 0 /* pts */,
167 duration.InMicroseconds(), 186 duration.InMicroseconds(),
168 kNoFlags, 187 kNoFlags,
169 VPX_DL_REALTIME); 188 VPX_DL_REALTIME);
170 DCHECK_EQ(ret, VPX_CODEC_OK) << vpx_codec_err_to_string(ret) << ", #" 189 DCHECK_EQ(ret, VPX_CODEC_OK) << vpx_codec_err_to_string(ret) << ", #"
171 << vpx_codec_error(&encoder_) << " -" 190 << vpx_codec_error(encoder_.get()) << " -"
172 << vpx_codec_error_detail(&encoder_); 191 << vpx_codec_error_detail(encoder_.get());
173 192
174 scoped_ptr<std::string> data(new std::string); 193 scoped_ptr<std::string> data(new std::string);
175 bool keyframe = false; 194 bool keyframe = false;
176 vpx_codec_iter_t iter = NULL; 195 vpx_codec_iter_t iter = NULL;
177 const vpx_codec_cx_pkt_t* pkt = NULL; 196 const vpx_codec_cx_pkt_t* pkt = NULL;
178 while ((pkt = vpx_codec_get_cx_data(&encoder_, &iter)) != NULL) { 197 while ((pkt = vpx_codec_get_cx_data(encoder_.get(), &iter)) != NULL) {
179 if (pkt->kind != VPX_CODEC_CX_FRAME_PKT) 198 if (pkt->kind != VPX_CODEC_CX_FRAME_PKT)
180 continue; 199 continue;
181 data->assign(static_cast<char*>(pkt->data.frame.buf), pkt->data.frame.sz); 200 data->assign(static_cast<char*>(pkt->data.frame.buf), pkt->data.frame.sz);
182 keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0; 201 keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0;
183 break; 202 break;
184 } 203 }
185 origin_task_runner_->PostTask(FROM_HERE, 204 origin_task_runner_->PostTask(FROM_HERE,
186 base::Bind(&OnFrameEncodeCompleted, 205 base::Bind(OnFrameEncodeCompleted,
187 on_encoded_video_callback_, 206 on_encoded_video_callback_,
188 frame, 207 frame,
189 base::Passed(&data), 208 base::Passed(&data),
190 capture_timestamp, 209 capture_timestamp,
191 keyframe)); 210 keyframe));
192 } 211 }
193 212
194 void VideoTrackRecorder::VpxEncoder::ConfigureVp8Encoding( 213 void VideoTrackRecorder::VpxEncoder::ConfigureVp8Encoding(
195 const gfx::Size& size) { 214 const gfx::Size& size) {
196 if (IsInitialized()) { 215 if (IsInitialized()) {
197 // TODO(mcasas) VP8 quirk/optimisation: If the new |size| is strictly less- 216 // TODO(mcasas) VP8 quirk/optimisation: If the new |size| is strictly less-
198 // than-or-equal than the old size, in terms of area, the existing encoder 217 // than-or-equal than the old size, in terms of area, the existing encoder
199 // instance could be reused after changing |codec_config_.{g_w,g_h}|. 218 // instance could be reused after changing |codec_config_.{g_w,g_h}|.
200 DVLOG(1) << "Destroying/Re-Creating encoder for new frame size: " 219 DVLOG(1) << "Destroying/Re-Creating encoder for new frame size: "
201 << gfx::Size(codec_config_.g_w, codec_config_.g_h).ToString() 220 << gfx::Size(codec_config_.g_w, codec_config_.g_h).ToString()
202 << " --> " << size.ToString(); 221 << " --> " << size.ToString();
203 vpx_codec_destroy(&encoder_); 222 encoder_.reset();
204 } 223 }
205 224
206 const vpx_codec_iface_t* interface = vpx_codec_vp8_cx(); 225 const vpx_codec_iface_t* interface = vpx_codec_vp8_cx();
207 const vpx_codec_err_t result = vpx_codec_enc_config_default(interface, 226 const vpx_codec_err_t result = vpx_codec_enc_config_default(interface,
208 &codec_config_, 227 &codec_config_,
209 0 /* reserved */); 228 0 /* reserved */);
210 DCHECK_EQ(VPX_CODEC_OK, result); 229 DCHECK_EQ(VPX_CODEC_OK, result);
211 230
212 // Adjust default bit rate to account for the actual size. 231 // Adjust default bit rate to account for the actual size.
213 DCHECK_EQ(320u, codec_config_.g_w); 232 DCHECK_EQ(320u, codec_config_.g_w);
(...skipping 25 matching lines...) Expand all
239 258
240 // Do not saturate CPU utilization just for encoding. On a lower-end system 259 // Do not saturate CPU utilization just for encoding. On a lower-end system
241 // with only 1 or 2 cores, use only one thread for encoding. On systems with 260 // with only 1 or 2 cores, use only one thread for encoding. On systems with
242 // more cores, allow half of the cores to be used for encoding. 261 // more cores, allow half of the cores to be used for encoding.
243 codec_config_.g_threads = 262 codec_config_.g_threads =
244 std::min(8, (base::SysInfo::NumberOfProcessors() + 1) / 2); 263 std::min(8, (base::SysInfo::NumberOfProcessors() + 1) / 2);
245 264
246 // Number of frames to consume before producing output. 265 // Number of frames to consume before producing output.
247 codec_config_.g_lag_in_frames = 0; 266 codec_config_.g_lag_in_frames = 0;
248 267
249 const vpx_codec_err_t ret = vpx_codec_enc_init(&encoder_, interface, 268 DCHECK(!encoder_);
269 encoder_.reset(new vpx_codec_ctx_t);
miu 2015/09/02 21:28:13 Why did you change this to a custom scoped ptr? I
mcasas 2015/09/04 02:16:30 Is due to the possible case of ctor() + dtor() wit
miu 2015/09/04 21:48:52 But you have IsInitialized() to tell you whether y
mcasas 2015/09/05 02:43:01 Acknowledged.
270 const vpx_codec_err_t ret = vpx_codec_enc_init(encoder_.get(), interface,
250 &codec_config_, kNoFlags); 271 &codec_config_, kNoFlags);
251 DCHECK_EQ(VPX_CODEC_OK, ret); 272 DCHECK_EQ(VPX_CODEC_OK, ret);
252 } 273 }
253 274
254 bool VideoTrackRecorder::VpxEncoder::IsInitialized() const { 275 bool VideoTrackRecorder::VpxEncoder::IsInitialized() const {
255 DCHECK(encoding_thread_.task_runner()->BelongsToCurrentThread()); 276 DCHECK(encoding_thread_.task_runner()->BelongsToCurrentThread());
256 return codec_config_.g_timebase.den != 0; 277 return codec_config_.g_timebase.den != 0;
257 } 278 }
258 279
259 base::TimeDelta VideoTrackRecorder::VpxEncoder::CalculateFrameDuration( 280 base::TimeDelta VideoTrackRecorder::VpxEncoder::CalculateFrameDuration(
(...skipping 18 matching lines...) Expand all
278 const TimeDelta kMaxFrameDuration = TimeDelta::FromSecondsD(1.0 / 8); 299 const TimeDelta kMaxFrameDuration = TimeDelta::FromSecondsD(1.0 / 8);
279 const TimeDelta kMinFrameDuration = TimeDelta::FromMilliseconds(1); 300 const TimeDelta kMinFrameDuration = TimeDelta::FromMilliseconds(1);
280 return std::min(kMaxFrameDuration, std::max(predicted_frame_duration, 301 return std::min(kMaxFrameDuration, std::max(predicted_frame_duration,
281 kMinFrameDuration)); 302 kMinFrameDuration));
282 } 303 }
283 304
284 VideoTrackRecorder::VideoTrackRecorder( 305 VideoTrackRecorder::VideoTrackRecorder(
285 const blink::WebMediaStreamTrack& track, 306 const blink::WebMediaStreamTrack& track,
286 const OnEncodedVideoCB& on_encoded_video_callback) 307 const OnEncodedVideoCB& on_encoded_video_callback)
287 : track_(track), 308 : track_(track),
288 encoder_(new VpxEncoder(on_encoded_video_callback)), 309 encoder_(new VpxEncoder(on_encoded_video_callback)) {
289 weak_factory_(this) {
290 DCHECK(main_render_thread_checker_.CalledOnValidThread()); 310 DCHECK(main_render_thread_checker_.CalledOnValidThread());
291 DCHECK(!track_.isNull()); 311 DCHECK(!track_.isNull());
292 DCHECK(track.extraData()); 312 DCHECK(track.extraData());
313
314 // StartFrameEncode() will be called on Render IO thread.
293 AddToVideoTrack(this, 315 AddToVideoTrack(this,
294 media::BindToCurrentLoop( 316 base::Bind(&VideoTrackRecorder::VpxEncoder::StartFrameEncode,
295 base::Bind(&VideoTrackRecorder::OnVideoFrame, 317 encoder_),
296 weak_factory_.GetWeakPtr())),
297 track_); 318 track_);
298 } 319 }
299 320
300 VideoTrackRecorder::~VideoTrackRecorder() { 321 VideoTrackRecorder::~VideoTrackRecorder() {
301 DCHECK(main_render_thread_checker_.CalledOnValidThread()); 322 DCHECK(main_render_thread_checker_.CalledOnValidThread());
302 RemoveFromVideoTrack(this, track_); 323 RemoveFromVideoTrack(this, track_);
303 weak_factory_.InvalidateWeakPtrs();
304 track_.reset(); 324 track_.reset();
305 } 325 }
306 326
307 void VideoTrackRecorder::OnVideoFrame(const scoped_refptr<VideoFrame>& frame, 327 void VideoTrackRecorder::OnVideoFrameForTesting(
308 base::TimeTicks timestamp) { 328 const scoped_refptr<media::VideoFrame>& frame,
309 DCHECK(main_render_thread_checker_.CalledOnValidThread()); 329 base::TimeTicks timestamp) {
310 encoder_->StartFrameEncode(frame, timestamp); 330 encoder_->StartFrameEncode(frame, timestamp);
311 } 331 }
312 332
313 } // namespace content 333 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698