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

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

Issue 1472943002: Refactor MediaCodecBridge to add support for NDK APIs (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: addressing comments Created 5 years 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "media/base/android/media_codec_util.h"
6
7 #include <algorithm>
8
9 #include "base/android/build_info.h"
10 #include "base/android/jni_android.h"
11 #include "base/android/jni_array.h"
12 #include "base/android/jni_string.h"
13 #include "base/basictypes.h"
14 #include "base/logging.h"
15 #include "base/strings/string_util.h"
16 #include "jni/MediaCodecUtil_jni.h"
17
18 using base::android::AttachCurrentThread;
19 using base::android::ConvertJavaStringToUTF8;
20 using base::android::ConvertUTF8ToJavaString;
21 using base::android::JavaIntArrayToIntVector;
22 using base::android::ScopedJavaLocalRef;
23
24 namespace media {
25
26 // static
27 const std::string CodecTypeToAndroidMimeType(
28 const std::string& codec) {
29 // TODO(xhwang): Shall we handle more detailed strings like "mp4a.40.2"?
30 if (codec == "avc1")
31 return "video/avc";
32 if (codec == "hvc1")
33 return "video/hevc";
34 if (codec == "mp4a")
35 return "audio/mp4a-latm";
36 if (codec == "vp8" || codec == "vp8.0")
37 return "video/x-vnd.on2.vp8";
38 if (codec == "vp9" || codec == "vp9.0")
39 return "video/x-vnd.on2.vp9";
40 if (codec == "vorbis")
41 return "audio/vorbis";
42 if (codec == "opus")
43 return "audio/opus";
44 return std::string();
45 }
46
47 // TODO(qinmin): using a map to help all the conversions in this class.
48 const std::string AndroidMimeTypeToCodecType(
49 const std::string& mime) {
50 if (mime == "video/mp4v-es")
51 return "mp4v";
52 if (mime == "video/avc")
53 return "avc1";
54 if (mime == "video/hevc")
55 return "hvc1";
56 if (mime == "video/x-vnd.on2.vp8")
57 return "vp8";
58 if (mime == "video/x-vnd.on2.vp9")
59 return "vp9";
60 if (mime == "audio/mp4a-latm")
61 return "mp4a";
62 if (mime == "audio/mpeg")
63 return "mp3";
64 if (mime == "audio/vorbis")
65 return "vorbis";
66 if (mime == "audio/opus")
67 return "opus";
68 return std::string();
69 }
70
71 std::string GetDefaultCodecName(
72 const std::string& mime_type,
73 MediaCodecDirection direction) {
74 if (!MediaCodecUtil::IsMediaCodecAvailable())
75 return std::string();
76
77 JNIEnv* env = AttachCurrentThread();
78 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime_type);
79 ScopedJavaLocalRef<jstring> j_codec_name =
80 Java_MediaCodecUtil_getDefaultCodecName(env, j_mime.obj(), direction);
81 return ConvertJavaStringToUTF8(env, j_codec_name.obj());
82 }
83
84 bool SupportsGetName() {
85 // MediaCodec.getName() is only available on JB MR2 and greater.
86 return base::android::BuildInfo::GetInstance()->sdk_int() >= 18;
87 }
88
89 // Represents supported codecs on android.
90 // TODO(qinmin): Currently the codecs string only contains one codec. Do we
91 // need to support codecs separated by comma. (e.g. "vp8" -> "vp8, vp8.0")?
92 struct CodecsInfo {
93 std::string codecs; // E.g. "vp8" or "avc1".
94 std::string name; // E.g. "OMX.google.vp8.decoder".
95 MediaCodecDirection direction;
96 };
97
98 // Get a list of supported codecs.
99 std::vector<CodecsInfo> GetCodecsInfo() {
100 std::vector<CodecsInfo> codecs_info;
101 if (!MediaCodecUtil::IsMediaCodecAvailable())
102 return codecs_info;
103
104 JNIEnv* env = AttachCurrentThread();
105 std::string mime_type;
106 ScopedJavaLocalRef<jobjectArray> j_codec_info_array =
107 Java_MediaCodecUtil_getCodecsInfo(env);
108 jsize len = env->GetArrayLength(j_codec_info_array.obj());
109 for (jsize i = 0; i < len; ++i) {
110 ScopedJavaLocalRef<jobject> j_info(
111 env, env->GetObjectArrayElement(j_codec_info_array.obj(), i));
112 ScopedJavaLocalRef<jstring> j_codec_type =
113 Java_CodecInfo_codecType(env, j_info.obj());
114 ConvertJavaStringToUTF8(env, j_codec_type.obj(), &mime_type);
115 ScopedJavaLocalRef<jstring> j_codec_name =
116 Java_CodecInfo_codecName(env, j_info.obj());
117 CodecsInfo info;
118 info.codecs = AndroidMimeTypeToCodecType(mime_type);
119 ConvertJavaStringToUTF8(env, j_codec_name.obj(), &info.name);
120 info.direction = static_cast<MediaCodecDirection>(
121 Java_CodecInfo_direction(env, j_info.obj()));
122 codecs_info.push_back(info);
123 }
124 return codecs_info;
125 }
126
127 // static
128 bool MediaCodecUtil::IsMediaCodecAvailable() {
129 // MediaCodec is only available on JB and greater.
130 if (base::android::BuildInfo::GetInstance()->sdk_int() < 16)
131 return false;
132 // Blacklist some devices on Jellybean as for MediaCodec support is buggy.
133 // http://crbug.com/365494.
134 if (base::android::BuildInfo::GetInstance()->sdk_int() == 16) {
135 std::string model(base::android::BuildInfo::GetInstance()->model());
136 return model != "GT-I9100" && model != "GT-I9300" && model != "GT-N7000";
137 }
138 return true;
139 }
140
141 // static
142 bool MediaCodecUtil::SupportsSetParameters() {
143 // MediaCodec.setParameters() is only available starting with K.
144 return base::android::BuildInfo::GetInstance()->sdk_int() >= 19;
145 }
146
147 // static
148 std::set<int> MediaCodecUtil::GetEncoderColorFormats(
149 const std::string& mime_type) {
150 std::set<int> color_formats;
151 if (!IsMediaCodecAvailable())
152 return color_formats;
153
154 JNIEnv* env = AttachCurrentThread();
155 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime_type);
156 ScopedJavaLocalRef<jintArray> j_color_format_array =
157 Java_MediaCodecUtil_getEncoderColorFormatsForMime(env, j_mime.obj());
158
159 if (j_color_format_array.obj()) {
160 std::vector<int> formats;
161 JavaIntArrayToIntVector(env, j_color_format_array.obj(), &formats);
162 color_formats = std::set<int>(formats.begin(), formats.end());
163 }
164
165 return color_formats;
166 }
167
168 // static
169 bool MediaCodecUtil::CanDecode(const std::string& codec, bool is_secure) {
170 if (!IsMediaCodecAvailable())
171 return false;
172
173 JNIEnv* env = AttachCurrentThread();
174 std::string mime = CodecTypeToAndroidMimeType(codec);
175 if (mime.empty())
176 return false;
177 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
178 return Java_MediaCodecUtil_canDecode(env, j_mime.obj(), is_secure);
179 }
180
181 // static
182 bool MediaCodecUtil::IsKnownUnaccelerated(const std::string& mime_type,
183 MediaCodecDirection direction) {
184 if (!IsMediaCodecAvailable())
185 return true;
186
187 std::string codec_name;
188 if (SupportsGetName()) {
189 codec_name = GetDefaultCodecName(mime_type, direction);
190 } else {
191 std::string codec_type = AndroidMimeTypeToCodecType(mime_type);
192 std::vector<CodecsInfo> codecs_info = GetCodecsInfo();
193 for (size_t i = 0; i < codecs_info.size(); ++i) {
194 if (codecs_info[i].codecs == codec_type &&
195 codecs_info[i].direction == direction) {
196 codec_name = codecs_info[i].name;
197 break;
198 }
199 }
200 }
201 DVLOG(1) << __PRETTY_FUNCTION__ << "Default codec for " << mime_type <<
202 " : " << codec_name;
203 // It would be nice if MediaCodecInfo externalized some notion of
204 // HW-acceleration but it doesn't. Android Media guidance is that the
205 // "OMX.google" prefix is always used for SW decoders, so that's what we
206 // use. "OMX.SEC.*" codec is Samsung software implementation - report it
207 // as unaccelerated as well. Also temporary blacklist Exynos and MediaTek
208 // devices while HW decoder video freezes and distortions are
209 // investigated - http://crbug.com/446974.
210 if (codec_name.length() > 0) {
211 return (base::StartsWith(codec_name, "OMX.google.",
212 base::CompareCase::SENSITIVE) ||
213 base::StartsWith(codec_name, "OMX.SEC.",
214 base::CompareCase::SENSITIVE) ||
215 base::StartsWith(codec_name, "OMX.MTK.",
216 base::CompareCase::SENSITIVE) ||
217 base::StartsWith(codec_name, "OMX.Exynos.",
218 base::CompareCase::SENSITIVE));
219 }
220 return true;
221 }
222
223 // static
224 bool MediaCodecUtil::RegisterMediaCodecUtil(JNIEnv* env) {
225 return RegisterNativesImpl(env);
226 }
227
228 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698