| Index: media/cast/sender/external_video_encoder.cc
|
| diff --git a/media/cast/sender/external_video_encoder.cc b/media/cast/sender/external_video_encoder.cc
|
| index 6dec102436ed50892f671ca1c5a33ca625e8603c..9cc2e8ccbdd40ea43b70b966f020398ee3f011b5 100644
|
| --- a/media/cast/sender/external_video_encoder.cc
|
| +++ b/media/cast/sender/external_video_encoder.cc
|
| @@ -17,13 +17,8 @@
|
| #include "media/cast/net/cast_transport_config.h"
|
| #include "media/video/video_encode_accelerator.h"
|
|
|
| -namespace media {
|
| -namespace cast {
|
| -class LocalVideoEncodeAcceleratorClient;
|
| -} // namespace cast
|
| -} // namespace media
|
| -
|
| namespace {
|
| +
|
| static const size_t kOutputBufferCount = 3;
|
|
|
| void LogFrameEncodedEvent(
|
| @@ -35,6 +30,7 @@ void LogFrameEncodedEvent(
|
| event_time, media::cast::FRAME_ENCODED, media::cast::VIDEO_EVENT,
|
| rtp_timestamp, frame_id);
|
| }
|
| +
|
| } // namespace
|
|
|
| namespace media {
|
| @@ -54,102 +50,63 @@ struct InProgressFrameEncode {
|
| frame_encoded_callback(callback) {}
|
| };
|
|
|
| -// The ExternalVideoEncoder class can be deleted directly by cast, while
|
| -// LocalVideoEncodeAcceleratorClient stays around long enough to properly shut
|
| -// down the VideoEncodeAccelerator.
|
| -class LocalVideoEncodeAcceleratorClient
|
| +// Owns a VideoEncoderAccelerator instance and provides the necessary adapters
|
| +// to encode media::VideoFrames and emit media::cast::EncodedFrames. All
|
| +// methods must be called on the thread associated with the given
|
| +// SingleThreadTaskRunner, except for the task_runner() accessor.
|
| +class ExternalVideoEncoder::VEAClientImpl
|
| : public VideoEncodeAccelerator::Client,
|
| - public base::RefCountedThreadSafe<LocalVideoEncodeAcceleratorClient> {
|
| + public base::RefCountedThreadSafe<VEAClientImpl> {
|
| public:
|
| - // Create an instance of this class and post a task to create
|
| - // video_encode_accelerator_. A ref to |this| will be kept, awaiting reply
|
| - // via ProxyCreateVideoEncodeAccelerator, which will provide us with the
|
| - // encoder task runner and vea instance. We cannot be destroyed until we
|
| - // receive the reply, otherwise the VEA object created may leak.
|
| - static scoped_refptr<LocalVideoEncodeAcceleratorClient> Create(
|
| - scoped_refptr<CastEnvironment> cast_environment,
|
| - const CreateVideoEncodeAcceleratorCallback& create_vea_cb,
|
| - const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb,
|
| - const base::WeakPtr<ExternalVideoEncoder>& weak_owner) {
|
| - scoped_refptr<LocalVideoEncodeAcceleratorClient> client(
|
| - new LocalVideoEncodeAcceleratorClient(
|
| - cast_environment, create_video_encode_mem_cb, weak_owner));
|
| -
|
| - // This will keep a ref to |client|, if weak_owner is destroyed before
|
| - // ProxyCreateVideoEncodeAccelerator is called, we will stay alive until
|
| - // we can properly destroy the VEA.
|
| - create_vea_cb.Run(base::Bind(
|
| - &LocalVideoEncodeAcceleratorClient::OnCreateVideoEncodeAcceleratorProxy,
|
| - client));
|
| -
|
| - return client;
|
| + VEAClientImpl(
|
| + const scoped_refptr<CastEnvironment>& cast_environment,
|
| + const scoped_refptr<base::SingleThreadTaskRunner>& encoder_task_runner,
|
| + scoped_ptr<media::VideoEncodeAccelerator> vea,
|
| + int max_frame_rate,
|
| + const CreateVideoEncodeMemoryCallback& create_video_encode_memory_cb)
|
| + : cast_environment_(cast_environment),
|
| + task_runner_(encoder_task_runner),
|
| + max_frame_rate_(max_frame_rate),
|
| + create_video_encode_memory_cb_(create_video_encode_memory_cb),
|
| + video_encode_accelerator_(vea.Pass()),
|
| + encoder_active_(false),
|
| + last_encoded_frame_id_(kStartFrameId),
|
| + key_frame_encountered_(false) {
|
| }
|
|
|
| - // Initialize the real HW encoder.
|
| - void Initialize(const VideoSenderConfig& video_config) {
|
| - DCHECK(encoder_task_runner_.get());
|
| - DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread());
|
| -
|
| - VideoCodecProfile output_profile = media::VIDEO_CODEC_PROFILE_UNKNOWN;
|
| - switch (video_config.codec) {
|
| - case CODEC_VIDEO_VP8:
|
| - output_profile = media::VP8PROFILE_ANY;
|
| - break;
|
| - case CODEC_VIDEO_H264:
|
| - output_profile = media::H264PROFILE_MAIN;
|
| - break;
|
| - case CODEC_VIDEO_FAKE:
|
| - NOTREACHED() << "Fake software video encoder cannot be external";
|
| - break;
|
| - default:
|
| - NOTREACHED() << "Video codec not specified or not supported";
|
| - break;
|
| - }
|
| - max_frame_rate_ = video_config.max_frame_rate;
|
| + base::SingleThreadTaskRunner* task_runner() const {
|
| + return task_runner_.get();
|
| + }
|
| +
|
| + void Initialize(const gfx::Size& frame_size,
|
| + VideoCodecProfile codec_profile,
|
| + int start_bit_rate,
|
| + const CastInitializationCallback& initialization_cb) {
|
| + DCHECK(task_runner_->RunsTasksOnCurrentThread());
|
| + DCHECK(!frame_size.IsEmpty());
|
|
|
| - bool result = video_encode_accelerator_->Initialize(
|
| + encoder_active_ = video_encode_accelerator_->Initialize(
|
| media::VideoFrame::I420,
|
| - gfx::Size(video_config.width, video_config.height),
|
| - output_profile,
|
| - video_config.start_bitrate,
|
| + frame_size,
|
| + codec_profile,
|
| + start_bit_rate,
|
| this);
|
|
|
| UMA_HISTOGRAM_BOOLEAN("Cast.Sender.VideoEncodeAcceleratorInitializeSuccess",
|
| - result);
|
| - if (!result) {
|
| + encoder_active_);
|
| +
|
| + if (!initialization_cb.is_null()) {
|
| cast_environment_->PostTask(
|
| CastEnvironment::MAIN,
|
| FROM_HERE,
|
| - base::Bind(&ExternalVideoEncoder::EncoderInitialized, weak_owner_,
|
| - false));
|
| - return;
|
| - }
|
| -
|
| - // Wait until shared memory is allocated to indicate that encoder is
|
| - // initialized.
|
| - }
|
| -
|
| - // Destroy the VEA on the correct thread.
|
| - void Destroy() {
|
| - DCHECK(encoder_task_runner_.get());
|
| - if (!video_encode_accelerator_)
|
| - return;
|
| -
|
| - if (encoder_task_runner_->RunsTasksOnCurrentThread()) {
|
| - video_encode_accelerator_.reset();
|
| - } else {
|
| - // We do this instead of just reposting to encoder_task_runner_, because
|
| - // we are called from the destructor.
|
| - encoder_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&DestroyVideoEncodeAcceleratorOnEncoderThread,
|
| - base::Passed(&video_encode_accelerator_)));
|
| + base::Bind(initialization_cb,
|
| + encoder_active_ ? STATUS_VIDEO_INITIALIZED :
|
| + STATUS_HW_VIDEO_ENCODER_NOT_SUPPORTED));
|
| }
|
| }
|
|
|
| - void SetBitRate(uint32 bit_rate) {
|
| - DCHECK(encoder_task_runner_.get());
|
| - DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread());
|
| + void SetBitRate(int bit_rate) {
|
| + DCHECK(task_runner_->RunsTasksOnCurrentThread());
|
|
|
| video_encode_accelerator_->RequestEncodingParametersChange(bit_rate,
|
| max_frame_rate_);
|
| @@ -160,8 +117,10 @@ class LocalVideoEncodeAcceleratorClient
|
| const base::TimeTicks& reference_time,
|
| bool key_frame_requested,
|
| const VideoEncoder::FrameEncodedCallback& frame_encoded_callback) {
|
| - DCHECK(encoder_task_runner_.get());
|
| - DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread());
|
| + DCHECK(task_runner_->RunsTasksOnCurrentThread());
|
| +
|
| + if (!encoder_active_)
|
| + return;
|
|
|
| in_progress_frame_encodes_.push_back(InProgressFrameEncode(
|
| TimeDeltaToRtpDelta(video_frame->timestamp(), kVideoFrequency),
|
| @@ -174,39 +133,38 @@ class LocalVideoEncodeAcceleratorClient
|
|
|
| protected:
|
| void NotifyError(VideoEncodeAccelerator::Error error) override {
|
| - DCHECK(encoder_task_runner_.get());
|
| - DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread());
|
| + DCHECK(task_runner_->RunsTasksOnCurrentThread());
|
| VLOG(1) << "ExternalVideoEncoder NotifyError: " << error;
|
|
|
| - cast_environment_->PostTask(
|
| - CastEnvironment::MAIN,
|
| - FROM_HERE,
|
| - base::Bind(&ExternalVideoEncoder::EncoderError, weak_owner_));
|
| + encoder_active_ = false;
|
| + // TODO(miu): Plumbing is required to bubble this up to the CastSession and
|
| + // beyond.
|
| + // TODO(miu): Force-flush all |in_progress_frame_encodes_| immediately so
|
| + // pending frames do not become stuck, freezing VideoSender.
|
| }
|
|
|
| // Called to allocate the input and output buffers.
|
| void RequireBitstreamBuffers(unsigned int input_count,
|
| const gfx::Size& input_coded_size,
|
| size_t output_buffer_size) override {
|
| - DCHECK(encoder_task_runner_.get());
|
| - DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread());
|
| - DCHECK(video_encode_accelerator_);
|
| + DCHECK(task_runner_->RunsTasksOnCurrentThread());
|
|
|
| + // TODO(miu): Investigate why we are ignoring |input_count| (4) and instead
|
| + // using |kOutputBufferCount| (3) here.
|
| for (size_t j = 0; j < kOutputBufferCount; ++j) {
|
| create_video_encode_memory_cb_.Run(
|
| output_buffer_size,
|
| - base::Bind(&LocalVideoEncodeAcceleratorClient::OnCreateSharedMemory,
|
| - this));
|
| + base::Bind(&VEAClientImpl::OnCreateSharedMemory, this));
|
| }
|
| }
|
|
|
| - // Encoder has encoded a frame and it's available in one of out output
|
| - // buffers.
|
| + // Encoder has encoded a frame and it's available in one of the output
|
| + // buffers. Package the result in a media::cast::EncodedFrame and post it
|
| + // to the Cast MAIN thread via the supplied callback.
|
| void BitstreamBufferReady(int32 bitstream_buffer_id,
|
| size_t payload_size,
|
| bool key_frame) override {
|
| - DCHECK(encoder_task_runner_.get());
|
| - DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread());
|
| + DCHECK(task_runner_->RunsTasksOnCurrentThread());
|
| if (bitstream_buffer_id < 0 ||
|
| bitstream_buffer_id >= static_cast<int32>(output_buffers_.size())) {
|
| NOTREACHED();
|
| @@ -229,6 +187,9 @@ class LocalVideoEncodeAcceleratorClient
|
| // Do not send video until we have encountered the first key frame.
|
| // Save the bitstream buffer in |stream_header_| to be sent later along
|
| // with the first key frame.
|
| + //
|
| + // TODO(miu): Should |stream_header_| be an std::ostringstream for
|
| + // performance reasons?
|
| stream_header_.append(static_cast<const char*>(output_buffer->memory()),
|
| payload_size);
|
| } else if (!in_progress_frame_encodes_.empty()) {
|
| @@ -280,58 +241,27 @@ class LocalVideoEncodeAcceleratorClient
|
| }
|
|
|
| private:
|
| - LocalVideoEncodeAcceleratorClient(
|
| - scoped_refptr<CastEnvironment> cast_environment,
|
| - const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb,
|
| - const base::WeakPtr<ExternalVideoEncoder>& weak_owner)
|
| - : cast_environment_(cast_environment),
|
| - create_video_encode_memory_cb_(create_video_encode_mem_cb),
|
| - weak_owner_(weak_owner),
|
| - last_encoded_frame_id_(kStartFrameId),
|
| - key_frame_encountered_(false) {}
|
| -
|
| - // Trampoline VEA creation callback to OnCreateVideoEncodeAccelerator()
|
| - // on encoder_task_runner. Normally we would just repost the same method to
|
| - // it, and would not need a separate proxy method, but we can't
|
| - // ThreadTaskRunnerHandle::Get() in unittests just yet.
|
| - void OnCreateVideoEncodeAcceleratorProxy(
|
| - scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner,
|
| - scoped_ptr<media::VideoEncodeAccelerator> vea) {
|
| - encoder_task_runner->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&media::cast::LocalVideoEncodeAcceleratorClient::
|
| - OnCreateVideoEncodeAccelerator,
|
| - this,
|
| - encoder_task_runner,
|
| - base::Passed(&vea)));
|
| - }
|
| + friend class base::RefCountedThreadSafe<VEAClientImpl>;
|
|
|
| - void OnCreateVideoEncodeAccelerator(
|
| - scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner,
|
| - scoped_ptr<media::VideoEncodeAccelerator> vea) {
|
| - encoder_task_runner_ = encoder_task_runner;
|
| - video_encode_accelerator_.reset(vea.release());
|
| -
|
| - cast_environment_->PostTask(
|
| - CastEnvironment::MAIN,
|
| + ~VEAClientImpl() override {
|
| + // According to the media::VideoEncodeAccelerator interface, Destroy()
|
| + // should be called instead of invoking its private destructor.
|
| + task_runner_->PostTask(
|
| FROM_HERE,
|
| - base::Bind(&ExternalVideoEncoder::OnCreateVideoEncodeAccelerator,
|
| - weak_owner_,
|
| - encoder_task_runner_));
|
| + base::Bind(&media::VideoEncodeAccelerator::Destroy,
|
| + base::Unretained(video_encode_accelerator_.release())));
|
| }
|
|
|
| // Note: This method can be called on any thread.
|
| void OnCreateSharedMemory(scoped_ptr<base::SharedMemory> memory) {
|
| - encoder_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&LocalVideoEncodeAcceleratorClient::ReceivedSharedMemory,
|
| - this,
|
| - base::Passed(&memory)));
|
| + task_runner_->PostTask(FROM_HERE,
|
| + base::Bind(&VEAClientImpl::OnReceivedSharedMemory,
|
| + this,
|
| + base::Passed(&memory)));
|
| }
|
|
|
| - void ReceivedSharedMemory(scoped_ptr<base::SharedMemory> memory) {
|
| - DCHECK(encoder_task_runner_.get());
|
| - DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread());
|
| + void OnReceivedSharedMemory(scoped_ptr<base::SharedMemory> memory) {
|
| + DCHECK(task_runner_->RunsTasksOnCurrentThread());
|
|
|
| output_buffers_.push_back(memory.release());
|
|
|
| @@ -346,32 +276,14 @@ class LocalVideoEncodeAcceleratorClient
|
| output_buffers_[i]->handle(),
|
| output_buffers_[i]->mapped_size()));
|
| }
|
| -
|
| - cast_environment_->PostTask(
|
| - CastEnvironment::MAIN,
|
| - FROM_HERE,
|
| - base::Bind(&ExternalVideoEncoder::EncoderInitialized, weak_owner_,
|
| - true));
|
| - }
|
| -
|
| - static void DestroyVideoEncodeAcceleratorOnEncoderThread(
|
| - scoped_ptr<media::VideoEncodeAccelerator> vea) {
|
| - // VEA::~VEA specialization takes care of calling Destroy() on the VEA impl.
|
| - }
|
| -
|
| - friend class base::RefCountedThreadSafe<LocalVideoEncodeAcceleratorClient>;
|
| -
|
| - ~LocalVideoEncodeAcceleratorClient() override {
|
| - Destroy();
|
| - DCHECK(!video_encode_accelerator_);
|
| }
|
|
|
| const scoped_refptr<CastEnvironment> cast_environment_;
|
| - scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner_;
|
| - scoped_ptr<media::VideoEncodeAccelerator> video_encode_accelerator_;
|
| + const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
|
| + const int max_frame_rate_;
|
| const CreateVideoEncodeMemoryCallback create_video_encode_memory_cb_;
|
| - const base::WeakPtr<ExternalVideoEncoder> weak_owner_;
|
| - int max_frame_rate_;
|
| + scoped_ptr<media::VideoEncodeAccelerator> video_encode_accelerator_;
|
| + bool encoder_active_;
|
| uint32 last_encoded_frame_id_;
|
| bool key_frame_encountered_;
|
| std::string stream_header_;
|
| @@ -382,109 +294,137 @@ class LocalVideoEncodeAcceleratorClient
|
| // FIFO list.
|
| std::list<InProgressFrameEncode> in_progress_frame_encodes_;
|
|
|
| - DISALLOW_COPY_AND_ASSIGN(LocalVideoEncodeAcceleratorClient);
|
| + DISALLOW_COPY_AND_ASSIGN(VEAClientImpl);
|
| };
|
|
|
| ExternalVideoEncoder::ExternalVideoEncoder(
|
| - scoped_refptr<CastEnvironment> cast_environment,
|
| + const scoped_refptr<CastEnvironment>& cast_environment,
|
| const VideoSenderConfig& video_config,
|
| + const gfx::Size& frame_size,
|
| const CastInitializationCallback& initialization_cb,
|
| const CreateVideoEncodeAcceleratorCallback& create_vea_cb,
|
| - const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb)
|
| - : video_config_(video_config),
|
| - cast_environment_(cast_environment),
|
| - encoder_active_(false),
|
| + const CreateVideoEncodeMemoryCallback& create_video_encode_memory_cb)
|
| + : cast_environment_(cast_environment),
|
| + create_video_encode_memory_cb_(create_video_encode_memory_cb),
|
| + bit_rate_(video_config.start_bitrate),
|
| key_frame_requested_(false),
|
| - initialization_cb_(initialization_cb),
|
| weak_factory_(this) {
|
| DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
|
| + DCHECK_GT(video_config.max_frame_rate, 0);
|
| + DCHECK(!frame_size.IsEmpty());
|
| + DCHECK(!create_vea_cb.is_null());
|
| + DCHECK(!create_video_encode_memory_cb_.is_null());
|
| + DCHECK_GT(bit_rate_, 0);
|
| +
|
| + VideoCodecProfile codec_profile;
|
| + switch (video_config.codec) {
|
| + case CODEC_VIDEO_VP8:
|
| + codec_profile = media::VP8PROFILE_ANY;
|
| + break;
|
| + case CODEC_VIDEO_H264:
|
| + codec_profile = media::H264PROFILE_MAIN;
|
| + break;
|
| + case CODEC_VIDEO_FAKE:
|
| + NOTREACHED() << "Fake software video encoder cannot be external";
|
| + // ...flow through to next case...
|
| + default:
|
| + cast_environment_->PostTask(
|
| + CastEnvironment::MAIN,
|
| + FROM_HERE,
|
| + base::Bind(initialization_cb, STATUS_HW_VIDEO_ENCODER_NOT_SUPPORTED));
|
| + return;
|
| + }
|
|
|
| - video_accelerator_client_ =
|
| - LocalVideoEncodeAcceleratorClient::Create(cast_environment_,
|
| - create_vea_cb,
|
| - create_video_encode_mem_cb,
|
| - weak_factory_.GetWeakPtr());
|
| - DCHECK(video_accelerator_client_.get());
|
| + create_vea_cb.Run(
|
| + base::Bind(&ExternalVideoEncoder::OnCreateVideoEncodeAccelerator,
|
| + weak_factory_.GetWeakPtr(),
|
| + frame_size,
|
| + codec_profile,
|
| + video_config.max_frame_rate,
|
| + initialization_cb));
|
| }
|
|
|
| ExternalVideoEncoder::~ExternalVideoEncoder() {
|
| }
|
|
|
| -void ExternalVideoEncoder::EncoderInitialized(bool success) {
|
| - DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
|
| - encoder_active_ = success;
|
| - DCHECK(!initialization_cb_.is_null());
|
| - initialization_cb_.Run(
|
| - success ?
|
| - STATUS_VIDEO_INITIALIZED : STATUS_HW_VIDEO_ENCODER_NOT_SUPPORTED);
|
| - initialization_cb_.Reset();
|
| -}
|
| -
|
| -void ExternalVideoEncoder::EncoderError() {
|
| - DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
|
| - encoder_active_ = false;
|
| -}
|
| -
|
| -void ExternalVideoEncoder::OnCreateVideoEncodeAccelerator(
|
| - scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner) {
|
| - DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
|
| - encoder_task_runner_ = encoder_task_runner;
|
| -
|
| - encoder_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&LocalVideoEncodeAcceleratorClient::Initialize,
|
| - video_accelerator_client_,
|
| - video_config_));
|
| -}
|
| -
|
| bool ExternalVideoEncoder::EncodeVideoFrame(
|
| const scoped_refptr<media::VideoFrame>& video_frame,
|
| const base::TimeTicks& reference_time,
|
| const FrameEncodedCallback& frame_encoded_callback) {
|
| DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
|
| -
|
| - if (!encoder_active_)
|
| - return false;
|
| -
|
| - encoder_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&LocalVideoEncodeAcceleratorClient::EncodeVideoFrame,
|
| - video_accelerator_client_,
|
| - video_frame,
|
| - reference_time,
|
| - key_frame_requested_,
|
| - frame_encoded_callback));
|
| -
|
| + DCHECK(!video_frame->visible_rect().IsEmpty());
|
| + DCHECK(!frame_encoded_callback.is_null());
|
| +
|
| + if (!client_)
|
| + return false; // Not ready.
|
| +
|
| + client_->task_runner()->PostTask(FROM_HERE,
|
| + base::Bind(&VEAClientImpl::EncodeVideoFrame,
|
| + client_,
|
| + video_frame,
|
| + reference_time,
|
| + key_frame_requested_,
|
| + frame_encoded_callback));
|
| key_frame_requested_ = false;
|
| return true;
|
| }
|
|
|
| -// Inform the encoder about the new target bit rate.
|
| void ExternalVideoEncoder::SetBitRate(int new_bit_rate) {
|
| - if (!encoder_active_) {
|
| - // If we receive SetBitRate() before VEA creation callback is invoked,
|
| - // cache the new bit rate in the encoder config and use the new settings
|
| - // to initialize VEA.
|
| - video_config_.start_bitrate = new_bit_rate;
|
| - return;
|
| - }
|
| + DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
|
| + DCHECK_GT(new_bit_rate, 0);
|
|
|
| - encoder_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&LocalVideoEncodeAcceleratorClient::SetBitRate,
|
| - video_accelerator_client_,
|
| - new_bit_rate));
|
| + bit_rate_ = new_bit_rate;
|
| + if (!client_)
|
| + return;
|
| + client_->task_runner()->PostTask(
|
| + FROM_HERE, base::Bind(&VEAClientImpl::SetBitRate, client_, bit_rate_));
|
| }
|
|
|
| -// Inform the encoder to encode the next frame as a key frame.
|
| void ExternalVideoEncoder::GenerateKeyFrame() {
|
| DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
|
| key_frame_requested_ = true;
|
| }
|
|
|
| -// Inform the encoder to only reference frames older or equal to frame_id;
|
| void ExternalVideoEncoder::LatestFrameIdToReference(uint32 /*frame_id*/) {
|
| - // Do nothing not supported.
|
| + // Do nothing. Not supported.
|
| +}
|
| +
|
| +void ExternalVideoEncoder::OnCreateVideoEncodeAccelerator(
|
| + const gfx::Size& frame_size,
|
| + VideoCodecProfile codec_profile,
|
| + int max_frame_rate,
|
| + const CastInitializationCallback& initialization_cb,
|
| + scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner,
|
| + scoped_ptr<media::VideoEncodeAccelerator> vea) {
|
| + DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
|
| +
|
| + // The callback will be invoked with null pointers in the case where the
|
| + // system does not support or lacks the resources to provide GPU-accelerated
|
| + // video encoding.
|
| + if (!encoder_task_runner || !vea) {
|
| + if (!initialization_cb.is_null()) {
|
| + cast_environment_->PostTask(
|
| + CastEnvironment::MAIN,
|
| + FROM_HERE,
|
| + base::Bind(initialization_cb, STATUS_INVALID_VIDEO_CONFIGURATION));
|
| + }
|
| + return;
|
| + }
|
| +
|
| + DCHECK(!client_);
|
| + client_ = new VEAClientImpl(cast_environment_,
|
| + encoder_task_runner,
|
| + vea.Pass(),
|
| + max_frame_rate,
|
| + create_video_encode_memory_cb_);
|
| + client_->task_runner()->PostTask(FROM_HERE,
|
| + base::Bind(&VEAClientImpl::Initialize,
|
| + client_,
|
| + frame_size,
|
| + codec_profile,
|
| + bit_rate_,
|
| + initialization_cb));
|
| }
|
| +
|
| } // namespace cast
|
| } // namespace media
|
|
|