| 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 "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/memory/scoped_vector.h" | 9 #include "base/memory/scoped_vector.h" |
| 10 #include "base/memory/shared_memory.h" | 10 #include "base/memory/shared_memory.h" |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 // SingleThreadTaskRunner, except for the task_runner() accessor. | 56 // SingleThreadTaskRunner, except for the task_runner() accessor. |
| 57 class ExternalVideoEncoder::VEAClientImpl | 57 class ExternalVideoEncoder::VEAClientImpl |
| 58 : public VideoEncodeAccelerator::Client, | 58 : public VideoEncodeAccelerator::Client, |
| 59 public base::RefCountedThreadSafe<VEAClientImpl> { | 59 public base::RefCountedThreadSafe<VEAClientImpl> { |
| 60 public: | 60 public: |
| 61 VEAClientImpl( | 61 VEAClientImpl( |
| 62 const scoped_refptr<CastEnvironment>& cast_environment, | 62 const scoped_refptr<CastEnvironment>& cast_environment, |
| 63 const scoped_refptr<base::SingleThreadTaskRunner>& encoder_task_runner, | 63 const scoped_refptr<base::SingleThreadTaskRunner>& encoder_task_runner, |
| 64 scoped_ptr<media::VideoEncodeAccelerator> vea, | 64 scoped_ptr<media::VideoEncodeAccelerator> vea, |
| 65 int max_frame_rate, | 65 int max_frame_rate, |
| 66 const StatusChangeCallback& status_change_cb, |
| 66 const CreateVideoEncodeMemoryCallback& create_video_encode_memory_cb) | 67 const CreateVideoEncodeMemoryCallback& create_video_encode_memory_cb) |
| 67 : cast_environment_(cast_environment), | 68 : cast_environment_(cast_environment), |
| 68 task_runner_(encoder_task_runner), | 69 task_runner_(encoder_task_runner), |
| 69 max_frame_rate_(max_frame_rate), | 70 max_frame_rate_(max_frame_rate), |
| 71 status_change_cb_(status_change_cb), |
| 70 create_video_encode_memory_cb_(create_video_encode_memory_cb), | 72 create_video_encode_memory_cb_(create_video_encode_memory_cb), |
| 71 video_encode_accelerator_(vea.Pass()), | 73 video_encode_accelerator_(vea.Pass()), |
| 72 encoder_active_(false), | 74 encoder_active_(false), |
| 73 last_encoded_frame_id_(kStartFrameId), | 75 last_encoded_frame_id_(kStartFrameId), |
| 74 key_frame_encountered_(false) { | 76 key_frame_encountered_(false) { |
| 75 } | 77 } |
| 76 | 78 |
| 77 base::SingleThreadTaskRunner* task_runner() const { | 79 base::SingleThreadTaskRunner* task_runner() const { |
| 78 return task_runner_.get(); | 80 return task_runner_.get(); |
| 79 } | 81 } |
| 80 | 82 |
| 81 void Initialize(const gfx::Size& frame_size, | 83 void Initialize(const gfx::Size& frame_size, |
| 82 VideoCodecProfile codec_profile, | 84 VideoCodecProfile codec_profile, |
| 83 int start_bit_rate, | 85 int start_bit_rate) { |
| 84 const CastInitializationCallback& initialization_cb) { | |
| 85 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 86 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 86 DCHECK(!frame_size.IsEmpty()); | 87 DCHECK(!frame_size.IsEmpty()); |
| 87 | 88 |
| 88 encoder_active_ = video_encode_accelerator_->Initialize( | 89 encoder_active_ = video_encode_accelerator_->Initialize( |
| 89 media::VideoFrame::I420, | 90 media::VideoFrame::I420, |
| 90 frame_size, | 91 frame_size, |
| 91 codec_profile, | 92 codec_profile, |
| 92 start_bit_rate, | 93 start_bit_rate, |
| 93 this); | 94 this); |
| 94 | 95 |
| 95 UMA_HISTOGRAM_BOOLEAN("Cast.Sender.VideoEncodeAcceleratorInitializeSuccess", | 96 UMA_HISTOGRAM_BOOLEAN("Cast.Sender.VideoEncodeAcceleratorInitializeSuccess", |
| 96 encoder_active_); | 97 encoder_active_); |
| 97 | 98 |
| 98 if (!initialization_cb.is_null()) { | 99 cast_environment_->PostTask( |
| 99 cast_environment_->PostTask( | 100 CastEnvironment::MAIN, |
| 100 CastEnvironment::MAIN, | 101 FROM_HERE, |
| 101 FROM_HERE, | 102 base::Bind(status_change_cb_, |
| 102 base::Bind(initialization_cb, | 103 encoder_active_ ? STATUS_INITIALIZED : |
| 103 encoder_active_ ? STATUS_VIDEO_INITIALIZED : | 104 STATUS_CODEC_INIT_FAILED)); |
| 104 STATUS_HW_VIDEO_ENCODER_NOT_SUPPORTED)); | |
| 105 } | |
| 106 } | 105 } |
| 107 | 106 |
| 108 void SetBitRate(int bit_rate) { | 107 void SetBitRate(int bit_rate) { |
| 109 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 108 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 110 | 109 |
| 111 video_encode_accelerator_->RequestEncodingParametersChange(bit_rate, | 110 video_encode_accelerator_->RequestEncodingParametersChange(bit_rate, |
| 112 max_frame_rate_); | 111 max_frame_rate_); |
| 113 } | 112 } |
| 114 | 113 |
| 115 void EncodeVideoFrame( | 114 void EncodeVideoFrame( |
| (...skipping 11 matching lines...) Expand all Loading... |
| 127 reference_time, | 126 reference_time, |
| 128 frame_encoded_callback)); | 127 frame_encoded_callback)); |
| 129 | 128 |
| 130 // BitstreamBufferReady will be called once the encoder is done. | 129 // BitstreamBufferReady will be called once the encoder is done. |
| 131 video_encode_accelerator_->Encode(video_frame, key_frame_requested); | 130 video_encode_accelerator_->Encode(video_frame, key_frame_requested); |
| 132 } | 131 } |
| 133 | 132 |
| 134 protected: | 133 protected: |
| 135 void NotifyError(VideoEncodeAccelerator::Error error) override { | 134 void NotifyError(VideoEncodeAccelerator::Error error) override { |
| 136 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 135 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 137 VLOG(1) << "ExternalVideoEncoder NotifyError: " << error; | 136 |
| 137 DCHECK(error != VideoEncodeAccelerator::kInvalidArgumentError && |
| 138 error != VideoEncodeAccelerator::kIllegalStateError); |
| 138 | 139 |
| 139 encoder_active_ = false; | 140 encoder_active_ = false; |
| 140 // TODO(miu): Plumbing is required to bubble this up to the CastSession and | 141 |
| 141 // beyond. | 142 cast_environment_->PostTask( |
| 143 CastEnvironment::MAIN, |
| 144 FROM_HERE, |
| 145 base::Bind(status_change_cb_, STATUS_CODEC_RUNTIME_ERROR)); |
| 146 |
| 142 // TODO(miu): Force-flush all |in_progress_frame_encodes_| immediately so | 147 // TODO(miu): Force-flush all |in_progress_frame_encodes_| immediately so |
| 143 // pending frames do not become stuck, freezing VideoSender. | 148 // pending frames do not become stuck, freezing VideoSender. |
| 144 } | 149 } |
| 145 | 150 |
| 146 // Called to allocate the input and output buffers. | 151 // Called to allocate the input and output buffers. |
| 147 void RequireBitstreamBuffers(unsigned int input_count, | 152 void RequireBitstreamBuffers(unsigned int input_count, |
| 148 const gfx::Size& input_coded_size, | 153 const gfx::Size& input_coded_size, |
| 149 size_t output_buffer_size) override { | 154 size_t output_buffer_size) override { |
| 150 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 155 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 151 | 156 |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 274 video_encode_accelerator_->UseOutputBitstreamBuffer( | 279 video_encode_accelerator_->UseOutputBitstreamBuffer( |
| 275 media::BitstreamBuffer(static_cast<int32>(i), | 280 media::BitstreamBuffer(static_cast<int32>(i), |
| 276 output_buffers_[i]->handle(), | 281 output_buffers_[i]->handle(), |
| 277 output_buffers_[i]->mapped_size())); | 282 output_buffers_[i]->mapped_size())); |
| 278 } | 283 } |
| 279 } | 284 } |
| 280 | 285 |
| 281 const scoped_refptr<CastEnvironment> cast_environment_; | 286 const scoped_refptr<CastEnvironment> cast_environment_; |
| 282 const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; | 287 const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
| 283 const int max_frame_rate_; | 288 const int max_frame_rate_; |
| 289 const StatusChangeCallback status_change_cb_; // Must be run on MAIN thread. |
| 284 const CreateVideoEncodeMemoryCallback create_video_encode_memory_cb_; | 290 const CreateVideoEncodeMemoryCallback create_video_encode_memory_cb_; |
| 285 scoped_ptr<media::VideoEncodeAccelerator> video_encode_accelerator_; | 291 scoped_ptr<media::VideoEncodeAccelerator> video_encode_accelerator_; |
| 286 bool encoder_active_; | 292 bool encoder_active_; |
| 287 uint32 last_encoded_frame_id_; | 293 uint32 last_encoded_frame_id_; |
| 288 bool key_frame_encountered_; | 294 bool key_frame_encountered_; |
| 289 std::string stream_header_; | 295 std::string stream_header_; |
| 290 | 296 |
| 291 // Shared memory buffers for output with the VideoAccelerator. | 297 // Shared memory buffers for output with the VideoAccelerator. |
| 292 ScopedVector<base::SharedMemory> output_buffers_; | 298 ScopedVector<base::SharedMemory> output_buffers_; |
| 293 | 299 |
| 294 // FIFO list. | 300 // FIFO list. |
| 295 std::list<InProgressFrameEncode> in_progress_frame_encodes_; | 301 std::list<InProgressFrameEncode> in_progress_frame_encodes_; |
| 296 | 302 |
| 297 DISALLOW_COPY_AND_ASSIGN(VEAClientImpl); | 303 DISALLOW_COPY_AND_ASSIGN(VEAClientImpl); |
| 298 }; | 304 }; |
| 299 | 305 |
| 300 ExternalVideoEncoder::ExternalVideoEncoder( | 306 ExternalVideoEncoder::ExternalVideoEncoder( |
| 301 const scoped_refptr<CastEnvironment>& cast_environment, | 307 const scoped_refptr<CastEnvironment>& cast_environment, |
| 302 const VideoSenderConfig& video_config, | 308 const VideoSenderConfig& video_config, |
| 303 const gfx::Size& frame_size, | 309 const gfx::Size& frame_size, |
| 304 const CastInitializationCallback& initialization_cb, | 310 const StatusChangeCallback& status_change_cb, |
| 305 const CreateVideoEncodeAcceleratorCallback& create_vea_cb, | 311 const CreateVideoEncodeAcceleratorCallback& create_vea_cb, |
| 306 const CreateVideoEncodeMemoryCallback& create_video_encode_memory_cb) | 312 const CreateVideoEncodeMemoryCallback& create_video_encode_memory_cb) |
| 307 : cast_environment_(cast_environment), | 313 : cast_environment_(cast_environment), |
| 308 create_video_encode_memory_cb_(create_video_encode_memory_cb), | 314 create_video_encode_memory_cb_(create_video_encode_memory_cb), |
| 309 bit_rate_(video_config.start_bitrate), | 315 bit_rate_(video_config.start_bitrate), |
| 310 key_frame_requested_(false), | 316 key_frame_requested_(false), |
| 311 weak_factory_(this) { | 317 weak_factory_(this) { |
| 312 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 318 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 313 DCHECK_GT(video_config.max_frame_rate, 0); | 319 DCHECK_GT(video_config.max_frame_rate, 0); |
| 314 DCHECK(!frame_size.IsEmpty()); | 320 DCHECK(!frame_size.IsEmpty()); |
| 321 DCHECK(!status_change_cb.is_null()); |
| 315 DCHECK(!create_vea_cb.is_null()); | 322 DCHECK(!create_vea_cb.is_null()); |
| 316 DCHECK(!create_video_encode_memory_cb_.is_null()); | 323 DCHECK(!create_video_encode_memory_cb_.is_null()); |
| 317 DCHECK_GT(bit_rate_, 0); | 324 DCHECK_GT(bit_rate_, 0); |
| 318 | 325 |
| 319 VideoCodecProfile codec_profile; | 326 VideoCodecProfile codec_profile; |
| 320 switch (video_config.codec) { | 327 switch (video_config.codec) { |
| 321 case CODEC_VIDEO_VP8: | 328 case CODEC_VIDEO_VP8: |
| 322 codec_profile = media::VP8PROFILE_ANY; | 329 codec_profile = media::VP8PROFILE_ANY; |
| 323 break; | 330 break; |
| 324 case CODEC_VIDEO_H264: | 331 case CODEC_VIDEO_H264: |
| 325 codec_profile = media::H264PROFILE_MAIN; | 332 codec_profile = media::H264PROFILE_MAIN; |
| 326 break; | 333 break; |
| 327 case CODEC_VIDEO_FAKE: | 334 case CODEC_VIDEO_FAKE: |
| 328 NOTREACHED() << "Fake software video encoder cannot be external"; | 335 NOTREACHED() << "Fake software video encoder cannot be external"; |
| 329 // ...flow through to next case... | 336 // ...flow through to next case... |
| 330 default: | 337 default: |
| 331 cast_environment_->PostTask( | 338 cast_environment_->PostTask( |
| 332 CastEnvironment::MAIN, | 339 CastEnvironment::MAIN, |
| 333 FROM_HERE, | 340 FROM_HERE, |
| 334 base::Bind(initialization_cb, STATUS_HW_VIDEO_ENCODER_NOT_SUPPORTED)); | 341 base::Bind(status_change_cb, STATUS_UNSUPPORTED_CODEC)); |
| 335 return; | 342 return; |
| 336 } | 343 } |
| 337 | 344 |
| 338 create_vea_cb.Run( | 345 create_vea_cb.Run( |
| 339 base::Bind(&ExternalVideoEncoder::OnCreateVideoEncodeAccelerator, | 346 base::Bind(&ExternalVideoEncoder::OnCreateVideoEncodeAccelerator, |
| 340 weak_factory_.GetWeakPtr(), | 347 weak_factory_.GetWeakPtr(), |
| 341 frame_size, | 348 frame_size, |
| 342 codec_profile, | 349 codec_profile, |
| 343 video_config.max_frame_rate, | 350 video_config.max_frame_rate, |
| 344 initialization_cb)); | 351 status_change_cb)); |
| 345 } | 352 } |
| 346 | 353 |
| 347 ExternalVideoEncoder::~ExternalVideoEncoder() { | 354 ExternalVideoEncoder::~ExternalVideoEncoder() { |
| 348 } | 355 } |
| 349 | 356 |
| 350 bool ExternalVideoEncoder::CanEncodeVariedFrameSizes() const { | 357 bool ExternalVideoEncoder::CanEncodeVariedFrameSizes() const { |
| 351 return false; | 358 return false; |
| 352 } | 359 } |
| 353 | 360 |
| 354 bool ExternalVideoEncoder::EncodeVideoFrame( | 361 bool ExternalVideoEncoder::EncodeVideoFrame( |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 390 } | 397 } |
| 391 | 398 |
| 392 void ExternalVideoEncoder::LatestFrameIdToReference(uint32 /*frame_id*/) { | 399 void ExternalVideoEncoder::LatestFrameIdToReference(uint32 /*frame_id*/) { |
| 393 // Do nothing. Not supported. | 400 // Do nothing. Not supported. |
| 394 } | 401 } |
| 395 | 402 |
| 396 void ExternalVideoEncoder::OnCreateVideoEncodeAccelerator( | 403 void ExternalVideoEncoder::OnCreateVideoEncodeAccelerator( |
| 397 const gfx::Size& frame_size, | 404 const gfx::Size& frame_size, |
| 398 VideoCodecProfile codec_profile, | 405 VideoCodecProfile codec_profile, |
| 399 int max_frame_rate, | 406 int max_frame_rate, |
| 400 const CastInitializationCallback& initialization_cb, | 407 const StatusChangeCallback& status_change_cb, |
| 401 scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner, | 408 scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner, |
| 402 scoped_ptr<media::VideoEncodeAccelerator> vea) { | 409 scoped_ptr<media::VideoEncodeAccelerator> vea) { |
| 403 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 410 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 404 | 411 |
| 405 // The callback will be invoked with null pointers in the case where the | 412 // The callback will be invoked with null pointers in the case where the |
| 406 // system does not support or lacks the resources to provide GPU-accelerated | 413 // system does not support or lacks the resources to provide GPU-accelerated |
| 407 // video encoding. | 414 // video encoding. |
| 408 if (!encoder_task_runner || !vea) { | 415 if (!encoder_task_runner || !vea) { |
| 409 if (!initialization_cb.is_null()) { | 416 cast_environment_->PostTask( |
| 410 cast_environment_->PostTask( | 417 CastEnvironment::MAIN, |
| 411 CastEnvironment::MAIN, | 418 FROM_HERE, |
| 412 FROM_HERE, | 419 base::Bind(status_change_cb, STATUS_CODEC_INIT_FAILED)); |
| 413 base::Bind(initialization_cb, STATUS_INVALID_VIDEO_CONFIGURATION)); | |
| 414 } | |
| 415 return; | 420 return; |
| 416 } | 421 } |
| 417 | 422 |
| 418 DCHECK(!client_); | 423 DCHECK(!client_); |
| 419 client_ = new VEAClientImpl(cast_environment_, | 424 client_ = new VEAClientImpl(cast_environment_, |
| 420 encoder_task_runner, | 425 encoder_task_runner, |
| 421 vea.Pass(), | 426 vea.Pass(), |
| 422 max_frame_rate, | 427 max_frame_rate, |
| 428 status_change_cb, |
| 423 create_video_encode_memory_cb_); | 429 create_video_encode_memory_cb_); |
| 424 client_->task_runner()->PostTask(FROM_HERE, | 430 client_->task_runner()->PostTask(FROM_HERE, |
| 425 base::Bind(&VEAClientImpl::Initialize, | 431 base::Bind(&VEAClientImpl::Initialize, |
| 426 client_, | 432 client_, |
| 427 frame_size, | 433 frame_size, |
| 428 codec_profile, | 434 codec_profile, |
| 429 bit_rate_, | 435 bit_rate_)); |
| 430 initialization_cb)); | |
| 431 } | 436 } |
| 432 | 437 |
| 433 } // namespace cast | 438 } // namespace cast |
| 434 } // namespace media | 439 } // namespace media |
| OLD | NEW |