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

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

Issue 74563002: AndroidVideoEncodeAccelerator is born! (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 7 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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_bridge.h" 5 #include "media/base/android/media_codec_bridge.h"
6 6
7 #include <jni.h> 7 #include <jni.h>
8 #include <string> 8 #include <string>
9 9
10 #include "base/android/build_info.h" 10 #include "base/android/build_info.h"
(...skipping 10 matching lines...) Expand all
21 #include "media/base/bit_reader.h" 21 #include "media/base/bit_reader.h"
22 #include "media/base/decrypt_config.h" 22 #include "media/base/decrypt_config.h"
23 23
24 using base::android::AttachCurrentThread; 24 using base::android::AttachCurrentThread;
25 using base::android::ConvertJavaStringToUTF8; 25 using base::android::ConvertJavaStringToUTF8;
26 using base::android::ConvertUTF8ToJavaString; 26 using base::android::ConvertUTF8ToJavaString;
27 using base::android::ScopedJavaLocalRef; 27 using base::android::ScopedJavaLocalRef;
28 28
29 namespace media { 29 namespace media {
30 30
31 enum { kBufferFlagEndOfStream = 4 }; 31 enum {
32 kBufferFlagSyncFrame = 1, // BUFFER_FLAG_SYNC_FRAME
33 kBufferFlagEndOfStream = 4, // BUFFER_FLAG_END_OF_STREAM
34 kConfigureFlagEncode = 1, // CONFIGURE_FLAG_ENCODE
35 };
32 36
33 static const std::string AudioCodecToAndroidMimeType(const AudioCodec& codec) { 37 static const std::string AudioCodecToAndroidMimeType(const AudioCodec& codec) {
34 switch (codec) { 38 switch (codec) {
35 case kCodecMP3: 39 case kCodecMP3:
36 return "audio/mpeg"; 40 return "audio/mpeg";
37 case kCodecVorbis: 41 case kCodecVorbis:
38 return "audio/vorbis"; 42 return "audio/vorbis";
39 case kCodecAAC: 43 case kCodecAAC:
40 return "audio/mp4a-latm"; 44 return "audio/mp4a-latm";
41 default: 45 default:
(...skipping 15 matching lines...) Expand all
57 } 61 }
58 62
59 static const std::string CodecTypeToAndroidMimeType(const std::string& codec) { 63 static const std::string CodecTypeToAndroidMimeType(const std::string& codec) {
60 // TODO(xhwang): Shall we handle more detailed strings like "mp4a.40.2"? 64 // TODO(xhwang): Shall we handle more detailed strings like "mp4a.40.2"?
61 if (codec == "avc1") 65 if (codec == "avc1")
62 return "video/avc"; 66 return "video/avc";
63 if (codec == "mp4a") 67 if (codec == "mp4a")
64 return "audio/mp4a-latm"; 68 return "audio/mp4a-latm";
65 if (codec == "vp8" || codec == "vp8.0") 69 if (codec == "vp8" || codec == "vp8.0")
66 return "video/x-vnd.on2.vp8"; 70 return "video/x-vnd.on2.vp8";
67 if (codec == "vp9" || codec == "vp9.0") 71 if (codec == "vp9" || codec == "vp9.0")
68 return "video/x-vnd.on2.vp9"; 72 return "video/x-vnd.on2.vp9";
69 if (codec == "vorbis") 73 if (codec == "vorbis")
70 return "audio/vorbis"; 74 return "audio/vorbis";
71 return std::string(); 75 return std::string();
72 } 76 }
73 77
74 // TODO(qinmin): using a map to help all the conversions in this class. 78 // TODO(qinmin): using a map to help all the conversions in this class.
75 static const std::string AndroidMimeTypeToCodecType(const std::string& mime) { 79 static const std::string AndroidMimeTypeToCodecType(const std::string& mime) {
76 if (mime == "video/mp4v-es") 80 if (mime == "video/mp4v-es")
77 return "mp4v"; 81 return "mp4v";
78 if (mime == "video/avc") 82 if (mime == "video/avc")
79 return "avc1"; 83 return "avc1";
80 if (mime == "video/x-vnd.on2.vp8") 84 if (mime == "video/x-vnd.on2.vp8")
81 return "vp8"; 85 return "vp8";
82 if (mime == "video/x-vnd.on2.vp9") 86 if (mime == "video/x-vnd.on2.vp9")
83 return "vp9"; 87 return "vp9";
84 if (mime == "audio/mp4a-latm") 88 if (mime == "audio/mp4a-latm")
85 return "mp4a"; 89 return "mp4a";
86 if (mime == "audio/mpeg") 90 if (mime == "audio/mpeg")
87 return "mp3"; 91 return "mp3";
88 if (mime == "audio/vorbis") 92 if (mime == "audio/vorbis")
89 return "vorbis"; 93 return "vorbis";
90 return std::string(); 94 return std::string();
91 } 95 }
92 96
93 static ScopedJavaLocalRef<jintArray> ToJavaIntArray( 97 static ScopedJavaLocalRef<jintArray>
94 JNIEnv* env, scoped_ptr<jint[]> native_array, int size) { 98 ToJavaIntArray(JNIEnv* env, scoped_ptr<jint[]> native_array, int size) {
95 ScopedJavaLocalRef<jintArray> j_array(env, env->NewIntArray(size)); 99 ScopedJavaLocalRef<jintArray> j_array(env, env->NewIntArray(size));
96 env->SetIntArrayRegion(j_array.obj(), 0, size, native_array.get()); 100 env->SetIntArrayRegion(j_array.obj(), 0, size, native_array.get());
97 return j_array; 101 return j_array;
98 } 102 }
99 103
100 // static 104 // static
101 bool MediaCodecBridge::IsAvailable() { 105 bool MediaCodecBridge::IsAvailable() {
102 // MediaCodec is only available on JB and greater. 106 // MediaCodec is only available on JB and greater.
103 return base::android::BuildInfo::GetInstance()->sdk_int() >= 16; 107 return base::android::BuildInfo::GetInstance()->sdk_int() >= 16;
104 } 108 }
105 109
106 // static 110 // static
107 void MediaCodecBridge::GetCodecsInfo( 111 bool MediaCodecBridge::SupportsSetParameters() {
108 std::vector<CodecsInfo>* codecs_info) { 112 // MediaCodec.setParameters() is only available starting with K.
113 return base::android::BuildInfo::GetInstance()->sdk_int() >= 19;
114 }
115
116 // static
117 std::vector<MediaCodecBridge::CodecsInfo> MediaCodecBridge::GetCodecsInfo() {
118 std::vector<CodecsInfo> codecs_info;
109 JNIEnv* env = AttachCurrentThread(); 119 JNIEnv* env = AttachCurrentThread();
110 if (!IsAvailable()) 120 if (!IsAvailable())
111 return; 121 return codecs_info;
112 122
113 std::string mime_type; 123 std::string mime_type;
114 std::string codec_name; 124 std::string codec_name;
115 ScopedJavaLocalRef<jobjectArray> j_codec_info_array = 125 ScopedJavaLocalRef<jobjectArray> j_codec_info_array =
116 Java_MediaCodecBridge_getCodecsInfo(env); 126 Java_MediaCodecBridge_getCodecsInfo(env);
117 jsize len = env->GetArrayLength(j_codec_info_array.obj()); 127 jsize len = env->GetArrayLength(j_codec_info_array.obj());
118 for (jsize i = 0; i < len; ++i) { 128 for (jsize i = 0; i < len; ++i) {
119 ScopedJavaLocalRef<jobject> j_info( 129 ScopedJavaLocalRef<jobject> j_info(
120 env, env->GetObjectArrayElement(j_codec_info_array.obj(), i)); 130 env, env->GetObjectArrayElement(j_codec_info_array.obj(), i));
121 ScopedJavaLocalRef<jstring> j_codec_type = 131 ScopedJavaLocalRef<jstring> j_codec_type =
122 Java_CodecInfo_codecType(env, j_info.obj()); 132 Java_CodecInfo_codecType(env, j_info.obj());
123 ConvertJavaStringToUTF8(env, j_codec_type.obj(), &mime_type); 133 ConvertJavaStringToUTF8(env, j_codec_type.obj(), &mime_type);
124 ScopedJavaLocalRef<jstring> j_codec_name = 134 ScopedJavaLocalRef<jstring> j_codec_name =
125 Java_CodecInfo_codecName(env, j_info.obj()); 135 Java_CodecInfo_codecName(env, j_info.obj());
126 CodecsInfo info; 136 CodecsInfo info;
127 info.codecs = AndroidMimeTypeToCodecType(mime_type); 137 info.codecs = AndroidMimeTypeToCodecType(mime_type);
128 ConvertJavaStringToUTF8(env, j_codec_name.obj(), &info.name); 138 ConvertJavaStringToUTF8(env, j_codec_name.obj(), &info.name);
129 codecs_info->push_back(info); 139 info.direction = static_cast<MediaCodecDirection>(
140 Java_CodecInfo_direction(env, j_info.obj()));
141 codecs_info.push_back(info);
130 } 142 }
143 return codecs_info;
131 } 144 }
132 145
133 // static 146 // static
134 bool MediaCodecBridge::CanDecode(const std::string& codec, bool is_secure) { 147 bool MediaCodecBridge::CanDecode(const std::string& codec, bool is_secure) {
135 JNIEnv* env = AttachCurrentThread(); 148 JNIEnv* env = AttachCurrentThread();
136 std::string mime = CodecTypeToAndroidMimeType(codec); 149 std::string mime = CodecTypeToAndroidMimeType(codec);
137 if (mime.empty()) 150 if (mime.empty())
138 return false; 151 return false;
139 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime); 152 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
140 ScopedJavaLocalRef<jobject> j_media_codec_bridge = 153 ScopedJavaLocalRef<jobject> j_media_codec_bridge =
141 Java_MediaCodecBridge_create(env, j_mime.obj(), is_secure); 154 Java_MediaCodecBridge_create(env, j_mime.obj(), is_secure, false);
142 if (!j_media_codec_bridge.is_null()) { 155 if (!j_media_codec_bridge.is_null()) {
143 Java_MediaCodecBridge_release(env, j_media_codec_bridge.obj()); 156 Java_MediaCodecBridge_release(env, j_media_codec_bridge.obj());
144 return true; 157 return true;
145 } 158 }
146 return false; 159 return false;
147 } 160 }
148 161
149 // static 162 // static
150 bool MediaCodecBridge::IsKnownUnaccelerated(const std::string& mime_type) { 163 bool MediaCodecBridge::IsKnownUnaccelerated(const std::string& mime_type,
164 MediaCodecDirection direction) {
151 std::string codec_type = AndroidMimeTypeToCodecType(mime_type); 165 std::string codec_type = AndroidMimeTypeToCodecType(mime_type);
152 std::vector<media::MediaCodecBridge::CodecsInfo> codecs_info; 166 std::vector<media::MediaCodecBridge::CodecsInfo> codecs_info =
153 media::MediaCodecBridge::GetCodecsInfo(&codecs_info); 167 MediaCodecBridge::GetCodecsInfo();
154 for (size_t i = 0; i < codecs_info.size(); ++i) { 168 for (size_t i = 0; i < codecs_info.size(); ++i) {
155 if (codecs_info[i].codecs == codec_type) { 169 if (codecs_info[i].codecs == codec_type &&
170 codecs_info[i].direction == direction) {
156 // It would be nice if MediaCodecInfo externalized some notion of 171 // It would be nice if MediaCodecInfo externalized some notion of
157 // HW-acceleration but it doesn't. Android Media guidance is that the 172 // HW-acceleration but it doesn't. Android Media guidance is that the
158 // prefix below is always used for SW decoders, so that's what we use. 173 // prefix below is always used for SW decoders, so that's what we use.
159 return StartsWithASCII(codecs_info[i].name, "OMX.google.", true); 174 return StartsWithASCII(codecs_info[i].name, "OMX.google.", true);
160 } 175 }
161 } 176 }
162 return true; 177 return true;
163 } 178 }
164 179
165 MediaCodecBridge::MediaCodecBridge(const std::string& mime, bool is_secure) { 180 MediaCodecBridge::MediaCodecBridge(const std::string& mime,
181 bool is_secure,
182 MediaCodecDirection direction) {
166 JNIEnv* env = AttachCurrentThread(); 183 JNIEnv* env = AttachCurrentThread();
167 CHECK(env); 184 CHECK(env);
168 DCHECK(!mime.empty()); 185 DCHECK(!mime.empty());
169 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime); 186 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
170 j_media_codec_.Reset( 187 j_media_codec_.Reset(
171 Java_MediaCodecBridge_create(env, j_mime.obj(), is_secure)); 188 Java_MediaCodecBridge_create(env, j_mime.obj(), is_secure, direction));
172 } 189 }
173 190
174 MediaCodecBridge::~MediaCodecBridge() { 191 MediaCodecBridge::~MediaCodecBridge() {
175 JNIEnv* env = AttachCurrentThread(); 192 JNIEnv* env = AttachCurrentThread();
176 CHECK(env); 193 CHECK(env);
177 if (j_media_codec_.obj()) 194 if (j_media_codec_.obj())
178 Java_MediaCodecBridge_release(env, j_media_codec_.obj()); 195 Java_MediaCodecBridge_release(env, j_media_codec_.obj());
179 } 196 }
180 197
181 bool MediaCodecBridge::StartInternal() { 198 bool MediaCodecBridge::StartInternal() {
(...skipping 14 matching lines...) Expand all
196 } 213 }
197 214
198 void MediaCodecBridge::GetOutputFormat(int* width, int* height) { 215 void MediaCodecBridge::GetOutputFormat(int* width, int* height) {
199 JNIEnv* env = AttachCurrentThread(); 216 JNIEnv* env = AttachCurrentThread();
200 217
201 *width = Java_MediaCodecBridge_getOutputWidth(env, j_media_codec_.obj()); 218 *width = Java_MediaCodecBridge_getOutputWidth(env, j_media_codec_.obj());
202 *height = Java_MediaCodecBridge_getOutputHeight(env, j_media_codec_.obj()); 219 *height = Java_MediaCodecBridge_getOutputHeight(env, j_media_codec_.obj());
203 } 220 }
204 221
205 MediaCodecStatus MediaCodecBridge::QueueInputBuffer( 222 MediaCodecStatus MediaCodecBridge::QueueInputBuffer(
206 int index, const uint8* data, int data_size, 223 int index,
224 const uint8* data,
225 int orig_data_size,
207 const base::TimeDelta& presentation_time) { 226 const base::TimeDelta& presentation_time) {
208 if (!FillInputBuffer(index, data, data_size)) 227 DVLOG(3) << "MediaCodecBridge::QueueInputBuffer: " << index << ": "
228 << orig_data_size;
229 size_t data_size = base::checked_numeric_cast<size_t>(orig_data_size);
230 if (data && !FillInputBuffer(index, data, data_size))
209 return MEDIA_CODEC_ERROR; 231 return MEDIA_CODEC_ERROR;
210 JNIEnv* env = AttachCurrentThread(); 232 JNIEnv* env = AttachCurrentThread();
211 return static_cast<MediaCodecStatus>(Java_MediaCodecBridge_queueInputBuffer( 233 return static_cast<MediaCodecStatus>(
212 env, j_media_codec_.obj(), 234 Java_MediaCodecBridge_queueInputBuffer(env,
213 index, 0, data_size, presentation_time.InMicroseconds(), 0)); 235 j_media_codec_.obj(),
236 index,
237 0,
238 data_size,
239 presentation_time.InMicroseconds(),
240 0));
214 } 241 }
215 242
216 MediaCodecStatus MediaCodecBridge::QueueSecureInputBuffer( 243 MediaCodecStatus MediaCodecBridge::QueueSecureInputBuffer(
217 int index, const uint8* data, int data_size, const uint8* key_id, 244 int index,
218 int key_id_size, const uint8* iv, int iv_size, 245 const uint8* data,
219 const SubsampleEntry* subsamples, int subsamples_size, 246 int orig_data_size,
247 const uint8* key_id,
248 int key_id_size,
249 const uint8* iv,
250 int iv_size,
251 const SubsampleEntry* subsamples,
252 int subsamples_size,
220 const base::TimeDelta& presentation_time) { 253 const base::TimeDelta& presentation_time) {
221 if (!FillInputBuffer(index, data, data_size)) 254 DVLOG(3) << "MediaCodecBridge::QueueSecureInputBuffer: " << index << ": "
255 << orig_data_size;
256 size_t data_size = base::checked_numeric_cast<size_t>(orig_data_size);
257 if (data && !FillInputBuffer(index, data, data_size))
222 return MEDIA_CODEC_ERROR; 258 return MEDIA_CODEC_ERROR;
223 259
224 JNIEnv* env = AttachCurrentThread(); 260 JNIEnv* env = AttachCurrentThread();
225 ScopedJavaLocalRef<jbyteArray> j_key_id = 261 ScopedJavaLocalRef<jbyteArray> j_key_id =
226 base::android::ToJavaByteArray(env, key_id, key_id_size); 262 base::android::ToJavaByteArray(env, key_id, key_id_size);
227 ScopedJavaLocalRef<jbyteArray> j_iv = 263 ScopedJavaLocalRef<jbyteArray> j_iv =
228 base::android::ToJavaByteArray(env, iv, iv_size); 264 base::android::ToJavaByteArray(env, iv, iv_size);
229 265
230 // MediaCodec.CryptoInfo documentations says passing NULL for |clear_array| 266 // MediaCodec.CryptoInfo documentations says passing NULL for |clear_array|
231 // to indicate that all data is encrypted. But it doesn't specify what 267 // to indicate that all data is encrypted. But it doesn't specify what
(...skipping 17 matching lines...) Expand all
249 static_cast<uint32>(std::numeric_limits<jint>::max())) { 285 static_cast<uint32>(std::numeric_limits<jint>::max())) {
250 return MEDIA_CODEC_ERROR; 286 return MEDIA_CODEC_ERROR;
251 } 287 }
252 288
253 native_clear_array[i] = subsamples[i].clear_bytes; 289 native_clear_array[i] = subsamples[i].clear_bytes;
254 native_cypher_array[i] = subsamples[i].cypher_bytes; 290 native_cypher_array[i] = subsamples[i].cypher_bytes;
255 } 291 }
256 } 292 }
257 293
258 ScopedJavaLocalRef<jintArray> clear_array = 294 ScopedJavaLocalRef<jintArray> clear_array =
259 ToJavaIntArray(env, native_clear_array.Pass(), new_subsamples_size); 295 ToJavaIntArray(env, native_clear_array.Pass(), new_subsamples_size);
260 ScopedJavaLocalRef<jintArray> cypher_array = 296 ScopedJavaLocalRef<jintArray> cypher_array =
261 ToJavaIntArray(env, native_cypher_array.Pass(), new_subsamples_size); 297 ToJavaIntArray(env, native_cypher_array.Pass(), new_subsamples_size);
262 298
263 return static_cast<MediaCodecStatus>( 299 return static_cast<MediaCodecStatus>(
264 Java_MediaCodecBridge_queueSecureInputBuffer( 300 Java_MediaCodecBridge_queueSecureInputBuffer(
265 env, j_media_codec_.obj(), index, 0, j_iv.obj(), j_key_id.obj(), 301 env,
266 clear_array.obj(), cypher_array.obj(), new_subsamples_size, 302 j_media_codec_.obj(),
303 index,
304 0,
305 j_iv.obj(),
306 j_key_id.obj(),
307 clear_array.obj(),
308 cypher_array.obj(),
309 new_subsamples_size,
267 presentation_time.InMicroseconds())); 310 presentation_time.InMicroseconds()));
268 } 311 }
269 312
270 void MediaCodecBridge::QueueEOS(int input_buffer_index) { 313 void MediaCodecBridge::QueueEOS(int input_buffer_index) {
314 DVLOG(3) << "MediaCodecBridge::QueueEOS: " << input_buffer_index;
271 JNIEnv* env = AttachCurrentThread(); 315 JNIEnv* env = AttachCurrentThread();
272 Java_MediaCodecBridge_queueInputBuffer( 316 Java_MediaCodecBridge_queueInputBuffer(env,
273 env, j_media_codec_.obj(), 317 j_media_codec_.obj(),
274 input_buffer_index, 0, 0, 0, kBufferFlagEndOfStream); 318 input_buffer_index,
319 0,
320 0,
321 0,
322 kBufferFlagEndOfStream);
275 } 323 }
276 324
277 MediaCodecStatus MediaCodecBridge::DequeueInputBuffer( 325 MediaCodecStatus MediaCodecBridge::DequeueInputBuffer(
278 const base::TimeDelta& timeout, int* index) { 326 const base::TimeDelta& timeout,
327 int* index) {
279 JNIEnv* env = AttachCurrentThread(); 328 JNIEnv* env = AttachCurrentThread();
280 ScopedJavaLocalRef<jobject> result = Java_MediaCodecBridge_dequeueInputBuffer( 329 ScopedJavaLocalRef<jobject> result = Java_MediaCodecBridge_dequeueInputBuffer(
281 env, j_media_codec_.obj(), timeout.InMicroseconds()); 330 env, j_media_codec_.obj(), timeout.InMicroseconds());
282 *index = Java_DequeueInputResult_index(env, result.obj()); 331 *index = Java_DequeueInputResult_index(env, result.obj());
283 return static_cast<MediaCodecStatus>( 332 MediaCodecStatus status = static_cast<MediaCodecStatus>(
284 Java_DequeueInputResult_status(env, result.obj())); 333 Java_DequeueInputResult_status(env, result.obj()));
334 DVLOG(3) << "MediaCodecBridge::DequeueInputBuffer: status: " << status
335 << ", index: " << *index;
336 return status;
285 } 337 }
286 338
287 MediaCodecStatus MediaCodecBridge::DequeueOutputBuffer( 339 MediaCodecStatus MediaCodecBridge::DequeueOutputBuffer(
288 const base::TimeDelta& timeout, int* index, size_t* offset, size_t* size, 340 const base::TimeDelta& timeout,
289 base::TimeDelta* presentation_time, bool* end_of_stream) { 341 int* index,
342 size_t* offset,
343 size_t* size,
344 base::TimeDelta* presentation_time,
345 bool* end_of_stream,
346 bool* key_frame) {
290 JNIEnv* env = AttachCurrentThread(); 347 JNIEnv* env = AttachCurrentThread();
291 ScopedJavaLocalRef<jobject> result = 348 ScopedJavaLocalRef<jobject> result =
292 Java_MediaCodecBridge_dequeueOutputBuffer(env, j_media_codec_.obj(), 349 Java_MediaCodecBridge_dequeueOutputBuffer(
293 timeout.InMicroseconds()); 350 env, j_media_codec_.obj(), timeout.InMicroseconds());
294 *index = Java_DequeueOutputResult_index(env, result.obj());; 351 *index = Java_DequeueOutputResult_index(env, result.obj());
295 *offset = base::checked_numeric_cast<size_t>( 352 *offset = base::checked_numeric_cast<size_t>(
296 Java_DequeueOutputResult_offset(env, result.obj())); 353 Java_DequeueOutputResult_offset(env, result.obj()));
297 *size = base::checked_numeric_cast<size_t>( 354 *size = base::checked_numeric_cast<size_t>(
298 Java_DequeueOutputResult_numBytes(env, result.obj())); 355 Java_DequeueOutputResult_numBytes(env, result.obj()));
299 *presentation_time = base::TimeDelta::FromMicroseconds( 356 if (presentation_time) {
300 Java_DequeueOutputResult_presentationTimeMicroseconds(env, result.obj())); 357 *presentation_time = base::TimeDelta::FromMicroseconds(
358 Java_DequeueOutputResult_presentationTimeMicroseconds(env,
359 result.obj()));
360 }
301 int flags = Java_DequeueOutputResult_flags(env, result.obj()); 361 int flags = Java_DequeueOutputResult_flags(env, result.obj());
302 *end_of_stream = flags & kBufferFlagEndOfStream; 362 if (end_of_stream)
303 return static_cast<MediaCodecStatus>( 363 *end_of_stream = flags & kBufferFlagEndOfStream;
364 if (key_frame)
365 *key_frame = flags & kBufferFlagSyncFrame;
366 MediaCodecStatus status = static_cast<MediaCodecStatus>(
304 Java_DequeueOutputResult_status(env, result.obj())); 367 Java_DequeueOutputResult_status(env, result.obj()));
368 DVLOG(3) << "MediaCodecBridge::DequeueOutputBuffer: status: " << status
369 << ", index: " << *index << ", offset: " << *offset
370 << ", size: " << *size << ", flags: " << flags;
371 return status;
305 } 372 }
306 373
307 void MediaCodecBridge::ReleaseOutputBuffer(int index, bool render) { 374 void MediaCodecBridge::ReleaseOutputBuffer(int index, bool render) {
375 DVLOG(3) << "MediaCodecBridge::ReleaseOutputBuffer: " << index;
308 JNIEnv* env = AttachCurrentThread(); 376 JNIEnv* env = AttachCurrentThread();
309 CHECK(env); 377 CHECK(env);
310 378
311 Java_MediaCodecBridge_releaseOutputBuffer( 379 Java_MediaCodecBridge_releaseOutputBuffer(
312 env, j_media_codec_.obj(), index, render); 380 env, j_media_codec_.obj(), index, render);
313 } 381 }
314 382
383 int MediaCodecBridge::GetInputBuffersCount() {
384 JNIEnv* env = AttachCurrentThread();
385 return Java_MediaCodecBridge_getInputBuffersCount(env, j_media_codec_.obj());
386 }
387
388 int MediaCodecBridge::GetOutputBuffersCount() {
389 JNIEnv* env = AttachCurrentThread();
390 return Java_MediaCodecBridge_getOutputBuffersCount(env, j_media_codec_.obj());
391 }
392
393 size_t MediaCodecBridge::GetOutputBuffersCapacity() {
394 JNIEnv* env = AttachCurrentThread();
395 return Java_MediaCodecBridge_getOutputBuffersCapacity(env,
396 j_media_codec_.obj());
397 }
398
315 bool MediaCodecBridge::GetOutputBuffers() { 399 bool MediaCodecBridge::GetOutputBuffers() {
316 JNIEnv* env = AttachCurrentThread(); 400 JNIEnv* env = AttachCurrentThread();
317 return Java_MediaCodecBridge_getOutputBuffers(env, j_media_codec_.obj()); 401 return Java_MediaCodecBridge_getOutputBuffers(env, j_media_codec_.obj());
318 } 402 }
319 403
320 bool MediaCodecBridge::FillInputBuffer(int index, const uint8* data, int size) { 404 void MediaCodecBridge::GetInputBuffer(int input_buffer_index,
405 uint8** data,
406 size_t* capacity) {
321 JNIEnv* env = AttachCurrentThread(); 407 JNIEnv* env = AttachCurrentThread();
408 ScopedJavaLocalRef<jobject> j_buffer(Java_MediaCodecBridge_getInputBuffer(
409 env, j_media_codec_.obj(), input_buffer_index));
410 *data = static_cast<uint8*>(env->GetDirectBufferAddress(j_buffer.obj()));
411 *capacity = base::checked_numeric_cast<size_t>(
412 env->GetDirectBufferCapacity(j_buffer.obj()));
413 }
322 414
415 bool MediaCodecBridge::CopyFromOutputBuffer(int index,
416 size_t offset,
417 void* dst,
418 int dst_size) {
419 JNIEnv* env = AttachCurrentThread();
323 ScopedJavaLocalRef<jobject> j_buffer( 420 ScopedJavaLocalRef<jobject> j_buffer(
324 Java_MediaCodecBridge_getInputBuffer(env, j_media_codec_.obj(), index)); 421 Java_MediaCodecBridge_getOutputBuffer(env, j_media_codec_.obj(), index));
325 jlong capacity = env->GetDirectBufferCapacity(j_buffer.obj()); 422 void* src_data =
423 reinterpret_cast<uint8*>(env->GetDirectBufferAddress(j_buffer.obj())) +
424 offset;
425 int src_capacity = env->GetDirectBufferCapacity(j_buffer.obj()) - offset;
426 if (src_capacity < dst_size)
427 return false;
428 memcpy(dst, src_data, dst_size);
429 return true;
430 }
431
432 bool MediaCodecBridge::FillInputBuffer(int index,
433 const uint8* data,
434 size_t size) {
435 uint8* dst = NULL;
436 size_t capacity = 0;
437 GetInputBuffer(index, &dst, &capacity);
438 CHECK(dst);
439
326 if (size > capacity) { 440 if (size > capacity) {
327 LOG(ERROR) << "Input buffer size " << size 441 LOG(ERROR) << "Input buffer size " << size
328 << " exceeds MediaCodec input buffer capacity: " << capacity; 442 << " exceeds MediaCodec input buffer capacity: " << capacity;
329 return false; 443 return false;
330 } 444 }
331 445
332 uint8* direct_buffer = 446 memcpy(dst, data, size);
333 static_cast<uint8*>(env->GetDirectBufferAddress(j_buffer.obj()));
334 memcpy(direct_buffer, data, size);
335 return true; 447 return true;
336 } 448 }
337 449
338 AudioCodecBridge::AudioCodecBridge(const std::string& mime) 450 AudioCodecBridge::AudioCodecBridge(const std::string& mime)
339 // Audio codec doesn't care about security level. 451 // Audio codec doesn't care about security level and there is no need for
340 : MediaCodecBridge(mime, false) { 452 // audio encoding yet.
341 } 453 : MediaCodecBridge(mime, false, MEDIA_CODEC_DECODER) {}
342 454
343 bool AudioCodecBridge::Start( 455 bool AudioCodecBridge::Start(const AudioCodec& codec,
344 const AudioCodec& codec, int sample_rate, int channel_count, 456 int sample_rate,
345 const uint8* extra_data, size_t extra_data_size, bool play_audio, 457 int channel_count,
346 jobject media_crypto) { 458 const uint8* extra_data,
459 size_t extra_data_size,
460 bool play_audio,
461 jobject media_crypto) {
347 JNIEnv* env = AttachCurrentThread(); 462 JNIEnv* env = AttachCurrentThread();
348 463
349 if (!media_codec()) 464 if (!media_codec())
350 return false; 465 return false;
351 466
352 std::string codec_string = AudioCodecToAndroidMimeType(codec); 467 std::string codec_string = AudioCodecToAndroidMimeType(codec);
353 if (codec_string.empty()) 468 if (codec_string.empty())
354 return false; 469 return false;
355 470
356 ScopedJavaLocalRef<jstring> j_mime = 471 ScopedJavaLocalRef<jstring> j_mime =
357 ConvertUTF8ToJavaString(env, codec_string); 472 ConvertUTF8ToJavaString(env, codec_string);
358 ScopedJavaLocalRef<jobject> j_format( 473 ScopedJavaLocalRef<jobject> j_format(Java_MediaCodecBridge_createAudioFormat(
359 Java_MediaCodecBridge_createAudioFormat( 474 env, j_mime.obj(), sample_rate, channel_count));
360 env, j_mime.obj(), sample_rate, channel_count));
361 DCHECK(!j_format.is_null()); 475 DCHECK(!j_format.is_null());
362 476
363 if (!ConfigureMediaFormat(j_format.obj(), codec, extra_data, extra_data_size)) 477 if (!ConfigureMediaFormat(j_format.obj(), codec, extra_data, extra_data_size))
364 return false; 478 return false;
365 479
366 if (!Java_MediaCodecBridge_configureAudio( 480 if (!Java_MediaCodecBridge_configureAudio(
367 env, media_codec(), j_format.obj(), media_crypto, 0, play_audio)) { 481 env, media_codec(), j_format.obj(), media_crypto, 0, play_audio)) {
368 return false; 482 return false;
369 } 483 }
370 484
371 return StartInternal(); 485 return StartInternal();
372 } 486 }
373 487
374 bool AudioCodecBridge::ConfigureMediaFormat( 488 bool AudioCodecBridge::ConfigureMediaFormat(jobject j_format,
375 jobject j_format, const AudioCodec& codec, const uint8* extra_data, 489 const AudioCodec& codec,
376 size_t extra_data_size) { 490 const uint8* extra_data,
491 size_t extra_data_size) {
377 if (extra_data_size == 0) 492 if (extra_data_size == 0)
378 return true; 493 return true;
379 494
380 JNIEnv* env = AttachCurrentThread(); 495 JNIEnv* env = AttachCurrentThread();
381 switch (codec) { 496 switch (codec) {
382 case kCodecVorbis: 497 case kCodecVorbis: {
383 {
384 if (extra_data[0] != 2) { 498 if (extra_data[0] != 2) {
385 LOG(ERROR) << "Invalid number of vorbis headers before the codec " 499 LOG(ERROR) << "Invalid number of vorbis headers before the codec "
386 << "header: " << extra_data[0]; 500 << "header: " << extra_data[0];
387 return false; 501 return false;
388 } 502 }
389 503
390 size_t header_length[2]; 504 size_t header_length[2];
391 // |total_length| keeps track of the total number of bytes before the last 505 // |total_length| keeps track of the total number of bytes before the last
392 // header. 506 // header.
393 size_t total_length = 1; 507 size_t total_length = 1;
(...skipping 24 matching lines...) Expand all
418 Java_MediaCodecBridge_setCodecSpecificData( 532 Java_MediaCodecBridge_setCodecSpecificData(
419 env, j_format, 0, first_header.obj()); 533 env, j_format, 0, first_header.obj());
420 // The last header is codec header. 534 // The last header is codec header.
421 ScopedJavaLocalRef<jbyteArray> last_header = 535 ScopedJavaLocalRef<jbyteArray> last_header =
422 base::android::ToJavaByteArray( 536 base::android::ToJavaByteArray(
423 env, extra_data + total_length, extra_data_size - total_length); 537 env, extra_data + total_length, extra_data_size - total_length);
424 Java_MediaCodecBridge_setCodecSpecificData( 538 Java_MediaCodecBridge_setCodecSpecificData(
425 env, j_format, 1, last_header.obj()); 539 env, j_format, 1, last_header.obj());
426 break; 540 break;
427 } 541 }
428 case kCodecAAC: 542 case kCodecAAC: {
429 {
430 media::BitReader reader(extra_data, extra_data_size); 543 media::BitReader reader(extra_data, extra_data_size);
431 544
432 // The following code is copied from aac.cc 545 // The following code is copied from aac.cc
433 // TODO(qinmin): refactor the code in aac.cc to make it more reusable. 546 // TODO(qinmin): refactor the code in aac.cc to make it more reusable.
434 uint8 profile = 0; 547 uint8 profile = 0;
435 uint8 frequency_index = 0; 548 uint8 frequency_index = 0;
436 uint8 channel_config = 0; 549 uint8 channel_config = 0;
437 if (!reader.ReadBits(5, &profile) || 550 if (!reader.ReadBits(5, &profile) ||
438 !reader.ReadBits(4, &frequency_index)) { 551 !reader.ReadBits(4, &frequency_index)) {
439 LOG(ERROR) << "Unable to parse AAC header"; 552 LOG(ERROR) << "Unable to parse AAC header";
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
478 void AudioCodecBridge::PlayOutputBuffer(int index, size_t size) { 591 void AudioCodecBridge::PlayOutputBuffer(int index, size_t size) {
479 DCHECK_LE(0, index); 592 DCHECK_LE(0, index);
480 int numBytes = base::checked_numeric_cast<int>(size); 593 int numBytes = base::checked_numeric_cast<int>(size);
481 JNIEnv* env = AttachCurrentThread(); 594 JNIEnv* env = AttachCurrentThread();
482 ScopedJavaLocalRef<jobject> buf = 595 ScopedJavaLocalRef<jobject> buf =
483 Java_MediaCodecBridge_getOutputBuffer(env, media_codec(), index); 596 Java_MediaCodecBridge_getOutputBuffer(env, media_codec(), index);
484 uint8* buffer = static_cast<uint8*>(env->GetDirectBufferAddress(buf.obj())); 597 uint8* buffer = static_cast<uint8*>(env->GetDirectBufferAddress(buf.obj()));
485 598
486 ScopedJavaLocalRef<jbyteArray> byte_array = 599 ScopedJavaLocalRef<jbyteArray> byte_array =
487 base::android::ToJavaByteArray(env, buffer, numBytes); 600 base::android::ToJavaByteArray(env, buffer, numBytes);
488 Java_MediaCodecBridge_playOutputBuffer( 601 Java_MediaCodecBridge_playOutputBuffer(env, media_codec(), byte_array.obj());
489 env, media_codec(), byte_array.obj());
490 } 602 }
491 603
492 void AudioCodecBridge::SetVolume(double volume) { 604 void AudioCodecBridge::SetVolume(double volume) {
493 JNIEnv* env = AttachCurrentThread(); 605 JNIEnv* env = AttachCurrentThread();
494 Java_MediaCodecBridge_setVolume(env, media_codec(), volume); 606 Java_MediaCodecBridge_setVolume(env, media_codec(), volume);
495 } 607 }
496 608
497 VideoCodecBridge::VideoCodecBridge(const std::string& mime, bool is_secure)
498 : MediaCodecBridge(mime, is_secure) {
499 }
500
501 bool VideoCodecBridge::Start(
502 const VideoCodec& codec, const gfx::Size& size, jobject surface,
503 jobject media_crypto) {
504 JNIEnv* env = AttachCurrentThread();
505
506 if (!media_codec())
507 return false;
508
509 std::string codec_string = VideoCodecToAndroidMimeType(codec);
510 if (codec_string.empty())
511 return false;
512
513 ScopedJavaLocalRef<jstring> j_mime =
514 ConvertUTF8ToJavaString(env, codec_string);
515 ScopedJavaLocalRef<jobject> j_format(
516 Java_MediaCodecBridge_createVideoFormat(
517 env, j_mime.obj(), size.width(), size.height()));
518 DCHECK(!j_format.is_null());
519 if (!Java_MediaCodecBridge_configureVideo(
520 env, media_codec(), j_format.obj(), surface, media_crypto, 0)) {
521 return false;
522 }
523
524 return StartInternal();
525 }
526
527 AudioCodecBridge* AudioCodecBridge::Create(const AudioCodec& codec) { 609 AudioCodecBridge* AudioCodecBridge::Create(const AudioCodec& codec) {
528 const std::string mime = AudioCodecToAndroidMimeType(codec); 610 const std::string mime = AudioCodecToAndroidMimeType(codec);
529 return mime.empty() ? NULL : new AudioCodecBridge(mime); 611 return mime.empty() ? NULL : new AudioCodecBridge(mime);
530 } 612 }
531 613
532 // static 614 // static
533 bool AudioCodecBridge::IsKnownUnaccelerated(const AudioCodec& codec) { 615 bool AudioCodecBridge::IsKnownUnaccelerated(const AudioCodec& codec) {
534 return MediaCodecBridge::IsKnownUnaccelerated( 616 return MediaCodecBridge::IsKnownUnaccelerated(
535 AudioCodecToAndroidMimeType(codec)); 617 AudioCodecToAndroidMimeType(codec), MEDIA_CODEC_DECODER);
536 }
537
538 VideoCodecBridge* VideoCodecBridge::Create(const VideoCodec& codec,
539 bool is_secure) {
540 const std::string mime = VideoCodecToAndroidMimeType(codec);
541 return mime.empty() ? NULL : new VideoCodecBridge(mime, is_secure);
542 } 618 }
543 619
544 // static 620 // static
545 bool VideoCodecBridge::IsKnownUnaccelerated(const VideoCodec& codec) { 621 bool VideoCodecBridge::IsKnownUnaccelerated(const VideoCodec& codec,
622 MediaCodecDirection direction) {
546 return MediaCodecBridge::IsKnownUnaccelerated( 623 return MediaCodecBridge::IsKnownUnaccelerated(
547 VideoCodecToAndroidMimeType(codec)); 624 VideoCodecToAndroidMimeType(codec), direction);
625 }
626
627 VideoCodecBridge* VideoCodecBridge::CreateDecoder(const VideoCodec& codec,
628 bool is_secure,
629 const gfx::Size& size,
630 jobject surface,
631 jobject media_crypto) {
632 JNIEnv* env = AttachCurrentThread();
633 const std::string mime = VideoCodecToAndroidMimeType(codec);
634 if (mime.empty())
635 return NULL;
636
637 scoped_ptr<VideoCodecBridge> bridge(
638 new VideoCodecBridge(mime, is_secure, MEDIA_CODEC_DECODER));
639
640 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
641 ScopedJavaLocalRef<jobject> j_format(
642 Java_MediaCodecBridge_createVideoDecoderFormat(
643 env, j_mime.obj(), size.width(), size.height()));
644 DCHECK(!j_format.is_null());
645 if (!Java_MediaCodecBridge_configureVideo(env,
646 bridge->media_codec(),
647 j_format.obj(),
648 surface,
649 media_crypto,
650 0)) {
651 return NULL;
652 }
653
654 return bridge->StartInternal() ? bridge.release() : NULL;
655 }
656
657 VideoCodecBridge* VideoCodecBridge::CreateEncoder(const VideoCodec& codec,
658 const gfx::Size& size,
659 int bit_rate,
660 int frame_rate,
661 int i_frame_interval,
662 int color_format) {
663 JNIEnv* env = AttachCurrentThread();
664 const std::string mime = VideoCodecToAndroidMimeType(codec);
665 if (mime.empty())
666 return NULL;
667
668 scoped_ptr<VideoCodecBridge> bridge(
669 new VideoCodecBridge(mime, false, MEDIA_CODEC_ENCODER));
670
671 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
672 ScopedJavaLocalRef<jobject> j_format(
673 Java_MediaCodecBridge_createVideoEncoderFormat(env,
674 j_mime.obj(),
675 size.width(),
676 size.height(),
677 bit_rate,
678 frame_rate,
679 i_frame_interval,
680 color_format));
681 DCHECK(!j_format.is_null());
682 if (!Java_MediaCodecBridge_configureVideo(env,
683 bridge->media_codec(),
684 j_format.obj(),
685 NULL,
686 NULL,
687 kConfigureFlagEncode)) {
688 return NULL;
689 }
690
691 return bridge->StartInternal() ? bridge.release() : NULL;
692 }
693
694 VideoCodecBridge::VideoCodecBridge(const std::string& mime,
695 bool is_secure,
696 MediaCodecDirection direction)
697 : MediaCodecBridge(mime, is_secure, direction) {}
698
699 void VideoCodecBridge::SetVideoBitrate(int bps) {
700 JNIEnv* env = AttachCurrentThread();
701 Java_MediaCodecBridge_setVideoBitrate(env, media_codec(), bps);
702 }
703
704 void VideoCodecBridge::RequestKeyFrameSoon() {
705 JNIEnv* env = AttachCurrentThread();
706 Java_MediaCodecBridge_requestKeyFrameSoon(env, media_codec());
548 } 707 }
549 708
550 bool MediaCodecBridge::RegisterMediaCodecBridge(JNIEnv* env) { 709 bool MediaCodecBridge::RegisterMediaCodecBridge(JNIEnv* env) {
551 return RegisterNativesImpl(env); 710 return RegisterNativesImpl(env);
552 } 711 }
553 712
554 } // namespace media 713 } // namespace media
OLDNEW
« no previous file with comments | « media/base/android/media_codec_bridge.h ('k') | media/base/android/media_codec_bridge_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698