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

Side by Side Diff: media/cast/sender/external_video_encoder.cc

Issue 906403006: [Cast] Size-Adaptable platform video encoders. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed hubbe's comments. Created 5 years, 10 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
OLDNEW
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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 int max_frame_rate, 65 int max_frame_rate,
66 const StatusChangeCallback& status_change_cb, 66 const StatusChangeCallback& status_change_cb,
67 const CreateVideoEncodeMemoryCallback& create_video_encode_memory_cb) 67 const CreateVideoEncodeMemoryCallback& create_video_encode_memory_cb)
68 : cast_environment_(cast_environment), 68 : cast_environment_(cast_environment),
69 task_runner_(encoder_task_runner), 69 task_runner_(encoder_task_runner),
70 max_frame_rate_(max_frame_rate), 70 max_frame_rate_(max_frame_rate),
71 status_change_cb_(status_change_cb), 71 status_change_cb_(status_change_cb),
72 create_video_encode_memory_cb_(create_video_encode_memory_cb), 72 create_video_encode_memory_cb_(create_video_encode_memory_cb),
73 video_encode_accelerator_(vea.Pass()), 73 video_encode_accelerator_(vea.Pass()),
74 encoder_active_(false), 74 encoder_active_(false),
75 last_encoded_frame_id_(kStartFrameId), 75 next_frame_id_(0u),
76 key_frame_encountered_(false) { 76 key_frame_encountered_(false) {
77 } 77 }
78 78
79 base::SingleThreadTaskRunner* task_runner() const { 79 base::SingleThreadTaskRunner* task_runner() const {
80 return task_runner_.get(); 80 return task_runner_.get();
81 } 81 }
82 82
83 void Initialize(const gfx::Size& frame_size, 83 void Initialize(const gfx::Size& frame_size,
84 VideoCodecProfile codec_profile, 84 VideoCodecProfile codec_profile,
85 int start_bit_rate) { 85 int start_bit_rate,
86 uint32 first_frame_id) {
86 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 87 DCHECK(task_runner_->RunsTasksOnCurrentThread());
87 DCHECK(!frame_size.IsEmpty());
88 88
89 encoder_active_ = video_encode_accelerator_->Initialize( 89 encoder_active_ = video_encode_accelerator_->Initialize(
90 media::VideoFrame::I420, 90 media::VideoFrame::I420,
91 frame_size, 91 frame_size,
92 codec_profile, 92 codec_profile,
93 start_bit_rate, 93 start_bit_rate,
94 this); 94 this);
95 next_frame_id_ = first_frame_id;
95 96
96 UMA_HISTOGRAM_BOOLEAN("Cast.Sender.VideoEncodeAcceleratorInitializeSuccess", 97 UMA_HISTOGRAM_BOOLEAN("Cast.Sender.VideoEncodeAcceleratorInitializeSuccess",
97 encoder_active_); 98 encoder_active_);
98 99
99 cast_environment_->PostTask( 100 cast_environment_->PostTask(
100 CastEnvironment::MAIN, 101 CastEnvironment::MAIN,
101 FROM_HERE, 102 FROM_HERE,
102 base::Bind(status_change_cb_, 103 base::Bind(status_change_cb_,
103 encoder_active_ ? STATUS_INITIALIZED : 104 encoder_active_ ? STATUS_INITIALIZED :
104 STATUS_CODEC_INIT_FAILED)); 105 STATUS_CODEC_INIT_FAILED));
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 // TODO(miu): Should |stream_header_| be an std::ostringstream for 197 // TODO(miu): Should |stream_header_| be an std::ostringstream for
197 // performance reasons? 198 // performance reasons?
198 stream_header_.append(static_cast<const char*>(output_buffer->memory()), 199 stream_header_.append(static_cast<const char*>(output_buffer->memory()),
199 payload_size); 200 payload_size);
200 } else if (!in_progress_frame_encodes_.empty()) { 201 } else if (!in_progress_frame_encodes_.empty()) {
201 const InProgressFrameEncode& request = in_progress_frame_encodes_.front(); 202 const InProgressFrameEncode& request = in_progress_frame_encodes_.front();
202 203
203 scoped_ptr<EncodedFrame> encoded_frame(new EncodedFrame()); 204 scoped_ptr<EncodedFrame> encoded_frame(new EncodedFrame());
204 encoded_frame->dependency = key_frame ? EncodedFrame::KEY : 205 encoded_frame->dependency = key_frame ? EncodedFrame::KEY :
205 EncodedFrame::DEPENDENT; 206 EncodedFrame::DEPENDENT;
206 encoded_frame->frame_id = ++last_encoded_frame_id_; 207 encoded_frame->frame_id = next_frame_id_++;
207 if (key_frame) 208 if (key_frame)
208 encoded_frame->referenced_frame_id = encoded_frame->frame_id; 209 encoded_frame->referenced_frame_id = encoded_frame->frame_id;
209 else 210 else
210 encoded_frame->referenced_frame_id = encoded_frame->frame_id - 1; 211 encoded_frame->referenced_frame_id = encoded_frame->frame_id - 1;
211 encoded_frame->rtp_timestamp = request.rtp_timestamp; 212 encoded_frame->rtp_timestamp = request.rtp_timestamp;
212 encoded_frame->reference_time = request.reference_time; 213 encoded_frame->reference_time = request.reference_time;
213 if (!stream_header_.empty()) { 214 if (!stream_header_.empty()) {
214 encoded_frame->data = stream_header_; 215 encoded_frame->data = stream_header_;
215 stream_header_.clear(); 216 stream_header_.clear();
216 } 217 }
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 } 284 }
284 } 285 }
285 286
286 const scoped_refptr<CastEnvironment> cast_environment_; 287 const scoped_refptr<CastEnvironment> cast_environment_;
287 const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; 288 const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
288 const int max_frame_rate_; 289 const int max_frame_rate_;
289 const StatusChangeCallback status_change_cb_; // Must be run on MAIN thread. 290 const StatusChangeCallback status_change_cb_; // Must be run on MAIN thread.
290 const CreateVideoEncodeMemoryCallback create_video_encode_memory_cb_; 291 const CreateVideoEncodeMemoryCallback create_video_encode_memory_cb_;
291 scoped_ptr<media::VideoEncodeAccelerator> video_encode_accelerator_; 292 scoped_ptr<media::VideoEncodeAccelerator> video_encode_accelerator_;
292 bool encoder_active_; 293 bool encoder_active_;
293 uint32 last_encoded_frame_id_; 294 uint32 next_frame_id_;
294 bool key_frame_encountered_; 295 bool key_frame_encountered_;
295 std::string stream_header_; 296 std::string stream_header_;
296 297
297 // Shared memory buffers for output with the VideoAccelerator. 298 // Shared memory buffers for output with the VideoAccelerator.
298 ScopedVector<base::SharedMemory> output_buffers_; 299 ScopedVector<base::SharedMemory> output_buffers_;
299 300
300 // FIFO list. 301 // FIFO list.
301 std::list<InProgressFrameEncode> in_progress_frame_encodes_; 302 std::list<InProgressFrameEncode> in_progress_frame_encodes_;
302 303
303 DISALLOW_COPY_AND_ASSIGN(VEAClientImpl); 304 DISALLOW_COPY_AND_ASSIGN(VEAClientImpl);
304 }; 305 };
305 306
307 // static
308 bool ExternalVideoEncoder::IsSupported(const VideoSenderConfig& video_config) {
309 if (video_config.codec != CODEC_VIDEO_VP8 &&
310 video_config.codec != CODEC_VIDEO_H264)
311 return false;
312
313 // TODO(miu): "Layering hooks" are needed to be able to query outside of
314 // libmedia, to determine whether the system provides a hardware encoder. For
315 // now, assume that this was already checked by this point.
316 // http://crbug.com/454029
317 return video_config.use_external_encoder;
318 }
319
306 ExternalVideoEncoder::ExternalVideoEncoder( 320 ExternalVideoEncoder::ExternalVideoEncoder(
307 const scoped_refptr<CastEnvironment>& cast_environment, 321 const scoped_refptr<CastEnvironment>& cast_environment,
308 const VideoSenderConfig& video_config, 322 const VideoSenderConfig& video_config,
309 const gfx::Size& frame_size, 323 const gfx::Size& frame_size,
324 uint32 first_frame_id,
310 const StatusChangeCallback& status_change_cb, 325 const StatusChangeCallback& status_change_cb,
311 const CreateVideoEncodeAcceleratorCallback& create_vea_cb, 326 const CreateVideoEncodeAcceleratorCallback& create_vea_cb,
312 const CreateVideoEncodeMemoryCallback& create_video_encode_memory_cb) 327 const CreateVideoEncodeMemoryCallback& create_video_encode_memory_cb)
313 : cast_environment_(cast_environment), 328 : cast_environment_(cast_environment),
314 create_video_encode_memory_cb_(create_video_encode_memory_cb), 329 create_video_encode_memory_cb_(create_video_encode_memory_cb),
330 frame_size_(frame_size),
315 bit_rate_(video_config.start_bitrate), 331 bit_rate_(video_config.start_bitrate),
316 key_frame_requested_(false), 332 key_frame_requested_(false),
317 weak_factory_(this) { 333 weak_factory_(this) {
318 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 334 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
319 DCHECK_GT(video_config.max_frame_rate, 0); 335 DCHECK_GT(video_config.max_frame_rate, 0);
320 DCHECK(!frame_size.IsEmpty()); 336 DCHECK(!frame_size_.IsEmpty());
321 DCHECK(!status_change_cb.is_null()); 337 DCHECK(!status_change_cb.is_null());
322 DCHECK(!create_vea_cb.is_null()); 338 DCHECK(!create_vea_cb.is_null());
323 DCHECK(!create_video_encode_memory_cb_.is_null()); 339 DCHECK(!create_video_encode_memory_cb_.is_null());
324 DCHECK_GT(bit_rate_, 0); 340 DCHECK_GT(bit_rate_, 0);
325 341
326 VideoCodecProfile codec_profile;
327 switch (video_config.codec) {
328 case CODEC_VIDEO_VP8:
329 codec_profile = media::VP8PROFILE_ANY;
330 break;
331 case CODEC_VIDEO_H264:
332 codec_profile = media::H264PROFILE_MAIN;
333 break;
334 case CODEC_VIDEO_FAKE:
335 NOTREACHED() << "Fake software video encoder cannot be external";
336 // ...flow through to next case...
337 default:
338 cast_environment_->PostTask(
339 CastEnvironment::MAIN,
340 FROM_HERE,
341 base::Bind(status_change_cb, STATUS_UNSUPPORTED_CODEC));
342 return;
343 }
344
345 create_vea_cb.Run( 342 create_vea_cb.Run(
346 base::Bind(&ExternalVideoEncoder::OnCreateVideoEncodeAccelerator, 343 base::Bind(&ExternalVideoEncoder::OnCreateVideoEncodeAccelerator,
347 weak_factory_.GetWeakPtr(), 344 weak_factory_.GetWeakPtr(),
348 frame_size, 345 video_config,
349 codec_profile, 346 first_frame_id,
350 video_config.max_frame_rate,
351 status_change_cb)); 347 status_change_cb));
352 } 348 }
353 349
354 ExternalVideoEncoder::~ExternalVideoEncoder() { 350 ExternalVideoEncoder::~ExternalVideoEncoder() {
355 } 351 }
356 352
357 bool ExternalVideoEncoder::CanEncodeVariedFrameSizes() const {
358 return false;
359 }
360
361 bool ExternalVideoEncoder::EncodeVideoFrame( 353 bool ExternalVideoEncoder::EncodeVideoFrame(
362 const scoped_refptr<media::VideoFrame>& video_frame, 354 const scoped_refptr<media::VideoFrame>& video_frame,
363 const base::TimeTicks& reference_time, 355 const base::TimeTicks& reference_time,
364 const FrameEncodedCallback& frame_encoded_callback) { 356 const FrameEncodedCallback& frame_encoded_callback) {
365 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 357 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
366 DCHECK(!video_frame->visible_rect().IsEmpty());
367 DCHECK(!frame_encoded_callback.is_null()); 358 DCHECK(!frame_encoded_callback.is_null());
368 359
369 if (!client_) 360 if (!client_ || video_frame->visible_rect().size() != frame_size_)
370 return false; // Not ready. 361 return false;
371 362
372 client_->task_runner()->PostTask(FROM_HERE, 363 client_->task_runner()->PostTask(FROM_HERE,
373 base::Bind(&VEAClientImpl::EncodeVideoFrame, 364 base::Bind(&VEAClientImpl::EncodeVideoFrame,
374 client_, 365 client_,
375 video_frame, 366 video_frame,
376 reference_time, 367 reference_time,
377 key_frame_requested_, 368 key_frame_requested_,
378 frame_encoded_callback)); 369 frame_encoded_callback));
379 key_frame_requested_ = false; 370 key_frame_requested_ = false;
380 return true; 371 return true;
(...skipping 13 matching lines...) Expand all
394 void ExternalVideoEncoder::GenerateKeyFrame() { 385 void ExternalVideoEncoder::GenerateKeyFrame() {
395 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 386 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
396 key_frame_requested_ = true; 387 key_frame_requested_ = true;
397 } 388 }
398 389
399 void ExternalVideoEncoder::LatestFrameIdToReference(uint32 /*frame_id*/) { 390 void ExternalVideoEncoder::LatestFrameIdToReference(uint32 /*frame_id*/) {
400 // Do nothing. Not supported. 391 // Do nothing. Not supported.
401 } 392 }
402 393
403 void ExternalVideoEncoder::OnCreateVideoEncodeAccelerator( 394 void ExternalVideoEncoder::OnCreateVideoEncodeAccelerator(
404 const gfx::Size& frame_size, 395 const VideoSenderConfig& video_config,
405 VideoCodecProfile codec_profile, 396 uint32 first_frame_id,
406 int max_frame_rate,
407 const StatusChangeCallback& status_change_cb, 397 const StatusChangeCallback& status_change_cb,
408 scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner, 398 scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner,
409 scoped_ptr<media::VideoEncodeAccelerator> vea) { 399 scoped_ptr<media::VideoEncodeAccelerator> vea) {
410 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 400 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
411 401
412 // The callback will be invoked with null pointers in the case where the 402 // The callback will be invoked with null pointers in the case where the
413 // system does not support or lacks the resources to provide GPU-accelerated 403 // system does not support or lacks the resources to provide GPU-accelerated
414 // video encoding. 404 // video encoding.
415 if (!encoder_task_runner || !vea) { 405 if (!encoder_task_runner || !vea) {
416 cast_environment_->PostTask( 406 cast_environment_->PostTask(
417 CastEnvironment::MAIN, 407 CastEnvironment::MAIN,
418 FROM_HERE, 408 FROM_HERE,
419 base::Bind(status_change_cb, STATUS_CODEC_INIT_FAILED)); 409 base::Bind(status_change_cb, STATUS_CODEC_INIT_FAILED));
420 return; 410 return;
421 } 411 }
422 412
413 VideoCodecProfile codec_profile;
414 switch (video_config.codec) {
415 case CODEC_VIDEO_VP8:
416 codec_profile = media::VP8PROFILE_ANY;
417 break;
418 case CODEC_VIDEO_H264:
419 codec_profile = media::H264PROFILE_MAIN;
420 break;
421 case CODEC_VIDEO_FAKE:
422 NOTREACHED() << "Fake software video encoder cannot be external";
423 // ...flow through to next case...
424 default:
425 cast_environment_->PostTask(
426 CastEnvironment::MAIN,
427 FROM_HERE,
428 base::Bind(status_change_cb, STATUS_UNSUPPORTED_CODEC));
429 return;
430 }
431
423 DCHECK(!client_); 432 DCHECK(!client_);
424 client_ = new VEAClientImpl(cast_environment_, 433 client_ = new VEAClientImpl(cast_environment_,
425 encoder_task_runner, 434 encoder_task_runner,
426 vea.Pass(), 435 vea.Pass(),
427 max_frame_rate, 436 video_config.max_frame_rate,
428 status_change_cb, 437 status_change_cb,
429 create_video_encode_memory_cb_); 438 create_video_encode_memory_cb_);
430 client_->task_runner()->PostTask(FROM_HERE, 439 client_->task_runner()->PostTask(FROM_HERE,
431 base::Bind(&VEAClientImpl::Initialize, 440 base::Bind(&VEAClientImpl::Initialize,
432 client_, 441 client_,
433 frame_size, 442 frame_size_,
434 codec_profile, 443 codec_profile,
435 bit_rate_)); 444 bit_rate_,
445 first_frame_id));
446 }
447
448 SizeAdaptableExternalVideoEncoder::SizeAdaptableExternalVideoEncoder(
449 const scoped_refptr<CastEnvironment>& cast_environment,
450 const VideoSenderConfig& video_config,
451 const StatusChangeCallback& status_change_cb,
452 const CreateVideoEncodeAcceleratorCallback& create_vea_cb,
453 const CreateVideoEncodeMemoryCallback& create_video_encode_memory_cb)
454 : SizeAdaptableVideoEncoderBase(cast_environment,
455 video_config,
456 status_change_cb),
457 create_vea_cb_(create_vea_cb),
458 create_video_encode_memory_cb_(create_video_encode_memory_cb) {}
459
460 SizeAdaptableExternalVideoEncoder::~SizeAdaptableExternalVideoEncoder() {}
461
462 scoped_ptr<VideoEncoder> SizeAdaptableExternalVideoEncoder::CreateEncoder() {
463 return scoped_ptr<VideoEncoder>(new ExternalVideoEncoder(
464 cast_environment(),
465 video_config(),
466 frame_size(),
467 last_frame_id() + 1,
468 CreateEncoderStatusChangeCallback(),
469 create_vea_cb_,
470 create_video_encode_memory_cb_));
436 } 471 }
437 472
438 } // namespace cast 473 } // namespace cast
439 } // namespace media 474 } // namespace media
OLDNEW
« no previous file with comments | « media/cast/sender/external_video_encoder.h ('k') | media/cast/sender/external_video_encoder_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698