| 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 <jni.h> | 7 #include <jni.h> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/android/build_info.h" | 10 #include "base/android/build_info.h" |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 kBufferFlagEndOfStream = 4, // BUFFER_FLAG_END_OF_STREAM | 34 kBufferFlagEndOfStream = 4, // BUFFER_FLAG_END_OF_STREAM |
| 35 kConfigureFlagEncode = 1, // CONFIGURE_FLAG_ENCODE | 35 kConfigureFlagEncode = 1, // CONFIGURE_FLAG_ENCODE |
| 36 }; | 36 }; |
| 37 | 37 |
| 38 static const std::string AudioCodecToAndroidMimeType(const AudioCodec& codec) { | 38 static const std::string AudioCodecToAndroidMimeType(const AudioCodec& codec) { |
| 39 switch (codec) { | 39 switch (codec) { |
| 40 case kCodecMP3: | 40 case kCodecMP3: |
| 41 return "audio/mpeg"; | 41 return "audio/mpeg"; |
| 42 case kCodecVorbis: | 42 case kCodecVorbis: |
| 43 return "audio/vorbis"; | 43 return "audio/vorbis"; |
| 44 case kCodecOpus: | |
| 45 return "audio/opus"; | |
| 46 case kCodecAAC: | 44 case kCodecAAC: |
| 47 return "audio/mp4a-latm"; | 45 return "audio/mp4a-latm"; |
| 48 default: | 46 default: |
| 49 return std::string(); | 47 return std::string(); |
| 50 } | 48 } |
| 51 } | 49 } |
| 52 | 50 |
| 53 static const std::string VideoCodecToAndroidMimeType(const VideoCodec& codec) { | 51 static const std::string VideoCodecToAndroidMimeType(const VideoCodec& codec) { |
| 54 switch (codec) { | 52 switch (codec) { |
| 55 case kCodecH264: | 53 case kCodecH264: |
| (...skipping 12 matching lines...) Expand all Loading... |
| 68 if (codec == "avc1") | 66 if (codec == "avc1") |
| 69 return "video/avc"; | 67 return "video/avc"; |
| 70 if (codec == "mp4a") | 68 if (codec == "mp4a") |
| 71 return "audio/mp4a-latm"; | 69 return "audio/mp4a-latm"; |
| 72 if (codec == "vp8" || codec == "vp8.0") | 70 if (codec == "vp8" || codec == "vp8.0") |
| 73 return "video/x-vnd.on2.vp8"; | 71 return "video/x-vnd.on2.vp8"; |
| 74 if (codec == "vp9" || codec == "vp9.0") | 72 if (codec == "vp9" || codec == "vp9.0") |
| 75 return "video/x-vnd.on2.vp9"; | 73 return "video/x-vnd.on2.vp9"; |
| 76 if (codec == "vorbis") | 74 if (codec == "vorbis") |
| 77 return "audio/vorbis"; | 75 return "audio/vorbis"; |
| 78 if (codec == "opus") | |
| 79 return "audio/opus"; | |
| 80 return std::string(); | 76 return std::string(); |
| 81 } | 77 } |
| 82 | 78 |
| 83 // TODO(qinmin): using a map to help all the conversions in this class. | 79 // TODO(qinmin): using a map to help all the conversions in this class. |
| 84 static const std::string AndroidMimeTypeToCodecType(const std::string& mime) { | 80 static const std::string AndroidMimeTypeToCodecType(const std::string& mime) { |
| 85 if (mime == "video/mp4v-es") | 81 if (mime == "video/mp4v-es") |
| 86 return "mp4v"; | 82 return "mp4v"; |
| 87 if (mime == "video/avc") | 83 if (mime == "video/avc") |
| 88 return "avc1"; | 84 return "avc1"; |
| 89 if (mime == "video/x-vnd.on2.vp8") | 85 if (mime == "video/x-vnd.on2.vp8") |
| 90 return "vp8"; | 86 return "vp8"; |
| 91 if (mime == "video/x-vnd.on2.vp9") | 87 if (mime == "video/x-vnd.on2.vp9") |
| 92 return "vp9"; | 88 return "vp9"; |
| 93 if (mime == "audio/mp4a-latm") | 89 if (mime == "audio/mp4a-latm") |
| 94 return "mp4a"; | 90 return "mp4a"; |
| 95 if (mime == "audio/mpeg") | 91 if (mime == "audio/mpeg") |
| 96 return "mp3"; | 92 return "mp3"; |
| 97 if (mime == "audio/vorbis") | 93 if (mime == "audio/vorbis") |
| 98 return "vorbis"; | 94 return "vorbis"; |
| 99 if (mime == "audio/opus") | |
| 100 return "opus"; | |
| 101 return std::string(); | 95 return std::string(); |
| 102 } | 96 } |
| 103 | 97 |
| 104 static ScopedJavaLocalRef<jintArray> | 98 static ScopedJavaLocalRef<jintArray> |
| 105 ToJavaIntArray(JNIEnv* env, scoped_ptr<jint[]> native_array, int size) { | 99 ToJavaIntArray(JNIEnv* env, scoped_ptr<jint[]> native_array, int size) { |
| 106 ScopedJavaLocalRef<jintArray> j_array(env, env->NewIntArray(size)); | 100 ScopedJavaLocalRef<jintArray> j_array(env, env->NewIntArray(size)); |
| 107 env->SetIntArrayRegion(j_array.obj(), 0, size, native_array.get()); | 101 env->SetIntArrayRegion(j_array.obj(), 0, size, native_array.get()); |
| 108 return j_array; | 102 return j_array; |
| 109 } | 103 } |
| 110 | 104 |
| (...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 524 AudioCodecBridge::AudioCodecBridge(const std::string& mime) | 518 AudioCodecBridge::AudioCodecBridge(const std::string& mime) |
| 525 // Audio codec doesn't care about security level and there is no need for | 519 // Audio codec doesn't care about security level and there is no need for |
| 526 // audio encoding yet. | 520 // audio encoding yet. |
| 527 : MediaCodecBridge(mime, false, MEDIA_CODEC_DECODER) {} | 521 : MediaCodecBridge(mime, false, MEDIA_CODEC_DECODER) {} |
| 528 | 522 |
| 529 bool AudioCodecBridge::Start(const AudioCodec& codec, | 523 bool AudioCodecBridge::Start(const AudioCodec& codec, |
| 530 int sample_rate, | 524 int sample_rate, |
| 531 int channel_count, | 525 int channel_count, |
| 532 const uint8* extra_data, | 526 const uint8* extra_data, |
| 533 size_t extra_data_size, | 527 size_t extra_data_size, |
| 534 int64 codec_delay_ns, | |
| 535 int64 seek_preroll_ns, | |
| 536 bool play_audio, | 528 bool play_audio, |
| 537 jobject media_crypto) { | 529 jobject media_crypto) { |
| 538 JNIEnv* env = AttachCurrentThread(); | 530 JNIEnv* env = AttachCurrentThread(); |
| 539 | 531 |
| 540 if (!media_codec()) | 532 if (!media_codec()) |
| 541 return false; | 533 return false; |
| 542 | 534 |
| 543 std::string codec_string = AudioCodecToAndroidMimeType(codec); | 535 std::string codec_string = AudioCodecToAndroidMimeType(codec); |
| 544 if (codec_string.empty()) | 536 if (codec_string.empty()) |
| 545 return false; | 537 return false; |
| 546 | 538 |
| 547 ScopedJavaLocalRef<jstring> j_mime = | 539 ScopedJavaLocalRef<jstring> j_mime = |
| 548 ConvertUTF8ToJavaString(env, codec_string); | 540 ConvertUTF8ToJavaString(env, codec_string); |
| 549 ScopedJavaLocalRef<jobject> j_format(Java_MediaCodecBridge_createAudioFormat( | 541 ScopedJavaLocalRef<jobject> j_format(Java_MediaCodecBridge_createAudioFormat( |
| 550 env, j_mime.obj(), sample_rate, channel_count)); | 542 env, j_mime.obj(), sample_rate, channel_count)); |
| 551 DCHECK(!j_format.is_null()); | 543 DCHECK(!j_format.is_null()); |
| 552 | 544 |
| 553 if (!ConfigureMediaFormat(j_format.obj(), codec, extra_data, extra_data_size, | 545 if (!ConfigureMediaFormat(j_format.obj(), codec, extra_data, extra_data_size)) |
| 554 codec_delay_ns, seek_preroll_ns)) { | |
| 555 return false; | 546 return false; |
| 556 } | |
| 557 | 547 |
| 558 if (!Java_MediaCodecBridge_configureAudio( | 548 if (!Java_MediaCodecBridge_configureAudio( |
| 559 env, media_codec(), j_format.obj(), media_crypto, 0, play_audio)) { | 549 env, media_codec(), j_format.obj(), media_crypto, 0, play_audio)) { |
| 560 return false; | 550 return false; |
| 561 } | 551 } |
| 562 | 552 |
| 563 return StartInternal(); | 553 return StartInternal(); |
| 564 } | 554 } |
| 565 | 555 |
| 566 bool AudioCodecBridge::ConfigureMediaFormat(jobject j_format, | 556 bool AudioCodecBridge::ConfigureMediaFormat(jobject j_format, |
| 567 const AudioCodec& codec, | 557 const AudioCodec& codec, |
| 568 const uint8* extra_data, | 558 const uint8* extra_data, |
| 569 size_t extra_data_size, | 559 size_t extra_data_size) { |
| 570 int64 codec_delay_ns, | 560 if (extra_data_size == 0) |
| 571 int64 seek_preroll_ns) { | |
| 572 if (extra_data_size == 0 && codec != kCodecOpus) | |
| 573 return true; | 561 return true; |
| 574 | 562 |
| 575 JNIEnv* env = AttachCurrentThread(); | 563 JNIEnv* env = AttachCurrentThread(); |
| 576 switch (codec) { | 564 switch (codec) { |
| 577 case kCodecVorbis: { | 565 case kCodecVorbis: { |
| 578 if (extra_data[0] != 2) { | 566 if (extra_data[0] != 2) { |
| 579 LOG(ERROR) << "Invalid number of vorbis headers before the codec " | 567 LOG(ERROR) << "Invalid number of vorbis headers before the codec " |
| 580 << "header: " << extra_data[0]; | 568 << "header: " << extra_data[0]; |
| 581 return false; | 569 return false; |
| 582 } | 570 } |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 653 ScopedJavaLocalRef<jbyteArray> byte_array = | 641 ScopedJavaLocalRef<jbyteArray> byte_array = |
| 654 base::android::ToJavaByteArray(env, csd, kCsdLength); | 642 base::android::ToJavaByteArray(env, csd, kCsdLength); |
| 655 Java_MediaCodecBridge_setCodecSpecificData( | 643 Java_MediaCodecBridge_setCodecSpecificData( |
| 656 env, j_format, 0, byte_array.obj()); | 644 env, j_format, 0, byte_array.obj()); |
| 657 | 645 |
| 658 // TODO(qinmin): pass an extra variable to this function to determine | 646 // TODO(qinmin): pass an extra variable to this function to determine |
| 659 // whether we need to call this. | 647 // whether we need to call this. |
| 660 Java_MediaCodecBridge_setFrameHasADTSHeader(env, j_format); | 648 Java_MediaCodecBridge_setFrameHasADTSHeader(env, j_format); |
| 661 break; | 649 break; |
| 662 } | 650 } |
| 663 case kCodecOpus: { | |
| 664 if (!extra_data || extra_data_size == 0 || | |
| 665 codec_delay_ns < 0 || seek_preroll_ns < 0) { | |
| 666 LOG(ERROR) << "Invalid Opus Header"; | |
| 667 return false; | |
| 668 } | |
| 669 | |
| 670 // csd0 - Opus Header | |
| 671 ScopedJavaLocalRef<jbyteArray> csd0 = | |
| 672 base::android::ToJavaByteArray(env, extra_data, extra_data_size); | |
| 673 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0, csd0.obj()); | |
| 674 | |
| 675 // csd1 - Codec Delay | |
| 676 ScopedJavaLocalRef<jbyteArray> csd1 = | |
| 677 base::android::ToJavaByteArray( | |
| 678 env, reinterpret_cast<const uint8*>(&codec_delay_ns), | |
| 679 sizeof(int64_t)); | |
| 680 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 1, csd1.obj()); | |
| 681 | |
| 682 // csd2 - Seek Preroll | |
| 683 ScopedJavaLocalRef<jbyteArray> csd2 = | |
| 684 base::android::ToJavaByteArray( | |
| 685 env, reinterpret_cast<const uint8*>(&seek_preroll_ns), | |
| 686 sizeof(int64_t)); | |
| 687 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 2, csd2.obj()); | |
| 688 break; | |
| 689 } | |
| 690 default: | 651 default: |
| 691 LOG(ERROR) << "Invalid header encountered for codec: " | 652 LOG(ERROR) << "Invalid header encountered for codec: " |
| 692 << AudioCodecToAndroidMimeType(codec); | 653 << AudioCodecToAndroidMimeType(codec); |
| 693 return false; | 654 return false; |
| 694 } | 655 } |
| 695 return true; | 656 return true; |
| 696 } | 657 } |
| 697 | 658 |
| 698 int64 AudioCodecBridge::PlayOutputBuffer(int index, size_t size) { | 659 int64 AudioCodecBridge::PlayOutputBuffer(int index, size_t size) { |
| 699 DCHECK_LE(0, index); | 660 DCHECK_LE(0, index); |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 839 JNIEnv* env = AttachCurrentThread(); | 800 JNIEnv* env = AttachCurrentThread(); |
| 840 return Java_MediaCodecBridge_isAdaptivePlaybackSupported( | 801 return Java_MediaCodecBridge_isAdaptivePlaybackSupported( |
| 841 env, media_codec(), width, height); | 802 env, media_codec(), width, height); |
| 842 } | 803 } |
| 843 | 804 |
| 844 bool MediaCodecBridge::RegisterMediaCodecBridge(JNIEnv* env) { | 805 bool MediaCodecBridge::RegisterMediaCodecBridge(JNIEnv* env) { |
| 845 return RegisterNativesImpl(env); | 806 return RegisterNativesImpl(env); |
| 846 } | 807 } |
| 847 | 808 |
| 848 } // namespace media | 809 } // namespace media |
| OLD | NEW |