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 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
77 // we can properly destroy the VEA. | 77 // we can properly destroy the VEA. |
78 create_vea_cb.Run(base::Bind( | 78 create_vea_cb.Run(base::Bind( |
79 &LocalVideoEncodeAcceleratorClient::OnCreateVideoEncodeAcceleratorProxy, | 79 &LocalVideoEncodeAcceleratorClient::OnCreateVideoEncodeAcceleratorProxy, |
80 client)); | 80 client)); |
81 | 81 |
82 return client; | 82 return client; |
83 } | 83 } |
84 | 84 |
85 // Initialize the real HW encoder. | 85 // Initialize the real HW encoder. |
86 void Initialize(const VideoSenderConfig& video_config) { | 86 void Initialize(const VideoSenderConfig& video_config) { |
87 DCHECK(encoder_task_runner_); | 87 DCHECK(encoder_task_runner_.get()); |
88 DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread()); | 88 DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread()); |
89 | 89 |
90 VideoCodecProfile output_profile = media::VIDEO_CODEC_PROFILE_UNKNOWN; | 90 VideoCodecProfile output_profile = media::VIDEO_CODEC_PROFILE_UNKNOWN; |
91 switch (video_config.codec) { | 91 switch (video_config.codec) { |
92 case CODEC_VIDEO_VP8: | 92 case CODEC_VIDEO_VP8: |
93 output_profile = media::VP8PROFILE_ANY; | 93 output_profile = media::VP8PROFILE_ANY; |
94 break; | 94 break; |
95 case CODEC_VIDEO_H264: | 95 case CODEC_VIDEO_H264: |
96 output_profile = media::H264PROFILE_MAIN; | 96 output_profile = media::H264PROFILE_MAIN; |
97 break; | 97 break; |
(...skipping 19 matching lines...) Expand all Loading... |
117 NotifyError(VideoEncodeAccelerator::kInvalidArgumentError); | 117 NotifyError(VideoEncodeAccelerator::kInvalidArgumentError); |
118 return; | 118 return; |
119 } | 119 } |
120 | 120 |
121 // Wait until shared memory is allocated to indicate that encoder is | 121 // Wait until shared memory is allocated to indicate that encoder is |
122 // initialized. | 122 // initialized. |
123 } | 123 } |
124 | 124 |
125 // Destroy the VEA on the correct thread. | 125 // Destroy the VEA on the correct thread. |
126 void Destroy() { | 126 void Destroy() { |
127 DCHECK(encoder_task_runner_); | 127 DCHECK(encoder_task_runner_.get()); |
128 if (!video_encode_accelerator_) | 128 if (!video_encode_accelerator_) |
129 return; | 129 return; |
130 | 130 |
131 if (encoder_task_runner_->RunsTasksOnCurrentThread()) { | 131 if (encoder_task_runner_->RunsTasksOnCurrentThread()) { |
132 video_encode_accelerator_.reset(); | 132 video_encode_accelerator_.reset(); |
133 } else { | 133 } else { |
134 // We do this instead of just reposting to encoder_task_runner_, because | 134 // We do this instead of just reposting to encoder_task_runner_, because |
135 // we are called from the destructor. | 135 // we are called from the destructor. |
136 encoder_task_runner_->PostTask( | 136 encoder_task_runner_->PostTask( |
137 FROM_HERE, | 137 FROM_HERE, |
138 base::Bind(&DestroyVideoEncodeAcceleratorOnEncoderThread, | 138 base::Bind(&DestroyVideoEncodeAcceleratorOnEncoderThread, |
139 base::Passed(&video_encode_accelerator_))); | 139 base::Passed(&video_encode_accelerator_))); |
140 } | 140 } |
141 } | 141 } |
142 | 142 |
143 void SetBitRate(uint32 bit_rate) { | 143 void SetBitRate(uint32 bit_rate) { |
144 DCHECK(encoder_task_runner_); | 144 DCHECK(encoder_task_runner_.get()); |
145 DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread()); | 145 DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread()); |
146 | 146 |
147 video_encode_accelerator_->RequestEncodingParametersChange(bit_rate, | 147 video_encode_accelerator_->RequestEncodingParametersChange(bit_rate, |
148 max_frame_rate_); | 148 max_frame_rate_); |
149 } | 149 } |
150 | 150 |
151 void EncodeVideoFrame( | 151 void EncodeVideoFrame( |
152 const scoped_refptr<media::VideoFrame>& video_frame, | 152 const scoped_refptr<media::VideoFrame>& video_frame, |
153 const base::TimeTicks& capture_time, | 153 const base::TimeTicks& capture_time, |
154 bool key_frame_requested, | 154 bool key_frame_requested, |
155 const VideoEncoder::FrameEncodedCallback& frame_encoded_callback) { | 155 const VideoEncoder::FrameEncodedCallback& frame_encoded_callback) { |
156 DCHECK(encoder_task_runner_); | 156 DCHECK(encoder_task_runner_.get()); |
157 DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread()); | 157 DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread()); |
158 | 158 |
159 encoded_frame_data_storage_.push_back( | 159 encoded_frame_data_storage_.push_back( |
160 EncodedFrameReturnData(capture_time, frame_encoded_callback)); | 160 EncodedFrameReturnData(capture_time, frame_encoded_callback)); |
161 | 161 |
162 // BitstreamBufferReady will be called once the encoder is done. | 162 // BitstreamBufferReady will be called once the encoder is done. |
163 video_encode_accelerator_->Encode(video_frame, key_frame_requested); | 163 video_encode_accelerator_->Encode(video_frame, key_frame_requested); |
164 } | 164 } |
165 | 165 |
166 protected: | 166 protected: |
167 virtual void NotifyError(VideoEncodeAccelerator::Error error) OVERRIDE { | 167 virtual void NotifyError(VideoEncodeAccelerator::Error error) OVERRIDE { |
168 DCHECK(encoder_task_runner_); | 168 DCHECK(encoder_task_runner_.get()); |
169 DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread()); | 169 DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread()); |
170 VLOG(1) << "ExternalVideoEncoder NotifyError: " << error; | 170 VLOG(1) << "ExternalVideoEncoder NotifyError: " << error; |
171 | 171 |
172 cast_environment_->PostTask( | 172 cast_environment_->PostTask( |
173 CastEnvironment::MAIN, | 173 CastEnvironment::MAIN, |
174 FROM_HERE, | 174 FROM_HERE, |
175 base::Bind(&ExternalVideoEncoder::EncoderError, weak_owner_)); | 175 base::Bind(&ExternalVideoEncoder::EncoderError, weak_owner_)); |
176 } | 176 } |
177 | 177 |
178 // Called to allocate the input and output buffers. | 178 // Called to allocate the input and output buffers. |
179 virtual void RequireBitstreamBuffers(unsigned int input_count, | 179 virtual void RequireBitstreamBuffers(unsigned int input_count, |
180 const gfx::Size& input_coded_size, | 180 const gfx::Size& input_coded_size, |
181 size_t output_buffer_size) OVERRIDE { | 181 size_t output_buffer_size) OVERRIDE { |
182 DCHECK(encoder_task_runner_); | 182 DCHECK(encoder_task_runner_.get()); |
183 DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread()); | 183 DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread()); |
184 DCHECK(video_encode_accelerator_); | 184 DCHECK(video_encode_accelerator_); |
185 | 185 |
186 for (size_t j = 0; j < kOutputBufferCount; ++j) { | 186 for (size_t j = 0; j < kOutputBufferCount; ++j) { |
187 create_video_encode_memory_cb_.Run( | 187 create_video_encode_memory_cb_.Run( |
188 output_buffer_size, | 188 output_buffer_size, |
189 base::Bind(&LocalVideoEncodeAcceleratorClient::OnCreateSharedMemory, | 189 base::Bind(&LocalVideoEncodeAcceleratorClient::OnCreateSharedMemory, |
190 this)); | 190 this)); |
191 } | 191 } |
192 } | 192 } |
193 | 193 |
194 // Encoder has encoded a frame and it's available in one of out output | 194 // Encoder has encoded a frame and it's available in one of out output |
195 // buffers. | 195 // buffers. |
196 virtual void BitstreamBufferReady(int32 bitstream_buffer_id, | 196 virtual void BitstreamBufferReady(int32 bitstream_buffer_id, |
197 size_t payload_size, | 197 size_t payload_size, |
198 bool key_frame) OVERRIDE { | 198 bool key_frame) OVERRIDE { |
199 DCHECK(encoder_task_runner_); | 199 DCHECK(encoder_task_runner_.get()); |
200 DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread()); | 200 DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread()); |
201 if (bitstream_buffer_id < 0 || | 201 if (bitstream_buffer_id < 0 || |
202 bitstream_buffer_id >= static_cast<int32>(output_buffers_.size())) { | 202 bitstream_buffer_id >= static_cast<int32>(output_buffers_.size())) { |
203 NOTREACHED(); | 203 NOTREACHED(); |
204 VLOG(1) << "BitstreamBufferReady(): invalid bitstream_buffer_id=" | 204 VLOG(1) << "BitstreamBufferReady(): invalid bitstream_buffer_id=" |
205 << bitstream_buffer_id; | 205 << bitstream_buffer_id; |
206 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); | 206 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); |
207 return; | 207 return; |
208 } | 208 } |
209 base::SharedMemory* output_buffer = output_buffers_[bitstream_buffer_id]; | 209 base::SharedMemory* output_buffer = output_buffers_[bitstream_buffer_id]; |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
315 // Note: This method can be called on any thread. | 315 // Note: This method can be called on any thread. |
316 void OnCreateSharedMemory(scoped_ptr<base::SharedMemory> memory) { | 316 void OnCreateSharedMemory(scoped_ptr<base::SharedMemory> memory) { |
317 encoder_task_runner_->PostTask( | 317 encoder_task_runner_->PostTask( |
318 FROM_HERE, | 318 FROM_HERE, |
319 base::Bind(&LocalVideoEncodeAcceleratorClient::ReceivedSharedMemory, | 319 base::Bind(&LocalVideoEncodeAcceleratorClient::ReceivedSharedMemory, |
320 this, | 320 this, |
321 base::Passed(&memory))); | 321 base::Passed(&memory))); |
322 } | 322 } |
323 | 323 |
324 void ReceivedSharedMemory(scoped_ptr<base::SharedMemory> memory) { | 324 void ReceivedSharedMemory(scoped_ptr<base::SharedMemory> memory) { |
325 DCHECK(encoder_task_runner_); | 325 DCHECK(encoder_task_runner_.get()); |
326 DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread()); | 326 DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread()); |
327 | 327 |
328 output_buffers_.push_back(memory.release()); | 328 output_buffers_.push_back(memory.release()); |
329 | 329 |
330 // Wait until all requested buffers are received. | 330 // Wait until all requested buffers are received. |
331 if (output_buffers_.size() < kOutputBufferCount) | 331 if (output_buffers_.size() < kOutputBufferCount) |
332 return; | 332 return; |
333 | 333 |
334 // Immediately provide all output buffers to the VEA. | 334 // Immediately provide all output buffers to the VEA. |
335 for (size_t i = 0; i < output_buffers_.size(); ++i) { | 335 for (size_t i = 0; i < output_buffers_.size(); ++i) { |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
386 encoder_active_(false), | 386 encoder_active_(false), |
387 key_frame_requested_(false), | 387 key_frame_requested_(false), |
388 weak_factory_(this) { | 388 weak_factory_(this) { |
389 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 389 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
390 | 390 |
391 video_accelerator_client_ = | 391 video_accelerator_client_ = |
392 LocalVideoEncodeAcceleratorClient::Create(cast_environment_, | 392 LocalVideoEncodeAcceleratorClient::Create(cast_environment_, |
393 create_vea_cb, | 393 create_vea_cb, |
394 create_video_encode_mem_cb, | 394 create_video_encode_mem_cb, |
395 weak_factory_.GetWeakPtr()); | 395 weak_factory_.GetWeakPtr()); |
396 DCHECK(video_accelerator_client_); | 396 DCHECK(video_accelerator_client_.get()); |
397 } | 397 } |
398 | 398 |
399 ExternalVideoEncoder::~ExternalVideoEncoder() { | 399 ExternalVideoEncoder::~ExternalVideoEncoder() { |
400 } | 400 } |
401 | 401 |
402 void ExternalVideoEncoder::EncoderInitialized() { | 402 void ExternalVideoEncoder::EncoderInitialized() { |
403 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 403 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
404 encoder_active_ = true; | 404 encoder_active_ = true; |
405 } | 405 } |
406 | 406 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
465 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 465 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
466 key_frame_requested_ = true; | 466 key_frame_requested_ = true; |
467 } | 467 } |
468 | 468 |
469 // Inform the encoder to only reference frames older or equal to frame_id; | 469 // Inform the encoder to only reference frames older or equal to frame_id; |
470 void ExternalVideoEncoder::LatestFrameIdToReference(uint32 /*frame_id*/) { | 470 void ExternalVideoEncoder::LatestFrameIdToReference(uint32 /*frame_id*/) { |
471 // Do nothing not supported. | 471 // Do nothing not supported. |
472 } | 472 } |
473 } // namespace cast | 473 } // namespace cast |
474 } // namespace media | 474 } // namespace media |
OLD | NEW |