Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(40)

Side by Side Diff: media/base/android/media_codec_util.cc

Issue 2697643003: media: Clean up MediaCodecBridge and remove subclasses (Closed)
Patch Set: Remove static initializers (thanks to dale's suggestion) Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 11 matching lines...) Expand all
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 31
32 namespace { 32 namespace mime_type {
liberato (no reviews please) 2017/02/14 17:44:11 these seem to be alternately named "android mime t
DaleCurtis 2017/02/14 18:10:32 I feel like these should share the values we have
watk 2017/02/14 23:28:57 I agree, but didn't see an obvious way to share, s
33 33 const char kMp3[] = "audio/mpeg";
34 const char kMp4aMimeType[] = "audio/mp4a-latm"; 34 const char kAac[] = "audio/mp4a-latm";
35 const char kOpusMimeType[] = "audio/opus"; 35 const char kOpus[] = "audio/opus";
36 const char kVorbisMimeType[] = "audio/vorbis"; 36 const char kVorbis[] = "audio/vorbis";
37 const char kAc3MimeType[] = "audio/ac3"; 37 const char kAc3[] = "audio/ac3";
38 const char kEac3MimeType[] = "audio/eac3"; 38 const char kEac3[] = "audio/eac3";
39 const char kAvcMimeType[] = "video/avc"; 39 const char kAvc[] = "video/avc";
40 const char kHevcMimeType[] = "video/hevc"; 40 const char kHevc[] = "video/hevc";
41 const char kVp8MimeType[] = "video/x-vnd.on2.vp8"; 41 const char kVp8[] = "video/x-vnd.on2.vp8";
42 const char kVp9MimeType[] = "video/x-vnd.on2.vp9"; 42 const char kVp9[] = "video/x-vnd.on2.vp9";
43 43 } // namespace mime_type
44 } // namespace
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) {
72 if (codec == "AVC")
73 return kCodecH264;
74 if (codec == "VP8")
75 return kCodecVP8;
76 if (codec == "VP9")
77 return kCodecVP9;
78 if (codec == "HEVC")
79 return kCodecHEVC;
80 DLOG(WARNING) << "Unknown video codec name \"" << codec << "\"";
81 return kUnknownVideoCodec;
82 }
83 44
84 static CodecProfileLevel MediaCodecProfileLevelToChromiumProfileLevel( 45 static CodecProfileLevel MediaCodecProfileLevelToChromiumProfileLevel(
85 JNIEnv* env, 46 JNIEnv* env,
86 const jobject& j_codec_profile_level) { 47 const jobject& j_codec_profile_level) {
87 ScopedJavaLocalRef<jstring> codec = 48 VideoCodec codec = static_cast<VideoCodec>(
88 Java_CodecProfileLevelAdapter_getCodec(env, j_codec_profile_level); 49 Java_CodecProfileLevelAdapter_getCodec(env, j_codec_profile_level));
89 int profile = 50 VideoCodecProfile profile = static_cast<VideoCodecProfile>(
90 Java_CodecProfileLevelAdapter_getProfile(env, j_codec_profile_level); 51 Java_CodecProfileLevelAdapter_getProfile(env, j_codec_profile_level));
91 int level = 52 int level =
92 Java_CodecProfileLevelAdapter_getLevel(env, j_codec_profile_level); 53 Java_CodecProfileLevelAdapter_getLevel(env, j_codec_profile_level);
93 return {AndroidCodecToCodecEnum(ConvertJavaStringToUTF8(codec)), 54 return {codec, profile, level};
94 static_cast<VideoCodecProfile>(profile), level};
95 } 55 }
96 56
97 static bool IsSupportedAndroidMimeType(const std::string& mime_type) { 57 static bool IsSupportedAndroidMimeType(const std::string& mime_type) {
98 std::vector<std::string> supported{ 58 std::vector<std::string> supported{
99 kMp4aMimeType, kOpusMimeType, kVorbisMimeType, kAvcMimeType, 59 mime_type::kMp3, mime_type::kAac, mime_type::kOpus, mime_type::kVorbis,
watk 2017/02/14 23:35:56 I added mp3 here, because I didn't know why it wou
DaleCurtis 2017/02/14 23:44:43 Probably because there are no protected content mp
100 kHevcMimeType, kVp8MimeType, kVp9MimeType}; 60 mime_type::kAvc, mime_type::kHevc, mime_type::kVp8, mime_type::kVp9};
101 return std::find(supported.begin(), supported.end(), mime_type) != 61 return std::find(supported.begin(), supported.end(), mime_type) !=
102 supported.end(); 62 supported.end();
103 } 63 }
104 64
105 static std::string GetDefaultCodecName(const std::string& mime_type, 65 static std::string GetDefaultCodecName(const std::string& mime_type,
106 MediaCodecDirection direction, 66 MediaCodecDirection direction,
107 bool require_software_codec) { 67 bool require_software_codec) {
108 DCHECK(MediaCodecUtil::IsMediaCodecAvailable()); 68 DCHECK(MediaCodecUtil::IsMediaCodecAvailable());
109 JNIEnv* env = AttachCurrentThread(); 69 JNIEnv* env = AttachCurrentThread();
110 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime_type); 70 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime_type);
111 ScopedJavaLocalRef<jstring> j_codec_name = 71 ScopedJavaLocalRef<jstring> j_codec_name =
112 Java_MediaCodecUtil_getDefaultCodecName(env, j_mime, direction, 72 Java_MediaCodecUtil_getDefaultCodecName(
113 require_software_codec); 73 env, j_mime, static_cast<int>(direction), require_software_codec);
114 return ConvertJavaStringToUTF8(env, j_codec_name.obj()); 74 return ConvertJavaStringToUTF8(env, j_codec_name.obj());
115 } 75 }
116 76
117 static bool IsDecoderSupportedByDevice(const std::string& android_mime_type) { 77 static bool IsDecoderSupportedByDevice(const std::string& android_mime_type) {
118 DCHECK(MediaCodecUtil::IsMediaCodecAvailable()); 78 DCHECK(MediaCodecUtil::IsMediaCodecAvailable());
119 DCHECK(IsSupportedAndroidMimeType(android_mime_type)); 79 DCHECK(IsSupportedAndroidMimeType(android_mime_type));
120 JNIEnv* env = AttachCurrentThread(); 80 JNIEnv* env = AttachCurrentThread();
121 ScopedJavaLocalRef<jstring> j_mime = 81 ScopedJavaLocalRef<jstring> j_mime =
122 ConvertUTF8ToJavaString(env, android_mime_type); 82 ConvertUTF8ToJavaString(env, android_mime_type);
123 return Java_MediaCodecUtil_isDecoderSupportedForDevice(env, j_mime); 83 return Java_MediaCodecUtil_isDecoderSupportedForDevice(env, j_mime);
124 } 84 }
125 85
126 static bool IsEncoderSupportedByDevice(const std::string& android_mime_type) { 86 static bool IsEncoderSupportedByDevice(const std::string& android_mime_type) {
127 DCHECK(MediaCodecUtil::IsMediaCodecAvailable()); 87 DCHECK(MediaCodecUtil::IsMediaCodecAvailable());
128 JNIEnv* env = AttachCurrentThread(); 88 JNIEnv* env = AttachCurrentThread();
129 ScopedJavaLocalRef<jstring> j_mime = 89 ScopedJavaLocalRef<jstring> j_mime =
130 ConvertUTF8ToJavaString(env, android_mime_type); 90 ConvertUTF8ToJavaString(env, android_mime_type);
131 return Java_MediaCodecUtil_isEncoderSupportedByDevice(env, j_mime); 91 return Java_MediaCodecUtil_isEncoderSupportedByDevice(env, j_mime);
132 } 92 }
133 93
134 // static 94 // static
95 std::string MediaCodecUtil::CodecToAndroidMimeType(AudioCodec codec) {
96 switch (codec) {
97 case kCodecMP3:
98 return mime_type::kMp3;
99 case kCodecVorbis:
100 return mime_type::kVorbis;
101 case kCodecOpus:
102 return mime_type::kOpus;
103 case kCodecAAC:
104 return mime_type::kAac;
105 case kCodecAC3:
106 return mime_type::kAc3;
107 case kCodecEAC3:
108 return mime_type::kEac3;
109 default:
110 return std::string();
111 }
112 }
113
114 // static
115 std::string MediaCodecUtil::CodecToAndroidMimeType(VideoCodec codec) {
116 switch (codec) {
117 case kCodecH264:
118 return mime_type::kAvc;
119 case kCodecHEVC:
120 return mime_type::kHevc;
121 case kCodecVP8:
122 return mime_type::kVp8;
123 case kCodecVP9:
124 return mime_type::kVp9;
125 default:
126 return std::string();
127 }
128 }
129
130 // static
135 bool MediaCodecUtil::IsMediaCodecAvailable() { 131 bool MediaCodecUtil::IsMediaCodecAvailable() {
136 // Blacklist some devices on Jellybean as MediaCodec is buggy. 132 // Blacklist some devices on Jellybean as MediaCodec is buggy.
137 // http://crbug.com/365494, http://crbug.com/615872 133 // http://crbug.com/365494, http://crbug.com/615872
138 // Blacklist Lenovo A6600 / A6800 on KitKat, which tends to crash a lot. 134 // 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. 135 // See crbug.com/628059 . We include < K since they don't exist.
140 // Blacklist Samsung Galaxy Star Pro (GT-S7262) (crbug.com/634920). 136 // Blacklist Samsung Galaxy Star Pro (GT-S7262) (crbug.com/634920).
141 // GT-S5282 and GT-I8552 are for crbug.com/634920 . 137 // GT-S5282 and GT-I8552 are for crbug.com/634920 .
142 if (base::android::BuildInfo::GetInstance()->sdk_int() <= 19) { 138 if (base::android::BuildInfo::GetInstance()->sdk_int() <= 19) {
143 std::string model(base::android::BuildInfo::GetInstance()->model()); 139 std::string model(base::android::BuildInfo::GetInstance()->model());
144 return model != "GT-I9100" && model != "GT-I9300" && model != "GT-N7000" && 140 return model != "GT-I9100" && model != "GT-I9300" && model != "GT-N7000" &&
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
176 if (j_color_format_array.obj()) { 172 if (j_color_format_array.obj()) {
177 std::vector<int> formats; 173 std::vector<int> formats;
178 JavaIntArrayToIntVector(env, j_color_format_array.obj(), &formats); 174 JavaIntArrayToIntVector(env, j_color_format_array.obj(), &formats);
179 color_formats = std::set<int>(formats.begin(), formats.end()); 175 color_formats = std::set<int>(formats.begin(), formats.end());
180 } 176 }
181 177
182 return color_formats; 178 return color_formats;
183 } 179 }
184 180
185 // static 181 // static
186 bool MediaCodecUtil::CanDecode(const std::string& codec, bool is_secure) { 182 bool MediaCodecUtil::CanDecode(const std::string& mime, bool is_secure) {
187 if (!IsMediaCodecAvailable()) 183 if (!IsMediaCodecAvailable())
188 return false; 184 return false;
185 if (mime.empty())
186 return false;
189 187
190 JNIEnv* env = AttachCurrentThread(); 188 JNIEnv* env = AttachCurrentThread();
191 std::string mime = CodecTypeToAndroidMimeType(codec);
192 if (mime.empty())
193 return false;
194 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime); 189 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
195 return Java_MediaCodecUtil_canDecode(env, j_mime, is_secure); 190 return Java_MediaCodecUtil_canDecode(env, j_mime, is_secure);
196 } 191 }
197 192
198 // static 193 // static
199 bool MediaCodecUtil::AddSupportedCodecProfileLevels( 194 bool MediaCodecUtil::AddSupportedCodecProfileLevels(
200 std::vector<CodecProfileLevel>* result) { 195 std::vector<CodecProfileLevel>* result) {
201 DCHECK(result); 196 DCHECK(result);
202 if (!IsMediaCodecAvailable()) 197 if (!IsMediaCodecAvailable())
203 return false; 198 return false;
204 JNIEnv* env = AttachCurrentThread(); 199 JNIEnv* env = AttachCurrentThread();
205 ScopedJavaLocalRef<jobjectArray> j_codec_profile_levels( 200 ScopedJavaLocalRef<jobjectArray> j_codec_profile_levels(
206 Java_MediaCodecUtil_getSupportedCodecProfileLevels(env)); 201 Java_MediaCodecUtil_getSupportedCodecProfileLevels(env));
207 int java_array_length = env->GetArrayLength(j_codec_profile_levels.obj()); 202 int java_array_length = env->GetArrayLength(j_codec_profile_levels.obj());
208 for (int i = 0; i < java_array_length; ++i) { 203 for (int i = 0; i < java_array_length; ++i) {
209 const jobject& java_codec_profile_level = 204 const jobject& java_codec_profile_level =
210 env->GetObjectArrayElement(j_codec_profile_levels.obj(), i); 205 env->GetObjectArrayElement(j_codec_profile_levels.obj(), i);
211 result->push_back(MediaCodecProfileLevelToChromiumProfileLevel( 206 result->push_back(MediaCodecProfileLevelToChromiumProfileLevel(
212 env, java_codec_profile_level)); 207 env, java_codec_profile_level));
213 } 208 }
214 return true; 209 return true;
215 } 210 }
216 211
217 // static 212 // static
218 bool MediaCodecUtil::IsKnownUnaccelerated(const std::string& android_mime_type, 213 bool MediaCodecUtil::IsKnownUnaccelerated(VideoCodec codec,
219 MediaCodecDirection direction) { 214 MediaCodecDirection direction) {
220 DCHECK(IsSupportedAndroidMimeType(android_mime_type));
221 if (!IsMediaCodecAvailable()) 215 if (!IsMediaCodecAvailable())
222 return true; 216 return true;
223 217
224 std::string codec_name = 218 std::string codec_name =
225 GetDefaultCodecName(android_mime_type, direction, false); 219 GetDefaultCodecName(CodecToAndroidMimeType(codec), direction, false);
226 DVLOG(1) << __func__ << "Default codec for " << android_mime_type << " : " 220 DVLOG(1) << __func__ << "Default codec for " << GetCodecName(codec) << " : "
227 << codec_name << ", direction: " << direction; 221 << codec_name << ", direction: " << static_cast<int>(direction);
228 if (codec_name.empty()) 222 if (codec_name.empty())
229 return true; 223 return true;
230 224
231 // MediaTek hardware vp8 is known slower than the software implementation. 225 // MediaTek hardware vp8 is known slower than the software implementation.
232 // MediaTek hardware vp9 is known crashy, see http://crbug.com/446974 and 226 // MediaTek hardware vp9 is known crashy, see http://crbug.com/446974 and
233 // http://crbug.com/597836. 227 // http://crbug.com/597836.
234 if (base::StartsWith(codec_name, "OMX.MTK.", base::CompareCase::SENSITIVE)) { 228 if (base::StartsWith(codec_name, "OMX.MTK.", base::CompareCase::SENSITIVE)) {
235 if (android_mime_type == kVp8MimeType) 229 if (codec == kCodecVP8)
236 return true; 230 return true;
237 231
238 if (android_mime_type == kVp9MimeType) 232 if (codec == kCodecVP9)
239 return base::android::BuildInfo::GetInstance()->sdk_int() < 21; 233 return base::android::BuildInfo::GetInstance()->sdk_int() < 21;
240 234
241 return false; 235 return false;
242 } 236 }
243 237
244 // It would be nice if MediaCodecInfo externalized some notion of 238 // It would be nice if MediaCodecInfo externalized some notion of
245 // HW-acceleration but it doesn't. Android Media guidance is that the 239 // 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 240 // "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 241 // use. "OMX.SEC.*" codec is Samsung software implementation - report it
248 // as unaccelerated as well. 242 // as unaccelerated as well.
(...skipping 10 matching lines...) Expand all
259 } 253 }
260 254
261 // static 255 // static
262 bool MediaCodecUtil::IsHLSURL(const GURL& url) { 256 bool MediaCodecUtil::IsHLSURL(const GURL& url) {
263 return (url.SchemeIsHTTPOrHTTPS() || url.SchemeIsFile()) && 257 return (url.SchemeIsHTTPOrHTTPS() || url.SchemeIsFile()) &&
264 url.spec().find("m3u8") != std::string::npos; 258 url.spec().find("m3u8") != std::string::npos;
265 } 259 }
266 260
267 // static 261 // static
268 bool MediaCodecUtil::IsVp8DecoderAvailable() { 262 bool MediaCodecUtil::IsVp8DecoderAvailable() {
269 return IsMediaCodecAvailable() && IsDecoderSupportedByDevice(kVp8MimeType); 263 return IsMediaCodecAvailable() && IsDecoderSupportedByDevice(mime_type::kVp8);
270 } 264 }
271 265
272 // static 266 // static
273 bool MediaCodecUtil::IsVp8EncoderAvailable() { 267 bool MediaCodecUtil::IsVp8EncoderAvailable() {
274 // Currently the vp8 encoder and decoder blacklists cover the same devices, 268 // Currently the vp8 encoder and decoder blacklists cover the same devices,
275 // but we have a second method for clarity in future issues. 269 // but we have a second method for clarity in future issues.
276 return IsVp8DecoderAvailable(); 270 return IsVp8DecoderAvailable();
277 } 271 }
278 272
279 // static 273 // static
280 bool MediaCodecUtil::IsVp9DecoderAvailable() { 274 bool MediaCodecUtil::IsVp9DecoderAvailable() {
281 return IsMediaCodecAvailable() && IsDecoderSupportedByDevice(kVp9MimeType); 275 return IsMediaCodecAvailable() && IsDecoderSupportedByDevice(mime_type::kVp9);
282 } 276 }
283 277
284 // static 278 // static
285 bool MediaCodecUtil::IsH264EncoderAvailable() { 279 bool MediaCodecUtil::IsH264EncoderAvailable() {
286 return IsMediaCodecAvailable() && IsEncoderSupportedByDevice(kAvcMimeType); 280 return IsMediaCodecAvailable() && IsEncoderSupportedByDevice(mime_type::kAvc);
287 } 281 }
288 282
289 // static 283 // static
290 bool MediaCodecUtil::IsSurfaceViewOutputSupported() { 284 bool MediaCodecUtil::IsSurfaceViewOutputSupported() {
291 // Disable SurfaceView output for the Samsung Galaxy S3; it does not work 285 // Disable SurfaceView output for the Samsung Galaxy S3; it does not work
292 // well enough for even 360p24 H264 playback. http://crbug.com/602870. 286 // well enough for even 360p24 H264 playback. http://crbug.com/602870.
293 // 287 //
294 // Notably this is codec agnostic at present, so any devices added to 288 // Notably this is codec agnostic at present, so any devices added to
295 // the blacklist will avoid trying to play any codecs on SurfaceView. If 289 // the blacklist will avoid trying to play any codecs on SurfaceView. If
296 // needed in the future this can be expanded to be codec specific. 290 // needed in the future this can be expanded to be codec specific.
(...skipping 29 matching lines...) Expand all
326 (sdk_int == 18 && ("OMX.SEC.avc.dec" == codec_name || 320 (sdk_int == 18 && ("OMX.SEC.avc.dec" == codec_name ||
327 "OMX.SEC.avc.dec.secure" == codec_name)) || 321 "OMX.SEC.avc.dec.secure" == codec_name)) ||
328 (sdk_int == 19 && 322 (sdk_int == 19 &&
329 base::StartsWith(base::android::BuildInfo::GetInstance()->model(), 323 base::StartsWith(base::android::BuildInfo::GetInstance()->model(),
330 "SM-G800", base::CompareCase::INSENSITIVE_ASCII) && 324 "SM-G800", base::CompareCase::INSENSITIVE_ASCII) &&
331 ("OMX.Exynos.avc.dec" == codec_name || 325 ("OMX.Exynos.avc.dec" == codec_name ||
332 "OMX.Exynos.avc.dec.secure" == codec_name)); 326 "OMX.Exynos.avc.dec.secure" == codec_name));
333 } 327 }
334 328
335 } // namespace media 329 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698