OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/base/android/media_codec_util.h" | 5 #include "media/base/android/media_codec_util.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 | 10 |
(...skipping 10 matching lines...) Expand all Loading... | |
21 #include "url/gurl.h" | 21 #include "url/gurl.h" |
22 | 22 |
23 using base::android::AttachCurrentThread; | 23 using base::android::AttachCurrentThread; |
24 using base::android::ConvertJavaStringToUTF8; | 24 using base::android::ConvertJavaStringToUTF8; |
25 using base::android::ConvertUTF8ToJavaString; | 25 using base::android::ConvertUTF8ToJavaString; |
26 using base::android::JavaIntArrayToIntVector; | 26 using base::android::JavaIntArrayToIntVector; |
27 using base::android::JavaRef; | 27 using base::android::JavaRef; |
28 using base::android::ScopedJavaLocalRef; | 28 using base::android::ScopedJavaLocalRef; |
29 | 29 |
30 namespace media { | 30 namespace media { |
31 | |
32 namespace { | 31 namespace { |
33 | 32 |
34 const char kMp4aMimeType[] = "audio/mp4a-latm"; | 33 const char kMp3MimeType[] = "audio/mpeg"; |
34 const char kAacMimeType[] = "audio/mp4a-latm"; | |
35 const char kOpusMimeType[] = "audio/opus"; | 35 const char kOpusMimeType[] = "audio/opus"; |
36 const char kVorbisMimeType[] = "audio/vorbis"; | 36 const char kVorbisMimeType[] = "audio/vorbis"; |
37 const char kAc3MimeType[] = "audio/ac3"; | 37 const char kAc3MimeType[] = "audio/ac3"; |
38 const char kEac3MimeType[] = "audio/eac3"; | 38 const char kEac3MimeType[] = "audio/eac3"; |
39 const char kAvcMimeType[] = "video/avc"; | 39 const char kAvcMimeType[] = "video/avc"; |
40 const char kHevcMimeType[] = "video/hevc"; | 40 const char kHevcMimeType[] = "video/hevc"; |
41 const char kVp8MimeType[] = "video/x-vnd.on2.vp8"; | 41 const char kVp8MimeType[] = "video/x-vnd.on2.vp8"; |
42 const char kVp9MimeType[] = "video/x-vnd.on2.vp9"; | 42 const char kVp9MimeType[] = "video/x-vnd.on2.vp9"; |
43 | 43 |
44 } // namespace | 44 } // namespace |
45 | 45 |
46 static std::string CodecTypeToAndroidMimeType(const std::string& codec) { | |
47 // TODO(xhwang): Shall we handle more detailed strings like "mp4a.40.2"? | |
48 if (codec == "avc1") | |
49 return kAvcMimeType; | |
50 if (codec == "hvc1") | |
51 return kHevcMimeType; | |
52 if (codec == "mp4a") | |
53 return kMp4aMimeType; | |
54 if (codec == "vp8" || codec == "vp8.0") | |
55 return kVp8MimeType; | |
56 if (codec == "vp9" || codec == "vp9.0") | |
57 return kVp9MimeType; | |
58 if (codec == "vorbis") | |
59 return kVorbisMimeType; | |
60 if (codec == "opus") | |
61 return kOpusMimeType; | |
62 if (codec == "ac3") | |
63 return kAc3MimeType; | |
64 if (codec == "eac3") | |
65 return kEac3MimeType; | |
66 | |
67 DLOG(WARNING) << "Cannot convert codec to Android MIME type: " << codec; | |
68 return std::string(); | |
69 } | |
70 | |
71 static VideoCodec AndroidCodecToCodecEnum(const std::string& codec) { | 46 static VideoCodec AndroidCodecToCodecEnum(const std::string& codec) { |
72 if (codec == "AVC") | 47 if (codec == "AVC") |
73 return kCodecH264; | 48 return kCodecH264; |
74 if (codec == "VP8") | 49 if (codec == "VP8") |
75 return kCodecVP8; | 50 return kCodecVP8; |
76 if (codec == "VP9") | 51 if (codec == "VP9") |
77 return kCodecVP9; | 52 return kCodecVP9; |
78 if (codec == "HEVC") | 53 if (codec == "HEVC") |
79 return kCodecHEVC; | 54 return kCodecHEVC; |
80 DLOG(WARNING) << "Unknown video codec name \"" << codec << "\""; | 55 DLOG(WARNING) << "Unknown video codec name \"" << codec << "\""; |
81 return kUnknownVideoCodec; | 56 return kUnknownVideoCodec; |
82 } | 57 } |
83 | 58 |
84 static CodecProfileLevel MediaCodecProfileLevelToChromiumProfileLevel( | 59 static CodecProfileLevel MediaCodecProfileLevelToChromiumProfileLevel( |
85 JNIEnv* env, | 60 JNIEnv* env, |
86 const jobject& j_codec_profile_level) { | 61 const jobject& j_codec_profile_level) { |
87 ScopedJavaLocalRef<jstring> codec = | 62 ScopedJavaLocalRef<jstring> codec = |
88 Java_CodecProfileLevelAdapter_getCodec(env, j_codec_profile_level); | 63 Java_CodecProfileLevelAdapter_getCodec(env, j_codec_profile_level); |
89 int profile = | 64 int profile = |
90 Java_CodecProfileLevelAdapter_getProfile(env, j_codec_profile_level); | 65 Java_CodecProfileLevelAdapter_getProfile(env, j_codec_profile_level); |
91 int level = | 66 int level = |
92 Java_CodecProfileLevelAdapter_getLevel(env, j_codec_profile_level); | 67 Java_CodecProfileLevelAdapter_getLevel(env, j_codec_profile_level); |
93 return {AndroidCodecToCodecEnum(ConvertJavaStringToUTF8(codec)), | 68 return {AndroidCodecToCodecEnum(ConvertJavaStringToUTF8(codec)), |
94 static_cast<VideoCodecProfile>(profile), level}; | 69 static_cast<VideoCodecProfile>(profile), level}; |
95 } | 70 } |
96 | 71 |
97 static bool IsSupportedAndroidMimeType(const std::string& mime_type) { | 72 static bool IsSupportedAndroidMimeType(const std::string& mime_type) { |
98 std::vector<std::string> supported{ | 73 std::vector<std::string> supported{ |
99 kMp4aMimeType, kOpusMimeType, kVorbisMimeType, kAvcMimeType, | 74 kMp3MimeType, kAacMimeType, kOpusMimeType, kVorbisMimeType, |
watk
2017/02/14 01:40:51
I added mp3 here. Seems like it was missing before
| |
100 kHevcMimeType, kVp8MimeType, kVp9MimeType}; | 75 kAvcMimeType, kHevcMimeType, kVp8MimeType, kVp9MimeType}; |
101 return std::find(supported.begin(), supported.end(), mime_type) != | 76 return std::find(supported.begin(), supported.end(), mime_type) != |
102 supported.end(); | 77 supported.end(); |
103 } | 78 } |
104 | 79 |
105 static std::string GetDefaultCodecName(const std::string& mime_type, | 80 static std::string GetDefaultCodecName(const std::string& mime_type, |
106 MediaCodecDirection direction, | 81 MediaCodecDirection direction, |
107 bool require_software_codec) { | 82 bool require_software_codec) { |
108 DCHECK(MediaCodecUtil::IsMediaCodecAvailable()); | 83 DCHECK(MediaCodecUtil::IsMediaCodecAvailable()); |
109 JNIEnv* env = AttachCurrentThread(); | 84 JNIEnv* env = AttachCurrentThread(); |
110 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime_type); | 85 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime_type); |
111 ScopedJavaLocalRef<jstring> j_codec_name = | 86 ScopedJavaLocalRef<jstring> j_codec_name = |
112 Java_MediaCodecUtil_getDefaultCodecName(env, j_mime, direction, | 87 Java_MediaCodecUtil_getDefaultCodecName( |
113 require_software_codec); | 88 env, j_mime, static_cast<int>(direction), require_software_codec); |
114 return ConvertJavaStringToUTF8(env, j_codec_name.obj()); | 89 return ConvertJavaStringToUTF8(env, j_codec_name.obj()); |
115 } | 90 } |
116 | 91 |
117 static bool IsDecoderSupportedByDevice(const std::string& android_mime_type) { | 92 static bool IsDecoderSupportedByDevice(const std::string& android_mime_type) { |
118 DCHECK(MediaCodecUtil::IsMediaCodecAvailable()); | 93 DCHECK(MediaCodecUtil::IsMediaCodecAvailable()); |
119 DCHECK(IsSupportedAndroidMimeType(android_mime_type)); | 94 DCHECK(IsSupportedAndroidMimeType(android_mime_type)); |
120 JNIEnv* env = AttachCurrentThread(); | 95 JNIEnv* env = AttachCurrentThread(); |
121 ScopedJavaLocalRef<jstring> j_mime = | 96 ScopedJavaLocalRef<jstring> j_mime = |
122 ConvertUTF8ToJavaString(env, android_mime_type); | 97 ConvertUTF8ToJavaString(env, android_mime_type); |
123 return Java_MediaCodecUtil_isDecoderSupportedForDevice(env, j_mime); | 98 return Java_MediaCodecUtil_isDecoderSupportedForDevice(env, j_mime); |
124 } | 99 } |
125 | 100 |
126 static bool IsEncoderSupportedByDevice(const std::string& android_mime_type) { | 101 static bool IsEncoderSupportedByDevice(const std::string& android_mime_type) { |
127 DCHECK(MediaCodecUtil::IsMediaCodecAvailable()); | 102 DCHECK(MediaCodecUtil::IsMediaCodecAvailable()); |
128 JNIEnv* env = AttachCurrentThread(); | 103 JNIEnv* env = AttachCurrentThread(); |
129 ScopedJavaLocalRef<jstring> j_mime = | 104 ScopedJavaLocalRef<jstring> j_mime = |
130 ConvertUTF8ToJavaString(env, android_mime_type); | 105 ConvertUTF8ToJavaString(env, android_mime_type); |
131 return Java_MediaCodecUtil_isEncoderSupportedByDevice(env, j_mime); | 106 return Java_MediaCodecUtil_isEncoderSupportedByDevice(env, j_mime); |
132 } | 107 } |
133 | 108 |
134 // static | 109 // static |
110 std::string MediaCodecUtil::CodecToAndroidMimeType(AudioCodec codec) { | |
111 switch (codec) { | |
112 case kCodecMP3: | |
113 return kMp3MimeType; | |
114 case kCodecVorbis: | |
115 return kVorbisMimeType; | |
116 case kCodecOpus: | |
117 return kOpusMimeType; | |
118 case kCodecAAC: | |
119 return kAacMimeType; | |
120 case kCodecAC3: | |
121 return kAc3MimeType; | |
122 case kCodecEAC3: | |
123 return kEac3MimeType; | |
124 default: | |
125 return std::string(); | |
126 } | |
127 } | |
128 | |
129 // static | |
130 std::string MediaCodecUtil::CodecToAndroidMimeType(VideoCodec codec) { | |
131 switch (codec) { | |
132 case kCodecH264: | |
133 return kAvcMimeType; | |
134 case kCodecHEVC: | |
135 return kHevcMimeType; | |
136 case kCodecVP8: | |
137 return kVp8MimeType; | |
138 case kCodecVP9: | |
139 return kVp9MimeType; | |
140 default: | |
141 return std::string(); | |
142 } | |
143 } | |
144 | |
145 // static | |
135 bool MediaCodecUtil::IsMediaCodecAvailable() { | 146 bool MediaCodecUtil::IsMediaCodecAvailable() { |
136 // Blacklist some devices on Jellybean as MediaCodec is buggy. | 147 // Blacklist some devices on Jellybean as MediaCodec is buggy. |
137 // http://crbug.com/365494, http://crbug.com/615872 | 148 // http://crbug.com/365494, http://crbug.com/615872 |
138 // Blacklist Lenovo A6600 / A6800 on KitKat, which tends to crash a lot. | 149 // Blacklist Lenovo A6600 / A6800 on KitKat, which tends to crash a lot. |
139 // See crbug.com/628059 . We include < K since they don't exist. | 150 // See crbug.com/628059 . We include < K since they don't exist. |
140 // Blacklist Samsung Galaxy Star Pro (GT-S7262) (crbug.com/634920). | 151 // Blacklist Samsung Galaxy Star Pro (GT-S7262) (crbug.com/634920). |
141 // GT-S5282 and GT-I8552 are for crbug.com/634920 . | 152 // GT-S5282 and GT-I8552 are for crbug.com/634920 . |
142 if (base::android::BuildInfo::GetInstance()->sdk_int() <= 19) { | 153 if (base::android::BuildInfo::GetInstance()->sdk_int() <= 19) { |
143 std::string model(base::android::BuildInfo::GetInstance()->model()); | 154 std::string model(base::android::BuildInfo::GetInstance()->model()); |
144 return model != "GT-I9100" && model != "GT-I9300" && model != "GT-N7000" && | 155 return model != "GT-I9100" && model != "GT-I9300" && model != "GT-N7000" && |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
176 if (j_color_format_array.obj()) { | 187 if (j_color_format_array.obj()) { |
177 std::vector<int> formats; | 188 std::vector<int> formats; |
178 JavaIntArrayToIntVector(env, j_color_format_array.obj(), &formats); | 189 JavaIntArrayToIntVector(env, j_color_format_array.obj(), &formats); |
179 color_formats = std::set<int>(formats.begin(), formats.end()); | 190 color_formats = std::set<int>(formats.begin(), formats.end()); |
180 } | 191 } |
181 | 192 |
182 return color_formats; | 193 return color_formats; |
183 } | 194 } |
184 | 195 |
185 // static | 196 // static |
186 bool MediaCodecUtil::CanDecode(const std::string& codec, bool is_secure) { | 197 bool MediaCodecUtil::CanDecode(const std::string& mime, bool is_secure) { |
187 if (!IsMediaCodecAvailable()) | 198 if (!IsMediaCodecAvailable()) |
188 return false; | 199 return false; |
200 if (mime.empty()) | |
201 return false; | |
189 | 202 |
190 JNIEnv* env = AttachCurrentThread(); | 203 JNIEnv* env = AttachCurrentThread(); |
191 std::string mime = CodecTypeToAndroidMimeType(codec); | |
192 if (mime.empty()) | |
193 return false; | |
194 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime); | 204 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime); |
195 return Java_MediaCodecUtil_canDecode(env, j_mime, is_secure); | 205 return Java_MediaCodecUtil_canDecode(env, j_mime, is_secure); |
196 } | 206 } |
197 | 207 |
198 // static | 208 // static |
199 bool MediaCodecUtil::AddSupportedCodecProfileLevels( | 209 bool MediaCodecUtil::AddSupportedCodecProfileLevels( |
200 std::vector<CodecProfileLevel>* result) { | 210 std::vector<CodecProfileLevel>* result) { |
201 DCHECK(result); | 211 DCHECK(result); |
202 if (!IsMediaCodecAvailable()) | 212 if (!IsMediaCodecAvailable()) |
203 return false; | 213 return false; |
204 JNIEnv* env = AttachCurrentThread(); | 214 JNIEnv* env = AttachCurrentThread(); |
205 ScopedJavaLocalRef<jobjectArray> j_codec_profile_levels( | 215 ScopedJavaLocalRef<jobjectArray> j_codec_profile_levels( |
206 Java_MediaCodecUtil_getSupportedCodecProfileLevels(env)); | 216 Java_MediaCodecUtil_getSupportedCodecProfileLevels(env)); |
207 int java_array_length = env->GetArrayLength(j_codec_profile_levels.obj()); | 217 int java_array_length = env->GetArrayLength(j_codec_profile_levels.obj()); |
208 for (int i = 0; i < java_array_length; ++i) { | 218 for (int i = 0; i < java_array_length; ++i) { |
209 const jobject& java_codec_profile_level = | 219 const jobject& java_codec_profile_level = |
210 env->GetObjectArrayElement(j_codec_profile_levels.obj(), i); | 220 env->GetObjectArrayElement(j_codec_profile_levels.obj(), i); |
211 result->push_back(MediaCodecProfileLevelToChromiumProfileLevel( | 221 result->push_back(MediaCodecProfileLevelToChromiumProfileLevel( |
212 env, java_codec_profile_level)); | 222 env, java_codec_profile_level)); |
213 } | 223 } |
214 return true; | 224 return true; |
215 } | 225 } |
216 | 226 |
217 // static | 227 // static |
218 bool MediaCodecUtil::IsKnownUnaccelerated(const std::string& android_mime_type, | 228 bool MediaCodecUtil::IsKnownUnaccelerated(VideoCodec codec, |
219 MediaCodecDirection direction) { | 229 MediaCodecDirection direction) { |
220 DCHECK(IsSupportedAndroidMimeType(android_mime_type)); | |
221 if (!IsMediaCodecAvailable()) | 230 if (!IsMediaCodecAvailable()) |
222 return true; | 231 return true; |
223 | 232 |
224 std::string codec_name = | 233 std::string codec_name = |
225 GetDefaultCodecName(android_mime_type, direction, false); | 234 GetDefaultCodecName(CodecToAndroidMimeType(codec), direction, false); |
226 DVLOG(1) << __func__ << "Default codec for " << android_mime_type << " : " | 235 DVLOG(1) << __func__ << "Default codec for " << GetCodecName(codec) << " : " |
227 << codec_name << ", direction: " << direction; | 236 << codec_name << ", direction: " << static_cast<int>(direction); |
228 if (codec_name.empty()) | 237 if (codec_name.empty()) |
229 return true; | 238 return true; |
230 | 239 |
231 // MediaTek hardware vp8 is known slower than the software implementation. | 240 // MediaTek hardware vp8 is known slower than the software implementation. |
232 // MediaTek hardware vp9 is known crashy, see http://crbug.com/446974 and | 241 // MediaTek hardware vp9 is known crashy, see http://crbug.com/446974 and |
233 // http://crbug.com/597836. | 242 // http://crbug.com/597836. |
234 if (base::StartsWith(codec_name, "OMX.MTK.", base::CompareCase::SENSITIVE)) { | 243 if (base::StartsWith(codec_name, "OMX.MTK.", base::CompareCase::SENSITIVE)) { |
235 if (android_mime_type == kVp8MimeType) | 244 if (codec == kCodecVP8) |
236 return true; | 245 return true; |
237 | 246 |
238 if (android_mime_type == kVp9MimeType) | 247 if (codec == kCodecVP9) |
239 return base::android::BuildInfo::GetInstance()->sdk_int() < 21; | 248 return base::android::BuildInfo::GetInstance()->sdk_int() < 21; |
240 | 249 |
241 return false; | 250 return false; |
242 } | 251 } |
243 | 252 |
244 // It would be nice if MediaCodecInfo externalized some notion of | 253 // It would be nice if MediaCodecInfo externalized some notion of |
245 // HW-acceleration but it doesn't. Android Media guidance is that the | 254 // HW-acceleration but it doesn't. Android Media guidance is that the |
246 // "OMX.google" prefix is always used for SW decoders, so that's what we | 255 // "OMX.google" prefix is always used for SW decoders, so that's what we |
247 // use. "OMX.SEC.*" codec is Samsung software implementation - report it | 256 // use. "OMX.SEC.*" codec is Samsung software implementation - report it |
248 // as unaccelerated as well. | 257 // as unaccelerated as well. |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
326 (sdk_int == 18 && ("OMX.SEC.avc.dec" == codec_name || | 335 (sdk_int == 18 && ("OMX.SEC.avc.dec" == codec_name || |
327 "OMX.SEC.avc.dec.secure" == codec_name)) || | 336 "OMX.SEC.avc.dec.secure" == codec_name)) || |
328 (sdk_int == 19 && | 337 (sdk_int == 19 && |
329 base::StartsWith(base::android::BuildInfo::GetInstance()->model(), | 338 base::StartsWith(base::android::BuildInfo::GetInstance()->model(), |
330 "SM-G800", base::CompareCase::INSENSITIVE_ASCII) && | 339 "SM-G800", base::CompareCase::INSENSITIVE_ASCII) && |
331 ("OMX.Exynos.avc.dec" == codec_name || | 340 ("OMX.Exynos.avc.dec" == codec_name || |
332 "OMX.Exynos.avc.dec.secure" == codec_name)); | 341 "OMX.Exynos.avc.dec.secure" == codec_name)); |
333 } | 342 } |
334 | 343 |
335 } // namespace media | 344 } // namespace media |
OLD | NEW |