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