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