| 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 "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"; | 
|  | 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, and is supposed to be the render IO | 
|  | 69 // 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); | 
|  | 76 | 
|  | 77   void StartFrameEncode(const scoped_refptr<VideoFrame>& frame, | 
|  | 78                         const base::TimeTicks& capture_timestamp); | 
|  | 79 | 
|  | 80  private: | 
|  | 81   friend class base::RefCountedThreadSafe<VpxEncoder>; | 
| 59   ~VpxEncoder(); | 82   ~VpxEncoder(); | 
| 60 | 83 | 
| 61   void StartFrameEncode(const scoped_refptr<VideoFrame>& frame, |  | 
| 62                         base::TimeTicks capture_timestamp); |  | 
| 63 |  | 
| 64  private: |  | 
| 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()); | 
| 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     const 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  Loading... | 
| 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  Loading... | 
| 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); | 
|  | 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  Loading... | 
| 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                                       const base::TimeTicks& timestamp) { | 328     const scoped_refptr<media::VideoFrame>& frame, | 
| 309   DCHECK(main_render_thread_checker_.CalledOnValidThread()); | 329     const base::TimeTicks& timestamp) { | 
| 310   encoder_->StartFrameEncode(frame, timestamp); | 330   encoder_->StartFrameEncode(frame, timestamp); | 
| 311 } | 331 } | 
| 312 | 332 | 
| 313 }  // namespace content | 333 }  // namespace content | 
| OLD | NEW | 
|---|