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 |