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/h264_vt_encoder.h" | 5 #include "media/cast/sender/h264_vt_encoder.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/big_endian.h" | 10 #include "base/big_endian.h" |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 | 217 |
218 private: | 218 private: |
219 base::ScopedCFTypeRef<CVPixelBufferPoolRef> pool_; | 219 base::ScopedCFTypeRef<CVPixelBufferPoolRef> pool_; |
220 | 220 |
221 DISALLOW_COPY_AND_ASSIGN(VideoFrameFactoryCVPixelBufferPoolImpl); | 221 DISALLOW_COPY_AND_ASSIGN(VideoFrameFactoryCVPixelBufferPoolImpl); |
222 }; | 222 }; |
223 | 223 |
224 } // namespace | 224 } // namespace |
225 | 225 |
226 H264VideoToolboxEncoder::H264VideoToolboxEncoder( | 226 H264VideoToolboxEncoder::H264VideoToolboxEncoder( |
227 scoped_refptr<CastEnvironment> cast_environment, | 227 const scoped_refptr<CastEnvironment>& cast_environment, |
228 const VideoSenderConfig& video_config, | 228 const VideoSenderConfig& video_config, |
| 229 const gfx::Size& frame_size, |
229 const CastInitializationCallback& initialization_cb) | 230 const CastInitializationCallback& initialization_cb) |
230 : cast_environment_(cast_environment), | 231 : cast_environment_(cast_environment), |
| 232 |
231 videotoolbox_glue_(VideoToolboxGlue::Get()), | 233 videotoolbox_glue_(VideoToolboxGlue::Get()), |
232 frame_id_(kStartFrameId), | 234 frame_id_(kStartFrameId), |
233 encode_next_frame_as_keyframe_(false) { | 235 encode_next_frame_as_keyframe_(false) { |
234 DCHECK(!initialization_cb.is_null()); | 236 DCHECK(!frame_size.IsEmpty()); |
| 237 |
235 CastInitializationStatus initialization_status; | 238 CastInitializationStatus initialization_status; |
236 if (videotoolbox_glue_) { | 239 if (videotoolbox_glue_) { |
237 initialization_status = (Initialize(video_config)) | 240 initialization_status = (Initialize(video_config, frame_size)) |
238 ? STATUS_VIDEO_INITIALIZED | 241 ? STATUS_VIDEO_INITIALIZED |
239 : STATUS_INVALID_VIDEO_CONFIGURATION; | 242 : STATUS_INVALID_VIDEO_CONFIGURATION; |
240 } else { | 243 } else { |
241 LOG(ERROR) << " VideoToolbox is not available"; | 244 LOG(ERROR) << " VideoToolbox is not available"; |
242 initialization_status = STATUS_HW_VIDEO_ENCODER_NOT_SUPPORTED; | 245 initialization_status = STATUS_HW_VIDEO_ENCODER_NOT_SUPPORTED; |
243 } | 246 } |
244 cast_environment_->PostTask( | 247 if (!initialization_cb.is_null()) { |
245 CastEnvironment::MAIN, FROM_HERE, | 248 cast_environment_->PostTask( |
246 base::Bind(initialization_cb, initialization_status)); | 249 CastEnvironment::MAIN, |
| 250 FROM_HERE, |
| 251 base::Bind(initialization_cb, initialization_status)); |
| 252 } |
247 } | 253 } |
248 | 254 |
249 H264VideoToolboxEncoder::~H264VideoToolboxEncoder() { | 255 H264VideoToolboxEncoder::~H264VideoToolboxEncoder() { |
250 Teardown(); | 256 Teardown(); |
251 } | 257 } |
252 | 258 |
253 bool H264VideoToolboxEncoder::Initialize( | 259 bool H264VideoToolboxEncoder::Initialize( |
254 const VideoSenderConfig& video_config) { | 260 const VideoSenderConfig& video_config, |
| 261 const gfx::Size& frame_size) { |
255 DCHECK(thread_checker_.CalledOnValidThread()); | 262 DCHECK(thread_checker_.CalledOnValidThread()); |
256 DCHECK(!compression_session_); | 263 DCHECK(!compression_session_); |
257 | 264 |
258 // Note that the encoder object is given to the compression session as the | 265 // Note that the encoder object is given to the compression session as the |
259 // callback context using a raw pointer. The C API does not allow us to use | 266 // callback context using a raw pointer. The C API does not allow us to use |
260 // a smart pointer, nor is this encoder ref counted. However, this is still | 267 // a smart pointer, nor is this encoder ref counted. However, this is still |
261 // safe, because we 1) we own the compression session and 2) we tear it down | 268 // safe, because we 1) we own the compression session and 2) we tear it down |
262 // safely. When destructing the encoder, the compression session is flushed | 269 // safely. When destructing the encoder, the compression session is flushed |
263 // and invalidated. Internally, VideoToolbox will join all of its threads | 270 // and invalidated. Internally, VideoToolbox will join all of its threads |
264 // before returning to the client. Therefore, when control returns to us, we | 271 // before returning to the client. Therefore, when control returns to us, we |
(...skipping 14 matching lines...) Expand all Loading... |
279 const int formats[] = { | 286 const int formats[] = { |
280 kCVPixelFormatType_420YpCbCr8Planar, | 287 kCVPixelFormatType_420YpCbCr8Planar, |
281 CoreVideoGlue::kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange}; | 288 CoreVideoGlue::kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange}; |
282 base::ScopedCFTypeRef<CFArrayRef> formats_array = ArrayWithIntegers( | 289 base::ScopedCFTypeRef<CFArrayRef> formats_array = ArrayWithIntegers( |
283 std::vector<int>(formats, formats + arraysize(formats))); | 290 std::vector<int>(formats, formats + arraysize(formats))); |
284 base::ScopedCFTypeRef<CFDictionaryRef> buffer_attributes = | 291 base::ScopedCFTypeRef<CFDictionaryRef> buffer_attributes = |
285 DictionaryWithKeyValue(kCVPixelBufferPixelFormatTypeKey, formats_array); | 292 DictionaryWithKeyValue(kCVPixelBufferPixelFormatTypeKey, formats_array); |
286 | 293 |
287 VTCompressionSessionRef session; | 294 VTCompressionSessionRef session; |
288 OSStatus status = videotoolbox_glue_->VTCompressionSessionCreate( | 295 OSStatus status = videotoolbox_glue_->VTCompressionSessionCreate( |
289 kCFAllocatorDefault, video_config.width, video_config.height, | 296 kCFAllocatorDefault, frame_size.width(), frame_size.height(), |
290 CoreMediaGlue::kCMVideoCodecType_H264, encoder_spec, buffer_attributes, | 297 CoreMediaGlue::kCMVideoCodecType_H264, encoder_spec, buffer_attributes, |
291 nullptr /* compressedDataAllocator */, | 298 nullptr /* compressedDataAllocator */, |
292 &H264VideoToolboxEncoder::CompressionCallback, | 299 &H264VideoToolboxEncoder::CompressionCallback, |
293 reinterpret_cast<void*>(this), &session); | 300 reinterpret_cast<void*>(this), &session); |
294 if (status != noErr) { | 301 if (status != noErr) { |
295 DLOG(ERROR) << " VTCompressionSessionCreate failed: " << status; | 302 DLOG(ERROR) << " VTCompressionSessionCreate failed: " << status; |
296 return false; | 303 return false; |
297 } | 304 } |
298 compression_session_.reset(session); | 305 compression_session_.reset(session); |
299 | 306 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
347 videotoolbox_glue_->VTCompressionSessionInvalidate(compression_session_); | 354 videotoolbox_glue_->VTCompressionSessionInvalidate(compression_session_); |
348 compression_session_.reset(); | 355 compression_session_.reset(); |
349 } | 356 } |
350 } | 357 } |
351 | 358 |
352 bool H264VideoToolboxEncoder::EncodeVideoFrame( | 359 bool H264VideoToolboxEncoder::EncodeVideoFrame( |
353 const scoped_refptr<media::VideoFrame>& video_frame, | 360 const scoped_refptr<media::VideoFrame>& video_frame, |
354 const base::TimeTicks& reference_time, | 361 const base::TimeTicks& reference_time, |
355 const FrameEncodedCallback& frame_encoded_callback) { | 362 const FrameEncodedCallback& frame_encoded_callback) { |
356 DCHECK(thread_checker_.CalledOnValidThread()); | 363 DCHECK(thread_checker_.CalledOnValidThread()); |
357 DCHECK(!reference_time.is_null()); | 364 DCHECK(!video_frame->visible_rect().IsEmpty()); |
| 365 DCHECK(!frame_encoded_callback.is_null()); |
358 | 366 |
359 if (!compression_session_) { | 367 if (!compression_session_) { |
360 DLOG(ERROR) << " compression session is null"; | 368 DLOG(ERROR) << " compression session is null"; |
361 return false; | 369 return false; |
362 } | 370 } |
363 | 371 |
364 // Wrap the VideoFrame in a CVPixelBuffer. In all cases, no data will be | 372 // Wrap the VideoFrame in a CVPixelBuffer. In all cases, no data will be |
365 // copied. If the VideoFrame was created by this encoder's video frame | 373 // copied. If the VideoFrame was created by this encoder's video frame |
366 // factory, then the returned CVPixelBuffer will have been obtained from the | 374 // factory, then the returned CVPixelBuffer will have been obtained from the |
367 // compression session's pixel buffer pool. This will eliminate a copy of the | 375 // compression session's pixel buffer pool. This will eliminate a copy of the |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
505 CopySampleBufferToAnnexBBuffer(sbuf, &encoded_frame->data, keyframe); | 513 CopySampleBufferToAnnexBBuffer(sbuf, &encoded_frame->data, keyframe); |
506 | 514 |
507 encoder->cast_environment_->PostTask( | 515 encoder->cast_environment_->PostTask( |
508 CastEnvironment::MAIN, FROM_HERE, | 516 CastEnvironment::MAIN, FROM_HERE, |
509 base::Bind(request->frame_encoded_callback, | 517 base::Bind(request->frame_encoded_callback, |
510 base::Passed(&encoded_frame))); | 518 base::Passed(&encoded_frame))); |
511 } | 519 } |
512 | 520 |
513 } // namespace cast | 521 } // namespace cast |
514 } // namespace media | 522 } // namespace media |
OLD | NEW |