OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/rtc_video_encoder.h" | 5 #include "content/renderer/media/rtc_video_encoder.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/location.h" | 8 #include "base/location.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/memory/scoped_vector.h" | 10 #include "base/memory/scoped_vector.h" |
11 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
12 #include "base/rand_util.h" | 12 #include "base/rand_util.h" |
13 #include "base/single_thread_task_runner.h" | 13 #include "base/single_thread_task_runner.h" |
14 #include "base/synchronization/waitable_event.h" | 14 #include "base/synchronization/waitable_event.h" |
15 #include "base/thread_task_runner_handle.h" | 15 #include "base/thread_task_runner_handle.h" |
| 16 #include "media/base/bind_to_current_loop.h" |
16 #include "media/base/bitstream_buffer.h" | 17 #include "media/base/bitstream_buffer.h" |
17 #include "media/base/video_frame.h" | 18 #include "media/base/video_frame.h" |
18 #include "media/base/video_util.h" | 19 #include "media/base/video_util.h" |
19 #include "media/filters/h264_parser.h" | 20 #include "media/filters/h264_parser.h" |
20 #include "media/renderers/gpu_video_accelerator_factories.h" | 21 #include "media/renderers/gpu_video_accelerator_factories.h" |
21 #include "media/video/video_encode_accelerator.h" | 22 #include "media/video/video_encode_accelerator.h" |
22 #include "third_party/libyuv/include/libyuv.h" | 23 #include "third_party/libyuv/include/libyuv.h" |
23 #include "third_party/webrtc/system_wrappers/interface/tick_util.h" | 24 #include "third_party/webrtc/system_wrappers/interface/tick_util.h" |
24 | 25 |
25 #define NOTIFY_ERROR(x) \ | 26 #define NOTIFY_ERROR(x) \ |
(...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
484 bool next_frame_keyframe = input_next_frame_keyframe_; | 485 bool next_frame_keyframe = input_next_frame_keyframe_; |
485 input_next_frame_ = NULL; | 486 input_next_frame_ = NULL; |
486 input_next_frame_keyframe_ = false; | 487 input_next_frame_keyframe_ = false; |
487 | 488 |
488 if (!video_encoder_) { | 489 if (!video_encoder_) { |
489 SignalAsyncWaiter(WEBRTC_VIDEO_CODEC_ERROR); | 490 SignalAsyncWaiter(WEBRTC_VIDEO_CODEC_ERROR); |
490 return; | 491 return; |
491 } | 492 } |
492 | 493 |
493 const int index = input_buffers_free_.back(); | 494 const int index = input_buffers_free_.back(); |
494 base::SharedMemory* input_buffer = input_buffers_[index]; | 495 scoped_refptr<media::VideoFrame> frame; |
495 scoped_refptr<media::VideoFrame> frame = | 496 if (next_frame->native_handle()) { |
496 media::VideoFrame::WrapExternalSharedMemory( | 497 frame = static_cast<media::VideoFrame*>(next_frame->native_handle()); |
497 media::VideoFrame::I420, | 498 } else { |
498 input_frame_coded_size_, | 499 base::SharedMemory* input_buffer = input_buffers_[index]; |
499 gfx::Rect(input_visible_size_), | 500 frame = media::VideoFrame::WrapExternalSharedMemory( |
500 input_visible_size_, | 501 media::VideoFrame::I420, |
501 reinterpret_cast<uint8*>(input_buffer->memory()), | 502 input_frame_coded_size_, |
502 input_buffer->mapped_size(), | 503 gfx::Rect(input_visible_size_), |
503 input_buffer->handle(), | 504 input_visible_size_, |
504 0, | 505 reinterpret_cast<uint8*>(input_buffer->memory()), |
505 base::TimeDelta()); | 506 input_buffer->mapped_size(), |
506 frame->AddDestructionObserver( | 507 input_buffer->handle(), |
507 base::Bind(&RTCVideoEncoder::Impl::EncodeFrameFinished, this, index)); | 508 0, |
508 if (!frame.get()) { | 509 base::TimeDelta()); |
509 DLOG(ERROR) << "Impl::EncodeOneFrame(): failed to create frame"; | 510 frame->AddDestructionObserver( |
510 NOTIFY_ERROR(media::VideoEncodeAccelerator::kPlatformFailureError); | 511 base::Bind(&RTCVideoEncoder::Impl::EncodeFrameFinished, this, index)); |
511 return; | 512 if (!frame.get()) { |
| 513 DLOG(ERROR) << "Impl::EncodeOneFrame(): failed to create frame"; |
| 514 NOTIFY_ERROR(media::VideoEncodeAccelerator::kPlatformFailureError); |
| 515 return; |
| 516 } |
| 517 // Do a strided copy of the input frame to match the input requirements for |
| 518 // the encoder. |
| 519 // TODO(sheu): support zero-copy from WebRTC. http://crbug.com/269312 |
| 520 if (libyuv::I420Copy(next_frame->buffer(webrtc::kYPlane), |
| 521 next_frame->stride(webrtc::kYPlane), |
| 522 next_frame->buffer(webrtc::kUPlane), |
| 523 next_frame->stride(webrtc::kUPlane), |
| 524 next_frame->buffer(webrtc::kVPlane), |
| 525 next_frame->stride(webrtc::kVPlane), |
| 526 frame->data(media::VideoFrame::kYPlane), |
| 527 frame->stride(media::VideoFrame::kYPlane), |
| 528 frame->data(media::VideoFrame::kUPlane), |
| 529 frame->stride(media::VideoFrame::kUPlane), |
| 530 frame->data(media::VideoFrame::kVPlane), |
| 531 frame->stride(media::VideoFrame::kVPlane), |
| 532 next_frame->width(), next_frame->height())) { |
| 533 DLOG(ERROR) << "Failed to copy buffer"; |
| 534 NOTIFY_ERROR(media::VideoEncodeAccelerator::kPlatformFailureError); |
| 535 return; |
| 536 } |
512 } | 537 } |
513 | 538 frame->AddDestructionObserver(media::BindToCurrentLoop( |
514 // Do a strided copy of the input frame to match the input requirements for | 539 base::Bind(&RTCVideoEncoder::Impl::EncodeFrameFinished, this, index))); |
515 // the encoder. | |
516 // TODO(sheu): support zero-copy from WebRTC. http://crbug.com/269312 | |
517 if (libyuv::I420Copy(next_frame->buffer(webrtc::kYPlane), | |
518 next_frame->stride(webrtc::kYPlane), | |
519 next_frame->buffer(webrtc::kUPlane), | |
520 next_frame->stride(webrtc::kUPlane), | |
521 next_frame->buffer(webrtc::kVPlane), | |
522 next_frame->stride(webrtc::kVPlane), | |
523 frame->data(media::VideoFrame::kYPlane), | |
524 frame->stride(media::VideoFrame::kYPlane), | |
525 frame->data(media::VideoFrame::kUPlane), | |
526 frame->stride(media::VideoFrame::kUPlane), | |
527 frame->data(media::VideoFrame::kVPlane), | |
528 frame->stride(media::VideoFrame::kVPlane), | |
529 next_frame->width(), | |
530 next_frame->height())) { | |
531 DLOG(ERROR) << "Failed to copy buffer"; | |
532 NOTIFY_ERROR(media::VideoEncodeAccelerator::kPlatformFailureError); | |
533 return; | |
534 } | |
535 | |
536 video_encoder_->Encode(frame, next_frame_keyframe); | 540 video_encoder_->Encode(frame, next_frame_keyframe); |
537 input_buffers_free_.pop_back(); | 541 input_buffers_free_.pop_back(); |
538 SignalAsyncWaiter(WEBRTC_VIDEO_CODEC_OK); | 542 SignalAsyncWaiter(WEBRTC_VIDEO_CODEC_OK); |
539 } | 543 } |
540 | 544 |
541 void RTCVideoEncoder::Impl::EncodeFrameFinished(int index) { | 545 void RTCVideoEncoder::Impl::EncodeFrameFinished(int index) { |
542 DVLOG(3) << "Impl::EncodeFrameFinished(): index=" << index; | 546 DVLOG(3) << "Impl::EncodeFrameFinished(): index=" << index; |
543 DCHECK(thread_checker_.CalledOnValidThread()); | 547 DCHECK(thread_checker_.CalledOnValidThread()); |
544 DCHECK_GE(index, 0); | 548 DCHECK_GE(index, 0); |
545 DCHECK_LT(index, static_cast<int>(input_buffers_.size())); | 549 DCHECK_LT(index, static_cast<int>(input_buffers_.size())); |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
779 UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoEncoderInitEncodeSuccess", | 783 UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoEncoderInitEncodeSuccess", |
780 init_retval == WEBRTC_VIDEO_CODEC_OK); | 784 init_retval == WEBRTC_VIDEO_CODEC_OK); |
781 if (init_retval == WEBRTC_VIDEO_CODEC_OK) { | 785 if (init_retval == WEBRTC_VIDEO_CODEC_OK) { |
782 UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoEncoderProfile", | 786 UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoEncoderProfile", |
783 profile, | 787 profile, |
784 media::VIDEO_CODEC_PROFILE_MAX + 1); | 788 media::VIDEO_CODEC_PROFILE_MAX + 1); |
785 } | 789 } |
786 } | 790 } |
787 | 791 |
788 } // namespace content | 792 } // namespace content |
OLD | NEW |