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

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

Issue 11973010: AndroidVDA by using Android's MediaCodec API. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years, 11 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "media/base/android/media_codec_bridge.h"
6
7 #include <jni.h>
8
9 #include "base/android/jni_android.h"
10 #include "base/android/jni_array.h"
11 #include "base/android/jni_string.h"
12 #include "base/basictypes.h"
13 #include "base/logging.h"
14 #include "base/stringprintf.h"
15
16 #include "jni/MediaFormat_jni.h"
17 #include "MediaCodec_jni.h"
18
19
20 using base::android::AttachCurrentThread;
21 using base::android::ConvertUTF8ToJavaString;
22 using base::android::ScopedJavaLocalRef;
23
24 namespace {
25
26 static jclass g_MediaCodecBufferInfo_clazz = NULL;
Ami GONE FROM CHROMIUM 2013/01/23 01:32:32 Why not move this into BI_FI below, since it's nev
27
28 struct BufferInfo_FieldIds {
Ami GONE FROM CHROMIUM 2013/01/23 01:32:32 I believe you can drastically simplify the code ar
dwkang1 2013/01/28 14:54:30 Done.
29 BufferInfo_FieldIds(JNIEnv* env) {
30 offset = env->GetFieldID(g_MediaCodecBufferInfo_clazz, "offset", "I");
31 size = env->GetFieldID(g_MediaCodecBufferInfo_clazz, "size", "I");
32 presentation_time_us = env->GetFieldID(g_MediaCodecBufferInfo_clazz,
33 "presentationTimeUs", "J");
34 flags = env->GetFieldID(g_MediaCodecBufferInfo_clazz, "flags", "I");
35 }
36 jfieldID offset;
37 jfieldID size;
38 jfieldID presentation_time_us;
39 jfieldID flags;
40 };
41 static BufferInfo_FieldIds* g_field_ids;
Ami GONE FROM CHROMIUM 2013/01/23 01:32:32 s/;/ = NULL;/
dwkang1 2013/01/28 14:54:30 Done.
42
43 const char kMediaCodecBufferInfoClassPath[] =
44 "android/media/MediaCodec$BufferInfo";
45
46 static bool MediaCodecBufferInfo_RegisterNativesImpl(JNIEnv* env) {
47 g_MediaCodecBufferInfo_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
48 base::android::GetUnscopedClass(env, kMediaCodecBufferInfoClassPath)));
49 g_field_ids = new BufferInfo_FieldIds(env);
50 return true;
Ami GONE FROM CHROMIUM 2013/01/23 01:32:32 What if any of the lookups fail? Don't you want t
dwkang1 2013/01/28 14:54:30 base::android::CheckException(env) is added.
51 }
52
53 static base::subtle::AtomicWord g_MediaCodecBufferInfo_Constructor = 0;
54 static ScopedJavaLocalRef<jobject> Java_MediaCodecBufferInfo_Constructor(
55 JNIEnv* env) {
56 /* Must call RegisterNativesImpl() */
57 DCHECK(g_MediaCodecBufferInfo_clazz);
58 jmethodID method_id =
59 base::android::MethodID::LazyGet<base::android::MethodID::TYPE_INSTANCE>(
60 env, g_MediaCodecBufferInfo_clazz,
61 "<init>", "()V",
62 &g_MediaCodecBufferInfo_Constructor);
63
64 jobject ret = env->NewObject(g_MediaCodecBufferInfo_clazz, method_id);
65 base::android::CheckException(env);
66 return ScopedJavaLocalRef<jobject>(env, ret);
67 }
68
69 void RegisterNativesIfNeeded(JNIEnv* env) {
70 static bool jni_initialized = false;
71 if (!jni_initialized) {
72 JNI_MediaCodec::RegisterNativesImpl(env);
73 MediaCodecBufferInfo_RegisterNativesImpl(env);
74 JNI_MediaFormat::RegisterNativesImpl(env);
Ami GONE FROM CHROMIUM 2013/01/23 01:32:32 These 3 methods can return false; shouldn't you ha
dwkang1 2013/01/28 14:54:30 Done.
75 jni_initialized = true;
76 }
77 }
78 } // namespace
79
80 namespace media {
81
82 MediaCodecBridge::MediaCodecBridge(const std::string& type)
83 : j_byte_array_size_(0) {
84 JNIEnv* env = AttachCurrentThread();
85 CHECK(env);
86 RegisterNativesIfNeeded(env);
87
88 ScopedJavaLocalRef<jstring> j_type = ConvertUTF8ToJavaString(env, type);
89
90 ScopedJavaLocalRef<jobject> tmp(
91 JNI_MediaCodec::Java_MediaCodec_createDecoderByType(env, j_type.obj()));
92 DCHECK(!tmp.is_null());
93 j_media_codec_.Reset(tmp);
94 }
95
96 MediaCodecBridge::~MediaCodecBridge() {
97 JNIEnv* env = AttachCurrentThread();
98 CHECK(env);
99
100 // Release graphics memory.
101 JNI_MediaCodec::Java_MediaCodec_release(env, j_media_codec_.obj());
102 }
103
104 void MediaCodecBridge::ConfigureAudio(
105 const std::string& mime, int sample_rate, int channel_count,
106 const uint8* csd0, int csd0_size, const uint8* csd1, int csd1_size,
107 int encoder_delay, int encoder_padding, int max_input_size) {
108 JNIEnv* env = AttachCurrentThread();
109 CHECK(env);
110
111 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
112 ScopedJavaLocalRef<jobject> j_format(
113 JNI_MediaFormat::Java_MediaFormat_createAudioFormat(
114 env, j_mime.obj(), static_cast<jint>(sample_rate),
115 static_cast<jint>(channel_count)));
116 DCHECK(!j_format.is_null());
Ami GONE FROM CHROMIUM 2013/01/23 01:32:32 Again, I worry about a free-text mime-type causing
dwkang1 2013/01/28 14:54:30 CodecToMimeType() is introduced for type checking.
117
118 if (csd0 != NULL && csd0_size > 0) {
119 ScopedJavaLocalRef<jstring> j_csd_string =
120 ConvertUTF8ToJavaString(env, "csd-0");
121 JNI_MediaFormat::Java_MediaFormat_setByteBuffer(
122 env, j_format.obj(), j_csd_string.obj(),
123 env->NewDirectByteBuffer(const_cast<uint8*>(csd0), csd0_size));
124 }
125
126 if (csd1 != NULL && csd1_size > 0) {
127 ScopedJavaLocalRef<jstring> j_csd_string =
128 ConvertUTF8ToJavaString(env, "csd-1");
129 JNI_MediaFormat::Java_MediaFormat_setByteBuffer(
130 env, j_format.obj(), j_csd_string.obj(),
131 env->NewDirectByteBuffer(const_cast<uint8*>(csd1), csd1_size));
132 }
133
134 if (encoder_delay > 0) {
135 ScopedJavaLocalRef<jstring> j_encoder_delay_string =
136 ConvertUTF8ToJavaString(env, "encoder-delay");
Ami GONE FROM CHROMIUM 2013/01/23 01:32:32 Where does this string come from? I don't see it
dwkang1 2013/01/28 14:54:30 Removed. Will add when these are needed.
137 JNI_MediaFormat::Java_MediaFormat_setInteger(
138 env, j_format.obj(), j_encoder_delay_string.obj(),
139 static_cast<jint>(encoder_delay));
140 }
141
142 if (encoder_padding > 0) {
143 ScopedJavaLocalRef<jstring> j_encoder_padding_string =
144 ConvertUTF8ToJavaString(env, "encoder-padding");
145 JNI_MediaFormat::Java_MediaFormat_setInteger(
146 env, j_format.obj(), j_encoder_padding_string.obj(),
147 static_cast<jint>(encoder_padding));
148 }
149
150 if (max_input_size > 0) {
151 ScopedJavaLocalRef<jstring> j_max_input_size_string =
152 ConvertUTF8ToJavaString(env, "max-input-size");
153 JNI_MediaFormat::Java_MediaFormat_setInteger(
154 env, j_format.obj(), j_max_input_size_string.obj(),
155 static_cast<jint>(max_input_size));
156 }
Ami GONE FROM CHROMIUM 2013/01/23 01:32:32 There's an aweful lot of copy/pasta above; why not
dwkang1 2013/01/28 14:54:30 Removed.
157
158 ScopedJavaLocalRef<jstring> j_is_adts_string =
159 ConvertUTF8ToJavaString(env, "is-adts");
160 JNI_MediaFormat::Java_MediaFormat_setInteger(
161 env, j_format.obj(), j_is_adts_string.obj(), static_cast<jint>(1));
Ami GONE FROM CHROMIUM 2013/01/23 01:32:32 Why is this always true?
dwkang1 2013/01/28 14:54:30 I believe this is added while testing AAC codec an
162
163 JNI_MediaCodec::Java_MediaCodec_configure(
164 env, j_media_codec_.obj(), j_format.obj(), NULL, NULL, 0);
165 }
166
167 void MediaCodecBridge::ConfigureVideo(
168 const std::string& mime, int width, int height,
Ami GONE FROM CHROMIUM 2013/01/23 01:32:32 prefer to use gfx::Size instead of width/height pa
dwkang1 2013/01/28 14:54:30 Done.
169 const uint8* csd0, int csd0_size, const uint8* csd1, int csd1_size,
170 jobject surface) {
171 JNIEnv* env = AttachCurrentThread();
172 CHECK(env);
173
174 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
175 ScopedJavaLocalRef<jobject> j_format(
176 JNI_MediaFormat::Java_MediaFormat_createVideoFormat(
177 env, j_mime.obj(), static_cast<jint>(width), static_cast<jint>(height) ));
Ami GONE FROM CHROMIUM 2013/01/23 01:32:32 80-cols
Ami GONE FROM CHROMIUM 2013/01/23 01:32:32 Is it really necessary to static_cast an int to a
dwkang1 2013/01/28 14:54:30 Done.
dwkang1 2013/01/28 14:54:30 Done.
178 DCHECK(!j_format.is_null());
179
180 if (csd0 != NULL && csd0_size > 0) {
181 ScopedJavaLocalRef<jstring> j_csd_string =
182 ConvertUTF8ToJavaString(env, "csd-0");
183 JNI_MediaFormat::Java_MediaFormat_setByteBuffer(
184 env, j_format.obj(), j_csd_string.obj(),
185 env->NewDirectByteBuffer(const_cast<uint8*>(csd0), csd0_size));
186 }
187
188 if (csd1 != NULL && csd1_size > 0) {
189 ScopedJavaLocalRef<jstring> j_csd_string =
190 ConvertUTF8ToJavaString(env, "csd-1");
191 JNI_MediaFormat::Java_MediaFormat_setByteBuffer(
192 env, j_format.obj(), j_csd_string.obj(),
193 env->NewDirectByteBuffer(const_cast<uint8*>(csd1), csd1_size));
194 }
195
196 JNI_MediaCodec::Java_MediaCodec_configure(
197 env, j_media_codec_.obj(), j_format.obj(), surface, NULL, 0);
198 }
199
200 void MediaCodecBridge::Start() {
Ami GONE FROM CHROMIUM 2013/01/23 01:32:32 Why not make all configuration (audio/video) a sin
dwkang1 2013/01/28 14:54:30 I guess it was because they have difference argume
201 JNIEnv* env = AttachCurrentThread();
202 CHECK(env);
203
204 JNI_MediaCodec::Java_MediaCodec_start(env, j_media_codec_.obj());
205 }
206
207 void MediaCodecBridge::Flush() {
208 JNIEnv* env = AttachCurrentThread();
209 CHECK(env);
210
211 JNI_MediaCodec::Java_MediaCodec_flush(env, j_media_codec_.obj());
212 }
213
214 void MediaCodecBridge::Stop() {
215 JNIEnv* env = AttachCurrentThread();
216 CHECK(env);
217
218 JNI_MediaCodec::Java_MediaCodec_stop(env, j_media_codec_.obj());
219 }
220
221 void MediaCodecBridge::Release() {
Ami GONE FROM CHROMIUM 2013/01/23 01:32:32 Hopefully you can drop this method in favor of the
dwkang1 2013/01/28 14:54:30 Done.
222 JNIEnv* env = AttachCurrentThread();
223 CHECK(env);
224
225 JNI_MediaCodec::Java_MediaCodec_release(env, j_media_codec_.obj());
226 }
227
228 void MediaCodecBridge::GetOutputFormat(int* format, int* width, int* height) {
229 JNIEnv* env = AttachCurrentThread();
230 CHECK(env);
231
232 ScopedJavaLocalRef<jobject> j_format(
233 JNI_MediaCodec::Java_MediaCodec_getOutputFormat(
234 env, j_media_codec_.obj()));
235 if (!j_format.is_null()) {
236 ScopedJavaLocalRef<jstring> j_key_format =
237 ConvertUTF8ToJavaString(env, "color-format");
238 *format = static_cast<int>(JNI_MediaFormat::Java_MediaFormat_getInteger(
239 env, j_format.obj(), j_key_format.obj()));
240
241 ScopedJavaLocalRef<jstring> j_key_width =
242 ConvertUTF8ToJavaString(env, "width");
243 *width = static_cast<int>(JNI_MediaFormat::Java_MediaFormat_getInteger(
244 env, j_format.obj(), j_key_width.obj()));
245
246 ScopedJavaLocalRef<jstring> j_key_height =
247 ConvertUTF8ToJavaString(env, "height");
248 *height = static_cast<int>(JNI_MediaFormat::Java_MediaFormat_getInteger(
249 env, j_format.obj(), j_key_height.obj()));
250 }
251 }
252
253 void MediaCodecBridge::QueueInputBuffer(
254 int index, int offset, int size, int64 presentation_time_us, int flags) {
255 JNIEnv* env = AttachCurrentThread();
256 CHECK(env);
257
258 JNI_MediaCodec::Java_MediaCodec_queueInputBuffer(
259 env, j_media_codec_.obj(),
260 static_cast<jint>(index), static_cast<jint>(offset),
261 static_cast<jint>(size), static_cast<jlong>(presentation_time_us),
262 static_cast<jint>(flags));
263 }
264
265 int MediaCodecBridge::DequeueInputBuffer(int64 timeout_us) {
266 JNIEnv* env = AttachCurrentThread();
267 CHECK(env);
268
269 return JNI_MediaCodec::Java_MediaCodec_dequeueInputBuffer(
270 env, j_media_codec_.obj(), static_cast<jlong>(timeout_us));
271 }
272
273 int MediaCodecBridge::DequeueOutputBuffer(
274 int64 timeout_us, int* offset, int* size, int64* presentation_time_us,
275 int* flags) {
276 JNIEnv* env = AttachCurrentThread();
277 CHECK(env);
278
279 ScopedJavaLocalRef<jobject> j_info(
280 Java_MediaCodecBufferInfo_Constructor(env));
281 jint j_buffer = JNI_MediaCodec::Java_MediaCodec_dequeueOutputBuffer(
282 env, j_media_codec_.obj(), j_info.obj(), static_cast<jlong>(timeout_us));
283
284 if (j_buffer >= 0) {
285 *offset =
286 static_cast<int>(env->GetIntField(j_info.obj(), g_field_ids->offset));
287 *size = static_cast<int>(env->GetIntField(j_info.obj(), g_field_ids->size));
288 *presentation_time_us = static_cast<int64>(env->GetLongField(
289 j_info.obj(), g_field_ids->presentation_time_us));
290 *flags =
291 static_cast<int>(env->GetIntField(j_info.obj(), g_field_ids->flags));
292 }
293 return static_cast<int>(j_buffer);
294 }
295
296 void MediaCodecBridge::ReleaseOutputBuffer(int index, bool render) {
297 JNIEnv* env = AttachCurrentThread();
298 CHECK(env);
299
300 JNI_MediaCodec::Java_MediaCodec_releaseOutputBuffer(
301 env, j_media_codec_.obj(), static_cast<jint>(index),
302 static_cast<jboolean>(render));
303 }
304
305 int MediaCodecBridge::GetInputBuffers() {
306 JNIEnv* env = AttachCurrentThread();
307 CHECK(env);
308
309 j_input_buffers_.Reset(
310 JNI_MediaCodec::Java_MediaCodec_getInputBuffers(
311 env, j_media_codec_.obj()));
312 if (j_input_buffers_.is_null()) return -1;
Ami GONE FROM CHROMIUM 2013/01/23 01:32:32 I don't see this in the javadoc.
dwkang1 2013/01/28 14:54:30 Removed.
313
314 return static_cast<int>(env->GetArrayLength(j_input_buffers_.obj()));
315 }
316
317 int MediaCodecBridge::GetOutputBuffers() {
318 JNIEnv* env = AttachCurrentThread();
319 CHECK(env);
320
321 j_output_buffers_.Reset(
322 JNI_MediaCodec::Java_MediaCodec_getOutputBuffers(
323 env, j_media_codec_.obj()));
324 if (j_output_buffers_.is_null()) return -1;
Ami GONE FROM CHROMIUM 2013/01/23 01:32:32 again, javadoc doesn't support this.
dwkang1 2013/01/28 14:54:30 Removed.
325
326 return static_cast<int>(env->GetArrayLength(j_output_buffers_.obj()));
327 }
328
329 void MediaCodecBridge::PutToInputBuffer(
330 int index, const uint8* data, int size) {
331 JNIEnv* env = AttachCurrentThread();
332 CHECK(env);
333
334 ScopedJavaLocalRef<jobject> j_buffer(
335 env, env->GetObjectArrayElement(j_input_buffers_.obj(), index));
336
337 uint8* direct_buffer =
338 static_cast<uint8*>(env->GetDirectBufferAddress(j_buffer.obj()));
Ami GONE FROM CHROMIUM 2013/01/23 01:32:32 What guarantees that the bytebuffers MediaCodec re
ycheo (away) 2013/01/27 07:34:48 Actually, we refereed the underlying implementatio
Ami GONE FROM CHROMIUM 2013/01/27 17:50:42 If all known impls are direct then probably not wo
ycheo (away) 2013/01/27 19:47:22 We can ask them, but I don't expect that they try
339 memcpy(direct_buffer, data, size);
Ami GONE FROM CHROMIUM 2013/01/23 01:32:32 what if |size| is too big?
Ami GONE FROM CHROMIUM 2013/01/23 01:32:32 Is it not necessary to set the bytebuffer's mark/p
ycheo (away) 2013/01/27 07:34:48 Yes, the underlying implementation doesn't care ab
340 }
341
342 void MediaCodecBridge::GetFromOutputBuffer(
343 int index, int offset, uint8* data, int size) {
344 JNIEnv* env = AttachCurrentThread();
345 CHECK(env);
346
347 ScopedJavaLocalRef<jobject> j_buffer(
348 env, env->GetObjectArrayElement(j_output_buffers_.obj(), index));
349
350 uint8* direct_buffer =
351 static_cast<uint8*>(env->GetDirectBufferAddress(j_buffer.obj()));
Ami GONE FROM CHROMIUM 2013/01/23 01:32:32 ditto what if not direct?
352 memcpy(data, direct_buffer + offset, size);
353 }
354
355 void MediaCodecBridge::GetFromOutputBuffer(int index,
356 uint8* data0, int size0, uint8* data1, int size1, uint8* data2, int size2) {
357 JNIEnv* env = AttachCurrentThread();
358 CHECK(env);
359
360 ScopedJavaLocalRef<jobject> j_buffer(
361 env, env->GetObjectArrayElement(j_output_buffers_.obj(), index));
362
363 uint8* direct_buffer =
364 static_cast<uint8*>(env->GetDirectBufferAddress(j_buffer.obj()));
365 memcpy(data0, direct_buffer, size0);
366 memcpy(data1, direct_buffer + size0, size1);
Ami GONE FROM CHROMIUM 2013/01/23 01:32:32 What guarantees that the planes are mashed togethe
dwkang1 2013/01/28 14:54:30 This method will be removed and added when this is
367 memcpy(data2, direct_buffer + size0 + size1, size2);
368 }
369
370 } // namespace media
371
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698