| Index: media/base/android/media_codec_bridge.cc
|
| diff --git a/media/base/android/media_codec_bridge.cc b/media/base/android/media_codec_bridge.cc
|
| index 10fbf0f32cfd7880be5418fa0e842e8683d32ee3..9128df32f1fd9a36930ef3d4f83a63d4faa85ccc 100644
|
| --- a/media/base/android/media_codec_bridge.cc
|
| +++ b/media/base/android/media_codec_bridge.cc
|
| @@ -41,6 +41,8 @@ static const std::string AudioCodecToAndroidMimeType(const AudioCodec& codec) {
|
| return "audio/mpeg";
|
| case kCodecVorbis:
|
| return "audio/vorbis";
|
| + case kCodecOpus:
|
| + return "audio/opus";
|
| case kCodecAAC:
|
| return "audio/mp4a-latm";
|
| default:
|
| @@ -73,6 +75,8 @@ static const std::string CodecTypeToAndroidMimeType(const std::string& codec) {
|
| return "video/x-vnd.on2.vp9";
|
| if (codec == "vorbis")
|
| return "audio/vorbis";
|
| + if (codec == "opus")
|
| + return "audio/opus";
|
| return std::string();
|
| }
|
|
|
| @@ -92,6 +96,8 @@ static const std::string AndroidMimeTypeToCodecType(const std::string& mime) {
|
| return "mp3";
|
| if (mime == "audio/vorbis")
|
| return "vorbis";
|
| + if (mime == "audio/opus")
|
| + return "opus";
|
| return std::string();
|
| }
|
|
|
| @@ -525,6 +531,8 @@ bool AudioCodecBridge::Start(const AudioCodec& codec,
|
| int channel_count,
|
| const uint8* extra_data,
|
| size_t extra_data_size,
|
| + int64 codec_delay_ns,
|
| + int64 seek_preroll_ns,
|
| bool play_audio,
|
| jobject media_crypto) {
|
| JNIEnv* env = AttachCurrentThread();
|
| @@ -542,8 +550,10 @@ bool AudioCodecBridge::Start(const AudioCodec& codec,
|
| env, j_mime.obj(), sample_rate, channel_count));
|
| DCHECK(!j_format.is_null());
|
|
|
| - if (!ConfigureMediaFormat(j_format.obj(), codec, extra_data, extra_data_size))
|
| + if (!ConfigureMediaFormat(j_format.obj(), codec, extra_data, extra_data_size,
|
| + codec_delay_ns, seek_preroll_ns)) {
|
| return false;
|
| + }
|
|
|
| if (!Java_MediaCodecBridge_configureAudio(
|
| env, media_codec(), j_format.obj(), media_crypto, 0, play_audio)) {
|
| @@ -556,8 +566,10 @@ bool AudioCodecBridge::Start(const AudioCodec& codec,
|
| bool AudioCodecBridge::ConfigureMediaFormat(jobject j_format,
|
| const AudioCodec& codec,
|
| const uint8* extra_data,
|
| - size_t extra_data_size) {
|
| - if (extra_data_size == 0)
|
| + size_t extra_data_size,
|
| + int64 codec_delay_ns,
|
| + int64 seek_preroll_ns) {
|
| + if (extra_data_size == 0 && codec != kCodecOpus)
|
| return true;
|
|
|
| JNIEnv* env = AttachCurrentThread();
|
| @@ -648,6 +660,33 @@ bool AudioCodecBridge::ConfigureMediaFormat(jobject j_format,
|
| Java_MediaCodecBridge_setFrameHasADTSHeader(env, j_format);
|
| break;
|
| }
|
| + case kCodecOpus: {
|
| + if (!extra_data || extra_data_size == 0 ||
|
| + codec_delay_ns < 0 || seek_preroll_ns < 0) {
|
| + LOG(ERROR) << "Invalid Opus Header";
|
| + return false;
|
| + }
|
| +
|
| + // csd0 - Opus Header
|
| + ScopedJavaLocalRef<jbyteArray> csd0 =
|
| + base::android::ToJavaByteArray(env, extra_data, extra_data_size);
|
| + Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0, csd0.obj());
|
| +
|
| + // csd1 - Codec Delay
|
| + ScopedJavaLocalRef<jbyteArray> csd1 =
|
| + base::android::ToJavaByteArray(
|
| + env, reinterpret_cast<const uint8*>(&codec_delay_ns),
|
| + sizeof(int64_t));
|
| + Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 1, csd1.obj());
|
| +
|
| + // csd2 - Seek Preroll
|
| + ScopedJavaLocalRef<jbyteArray> csd2 =
|
| + base::android::ToJavaByteArray(
|
| + env, reinterpret_cast<const uint8*>(&seek_preroll_ns),
|
| + sizeof(int64_t));
|
| + Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 2, csd2.obj());
|
| + break;
|
| + }
|
| default:
|
| LOG(ERROR) << "Invalid header encountered for codec: "
|
| << AudioCodecToAndroidMimeType(codec);
|
|
|