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