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