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

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/Buffer_jni.h"
17 #include "jni/ByteBuffer_jni.h"
18 #include "jni/MediaFormat_jni.h"
19 #include "MediaCodec_jni.h"
20 #include "MediaCodec$BufferInfo_jni.h"
21
22 using base::android::AttachCurrentThread;
23 using base::android::ConvertUTF8ToJavaString;
24 using base::android::GetClass;
25 using base::android::GetFieldID;
26 using base::android::ScopedJavaLocalRef;
27 using base::android::ToJavaByteArray;
28
29
30 namespace {
31 struct FieldIds {
32 FieldIds(JNIEnv* env) {
33 ScopedJavaLocalRef<jclass> clazz(
34 GetClass(env, "android/media/MediaCodec$BufferInfo"));
35 offset = GetFieldID(env, clazz, "offset", "I");
36 size = GetFieldID(env, clazz, "size", "I");
37 presentation_time_us = GetFieldID(env, clazz, "presentationTimeUs", "J");
38 flags = GetFieldID(env, clazz, "flags", "I");
39 }
40 jfieldID offset;
41 jfieldID size;
42 jfieldID presentation_time_us;
43 jfieldID flags;
44 };
45
46 FieldIds* g_field_ids;
47
48 void RegisterNativesIfNeeded(JNIEnv* env) {
49 static bool jni_initialized = false;
50 if (!jni_initialized) {
51 JNI_Buffer::RegisterNativesImpl(env);
52 JNI_ByteBuffer::RegisterNativesImpl(env);
53 JNI_MediaCodec::RegisterNativesImpl(env);
54 JNI_MediaCodec$BufferInfo::RegisterNativesImpl(env);
55 JNI_MediaFormat::RegisterNativesImpl(env);
56 g_field_ids = new FieldIds(env);
57 jni_initialized = true;
58 }
59 }
60 } // namespace
61
62 namespace media {
63
64 MediaCodecBridge::MediaCodecBridge(const std::string& type)
65 : j_byte_array_size_(0) {
66 JNIEnv* env = AttachCurrentThread();
67 CHECK(env);
68 RegisterNativesIfNeeded(env);
69
70 ScopedJavaLocalRef<jstring> j_type = ConvertUTF8ToJavaString(env, type);
71
72 ScopedJavaLocalRef<jobject> tmp(
73 JNI_MediaCodec::Java_MediaCodec_createDecoderByType(env, j_type.obj()));
74 DCHECK(!tmp.is_null());
75 j_media_codec_.Reset(tmp);
76 }
77
78 MediaCodecBridge::~MediaCodecBridge() {
79 JNIEnv* env = AttachCurrentThread();
80 CHECK(env);
81
82 // Release graphics memory.
83 JNI_MediaCodec::Java_MediaCodec_release(env, j_media_codec_.obj());
84 }
85
86 void MediaCodecBridge::ConfigureAudio(
87 const std::string& mime, int sample_rate, int channel_count,
88 const uint8* csd0, int csd0_size, const uint8* csd1, int csd1_size,
89 int encoder_delay, int encoder_padding, int max_input_size) {
90 JNIEnv* env = AttachCurrentThread();
91 CHECK(env);
92
93 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
94 ScopedJavaLocalRef<jobject> j_format(
95 JNI_MediaFormat::Java_MediaFormat_createAudioFormat(
96 env, j_mime.obj(), static_cast<jint>(sample_rate),
97 static_cast<jint>(channel_count)));
98 DCHECK(!j_format.is_null());
99
100 if (csd0 != NULL && csd0_size > 0) {
101 ScopedJavaLocalRef<jstring> j_csd_string =
102 ConvertUTF8ToJavaString(env, "csd-0");
103 ScopedJavaLocalRef<jbyteArray> j_csd_array =
104 ToJavaByteArray(env, csd0, csd0_size);
105 ScopedJavaLocalRef<jobject> j_bytebuffer =
106 JNI_ByteBuffer::Java_ByteBuffer_wrapJNBB_AB(env, j_csd_array.obj());
107 JNI_MediaFormat::Java_MediaFormat_setByteBuffer(
108 env, j_format.obj(), j_csd_string.obj(), j_bytebuffer.obj());
109 }
110
111 if (csd1 != NULL && csd1_size > 0) {
112 ScopedJavaLocalRef<jstring> j_csd_string =
113 ConvertUTF8ToJavaString(env, "csd-1");
114 ScopedJavaLocalRef<jbyteArray> j_csd_array =
115 ToJavaByteArray(env, csd1, csd1_size);
116 ScopedJavaLocalRef<jobject> j_bytebuffer =
117 JNI_ByteBuffer::Java_ByteBuffer_wrapJNBB_AB(env, j_csd_array.obj());
118 JNI_MediaFormat::Java_MediaFormat_setByteBuffer(
119 env, j_format.obj(), j_csd_string.obj(), j_bytebuffer.obj());
120 }
121
122 if (encoder_delay > 0) {
123 ScopedJavaLocalRef<jstring> j_encoder_delay_string =
124 ConvertUTF8ToJavaString(env, "encoder-delay");
125 JNI_MediaFormat::Java_MediaFormat_setInteger(
126 env, j_format.obj(), j_encoder_delay_string.obj(),
127 static_cast<jint>(encoder_delay));
128 }
129
130 if (encoder_padding > 0) {
131 ScopedJavaLocalRef<jstring> j_encoder_padding_string =
132 ConvertUTF8ToJavaString(env, "encoder-padding");
133 JNI_MediaFormat::Java_MediaFormat_setInteger(
134 env, j_format.obj(), j_encoder_padding_string.obj(),
135 static_cast<jint>(encoder_padding));
136 }
137
138 if (max_input_size > 0) {
139 ScopedJavaLocalRef<jstring> j_max_input_size_string =
140 ConvertUTF8ToJavaString(env, "max-input-size");
141 JNI_MediaFormat::Java_MediaFormat_setInteger(
142 env, j_format.obj(), j_max_input_size_string.obj(),
143 static_cast<jint>(max_input_size));
144 }
145
146 ScopedJavaLocalRef<jstring> j_is_adts_string =
147 ConvertUTF8ToJavaString(env, "is-adts");
148 JNI_MediaFormat::Java_MediaFormat_setInteger(
149 env, j_format.obj(), j_is_adts_string.obj(), static_cast<jint>(1));
150
151 JNI_MediaCodec::Java_MediaCodec_configure(
152 env, j_media_codec_.obj(), j_format.obj(), NULL, NULL, 0);
153 }
154
155 void MediaCodecBridge::ConfigureVideo(
156 const std::string& mime, int width, int height,
157 const uint8* csd0, int csd0_size, const uint8* csd1, int csd1_size,
158 jobject surface) {
159 JNIEnv* env = AttachCurrentThread();
160 CHECK(env);
161
162 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
163 ScopedJavaLocalRef<jobject> j_format(
164 JNI_MediaFormat::Java_MediaFormat_createVideoFormat(
165 env, j_mime.obj(), static_cast<jint>(width), static_cast<jint>(height) ));
166 DCHECK(!j_format.is_null());
167
168 if (csd0 != NULL && csd0_size > 0) {
169 ScopedJavaLocalRef<jstring> j_csd_string =
170 ConvertUTF8ToJavaString(env, "csd-0");
171 ScopedJavaLocalRef<jbyteArray> j_csd_array =
172 ToJavaByteArray(env, csd0, csd0_size);
173 ScopedJavaLocalRef<jobject> j_bytebuffer =
174 JNI_ByteBuffer::Java_ByteBuffer_wrapJNBB_AB(env, j_csd_array.obj());
175 JNI_MediaFormat::Java_MediaFormat_setByteBuffer(
176 env, j_format.obj(), j_csd_string.obj(), j_bytebuffer.obj());
177 }
178
179 if (csd1 != NULL && csd1_size > 0) {
180 ScopedJavaLocalRef<jstring> j_csd_string =
181 ConvertUTF8ToJavaString(env, "csd-1");
182 ScopedJavaLocalRef<jbyteArray> j_csd_array =
183 ToJavaByteArray(env, csd1, csd1_size);
184 ScopedJavaLocalRef<jobject> j_bytebuffer =
185 JNI_ByteBuffer::Java_ByteBuffer_wrapJNBB_AB(env, j_csd_array.obj());
186 JNI_MediaFormat::Java_MediaFormat_setByteBuffer(
187 env, j_format.obj(), j_csd_string.obj(), j_bytebuffer.obj());
188 }
189
190 JNI_MediaCodec::Java_MediaCodec_configure(
191 env, j_media_codec_.obj(), j_format.obj(), surface, NULL, 0);
192 }
193
194 void MediaCodecBridge::Start() {
195 JNIEnv* env = AttachCurrentThread();
196 CHECK(env);
197
198 JNI_MediaCodec::Java_MediaCodec_start(env, j_media_codec_.obj());
199 }
200
201 void MediaCodecBridge::Flush() {
202 JNIEnv* env = AttachCurrentThread();
203 CHECK(env);
204
205 JNI_MediaCodec::Java_MediaCodec_flush(env, j_media_codec_.obj());
206 }
207
208 void MediaCodecBridge::Stop() {
209 JNIEnv* env = AttachCurrentThread();
210 CHECK(env);
211
212 JNI_MediaCodec::Java_MediaCodec_stop(env, j_media_codec_.obj());
213 }
214
215 void MediaCodecBridge::Release() {
216 JNIEnv* env = AttachCurrentThread();
217 CHECK(env);
218
219 JNI_MediaCodec::Java_MediaCodec_release(env, j_media_codec_.obj());
220 }
221
222 void MediaCodecBridge::GetOutputFormat(int* format, int* width, int* height) {
223 JNIEnv* env = AttachCurrentThread();
224 CHECK(env);
225
226 ScopedJavaLocalRef<jobject> j_format(
227 JNI_MediaCodec::Java_MediaCodec_getOutputFormat(
228 env, j_media_codec_.obj()));
229 if (!j_format.is_null()) {
230 ScopedJavaLocalRef<jstring> j_key_format =
231 ConvertUTF8ToJavaString(env, "color-format");
232 *format = static_cast<int>(JNI_MediaFormat::Java_MediaFormat_getInteger(
233 env, j_format.obj(), j_key_format.obj()));
234
235 ScopedJavaLocalRef<jstring> j_key_width =
236 ConvertUTF8ToJavaString(env, "width");
237 *width = static_cast<int>(JNI_MediaFormat::Java_MediaFormat_getInteger(
238 env, j_format.obj(), j_key_width.obj()));
239
240 ScopedJavaLocalRef<jstring> j_key_height =
241 ConvertUTF8ToJavaString(env, "height");
242 *height = static_cast<int>(JNI_MediaFormat::Java_MediaFormat_getInteger(
243 env, j_format.obj(), j_key_height.obj()));
244 }
245 }
246
247 void MediaCodecBridge::QueueInputBuffer(
248 int index, int offset, int size, int64 presentation_time_us, int flags) {
249 JNIEnv* env = AttachCurrentThread();
250 CHECK(env);
251
252 JNI_MediaCodec::Java_MediaCodec_queueInputBuffer(
253 env, j_media_codec_.obj(),
254 static_cast<jint>(index), static_cast<jint>(offset),
255 static_cast<jint>(size), static_cast<jlong>(presentation_time_us),
256 static_cast<jint>(flags));
257 }
258
259 int MediaCodecBridge::DequeueInputBuffer(int64 timeout_us) {
260 JNIEnv* env = AttachCurrentThread();
261 CHECK(env);
262
263 return JNI_MediaCodec::Java_MediaCodec_dequeueInputBuffer(
264 env, j_media_codec_.obj(), static_cast<jlong>(timeout_us));
265 }
266
267 int MediaCodecBridge::DequeueOutputBuffer(
268 int64 timeout_us, int* offset, int* size, int64* presentation_time_us,
269 int* flags) {
270 JNIEnv* env = AttachCurrentThread();
271 CHECK(env);
272
273 ScopedJavaLocalRef<jobject> j_info(
274 JNI_MediaCodec$BufferInfo::Java_MediaCodec$BufferInfo_Constructor(env));
275 jint j_buffer = JNI_MediaCodec::Java_MediaCodec_dequeueOutputBuffer(
276 env, j_media_codec_.obj(), j_info.obj(), static_cast<jlong>(timeout_us));
277
278 if (j_buffer >= 0) {
279 *offset =
280 static_cast<int>(env->GetIntField(j_info.obj(), g_field_ids->offset));
281 *size = static_cast<int>(env->GetIntField(j_info.obj(), g_field_ids->size));
282 *presentation_time_us = static_cast<int64>(env->GetLongField(
283 j_info.obj(), g_field_ids->presentation_time_us));
284 *flags =
285 static_cast<int>(env->GetIntField(j_info.obj(), g_field_ids->flags));
286 }
287 return static_cast<int>(j_buffer);
288 }
289
290 void MediaCodecBridge::ReleaseOutputBuffer(int index, bool render) {
291 JNIEnv* env = AttachCurrentThread();
292 CHECK(env);
293
294 JNI_MediaCodec::Java_MediaCodec_releaseOutputBuffer(
295 env, j_media_codec_.obj(), static_cast<jint>(index),
296 static_cast<jboolean>(render));
297 }
298
299 int MediaCodecBridge::GetInputBuffers() {
300 JNIEnv* env = AttachCurrentThread();
301 CHECK(env);
302
303 j_input_buffers_.Reset(
304 JNI_MediaCodec::Java_MediaCodec_getInputBuffers(
305 env, j_media_codec_.obj()));
306 if (j_input_buffers_.is_null()) return -1;
307
308 return static_cast<int>(env->GetArrayLength(j_input_buffers_.obj()));
309 }
310
311 int MediaCodecBridge::GetOutputBuffers() {
312 JNIEnv* env = AttachCurrentThread();
313 CHECK(env);
314
315 j_output_buffers_.Reset(
316 JNI_MediaCodec::Java_MediaCodec_getOutputBuffers(
317 env, j_media_codec_.obj()));
318 if (j_output_buffers_.is_null()) return -1;
319
320 return static_cast<int>(env->GetArrayLength(j_output_buffers_.obj()));
321 }
322
323 void MediaCodecBridge::PutToInputBuffer(
324 int index, const uint8* data, int size) {
325 JNIEnv* env = AttachCurrentThread();
326 CHECK(env);
327
328 ScopedJavaLocalRef<jobject> j_buffer(
329 env, env->GetObjectArrayElement(j_input_buffers_.obj(), index));
330
331 uint8* direct_buffer =
332 static_cast<uint8*>(env->GetDirectBufferAddress(j_buffer.obj()));
333 memcpy(direct_buffer, data, size);
334 }
335
336 void MediaCodecBridge::GetFromOutputBuffer(
337 int index, int offset, uint8* data, int size) {
338 JNIEnv* env = AttachCurrentThread();
339 CHECK(env);
340
341 ScopedJavaLocalRef<jobject> j_buffer(
342 env, env->GetObjectArrayElement(j_output_buffers_.obj(), index));
343
344 uint8* direct_buffer =
345 static_cast<uint8*>(env->GetDirectBufferAddress(j_buffer.obj()));
346 memcpy(data, direct_buffer + offset, size);
347 }
348
349 void MediaCodecBridge::GetFromOutputBuffer(int index,
350 uint8* data0, int size0, uint8* data1, int size1, uint8* data2, int size2) {
351 JNIEnv* env = AttachCurrentThread();
352 CHECK(env);
353
354 ScopedJavaLocalRef<jobject> j_buffer(
355 env, env->GetObjectArrayElement(j_output_buffers_.obj(), index));
356
357 uint8* direct_buffer =
358 static_cast<uint8*>(env->GetDirectBufferAddress(j_buffer.obj()));
359 memcpy(data0, direct_buffer, size0);
360 memcpy(data1, direct_buffer + size0, size1);
361 memcpy(data2, direct_buffer + size0 + size1, size2);
362 }
363
364 } // namespace media
365
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698