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 12 matching lines...) Expand all Loading... |
23 #include "webrtc/api/android/jni/classreferenceholder.h" | 23 #include "webrtc/api/android/jni/classreferenceholder.h" |
24 #include "webrtc/api/android/jni/native_handle_impl.h" | 24 #include "webrtc/api/android/jni/native_handle_impl.h" |
25 #include "webrtc/base/bind.h" | 25 #include "webrtc/base/bind.h" |
26 #include "webrtc/base/checks.h" | 26 #include "webrtc/base/checks.h" |
27 #include "webrtc/base/logging.h" | 27 #include "webrtc/base/logging.h" |
28 #include "webrtc/base/thread.h" | 28 #include "webrtc/base/thread.h" |
29 #include "webrtc/base/thread_checker.h" | 29 #include "webrtc/base/thread_checker.h" |
30 #include "webrtc/base/timeutils.h" | 30 #include "webrtc/base/timeutils.h" |
31 #include "webrtc/common_types.h" | 31 #include "webrtc/common_types.h" |
32 #include "webrtc/common_video/h264/h264_bitstream_parser.h" | 32 #include "webrtc/common_video/h264/h264_bitstream_parser.h" |
| 33 #include "webrtc/common_video/h264/h264_common.h" |
33 #include "webrtc/common_video/h264/profile_level_id.h" | 34 #include "webrtc/common_video/h264/profile_level_id.h" |
34 #include "webrtc/media/engine/internalencoderfactory.h" | 35 #include "webrtc/media/engine/internalencoderfactory.h" |
35 #include "webrtc/modules/video_coding/include/video_codec_interface.h" | 36 #include "webrtc/modules/video_coding/include/video_codec_interface.h" |
36 #include "webrtc/modules/video_coding/utility/quality_scaler.h" | 37 #include "webrtc/modules/video_coding/utility/quality_scaler.h" |
37 #include "webrtc/modules/video_coding/utility/vp8_header_parser.h" | 38 #include "webrtc/modules/video_coding/utility/vp8_header_parser.h" |
38 #include "webrtc/system_wrappers/include/field_trial.h" | 39 #include "webrtc/system_wrappers/include/field_trial.h" |
39 #include "webrtc/system_wrappers/include/logcat_trace_context.h" | 40 #include "webrtc/system_wrappers/include/logcat_trace_context.h" |
40 #include "webrtc/video_encoder.h" | 41 #include "webrtc/video_encoder.h" |
41 | 42 |
42 using rtc::Bind; | 43 using rtc::Bind; |
43 using rtc::Thread; | 44 using rtc::Thread; |
44 using rtc::ThreadManager; | 45 using rtc::ThreadManager; |
45 | 46 |
46 using webrtc::CodecSpecificInfo; | 47 using webrtc::CodecSpecificInfo; |
47 using webrtc::EncodedImage; | 48 using webrtc::EncodedImage; |
48 using webrtc::VideoFrame; | 49 using webrtc::VideoFrame; |
49 using webrtc::RTPFragmentationHeader; | 50 using webrtc::RTPFragmentationHeader; |
50 using webrtc::VideoCodec; | 51 using webrtc::VideoCodec; |
51 using webrtc::VideoCodecType; | 52 using webrtc::VideoCodecType; |
52 using webrtc::kVideoCodecH264; | 53 using webrtc::kVideoCodecH264; |
53 using webrtc::kVideoCodecVP8; | 54 using webrtc::kVideoCodecVP8; |
54 using webrtc::kVideoCodecVP9; | 55 using webrtc::kVideoCodecVP9; |
55 using webrtc::QualityScaler; | 56 using webrtc::QualityScaler; |
56 | 57 |
57 namespace webrtc_jni { | 58 namespace webrtc_jni { |
58 | 59 |
59 // H.264 start code length. | |
60 #define H264_SC_LENGTH 4 | |
61 // Maximum allowed NALUs in one output frame. | |
62 #define MAX_NALUS_PERFRAME 32 | |
63 // Maximum supported HW video encoder fps. | 60 // Maximum supported HW video encoder fps. |
64 #define MAX_VIDEO_FPS 30 | 61 #define MAX_VIDEO_FPS 30 |
65 // Maximum allowed fps value in SetRates() call. | 62 // Maximum allowed fps value in SetRates() call. |
66 #define MAX_ALLOWED_VIDEO_FPS 60 | 63 #define MAX_ALLOWED_VIDEO_FPS 60 |
67 // Maximum allowed frames in encoder input queue. | 64 // Maximum allowed frames in encoder input queue. |
68 #define MAX_ENCODER_Q_SIZE 2 | 65 #define MAX_ENCODER_Q_SIZE 2 |
69 // Maximum amount of dropped frames caused by full encoder queue - exceeding | 66 // Maximum amount of dropped frames caused by full encoder queue - exceeding |
70 // this threshold means that encoder probably got stuck and need to be reset. | 67 // this threshold means that encoder probably got stuck and need to be reset. |
71 #define ENCODER_STALL_FRAMEDROP_THRESHOLD 60 | 68 #define ENCODER_STALL_FRAMEDROP_THRESHOLD 60 |
72 | 69 |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
172 int GetOutputBufferInfoIndex(JNIEnv* jni, jobject j_output_buffer_info); | 169 int GetOutputBufferInfoIndex(JNIEnv* jni, jobject j_output_buffer_info); |
173 jobject GetOutputBufferInfoBuffer(JNIEnv* jni, jobject j_output_buffer_info); | 170 jobject GetOutputBufferInfoBuffer(JNIEnv* jni, jobject j_output_buffer_info); |
174 bool GetOutputBufferInfoIsKeyFrame(JNIEnv* jni, jobject j_output_buffer_info); | 171 bool GetOutputBufferInfoIsKeyFrame(JNIEnv* jni, jobject j_output_buffer_info); |
175 jlong GetOutputBufferInfoPresentationTimestampUs( | 172 jlong GetOutputBufferInfoPresentationTimestampUs( |
176 JNIEnv* jni, jobject j_output_buffer_info); | 173 JNIEnv* jni, jobject j_output_buffer_info); |
177 | 174 |
178 // Deliver any outputs pending in the MediaCodec to our |callback_| and return | 175 // Deliver any outputs pending in the MediaCodec to our |callback_| and return |
179 // true on success. | 176 // true on success. |
180 bool DeliverPendingOutputs(JNIEnv* jni); | 177 bool DeliverPendingOutputs(JNIEnv* jni); |
181 | 178 |
182 // Search for H.264 start codes. | |
183 int32_t NextNaluPosition(uint8_t *buffer, size_t buffer_size); | |
184 | |
185 VideoEncoder::ScalingSettings GetScalingSettings() const override; | 179 VideoEncoder::ScalingSettings GetScalingSettings() const override; |
186 | 180 |
187 // Displays encoder statistics. | 181 // Displays encoder statistics. |
188 void LogStatistics(bool force_log); | 182 void LogStatistics(bool force_log); |
189 | 183 |
190 // Type of video codec. | 184 // Type of video codec. |
191 const cricket::VideoCodec codec_; | 185 const cricket::VideoCodec codec_; |
192 | 186 |
193 // Valid all the time since RegisterEncodeCompleteCallback() Invoke()s to | 187 // Valid all the time since RegisterEncodeCompleteCallback() Invoke()s to |
194 // |codec_thread_| synchronously. | 188 // |codec_thread_| synchronously. |
(...skipping 899 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1094 } | 1088 } |
1095 } | 1089 } |
1096 } else if (codec_type == kVideoCodecH264) { | 1090 } else if (codec_type == kVideoCodecH264) { |
1097 h264_bitstream_parser_.ParseBitstream(payload, payload_size); | 1091 h264_bitstream_parser_.ParseBitstream(payload, payload_size); |
1098 int qp; | 1092 int qp; |
1099 if (h264_bitstream_parser_.GetLastSliceQp(&qp)) { | 1093 if (h264_bitstream_parser_.GetLastSliceQp(&qp)) { |
1100 current_acc_qp_ += qp; | 1094 current_acc_qp_ += qp; |
1101 image->qp_ = qp; | 1095 image->qp_ = qp; |
1102 } | 1096 } |
1103 // For H.264 search for start codes. | 1097 // For H.264 search for start codes. |
1104 int32_t scPositions[MAX_NALUS_PERFRAME + 1] = {}; | 1098 const std::vector<webrtc::H264::NaluIndex> nalu_idxs = |
1105 int32_t scPositionsLength = 0; | 1099 webrtc::H264::FindNaluIndices(payload, payload_size); |
1106 int32_t scPosition = 0; | 1100 if (nalu_idxs.empty()) { |
1107 while (scPositionsLength < MAX_NALUS_PERFRAME) { | |
1108 int32_t naluPosition = NextNaluPosition( | |
1109 payload + scPosition, payload_size - scPosition); | |
1110 if (naluPosition < 0) { | |
1111 break; | |
1112 } | |
1113 scPosition += naluPosition; | |
1114 scPositions[scPositionsLength++] = scPosition; | |
1115 scPosition += H264_SC_LENGTH; | |
1116 } | |
1117 if (scPositionsLength == 0) { | |
1118 ALOGE << "Start code is not found!"; | 1101 ALOGE << "Start code is not found!"; |
1119 ALOGE << "Data:" << image->_buffer[0] << " " << image->_buffer[1] | 1102 ALOGE << "Data:" << image->_buffer[0] << " " << image->_buffer[1] |
1120 << " " << image->_buffer[2] << " " << image->_buffer[3] | 1103 << " " << image->_buffer[2] << " " << image->_buffer[3] |
1121 << " " << image->_buffer[4] << " " << image->_buffer[5]; | 1104 << " " << image->_buffer[4] << " " << image->_buffer[5]; |
1122 ProcessHWErrorOnCodecThread(true /* reset_if_fallback_unavailable */); | 1105 ProcessHWErrorOnCodecThread(true /* reset_if_fallback_unavailable */); |
1123 return false; | 1106 return false; |
1124 } | 1107 } |
1125 scPositions[scPositionsLength] = payload_size; | 1108 header.VerifyAndAllocateFragmentationHeader(nalu_idxs.size()); |
1126 header.VerifyAndAllocateFragmentationHeader(scPositionsLength); | 1109 for (size_t i = 0; i < nalu_idxs.size(); i++) { |
1127 for (size_t i = 0; i < scPositionsLength; i++) { | 1110 header.fragmentationOffset[i] = nalu_idxs[i].payload_start_offset; |
1128 header.fragmentationOffset[i] = scPositions[i] + H264_SC_LENGTH; | 1111 header.fragmentationLength[i] = nalu_idxs[i].payload_size; |
1129 header.fragmentationLength[i] = | |
1130 scPositions[i + 1] - header.fragmentationOffset[i]; | |
1131 header.fragmentationPlType[i] = 0; | 1112 header.fragmentationPlType[i] = 0; |
1132 header.fragmentationTimeDiff[i] = 0; | 1113 header.fragmentationTimeDiff[i] = 0; |
1133 } | 1114 } |
1134 } | 1115 } |
1135 | 1116 |
1136 callback_result = callback_->OnEncodedImage(*image, &info, &header); | 1117 callback_result = callback_->OnEncodedImage(*image, &info, &header); |
1137 } | 1118 } |
1138 | 1119 |
1139 // Return output buffer back to the encoder. | 1120 // Return output buffer back to the encoder. |
1140 bool success = jni->CallBooleanMethod(*j_media_codec_video_encoder_, | 1121 bool success = jni->CallBooleanMethod(*j_media_codec_video_encoder_, |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1197 current_acc_qp_ = 0; | 1178 current_acc_qp_ = 0; |
1198 current_encoding_time_ms_ = 0; | 1179 current_encoding_time_ms_ = 0; |
1199 } | 1180 } |
1200 } | 1181 } |
1201 | 1182 |
1202 webrtc::VideoEncoder::ScalingSettings | 1183 webrtc::VideoEncoder::ScalingSettings |
1203 MediaCodecVideoEncoder::GetScalingSettings() const { | 1184 MediaCodecVideoEncoder::GetScalingSettings() const { |
1204 return VideoEncoder::ScalingSettings(scale_); | 1185 return VideoEncoder::ScalingSettings(scale_); |
1205 } | 1186 } |
1206 | 1187 |
1207 int32_t MediaCodecVideoEncoder::NextNaluPosition( | |
1208 uint8_t *buffer, size_t buffer_size) { | |
1209 if (buffer_size < H264_SC_LENGTH) { | |
1210 return -1; | |
1211 } | |
1212 uint8_t *head = buffer; | |
1213 // Set end buffer pointer to 4 bytes before actual buffer end so we can | |
1214 // access head[1], head[2] and head[3] in a loop without buffer overrun. | |
1215 uint8_t *end = buffer + buffer_size - H264_SC_LENGTH; | |
1216 | |
1217 while (head < end) { | |
1218 if (head[0]) { | |
1219 head++; | |
1220 continue; | |
1221 } | |
1222 if (head[1]) { // got 00xx | |
1223 head += 2; | |
1224 continue; | |
1225 } | |
1226 if (head[2]) { // got 0000xx | |
1227 head += 3; | |
1228 continue; | |
1229 } | |
1230 if (head[3] != 0x01) { // got 000000xx | |
1231 head++; // xx != 1, continue searching. | |
1232 continue; | |
1233 } | |
1234 return (int32_t)(head - buffer); | |
1235 } | |
1236 return -1; | |
1237 } | |
1238 | |
1239 const char* MediaCodecVideoEncoder::ImplementationName() const { | 1188 const char* MediaCodecVideoEncoder::ImplementationName() const { |
1240 return "MediaCodec"; | 1189 return "MediaCodec"; |
1241 } | 1190 } |
1242 | 1191 |
1243 MediaCodecVideoEncoderFactory::MediaCodecVideoEncoderFactory() | 1192 MediaCodecVideoEncoderFactory::MediaCodecVideoEncoderFactory() |
1244 : egl_context_(nullptr) { | 1193 : egl_context_(nullptr) { |
1245 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | 1194 JNIEnv* jni = AttachCurrentThreadIfNeeded(); |
1246 ScopedLocalRefFrame local_ref_frame(jni); | 1195 ScopedLocalRefFrame local_ref_frame(jni); |
1247 jclass j_encoder_class = FindClass(jni, "org/webrtc/MediaCodecVideoEncoder"); | 1196 jclass j_encoder_class = FindClass(jni, "org/webrtc/MediaCodecVideoEncoder"); |
1248 supported_codecs_.clear(); | 1197 supported_codecs_.clear(); |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1330 return supported_codecs_; | 1279 return supported_codecs_; |
1331 } | 1280 } |
1332 | 1281 |
1333 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( | 1282 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( |
1334 webrtc::VideoEncoder* encoder) { | 1283 webrtc::VideoEncoder* encoder) { |
1335 ALOGD << "Destroy video encoder."; | 1284 ALOGD << "Destroy video encoder."; |
1336 delete encoder; | 1285 delete encoder; |
1337 } | 1286 } |
1338 | 1287 |
1339 } // namespace webrtc_jni | 1288 } // namespace webrtc_jni |
OLD | NEW |