Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "media/cast/sender/external_video_encoder.h" | 5 #include "media/cast/sender/external_video_encoder.h" |
| 6 | 6 |
| 7 #include <cmath> | 7 #include <cmath> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 22 #include "media/base/video_frame.h" | 22 #include "media/base/video_frame.h" |
| 23 #include "media/base/video_types.h" | 23 #include "media/base/video_types.h" |
| 24 #include "media/base/video_util.h" | 24 #include "media/base/video_util.h" |
| 25 #include "media/cast/cast_config.h" | 25 #include "media/cast/cast_config.h" |
| 26 #include "media/cast/cast_defines.h" | 26 #include "media/cast/cast_defines.h" |
| 27 #include "media/cast/common/rtp_time.h" | 27 #include "media/cast/common/rtp_time.h" |
| 28 #include "media/cast/logging/logging_defines.h" | 28 #include "media/cast/logging/logging_defines.h" |
| 29 #include "media/cast/net/cast_transport_config.h" | 29 #include "media/cast/net/cast_transport_config.h" |
| 30 #include "media/cast/sender/vp8_quantizer_parser.h" | 30 #include "media/cast/sender/vp8_quantizer_parser.h" |
| 31 #include "media/filters/h264_parser.h" | 31 #include "media/filters/h264_parser.h" |
| 32 #include "third_party/libyuv/include/libyuv.h" | |
| 32 | 33 |
| 33 namespace { | 34 namespace { |
| 34 | 35 |
| 35 enum { MAX_H264_QUANTIZER = 51 }; | 36 enum { MAX_H264_QUANTIZER = 51 }; |
| 36 static const size_t kOutputBufferCount = 3; | 37 static const size_t kOutputBufferCount = 3; |
| 37 | 38 |
| 38 } // namespace | 39 } // namespace |
| 39 | 40 |
| 40 namespace media { | 41 namespace media { |
| 41 namespace cast { | 42 namespace cast { |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 142 const VideoEncoder::FrameEncodedCallback& frame_encoded_callback) { | 143 const VideoEncoder::FrameEncodedCallback& frame_encoded_callback) { |
| 143 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 144 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 144 | 145 |
| 145 if (!encoder_active_) | 146 if (!encoder_active_) |
| 146 return; | 147 return; |
| 147 | 148 |
| 148 in_progress_frame_encodes_.push_back(InProgressFrameEncode( | 149 in_progress_frame_encodes_.push_back(InProgressFrameEncode( |
| 149 video_frame, reference_time, frame_encoded_callback, | 150 video_frame, reference_time, frame_encoded_callback, |
| 150 requested_bit_rate_)); | 151 requested_bit_rate_)); |
| 151 | 152 |
| 153 scoped_refptr<media::VideoFrame> frame = video_frame; | |
| 154 if (video_frame->coded_size() != frame_coded_size_) { | |
|
miu
2016/04/26 19:20:17
For safety, we should probably:
DCHECK_GE(frame
xjz
2016/04/27 22:13:54
Done.
| |
| 155 frame = VideoFrame::CreateZeroInitializedFrame( | |
| 156 video_frame->format(), frame_coded_size_, video_frame->visible_rect(), | |
| 157 video_frame->natural_size(), video_frame->timestamp()); | |
| 158 if (!frame.get()) { | |
| 159 VLOG(1) << "Error: ExternalVideoEncoder: CreateFrame failed."; | |
| 160 return; | |
| 161 } | |
| 162 | |
| 163 // Copy the input frame to match the input requirements for the encoder. | |
| 164 if (libyuv::I420Copy(video_frame->data(media::VideoFrame::kYPlane), | |
| 165 video_frame->stride(media::VideoFrame::kYPlane), | |
| 166 video_frame->data(media::VideoFrame::kUPlane), | |
| 167 video_frame->stride(media::VideoFrame::kUPlane), | |
| 168 video_frame->data(media::VideoFrame::kVPlane), | |
| 169 video_frame->stride(media::VideoFrame::kVPlane), | |
| 170 frame->data(media::VideoFrame::kYPlane), | |
| 171 frame->stride(media::VideoFrame::kYPlane), | |
| 172 frame->data(media::VideoFrame::kUPlane), | |
| 173 frame->stride(media::VideoFrame::kUPlane), | |
| 174 frame->data(media::VideoFrame::kVPlane), | |
| 175 frame->stride(media::VideoFrame::kVPlane), | |
| 176 video_frame->visible_rect().width(), | |
| 177 video_frame->visible_rect().height())) { | |
| 178 VLOG(1) << "ERROR: ExternalVideoEncoder: Copy failed."; | |
| 179 return; | |
| 180 } | |
| 181 } | |
| 182 | |
| 152 // BitstreamBufferReady will be called once the encoder is done. | 183 // BitstreamBufferReady will be called once the encoder is done. |
| 153 video_encode_accelerator_->Encode(video_frame, key_frame_requested); | 184 video_encode_accelerator_->Encode(frame, key_frame_requested); |
| 154 } | 185 } |
| 155 | 186 |
| 156 protected: | 187 protected: |
| 157 void NotifyError(VideoEncodeAccelerator::Error error) final { | 188 void NotifyError(VideoEncodeAccelerator::Error error) final { |
| 158 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 189 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 159 | 190 |
| 160 DCHECK(error != VideoEncodeAccelerator::kInvalidArgumentError && | 191 DCHECK(error != VideoEncodeAccelerator::kInvalidArgumentError && |
| 161 error != VideoEncodeAccelerator::kIllegalStateError); | 192 error != VideoEncodeAccelerator::kIllegalStateError); |
| 162 | 193 |
| 163 encoder_active_ = false; | 194 encoder_active_ = false; |
| 164 | 195 |
| 165 cast_environment_->PostTask( | 196 cast_environment_->PostTask( |
| 166 CastEnvironment::MAIN, | 197 CastEnvironment::MAIN, |
| 167 FROM_HERE, | 198 FROM_HERE, |
| 168 base::Bind(status_change_cb_, STATUS_CODEC_RUNTIME_ERROR)); | 199 base::Bind(status_change_cb_, STATUS_CODEC_RUNTIME_ERROR)); |
| 169 | 200 |
| 170 // TODO(miu): Force-flush all |in_progress_frame_encodes_| immediately so | 201 // TODO(miu): Force-flush all |in_progress_frame_encodes_| immediately so |
| 171 // pending frames do not become stuck, freezing VideoSender. | 202 // pending frames do not become stuck, freezing VideoSender. |
| 172 } | 203 } |
| 173 | 204 |
| 174 // Called to allocate the input and output buffers. | 205 // Called to allocate the input and output buffers. |
| 175 void RequireBitstreamBuffers(unsigned int input_count, | 206 void RequireBitstreamBuffers(unsigned int input_count, |
| 176 const gfx::Size& input_coded_size, | 207 const gfx::Size& input_coded_size, |
| 177 size_t output_buffer_size) final { | 208 size_t output_buffer_size) final { |
| 178 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 209 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 179 | 210 |
| 180 // TODO(miu): Investigate why we are ignoring |input_count| (4) and instead | 211 frame_coded_size_ = input_coded_size; |
| 181 // using |kOutputBufferCount| (3) here. | 212 |
| 182 for (size_t j = 0; j < kOutputBufferCount; ++j) { | 213 for (size_t j = 0; j < kOutputBufferCount; ++j) { |
| 183 create_video_encode_memory_cb_.Run( | 214 create_video_encode_memory_cb_.Run( |
| 184 output_buffer_size, | 215 output_buffer_size, |
| 185 base::Bind(&VEAClientImpl::OnCreateSharedMemory, this)); | 216 base::Bind(&VEAClientImpl::OnCreateSharedMemory, this)); |
| 186 } | 217 } |
| 187 } | 218 } |
| 188 | 219 |
| 189 // Encoder has encoded a frame and it's available in one of the output | 220 // Encoder has encoded a frame and it's available in one of the output |
| 190 // buffers. Package the result in a media::cast::EncodedFrame and post it | 221 // buffers. Package the result in a media::cast::EncodedFrame and post it |
| 191 // to the Cast MAIN thread via the supplied callback. | 222 // to the Cast MAIN thread via the supplied callback. |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 469 int requested_bit_rate_; | 500 int requested_bit_rate_; |
| 470 | 501 |
| 471 // Used to compute utilization metrics for each frame. | 502 // Used to compute utilization metrics for each frame. |
| 472 QuantizerEstimator quantizer_estimator_; | 503 QuantizerEstimator quantizer_estimator_; |
| 473 | 504 |
| 474 // Set to true once a frame with zero-length encoded data has been | 505 // Set to true once a frame with zero-length encoded data has been |
| 475 // encountered. | 506 // encountered. |
| 476 // TODO(miu): Remove after discovering cause. http://crbug.com/519022 | 507 // TODO(miu): Remove after discovering cause. http://crbug.com/519022 |
| 477 bool has_seen_zero_length_encoded_frame_; | 508 bool has_seen_zero_length_encoded_frame_; |
| 478 | 509 |
| 510 // The coded size of the video frame required by Encoder. This size is | |
| 511 // obtained from VEA through |RequireBitstreamBuffers()|. | |
| 512 gfx::Size frame_coded_size_; | |
| 513 | |
| 479 DISALLOW_COPY_AND_ASSIGN(VEAClientImpl); | 514 DISALLOW_COPY_AND_ASSIGN(VEAClientImpl); |
| 480 }; | 515 }; |
| 481 | 516 |
| 482 // static | 517 // static |
| 483 bool ExternalVideoEncoder::IsSupported(const VideoSenderConfig& video_config) { | 518 bool ExternalVideoEncoder::IsSupported(const VideoSenderConfig& video_config) { |
| 484 if (video_config.codec != CODEC_VIDEO_VP8 && | 519 if (video_config.codec != CODEC_VIDEO_VP8 && |
| 485 video_config.codec != CODEC_VIDEO_H264) | 520 video_config.codec != CODEC_VIDEO_H264) |
| 486 return false; | 521 return false; |
| 487 | 522 |
| 488 // TODO(miu): "Layering hooks" are needed to be able to query outside of | 523 // TODO(miu): "Layering hooks" are needed to be able to query outside of |
| (...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 787 const double kEntropyAtMaxQuantizer = 7.5; | 822 const double kEntropyAtMaxQuantizer = 7.5; |
| 788 const double slope = | 823 const double slope = |
| 789 (MAX_VP8_QUANTIZER - MIN_VP8_QUANTIZER) / kEntropyAtMaxQuantizer; | 824 (MAX_VP8_QUANTIZER - MIN_VP8_QUANTIZER) / kEntropyAtMaxQuantizer; |
| 790 const double quantizer = std::min<double>( | 825 const double quantizer = std::min<double>( |
| 791 MAX_VP8_QUANTIZER, MIN_VP8_QUANTIZER + slope * shannon_entropy); | 826 MAX_VP8_QUANTIZER, MIN_VP8_QUANTIZER + slope * shannon_entropy); |
| 792 return quantizer; | 827 return quantizer; |
| 793 } | 828 } |
| 794 | 829 |
| 795 } // namespace cast | 830 } // namespace cast |
| 796 } // namespace media | 831 } // namespace media |
| OLD | NEW |