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