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

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

Issue 1990643002: Add VEAEncoder to VideoTrackRecorder (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: mcasas@ comments. Created 4 years, 7 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
« no previous file with comments | « content/renderer/media/video_track_recorder.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <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"
11 #include "base/macros.h" 11 #include "base/macros.h"
12 #include "base/sys_info.h" 12 #include "base/sys_info.h"
13 #include "base/task_runner_util.h"
13 #include "base/threading/thread.h" 14 #include "base/threading/thread.h"
14 #include "base/time/time.h" 15 #include "base/time/time.h"
15 #include "base/trace_event/trace_event.h" 16 #include "base/trace_event/trace_event.h"
17 #include "content/renderer/media/renderer_gpu_video_accelerator_factories.h"
18 #include "content/renderer/render_thread_impl.h"
19 #include "media/base/bind_to_current_loop.h"
16 #include "media/base/video_frame.h" 20 #include "media/base/video_frame.h"
17 #include "media/base/video_util.h" 21 #include "media/base/video_util.h"
22 #include "third_party/libyuv/include/libyuv/convert.h"
18 #include "ui/gfx/geometry/size.h" 23 #include "ui/gfx/geometry/size.h"
19 24
20 #if BUILDFLAG(RTC_USE_H264) 25 #if BUILDFLAG(RTC_USE_H264)
21 #include "third_party/openh264/src/codec/api/svc/codec_api.h" 26 #include "third_party/openh264/src/codec/api/svc/codec_api.h"
22 #include "third_party/openh264/src/codec/api/svc/codec_app_def.h" 27 #include "third_party/openh264/src/codec/api/svc/codec_app_def.h"
23 #include "third_party/openh264/src/codec/api/svc/codec_def.h" 28 #include "third_party/openh264/src/codec/api/svc/codec_def.h"
24 #endif // #if BUILDFLAG(RTC_USE_H264) 29 #endif // #if BUILDFLAG(RTC_USE_H264)
25 30
26 extern "C" { 31 extern "C" {
27 // VPX_CODEC_DISABLE_COMPAT excludes parts of the libvpx API that provide 32 // VPX_CODEC_DISABLE_COMPAT excludes parts of the libvpx API that provide
28 // backwards compatibility for legacy applications using the library. 33 // backwards compatibility for legacy applications using the library.
29 #define VPX_CODEC_DISABLE_COMPAT 1 34 #define VPX_CODEC_DISABLE_COMPAT 1
30 #include "third_party/libvpx/source/libvpx/vpx/vp8cx.h" 35 #include "third_party/libvpx/source/libvpx/vpx/vp8cx.h"
31 #include "third_party/libvpx/source/libvpx/vpx/vpx_encoder.h" 36 #include "third_party/libvpx/source/libvpx/vpx/vpx_encoder.h"
32 } 37 }
33 38
34 using media::VideoFrame; 39 using media::VideoFrame;
35 using media::VideoFrameMetadata; 40 using media::VideoFrameMetadata;
36 41
37 namespace content { 42 namespace content {
38 43
44 namespace {
45
46 const int kVEAEncoderMinResolutionWidth = 640;
47 const int kVEAEncoderMinResolutionHeight = 480;
48 const int kVEAEncoderOutputBufferCount = 4;
49
50 static struct {
51 VideoTrackRecorder::CodecId codec_id;
52 media::VideoCodecProfile min_profile;
53 media::VideoCodecProfile max_profile;
54 } const kSupportedVideoCodecIdToProfile[] = {
55 {VideoTrackRecorder::CodecId::VP8,
56 media::VP8PROFILE_MIN,
57 media::VP8PROFILE_MAX},
58 {VideoTrackRecorder::CodecId::VP9,
59 media::VP9PROFILE_MIN,
60 media::VP9PROFILE_MAX},
61 {VideoTrackRecorder::CodecId::H264,
62 media::H264PROFILE_MIN,
63 media::H264PROFILE_MAX}};
64
65 // Returns the corresponding codec profile from VEA supported codecs. If no
66 // profile is found, returns VIDEO_CODEC_PROFILE_UNKNOWN.
67 media::VideoCodecProfile CodecIdToVEAProfile(
68 content::VideoTrackRecorder::CodecId codec) {
69 content::RenderThreadImpl* render_thread_impl =
70 content::RenderThreadImpl::current();
71 if (!render_thread_impl)
72 return media::VIDEO_CODEC_PROFILE_UNKNOWN;
73
74 media::GpuVideoAcceleratorFactories* gpu_factories =
75 content::RenderThreadImpl::current()->GetGpuFactories();
76 if (!gpu_factories || !gpu_factories->IsGpuVideoAcceleratorEnabled()) {
77 DVLOG(3) << "Couldn't initialize GpuVideoAcceleratorFactories";
78 return media::VIDEO_CODEC_PROFILE_UNKNOWN;
79 }
80
81 const media::VideoEncodeAccelerator::SupportedProfiles& vea_profiles =
82 gpu_factories->GetVideoEncodeAcceleratorSupportedProfiles();
83 for (const auto& vea_profile : vea_profiles) {
84 for (const auto& supported_profile : kSupportedVideoCodecIdToProfile) {
85 if (codec == supported_profile.codec_id &&
86 vea_profile.profile >= supported_profile.min_profile &&
87 vea_profile.profile <= supported_profile.max_profile)
88 return vea_profile.profile;
89 }
90 }
91 return media::VIDEO_CODEC_PROFILE_UNKNOWN;
92 }
93
94 } // anonymous namespace
95
39 // Base class to describe a generic Encoder, encapsulating all actual encoder 96 // Base class to describe a generic Encoder, encapsulating all actual encoder
40 // (re)configurations, encoding and delivery of received frames. This class is 97 // (re)configurations, encoding and delivery of received frames. This class is
41 // ref-counted to allow the MediaStreamVideoTrack to hold a reference to it (via 98 // ref-counted to allow the MediaStreamVideoTrack to hold a reference to it (via
42 // the callback that MediaStreamVideoSink passes along) and to jump back and 99 // the callback that MediaStreamVideoSink passes along) and to jump back and
43 // forth to an internal encoder thread. Moreover, this class: 100 // forth to an internal encoder thread. Moreover, this class:
44 // - is created and destroyed on its parent's thread (usually the main Render 101 // - is created and destroyed on its parent's thread (usually the main Render
45 // thread), |main_task_runner_|. 102 // thread), |main_task_runner_|.
46 // - receives VideoFrames on |origin_task_runner_| and runs OnEncodedVideoCB on 103 // - receives VideoFrames on |origin_task_runner_| and runs OnEncodedVideoCB on
47 // that thread as well. This task runner is cached on first frame arrival, and 104 // that thread as well. This task runner is cached on first frame arrival, and
48 // is supposed to be the render IO thread (but this is not enforced); 105 // is supposed to be the render IO thread (but this is not enforced);
49 // - uses an internal |encoding_task_runner_| for actual encoder interactions, 106 // - uses an internal |encoding_task_runner_| for actual encoder interactions,
50 // namely configuration, encoding (which might take some time) and destruction. 107 // namely configuration, encoding (which might take some time) and destruction.
51 // This task runner can be passed on the creation. If nothing is passed, a new 108 // This task runner can be passed on the creation. If nothing is passed, a new
52 // encoding thread is created and used. 109 // encoding thread is created and used.
53 class VideoTrackRecorder::Encoder : public base::RefCountedThreadSafe<Encoder> { 110 class VideoTrackRecorder::Encoder : public base::RefCountedThreadSafe<Encoder> {
54 public: 111 public:
55 Encoder(const OnEncodedVideoCB& on_encoded_video_callback, 112 Encoder(const OnEncodedVideoCB& on_encoded_video_callback,
56 int32_t bits_per_second, 113 int32_t bits_per_second,
57 scoped_refptr<base::SingleThreadTaskRunner> encoding_task_runner = 114 scoped_refptr<base::SingleThreadTaskRunner> encoding_task_runner =
58 nullptr) 115 nullptr)
59 : main_task_runner_(base::MessageLoop::current()->task_runner()), 116 : main_task_runner_(base::MessageLoop::current()->task_runner()),
60 encoding_task_runner_(encoding_task_runner), 117 encoding_task_runner_(encoding_task_runner),
61 paused_(false), 118 paused_(false),
62 on_encoded_video_callback_(on_encoded_video_callback), 119 on_encoded_video_callback_(on_encoded_video_callback),
63 bits_per_second_(bits_per_second) { 120 bits_per_second_(bits_per_second) {
64 DCHECK(!on_encoded_video_callback_.is_null()); 121 DCHECK(!on_encoded_video_callback_.is_null());
65 if (encoding_thread_) 122 if (encoding_task_runner_)
66 return; 123 return;
67 encoding_thread_.reset(new base::Thread("EncodingThread")); 124 encoding_thread_.reset(new base::Thread("EncodingThread"));
68 encoding_thread_->Start(); 125 encoding_thread_->Start();
69 encoding_task_runner_ = encoding_thread_->task_runner(); 126 encoding_task_runner_ = encoding_thread_->task_runner();
70 } 127 }
71 128
72 // Start encoding |frame|, returning via |on_encoded_video_callback_|. This 129 // Start encoding |frame|, returning via |on_encoded_video_callback_|. This
73 // call will also trigger a ConfigureEncoderOnEncodingTaskRunner() upon first 130 // call will also trigger a ConfigureEncoderOnEncodingTaskRunner() upon first
74 // frame arrival or parameter change, and an EncodeOnEncodingTaskRunner() to 131 // frame arrival or parameter change, and an EncodeOnEncodingTaskRunner() to
75 // actually encode the frame. 132 // actually encode the frame.
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 on_encoded_video_cb.Run(frame, std::move(data), capture_timestamp, keyframe); 229 on_encoded_video_cb.Run(frame, std::move(data), capture_timestamp, keyframe);
173 } 230 }
174 231
175 static int GetNumberOfThreadsForEncoding() { 232 static int GetNumberOfThreadsForEncoding() {
176 // Do not saturate CPU utilization just for encoding. On a lower-end system 233 // Do not saturate CPU utilization just for encoding. On a lower-end system
177 // with only 1 or 2 cores, use only one thread for encoding. On systems with 234 // with only 1 or 2 cores, use only one thread for encoding. On systems with
178 // more cores, allow half of the cores to be used for encoding. 235 // more cores, allow half of the cores to be used for encoding.
179 return std::min(8, (base::SysInfo::NumberOfProcessors() + 1) / 2); 236 return std::min(8, (base::SysInfo::NumberOfProcessors() + 1) / 2);
180 } 237 }
181 238
239 // Class encapsulating VideoEncodeAccelerator interactions.
240 // This class is created and destroyed in its owner thread. All other methods
241 // operate on the task runner pointed by GpuFactories.
242 class VEAEncoder final : public VideoTrackRecorder::Encoder,
243 public media::VideoEncodeAccelerator::Client {
244 public:
245 VEAEncoder(
246 const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback,
247 int32_t bits_per_second,
248 media::VideoCodecProfile codec);
249
250 // media::VideoEncodeAccelerator::Client implementation.
251 void RequireBitstreamBuffers(unsigned int input_count,
252 const gfx::Size& input_coded_size,
253 size_t output_buffer_size) override;
254 void BitstreamBufferReady(int32_t bitstream_buffer_id,
255 size_t payload_size,
256 bool key_frame) override;
257 void NotifyError(media::VideoEncodeAccelerator::Error error) override;
258
259 private:
260 using VideoFrameAndTimestamp =
261 std::pair<scoped_refptr<VideoFrame>, base::TimeTicks>;
262
263
mcasas 2016/05/21 01:36:58 Remove extra empty line.
emircan 2016/05/23 21:07:46 Done.
264 void UseOutputBitstreamBufferId(int32_t bitstream_buffer_id);
265 void FrameFinished(std::unique_ptr<base::SharedMemory> shm);
266
267 // VideoTrackRecorder::Encoder
mcasas 2016/05/21 01:36:58 nit: still missing "implementation", i.e. // Video
emircan 2016/05/23 21:07:46 Done. Changed it here and l.316, 368.
268 ~VEAEncoder() override;
269 void EncodeOnEncodingTaskRunner(const scoped_refptr<VideoFrame>& frame,
270 base::TimeTicks capture_timestamp) override;
271 void ConfigureEncoderOnEncodingTaskRunner(const gfx::Size& size) override;
272
273 media::GpuVideoAcceleratorFactories* const gpu_factories_;
274
275 const media::VideoCodecProfile codec_;
276
277 // The underlying VEA to perform encoding on.
278 std::unique_ptr<media::VideoEncodeAccelerator> video_encoder_;
279
280 // Shared memory buffers for output with the VEA.
281 std::vector<std::unique_ptr<base::SharedMemory>> output_buffers_;
282
283 // Shared memory buffers for output with the VEA as FIFO.
284 std::queue<std::unique_ptr<base::SharedMemory>> input_buffers_;
285
286 // The number of output buffers ready to be filled.
287 int output_buffers_free_count_;
288
289 // Tracks error status.
290 bool error_notified_;
291
292 // Tracks the first frame to encode.
293 std::unique_ptr<VideoFrameAndTimestamp> first_frame_;
294
295 // Size used to initialize encoder.
296 gfx::Size input_size_;
297
298 // Coded size that encoder requests as input.
299 gfx::Size vea_requested_input_size_;
300
301 // Frames and corresponding timestamps in encode as FIFO.
302 std::queue<VideoFrameAndTimestamp> frames_in_encode_;
303 };
304
182 // Class encapsulating all libvpx interactions for VP8/VP9 encoding. 305 // Class encapsulating all libvpx interactions for VP8/VP9 encoding.
183 class VpxEncoder final : public VideoTrackRecorder::Encoder { 306 class VpxEncoder final : public VideoTrackRecorder::Encoder {
184 public: 307 public:
185 static void ShutdownEncoder(std::unique_ptr<base::Thread> encoding_thread, 308 static void ShutdownEncoder(std::unique_ptr<base::Thread> encoding_thread,
186 ScopedVpxCodecCtxPtr encoder); 309 ScopedVpxCodecCtxPtr encoder);
187 310
188 VpxEncoder( 311 VpxEncoder(
189 bool use_vp9, 312 bool use_vp9,
190 const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback, 313 const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback,
191 int32_t bits_per_second); 314 int32_t bits_per_second);
192 315
193 private: 316 private:// VideoTrackRecorder::Encoder
194 // VideoTrackRecorder::Encoder
195 ~VpxEncoder() override; 317 ~VpxEncoder() override;
196 void EncodeOnEncodingTaskRunner(const scoped_refptr<VideoFrame>& frame, 318 void EncodeOnEncodingTaskRunner(const scoped_refptr<VideoFrame>& frame,
197 base::TimeTicks capture_timestamp) override; 319 base::TimeTicks capture_timestamp) override;
198 void ConfigureEncoderOnEncodingTaskRunner(const gfx::Size& size) override; 320 void ConfigureEncoderOnEncodingTaskRunner(const gfx::Size& size) override;
199 321
200 // Returns true if |codec_config_| has been filled in at least once. 322 // Returns true if |codec_config_| has been filled in at least once.
201 bool IsInitialized() const; 323 bool IsInitialized() const;
202 324
203 // Estimate the frame duration from |frame| and |last_frame_timestamp_|. 325 // Estimate the frame duration from |frame| and |last_frame_timestamp_|.
204 base::TimeDelta EstimateFrameDuration(const scoped_refptr<VideoFrame>& frame); 326 base::TimeDelta EstimateFrameDuration(const scoped_refptr<VideoFrame>& frame);
205 327
206 // Force usage of VP9 for encoding, instead of VP8 which is the default. 328 // Force usage of VP9 for encoding, instead of VP8 which is the default.
207 const bool use_vp9_; 329 const bool use_vp9_;
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 379
258 // The |VideoFrame::timestamp()| of the first received frame. Only used on 380 // The |VideoFrame::timestamp()| of the first received frame. Only used on
259 // |encoding_thread_|. 381 // |encoding_thread_|.
260 base::TimeTicks first_frame_timestamp_; 382 base::TimeTicks first_frame_timestamp_;
261 383
262 DISALLOW_COPY_AND_ASSIGN(H264Encoder); 384 DISALLOW_COPY_AND_ASSIGN(H264Encoder);
263 }; 385 };
264 386
265 #endif // #if BUILDFLAG(RTC_USE_H264) 387 #endif // #if BUILDFLAG(RTC_USE_H264)
266 388
389 VEAEncoder::VEAEncoder(
390 const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback,
391 int32_t bits_per_second,
392 media::VideoCodecProfile codec)
393 : Encoder(on_encoded_video_callback,
394 bits_per_second,
395 RenderThreadImpl::current()->GetGpuFactories()->GetTaskRunner()),
396 gpu_factories_(RenderThreadImpl::current()->GetGpuFactories()),
397 codec_(codec),
398 output_buffers_free_count_(0),
399 error_notified_(false) {
400 DCHECK(gpu_factories_);
401 }
402
403 VEAEncoder::~VEAEncoder() {
404 encoding_task_runner_->PostTask(
405 FROM_HERE, base::Bind(&media::VideoEncodeAccelerator::Destroy,
406 base::Unretained(video_encoder_.release())));
407 }
408
409 void VEAEncoder::RequireBitstreamBuffers(unsigned int /*input_count*/,
410 const gfx::Size& input_coded_size,
411 size_t output_buffer_size) {
412 DVLOG(3) << __FUNCTION__;
413 DCHECK(encoding_task_runner_->BelongsToCurrentThread());
414
415 vea_requested_input_size_ = input_coded_size;
416 output_buffers_.clear();
417 output_buffers_free_count_ = 0;
418 std::queue<std::unique_ptr<base::SharedMemory>>().swap(input_buffers_);
419
420 for (int i = 0; i < kVEAEncoderOutputBufferCount; ++i) {
421 std::unique_ptr<base::SharedMemory> shm =
422 gpu_factories_->CreateSharedMemory(output_buffer_size);
423 if (!shm) {
424 NOTREACHED();
425 return;
426 }
mcasas 2016/05/21 01:36:57 Micro-nit: I wonder how often this NOTREACHED() ge
emircan 2016/05/23 21:07:46 Done.
427 output_buffers_.push_back(base::WrapUnique(shm.release()));
428 }
429
430 for (size_t i = 0; i < output_buffers_.size(); ++i) {
431 video_encoder_->UseOutputBitstreamBuffer(media::BitstreamBuffer(
432 i, output_buffers_[i]->handle(), output_buffers_[i]->mapped_size()));
mcasas 2016/05/21 01:36:57 for (size_t i = 0; i < output_buffers_.size(); ++i
emircan 2016/05/23 21:07:46 Done.
433 output_buffers_free_count_++;
434 }
435 }
436
437 void VEAEncoder::BitstreamBufferReady(int32_t bitstream_buffer_id,
438 size_t payload_size,
439 bool keyframe) {
440 DVLOG(3) << __FUNCTION__;
441 DCHECK(encoding_task_runner_->BelongsToCurrentThread());
442
443 output_buffers_free_count_--;
444 base::SharedMemory* output_buffer =
445 output_buffers_[bitstream_buffer_id].get();
446
447 std::unique_ptr<std::string> data(new std::string);
448 data->append(reinterpret_cast<char*>(output_buffer->memory()), payload_size);
449
450 const auto front_frame = frames_in_encode_.front();
451 frames_in_encode_.pop();
452 origin_task_runner_->PostTask(
453 FROM_HERE, base::Bind(OnFrameEncodeCompleted, on_encoded_video_callback_,
454 front_frame.first, base::Passed(&data),
455 front_frame.second, keyframe));
456 UseOutputBitstreamBufferId(bitstream_buffer_id);
457 }
458
459 void VEAEncoder::NotifyError(media::VideoEncodeAccelerator::Error error) {
460 DVLOG(3) << __FUNCTION__;
461 DCHECK(encoding_task_runner_->BelongsToCurrentThread());
462
463 // TODO(emircan): Notify the owner via a callback.
464 error_notified_ = true;
465 }
466
467 void VEAEncoder::UseOutputBitstreamBufferId(int32_t bitstream_buffer_id) {
468 DVLOG(3) << __FUNCTION__;
469 DCHECK(encoding_task_runner_->BelongsToCurrentThread());
470
471 video_encoder_->UseOutputBitstreamBuffer(media::BitstreamBuffer(
472 bitstream_buffer_id, output_buffers_[bitstream_buffer_id]->handle(),
473 output_buffers_[bitstream_buffer_id]->mapped_size()));
474 output_buffers_free_count_++;
475 }
476
477 void VEAEncoder::FrameFinished(std::unique_ptr<base::SharedMemory> shm) {
478 DVLOG(3) << __FUNCTION__;
479 DCHECK(encoding_task_runner_->BelongsToCurrentThread());
480 input_buffers_.push(std::move(shm));
481 }
482
483 void VEAEncoder::EncodeOnEncodingTaskRunner(
484 const scoped_refptr<VideoFrame>& frame,
485 base::TimeTicks capture_timestamp) {
486 DVLOG(3) << __FUNCTION__;
487 DCHECK(encoding_task_runner_->BelongsToCurrentThread());
488
489 if (input_size_ != frame->visible_rect().size() && video_encoder_) {
490 video_encoder_->Destroy();
491 video_encoder_.reset();
492 }
493
494 if (!video_encoder_) {
495 ConfigureEncoderOnEncodingTaskRunner(frame->visible_rect().size());
496 first_frame_.reset(
497 new std::pair<scoped_refptr<VideoFrame>, base::TimeTicks>(
498 frame, capture_timestamp));
mcasas 2016/05/21 01:36:57 std::make_pair(frame, capture_timestamp)
emircan 2016/05/23 21:07:46 Implicit types cannot be decided with make_pair()
499 }
500
501 if (error_notified_) {
502 DVLOG(3) << "An error occurred in VEA encoder";
503 return;
504 }
505
506 // Drop frames if there is no output buffers available.
507 if (output_buffers_free_count_ == 0) {
mcasas 2016/05/21 01:36:57 nit: Suggest changing this counter to a boolean |i
emircan 2016/05/23 21:07:46 It counts down in l.443. I followed the pattern fr
508 // TODO(emircan): Investigate if resetting encoder would help.
509 DVLOG(3) << "Dropped frame.";
510 return;
511 }
512
513 // If first frame hasn't been encoded, do it first.
514 if (first_frame_) {
515 std::unique_ptr<VideoFrameAndTimestamp> first_frame(first_frame_.release());
mcasas 2016/05/21 01:36:57 micronit: std::unique_ptr<VideoFrameAndTimestamp>
emircan 2016/05/23 21:07:46 I think release() makes it more explicit that we a
516 EncodeOnEncodingTaskRunner(first_frame->first, first_frame->second);
517 }
518
519 // Lower resolutions may fall back to SW encoder in some platforms, i.e. Mac.
520 // In that case, the encoder expects more frames before returning result.
521 // Therefore, a copy is necessary to release the current frame.
522 scoped_refptr<media::VideoFrame> video_frame = frame;
523 if (vea_requested_input_size_ != input_size_ ||
524 input_size_.width() < kVEAEncoderMinResolutionWidth ||
525 input_size_.height() < kVEAEncoderMinResolutionHeight) {
526 // Create SharedMemory backed input buffers as necessary. These SharedMemory
527 // instances will be shared with GPU process.
528 std::unique_ptr<base::SharedMemory> input_buffer;
529 if (input_buffers_.empty()) {
530 input_buffer =
531 gpu_factories_->CreateSharedMemory(media::VideoFrame::AllocationSize(
532 media::PIXEL_FORMAT_I420, vea_requested_input_size_));
533 } else {
534 input_buffer = std::move(input_buffers_.front());
535 input_buffers_.pop();
536 }
537
538 while (input_buffer->mapped_size() <
539 media::VideoFrame::AllocationSize(media::PIXEL_FORMAT_I420,
540 vea_requested_input_size_)) {
541 input_buffer.reset(input_buffers_.front().release());
542 input_buffers_.pop();
543 }
mcasas 2016/05/21 01:36:57 This while(input_buffer-too-small) search only app
emircan 2016/05/23 21:07:46 Yes, it applies to the else. I was thinking of a c
544
545 video_frame = media::VideoFrame::WrapExternalSharedMemory(
546 media::PIXEL_FORMAT_I420, vea_requested_input_size_,
547 gfx::Rect(input_size_), input_size_,
mcasas 2016/05/21 01:36:57 s/input_size_/vea_requested_input_size_/ in the t
emircan 2016/05/23 21:07:46 RequireBitstreamBuffers() gives us coded_size()[0]
548 reinterpret_cast<uint8_t*>(input_buffer->memory()),
549 input_buffer->mapped_size(), input_buffer->handle(), 0,
550 frame->timestamp());
551 video_frame->AddDestructionObserver(media::BindToCurrentLoop(
552 base::Bind(&VEAEncoder::FrameFinished, this,
553 base::Passed(std::move(input_buffer)))));
554 libyuv::I420Copy(frame->visible_data(media::VideoFrame::kYPlane),
555 frame->stride(media::VideoFrame::kYPlane),
556 frame->visible_data(media::VideoFrame::kUPlane),
557 frame->stride(media::VideoFrame::kUPlane),
558 frame->visible_data(media::VideoFrame::kVPlane),
559 frame->stride(media::VideoFrame::kVPlane),
560 video_frame->visible_data(media::VideoFrame::kYPlane),
561 video_frame->stride(media::VideoFrame::kYPlane),
562 video_frame->visible_data(media::VideoFrame::kUPlane),
563 video_frame->stride(media::VideoFrame::kUPlane),
564 video_frame->visible_data(media::VideoFrame::kVPlane),
565 video_frame->stride(media::VideoFrame::kVPlane),
566 input_size_.width(), input_size_.height());
567 }
568 frames_in_encode_.push(std::make_pair(video_frame, capture_timestamp));
569
570 encoding_task_runner_->PostTask(
571 FROM_HERE,
572 base::Bind(&media::VideoEncodeAccelerator::Encode,
573 base::Unretained(video_encoder_.get()), video_frame, false));
574 }
575
576 void VEAEncoder::ConfigureEncoderOnEncodingTaskRunner(const gfx::Size& size) {
577 DVLOG(3) << __FUNCTION__;
578 DCHECK(encoding_task_runner_->BelongsToCurrentThread());
579 DCHECK(gpu_factories_->GetTaskRunner()->BelongsToCurrentThread());
580
581 input_size_ = size;
582 video_encoder_ = gpu_factories_->CreateVideoEncodeAccelerator();
583 if (!video_encoder_ ||
584 !video_encoder_->Initialize(media::PIXEL_FORMAT_I420, input_size_, codec_,
585 bits_per_second_, this)) {
586 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
587 }
588 }
589
267 // static 590 // static
268 void VpxEncoder::ShutdownEncoder(std::unique_ptr<base::Thread> encoding_thread, 591 void VpxEncoder::ShutdownEncoder(std::unique_ptr<base::Thread> encoding_thread,
269 ScopedVpxCodecCtxPtr encoder) { 592 ScopedVpxCodecCtxPtr encoder) {
270 DCHECK(encoding_thread->IsRunning()); 593 DCHECK(encoding_thread->IsRunning());
271 encoding_thread->Stop(); 594 encoding_thread->Stop();
272 // Both |encoding_thread| and |encoder| will be destroyed at end-of-scope. 595 // Both |encoding_thread| and |encoder| will be destroyed at end-of-scope.
273 } 596 }
274 597
275 VpxEncoder::VpxEncoder( 598 VpxEncoder::VpxEncoder(
276 bool use_vp9, 599 bool use_vp9,
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after
619 VideoTrackRecorder::VideoTrackRecorder( 942 VideoTrackRecorder::VideoTrackRecorder(
620 CodecId codec, 943 CodecId codec,
621 const blink::WebMediaStreamTrack& track, 944 const blink::WebMediaStreamTrack& track,
622 const OnEncodedVideoCB& on_encoded_video_callback, 945 const OnEncodedVideoCB& on_encoded_video_callback,
623 int32_t bits_per_second) 946 int32_t bits_per_second)
624 : track_(track) { 947 : track_(track) {
625 DCHECK(main_render_thread_checker_.CalledOnValidThread()); 948 DCHECK(main_render_thread_checker_.CalledOnValidThread());
626 DCHECK(!track_.isNull()); 949 DCHECK(!track_.isNull());
627 DCHECK(track_.getExtraData()); 950 DCHECK(track_.getExtraData());
628 951
629 switch (codec) { 952 const auto& vea_supported_profile = CodecIdToVEAProfile(codec);
953 // TODO(emircan): Prioritize software based encoders in lower resolutions.
954 if (vea_supported_profile != media::VIDEO_CODEC_PROFILE_UNKNOWN) {
955 encoder_ = new VEAEncoder(on_encoded_video_callback, bits_per_second,
956 vea_supported_profile);
957 } else {
958 switch (codec) {
630 #if BUILDFLAG(RTC_USE_H264) 959 #if BUILDFLAG(RTC_USE_H264)
631 case CodecId::H264: 960 case CodecId::H264:
632 encoder_ = new H264Encoder(on_encoded_video_callback, bits_per_second); 961 encoder_ = new H264Encoder(on_encoded_video_callback, bits_per_second);
633 break; 962 break;
634 #endif 963 #endif
635 case CodecId::VP8: 964 case CodecId::VP8:
636 case CodecId::VP9: 965 case CodecId::VP9:
637 encoder_ = new VpxEncoder(codec == CodecId::VP9, 966 encoder_ = new VpxEncoder(codec == CodecId::VP9,
638 on_encoded_video_callback, bits_per_second); 967 on_encoded_video_callback, bits_per_second);
639 break; 968 break;
640 default: 969 default:
641 NOTREACHED() << "Unsupported codec"; 970 NOTREACHED() << "Unsupported codec";
971 }
642 } 972 }
643 973
644 // StartFrameEncode() will be called on Render IO thread. 974 // StartFrameEncode() will be called on Render IO thread.
645 MediaStreamVideoSink::ConnectToTrack( 975 MediaStreamVideoSink::ConnectToTrack(
646 track_, 976 track_,
647 base::Bind(&VideoTrackRecorder::Encoder::StartFrameEncode, encoder_), 977 base::Bind(&VideoTrackRecorder::Encoder::StartFrameEncode, encoder_),
648 false); 978 false);
649 } 979 }
650 980
651 VideoTrackRecorder::~VideoTrackRecorder() { 981 VideoTrackRecorder::~VideoTrackRecorder() {
(...skipping 14 matching lines...) Expand all
666 encoder_->SetPaused(false); 996 encoder_->SetPaused(false);
667 } 997 }
668 998
669 void VideoTrackRecorder::OnVideoFrameForTesting( 999 void VideoTrackRecorder::OnVideoFrameForTesting(
670 const scoped_refptr<media::VideoFrame>& frame, 1000 const scoped_refptr<media::VideoFrame>& frame,
671 base::TimeTicks timestamp) { 1001 base::TimeTicks timestamp) {
672 encoder_->StartFrameEncode(frame, timestamp); 1002 encoder_->StartFrameEncode(frame, timestamp);
673 } 1003 }
674 1004
675 } // namespace content 1005 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/media/video_track_recorder.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698