OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright 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 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 // Android's MediaCodec SDK API behind the scenes to implement (hopefully) | 89 // Android's MediaCodec SDK API behind the scenes to implement (hopefully) |
90 // HW-backed video encode. This C++ class is implemented as a very thin shim, | 90 // HW-backed video encode. This C++ class is implemented as a very thin shim, |
91 // delegating all of the interesting work to org.webrtc.MediaCodecVideoEncoder. | 91 // delegating all of the interesting work to org.webrtc.MediaCodecVideoEncoder. |
92 // MediaCodecVideoEncoder is created, operated, and destroyed on a single | 92 // MediaCodecVideoEncoder is created, operated, and destroyed on a single |
93 // thread, currently the libjingle Worker thread. | 93 // thread, currently the libjingle Worker thread. |
94 class MediaCodecVideoEncoder : public webrtc::VideoEncoder, | 94 class MediaCodecVideoEncoder : public webrtc::VideoEncoder, |
95 public rtc::MessageHandler { | 95 public rtc::MessageHandler { |
96 public: | 96 public: |
97 virtual ~MediaCodecVideoEncoder(); | 97 virtual ~MediaCodecVideoEncoder(); |
98 MediaCodecVideoEncoder(JNIEnv* jni, | 98 MediaCodecVideoEncoder(JNIEnv* jni, |
99 VideoCodecType codecType, | 99 const cricket::VideoCodec& codec, |
100 jobject egl_context); | 100 jobject egl_context); |
101 | 101 |
102 // webrtc::VideoEncoder implementation. Everything trampolines to | 102 // webrtc::VideoEncoder implementation. Everything trampolines to |
103 // |codec_thread_| for execution. | 103 // |codec_thread_| for execution. |
104 int32_t InitEncode(const webrtc::VideoCodec* codec_settings, | 104 int32_t InitEncode(const webrtc::VideoCodec* codec_settings, |
105 int32_t /* number_of_cores */, | 105 int32_t /* number_of_cores */, |
106 size_t /* max_payload_size */) override; | 106 size_t /* max_payload_size */) override; |
107 int32_t Encode(const webrtc::VideoFrame& input_image, | 107 int32_t Encode(const webrtc::VideoFrame& input_image, |
108 const webrtc::CodecSpecificInfo* /* codec_specific_info */, | 108 const webrtc::CodecSpecificInfo* /* codec_specific_info */, |
109 const std::vector<webrtc::FrameType>* frame_types) override; | 109 const std::vector<webrtc::FrameType>* frame_types) override; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 // true on success. | 178 // true on success. |
179 bool DeliverPendingOutputs(JNIEnv* jni); | 179 bool DeliverPendingOutputs(JNIEnv* jni); |
180 | 180 |
181 // Search for H.264 start codes. | 181 // Search for H.264 start codes. |
182 int32_t NextNaluPosition(uint8_t *buffer, size_t buffer_size); | 182 int32_t NextNaluPosition(uint8_t *buffer, size_t buffer_size); |
183 | 183 |
184 // Displays encoder statistics. | 184 // Displays encoder statistics. |
185 void LogStatistics(bool force_log); | 185 void LogStatistics(bool force_log); |
186 | 186 |
187 // Type of video codec. | 187 // Type of video codec. |
188 VideoCodecType codecType_; | 188 const cricket::VideoCodec codec_; |
189 | 189 |
190 // Valid all the time since RegisterEncodeCompleteCallback() Invoke()s to | 190 // Valid all the time since RegisterEncodeCompleteCallback() Invoke()s to |
191 // |codec_thread_| synchronously. | 191 // |codec_thread_| synchronously. |
192 webrtc::EncodedImageCallback* callback_; | 192 webrtc::EncodedImageCallback* callback_; |
193 | 193 |
194 // State that is constant for the lifetime of this object once the ctor | 194 // State that is constant for the lifetime of this object once the ctor |
195 // returns. | 195 // returns. |
196 std::unique_ptr<Thread> | 196 std::unique_ptr<Thread> |
197 codec_thread_; // Thread on which to operate MediaCodec. | 197 codec_thread_; // Thread on which to operate MediaCodec. |
198 rtc::ThreadChecker codec_thread_checker_; | 198 rtc::ThreadChecker codec_thread_checker_; |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
294 | 294 |
295 bool sw_fallback_required_; | 295 bool sw_fallback_required_; |
296 }; | 296 }; |
297 | 297 |
298 MediaCodecVideoEncoder::~MediaCodecVideoEncoder() { | 298 MediaCodecVideoEncoder::~MediaCodecVideoEncoder() { |
299 // Call Release() to ensure no more callbacks to us after we are deleted. | 299 // Call Release() to ensure no more callbacks to us after we are deleted. |
300 Release(); | 300 Release(); |
301 } | 301 } |
302 | 302 |
303 MediaCodecVideoEncoder::MediaCodecVideoEncoder(JNIEnv* jni, | 303 MediaCodecVideoEncoder::MediaCodecVideoEncoder(JNIEnv* jni, |
304 VideoCodecType codecType, | 304 const cricket::VideoCodec& codec, |
305 jobject egl_context) | 305 jobject egl_context) |
306 : codecType_(codecType), | 306 : codec_(codec), |
307 callback_(NULL), | 307 callback_(NULL), |
308 codec_thread_(new Thread()), | 308 codec_thread_(new Thread()), |
309 j_media_codec_video_encoder_class_( | 309 j_media_codec_video_encoder_class_( |
310 jni, | 310 jni, |
311 FindClass(jni, "org/webrtc/MediaCodecVideoEncoder")), | 311 FindClass(jni, "org/webrtc/MediaCodecVideoEncoder")), |
312 j_media_codec_video_encoder_( | 312 j_media_codec_video_encoder_( |
313 jni, | 313 jni, |
314 jni->NewObject(*j_media_codec_video_encoder_class_, | 314 jni->NewObject(*j_media_codec_video_encoder_class_, |
315 GetMethodID(jni, | 315 GetMethodID(jni, |
316 *j_media_codec_video_encoder_class_, | 316 *j_media_codec_video_encoder_class_, |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
384 | 384 |
385 int32_t MediaCodecVideoEncoder::InitEncode( | 385 int32_t MediaCodecVideoEncoder::InitEncode( |
386 const webrtc::VideoCodec* codec_settings, | 386 const webrtc::VideoCodec* codec_settings, |
387 int32_t /* number_of_cores */, | 387 int32_t /* number_of_cores */, |
388 size_t /* max_payload_size */) { | 388 size_t /* max_payload_size */) { |
389 if (codec_settings == NULL) { | 389 if (codec_settings == NULL) { |
390 ALOGE << "NULL VideoCodec instance"; | 390 ALOGE << "NULL VideoCodec instance"; |
391 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 391 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
392 } | 392 } |
393 // Factory should guard against other codecs being used with us. | 393 // Factory should guard against other codecs being used with us. |
394 RTC_CHECK(codec_settings->codecType == codecType_) | 394 const VideoCodecType codec_type = cricket::CodecTypeFromName(codec_.name); |
| 395 RTC_CHECK(codec_settings->codecType == codec_type) |
395 << "Unsupported codec " << codec_settings->codecType << " for " | 396 << "Unsupported codec " << codec_settings->codecType << " for " |
396 << codecType_; | 397 << codec_type; |
397 if (sw_fallback_required_) { | 398 if (sw_fallback_required_) { |
398 return WEBRTC_VIDEO_CODEC_OK; | 399 return WEBRTC_VIDEO_CODEC_OK; |
399 } | 400 } |
400 codec_mode_ = codec_settings->mode; | 401 codec_mode_ = codec_settings->mode; |
401 int init_width = codec_settings->width; | 402 int init_width = codec_settings->width; |
402 int init_height = codec_settings->height; | 403 int init_height = codec_settings->height; |
403 // Scaling is disabled for VP9, but optionally enabled for VP8. | 404 // Scaling is disabled for VP9, but optionally enabled for VP8. |
404 // TODO(pbos): Extract automaticResizeOn out of VP8 settings. | 405 // TODO(pbos): Extract automaticResizeOn out of VP8 settings. |
405 scale_ = false; | 406 scale_ = false; |
406 if (codecType_ == kVideoCodecVP8) { | 407 if (codec_type == kVideoCodecVP8) { |
407 scale_ = codec_settings->codecSpecific.VP8.automaticResizeOn; | 408 scale_ = codec_settings->codecSpecific.VP8.automaticResizeOn; |
408 } else if (codecType_ != kVideoCodecVP9) { | 409 } else if (codec_type != kVideoCodecVP9) { |
409 scale_ = true; | 410 scale_ = true; |
410 } | 411 } |
411 | 412 |
412 ALOGD << "InitEncode request: " << init_width << " x " << init_height; | 413 ALOGD << "InitEncode request: " << init_width << " x " << init_height; |
413 ALOGD << "Encoder automatic resize " << (scale_ ? "enabled" : "disabled"); | 414 ALOGD << "Encoder automatic resize " << (scale_ ? "enabled" : "disabled"); |
414 | 415 |
415 if (scale_) { | 416 if (scale_) { |
416 if (codecType_ == kVideoCodecVP8 || codecType_ == kVideoCodecH264) { | 417 if (codec_type == kVideoCodecVP8 || codec_type == kVideoCodecH264) { |
417 quality_scaler_.Init(codecType_, codec_settings->startBitrate, | 418 quality_scaler_.Init(codec_type, codec_settings->startBitrate, |
418 codec_settings->width, codec_settings->height, | 419 codec_settings->width, codec_settings->height, |
419 codec_settings->maxFramerate); | 420 codec_settings->maxFramerate); |
420 } else { | 421 } else { |
421 // When adding codec support to additional hardware codecs, also configure | 422 // When adding codec support to additional hardware codecs, also configure |
422 // their QP thresholds for scaling. | 423 // their QP thresholds for scaling. |
423 RTC_NOTREACHED() << "Unsupported codec without configured QP thresholds."; | 424 RTC_NOTREACHED() << "Unsupported codec without configured QP thresholds."; |
424 scale_ = false; | 425 scale_ = false; |
425 } | 426 } |
426 QualityScaler::Resolution res = quality_scaler_.GetScaledResolution(); | 427 QualityScaler::Resolution res = quality_scaler_.GetScaledResolution(); |
427 init_width = res.width; | 428 init_width = res.width; |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
513 WEBRTC_VIDEO_CODEC_OK) { | 514 WEBRTC_VIDEO_CODEC_OK) { |
514 ALOGE << "Initializing encoder failed during reset."; | 515 ALOGE << "Initializing encoder failed during reset."; |
515 return false; | 516 return false; |
516 } | 517 } |
517 return true; | 518 return true; |
518 } | 519 } |
519 | 520 |
520 bool MediaCodecVideoEncoder::ProcessHWErrorOnCodecThread( | 521 bool MediaCodecVideoEncoder::ProcessHWErrorOnCodecThread( |
521 bool reset_if_fallback_unavailable) { | 522 bool reset_if_fallback_unavailable) { |
522 ALOGE << "ProcessHWErrorOnCodecThread"; | 523 ALOGE << "ProcessHWErrorOnCodecThread"; |
523 if (VideoEncoder::IsSupportedSoftware( | 524 if (VideoEncoder::IsSupportedSoftware(codec_)) { |
524 VideoEncoder::CodecToEncoderType(codecType_))) { | |
525 ALOGE << "Fallback to SW encoder."; | 525 ALOGE << "Fallback to SW encoder."; |
526 sw_fallback_required_ = true; | 526 sw_fallback_required_ = true; |
527 return false; | 527 return false; |
528 } else if (reset_if_fallback_unavailable) { | 528 } else if (reset_if_fallback_unavailable) { |
529 ALOGE << "Reset encoder."; | 529 ALOGE << "Reset encoder."; |
530 return ResetCodecOnCodecThread(); | 530 return ResetCodecOnCodecThread(); |
531 } | 531 } |
532 return false; | 532 return false; |
533 } | 533 } |
534 | 534 |
535 int32_t MediaCodecVideoEncoder::ProcessHWErrorOnEncodeOnCodecThread() { | 535 int32_t MediaCodecVideoEncoder::ProcessHWErrorOnEncodeOnCodecThread() { |
536 ProcessHWErrorOnCodecThread(true /* reset_if_fallback_unavailable */); | 536 ProcessHWErrorOnCodecThread(true /* reset_if_fallback_unavailable */); |
537 return sw_fallback_required_ ? WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE | 537 return sw_fallback_required_ ? WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE |
538 : WEBRTC_VIDEO_CODEC_ERROR; | 538 : WEBRTC_VIDEO_CODEC_ERROR; |
539 } | 539 } |
540 | 540 |
541 int32_t MediaCodecVideoEncoder::InitEncodeOnCodecThread( | 541 int32_t MediaCodecVideoEncoder::InitEncodeOnCodecThread( |
542 int width, int height, int kbps, int fps, bool use_surface) { | 542 int width, int height, int kbps, int fps, bool use_surface) { |
543 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); | 543 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); |
544 if (sw_fallback_required_) { | 544 if (sw_fallback_required_) { |
545 return WEBRTC_VIDEO_CODEC_OK; | 545 return WEBRTC_VIDEO_CODEC_OK; |
546 } | 546 } |
547 RTC_CHECK(!use_surface || egl_context_ != nullptr) << "EGL context not set."; | 547 RTC_CHECK(!use_surface || egl_context_ != nullptr) << "EGL context not set."; |
548 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | 548 JNIEnv* jni = AttachCurrentThreadIfNeeded(); |
549 ScopedLocalRefFrame local_ref_frame(jni); | 549 ScopedLocalRefFrame local_ref_frame(jni); |
550 | 550 |
551 ALOGD << "InitEncodeOnCodecThread Type: " << (int)codecType_ << ", " << | 551 const VideoCodecType codec_type = cricket::CodecTypeFromName(codec_.name); |
552 width << " x " << height << ". Bitrate: " << kbps << | 552 ALOGD << "InitEncodeOnCodecThread Type: " << (int)codec_type << ", " << width |
553 " kbps. Fps: " << fps; | 553 << " x " << height << ". Bitrate: " << kbps << " kbps. Fps: " << fps; |
554 if (kbps == 0) { | 554 if (kbps == 0) { |
555 kbps = last_set_bitrate_kbps_; | 555 kbps = last_set_bitrate_kbps_; |
556 } | 556 } |
557 if (fps == 0) { | 557 if (fps == 0) { |
558 fps = MAX_VIDEO_FPS; | 558 fps = MAX_VIDEO_FPS; |
559 } | 559 } |
560 | 560 |
561 width_ = width; | 561 width_ = width; |
562 height_ = height; | 562 height_ = height; |
563 last_set_bitrate_kbps_ = kbps; | 563 last_set_bitrate_kbps_ = kbps; |
(...skipping 18 matching lines...) Expand all Loading... |
582 use_surface_ = use_surface; | 582 use_surface_ = use_surface; |
583 picture_id_ = static_cast<uint16_t>(rand()) & 0x7FFF; | 583 picture_id_ = static_cast<uint16_t>(rand()) & 0x7FFF; |
584 gof_.SetGofInfoVP9(webrtc::TemporalStructureMode::kTemporalStructureMode1); | 584 gof_.SetGofInfoVP9(webrtc::TemporalStructureMode::kTemporalStructureMode1); |
585 tl0_pic_idx_ = static_cast<uint8_t>(rand()); | 585 tl0_pic_idx_ = static_cast<uint8_t>(rand()); |
586 gof_idx_ = 0; | 586 gof_idx_ = 0; |
587 last_frame_received_ms_ = -1; | 587 last_frame_received_ms_ = -1; |
588 frames_received_since_last_key_ = kMinKeyFrameInterval; | 588 frames_received_since_last_key_ = kMinKeyFrameInterval; |
589 | 589 |
590 // We enforce no extra stride/padding in the format creation step. | 590 // We enforce no extra stride/padding in the format creation step. |
591 jobject j_video_codec_enum = JavaEnumFromIndexAndClassName( | 591 jobject j_video_codec_enum = JavaEnumFromIndexAndClassName( |
592 jni, "MediaCodecVideoEncoder$VideoCodecType", codecType_); | 592 jni, "MediaCodecVideoEncoder$VideoCodecType", codec_type); |
593 const bool encode_status = jni->CallBooleanMethod( | 593 const bool encode_status = jni->CallBooleanMethod( |
594 *j_media_codec_video_encoder_, j_init_encode_method_, | 594 *j_media_codec_video_encoder_, j_init_encode_method_, |
595 j_video_codec_enum, width, height, kbps, fps, | 595 j_video_codec_enum, width, height, kbps, fps, |
596 (use_surface ? egl_context_ : nullptr)); | 596 (use_surface ? egl_context_ : nullptr)); |
597 if (!encode_status) { | 597 if (!encode_status) { |
598 ALOGE << "Failed to configure encoder."; | 598 ALOGE << "Failed to configure encoder."; |
599 ProcessHWErrorOnCodecThread(false /* reset_if_fallback_unavailable */); | 599 ProcessHWErrorOnCodecThread(false /* reset_if_fallback_unavailable */); |
600 return WEBRTC_VIDEO_CODEC_ERROR; | 600 return WEBRTC_VIDEO_CODEC_ERROR; |
601 } | 601 } |
602 if (CheckException(jni)) { | 602 if (CheckException(jni)) { |
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1056 size_t payload_size = jni->GetDirectBufferCapacity(j_output_buffer); | 1056 size_t payload_size = jni->GetDirectBufferCapacity(j_output_buffer); |
1057 uint8_t* payload = reinterpret_cast<uint8_t*>( | 1057 uint8_t* payload = reinterpret_cast<uint8_t*>( |
1058 jni->GetDirectBufferAddress(j_output_buffer)); | 1058 jni->GetDirectBufferAddress(j_output_buffer)); |
1059 if (CheckException(jni)) { | 1059 if (CheckException(jni)) { |
1060 ALOGE << "Exception in get direct buffer address."; | 1060 ALOGE << "Exception in get direct buffer address."; |
1061 ProcessHWErrorOnCodecThread(true /* reset_if_fallback_unavailable */); | 1061 ProcessHWErrorOnCodecThread(true /* reset_if_fallback_unavailable */); |
1062 return WEBRTC_VIDEO_CODEC_ERROR; | 1062 return WEBRTC_VIDEO_CODEC_ERROR; |
1063 } | 1063 } |
1064 | 1064 |
1065 // Callback - return encoded frame. | 1065 // Callback - return encoded frame. |
| 1066 const VideoCodecType codec_type = cricket::CodecTypeFromName(codec_.name); |
1066 int32_t callback_status = 0; | 1067 int32_t callback_status = 0; |
1067 if (callback_) { | 1068 if (callback_) { |
1068 std::unique_ptr<webrtc::EncodedImage> image( | 1069 std::unique_ptr<webrtc::EncodedImage> image( |
1069 new webrtc::EncodedImage(payload, payload_size, payload_size)); | 1070 new webrtc::EncodedImage(payload, payload_size, payload_size)); |
1070 image->_encodedWidth = width_; | 1071 image->_encodedWidth = width_; |
1071 image->_encodedHeight = height_; | 1072 image->_encodedHeight = height_; |
1072 image->_timeStamp = output_timestamp_; | 1073 image->_timeStamp = output_timestamp_; |
1073 image->capture_time_ms_ = output_render_time_ms_; | 1074 image->capture_time_ms_ = output_render_time_ms_; |
1074 image->rotation_ = output_rotation_; | 1075 image->rotation_ = output_rotation_; |
1075 image->_frameType = | 1076 image->_frameType = |
1076 (key_frame ? webrtc::kVideoFrameKey : webrtc::kVideoFrameDelta); | 1077 (key_frame ? webrtc::kVideoFrameKey : webrtc::kVideoFrameDelta); |
1077 image->_completeFrame = true; | 1078 image->_completeFrame = true; |
1078 image->adapt_reason_.quality_resolution_downscales = | 1079 image->adapt_reason_.quality_resolution_downscales = |
1079 scale_ ? quality_scaler_.downscale_shift() : -1; | 1080 scale_ ? quality_scaler_.downscale_shift() : -1; |
1080 | 1081 |
1081 webrtc::CodecSpecificInfo info; | 1082 webrtc::CodecSpecificInfo info; |
1082 memset(&info, 0, sizeof(info)); | 1083 memset(&info, 0, sizeof(info)); |
1083 info.codecType = codecType_; | 1084 info.codecType = codec_type; |
1084 if (codecType_ == kVideoCodecVP8) { | 1085 if (codec_type == kVideoCodecVP8) { |
1085 info.codecSpecific.VP8.pictureId = picture_id_; | 1086 info.codecSpecific.VP8.pictureId = picture_id_; |
1086 info.codecSpecific.VP8.nonReference = false; | 1087 info.codecSpecific.VP8.nonReference = false; |
1087 info.codecSpecific.VP8.simulcastIdx = 0; | 1088 info.codecSpecific.VP8.simulcastIdx = 0; |
1088 info.codecSpecific.VP8.temporalIdx = webrtc::kNoTemporalIdx; | 1089 info.codecSpecific.VP8.temporalIdx = webrtc::kNoTemporalIdx; |
1089 info.codecSpecific.VP8.layerSync = false; | 1090 info.codecSpecific.VP8.layerSync = false; |
1090 info.codecSpecific.VP8.tl0PicIdx = webrtc::kNoTl0PicIdx; | 1091 info.codecSpecific.VP8.tl0PicIdx = webrtc::kNoTl0PicIdx; |
1091 info.codecSpecific.VP8.keyIdx = webrtc::kNoKeyIdx; | 1092 info.codecSpecific.VP8.keyIdx = webrtc::kNoKeyIdx; |
1092 } else if (codecType_ == kVideoCodecVP9) { | 1093 } else if (codec_type == kVideoCodecVP9) { |
1093 if (key_frame) { | 1094 if (key_frame) { |
1094 gof_idx_ = 0; | 1095 gof_idx_ = 0; |
1095 } | 1096 } |
1096 info.codecSpecific.VP9.picture_id = picture_id_; | 1097 info.codecSpecific.VP9.picture_id = picture_id_; |
1097 info.codecSpecific.VP9.inter_pic_predicted = key_frame ? false : true; | 1098 info.codecSpecific.VP9.inter_pic_predicted = key_frame ? false : true; |
1098 info.codecSpecific.VP9.flexible_mode = false; | 1099 info.codecSpecific.VP9.flexible_mode = false; |
1099 info.codecSpecific.VP9.ss_data_available = key_frame ? true : false; | 1100 info.codecSpecific.VP9.ss_data_available = key_frame ? true : false; |
1100 info.codecSpecific.VP9.tl0_pic_idx = tl0_pic_idx_++; | 1101 info.codecSpecific.VP9.tl0_pic_idx = tl0_pic_idx_++; |
1101 info.codecSpecific.VP9.temporal_idx = webrtc::kNoTemporalIdx; | 1102 info.codecSpecific.VP9.temporal_idx = webrtc::kNoTemporalIdx; |
1102 info.codecSpecific.VP9.spatial_idx = webrtc::kNoSpatialIdx; | 1103 info.codecSpecific.VP9.spatial_idx = webrtc::kNoSpatialIdx; |
1103 info.codecSpecific.VP9.temporal_up_switch = true; | 1104 info.codecSpecific.VP9.temporal_up_switch = true; |
1104 info.codecSpecific.VP9.inter_layer_predicted = false; | 1105 info.codecSpecific.VP9.inter_layer_predicted = false; |
1105 info.codecSpecific.VP9.gof_idx = | 1106 info.codecSpecific.VP9.gof_idx = |
1106 static_cast<uint8_t>(gof_idx_++ % gof_.num_frames_in_gof); | 1107 static_cast<uint8_t>(gof_idx_++ % gof_.num_frames_in_gof); |
1107 info.codecSpecific.VP9.num_spatial_layers = 1; | 1108 info.codecSpecific.VP9.num_spatial_layers = 1; |
1108 info.codecSpecific.VP9.spatial_layer_resolution_present = false; | 1109 info.codecSpecific.VP9.spatial_layer_resolution_present = false; |
1109 if (info.codecSpecific.VP9.ss_data_available) { | 1110 if (info.codecSpecific.VP9.ss_data_available) { |
1110 info.codecSpecific.VP9.spatial_layer_resolution_present = true; | 1111 info.codecSpecific.VP9.spatial_layer_resolution_present = true; |
1111 info.codecSpecific.VP9.width[0] = width_; | 1112 info.codecSpecific.VP9.width[0] = width_; |
1112 info.codecSpecific.VP9.height[0] = height_; | 1113 info.codecSpecific.VP9.height[0] = height_; |
1113 info.codecSpecific.VP9.gof.CopyGofInfoVP9(gof_); | 1114 info.codecSpecific.VP9.gof.CopyGofInfoVP9(gof_); |
1114 } | 1115 } |
1115 } | 1116 } |
1116 picture_id_ = (picture_id_ + 1) & 0x7FFF; | 1117 picture_id_ = (picture_id_ + 1) & 0x7FFF; |
1117 | 1118 |
1118 // Generate a header describing a single fragment. | 1119 // Generate a header describing a single fragment. |
1119 webrtc::RTPFragmentationHeader header; | 1120 webrtc::RTPFragmentationHeader header; |
1120 memset(&header, 0, sizeof(header)); | 1121 memset(&header, 0, sizeof(header)); |
1121 if (codecType_ == kVideoCodecVP8 || codecType_ == kVideoCodecVP9) { | 1122 if (codec_type == kVideoCodecVP8 || codec_type == kVideoCodecVP9) { |
1122 header.VerifyAndAllocateFragmentationHeader(1); | 1123 header.VerifyAndAllocateFragmentationHeader(1); |
1123 header.fragmentationOffset[0] = 0; | 1124 header.fragmentationOffset[0] = 0; |
1124 header.fragmentationLength[0] = image->_length; | 1125 header.fragmentationLength[0] = image->_length; |
1125 header.fragmentationPlType[0] = 0; | 1126 header.fragmentationPlType[0] = 0; |
1126 header.fragmentationTimeDiff[0] = 0; | 1127 header.fragmentationTimeDiff[0] = 0; |
1127 if (codecType_ == kVideoCodecVP8 && scale_) { | 1128 if (codec_type == kVideoCodecVP8 && scale_) { |
1128 int qp; | 1129 int qp; |
1129 if (webrtc::vp8::GetQp(payload, payload_size, &qp)) { | 1130 if (webrtc::vp8::GetQp(payload, payload_size, &qp)) { |
1130 current_acc_qp_ += qp; | 1131 current_acc_qp_ += qp; |
1131 quality_scaler_.ReportQP(qp); | 1132 quality_scaler_.ReportQP(qp); |
1132 image->qp_ = qp; | 1133 image->qp_ = qp; |
1133 } | 1134 } |
1134 } | 1135 } |
1135 } else if (codecType_ == kVideoCodecH264) { | 1136 } else if (codec_type == kVideoCodecH264) { |
1136 if (scale_) { | 1137 if (scale_) { |
1137 h264_bitstream_parser_.ParseBitstream(payload, payload_size); | 1138 h264_bitstream_parser_.ParseBitstream(payload, payload_size); |
1138 int qp; | 1139 int qp; |
1139 if (h264_bitstream_parser_.GetLastSliceQp(&qp)) { | 1140 if (h264_bitstream_parser_.GetLastSliceQp(&qp)) { |
1140 current_acc_qp_ += qp; | 1141 current_acc_qp_ += qp; |
1141 quality_scaler_.ReportQP(qp); | 1142 quality_scaler_.ReportQP(qp); |
1142 } | 1143 } |
1143 } | 1144 } |
1144 // For H.264 search for start codes. | 1145 // For H.264 search for start codes. |
1145 int32_t scPositions[MAX_NALUS_PERFRAME + 1] = {}; | 1146 int32_t scPositions[MAX_NALUS_PERFRAME + 1] = {}; |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1351 } | 1352 } |
1352 | 1353 |
1353 webrtc::VideoEncoder* MediaCodecVideoEncoderFactory::CreateVideoEncoder( | 1354 webrtc::VideoEncoder* MediaCodecVideoEncoderFactory::CreateVideoEncoder( |
1354 const cricket::VideoCodec& codec) { | 1355 const cricket::VideoCodec& codec) { |
1355 if (supported_codecs_.empty()) { | 1356 if (supported_codecs_.empty()) { |
1356 ALOGW << "No HW video encoder for codec " << codec.name; | 1357 ALOGW << "No HW video encoder for codec " << codec.name; |
1357 return nullptr; | 1358 return nullptr; |
1358 } | 1359 } |
1359 if (IsCodecSupported(supported_codecs_, codec)) { | 1360 if (IsCodecSupported(supported_codecs_, codec)) { |
1360 ALOGD << "Create HW video encoder for " << codec.name; | 1361 ALOGD << "Create HW video encoder for " << codec.name; |
1361 const VideoCodecType type = cricket::CodecTypeFromName(codec.name); | 1362 return new MediaCodecVideoEncoder(AttachCurrentThreadIfNeeded(), codec, |
1362 return new MediaCodecVideoEncoder(AttachCurrentThreadIfNeeded(), type, | |
1363 egl_context_); | 1363 egl_context_); |
1364 } | 1364 } |
1365 ALOGW << "Can not find HW video encoder for type " << codec.name; | 1365 ALOGW << "Can not find HW video encoder for type " << codec.name; |
1366 return nullptr; | 1366 return nullptr; |
1367 } | 1367 } |
1368 | 1368 |
1369 const std::vector<cricket::VideoCodec>& | 1369 const std::vector<cricket::VideoCodec>& |
1370 MediaCodecVideoEncoderFactory::supported_codecs() const { | 1370 MediaCodecVideoEncoderFactory::supported_codecs() const { |
1371 return supported_codecs_; | 1371 return supported_codecs_; |
1372 } | 1372 } |
1373 | 1373 |
1374 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( | 1374 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( |
1375 webrtc::VideoEncoder* encoder) { | 1375 webrtc::VideoEncoder* encoder) { |
1376 ALOGD << "Destroy video encoder."; | 1376 ALOGD << "Destroy video encoder."; |
1377 delete encoder; | 1377 delete encoder; |
1378 } | 1378 } |
1379 | 1379 |
1380 } // namespace webrtc_jni | 1380 } // namespace webrtc_jni |
OLD | NEW |