Index: media/cast/video_sender/external_video_encoder.cc |
diff --git a/media/cast/video_sender/external_video_encoder.cc b/media/cast/video_sender/external_video_encoder.cc |
deleted file mode 100644 |
index 96ee51956fb597fe76e9e99ff5f010465db76ada..0000000000000000000000000000000000000000 |
--- a/media/cast/video_sender/external_video_encoder.cc |
+++ /dev/null |
@@ -1,434 +0,0 @@ |
-// Copyright 2014 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "media/cast/video_sender/external_video_encoder.h" |
- |
-#include "base/bind.h" |
-#include "base/logging.h" |
-#include "base/memory/scoped_vector.h" |
-#include "base/memory/shared_memory.h" |
-#include "base/message_loop/message_loop.h" |
-#include "media/base/video_frame.h" |
-#include "media/base/video_util.h" |
-#include "media/cast/cast_defines.h" |
-#include "media/cast/logging/logging_defines.h" |
-#include "media/cast/transport/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( |
- const scoped_refptr<media::cast::CastEnvironment>& cast_environment, |
- base::TimeTicks event_time, |
- media::cast::RtpTimestamp rtp_timestamp, |
- uint32 frame_id) { |
- cast_environment->Logging()->InsertFrameEvent( |
- event_time, media::cast::FRAME_ENCODED, media::cast::VIDEO_EVENT, |
- rtp_timestamp, frame_id); |
-} |
- |
-// Proxy this call to ExternalVideoEncoder on the cast main thread. |
-void ProxyCreateVideoEncodeAccelerator( |
- const scoped_refptr<media::cast::CastEnvironment>& cast_environment, |
- const base::WeakPtr<media::cast::ExternalVideoEncoder>& weak_ptr, |
- const media::cast::CreateVideoEncodeMemoryCallback& |
- create_video_encode_mem_cb, |
- scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner, |
- scoped_ptr<media::VideoEncodeAccelerator> vea) { |
- cast_environment->PostTask( |
- media::cast::CastEnvironment::MAIN, |
- FROM_HERE, |
- base::Bind( |
- &media::cast::ExternalVideoEncoder::OnCreateVideoEncodeAccelerator, |
- weak_ptr, |
- create_video_encode_mem_cb, |
- encoder_task_runner, |
- base::Passed(&vea))); |
-} |
-} // namespace |
- |
-namespace media { |
-namespace cast { |
- |
-// Container for the associated data of a video frame being processed. |
-struct EncodedFrameReturnData { |
- EncodedFrameReturnData(base::TimeTicks c_time, |
- VideoEncoder::FrameEncodedCallback callback) { |
- capture_time = c_time; |
- frame_encoded_callback = callback; |
- } |
- base::TimeTicks capture_time; |
- VideoEncoder::FrameEncodedCallback frame_encoded_callback; |
-}; |
- |
-// The ExternalVideoEncoder class can be deleted directly by cast, while |
-// LocalVideoEncodeAcceleratorClient stays around long enough to properly shut |
-// down the VideoEncodeAccelerator. |
-class LocalVideoEncodeAcceleratorClient |
- : public VideoEncodeAccelerator::Client, |
- public base::RefCountedThreadSafe<LocalVideoEncodeAcceleratorClient> { |
- public: |
- LocalVideoEncodeAcceleratorClient( |
- scoped_refptr<CastEnvironment> cast_environment, |
- scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner, |
- scoped_ptr<media::VideoEncodeAccelerator> vea, |
- const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb, |
- const base::WeakPtr<ExternalVideoEncoder>& weak_owner) |
- : cast_environment_(cast_environment), |
- encoder_task_runner_(encoder_task_runner), |
- video_encode_accelerator_(vea.Pass()), |
- create_video_encode_memory_cb_(create_video_encode_mem_cb), |
- weak_owner_(weak_owner), |
- last_encoded_frame_id_(kStartFrameId), |
- key_frame_encountered_(false) { |
- DCHECK(encoder_task_runner_); |
- } |
- |
- // Initialize the real HW encoder. |
- void Initialize(const VideoSenderConfig& video_config) { |
- DCHECK(encoder_task_runner_); |
- DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread()); |
- |
- VideoCodecProfile output_profile = media::VIDEO_CODEC_PROFILE_UNKNOWN; |
- switch (video_config.codec) { |
- case transport::CODEC_VIDEO_VP8: |
- output_profile = media::VP8PROFILE_MAIN; |
- break; |
- case transport::CODEC_VIDEO_H264: |
- output_profile = media::H264PROFILE_MAIN; |
- break; |
- case transport::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; |
- |
- if (!video_encode_accelerator_->Initialize( |
- media::VideoFrame::I420, |
- gfx::Size(video_config.width, video_config.height), |
- output_profile, |
- video_config.start_bitrate, |
- this)) { |
- NotifyError(VideoEncodeAccelerator::kInvalidArgumentError); |
- return; |
- } |
- |
- // Wait until shared memory is allocated to indicate that encoder is |
- // initialized. |
- } |
- |
- // Free the HW. |
- void Destroy() { |
- DCHECK(encoder_task_runner_); |
- DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread()); |
- |
- video_encode_accelerator_.reset(); |
- } |
- |
- void SetBitRate(uint32 bit_rate) { |
- DCHECK(encoder_task_runner_); |
- DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread()); |
- |
- video_encode_accelerator_->RequestEncodingParametersChange(bit_rate, |
- max_frame_rate_); |
- } |
- |
- void EncodeVideoFrame( |
- const scoped_refptr<media::VideoFrame>& video_frame, |
- const base::TimeTicks& capture_time, |
- bool key_frame_requested, |
- const VideoEncoder::FrameEncodedCallback& frame_encoded_callback) { |
- DCHECK(encoder_task_runner_); |
- DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread()); |
- |
- encoded_frame_data_storage_.push_back( |
- EncodedFrameReturnData(capture_time, frame_encoded_callback)); |
- |
- // BitstreamBufferReady will be called once the encoder is done. |
- video_encode_accelerator_->Encode(video_frame, key_frame_requested); |
- } |
- |
- protected: |
- virtual void NotifyError(VideoEncodeAccelerator::Error error) OVERRIDE { |
- DCHECK(encoder_task_runner_); |
- DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread()); |
- VLOG(1) << "ExternalVideoEncoder NotifyError: " << error; |
- |
- video_encode_accelerator_.reset(); |
- cast_environment_->PostTask( |
- CastEnvironment::MAIN, |
- FROM_HERE, |
- base::Bind(&ExternalVideoEncoder::EncoderError, weak_owner_)); |
- } |
- |
- // Called to allocate the input and output buffers. |
- virtual void RequireBitstreamBuffers(unsigned int input_count, |
- const gfx::Size& input_coded_size, |
- size_t output_buffer_size) OVERRIDE { |
- DCHECK(encoder_task_runner_); |
- DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread()); |
- DCHECK(video_encode_accelerator_); |
- |
- for (size_t j = 0; j < kOutputBufferCount; ++j) { |
- create_video_encode_memory_cb_.Run( |
- output_buffer_size, |
- base::Bind(&LocalVideoEncodeAcceleratorClient::OnCreateSharedMemory, |
- this)); |
- } |
- } |
- |
- // Encoder has encoded a frame and it's available in one of out output |
- // buffers. |
- virtual void BitstreamBufferReady(int32 bitstream_buffer_id, |
- size_t payload_size, |
- bool key_frame) OVERRIDE { |
- DCHECK(encoder_task_runner_); |
- DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread()); |
- if (bitstream_buffer_id < 0 || |
- bitstream_buffer_id >= static_cast<int32>(output_buffers_.size())) { |
- NOTREACHED(); |
- VLOG(1) << "BitstreamBufferReady(): invalid bitstream_buffer_id=" |
- << bitstream_buffer_id; |
- NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); |
- return; |
- } |
- base::SharedMemory* output_buffer = output_buffers_[bitstream_buffer_id]; |
- if (payload_size > output_buffer->mapped_size()) { |
- NOTREACHED(); |
- VLOG(1) << "BitstreamBufferReady(): invalid payload_size = " |
- << payload_size; |
- NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); |
- return; |
- } |
- if (key_frame) |
- key_frame_encountered_ = true; |
- if (!key_frame_encountered_) { |
- // 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. |
- stream_header_.append(static_cast<const char*>(output_buffer->memory()), |
- payload_size); |
- } else if (!encoded_frame_data_storage_.empty()) { |
- scoped_ptr<transport::EncodedFrame> encoded_frame( |
- new transport::EncodedFrame()); |
- encoded_frame->dependency = key_frame ? transport::EncodedFrame::KEY : |
- transport::EncodedFrame::DEPENDENT; |
- encoded_frame->frame_id = ++last_encoded_frame_id_; |
- if (key_frame) |
- encoded_frame->referenced_frame_id = encoded_frame->frame_id; |
- else |
- encoded_frame->referenced_frame_id = encoded_frame->frame_id - 1; |
- encoded_frame->reference_time = |
- encoded_frame_data_storage_.front().capture_time; |
- encoded_frame->rtp_timestamp = |
- GetVideoRtpTimestamp(encoded_frame->reference_time); |
- if (!stream_header_.empty()) { |
- encoded_frame->data = stream_header_; |
- stream_header_.clear(); |
- } |
- encoded_frame->data.append( |
- static_cast<const char*>(output_buffer->memory()), payload_size); |
- |
- cast_environment_->PostTask( |
- CastEnvironment::MAIN, |
- FROM_HERE, |
- base::Bind(&LogFrameEncodedEvent, |
- cast_environment_, |
- cast_environment_->Clock()->NowTicks(), |
- encoded_frame->rtp_timestamp, |
- encoded_frame->frame_id)); |
- |
- cast_environment_->PostTask( |
- CastEnvironment::MAIN, |
- FROM_HERE, |
- base::Bind(encoded_frame_data_storage_.front().frame_encoded_callback, |
- base::Passed(&encoded_frame))); |
- |
- encoded_frame_data_storage_.pop_front(); |
- } else { |
- VLOG(1) << "BitstreamBufferReady(): no encoded frame data available"; |
- } |
- |
- // We need to re-add the output buffer to the encoder after we are done |
- // with it. |
- video_encode_accelerator_->UseOutputBitstreamBuffer(media::BitstreamBuffer( |
- bitstream_buffer_id, |
- output_buffers_[bitstream_buffer_id]->handle(), |
- output_buffers_[bitstream_buffer_id]->mapped_size())); |
- } |
- |
- private: |
- // 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))); |
- } |
- |
- void ReceivedSharedMemory(scoped_ptr<base::SharedMemory> memory) { |
- DCHECK(encoder_task_runner_); |
- DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread()); |
- |
- output_buffers_.push_back(memory.release()); |
- |
- // Wait until all requested buffers are received. |
- if (output_buffers_.size() < kOutputBufferCount) |
- return; |
- |
- // Immediately provide all output buffers to the VEA. |
- for (size_t i = 0; i < output_buffers_.size(); ++i) { |
- video_encode_accelerator_->UseOutputBitstreamBuffer( |
- media::BitstreamBuffer(static_cast<int32>(i), |
- output_buffers_[i]->handle(), |
- output_buffers_[i]->mapped_size())); |
- } |
- |
- cast_environment_->PostTask( |
- CastEnvironment::MAIN, |
- FROM_HERE, |
- base::Bind(&ExternalVideoEncoder::EncoderInitialized, weak_owner_)); |
- } |
- |
- friend class base::RefCountedThreadSafe<LocalVideoEncodeAcceleratorClient>; |
- |
- virtual ~LocalVideoEncodeAcceleratorClient() {} |
- |
- const scoped_refptr<CastEnvironment> cast_environment_; |
- scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner_; |
- scoped_ptr<media::VideoEncodeAccelerator> video_encode_accelerator_; |
- const CreateVideoEncodeMemoryCallback create_video_encode_memory_cb_; |
- const base::WeakPtr<ExternalVideoEncoder> weak_owner_; |
- int max_frame_rate_; |
- uint32 last_encoded_frame_id_; |
- bool key_frame_encountered_; |
- std::string stream_header_; |
- |
- // Shared memory buffers for output with the VideoAccelerator. |
- ScopedVector<base::SharedMemory> output_buffers_; |
- |
- // FIFO list. |
- std::list<EncodedFrameReturnData> encoded_frame_data_storage_; |
- |
- DISALLOW_COPY_AND_ASSIGN(LocalVideoEncodeAcceleratorClient); |
-}; |
- |
-ExternalVideoEncoder::ExternalVideoEncoder( |
- scoped_refptr<CastEnvironment> cast_environment, |
- const VideoSenderConfig& video_config, |
- const CreateVideoEncodeAcceleratorCallback& create_vea_cb, |
- const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb) |
- : video_config_(video_config), |
- cast_environment_(cast_environment), |
- encoder_active_(false), |
- key_frame_requested_(false), |
- weak_factory_(this) { |
- DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
- |
- create_vea_cb.Run(base::Bind(&ProxyCreateVideoEncodeAccelerator, |
- cast_environment, |
- weak_factory_.GetWeakPtr(), |
- create_video_encode_mem_cb)); |
-} |
- |
-ExternalVideoEncoder::~ExternalVideoEncoder() { |
- encoder_task_runner_->PostTask( |
- FROM_HERE, |
- base::Bind(&LocalVideoEncodeAcceleratorClient::Destroy, |
- video_accelerator_client_)); |
-} |
- |
-void ExternalVideoEncoder::EncoderInitialized() { |
- DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
- encoder_active_ = true; |
-} |
- |
-void ExternalVideoEncoder::EncoderError() { |
- DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
- encoder_active_ = false; |
-} |
- |
-void ExternalVideoEncoder::OnCreateVideoEncodeAccelerator( |
- const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb, |
- scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner, |
- scoped_ptr<media::VideoEncodeAccelerator> vea) { |
- DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
- encoder_task_runner_ = encoder_task_runner; |
- |
- video_accelerator_client_ = |
- new LocalVideoEncodeAcceleratorClient(cast_environment_, |
- encoder_task_runner, |
- vea.Pass(), |
- create_video_encode_mem_cb, |
- weak_factory_.GetWeakPtr()); |
- 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& capture_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, |
- capture_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; |
- } |
- |
- encoder_task_runner_->PostTask( |
- FROM_HERE, |
- base::Bind(&LocalVideoEncodeAcceleratorClient::SetBitRate, |
- video_accelerator_client_, |
- new_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. |
-} |
- |
-} // namespace cast |
-} // namespace media |