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