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