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 |