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 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 CMTimeMake(input_image.render_time_ms(), 1000); | 307 CMTimeMake(input_image.render_time_ms(), 1000); |
300 CFDictionaryRef frame_properties = nullptr; | 308 CFDictionaryRef frame_properties = nullptr; |
301 if (is_keyframe_required) { | 309 if (is_keyframe_required) { |
302 CFTypeRef keys[] = {kVTEncodeFrameOptionKey_ForceKeyFrame}; | 310 CFTypeRef keys[] = {kVTEncodeFrameOptionKey_ForceKeyFrame}; |
303 CFTypeRef values[] = {kCFBooleanTrue}; | 311 CFTypeRef values[] = {kCFBooleanTrue}; |
304 frame_properties = internal::CreateCFDictionary(keys, values, 1); | 312 frame_properties = internal::CreateCFDictionary(keys, values, 1); |
305 } | 313 } |
306 std::unique_ptr<internal::FrameEncodeParams> encode_params; | 314 std::unique_ptr<internal::FrameEncodeParams> encode_params; |
307 encode_params.reset(new internal::FrameEncodeParams( | 315 encode_params.reset(new internal::FrameEncodeParams( |
308 this, codec_specific_info, width_, height_, input_image.render_time_ms(), | 316 this, codec_specific_info, width_, height_, input_image.render_time_ms(), |
309 input_image.timestamp())); | 317 input_image.timestamp(), input_image.rotation())); |
310 | 318 |
311 // Update the bitrate if needed. | 319 // Update the bitrate if needed. |
312 SetBitrateBps(bitrate_adjuster_.GetAdjustedBitrateBps()); | 320 SetBitrateBps(bitrate_adjuster_.GetAdjustedBitrateBps()); |
313 | 321 |
314 OSStatus status = VTCompressionSessionEncodeFrame( | 322 OSStatus status = VTCompressionSessionEncodeFrame( |
315 compression_session_, pixel_buffer, presentation_time_stamp, | 323 compression_session_, pixel_buffer, presentation_time_stamp, |
316 kCMTimeInvalid, frame_properties, encode_params.release(), nullptr); | 324 kCMTimeInvalid, frame_properties, encode_params.release(), nullptr); |
317 if (frame_properties) { | 325 if (frame_properties) { |
318 CFRelease(frame_properties); | 326 CFRelease(frame_properties); |
319 } | 327 } |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
464 } | 472 } |
465 | 473 |
466 void H264VideoToolboxEncoder::OnEncodedFrame( | 474 void H264VideoToolboxEncoder::OnEncodedFrame( |
467 OSStatus status, | 475 OSStatus status, |
468 VTEncodeInfoFlags info_flags, | 476 VTEncodeInfoFlags info_flags, |
469 CMSampleBufferRef sample_buffer, | 477 CMSampleBufferRef sample_buffer, |
470 CodecSpecificInfo codec_specific_info, | 478 CodecSpecificInfo codec_specific_info, |
471 int32_t width, | 479 int32_t width, |
472 int32_t height, | 480 int32_t height, |
473 int64_t render_time_ms, | 481 int64_t render_time_ms, |
474 uint32_t timestamp) { | 482 uint32_t timestamp, |
| 483 VideoRotation rotation) { |
475 if (status != noErr) { | 484 if (status != noErr) { |
476 LOG(LS_ERROR) << "H264 encode failed."; | 485 LOG(LS_ERROR) << "H264 encode failed."; |
477 return; | 486 return; |
478 } | 487 } |
479 if (info_flags & kVTEncodeInfo_FrameDropped) { | 488 if (info_flags & kVTEncodeInfo_FrameDropped) { |
480 LOG(LS_INFO) << "H264 encode dropped frame."; | 489 LOG(LS_INFO) << "H264 encode dropped frame."; |
481 } | 490 } |
482 | 491 |
483 bool is_keyframe = false; | 492 bool is_keyframe = false; |
484 CFArrayRef attachments = | 493 CFArrayRef attachments = |
(...skipping 19 matching lines...) Expand all Loading... |
504 } | 513 } |
505 } | 514 } |
506 webrtc::EncodedImage frame(buffer->data(), buffer->size(), buffer->size()); | 515 webrtc::EncodedImage frame(buffer->data(), buffer->size(), buffer->size()); |
507 frame._encodedWidth = width; | 516 frame._encodedWidth = width; |
508 frame._encodedHeight = height; | 517 frame._encodedHeight = height; |
509 frame._completeFrame = true; | 518 frame._completeFrame = true; |
510 frame._frameType = | 519 frame._frameType = |
511 is_keyframe ? webrtc::kVideoFrameKey : webrtc::kVideoFrameDelta; | 520 is_keyframe ? webrtc::kVideoFrameKey : webrtc::kVideoFrameDelta; |
512 frame.capture_time_ms_ = render_time_ms; | 521 frame.capture_time_ms_ = render_time_ms; |
513 frame._timeStamp = timestamp; | 522 frame._timeStamp = timestamp; |
| 523 frame.rotation_ = rotation; |
514 | 524 |
515 int result = callback_->Encoded(frame, &codec_specific_info, header.get()); | 525 int result = callback_->Encoded(frame, &codec_specific_info, header.get()); |
516 if (result != 0) { | 526 if (result != 0) { |
517 LOG(LS_ERROR) << "Encode callback failed: " << result; | 527 LOG(LS_ERROR) << "Encode callback failed: " << result; |
518 return; | 528 return; |
519 } | 529 } |
520 bitrate_adjuster_.Update(frame._size); | 530 bitrate_adjuster_.Update(frame._size); |
521 } | 531 } |
522 | 532 |
523 } // namespace webrtc | 533 } // namespace webrtc |
524 | 534 |
525 #endif // defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED) | 535 #endif // defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED) |
OLD | NEW |