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

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

Issue 1212133002: Passing Texture backed VideoFrame through WebRTC wrappers (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove __func__ Created 5 years, 6 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 | « no previous file | content/renderer/media/webrtc/webrtc_video_capturer_adapter.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 389 matching lines...) Expand 10 before | Expand all | Expand 10 after
415 NOTIFY_ERROR(media::VideoEncodeAccelerator::kPlatformFailureError); 416 NOTIFY_ERROR(media::VideoEncodeAccelerator::kPlatformFailureError);
416 return; 417 return;
417 } 418 }
418 output_buffers_free_count_--; 419 output_buffers_free_count_--;
419 420
420 // Use webrtc timestamps to ensure correct RTP sender behavior. 421 // Use webrtc timestamps to ensure correct RTP sender behavior.
421 // TODO(hshi): obtain timestamp from the capturer, see crbug.com/350106. 422 // TODO(hshi): obtain timestamp from the capturer, see crbug.com/350106.
422 const int64 capture_time_us = webrtc::TickTime::MicrosecondTimestamp(); 423 const int64 capture_time_us = webrtc::TickTime::MicrosecondTimestamp();
423 424
424 // Derive the capture time (in ms) and RTP timestamp (in 90KHz ticks). 425 // Derive the capture time (in ms) and RTP timestamp (in 90KHz ticks).
425 int64 capture_time_ms = capture_time_us / 1000; 426 const int64 capture_time_ms = capture_time_us / 1000;
426 uint32_t rtp_timestamp = static_cast<uint32_t>(capture_time_us * 90 / 1000); 427 const uint32_t rtp_timestamp =
428 static_cast<uint32_t>(capture_time_us * 90 / 1000);
427 429
428 scoped_ptr<webrtc::EncodedImage> image(new webrtc::EncodedImage( 430 scoped_ptr<webrtc::EncodedImage> image(new webrtc::EncodedImage(
429 reinterpret_cast<uint8_t*>(output_buffer->memory()), 431 reinterpret_cast<uint8_t*>(output_buffer->memory()),
430 payload_size, 432 payload_size,
431 output_buffer->mapped_size())); 433 output_buffer->mapped_size()));
432 image->_encodedWidth = input_visible_size_.width(); 434 image->_encodedWidth = input_visible_size_.width();
433 image->_encodedHeight = input_visible_size_.height(); 435 image->_encodedHeight = input_visible_size_.height();
434 image->_timeStamp = rtp_timestamp; 436 image->_timeStamp = rtp_timestamp;
435 image->capture_time_ms_ = capture_time_ms; 437 image->capture_time_ms_ = capture_time_ms;
436 image->_frameType = (key_frame ? webrtc::kKeyFrame : webrtc::kDeltaFrame); 438 image->_frameType = (key_frame ? webrtc::kKeyFrame : webrtc::kDeltaFrame);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
474 DVLOG(3) << "Impl::EncodeOneFrame()"; 476 DVLOG(3) << "Impl::EncodeOneFrame()";
475 DCHECK(thread_checker_.CalledOnValidThread()); 477 DCHECK(thread_checker_.CalledOnValidThread());
476 DCHECK(input_next_frame_); 478 DCHECK(input_next_frame_);
477 DCHECK(!input_buffers_free_.empty()); 479 DCHECK(!input_buffers_free_.empty());
478 480
479 // EncodeOneFrame() may re-enter EncodeFrameFinished() if VEA::Encode() fails, 481 // EncodeOneFrame() may re-enter EncodeFrameFinished() if VEA::Encode() fails,
480 // we receive a VEA::NotifyError(), and the media::VideoFrame we pass to 482 // we receive a VEA::NotifyError(), and the media::VideoFrame we pass to
481 // Encode() gets destroyed early. Handle this by resetting our 483 // Encode() gets destroyed early. Handle this by resetting our
482 // input_next_frame_* state before we hand off the VideoFrame to the VEA. 484 // input_next_frame_* state before we hand off the VideoFrame to the VEA.
483 const webrtc::VideoFrame* next_frame = input_next_frame_; 485 const webrtc::VideoFrame* next_frame = input_next_frame_;
484 bool next_frame_keyframe = input_next_frame_keyframe_; 486 const bool next_frame_keyframe = input_next_frame_keyframe_;
485 input_next_frame_ = NULL; 487 input_next_frame_ = NULL;
486 input_next_frame_keyframe_ = false; 488 input_next_frame_keyframe_ = false;
487 489
488 if (!video_encoder_) { 490 if (!video_encoder_) {
489 SignalAsyncWaiter(WEBRTC_VIDEO_CODEC_ERROR); 491 SignalAsyncWaiter(WEBRTC_VIDEO_CODEC_ERROR);
490 return; 492 return;
491 } 493 }
492 494
493 const int index = input_buffers_free_.back(); 495 const int index = input_buffers_free_.back();
494 base::SharedMemory* input_buffer = input_buffers_[index]; 496 scoped_refptr<media::VideoFrame> frame;
495 scoped_refptr<media::VideoFrame> frame = 497 if (next_frame->native_handle()) {
496 media::VideoFrame::WrapExternalSharedMemory( 498 frame = static_cast<media::VideoFrame*>(next_frame->native_handle());
497 media::VideoFrame::I420, 499 } else {
498 input_frame_coded_size_, 500 base::SharedMemory* input_buffer = input_buffers_[index];
499 gfx::Rect(input_visible_size_), 501 frame = media::VideoFrame::WrapExternalSharedMemory(
500 input_visible_size_, 502 media::VideoFrame::I420,
501 reinterpret_cast<uint8*>(input_buffer->memory()), 503 input_frame_coded_size_,
502 input_buffer->mapped_size(), 504 gfx::Rect(input_visible_size_),
503 input_buffer->handle(), 505 input_visible_size_,
504 0, 506 reinterpret_cast<uint8*>(input_buffer->memory()),
505 base::TimeDelta()); 507 input_buffer->mapped_size(),
506 frame->AddDestructionObserver( 508 input_buffer->handle(),
507 base::Bind(&RTCVideoEncoder::Impl::EncodeFrameFinished, this, index)); 509 0,
508 if (!frame.get()) { 510 base::TimeDelta());
509 DLOG(ERROR) << "Impl::EncodeOneFrame(): failed to create frame"; 511 frame->AddDestructionObserver(
510 NOTIFY_ERROR(media::VideoEncodeAccelerator::kPlatformFailureError); 512 base::Bind(&RTCVideoEncoder::Impl::EncodeFrameFinished, this, index));
511 return; 513 if (!frame.get()) {
514 DLOG(ERROR) << "Impl::EncodeOneFrame(): failed to create frame";
515 NOTIFY_ERROR(media::VideoEncodeAccelerator::kPlatformFailureError);
516 return;
517 }
518 // Do a strided copy of the input frame to match the input requirements for
519 // the encoder.
520 // TODO(sheu): support zero-copy from WebRTC. http://crbug.com/269312
521 if (libyuv::I420Copy(next_frame->buffer(webrtc::kYPlane),
522 next_frame->stride(webrtc::kYPlane),
523 next_frame->buffer(webrtc::kUPlane),
524 next_frame->stride(webrtc::kUPlane),
525 next_frame->buffer(webrtc::kVPlane),
526 next_frame->stride(webrtc::kVPlane),
527 frame->data(media::VideoFrame::kYPlane),
528 frame->stride(media::VideoFrame::kYPlane),
529 frame->data(media::VideoFrame::kUPlane),
530 frame->stride(media::VideoFrame::kUPlane),
531 frame->data(media::VideoFrame::kVPlane),
532 frame->stride(media::VideoFrame::kVPlane),
533 next_frame->width(), next_frame->height())) {
534 DLOG(ERROR) << "Failed to copy buffer";
535 NOTIFY_ERROR(media::VideoEncodeAccelerator::kPlatformFailureError);
536 return;
537 }
512 } 538 }
513 539 frame->AddDestructionObserver(media::BindToCurrentLoop(
mcasas 2015/06/26 23:52:56 This will register EncodeFrameFinished() a second
emircan 2015/06/27 00:37:17 Thanks for pointing out, I removed l.511. I must h
514 // Do a strided copy of the input frame to match the input requirements for 540 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); 541 video_encoder_->Encode(frame, next_frame_keyframe);
537 input_buffers_free_.pop_back(); 542 input_buffers_free_.pop_back();
538 SignalAsyncWaiter(WEBRTC_VIDEO_CODEC_OK); 543 SignalAsyncWaiter(WEBRTC_VIDEO_CODEC_OK);
539 } 544 }
540 545
541 void RTCVideoEncoder::Impl::EncodeFrameFinished(int index) { 546 void RTCVideoEncoder::Impl::EncodeFrameFinished(int index) {
542 DVLOG(3) << "Impl::EncodeFrameFinished(): index=" << index; 547 DVLOG(3) << "Impl::EncodeFrameFinished(): index=" << index;
543 DCHECK(thread_checker_.CalledOnValidThread()); 548 DCHECK(thread_checker_.CalledOnValidThread());
544 DCHECK_GE(index, 0); 549 DCHECK_GE(index, 0);
545 DCHECK_LT(index, static_cast<int>(input_buffers_.size())); 550 DCHECK_LT(index, static_cast<int>(input_buffers_.size()));
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
594 int32_t RTCVideoEncoder::InitEncode(const webrtc::VideoCodec* codec_settings, 599 int32_t RTCVideoEncoder::InitEncode(const webrtc::VideoCodec* codec_settings,
595 int32_t number_of_cores, 600 int32_t number_of_cores,
596 size_t max_payload_size) { 601 size_t max_payload_size) {
597 DVLOG(1) << "InitEncode(): codecType=" << codec_settings->codecType 602 DVLOG(1) << "InitEncode(): codecType=" << codec_settings->codecType
598 << ", width=" << codec_settings->width 603 << ", width=" << codec_settings->width
599 << ", height=" << codec_settings->height 604 << ", height=" << codec_settings->height
600 << ", startBitrate=" << codec_settings->startBitrate; 605 << ", startBitrate=" << codec_settings->startBitrate;
601 DCHECK(thread_checker_.CalledOnValidThread()); 606 DCHECK(thread_checker_.CalledOnValidThread());
602 DCHECK(!impl_.get()); 607 DCHECK(!impl_.get());
603 608
604 media::VideoCodecProfile profile = WebRTCVideoCodecToVideoCodecProfile( 609 const media::VideoCodecProfile profile =
605 video_codec_type_, codec_settings); 610 WebRTCVideoCodecToVideoCodecProfile(video_codec_type_, codec_settings);
606 611
607 weak_factory_.InvalidateWeakPtrs(); 612 weak_factory_.InvalidateWeakPtrs();
608 impl_ = new Impl(weak_factory_.GetWeakPtr(), gpu_factories_); 613 impl_ = new Impl(weak_factory_.GetWeakPtr(), gpu_factories_);
609 base::WaitableEvent initialization_waiter(true, false); 614 base::WaitableEvent initialization_waiter(true, false);
610 int32_t initialization_retval = WEBRTC_VIDEO_CODEC_UNINITIALIZED; 615 int32_t initialization_retval = WEBRTC_VIDEO_CODEC_UNINITIALIZED;
611 gpu_factories_->GetTaskRunner()->PostTask( 616 gpu_factories_->GetTaskRunner()->PostTask(
612 FROM_HERE, 617 FROM_HERE,
613 base::Bind(&RTCVideoEncoder::Impl::CreateAndInitializeVEA, 618 base::Bind(&RTCVideoEncoder::Impl::CreateAndInitializeVEA,
614 impl_, 619 impl_,
615 gfx::Size(codec_settings->width, codec_settings->height), 620 gfx::Size(codec_settings->width, codec_settings->height),
(...skipping 11 matching lines...) Expand all
627 int32_t RTCVideoEncoder::Encode( 632 int32_t RTCVideoEncoder::Encode(
628 const webrtc::VideoFrame& input_image, 633 const webrtc::VideoFrame& input_image,
629 const webrtc::CodecSpecificInfo* codec_specific_info, 634 const webrtc::CodecSpecificInfo* codec_specific_info,
630 const std::vector<webrtc::VideoFrameType>* frame_types) { 635 const std::vector<webrtc::VideoFrameType>* frame_types) {
631 DVLOG(3) << "Encode()"; 636 DVLOG(3) << "Encode()";
632 if (!impl_.get()) { 637 if (!impl_.get()) {
633 DVLOG(3) << "Encode(): returning impl_status_=" << impl_status_; 638 DVLOG(3) << "Encode(): returning impl_status_=" << impl_status_;
634 return impl_status_; 639 return impl_status_;
635 } 640 }
636 641
637 bool want_key_frame = frame_types && frame_types->size() && 642 const bool want_key_frame = frame_types && frame_types->size() &&
638 frame_types->front() == webrtc::kKeyFrame; 643 frame_types->front() == webrtc::kKeyFrame;
639 base::WaitableEvent encode_waiter(true, false); 644 base::WaitableEvent encode_waiter(true, false);
640 int32_t encode_retval = WEBRTC_VIDEO_CODEC_UNINITIALIZED; 645 int32_t encode_retval = WEBRTC_VIDEO_CODEC_UNINITIALIZED;
641 gpu_factories_->GetTaskRunner()->PostTask( 646 gpu_factories_->GetTaskRunner()->PostTask(
642 FROM_HERE, 647 FROM_HERE,
643 base::Bind(&RTCVideoEncoder::Impl::Enqueue, 648 base::Bind(&RTCVideoEncoder::Impl::Enqueue,
644 impl_, 649 impl_,
645 &input_image, 650 &input_image,
646 want_key_frame, 651 want_key_frame,
647 &encode_waiter, 652 &encode_waiter,
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
779 UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoEncoderInitEncodeSuccess", 784 UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoEncoderInitEncodeSuccess",
780 init_retval == WEBRTC_VIDEO_CODEC_OK); 785 init_retval == WEBRTC_VIDEO_CODEC_OK);
781 if (init_retval == WEBRTC_VIDEO_CODEC_OK) { 786 if (init_retval == WEBRTC_VIDEO_CODEC_OK) {
782 UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoEncoderProfile", 787 UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoEncoderProfile",
783 profile, 788 profile,
784 media::VIDEO_CODEC_PROFILE_MAX + 1); 789 media::VIDEO_CODEC_PROFILE_MAX + 1);
785 } 790 }
786 } 791 }
787 792
788 } // namespace content 793 } // namespace content
OLDNEW
« no previous file with comments | « no previous file | content/renderer/media/webrtc/webrtc_video_capturer_adapter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698