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" |
| 11 #include "base/debug/crash_logging.h" | 11 #include "base/debug/crash_logging.h" |
| 12 #include "base/debug/dump_without_crashing.h" | 12 #include "base/debug/dump_without_crashing.h" |
| 13 #include "base/format_macros.h" | 13 #include "base/format_macros.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/macros.h" | 15 #include "base/macros.h" |
| 16 #include "base/memory/scoped_vector.h" | |
| 17 #include "base/memory/shared_memory.h" | 16 #include "base/memory/shared_memory.h" |
| 18 #include "base/message_loop/message_loop.h" | 17 #include "base/message_loop/message_loop.h" |
| 19 #include "base/metrics/histogram.h" | 18 #include "base/metrics/histogram.h" |
| 20 #include "base/strings/stringprintf.h" | 19 #include "base/strings/stringprintf.h" |
| 21 #include "build/build_config.h" | 20 #include "build/build_config.h" |
| 21 #include "media/base/bind_to_current_loop.h" | |
| 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 | 32 |
| 33 namespace { | 33 namespace { |
| 34 | 34 |
| 35 enum { MAX_H264_QUANTIZER = 51 }; | 35 enum { MAX_H264_QUANTIZER = 51 }; |
| 36 | |
| 37 // Number of buffers for encoded bit stream. | |
| 36 static const size_t kOutputBufferCount = 3; | 38 static const size_t kOutputBufferCount = 3; |
| 37 | 39 |
| 40 // Maximum number of extra input buffers for encoder. The input buffers are only | |
| 41 // used when copy is needed to match the required coded size. | |
| 42 static const size_t kExtraInputBufferCount = 2; | |
|
miu
2016/05/03 19:05:43
Note: They've just allowed the use of constexpr, a
xjz
2016/05/03 23:30:15
Done.
| |
| 43 | |
| 38 } // namespace | 44 } // namespace |
| 39 | 45 |
| 40 namespace media { | 46 namespace media { |
| 41 namespace cast { | 47 namespace cast { |
| 42 | 48 |
| 43 // Container for the associated data of a video frame being processed. | 49 // Container for the associated data of a video frame being processed. |
| 44 struct InProgressFrameEncode { | 50 struct InProgressFrameEncode { |
| 45 // The source content to encode. | 51 // The source content to encode. |
| 46 const scoped_refptr<VideoFrame> video_frame; | 52 const scoped_refptr<VideoFrame> video_frame; |
| 47 | 53 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 90 max_frame_rate_(max_frame_rate), | 96 max_frame_rate_(max_frame_rate), |
| 91 status_change_cb_(status_change_cb), | 97 status_change_cb_(status_change_cb), |
| 92 create_video_encode_memory_cb_(create_video_encode_memory_cb), | 98 create_video_encode_memory_cb_(create_video_encode_memory_cb), |
| 93 video_encode_accelerator_(std::move(vea)), | 99 video_encode_accelerator_(std::move(vea)), |
| 94 encoder_active_(false), | 100 encoder_active_(false), |
| 95 next_frame_id_(0u), | 101 next_frame_id_(0u), |
| 96 key_frame_encountered_(false), | 102 key_frame_encountered_(false), |
| 97 codec_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN), | 103 codec_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN), |
| 98 key_frame_quantizer_parsable_(false), | 104 key_frame_quantizer_parsable_(false), |
| 99 requested_bit_rate_(-1), | 105 requested_bit_rate_(-1), |
| 100 has_seen_zero_length_encoded_frame_(false) {} | 106 has_seen_zero_length_encoded_frame_(false), |
| 107 max_allowed_input_buffers_(0) {} | |
| 101 | 108 |
| 102 base::SingleThreadTaskRunner* task_runner() const { | 109 base::SingleThreadTaskRunner* task_runner() const { |
| 103 return task_runner_.get(); | 110 return task_runner_.get(); |
| 104 } | 111 } |
| 105 | 112 |
| 106 void Initialize(const gfx::Size& frame_size, | 113 void Initialize(const gfx::Size& frame_size, |
| 107 VideoCodecProfile codec_profile, | 114 VideoCodecProfile codec_profile, |
| 108 int start_bit_rate, | 115 int start_bit_rate, |
| 109 uint32_t first_frame_id) { | 116 uint32_t first_frame_id) { |
| 110 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 117 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 128 } | 135 } |
| 129 | 136 |
| 130 void SetBitRate(int bit_rate) { | 137 void SetBitRate(int bit_rate) { |
| 131 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 138 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 132 | 139 |
| 133 requested_bit_rate_ = bit_rate; | 140 requested_bit_rate_ = bit_rate; |
| 134 video_encode_accelerator_->RequestEncodingParametersChange(bit_rate, | 141 video_encode_accelerator_->RequestEncodingParametersChange(bit_rate, |
| 135 max_frame_rate_); | 142 max_frame_rate_); |
| 136 } | 143 } |
| 137 | 144 |
| 145 // The destruction call back of the copied video frame to free its use of | |
| 146 // the input buffer. | |
| 147 void ReturnInputBufferToPool(int index) { | |
| 148 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | |
| 149 DCHECK_GE(index, 0); | |
| 150 DCHECK_LT(index, static_cast<int>(input_buffers_.size())); | |
| 151 free_input_buffer_index_.push_back(index); | |
| 152 } | |
| 153 | |
| 138 void EncodeVideoFrame( | 154 void EncodeVideoFrame( |
| 139 const scoped_refptr<media::VideoFrame>& video_frame, | 155 const scoped_refptr<media::VideoFrame>& video_frame, |
| 140 const base::TimeTicks& reference_time, | 156 const base::TimeTicks& reference_time, |
| 141 bool key_frame_requested, | 157 bool key_frame_requested, |
| 142 const VideoEncoder::FrameEncodedCallback& frame_encoded_callback) { | 158 const VideoEncoder::FrameEncodedCallback& frame_encoded_callback) { |
| 143 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 159 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 144 | 160 |
| 145 if (!encoder_active_) | 161 if (!encoder_active_) |
| 146 return; | 162 return; |
| 147 | 163 |
| 148 in_progress_frame_encodes_.push_back(InProgressFrameEncode( | 164 in_progress_frame_encodes_.push_back(InProgressFrameEncode( |
| 149 video_frame, reference_time, frame_encoded_callback, | 165 video_frame, reference_time, frame_encoded_callback, |
| 150 requested_bit_rate_)); | 166 requested_bit_rate_)); |
| 151 | 167 |
| 168 scoped_refptr<media::VideoFrame> frame = video_frame; | |
| 169 if (video_frame->coded_size() != frame_coded_size_) { | |
| 170 DCHECK_GE(frame_coded_size_.width(), video_frame->visible_rect().width()); | |
| 171 DCHECK_GE(frame_coded_size_.height(), | |
| 172 video_frame->visible_rect().height()); | |
| 173 | |
| 174 if (free_input_buffer_index_.empty()) { | |
| 175 if (input_buffers_.size() < max_allowed_input_buffers_) { | |
|
miu
2016/05/03 19:05:43
It's unlikely, but possible, for this method to be
xjz
2016/05/03 23:30:15
Done. Changed to only allocate one buffer at one t
| |
| 176 create_video_encode_memory_cb_.Run( | |
| 177 media::VideoFrame::AllocationSize(media::PIXEL_FORMAT_I420, | |
| 178 frame_coded_size_), | |
| 179 base::Bind(&VEAClientImpl::OnCreateInputSharedMemory, this)); | |
| 180 } | |
| 181 ExitEncodingWithErrors(); | |
| 182 return; | |
| 183 } | |
| 184 | |
| 185 int index = free_input_buffer_index_.back(); | |
| 186 base::SharedMemory* input_buffer = input_buffers_[index].get(); | |
| 187 frame = VideoFrame::WrapExternalSharedMemory( | |
| 188 video_frame->format(), frame_coded_size_, video_frame->visible_rect(), | |
| 189 video_frame->visible_rect().size(), | |
| 190 static_cast<uint8_t*>(input_buffer->memory()), | |
| 191 input_buffer->mapped_size(), input_buffer->handle(), 0, | |
| 192 video_frame->timestamp()); | |
| 193 if (!frame || !media::I420CopyWithPadding(*video_frame, frame.get())) { | |
| 194 LOG(DFATAL) << "Error: ExternalVideoEncoder: copy failed."; | |
| 195 ExitEncodingWithErrors(); | |
| 196 return; | |
| 197 } | |
| 198 | |
| 199 frame->AddDestructionObserver(media::BindToCurrentLoop(base::Bind( | |
| 200 &ExternalVideoEncoder::VEAClientImpl::ReturnInputBufferToPool, this, | |
| 201 index))); | |
| 202 free_input_buffer_index_.pop_back(); | |
| 203 } | |
| 204 | |
| 152 // BitstreamBufferReady will be called once the encoder is done. | 205 // BitstreamBufferReady will be called once the encoder is done. |
| 153 video_encode_accelerator_->Encode(video_frame, key_frame_requested); | 206 video_encode_accelerator_->Encode(frame, key_frame_requested); |
| 154 } | 207 } |
| 155 | 208 |
| 156 protected: | 209 protected: |
| 157 void NotifyError(VideoEncodeAccelerator::Error error) final { | 210 void NotifyError(VideoEncodeAccelerator::Error error) final { |
| 158 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 211 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 159 | 212 |
| 160 DCHECK(error != VideoEncodeAccelerator::kInvalidArgumentError && | 213 DCHECK(error != VideoEncodeAccelerator::kInvalidArgumentError && |
| 161 error != VideoEncodeAccelerator::kIllegalStateError); | 214 error != VideoEncodeAccelerator::kIllegalStateError); |
| 162 | 215 |
| 163 encoder_active_ = false; | 216 encoder_active_ = false; |
| 164 | 217 |
| 165 cast_environment_->PostTask( | 218 cast_environment_->PostTask( |
| 166 CastEnvironment::MAIN, | 219 CastEnvironment::MAIN, |
| 167 FROM_HERE, | 220 FROM_HERE, |
| 168 base::Bind(status_change_cb_, STATUS_CODEC_RUNTIME_ERROR)); | 221 base::Bind(status_change_cb_, STATUS_CODEC_RUNTIME_ERROR)); |
| 169 | 222 |
| 170 // TODO(miu): Force-flush all |in_progress_frame_encodes_| immediately so | 223 // TODO(miu): Force-flush all |in_progress_frame_encodes_| immediately so |
| 171 // pending frames do not become stuck, freezing VideoSender. | 224 // pending frames do not become stuck, freezing VideoSender. |
| 172 } | 225 } |
| 173 | 226 |
| 174 // Called to allocate the input and output buffers. | 227 // Called to allocate the input and output buffers. |
| 175 void RequireBitstreamBuffers(unsigned int input_count, | 228 void RequireBitstreamBuffers(unsigned int input_count, |
| 176 const gfx::Size& input_coded_size, | 229 const gfx::Size& input_coded_size, |
| 177 size_t output_buffer_size) final { | 230 size_t output_buffer_size) final { |
| 178 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 231 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 179 | 232 |
| 180 // TODO(miu): Investigate why we are ignoring |input_count| (4) and instead | 233 frame_coded_size_ = input_coded_size; |
| 181 // using |kOutputBufferCount| (3) here. | 234 |
| 235 max_allowed_input_buffers_ = input_count + kExtraInputBufferCount; | |
| 236 | |
| 182 for (size_t j = 0; j < kOutputBufferCount; ++j) { | 237 for (size_t j = 0; j < kOutputBufferCount; ++j) { |
| 183 create_video_encode_memory_cb_.Run( | 238 create_video_encode_memory_cb_.Run( |
| 184 output_buffer_size, | 239 output_buffer_size, |
| 185 base::Bind(&VEAClientImpl::OnCreateSharedMemory, this)); | 240 base::Bind(&VEAClientImpl::OnCreateSharedMemory, this)); |
| 186 } | 241 } |
| 187 } | 242 } |
| 188 | 243 |
| 189 // Encoder has encoded a frame and it's available in one of the output | 244 // 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 | 245 // buffers. Package the result in a media::cast::EncodedFrame and post it |
| 191 // to the Cast MAIN thread via the supplied callback. | 246 // to the Cast MAIN thread via the supplied callback. |
| 192 void BitstreamBufferReady(int32_t bitstream_buffer_id, | 247 void BitstreamBufferReady(int32_t bitstream_buffer_id, |
| 193 size_t payload_size, | 248 size_t payload_size, |
| 194 bool key_frame) final { | 249 bool key_frame) final { |
| 195 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 250 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 196 if (bitstream_buffer_id < 0 || | 251 if (bitstream_buffer_id < 0 || |
| 197 bitstream_buffer_id >= static_cast<int32_t>(output_buffers_.size())) { | 252 bitstream_buffer_id >= static_cast<int32_t>(output_buffers_.size())) { |
| 198 NOTREACHED(); | 253 NOTREACHED(); |
| 199 VLOG(1) << "BitstreamBufferReady(): invalid bitstream_buffer_id=" | 254 VLOG(1) << "BitstreamBufferReady(): invalid bitstream_buffer_id=" |
| 200 << bitstream_buffer_id; | 255 << bitstream_buffer_id; |
| 201 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); | 256 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); |
| 202 return; | 257 return; |
| 203 } | 258 } |
| 204 base::SharedMemory* output_buffer = output_buffers_[bitstream_buffer_id]; | 259 base::SharedMemory* output_buffer = |
| 260 output_buffers_[bitstream_buffer_id].get(); | |
| 205 if (payload_size > output_buffer->mapped_size()) { | 261 if (payload_size > output_buffer->mapped_size()) { |
| 206 NOTREACHED(); | 262 NOTREACHED(); |
| 207 VLOG(1) << "BitstreamBufferReady(): invalid payload_size = " | 263 VLOG(1) << "BitstreamBufferReady(): invalid payload_size = " |
| 208 << payload_size; | 264 << payload_size; |
| 209 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); | 265 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); |
| 210 return; | 266 return; |
| 211 } | 267 } |
| 212 if (key_frame) | 268 if (key_frame) |
| 213 key_frame_encountered_ = true; | 269 key_frame_encountered_ = true; |
| 214 if (!key_frame_encountered_) { | 270 if (!key_frame_encountered_) { |
| 215 // Do not send video until we have encountered the first key frame. | 271 // Do not send video until we have encountered the first key frame. |
| 216 // Save the bitstream buffer in |stream_header_| to be sent later along | 272 // Save the bitstream buffer in |stream_header_| to be sent later along |
| 217 // with the first key frame. | 273 // with the first key frame. |
| 218 // | 274 // |
| 219 // TODO(miu): Should |stream_header_| be an std::ostringstream for | 275 // TODO(miu): Should |stream_header_| be an std::ostringstream for |
| 220 // performance reasons? | 276 // performance reasons? |
| 221 stream_header_.append(static_cast<const char*>(output_buffer->memory()), | 277 stream_header_.append(static_cast<const char*>(output_buffer->memory()), |
| 222 payload_size); | 278 payload_size); |
| 223 } else if (!in_progress_frame_encodes_.empty()) { | 279 } else if (!in_progress_frame_encodes_.empty()) { |
| 224 const InProgressFrameEncode& request = in_progress_frame_encodes_.front(); | 280 const InProgressFrameEncode& request = in_progress_frame_encodes_.front(); |
| 225 | 281 |
| 226 scoped_ptr<SenderEncodedFrame> encoded_frame(new SenderEncodedFrame()); | 282 std::unique_ptr<SenderEncodedFrame> encoded_frame( |
| 283 new SenderEncodedFrame()); | |
| 227 encoded_frame->dependency = key_frame ? EncodedFrame::KEY : | 284 encoded_frame->dependency = key_frame ? EncodedFrame::KEY : |
| 228 EncodedFrame::DEPENDENT; | 285 EncodedFrame::DEPENDENT; |
| 229 encoded_frame->frame_id = next_frame_id_++; | 286 encoded_frame->frame_id = next_frame_id_++; |
| 230 if (key_frame) | 287 if (key_frame) |
| 231 encoded_frame->referenced_frame_id = encoded_frame->frame_id; | 288 encoded_frame->referenced_frame_id = encoded_frame->frame_id; |
| 232 else | 289 else |
| 233 encoded_frame->referenced_frame_id = encoded_frame->frame_id - 1; | 290 encoded_frame->referenced_frame_id = encoded_frame->frame_id - 1; |
| 234 encoded_frame->rtp_timestamp = RtpTimeTicks::FromTimeDelta( | 291 encoded_frame->rtp_timestamp = RtpTimeTicks::FromTimeDelta( |
| 235 request.video_frame->timestamp(), kVideoFrequency); | 292 request.video_frame->timestamp(), kVideoFrequency); |
| 236 encoded_frame->reference_time = request.reference_time; | 293 encoded_frame->reference_time = request.reference_time; |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 354 ~VEAClientImpl() final { | 411 ~VEAClientImpl() final { |
| 355 // According to the media::VideoEncodeAccelerator interface, Destroy() | 412 // According to the media::VideoEncodeAccelerator interface, Destroy() |
| 356 // should be called instead of invoking its private destructor. | 413 // should be called instead of invoking its private destructor. |
| 357 task_runner_->PostTask( | 414 task_runner_->PostTask( |
| 358 FROM_HERE, | 415 FROM_HERE, |
| 359 base::Bind(&media::VideoEncodeAccelerator::Destroy, | 416 base::Bind(&media::VideoEncodeAccelerator::Destroy, |
| 360 base::Unretained(video_encode_accelerator_.release()))); | 417 base::Unretained(video_encode_accelerator_.release()))); |
| 361 } | 418 } |
| 362 | 419 |
| 363 // Note: This method can be called on any thread. | 420 // Note: This method can be called on any thread. |
| 364 void OnCreateSharedMemory(scoped_ptr<base::SharedMemory> memory) { | 421 void OnCreateSharedMemory(std::unique_ptr<base::SharedMemory> memory) { |
| 365 task_runner_->PostTask(FROM_HERE, | 422 task_runner_->PostTask(FROM_HERE, |
| 366 base::Bind(&VEAClientImpl::OnReceivedSharedMemory, | 423 base::Bind(&VEAClientImpl::OnReceivedSharedMemory, |
| 367 this, | 424 this, |
| 368 base::Passed(&memory))); | 425 base::Passed(&memory))); |
| 369 } | 426 } |
| 370 | 427 |
| 371 void OnReceivedSharedMemory(scoped_ptr<base::SharedMemory> memory) { | 428 void OnCreateInputSharedMemory(std::unique_ptr<base::SharedMemory> memory) { |
| 429 task_runner_->PostTask( | |
| 430 FROM_HERE, base::Bind(&VEAClientImpl::OnReceivedInputSharedMemory, this, | |
| 431 base::Passed(&memory))); | |
| 432 } | |
| 433 | |
| 434 void OnReceivedSharedMemory(std::unique_ptr<base::SharedMemory> memory) { | |
| 372 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 435 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 373 | 436 |
| 374 output_buffers_.push_back(std::move(memory)); | 437 output_buffers_.push_back(std::move(memory)); |
| 375 | 438 |
| 376 // Wait until all requested buffers are received. | 439 // Wait until all requested buffers are received. |
| 377 if (output_buffers_.size() < kOutputBufferCount) | 440 if (output_buffers_.size() < kOutputBufferCount) |
| 378 return; | 441 return; |
| 379 | 442 |
| 380 // Immediately provide all output buffers to the VEA. | 443 // Immediately provide all output buffers to the VEA. |
| 381 for (size_t i = 0; i < output_buffers_.size(); ++i) { | 444 for (size_t i = 0; i < output_buffers_.size(); ++i) { |
| 382 video_encode_accelerator_->UseOutputBitstreamBuffer( | 445 video_encode_accelerator_->UseOutputBitstreamBuffer( |
| 383 media::BitstreamBuffer(static_cast<int32_t>(i), | 446 media::BitstreamBuffer(static_cast<int32_t>(i), |
| 384 output_buffers_[i]->handle(), | 447 output_buffers_[i]->handle(), |
| 385 output_buffers_[i]->mapped_size())); | 448 output_buffers_[i]->mapped_size())); |
| 386 } | 449 } |
| 387 } | 450 } |
| 388 | 451 |
| 452 void OnReceivedInputSharedMemory(std::unique_ptr<base::SharedMemory> memory) { | |
| 453 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | |
| 454 | |
| 455 input_buffers_.push_back(std::move(memory)); | |
| 456 free_input_buffer_index_.push_back(input_buffers_.size() - 1); | |
| 457 } | |
| 458 | |
| 459 // This is called when copy errors occur in encoding process when there is | |
| 460 // need to copy the VideoFrames to match the required coded size for encoder. | |
| 461 void ExitEncodingWithErrors() { | |
| 462 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | |
| 463 | |
| 464 std::unique_ptr<SenderEncodedFrame> no_result(nullptr); | |
| 465 cast_environment_->PostTask( | |
| 466 CastEnvironment::MAIN, FROM_HERE, | |
| 467 base::Bind(in_progress_frame_encodes_.back().frame_encoded_callback, | |
| 468 base::Passed(&no_result))); | |
| 469 in_progress_frame_encodes_.pop_back(); | |
| 470 } | |
| 471 | |
| 389 // Parse H264 SPS, PPS, and Slice header, and return the averaged frame | 472 // Parse H264 SPS, PPS, and Slice header, and return the averaged frame |
| 390 // quantizer in the range of [0, 51], or -1 on parse error. | 473 // quantizer in the range of [0, 51], or -1 on parse error. |
| 391 double GetH264FrameQuantizer(const uint8_t* encoded_data, off_t size) { | 474 double GetH264FrameQuantizer(const uint8_t* encoded_data, off_t size) { |
| 392 DCHECK(encoded_data); | 475 DCHECK(encoded_data); |
| 393 if (!size) | 476 if (!size) |
| 394 return -1; | 477 return -1; |
| 395 h264_parser_.SetStream(encoded_data, size); | 478 h264_parser_.SetStream(encoded_data, size); |
| 396 double total_quantizer = 0; | 479 double total_quantizer = 0; |
| 397 int num_slices = 0; | 480 int num_slices = 0; |
| 398 | 481 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 443 } | 526 } |
| 444 } | 527 } |
| 445 return (num_slices == 0) ? -1 : (total_quantizer / num_slices); | 528 return (num_slices == 0) ? -1 : (total_quantizer / num_slices); |
| 446 } | 529 } |
| 447 | 530 |
| 448 const scoped_refptr<CastEnvironment> cast_environment_; | 531 const scoped_refptr<CastEnvironment> cast_environment_; |
| 449 const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; | 532 const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
| 450 const int max_frame_rate_; | 533 const int max_frame_rate_; |
| 451 const StatusChangeCallback status_change_cb_; // Must be run on MAIN thread. | 534 const StatusChangeCallback status_change_cb_; // Must be run on MAIN thread. |
| 452 const CreateVideoEncodeMemoryCallback create_video_encode_memory_cb_; | 535 const CreateVideoEncodeMemoryCallback create_video_encode_memory_cb_; |
| 453 scoped_ptr<media::VideoEncodeAccelerator> video_encode_accelerator_; | 536 std::unique_ptr<media::VideoEncodeAccelerator> video_encode_accelerator_; |
| 454 bool encoder_active_; | 537 bool encoder_active_; |
| 455 uint32_t next_frame_id_; | 538 uint32_t next_frame_id_; |
| 456 bool key_frame_encountered_; | 539 bool key_frame_encountered_; |
| 457 std::string stream_header_; | 540 std::string stream_header_; |
| 458 VideoCodecProfile codec_profile_; | 541 VideoCodecProfile codec_profile_; |
| 459 bool key_frame_quantizer_parsable_; | 542 bool key_frame_quantizer_parsable_; |
| 460 H264Parser h264_parser_; | 543 H264Parser h264_parser_; |
| 461 | 544 |
| 462 // Shared memory buffers for output with the VideoAccelerator. | 545 // Shared memory buffers for output with the VideoAccelerator. |
| 463 ScopedVector<base::SharedMemory> output_buffers_; | 546 std::vector<std::unique_ptr<base::SharedMemory>> output_buffers_; |
| 547 | |
| 548 // Shared memory buffers for input video frames with the VideoAccelerator. | |
| 549 // These buffers will be allocated only when copy is needed to match the | |
| 550 // required coded size for encoder. They are allocated on-demand, up to | |
| 551 // |max_allowed_input_buffers_|. | |
| 552 std::vector<std::unique_ptr<base::SharedMemory>> input_buffers_; | |
| 553 | |
| 554 // Available input buffer index. These buffers are used in FILO order. | |
| 555 std::vector<int> free_input_buffer_index_; | |
| 464 | 556 |
| 465 // FIFO list. | 557 // FIFO list. |
| 466 std::list<InProgressFrameEncode> in_progress_frame_encodes_; | 558 std::list<InProgressFrameEncode> in_progress_frame_encodes_; |
| 467 | 559 |
| 468 // The requested encode bit rate for the next frame. | 560 // The requested encode bit rate for the next frame. |
| 469 int requested_bit_rate_; | 561 int requested_bit_rate_; |
| 470 | 562 |
| 471 // Used to compute utilization metrics for each frame. | 563 // Used to compute utilization metrics for each frame. |
| 472 QuantizerEstimator quantizer_estimator_; | 564 QuantizerEstimator quantizer_estimator_; |
| 473 | 565 |
| 474 // Set to true once a frame with zero-length encoded data has been | 566 // Set to true once a frame with zero-length encoded data has been |
| 475 // encountered. | 567 // encountered. |
| 476 // TODO(miu): Remove after discovering cause. http://crbug.com/519022 | 568 // TODO(miu): Remove after discovering cause. http://crbug.com/519022 |
| 477 bool has_seen_zero_length_encoded_frame_; | 569 bool has_seen_zero_length_encoded_frame_; |
| 478 | 570 |
| 571 // The coded size of the video frame required by Encoder. This size is | |
| 572 // obtained from VEA through |RequireBitstreamBuffers()|. | |
| 573 gfx::Size frame_coded_size_; | |
| 574 | |
| 575 // The maximum number of input buffers. These buffers are used to copy | |
| 576 // VideoFrames in order to match the required coded size for encoder. | |
| 577 uint32_t max_allowed_input_buffers_; | |
|
miu
2016/05/03 19:05:43
s/uint32_t/size_t/
xjz
2016/05/03 23:30:15
Done.
| |
| 578 | |
| 479 DISALLOW_COPY_AND_ASSIGN(VEAClientImpl); | 579 DISALLOW_COPY_AND_ASSIGN(VEAClientImpl); |
| 480 }; | 580 }; |
| 481 | 581 |
| 482 // static | 582 // static |
| 483 bool ExternalVideoEncoder::IsSupported(const VideoSenderConfig& video_config) { | 583 bool ExternalVideoEncoder::IsSupported(const VideoSenderConfig& video_config) { |
| 484 if (video_config.codec != CODEC_VIDEO_VP8 && | 584 if (video_config.codec != CODEC_VIDEO_VP8 && |
| 485 video_config.codec != CODEC_VIDEO_H264) | 585 video_config.codec != CODEC_VIDEO_H264) |
| 486 return false; | 586 return false; |
| 487 | 587 |
| 488 // TODO(miu): "Layering hooks" are needed to be able to query outside of | 588 // TODO(miu): "Layering hooks" are needed to be able to query outside of |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 620 const CreateVideoEncodeAcceleratorCallback& create_vea_cb, | 720 const CreateVideoEncodeAcceleratorCallback& create_vea_cb, |
| 621 const CreateVideoEncodeMemoryCallback& create_video_encode_memory_cb) | 721 const CreateVideoEncodeMemoryCallback& create_video_encode_memory_cb) |
| 622 : SizeAdaptableVideoEncoderBase(cast_environment, | 722 : SizeAdaptableVideoEncoderBase(cast_environment, |
| 623 video_config, | 723 video_config, |
| 624 status_change_cb), | 724 status_change_cb), |
| 625 create_vea_cb_(create_vea_cb), | 725 create_vea_cb_(create_vea_cb), |
| 626 create_video_encode_memory_cb_(create_video_encode_memory_cb) {} | 726 create_video_encode_memory_cb_(create_video_encode_memory_cb) {} |
| 627 | 727 |
| 628 SizeAdaptableExternalVideoEncoder::~SizeAdaptableExternalVideoEncoder() {} | 728 SizeAdaptableExternalVideoEncoder::~SizeAdaptableExternalVideoEncoder() {} |
| 629 | 729 |
| 630 scoped_ptr<VideoEncoder> SizeAdaptableExternalVideoEncoder::CreateEncoder() { | 730 std::unique_ptr<VideoEncoder> |
| 631 return scoped_ptr<VideoEncoder>(new ExternalVideoEncoder( | 731 SizeAdaptableExternalVideoEncoder::CreateEncoder() { |
| 632 cast_environment(), | 732 return std::unique_ptr<VideoEncoder>(new ExternalVideoEncoder( |
| 633 video_config(), | 733 cast_environment(), video_config(), frame_size(), last_frame_id() + 1, |
| 634 frame_size(), | 734 CreateEncoderStatusChangeCallback(), create_vea_cb_, |
| 635 last_frame_id() + 1, | |
| 636 CreateEncoderStatusChangeCallback(), | |
| 637 create_vea_cb_, | |
| 638 create_video_encode_memory_cb_)); | 735 create_video_encode_memory_cb_)); |
| 639 } | 736 } |
| 640 | 737 |
| 641 QuantizerEstimator::QuantizerEstimator() {} | 738 QuantizerEstimator::QuantizerEstimator() {} |
| 642 | 739 |
| 643 QuantizerEstimator::~QuantizerEstimator() {} | 740 QuantizerEstimator::~QuantizerEstimator() {} |
| 644 | 741 |
| 645 void QuantizerEstimator::Reset() { | 742 void QuantizerEstimator::Reset() { |
| 646 last_frame_pixel_buffer_.reset(); | 743 last_frame_pixel_buffer_.reset(); |
| 647 } | 744 } |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 787 const double kEntropyAtMaxQuantizer = 7.5; | 884 const double kEntropyAtMaxQuantizer = 7.5; |
| 788 const double slope = | 885 const double slope = |
| 789 (MAX_VP8_QUANTIZER - MIN_VP8_QUANTIZER) / kEntropyAtMaxQuantizer; | 886 (MAX_VP8_QUANTIZER - MIN_VP8_QUANTIZER) / kEntropyAtMaxQuantizer; |
| 790 const double quantizer = std::min<double>( | 887 const double quantizer = std::min<double>( |
| 791 MAX_VP8_QUANTIZER, MIN_VP8_QUANTIZER + slope * shannon_entropy); | 888 MAX_VP8_QUANTIZER, MIN_VP8_QUANTIZER + slope * shannon_entropy); |
| 792 return quantizer; | 889 return quantizer; |
| 793 } | 890 } |
| 794 | 891 |
| 795 } // namespace cast | 892 } // namespace cast |
| 796 } // namespace media | 893 } // namespace media |
| OLD | NEW |