| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 * | 9 * |
| 10 */ | 10 */ |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 111 } | 111 } |
| 112 | 112 |
| 113 // Struct that we pass to the encoder per frame to encode. We receive it again | 113 // Struct that we pass to the encoder per frame to encode. We receive it again |
| 114 // in the encoder callback. | 114 // in the encoder callback. |
| 115 struct FrameEncodeParams { | 115 struct FrameEncodeParams { |
| 116 FrameEncodeParams(webrtc::H264VideoToolboxEncoder* e, | 116 FrameEncodeParams(webrtc::H264VideoToolboxEncoder* e, |
| 117 const webrtc::CodecSpecificInfo* csi, | 117 const webrtc::CodecSpecificInfo* csi, |
| 118 int32_t w, | 118 int32_t w, |
| 119 int32_t h, | 119 int32_t h, |
| 120 int64_t rtms, | 120 int64_t rtms, |
| 121 uint32_t ts) | 121 uint32_t ts, |
| 122 : encoder(e), width(w), height(h), render_time_ms(rtms), timestamp(ts) { | 122 webrtc::VideoRotation r) |
| 123 : encoder(e), |
| 124 width(w), |
| 125 height(h), |
| 126 render_time_ms(rtms), |
| 127 timestamp(ts), |
| 128 rotation(r) { |
| 123 if (csi) { | 129 if (csi) { |
| 124 codec_specific_info = *csi; | 130 codec_specific_info = *csi; |
| 125 } else { | 131 } else { |
| 126 codec_specific_info.codecType = webrtc::kVideoCodecH264; | 132 codec_specific_info.codecType = webrtc::kVideoCodecH264; |
| 127 } | 133 } |
| 128 } | 134 } |
| 129 | 135 |
| 130 webrtc::H264VideoToolboxEncoder* encoder; | 136 webrtc::H264VideoToolboxEncoder* encoder; |
| 131 webrtc::CodecSpecificInfo codec_specific_info; | 137 webrtc::CodecSpecificInfo codec_specific_info; |
| 132 int32_t width; | 138 int32_t width; |
| 133 int32_t height; | 139 int32_t height; |
| 134 int64_t render_time_ms; | 140 int64_t render_time_ms; |
| 135 uint32_t timestamp; | 141 uint32_t timestamp; |
| 142 webrtc::VideoRotation rotation; |
| 136 }; | 143 }; |
| 137 | 144 |
| 138 // We receive I420Frames as input, but we need to feed CVPixelBuffers into the | 145 // We receive I420Frames as input, but we need to feed CVPixelBuffers into the |
| 139 // encoder. This performs the copy and format conversion. | 146 // encoder. This performs the copy and format conversion. |
| 140 // TODO(tkchin): See if encoder will accept i420 frames and compare performance. | 147 // TODO(tkchin): See if encoder will accept i420 frames and compare performance. |
| 141 bool CopyVideoFrameToPixelBuffer(const webrtc::VideoFrame& frame, | 148 bool CopyVideoFrameToPixelBuffer(const webrtc::VideoFrame& frame, |
| 142 CVPixelBufferRef pixel_buffer) { | 149 CVPixelBufferRef pixel_buffer) { |
| 143 RTC_DCHECK(pixel_buffer); | 150 RTC_DCHECK(pixel_buffer); |
| 144 RTC_DCHECK(CVPixelBufferGetPixelFormatType(pixel_buffer) == | 151 RTC_DCHECK(CVPixelBufferGetPixelFormatType(pixel_buffer) == |
| 145 kCVPixelFormatType_420YpCbCr8BiPlanarFullRange); | 152 kCVPixelFormatType_420YpCbCr8BiPlanarFullRange); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 178 void VTCompressionOutputCallback(void* encoder, | 185 void VTCompressionOutputCallback(void* encoder, |
| 179 void* params, | 186 void* params, |
| 180 OSStatus status, | 187 OSStatus status, |
| 181 VTEncodeInfoFlags info_flags, | 188 VTEncodeInfoFlags info_flags, |
| 182 CMSampleBufferRef sample_buffer) { | 189 CMSampleBufferRef sample_buffer) { |
| 183 std::unique_ptr<FrameEncodeParams> encode_params( | 190 std::unique_ptr<FrameEncodeParams> encode_params( |
| 184 reinterpret_cast<FrameEncodeParams*>(params)); | 191 reinterpret_cast<FrameEncodeParams*>(params)); |
| 185 encode_params->encoder->OnEncodedFrame( | 192 encode_params->encoder->OnEncodedFrame( |
| 186 status, info_flags, sample_buffer, encode_params->codec_specific_info, | 193 status, info_flags, sample_buffer, encode_params->codec_specific_info, |
| 187 encode_params->width, encode_params->height, | 194 encode_params->width, encode_params->height, |
| 188 encode_params->render_time_ms, encode_params->timestamp); | 195 encode_params->render_time_ms, encode_params->timestamp, |
| 196 encode_params->rotation); |
| 189 } | 197 } |
| 190 | 198 |
| 191 } // namespace internal | 199 } // namespace internal |
| 192 | 200 |
| 193 namespace webrtc { | 201 namespace webrtc { |
| 194 | 202 |
| 195 // .5 is set as a mininum to prevent overcompensating for large temporary | 203 // .5 is set as a mininum to prevent overcompensating for large temporary |
| 196 // overshoots. We don't want to degrade video quality too badly. | 204 // overshoots. We don't want to degrade video quality too badly. |
| 197 // .95 is set to prevent oscillations. When a lower bitrate is set on the | 205 // .95 is set to prevent oscillations. When a lower bitrate is set on the |
| 198 // encoder than previously set, its output seems to have a brief period of | 206 // encoder than previously set, its output seems to have a brief period of |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 297 CMTimeMake(input_image.render_time_ms(), 1000); | 305 CMTimeMake(input_image.render_time_ms(), 1000); |
| 298 CFDictionaryRef frame_properties = nullptr; | 306 CFDictionaryRef frame_properties = nullptr; |
| 299 if (is_keyframe_required) { | 307 if (is_keyframe_required) { |
| 300 CFTypeRef keys[] = {kVTEncodeFrameOptionKey_ForceKeyFrame}; | 308 CFTypeRef keys[] = {kVTEncodeFrameOptionKey_ForceKeyFrame}; |
| 301 CFTypeRef values[] = {kCFBooleanTrue}; | 309 CFTypeRef values[] = {kCFBooleanTrue}; |
| 302 frame_properties = internal::CreateCFDictionary(keys, values, 1); | 310 frame_properties = internal::CreateCFDictionary(keys, values, 1); |
| 303 } | 311 } |
| 304 std::unique_ptr<internal::FrameEncodeParams> encode_params; | 312 std::unique_ptr<internal::FrameEncodeParams> encode_params; |
| 305 encode_params.reset(new internal::FrameEncodeParams( | 313 encode_params.reset(new internal::FrameEncodeParams( |
| 306 this, codec_specific_info, width_, height_, input_image.render_time_ms(), | 314 this, codec_specific_info, width_, height_, input_image.render_time_ms(), |
| 307 input_image.timestamp())); | 315 input_image.timestamp(), input_image.rotation())); |
| 308 | 316 |
| 309 // Update the bitrate if needed. | 317 // Update the bitrate if needed. |
| 310 SetBitrateBps(bitrate_adjuster_.GetAdjustedBitrateBps()); | 318 SetBitrateBps(bitrate_adjuster_.GetAdjustedBitrateBps()); |
| 311 | 319 |
| 312 OSStatus status = VTCompressionSessionEncodeFrame( | 320 OSStatus status = VTCompressionSessionEncodeFrame( |
| 313 compression_session_, pixel_buffer, presentation_time_stamp, | 321 compression_session_, pixel_buffer, presentation_time_stamp, |
| 314 kCMTimeInvalid, frame_properties, encode_params.release(), nullptr); | 322 kCMTimeInvalid, frame_properties, encode_params.release(), nullptr); |
| 315 if (frame_properties) { | 323 if (frame_properties) { |
| 316 CFRelease(frame_properties); | 324 CFRelease(frame_properties); |
| 317 } | 325 } |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 462 } | 470 } |
| 463 | 471 |
| 464 void H264VideoToolboxEncoder::OnEncodedFrame( | 472 void H264VideoToolboxEncoder::OnEncodedFrame( |
| 465 OSStatus status, | 473 OSStatus status, |
| 466 VTEncodeInfoFlags info_flags, | 474 VTEncodeInfoFlags info_flags, |
| 467 CMSampleBufferRef sample_buffer, | 475 CMSampleBufferRef sample_buffer, |
| 468 CodecSpecificInfo codec_specific_info, | 476 CodecSpecificInfo codec_specific_info, |
| 469 int32_t width, | 477 int32_t width, |
| 470 int32_t height, | 478 int32_t height, |
| 471 int64_t render_time_ms, | 479 int64_t render_time_ms, |
| 472 uint32_t timestamp) { | 480 uint32_t timestamp, |
| 481 VideoRotation rotation) { |
| 473 if (status != noErr) { | 482 if (status != noErr) { |
| 474 LOG(LS_ERROR) << "H264 encode failed."; | 483 LOG(LS_ERROR) << "H264 encode failed."; |
| 475 return; | 484 return; |
| 476 } | 485 } |
| 477 if (info_flags & kVTEncodeInfo_FrameDropped) { | 486 if (info_flags & kVTEncodeInfo_FrameDropped) { |
| 478 LOG(LS_INFO) << "H264 encode dropped frame."; | 487 LOG(LS_INFO) << "H264 encode dropped frame."; |
| 479 } | 488 } |
| 480 | 489 |
| 481 bool is_keyframe = false; | 490 bool is_keyframe = false; |
| 482 CFArrayRef attachments = | 491 CFArrayRef attachments = |
| (...skipping 19 matching lines...) Expand all Loading... |
| 502 } | 511 } |
| 503 } | 512 } |
| 504 webrtc::EncodedImage frame(buffer->data(), buffer->size(), buffer->size()); | 513 webrtc::EncodedImage frame(buffer->data(), buffer->size(), buffer->size()); |
| 505 frame._encodedWidth = width; | 514 frame._encodedWidth = width; |
| 506 frame._encodedHeight = height; | 515 frame._encodedHeight = height; |
| 507 frame._completeFrame = true; | 516 frame._completeFrame = true; |
| 508 frame._frameType = | 517 frame._frameType = |
| 509 is_keyframe ? webrtc::kVideoFrameKey : webrtc::kVideoFrameDelta; | 518 is_keyframe ? webrtc::kVideoFrameKey : webrtc::kVideoFrameDelta; |
| 510 frame.capture_time_ms_ = render_time_ms; | 519 frame.capture_time_ms_ = render_time_ms; |
| 511 frame._timeStamp = timestamp; | 520 frame._timeStamp = timestamp; |
| 521 frame.rotation_ = rotation; |
| 512 | 522 |
| 513 int result = callback_->Encoded(frame, &codec_specific_info, header.get()); | 523 int result = callback_->Encoded(frame, &codec_specific_info, header.get()); |
| 514 if (result != 0) { | 524 if (result != 0) { |
| 515 LOG(LS_ERROR) << "Encode callback failed: " << result; | 525 LOG(LS_ERROR) << "Encode callback failed: " << result; |
| 516 return; | 526 return; |
| 517 } | 527 } |
| 518 bitrate_adjuster_.Update(frame._size); | 528 bitrate_adjuster_.Update(frame._size); |
| 519 } | 529 } |
| 520 | 530 |
| 521 } // namespace webrtc | 531 } // namespace webrtc |
| 522 | 532 |
| 523 #endif // defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED) | 533 #endif // defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED) |
| OLD | NEW |