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

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 void UseOutputBitstreamBufferId(int32_t bitstream_buffer_id);
264 void FrameFinished(std::unique_ptr<base::SharedMemory> shm);
265
266 // VideoTrackRecorder::Encoder implementation.
267 ~VEAEncoder() override;
268 void EncodeOnEncodingTaskRunner(const scoped_refptr<VideoFrame>& frame,
269 base::TimeTicks capture_timestamp) override;
270 void ConfigureEncoderOnEncodingTaskRunner(const gfx::Size& size) override;
271
272 media::GpuVideoAcceleratorFactories* const gpu_factories_;
273
274 const media::VideoCodecProfile codec_;
275
276 // The underlying VEA to perform encoding on.
277 std::unique_ptr<media::VideoEncodeAccelerator> video_encoder_;
278
279 // Shared memory buffers for output with the VEA.
280 std::vector<std::unique_ptr<base::SharedMemory>> output_buffers_;
281
282 // Shared memory buffers for output with the VEA as FIFO.
283 std::queue<std::unique_ptr<base::SharedMemory>> input_buffers_;
284
285 // Tracks error status.
286 bool error_notified_;
287
288 // Tracks the first frame to encode.
289 std::unique_ptr<VideoFrameAndTimestamp> first_frame_;
290
291 // Size used to initialize encoder.
292 gfx::Size input_size_;
293
294 // Coded size that encoder requests as input.
295 gfx::Size vea_requested_input_size_;
296
297 // Frames and corresponding timestamps in encode as FIFO.
298 std::queue<VideoFrameAndTimestamp> frames_in_encode_;
299 };
300
182 // Class encapsulating all libvpx interactions for VP8/VP9 encoding. 301 // Class encapsulating all libvpx interactions for VP8/VP9 encoding.
183 class VpxEncoder final : public VideoTrackRecorder::Encoder { 302 class VpxEncoder final : public VideoTrackRecorder::Encoder {
184 public: 303 public:
185 static void ShutdownEncoder(std::unique_ptr<base::Thread> encoding_thread, 304 static void ShutdownEncoder(std::unique_ptr<base::Thread> encoding_thread,
186 ScopedVpxCodecCtxPtr encoder); 305 ScopedVpxCodecCtxPtr encoder);
187 306
188 VpxEncoder( 307 VpxEncoder(
189 bool use_vp9, 308 bool use_vp9,
190 const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback, 309 const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback,
191 int32_t bits_per_second); 310 int32_t bits_per_second);
192 311
193 private: 312 private:
194 // VideoTrackRecorder::Encoder 313 // VideoTrackRecorder::Encoder implementation.
195 ~VpxEncoder() override; 314 ~VpxEncoder() override;
196 void EncodeOnEncodingTaskRunner(const scoped_refptr<VideoFrame>& frame, 315 void EncodeOnEncodingTaskRunner(const scoped_refptr<VideoFrame>& frame,
197 base::TimeTicks capture_timestamp) override; 316 base::TimeTicks capture_timestamp) override;
198 void ConfigureEncoderOnEncodingTaskRunner(const gfx::Size& size) override; 317 void ConfigureEncoderOnEncodingTaskRunner(const gfx::Size& size) override;
199 318
200 // Returns true if |codec_config_| has been filled in at least once. 319 // Returns true if |codec_config_| has been filled in at least once.
201 bool IsInitialized() const; 320 bool IsInitialized() const;
202 321
203 // Estimate the frame duration from |frame| and |last_frame_timestamp_|. 322 // Estimate the frame duration from |frame| and |last_frame_timestamp_|.
204 base::TimeDelta EstimateFrameDuration(const scoped_refptr<VideoFrame>& frame); 323 base::TimeDelta EstimateFrameDuration(const scoped_refptr<VideoFrame>& frame);
205 324
206 // Force usage of VP9 for encoding, instead of VP8 which is the default. 325 // Force usage of VP9 for encoding, instead of VP8 which is the default.
207 const bool use_vp9_; 326 const bool use_vp9_;
(...skipping 28 matching lines...) Expand all
236 class H264Encoder final : public VideoTrackRecorder::Encoder { 355 class H264Encoder final : public VideoTrackRecorder::Encoder {
237 public: 356 public:
238 static void ShutdownEncoder(std::unique_ptr<base::Thread> encoding_thread, 357 static void ShutdownEncoder(std::unique_ptr<base::Thread> encoding_thread,
239 ScopedISVCEncoderPtr encoder); 358 ScopedISVCEncoderPtr encoder);
240 359
241 H264Encoder( 360 H264Encoder(
242 const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback, 361 const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback,
243 int32_t bits_per_second); 362 int32_t bits_per_second);
244 363
245 private: 364 private:
246 // VideoTrackRecorder::Encoder 365 // VideoTrackRecorder::Encoder implementation.
247 ~H264Encoder() override; 366 ~H264Encoder() override;
248 void EncodeOnEncodingTaskRunner(const scoped_refptr<VideoFrame>& frame, 367 void EncodeOnEncodingTaskRunner(const scoped_refptr<VideoFrame>& frame,
249 base::TimeTicks capture_timestamp) override; 368 base::TimeTicks capture_timestamp) override;
250 void ConfigureEncoderOnEncodingTaskRunner(const gfx::Size& size) override; 369 void ConfigureEncoderOnEncodingTaskRunner(const gfx::Size& size) override;
251 370
252 // |openh264_encoder_| is a special scoped pointer to guarantee proper 371 // |openh264_encoder_| is a special scoped pointer to guarantee proper
253 // destruction, also when reconfiguring due to parameters change. Only used on 372 // destruction, also when reconfiguring due to parameters change. Only used on
254 // |encoding_thread_|. 373 // |encoding_thread_|.
255 gfx::Size configured_size_; 374 gfx::Size configured_size_;
256 ScopedISVCEncoderPtr openh264_encoder_; 375 ScopedISVCEncoderPtr openh264_encoder_;
257 376
258 // The |VideoFrame::timestamp()| of the first received frame. Only used on 377 // The |VideoFrame::timestamp()| of the first received frame. Only used on
259 // |encoding_thread_|. 378 // |encoding_thread_|.
260 base::TimeTicks first_frame_timestamp_; 379 base::TimeTicks first_frame_timestamp_;
261 380
262 DISALLOW_COPY_AND_ASSIGN(H264Encoder); 381 DISALLOW_COPY_AND_ASSIGN(H264Encoder);
263 }; 382 };
264 383
265 #endif // #if BUILDFLAG(RTC_USE_H264) 384 #endif // #if BUILDFLAG(RTC_USE_H264)
266 385
386 VEAEncoder::VEAEncoder(
387 const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback,
388 int32_t bits_per_second,
389 media::VideoCodecProfile codec)
390 : Encoder(on_encoded_video_callback,
391 bits_per_second,
392 RenderThreadImpl::current()->GetGpuFactories()->GetTaskRunner()),
393 gpu_factories_(RenderThreadImpl::current()->GetGpuFactories()),
394 codec_(codec),
395 error_notified_(false) {
396 DCHECK(gpu_factories_);
397 }
398
399 VEAEncoder::~VEAEncoder() {
400 encoding_task_runner_->PostTask(
401 FROM_HERE, base::Bind(&media::VideoEncodeAccelerator::Destroy,
402 base::Unretained(video_encoder_.release())));
403 }
404
405 void VEAEncoder::RequireBitstreamBuffers(unsigned int /*input_count*/,
406 const gfx::Size& input_coded_size,
407 size_t output_buffer_size) {
408 DVLOG(3) << __FUNCTION__;
409 DCHECK(encoding_task_runner_->BelongsToCurrentThread());
410
411 vea_requested_input_size_ = input_coded_size;
412 output_buffers_.clear();
413 std::queue<std::unique_ptr<base::SharedMemory>>().swap(input_buffers_);
414
415 for (int i = 0; i < kVEAEncoderOutputBufferCount; ++i) {
416 std::unique_ptr<base::SharedMemory> shm =
417 gpu_factories_->CreateSharedMemory(output_buffer_size);
418 if (shm)
419 output_buffers_.push_back(base::WrapUnique(shm.release()));
420 }
421
422 for (size_t i = 0; i < output_buffers_.size(); ++i)
423 UseOutputBitstreamBufferId(i);
424 }
425
426 void VEAEncoder::BitstreamBufferReady(int32_t bitstream_buffer_id,
427 size_t payload_size,
428 bool keyframe) {
429 DVLOG(3) << __FUNCTION__;
430 DCHECK(encoding_task_runner_->BelongsToCurrentThread());
431
432 base::SharedMemory* output_buffer =
433 output_buffers_[bitstream_buffer_id].get();
434
435 std::unique_ptr<std::string> data(new std::string);
436 data->append(reinterpret_cast<char*>(output_buffer->memory()), payload_size);
437
438 const auto front_frame = frames_in_encode_.front();
439 frames_in_encode_.pop();
440 origin_task_runner_->PostTask(
441 FROM_HERE, base::Bind(OnFrameEncodeCompleted, on_encoded_video_callback_,
442 front_frame.first, base::Passed(&data),
443 front_frame.second, keyframe));
444 UseOutputBitstreamBufferId(bitstream_buffer_id);
445 }
446
447 void VEAEncoder::NotifyError(media::VideoEncodeAccelerator::Error error) {
448 DVLOG(3) << __FUNCTION__;
449 DCHECK(encoding_task_runner_->BelongsToCurrentThread());
450
451 // TODO(emircan): Notify the owner via a callback.
452 error_notified_ = true;
453 }
454
455 void VEAEncoder::UseOutputBitstreamBufferId(int32_t bitstream_buffer_id) {
456 DVLOG(3) << __FUNCTION__;
457 DCHECK(encoding_task_runner_->BelongsToCurrentThread());
458
459 video_encoder_->UseOutputBitstreamBuffer(media::BitstreamBuffer(
460 bitstream_buffer_id, output_buffers_[bitstream_buffer_id]->handle(),
461 output_buffers_[bitstream_buffer_id]->mapped_size()));
462 }
463
464 void VEAEncoder::FrameFinished(std::unique_ptr<base::SharedMemory> shm) {
465 DVLOG(3) << __FUNCTION__;
466 DCHECK(encoding_task_runner_->BelongsToCurrentThread());
467 input_buffers_.push(std::move(shm));
468 }
469
470 void VEAEncoder::EncodeOnEncodingTaskRunner(
471 const scoped_refptr<VideoFrame>& frame,
472 base::TimeTicks capture_timestamp) {
473 DVLOG(3) << __FUNCTION__;
474 DCHECK(encoding_task_runner_->BelongsToCurrentThread());
475
476 if (input_size_ != frame->visible_rect().size() && video_encoder_) {
477 video_encoder_->Destroy();
478 video_encoder_.reset();
479 }
480
481 if (!video_encoder_) {
482 ConfigureEncoderOnEncodingTaskRunner(frame->visible_rect().size());
483 first_frame_.reset(
484 new std::pair<scoped_refptr<VideoFrame>, base::TimeTicks>(
485 frame, capture_timestamp));
486 }
487
488 if (error_notified_) {
489 DVLOG(3) << "An error occurred in VEA encoder";
490 return;
491 }
492
493 // Drop frames if there is no output buffers available.
494 if (output_buffers_.empty()) {
495 // TODO(emircan): Investigate if resetting encoder would help.
496 DVLOG(3) << "Dropped frame.";
497 return;
498 }
499
500 // If first frame hasn't been encoded, do it first.
501 if (first_frame_) {
502 std::unique_ptr<VideoFrameAndTimestamp> first_frame(first_frame_.release());
503 EncodeOnEncodingTaskRunner(first_frame->first, first_frame->second);
504 }
505
506 // Lower resolutions may fall back to SW encoder in some platforms, i.e. Mac.
507 // In that case, the encoder expects more frames before returning result.
508 // Therefore, a copy is necessary to release the current frame.
509 scoped_refptr<media::VideoFrame> video_frame = frame;
510 if (vea_requested_input_size_ != input_size_ ||
511 input_size_.width() < kVEAEncoderMinResolutionWidth ||
512 input_size_.height() < kVEAEncoderMinResolutionHeight) {
513 // Create SharedMemory backed input buffers as necessary. These SharedMemory
514 // instances will be shared with GPU process.
515 std::unique_ptr<base::SharedMemory> input_buffer;
516 const size_t desired_mapped_size = media::VideoFrame::AllocationSize(
517 media::PIXEL_FORMAT_I420, vea_requested_input_size_);
518 if (input_buffers_.empty()) {
519 input_buffer = gpu_factories_->CreateSharedMemory(desired_mapped_size);
520 } else {
521 do {
522 input_buffer = std::move(input_buffers_.front());
523 input_buffers_.pop();
524 } while (!input_buffers_.empty() &&
525 input_buffer->mapped_size() < desired_mapped_size);
526 if (!input_buffer || input_buffer->mapped_size() < desired_mapped_size)
527 return;
528 }
529
530 video_frame = media::VideoFrame::WrapExternalSharedMemory(
531 media::PIXEL_FORMAT_I420, vea_requested_input_size_,
532 gfx::Rect(input_size_), input_size_,
533 reinterpret_cast<uint8_t*>(input_buffer->memory()),
534 input_buffer->mapped_size(), input_buffer->handle(), 0,
535 frame->timestamp());
536 video_frame->AddDestructionObserver(media::BindToCurrentLoop(
537 base::Bind(&VEAEncoder::FrameFinished, this,
538 base::Passed(std::move(input_buffer)))));
539 libyuv::I420Copy(frame->visible_data(media::VideoFrame::kYPlane),
540 frame->stride(media::VideoFrame::kYPlane),
541 frame->visible_data(media::VideoFrame::kUPlane),
542 frame->stride(media::VideoFrame::kUPlane),
543 frame->visible_data(media::VideoFrame::kVPlane),
544 frame->stride(media::VideoFrame::kVPlane),
545 video_frame->visible_data(media::VideoFrame::kYPlane),
546 video_frame->stride(media::VideoFrame::kYPlane),
547 video_frame->visible_data(media::VideoFrame::kUPlane),
548 video_frame->stride(media::VideoFrame::kUPlane),
549 video_frame->visible_data(media::VideoFrame::kVPlane),
550 video_frame->stride(media::VideoFrame::kVPlane),
551 input_size_.width(), input_size_.height());
552 }
553 frames_in_encode_.push(std::make_pair(video_frame, capture_timestamp));
554
555 encoding_task_runner_->PostTask(
556 FROM_HERE,
557 base::Bind(&media::VideoEncodeAccelerator::Encode,
558 base::Unretained(video_encoder_.get()), video_frame, false));
559 }
560
561 void VEAEncoder::ConfigureEncoderOnEncodingTaskRunner(const gfx::Size& size) {
562 DVLOG(3) << __FUNCTION__;
563 DCHECK(encoding_task_runner_->BelongsToCurrentThread());
564 DCHECK(gpu_factories_->GetTaskRunner()->BelongsToCurrentThread());
565
566 input_size_ = size;
567 video_encoder_ = gpu_factories_->CreateVideoEncodeAccelerator();
568 if (!video_encoder_ ||
569 !video_encoder_->Initialize(media::PIXEL_FORMAT_I420, input_size_, codec_,
570 bits_per_second_, this)) {
571 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
572 }
573 }
574
267 // static 575 // static
268 void VpxEncoder::ShutdownEncoder(std::unique_ptr<base::Thread> encoding_thread, 576 void VpxEncoder::ShutdownEncoder(std::unique_ptr<base::Thread> encoding_thread,
269 ScopedVpxCodecCtxPtr encoder) { 577 ScopedVpxCodecCtxPtr encoder) {
270 DCHECK(encoding_thread->IsRunning()); 578 DCHECK(encoding_thread->IsRunning());
271 encoding_thread->Stop(); 579 encoding_thread->Stop();
272 // Both |encoding_thread| and |encoder| will be destroyed at end-of-scope. 580 // Both |encoding_thread| and |encoder| will be destroyed at end-of-scope.
273 } 581 }
274 582
275 VpxEncoder::VpxEncoder( 583 VpxEncoder::VpxEncoder(
276 bool use_vp9, 584 bool use_vp9,
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after
619 VideoTrackRecorder::VideoTrackRecorder( 927 VideoTrackRecorder::VideoTrackRecorder(
620 CodecId codec, 928 CodecId codec,
621 const blink::WebMediaStreamTrack& track, 929 const blink::WebMediaStreamTrack& track,
622 const OnEncodedVideoCB& on_encoded_video_callback, 930 const OnEncodedVideoCB& on_encoded_video_callback,
623 int32_t bits_per_second) 931 int32_t bits_per_second)
624 : track_(track) { 932 : track_(track) {
625 DCHECK(main_render_thread_checker_.CalledOnValidThread()); 933 DCHECK(main_render_thread_checker_.CalledOnValidThread());
626 DCHECK(!track_.isNull()); 934 DCHECK(!track_.isNull());
627 DCHECK(track_.getExtraData()); 935 DCHECK(track_.getExtraData());
628 936
629 switch (codec) { 937 const auto& vea_supported_profile = CodecIdToVEAProfile(codec);
938 // TODO(emircan): Prioritize software based encoders in lower resolutions.
939 if (vea_supported_profile != media::VIDEO_CODEC_PROFILE_UNKNOWN) {
940 encoder_ = new VEAEncoder(on_encoded_video_callback, bits_per_second,
941 vea_supported_profile);
942 } else {
943 switch (codec) {
630 #if BUILDFLAG(RTC_USE_H264) 944 #if BUILDFLAG(RTC_USE_H264)
631 case CodecId::H264: 945 case CodecId::H264:
632 encoder_ = new H264Encoder(on_encoded_video_callback, bits_per_second); 946 encoder_ = new H264Encoder(on_encoded_video_callback, bits_per_second);
633 break; 947 break;
634 #endif 948 #endif
635 case CodecId::VP8: 949 case CodecId::VP8:
636 case CodecId::VP9: 950 case CodecId::VP9:
637 encoder_ = new VpxEncoder(codec == CodecId::VP9, 951 encoder_ = new VpxEncoder(codec == CodecId::VP9,
638 on_encoded_video_callback, bits_per_second); 952 on_encoded_video_callback, bits_per_second);
639 break; 953 break;
640 default: 954 default:
641 NOTREACHED() << "Unsupported codec"; 955 NOTREACHED() << "Unsupported codec";
956 }
642 } 957 }
643 958
644 // StartFrameEncode() will be called on Render IO thread. 959 // StartFrameEncode() will be called on Render IO thread.
645 MediaStreamVideoSink::ConnectToTrack( 960 MediaStreamVideoSink::ConnectToTrack(
646 track_, 961 track_,
647 base::Bind(&VideoTrackRecorder::Encoder::StartFrameEncode, encoder_), 962 base::Bind(&VideoTrackRecorder::Encoder::StartFrameEncode, encoder_),
648 false); 963 false);
649 } 964 }
650 965
651 VideoTrackRecorder::~VideoTrackRecorder() { 966 VideoTrackRecorder::~VideoTrackRecorder() {
(...skipping 14 matching lines...) Expand all
666 encoder_->SetPaused(false); 981 encoder_->SetPaused(false);
667 } 982 }
668 983
669 void VideoTrackRecorder::OnVideoFrameForTesting( 984 void VideoTrackRecorder::OnVideoFrameForTesting(
670 const scoped_refptr<media::VideoFrame>& frame, 985 const scoped_refptr<media::VideoFrame>& frame,
671 base::TimeTicks timestamp) { 986 base::TimeTicks timestamp) {
672 encoder_->StartFrameEncode(frame, timestamp); 987 encoder_->StartFrameEncode(frame, timestamp);
673 } 988 }
674 989
675 } // namespace content 990 } // 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