| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "media/base/android/media_codec_bridge.h" | 5 #include "media/base/android/media_codec_bridge.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/android/build_info.h" | 9 #include "base/android/build_info.h" |
| 10 #include "base/android/jni_android.h" | 10 #include "base/android/jni_android.h" |
| 11 #include "base/android/jni_array.h" | 11 #include "base/android/jni_array.h" |
| 12 #include "base/android/jni_string.h" | 12 #include "base/android/jni_string.h" |
| 13 #include "base/basictypes.h" | |
| 14 #include "base/lazy_instance.h" | 13 #include "base/lazy_instance.h" |
| 15 #include "base/logging.h" | 14 #include "base/logging.h" |
| 16 #include "base/numerics/safe_conversions.h" | 15 #include "base/numerics/safe_conversions.h" |
| 17 #include "base/strings/string_util.h" | 16 #include "base/strings/string_util.h" |
| 18 #include "base/strings/stringprintf.h" | 17 #include "base/strings/stringprintf.h" |
| 19 #include "jni/MediaCodecBridge_jni.h" | 18 #include "jni/MediaCodecBridge_jni.h" |
| 20 #include "media/base/bit_reader.h" | 19 #include "media/base/bit_reader.h" |
| 21 #include "media/base/decrypt_config.h" | 20 #include "media/base/decrypt_config.h" |
| 22 | 21 |
| 23 using base::android::AttachCurrentThread; | 22 using base::android::AttachCurrentThread; |
| (...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 315 } | 314 } |
| 316 | 315 |
| 317 int MediaCodecBridge::GetOutputSamplingRate() { | 316 int MediaCodecBridge::GetOutputSamplingRate() { |
| 318 JNIEnv* env = AttachCurrentThread(); | 317 JNIEnv* env = AttachCurrentThread(); |
| 319 | 318 |
| 320 return Java_MediaCodecBridge_getOutputSamplingRate(env, j_media_codec_.obj()); | 319 return Java_MediaCodecBridge_getOutputSamplingRate(env, j_media_codec_.obj()); |
| 321 } | 320 } |
| 322 | 321 |
| 323 MediaCodecStatus MediaCodecBridge::QueueInputBuffer( | 322 MediaCodecStatus MediaCodecBridge::QueueInputBuffer( |
| 324 int index, | 323 int index, |
| 325 const uint8* data, | 324 const uint8_t* data, |
| 326 size_t data_size, | 325 size_t data_size, |
| 327 const base::TimeDelta& presentation_time) { | 326 const base::TimeDelta& presentation_time) { |
| 328 DVLOG(3) << __PRETTY_FUNCTION__ << index << ": " << data_size; | 327 DVLOG(3) << __PRETTY_FUNCTION__ << index << ": " << data_size; |
| 329 if (data_size > base::checked_cast<size_t>(kint32max)) | 328 if (data_size > |
| 329 base::checked_cast<size_t>(std::numeric_limits<int32_t>::max())) |
| 330 return MEDIA_CODEC_ERROR; | 330 return MEDIA_CODEC_ERROR; |
| 331 if (data && !FillInputBuffer(index, data, data_size)) | 331 if (data && !FillInputBuffer(index, data, data_size)) |
| 332 return MEDIA_CODEC_ERROR; | 332 return MEDIA_CODEC_ERROR; |
| 333 JNIEnv* env = AttachCurrentThread(); | 333 JNIEnv* env = AttachCurrentThread(); |
| 334 return static_cast<MediaCodecStatus>( | 334 return static_cast<MediaCodecStatus>( |
| 335 Java_MediaCodecBridge_queueInputBuffer(env, | 335 Java_MediaCodecBridge_queueInputBuffer(env, |
| 336 j_media_codec_.obj(), | 336 j_media_codec_.obj(), |
| 337 index, | 337 index, |
| 338 0, | 338 0, |
| 339 data_size, | 339 data_size, |
| 340 presentation_time.InMicroseconds(), | 340 presentation_time.InMicroseconds(), |
| 341 0)); | 341 0)); |
| 342 } | 342 } |
| 343 | 343 |
| 344 MediaCodecStatus MediaCodecBridge::QueueSecureInputBuffer( | 344 MediaCodecStatus MediaCodecBridge::QueueSecureInputBuffer( |
| 345 int index, | 345 int index, |
| 346 const uint8* data, | 346 const uint8_t* data, |
| 347 size_t data_size, | 347 size_t data_size, |
| 348 const std::string& key_id, | 348 const std::string& key_id, |
| 349 const std::string& iv, | 349 const std::string& iv, |
| 350 const std::vector<SubsampleEntry>& subsamples, | 350 const std::vector<SubsampleEntry>& subsamples, |
| 351 const base::TimeDelta& presentation_time) { | 351 const base::TimeDelta& presentation_time) { |
| 352 return QueueSecureInputBuffer( | 352 return QueueSecureInputBuffer( |
| 353 index, data, data_size, reinterpret_cast<const uint8_t*>(key_id.data()), | 353 index, data, data_size, reinterpret_cast<const uint8_t*>(key_id.data()), |
| 354 key_id.size(), reinterpret_cast<const uint8_t*>(iv.data()), iv.size(), | 354 key_id.size(), reinterpret_cast<const uint8_t*>(iv.data()), iv.size(), |
| 355 subsamples.empty() ? nullptr : &subsamples[0], subsamples.size(), | 355 subsamples.empty() ? nullptr : &subsamples[0], subsamples.size(), |
| 356 presentation_time); | 356 presentation_time); |
| 357 } | 357 } |
| 358 | 358 |
| 359 // TODO(timav): Combine this and above methods together keeping only the first | 359 // TODO(timav): Combine this and above methods together keeping only the first |
| 360 // interface after we switch to Spitzer pipeline. | 360 // interface after we switch to Spitzer pipeline. |
| 361 MediaCodecStatus MediaCodecBridge::QueueSecureInputBuffer( | 361 MediaCodecStatus MediaCodecBridge::QueueSecureInputBuffer( |
| 362 int index, | 362 int index, |
| 363 const uint8* data, | 363 const uint8_t* data, |
| 364 size_t data_size, | 364 size_t data_size, |
| 365 const uint8* key_id, | 365 const uint8_t* key_id, |
| 366 int key_id_size, | 366 int key_id_size, |
| 367 const uint8* iv, | 367 const uint8_t* iv, |
| 368 int iv_size, | 368 int iv_size, |
| 369 const SubsampleEntry* subsamples, | 369 const SubsampleEntry* subsamples, |
| 370 int subsamples_size, | 370 int subsamples_size, |
| 371 const base::TimeDelta& presentation_time) { | 371 const base::TimeDelta& presentation_time) { |
| 372 DVLOG(3) << __PRETTY_FUNCTION__ << index << ": " << data_size; | 372 DVLOG(3) << __PRETTY_FUNCTION__ << index << ": " << data_size; |
| 373 if (data_size > base::checked_cast<size_t>(kint32max)) | 373 if (data_size > |
| 374 base::checked_cast<size_t>(std::numeric_limits<int32_t>::max())) |
| 374 return MEDIA_CODEC_ERROR; | 375 return MEDIA_CODEC_ERROR; |
| 375 if (data && !FillInputBuffer(index, data, data_size)) | 376 if (data && !FillInputBuffer(index, data, data_size)) |
| 376 return MEDIA_CODEC_ERROR; | 377 return MEDIA_CODEC_ERROR; |
| 377 | 378 |
| 378 JNIEnv* env = AttachCurrentThread(); | 379 JNIEnv* env = AttachCurrentThread(); |
| 379 ScopedJavaLocalRef<jbyteArray> j_key_id = | 380 ScopedJavaLocalRef<jbyteArray> j_key_id = |
| 380 base::android::ToJavaByteArray(env, key_id, key_id_size); | 381 base::android::ToJavaByteArray(env, key_id, key_id_size); |
| 381 ScopedJavaLocalRef<jbyteArray> j_iv = | 382 ScopedJavaLocalRef<jbyteArray> j_iv = |
| 382 base::android::ToJavaByteArray(env, iv, iv_size); | 383 base::android::ToJavaByteArray(env, iv, iv_size); |
| 383 | 384 |
| 384 // MediaCodec.CryptoInfo documentations says passing NULL for |clear_array| | 385 // MediaCodec.CryptoInfo documentations says passing NULL for |clear_array| |
| 385 // to indicate that all data is encrypted. But it doesn't specify what | 386 // to indicate that all data is encrypted. But it doesn't specify what |
| 386 // |cypher_array| and |subsamples_size| should be in that case. Passing | 387 // |cypher_array| and |subsamples_size| should be in that case. Passing |
| 387 // one subsample here just to be on the safe side. | 388 // one subsample here just to be on the safe side. |
| 388 int new_subsamples_size = subsamples_size == 0 ? 1 : subsamples_size; | 389 int new_subsamples_size = subsamples_size == 0 ? 1 : subsamples_size; |
| 389 | 390 |
| 390 scoped_ptr<jint[]> native_clear_array(new jint[new_subsamples_size]); | 391 scoped_ptr<jint[]> native_clear_array(new jint[new_subsamples_size]); |
| 391 scoped_ptr<jint[]> native_cypher_array(new jint[new_subsamples_size]); | 392 scoped_ptr<jint[]> native_cypher_array(new jint[new_subsamples_size]); |
| 392 | 393 |
| 393 if (subsamples_size == 0) { | 394 if (subsamples_size == 0) { |
| 394 DCHECK(!subsamples); | 395 DCHECK(!subsamples); |
| 395 native_clear_array[0] = 0; | 396 native_clear_array[0] = 0; |
| 396 native_cypher_array[0] = data_size; | 397 native_cypher_array[0] = data_size; |
| 397 } else { | 398 } else { |
| 398 DCHECK_GT(subsamples_size, 0); | 399 DCHECK_GT(subsamples_size, 0); |
| 399 DCHECK(subsamples); | 400 DCHECK(subsamples); |
| 400 for (int i = 0; i < subsamples_size; ++i) { | 401 for (int i = 0; i < subsamples_size; ++i) { |
| 401 DCHECK(subsamples[i].clear_bytes <= std::numeric_limits<uint16>::max()); | 402 DCHECK(subsamples[i].clear_bytes <= std::numeric_limits<uint16_t>::max()); |
| 402 if (subsamples[i].cypher_bytes > | 403 if (subsamples[i].cypher_bytes > |
| 403 static_cast<uint32>(std::numeric_limits<jint>::max())) { | 404 static_cast<uint32_t>(std::numeric_limits<jint>::max())) { |
| 404 return MEDIA_CODEC_ERROR; | 405 return MEDIA_CODEC_ERROR; |
| 405 } | 406 } |
| 406 | 407 |
| 407 native_clear_array[i] = subsamples[i].clear_bytes; | 408 native_clear_array[i] = subsamples[i].clear_bytes; |
| 408 native_cypher_array[i] = subsamples[i].cypher_bytes; | 409 native_cypher_array[i] = subsamples[i].cypher_bytes; |
| 409 } | 410 } |
| 410 } | 411 } |
| 411 | 412 |
| 412 ScopedJavaLocalRef<jintArray> clear_array = | 413 ScopedJavaLocalRef<jintArray> clear_array = |
| 413 ToJavaIntArray(env, native_clear_array.Pass(), new_subsamples_size); | 414 ToJavaIntArray(env, native_clear_array.Pass(), new_subsamples_size); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 503 return Java_MediaCodecBridge_getOutputBuffersCount(env, j_media_codec_.obj()); | 504 return Java_MediaCodecBridge_getOutputBuffersCount(env, j_media_codec_.obj()); |
| 504 } | 505 } |
| 505 | 506 |
| 506 size_t MediaCodecBridge::GetOutputBuffersCapacity() { | 507 size_t MediaCodecBridge::GetOutputBuffersCapacity() { |
| 507 JNIEnv* env = AttachCurrentThread(); | 508 JNIEnv* env = AttachCurrentThread(); |
| 508 return Java_MediaCodecBridge_getOutputBuffersCapacity(env, | 509 return Java_MediaCodecBridge_getOutputBuffersCapacity(env, |
| 509 j_media_codec_.obj()); | 510 j_media_codec_.obj()); |
| 510 } | 511 } |
| 511 | 512 |
| 512 void MediaCodecBridge::GetInputBuffer(int input_buffer_index, | 513 void MediaCodecBridge::GetInputBuffer(int input_buffer_index, |
| 513 uint8** data, | 514 uint8_t** data, |
| 514 size_t* capacity) { | 515 size_t* capacity) { |
| 515 JNIEnv* env = AttachCurrentThread(); | 516 JNIEnv* env = AttachCurrentThread(); |
| 516 ScopedJavaLocalRef<jobject> j_buffer(Java_MediaCodecBridge_getInputBuffer( | 517 ScopedJavaLocalRef<jobject> j_buffer(Java_MediaCodecBridge_getInputBuffer( |
| 517 env, j_media_codec_.obj(), input_buffer_index)); | 518 env, j_media_codec_.obj(), input_buffer_index)); |
| 518 *data = static_cast<uint8*>(env->GetDirectBufferAddress(j_buffer.obj())); | 519 *data = static_cast<uint8_t*>(env->GetDirectBufferAddress(j_buffer.obj())); |
| 519 *capacity = base::checked_cast<size_t>( | 520 *capacity = base::checked_cast<size_t>( |
| 520 env->GetDirectBufferCapacity(j_buffer.obj())); | 521 env->GetDirectBufferCapacity(j_buffer.obj())); |
| 521 } | 522 } |
| 522 | 523 |
| 523 bool MediaCodecBridge::CopyFromOutputBuffer(int index, | 524 bool MediaCodecBridge::CopyFromOutputBuffer(int index, |
| 524 size_t offset, | 525 size_t offset, |
| 525 void* dst, | 526 void* dst, |
| 526 int dst_size) { | 527 int dst_size) { |
| 527 void* src_data = nullptr; | 528 void* src_data = nullptr; |
| 528 int src_capacity = GetOutputBufferAddress(index, offset, &src_data); | 529 int src_capacity = GetOutputBufferAddress(index, offset, &src_data); |
| 529 if (src_capacity < dst_size) | 530 if (src_capacity < dst_size) |
| 530 return false; | 531 return false; |
| 531 memcpy(dst, src_data, dst_size); | 532 memcpy(dst, src_data, dst_size); |
| 532 return true; | 533 return true; |
| 533 } | 534 } |
| 534 | 535 |
| 535 int MediaCodecBridge::GetOutputBufferAddress(int index, | 536 int MediaCodecBridge::GetOutputBufferAddress(int index, |
| 536 size_t offset, | 537 size_t offset, |
| 537 void** addr) { | 538 void** addr) { |
| 538 JNIEnv* env = AttachCurrentThread(); | 539 JNIEnv* env = AttachCurrentThread(); |
| 539 ScopedJavaLocalRef<jobject> j_buffer( | 540 ScopedJavaLocalRef<jobject> j_buffer( |
| 540 Java_MediaCodecBridge_getOutputBuffer(env, j_media_codec_.obj(), index)); | 541 Java_MediaCodecBridge_getOutputBuffer(env, j_media_codec_.obj(), index)); |
| 541 *addr = reinterpret_cast<uint8*>( | 542 *addr = |
| 542 env->GetDirectBufferAddress(j_buffer.obj())) + offset; | 543 reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(j_buffer.obj())) + |
| 544 offset; |
| 543 return env->GetDirectBufferCapacity(j_buffer.obj()) - offset; | 545 return env->GetDirectBufferCapacity(j_buffer.obj()) - offset; |
| 544 } | 546 } |
| 545 | 547 |
| 546 bool MediaCodecBridge::FillInputBuffer(int index, | 548 bool MediaCodecBridge::FillInputBuffer(int index, |
| 547 const uint8* data, | 549 const uint8_t* data, |
| 548 size_t size) { | 550 size_t size) { |
| 549 uint8* dst = NULL; | 551 uint8_t* dst = NULL; |
| 550 size_t capacity = 0; | 552 size_t capacity = 0; |
| 551 GetInputBuffer(index, &dst, &capacity); | 553 GetInputBuffer(index, &dst, &capacity); |
| 552 CHECK(dst); | 554 CHECK(dst); |
| 553 | 555 |
| 554 if (size > capacity) { | 556 if (size > capacity) { |
| 555 LOG(ERROR) << "Input buffer size " << size | 557 LOG(ERROR) << "Input buffer size " << size |
| 556 << " exceeds MediaCodec input buffer capacity: " << capacity; | 558 << " exceeds MediaCodec input buffer capacity: " << capacity; |
| 557 return false; | 559 return false; |
| 558 } | 560 } |
| 559 | 561 |
| 560 memcpy(dst, data, size); | 562 memcpy(dst, data, size); |
| 561 return true; | 563 return true; |
| 562 } | 564 } |
| 563 | 565 |
| 564 AudioCodecBridge::AudioCodecBridge(const std::string& mime) | 566 AudioCodecBridge::AudioCodecBridge(const std::string& mime) |
| 565 // Audio codec doesn't care about security level and there is no need for | 567 // Audio codec doesn't care about security level and there is no need for |
| 566 // audio encoding yet. | 568 // audio encoding yet. |
| 567 : MediaCodecBridge(mime, false, MEDIA_CODEC_DECODER) {} | 569 : MediaCodecBridge(mime, false, MEDIA_CODEC_DECODER) {} |
| 568 | 570 |
| 569 bool AudioCodecBridge::Start(const AudioCodec& codec, | 571 bool AudioCodecBridge::Start(const AudioCodec& codec, |
| 570 int sample_rate, | 572 int sample_rate, |
| 571 int channel_count, | 573 int channel_count, |
| 572 const uint8* extra_data, | 574 const uint8_t* extra_data, |
| 573 size_t extra_data_size, | 575 size_t extra_data_size, |
| 574 int64 codec_delay_ns, | 576 int64_t codec_delay_ns, |
| 575 int64 seek_preroll_ns, | 577 int64_t seek_preroll_ns, |
| 576 bool play_audio, | 578 bool play_audio, |
| 577 jobject media_crypto) { | 579 jobject media_crypto) { |
| 578 JNIEnv* env = AttachCurrentThread(); | 580 JNIEnv* env = AttachCurrentThread(); |
| 579 | 581 |
| 580 if (!media_codec()) | 582 if (!media_codec()) |
| 581 return false; | 583 return false; |
| 582 | 584 |
| 583 std::string codec_string = AudioCodecToAndroidMimeType(codec); | 585 std::string codec_string = AudioCodecToAndroidMimeType(codec); |
| 584 if (codec_string.empty()) | 586 if (codec_string.empty()) |
| 585 return false; | 587 return false; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 598 if (!Java_MediaCodecBridge_configureAudio( | 600 if (!Java_MediaCodecBridge_configureAudio( |
| 599 env, media_codec(), j_format.obj(), media_crypto, 0, play_audio)) { | 601 env, media_codec(), j_format.obj(), media_crypto, 0, play_audio)) { |
| 600 return false; | 602 return false; |
| 601 } | 603 } |
| 602 | 604 |
| 603 return StartInternal(); | 605 return StartInternal(); |
| 604 } | 606 } |
| 605 | 607 |
| 606 bool AudioCodecBridge::ConfigureMediaFormat(jobject j_format, | 608 bool AudioCodecBridge::ConfigureMediaFormat(jobject j_format, |
| 607 const AudioCodec& codec, | 609 const AudioCodec& codec, |
| 608 const uint8* extra_data, | 610 const uint8_t* extra_data, |
| 609 size_t extra_data_size, | 611 size_t extra_data_size, |
| 610 int64 codec_delay_ns, | 612 int64_t codec_delay_ns, |
| 611 int64 seek_preroll_ns) { | 613 int64_t seek_preroll_ns) { |
| 612 if (extra_data_size == 0 && codec != kCodecOpus) | 614 if (extra_data_size == 0 && codec != kCodecOpus) |
| 613 return true; | 615 return true; |
| 614 | 616 |
| 615 JNIEnv* env = AttachCurrentThread(); | 617 JNIEnv* env = AttachCurrentThread(); |
| 616 switch (codec) { | 618 switch (codec) { |
| 617 case kCodecVorbis: { | 619 case kCodecVorbis: { |
| 618 if (extra_data[0] != 2) { | 620 if (extra_data[0] != 2) { |
| 619 LOG(ERROR) << "Invalid number of vorbis headers before the codec " | 621 LOG(ERROR) << "Invalid number of vorbis headers before the codec " |
| 620 << "header: " << extra_data[0]; | 622 << "header: " << extra_data[0]; |
| 621 return false; | 623 return false; |
| 622 } | 624 } |
| 623 | 625 |
| 624 size_t header_length[2]; | 626 size_t header_length[2]; |
| 625 // |total_length| keeps track of the total number of bytes before the last | 627 // |total_length| keeps track of the total number of bytes before the last |
| 626 // header. | 628 // header. |
| 627 size_t total_length = 1; | 629 size_t total_length = 1; |
| 628 const uint8* current_pos = extra_data; | 630 const uint8_t* current_pos = extra_data; |
| 629 // Calculate the length of the first 2 headers. | 631 // Calculate the length of the first 2 headers. |
| 630 for (int i = 0; i < 2; ++i) { | 632 for (int i = 0; i < 2; ++i) { |
| 631 header_length[i] = 0; | 633 header_length[i] = 0; |
| 632 while (total_length < extra_data_size) { | 634 while (total_length < extra_data_size) { |
| 633 size_t size = *(++current_pos); | 635 size_t size = *(++current_pos); |
| 634 total_length += 1 + size; | 636 total_length += 1 + size; |
| 635 if (total_length > 0x80000000) { | 637 if (total_length > 0x80000000) { |
| 636 LOG(ERROR) << "Vorbis header size too large"; | 638 LOG(ERROR) << "Vorbis header size too large"; |
| 637 return false; | 639 return false; |
| 638 } | 640 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 657 env, extra_data + total_length, extra_data_size - total_length); | 659 env, extra_data + total_length, extra_data_size - total_length); |
| 658 Java_MediaCodecBridge_setCodecSpecificData( | 660 Java_MediaCodecBridge_setCodecSpecificData( |
| 659 env, j_format, 1, last_header.obj()); | 661 env, j_format, 1, last_header.obj()); |
| 660 break; | 662 break; |
| 661 } | 663 } |
| 662 case kCodecAAC: { | 664 case kCodecAAC: { |
| 663 media::BitReader reader(extra_data, extra_data_size); | 665 media::BitReader reader(extra_data, extra_data_size); |
| 664 | 666 |
| 665 // The following code is copied from aac.cc | 667 // The following code is copied from aac.cc |
| 666 // TODO(qinmin): refactor the code in aac.cc to make it more reusable. | 668 // TODO(qinmin): refactor the code in aac.cc to make it more reusable. |
| 667 uint8 profile = 0; | 669 uint8_t profile = 0; |
| 668 uint8 frequency_index = 0; | 670 uint8_t frequency_index = 0; |
| 669 uint8 channel_config = 0; | 671 uint8_t channel_config = 0; |
| 670 RETURN_ON_ERROR(reader.ReadBits(5, &profile)); | 672 RETURN_ON_ERROR(reader.ReadBits(5, &profile)); |
| 671 RETURN_ON_ERROR(reader.ReadBits(4, &frequency_index)); | 673 RETURN_ON_ERROR(reader.ReadBits(4, &frequency_index)); |
| 672 | 674 |
| 673 if (0xf == frequency_index) | 675 if (0xf == frequency_index) |
| 674 RETURN_ON_ERROR(reader.SkipBits(24)); | 676 RETURN_ON_ERROR(reader.SkipBits(24)); |
| 675 RETURN_ON_ERROR(reader.ReadBits(4, &channel_config)); | 677 RETURN_ON_ERROR(reader.ReadBits(4, &channel_config)); |
| 676 | 678 |
| 677 if (profile == 5 || profile == 29) { | 679 if (profile == 5 || profile == 29) { |
| 678 // Read extension config. | 680 // Read extension config. |
| 679 RETURN_ON_ERROR(reader.ReadBits(4, &frequency_index)); | 681 RETURN_ON_ERROR(reader.ReadBits(4, &frequency_index)); |
| 680 if (frequency_index == 0xf) | 682 if (frequency_index == 0xf) |
| 681 RETURN_ON_ERROR(reader.SkipBits(24)); | 683 RETURN_ON_ERROR(reader.SkipBits(24)); |
| 682 RETURN_ON_ERROR(reader.ReadBits(5, &profile)); | 684 RETURN_ON_ERROR(reader.ReadBits(5, &profile)); |
| 683 } | 685 } |
| 684 | 686 |
| 685 if (profile < 1 || profile > 4 || frequency_index == 0xf || | 687 if (profile < 1 || profile > 4 || frequency_index == 0xf || |
| 686 channel_config > 7) { | 688 channel_config > 7) { |
| 687 LOG(ERROR) << "Invalid AAC header"; | 689 LOG(ERROR) << "Invalid AAC header"; |
| 688 return false; | 690 return false; |
| 689 } | 691 } |
| 690 const size_t kCsdLength = 2; | 692 const size_t kCsdLength = 2; |
| 691 uint8 csd[kCsdLength]; | 693 uint8_t csd[kCsdLength]; |
| 692 csd[0] = profile << 3 | frequency_index >> 1; | 694 csd[0] = profile << 3 | frequency_index >> 1; |
| 693 csd[1] = (frequency_index & 0x01) << 7 | channel_config << 3; | 695 csd[1] = (frequency_index & 0x01) << 7 | channel_config << 3; |
| 694 ScopedJavaLocalRef<jbyteArray> byte_array = | 696 ScopedJavaLocalRef<jbyteArray> byte_array = |
| 695 base::android::ToJavaByteArray(env, csd, kCsdLength); | 697 base::android::ToJavaByteArray(env, csd, kCsdLength); |
| 696 Java_MediaCodecBridge_setCodecSpecificData( | 698 Java_MediaCodecBridge_setCodecSpecificData( |
| 697 env, j_format, 0, byte_array.obj()); | 699 env, j_format, 0, byte_array.obj()); |
| 698 | 700 |
| 699 // TODO(qinmin): pass an extra variable to this function to determine | 701 // TODO(qinmin): pass an extra variable to this function to determine |
| 700 // whether we need to call this. | 702 // whether we need to call this. |
| 701 Java_MediaCodecBridge_setFrameHasADTSHeader(env, j_format); | 703 Java_MediaCodecBridge_setFrameHasADTSHeader(env, j_format); |
| 702 break; | 704 break; |
| 703 } | 705 } |
| 704 case kCodecOpus: { | 706 case kCodecOpus: { |
| 705 if (!extra_data || extra_data_size == 0 || | 707 if (!extra_data || extra_data_size == 0 || |
| 706 codec_delay_ns < 0 || seek_preroll_ns < 0) { | 708 codec_delay_ns < 0 || seek_preroll_ns < 0) { |
| 707 LOG(ERROR) << "Invalid Opus Header"; | 709 LOG(ERROR) << "Invalid Opus Header"; |
| 708 return false; | 710 return false; |
| 709 } | 711 } |
| 710 | 712 |
| 711 // csd0 - Opus Header | 713 // csd0 - Opus Header |
| 712 ScopedJavaLocalRef<jbyteArray> csd0 = | 714 ScopedJavaLocalRef<jbyteArray> csd0 = |
| 713 base::android::ToJavaByteArray(env, extra_data, extra_data_size); | 715 base::android::ToJavaByteArray(env, extra_data, extra_data_size); |
| 714 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0, csd0.obj()); | 716 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0, csd0.obj()); |
| 715 | 717 |
| 716 // csd1 - Codec Delay | 718 // csd1 - Codec Delay |
| 717 ScopedJavaLocalRef<jbyteArray> csd1 = | 719 ScopedJavaLocalRef<jbyteArray> csd1 = base::android::ToJavaByteArray( |
| 718 base::android::ToJavaByteArray( | 720 env, reinterpret_cast<const uint8_t*>(&codec_delay_ns), |
| 719 env, reinterpret_cast<const uint8*>(&codec_delay_ns), | 721 sizeof(int64_t)); |
| 720 sizeof(int64_t)); | |
| 721 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 1, csd1.obj()); | 722 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 1, csd1.obj()); |
| 722 | 723 |
| 723 // csd2 - Seek Preroll | 724 // csd2 - Seek Preroll |
| 724 ScopedJavaLocalRef<jbyteArray> csd2 = | 725 ScopedJavaLocalRef<jbyteArray> csd2 = base::android::ToJavaByteArray( |
| 725 base::android::ToJavaByteArray( | 726 env, reinterpret_cast<const uint8_t*>(&seek_preroll_ns), |
| 726 env, reinterpret_cast<const uint8*>(&seek_preroll_ns), | 727 sizeof(int64_t)); |
| 727 sizeof(int64_t)); | |
| 728 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 2, csd2.obj()); | 728 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 2, csd2.obj()); |
| 729 break; | 729 break; |
| 730 } | 730 } |
| 731 default: | 731 default: |
| 732 LOG(ERROR) << "Invalid header encountered for codec: " | 732 LOG(ERROR) << "Invalid header encountered for codec: " |
| 733 << AudioCodecToAndroidMimeType(codec); | 733 << AudioCodecToAndroidMimeType(codec); |
| 734 return false; | 734 return false; |
| 735 } | 735 } |
| 736 return true; | 736 return true; |
| 737 } | 737 } |
| 738 | 738 |
| 739 int64 AudioCodecBridge::PlayOutputBuffer(int index, | 739 int64_t AudioCodecBridge::PlayOutputBuffer(int index, |
| 740 size_t size, | 740 size_t size, |
| 741 size_t offset, | 741 size_t offset, |
| 742 bool postpone) { | 742 bool postpone) { |
| 743 DCHECK_LE(0, index); | 743 DCHECK_LE(0, index); |
| 744 int numBytes = base::checked_cast<int>(size); | 744 int numBytes = base::checked_cast<int>(size); |
| 745 | 745 |
| 746 void* buffer = nullptr; | 746 void* buffer = nullptr; |
| 747 int capacity = GetOutputBufferAddress(index, offset, &buffer); | 747 int capacity = GetOutputBufferAddress(index, offset, &buffer); |
| 748 numBytes = std::min(capacity, numBytes); | 748 numBytes = std::min(capacity, numBytes); |
| 749 CHECK_GE(numBytes, 0); | 749 CHECK_GE(numBytes, 0); |
| 750 | 750 |
| 751 JNIEnv* env = AttachCurrentThread(); | 751 JNIEnv* env = AttachCurrentThread(); |
| 752 ScopedJavaLocalRef<jbyteArray> byte_array = base::android::ToJavaByteArray( | 752 ScopedJavaLocalRef<jbyteArray> byte_array = base::android::ToJavaByteArray( |
| 753 env, static_cast<uint8*>(buffer), numBytes); | 753 env, static_cast<uint8_t*>(buffer), numBytes); |
| 754 return Java_MediaCodecBridge_playOutputBuffer(env, media_codec(), | 754 return Java_MediaCodecBridge_playOutputBuffer(env, media_codec(), |
| 755 byte_array.obj(), postpone); | 755 byte_array.obj(), postpone); |
| 756 } | 756 } |
| 757 | 757 |
| 758 void AudioCodecBridge::SetVolume(double volume) { | 758 void AudioCodecBridge::SetVolume(double volume) { |
| 759 JNIEnv* env = AttachCurrentThread(); | 759 JNIEnv* env = AttachCurrentThread(); |
| 760 Java_MediaCodecBridge_setVolume(env, media_codec(), volume); | 760 Java_MediaCodecBridge_setVolume(env, media_codec(), volume); |
| 761 } | 761 } |
| 762 | 762 |
| 763 // static | 763 // static |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 885 JNIEnv* env = AttachCurrentThread(); | 885 JNIEnv* env = AttachCurrentThread(); |
| 886 return Java_MediaCodecBridge_isAdaptivePlaybackSupported( | 886 return Java_MediaCodecBridge_isAdaptivePlaybackSupported( |
| 887 env, media_codec(), width, height); | 887 env, media_codec(), width, height); |
| 888 } | 888 } |
| 889 | 889 |
| 890 bool MediaCodecBridge::RegisterMediaCodecBridge(JNIEnv* env) { | 890 bool MediaCodecBridge::RegisterMediaCodecBridge(JNIEnv* env) { |
| 891 return RegisterNativesImpl(env); | 891 return RegisterNativesImpl(env); |
| 892 } | 892 } |
| 893 | 893 |
| 894 } // namespace media | 894 } // namespace media |
| OLD | NEW |