| 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/sdk_media_codec_bridge.h" | 5 #include "media/base/android/sdk_media_codec_bridge.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> |
| 8 | 9 |
| 9 #include "base/android/build_info.h" | 10 #include "base/android/build_info.h" |
| 10 #include "base/android/jni_android.h" | 11 #include "base/android/jni_android.h" |
| 11 #include "base/android/jni_array.h" | 12 #include "base/android/jni_array.h" |
| 12 #include "base/android/jni_string.h" | 13 #include "base/android/jni_string.h" |
| 13 #include "base/basictypes.h" | 14 #include "base/basictypes.h" |
| 14 #include "base/logging.h" | 15 #include "base/logging.h" |
| 15 #include "base/numerics/safe_conversions.h" | 16 #include "base/numerics/safe_conversions.h" |
| 16 #include "base/strings/string_util.h" | 17 #include "base/strings/string_util.h" |
| 17 #include "jni/MediaCodecBridge_jni.h" | 18 #include "jni/MediaCodecBridge_jni.h" |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 } | 120 } |
| 120 | 121 |
| 121 int SdkMediaCodecBridge::GetOutputSamplingRate() { | 122 int SdkMediaCodecBridge::GetOutputSamplingRate() { |
| 122 JNIEnv* env = AttachCurrentThread(); | 123 JNIEnv* env = AttachCurrentThread(); |
| 123 | 124 |
| 124 return Java_MediaCodecBridge_getOutputSamplingRate(env, j_media_codec_.obj()); | 125 return Java_MediaCodecBridge_getOutputSamplingRate(env, j_media_codec_.obj()); |
| 125 } | 126 } |
| 126 | 127 |
| 127 MediaCodecStatus SdkMediaCodecBridge::QueueInputBuffer( | 128 MediaCodecStatus SdkMediaCodecBridge::QueueInputBuffer( |
| 128 int index, | 129 int index, |
| 129 const uint8* data, | 130 const uint8_t* data, |
| 130 size_t data_size, | 131 size_t data_size, |
| 131 const base::TimeDelta& presentation_time) { | 132 const base::TimeDelta& presentation_time) { |
| 132 DVLOG(3) << __PRETTY_FUNCTION__ << index << ": " << data_size; | 133 DVLOG(3) << __PRETTY_FUNCTION__ << index << ": " << data_size; |
| 133 if (data_size > base::checked_cast<size_t>(kint32max)) | 134 if (data_size > |
| 135 base::checked_cast<size_t>(std::numeric_limits<int32_t>::max())) { |
| 134 return MEDIA_CODEC_ERROR; | 136 return MEDIA_CODEC_ERROR; |
| 137 } |
| 135 if (data && !FillInputBuffer(index, data, data_size)) | 138 if (data && !FillInputBuffer(index, data, data_size)) |
| 136 return MEDIA_CODEC_ERROR; | 139 return MEDIA_CODEC_ERROR; |
| 137 JNIEnv* env = AttachCurrentThread(); | 140 JNIEnv* env = AttachCurrentThread(); |
| 138 return static_cast<MediaCodecStatus>(Java_MediaCodecBridge_queueInputBuffer( | 141 return static_cast<MediaCodecStatus>(Java_MediaCodecBridge_queueInputBuffer( |
| 139 env, j_media_codec_.obj(), index, 0, data_size, | 142 env, j_media_codec_.obj(), index, 0, data_size, |
| 140 presentation_time.InMicroseconds(), 0)); | 143 presentation_time.InMicroseconds(), 0)); |
| 141 } | 144 } |
| 142 | 145 |
| 143 // TODO(timav): Combine this and above methods together keeping only the first | 146 // TODO(timav): Combine this and above methods together keeping only the first |
| 144 // interface after we switch to Spitzer pipeline. | 147 // interface after we switch to Spitzer pipeline. |
| 145 MediaCodecStatus SdkMediaCodecBridge::QueueSecureInputBuffer( | 148 MediaCodecStatus SdkMediaCodecBridge::QueueSecureInputBuffer( |
| 146 int index, | 149 int index, |
| 147 const uint8* data, | 150 const uint8_t* data, |
| 148 size_t data_size, | 151 size_t data_size, |
| 149 const std::vector<char>& key_id, | 152 const std::vector<char>& key_id, |
| 150 const std::vector<char>& iv, | 153 const std::vector<char>& iv, |
| 151 const SubsampleEntry* subsamples, | 154 const SubsampleEntry* subsamples, |
| 152 int subsamples_size, | 155 int subsamples_size, |
| 153 const base::TimeDelta& presentation_time) { | 156 const base::TimeDelta& presentation_time) { |
| 154 DVLOG(3) << __PRETTY_FUNCTION__ << index << ": " << data_size; | 157 DVLOG(3) << __PRETTY_FUNCTION__ << index << ": " << data_size; |
| 155 if (data_size > base::checked_cast<size_t>(kint32max)) | 158 if (data_size > |
| 159 base::checked_cast<size_t>(std::numeric_limits<int32_t>::max())) { |
| 156 return MEDIA_CODEC_ERROR; | 160 return MEDIA_CODEC_ERROR; |
| 161 } |
| 157 if (data && !FillInputBuffer(index, data, data_size)) | 162 if (data && !FillInputBuffer(index, data, data_size)) |
| 158 return MEDIA_CODEC_ERROR; | 163 return MEDIA_CODEC_ERROR; |
| 159 | 164 |
| 160 JNIEnv* env = AttachCurrentThread(); | 165 JNIEnv* env = AttachCurrentThread(); |
| 161 ScopedJavaLocalRef<jbyteArray> j_key_id = base::android::ToJavaByteArray( | 166 ScopedJavaLocalRef<jbyteArray> j_key_id = base::android::ToJavaByteArray( |
| 162 env, reinterpret_cast<const uint8*>(key_id.data()), key_id.size()); | 167 env, reinterpret_cast<const uint8_t*>(key_id.data()), key_id.size()); |
| 163 ScopedJavaLocalRef<jbyteArray> j_iv = base::android::ToJavaByteArray( | 168 ScopedJavaLocalRef<jbyteArray> j_iv = base::android::ToJavaByteArray( |
| 164 env, reinterpret_cast<const uint8*>(iv.data()), iv.size()); | 169 env, reinterpret_cast<const uint8_t*>(iv.data()), iv.size()); |
| 165 | 170 |
| 166 // MediaCodec.CryptoInfo documentations says passing NULL for |clear_array| | 171 // MediaCodec.CryptoInfo documentations says passing NULL for |clear_array| |
| 167 // to indicate that all data is encrypted. But it doesn't specify what | 172 // to indicate that all data is encrypted. But it doesn't specify what |
| 168 // |cypher_array| and |subsamples_size| should be in that case. Passing | 173 // |cypher_array| and |subsamples_size| should be in that case. Passing |
| 169 // one subsample here just to be on the safe side. | 174 // one subsample here just to be on the safe side. |
| 170 int new_subsamples_size = subsamples_size == 0 ? 1 : subsamples_size; | 175 int new_subsamples_size = subsamples_size == 0 ? 1 : subsamples_size; |
| 171 | 176 |
| 172 scoped_ptr<jint[]> native_clear_array(new jint[new_subsamples_size]); | 177 scoped_ptr<jint[]> native_clear_array(new jint[new_subsamples_size]); |
| 173 scoped_ptr<jint[]> native_cypher_array(new jint[new_subsamples_size]); | 178 scoped_ptr<jint[]> native_cypher_array(new jint[new_subsamples_size]); |
| 174 | 179 |
| 175 if (subsamples_size == 0) { | 180 if (subsamples_size == 0) { |
| 176 DCHECK(!subsamples); | 181 DCHECK(!subsamples); |
| 177 native_clear_array[0] = 0; | 182 native_clear_array[0] = 0; |
| 178 native_cypher_array[0] = data_size; | 183 native_cypher_array[0] = data_size; |
| 179 } else { | 184 } else { |
| 180 DCHECK_GT(subsamples_size, 0); | 185 DCHECK_GT(subsamples_size, 0); |
| 181 DCHECK(subsamples); | 186 DCHECK(subsamples); |
| 182 for (int i = 0; i < subsamples_size; ++i) { | 187 for (int i = 0; i < subsamples_size; ++i) { |
| 183 DCHECK(subsamples[i].clear_bytes <= std::numeric_limits<uint16>::max()); | 188 DCHECK(subsamples[i].clear_bytes <= std::numeric_limits<uint16_t>::max()); |
| 184 if (subsamples[i].cypher_bytes > | 189 if (subsamples[i].cypher_bytes > |
| 185 static_cast<uint32>(std::numeric_limits<jint>::max())) { | 190 static_cast<uint32_t>(std::numeric_limits<jint>::max())) { |
| 186 return MEDIA_CODEC_ERROR; | 191 return MEDIA_CODEC_ERROR; |
| 187 } | 192 } |
| 188 | 193 |
| 189 native_clear_array[i] = subsamples[i].clear_bytes; | 194 native_clear_array[i] = subsamples[i].clear_bytes; |
| 190 native_cypher_array[i] = subsamples[i].cypher_bytes; | 195 native_cypher_array[i] = subsamples[i].cypher_bytes; |
| 191 } | 196 } |
| 192 } | 197 } |
| 193 | 198 |
| 194 ScopedJavaLocalRef<jintArray> clear_array = | 199 ScopedJavaLocalRef<jintArray> clear_array = |
| 195 ToJavaIntArray(env, native_clear_array.Pass(), new_subsamples_size); | 200 ToJavaIntArray(env, native_clear_array.Pass(), new_subsamples_size); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 274 return Java_MediaCodecBridge_getOutputBuffersCount(env, j_media_codec_.obj()); | 279 return Java_MediaCodecBridge_getOutputBuffersCount(env, j_media_codec_.obj()); |
| 275 } | 280 } |
| 276 | 281 |
| 277 size_t SdkMediaCodecBridge::GetOutputBuffersCapacity() { | 282 size_t SdkMediaCodecBridge::GetOutputBuffersCapacity() { |
| 278 JNIEnv* env = AttachCurrentThread(); | 283 JNIEnv* env = AttachCurrentThread(); |
| 279 return Java_MediaCodecBridge_getOutputBuffersCapacity(env, | 284 return Java_MediaCodecBridge_getOutputBuffersCapacity(env, |
| 280 j_media_codec_.obj()); | 285 j_media_codec_.obj()); |
| 281 } | 286 } |
| 282 | 287 |
| 283 void SdkMediaCodecBridge::GetInputBuffer(int input_buffer_index, | 288 void SdkMediaCodecBridge::GetInputBuffer(int input_buffer_index, |
| 284 uint8** data, | 289 uint8_t** data, |
| 285 size_t* capacity) { | 290 size_t* capacity) { |
| 286 JNIEnv* env = AttachCurrentThread(); | 291 JNIEnv* env = AttachCurrentThread(); |
| 287 ScopedJavaLocalRef<jobject> j_buffer(Java_MediaCodecBridge_getInputBuffer( | 292 ScopedJavaLocalRef<jobject> j_buffer(Java_MediaCodecBridge_getInputBuffer( |
| 288 env, j_media_codec_.obj(), input_buffer_index)); | 293 env, j_media_codec_.obj(), input_buffer_index)); |
| 289 *data = static_cast<uint8*>(env->GetDirectBufferAddress(j_buffer.obj())); | 294 *data = static_cast<uint8_t*>(env->GetDirectBufferAddress(j_buffer.obj())); |
| 290 *capacity = | 295 *capacity = |
| 291 base::checked_cast<size_t>(env->GetDirectBufferCapacity(j_buffer.obj())); | 296 base::checked_cast<size_t>(env->GetDirectBufferCapacity(j_buffer.obj())); |
| 292 } | 297 } |
| 293 | 298 |
| 294 bool SdkMediaCodecBridge::CopyFromOutputBuffer(int index, | 299 bool SdkMediaCodecBridge::CopyFromOutputBuffer(int index, |
| 295 size_t offset, | 300 size_t offset, |
| 296 void* dst, | 301 void* dst, |
| 297 int dst_size) { | 302 int dst_size) { |
| 298 void* src_data = nullptr; | 303 void* src_data = nullptr; |
| 299 size_t src_capacity = GetOutputBufferAddress(index, offset, &src_data); | 304 size_t src_capacity = GetOutputBufferAddress(index, offset, &src_data); |
| 300 if (src_capacity < offset || | 305 if (src_capacity < offset || |
| 301 src_capacity - offset < static_cast<size_t>(dst_size)) { | 306 src_capacity - offset < static_cast<size_t>(dst_size)) { |
| 302 return false; | 307 return false; |
| 303 } | 308 } |
| 304 memcpy(dst, static_cast<uint8*>(src_data) + offset, dst_size); | 309 memcpy(dst, static_cast<uint8_t*>(src_data) + offset, dst_size); |
| 305 return true; | 310 return true; |
| 306 } | 311 } |
| 307 | 312 |
| 308 int SdkMediaCodecBridge::GetOutputBufferAddress(int index, | 313 int SdkMediaCodecBridge::GetOutputBufferAddress(int index, |
| 309 size_t offset, | 314 size_t offset, |
| 310 void** addr) { | 315 void** addr) { |
| 311 JNIEnv* env = AttachCurrentThread(); | 316 JNIEnv* env = AttachCurrentThread(); |
| 312 ScopedJavaLocalRef<jobject> j_buffer( | 317 ScopedJavaLocalRef<jobject> j_buffer( |
| 313 Java_MediaCodecBridge_getOutputBuffer(env, j_media_codec_.obj(), index)); | 318 Java_MediaCodecBridge_getOutputBuffer(env, j_media_codec_.obj(), index)); |
| 314 *addr = | 319 *addr = |
| 315 reinterpret_cast<uint8*>(env->GetDirectBufferAddress(j_buffer.obj())) + | 320 reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(j_buffer.obj())) + |
| 316 offset; | 321 offset; |
| 317 return env->GetDirectBufferCapacity(j_buffer.obj()) - offset; | 322 return env->GetDirectBufferCapacity(j_buffer.obj()) - offset; |
| 318 } | 323 } |
| 319 | 324 |
| 320 // static | 325 // static |
| 321 bool SdkMediaCodecBridge::RegisterSdkMediaCodecBridge(JNIEnv* env) { | 326 bool SdkMediaCodecBridge::RegisterSdkMediaCodecBridge(JNIEnv* env) { |
| 322 return RegisterNativesImpl(env); | 327 return RegisterNativesImpl(env); |
| 323 } | 328 } |
| 324 | 329 |
| 325 // static | 330 // static |
| (...skipping 12 matching lines...) Expand all Loading... |
| 338 } | 343 } |
| 339 | 344 |
| 340 AudioCodecBridge::AudioCodecBridge(const std::string& mime) | 345 AudioCodecBridge::AudioCodecBridge(const std::string& mime) |
| 341 // Audio codec doesn't care about security level and there is no need for | 346 // Audio codec doesn't care about security level and there is no need for |
| 342 // audio encoding yet. | 347 // audio encoding yet. |
| 343 : SdkMediaCodecBridge(mime, false, MEDIA_CODEC_DECODER) {} | 348 : SdkMediaCodecBridge(mime, false, MEDIA_CODEC_DECODER) {} |
| 344 | 349 |
| 345 bool AudioCodecBridge::ConfigureAndStart(const AudioCodec& codec, | 350 bool AudioCodecBridge::ConfigureAndStart(const AudioCodec& codec, |
| 346 int sample_rate, | 351 int sample_rate, |
| 347 int channel_count, | 352 int channel_count, |
| 348 const uint8* extra_data, | 353 const uint8_t* extra_data, |
| 349 size_t extra_data_size, | 354 size_t extra_data_size, |
| 350 int64 codec_delay_ns, | 355 int64_t codec_delay_ns, |
| 351 int64 seek_preroll_ns, | 356 int64_t seek_preroll_ns, |
| 352 bool play_audio, | 357 bool play_audio, |
| 353 jobject media_crypto) { | 358 jobject media_crypto) { |
| 354 JNIEnv* env = AttachCurrentThread(); | 359 JNIEnv* env = AttachCurrentThread(); |
| 355 | 360 |
| 356 if (!media_codec()) | 361 if (!media_codec()) |
| 357 return false; | 362 return false; |
| 358 | 363 |
| 359 std::string codec_string = AudioCodecToAndroidMimeType(codec); | 364 std::string codec_string = AudioCodecToAndroidMimeType(codec); |
| 360 if (codec_string.empty()) | 365 if (codec_string.empty()) |
| 361 return false; | 366 return false; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 374 if (!Java_MediaCodecBridge_configureAudio(env, media_codec(), j_format.obj(), | 379 if (!Java_MediaCodecBridge_configureAudio(env, media_codec(), j_format.obj(), |
| 375 media_crypto, 0, play_audio)) { | 380 media_crypto, 0, play_audio)) { |
| 376 return false; | 381 return false; |
| 377 } | 382 } |
| 378 | 383 |
| 379 return Start(); | 384 return Start(); |
| 380 } | 385 } |
| 381 | 386 |
| 382 bool AudioCodecBridge::ConfigureMediaFormat(jobject j_format, | 387 bool AudioCodecBridge::ConfigureMediaFormat(jobject j_format, |
| 383 const AudioCodec& codec, | 388 const AudioCodec& codec, |
| 384 const uint8* extra_data, | 389 const uint8_t* extra_data, |
| 385 size_t extra_data_size, | 390 size_t extra_data_size, |
| 386 int64 codec_delay_ns, | 391 int64_t codec_delay_ns, |
| 387 int64 seek_preroll_ns) { | 392 int64_t seek_preroll_ns) { |
| 388 if (extra_data_size == 0 && codec != kCodecOpus) | 393 if (extra_data_size == 0 && codec != kCodecOpus) |
| 389 return true; | 394 return true; |
| 390 | 395 |
| 391 JNIEnv* env = AttachCurrentThread(); | 396 JNIEnv* env = AttachCurrentThread(); |
| 392 switch (codec) { | 397 switch (codec) { |
| 393 case kCodecVorbis: { | 398 case kCodecVorbis: { |
| 394 if (extra_data[0] != 2) { | 399 if (extra_data[0] != 2) { |
| 395 LOG(ERROR) << "Invalid number of vorbis headers before the codec " | 400 LOG(ERROR) << "Invalid number of vorbis headers before the codec " |
| 396 << "header: " << extra_data[0]; | 401 << "header: " << extra_data[0]; |
| 397 return false; | 402 return false; |
| 398 } | 403 } |
| 399 | 404 |
| 400 size_t header_length[2]; | 405 size_t header_length[2]; |
| 401 // |total_length| keeps track of the total number of bytes before the last | 406 // |total_length| keeps track of the total number of bytes before the last |
| 402 // header. | 407 // header. |
| 403 size_t total_length = 1; | 408 size_t total_length = 1; |
| 404 const uint8* current_pos = extra_data; | 409 const uint8_t* current_pos = extra_data; |
| 405 // Calculate the length of the first 2 headers. | 410 // Calculate the length of the first 2 headers. |
| 406 for (int i = 0; i < 2; ++i) { | 411 for (int i = 0; i < 2; ++i) { |
| 407 header_length[i] = 0; | 412 header_length[i] = 0; |
| 408 while (total_length < extra_data_size) { | 413 while (total_length < extra_data_size) { |
| 409 size_t size = *(++current_pos); | 414 size_t size = *(++current_pos); |
| 410 total_length += 1 + size; | 415 total_length += 1 + size; |
| 411 if (total_length > 0x80000000) { | 416 if (total_length > 0x80000000) { |
| 412 LOG(ERROR) << "Vorbis header size too large"; | 417 LOG(ERROR) << "Vorbis header size too large"; |
| 413 return false; | 418 return false; |
| 414 } | 419 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 433 extra_data_size - total_length); | 438 extra_data_size - total_length); |
| 434 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 1, | 439 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 1, |
| 435 last_header.obj()); | 440 last_header.obj()); |
| 436 break; | 441 break; |
| 437 } | 442 } |
| 438 case kCodecAAC: { | 443 case kCodecAAC: { |
| 439 media::BitReader reader(extra_data, extra_data_size); | 444 media::BitReader reader(extra_data, extra_data_size); |
| 440 | 445 |
| 441 // The following code is copied from aac.cc | 446 // The following code is copied from aac.cc |
| 442 // TODO(qinmin): refactor the code in aac.cc to make it more reusable. | 447 // TODO(qinmin): refactor the code in aac.cc to make it more reusable. |
| 443 uint8 profile = 0; | 448 uint8_t profile = 0; |
| 444 uint8 frequency_index = 0; | 449 uint8_t frequency_index = 0; |
| 445 uint8 channel_config = 0; | 450 uint8_t channel_config = 0; |
| 446 RETURN_ON_ERROR(reader.ReadBits(5, &profile)); | 451 RETURN_ON_ERROR(reader.ReadBits(5, &profile)); |
| 447 RETURN_ON_ERROR(reader.ReadBits(4, &frequency_index)); | 452 RETURN_ON_ERROR(reader.ReadBits(4, &frequency_index)); |
| 448 | 453 |
| 449 if (0xf == frequency_index) | 454 if (0xf == frequency_index) |
| 450 RETURN_ON_ERROR(reader.SkipBits(24)); | 455 RETURN_ON_ERROR(reader.SkipBits(24)); |
| 451 RETURN_ON_ERROR(reader.ReadBits(4, &channel_config)); | 456 RETURN_ON_ERROR(reader.ReadBits(4, &channel_config)); |
| 452 | 457 |
| 453 if (profile == 5 || profile == 29) { | 458 if (profile == 5 || profile == 29) { |
| 454 // Read extension config. | 459 // Read extension config. |
| 455 RETURN_ON_ERROR(reader.ReadBits(4, &frequency_index)); | 460 RETURN_ON_ERROR(reader.ReadBits(4, &frequency_index)); |
| 456 if (frequency_index == 0xf) | 461 if (frequency_index == 0xf) |
| 457 RETURN_ON_ERROR(reader.SkipBits(24)); | 462 RETURN_ON_ERROR(reader.SkipBits(24)); |
| 458 RETURN_ON_ERROR(reader.ReadBits(5, &profile)); | 463 RETURN_ON_ERROR(reader.ReadBits(5, &profile)); |
| 459 } | 464 } |
| 460 | 465 |
| 461 if (profile < 1 || profile > 4 || frequency_index == 0xf || | 466 if (profile < 1 || profile > 4 || frequency_index == 0xf || |
| 462 channel_config > 7) { | 467 channel_config > 7) { |
| 463 LOG(ERROR) << "Invalid AAC header"; | 468 LOG(ERROR) << "Invalid AAC header"; |
| 464 return false; | 469 return false; |
| 465 } | 470 } |
| 466 const size_t kCsdLength = 2; | 471 const size_t kCsdLength = 2; |
| 467 uint8 csd[kCsdLength]; | 472 uint8_t csd[kCsdLength]; |
| 468 csd[0] = profile << 3 | frequency_index >> 1; | 473 csd[0] = profile << 3 | frequency_index >> 1; |
| 469 csd[1] = (frequency_index & 0x01) << 7 | channel_config << 3; | 474 csd[1] = (frequency_index & 0x01) << 7 | channel_config << 3; |
| 470 ScopedJavaLocalRef<jbyteArray> byte_array = | 475 ScopedJavaLocalRef<jbyteArray> byte_array = |
| 471 base::android::ToJavaByteArray(env, csd, kCsdLength); | 476 base::android::ToJavaByteArray(env, csd, kCsdLength); |
| 472 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0, | 477 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0, |
| 473 byte_array.obj()); | 478 byte_array.obj()); |
| 474 | 479 |
| 475 // TODO(qinmin): pass an extra variable to this function to determine | 480 // TODO(qinmin): pass an extra variable to this function to determine |
| 476 // whether we need to call this. | 481 // whether we need to call this. |
| 477 Java_MediaCodecBridge_setFrameHasADTSHeader(env, j_format); | 482 Java_MediaCodecBridge_setFrameHasADTSHeader(env, j_format); |
| 478 break; | 483 break; |
| 479 } | 484 } |
| 480 case kCodecOpus: { | 485 case kCodecOpus: { |
| 481 if (!extra_data || extra_data_size == 0 || codec_delay_ns < 0 || | 486 if (!extra_data || extra_data_size == 0 || codec_delay_ns < 0 || |
| 482 seek_preroll_ns < 0) { | 487 seek_preroll_ns < 0) { |
| 483 LOG(ERROR) << "Invalid Opus Header"; | 488 LOG(ERROR) << "Invalid Opus Header"; |
| 484 return false; | 489 return false; |
| 485 } | 490 } |
| 486 | 491 |
| 487 // csd0 - Opus Header | 492 // csd0 - Opus Header |
| 488 ScopedJavaLocalRef<jbyteArray> csd0 = | 493 ScopedJavaLocalRef<jbyteArray> csd0 = |
| 489 base::android::ToJavaByteArray(env, extra_data, extra_data_size); | 494 base::android::ToJavaByteArray(env, extra_data, extra_data_size); |
| 490 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0, csd0.obj()); | 495 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0, csd0.obj()); |
| 491 | 496 |
| 492 // csd1 - Codec Delay | 497 // csd1 - Codec Delay |
| 493 ScopedJavaLocalRef<jbyteArray> csd1 = base::android::ToJavaByteArray( | 498 ScopedJavaLocalRef<jbyteArray> csd1 = base::android::ToJavaByteArray( |
| 494 env, reinterpret_cast<const uint8*>(&codec_delay_ns), | 499 env, reinterpret_cast<const uint8_t*>(&codec_delay_ns), |
| 495 sizeof(int64_t)); | 500 sizeof(int64_t)); |
| 496 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 1, csd1.obj()); | 501 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 1, csd1.obj()); |
| 497 | 502 |
| 498 // csd2 - Seek Preroll | 503 // csd2 - Seek Preroll |
| 499 ScopedJavaLocalRef<jbyteArray> csd2 = base::android::ToJavaByteArray( | 504 ScopedJavaLocalRef<jbyteArray> csd2 = base::android::ToJavaByteArray( |
| 500 env, reinterpret_cast<const uint8*>(&seek_preroll_ns), | 505 env, reinterpret_cast<const uint8_t*>(&seek_preroll_ns), |
| 501 sizeof(int64_t)); | 506 sizeof(int64_t)); |
| 502 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 2, csd2.obj()); | 507 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 2, csd2.obj()); |
| 503 break; | 508 break; |
| 504 } | 509 } |
| 505 default: | 510 default: |
| 506 LOG(ERROR) << "Invalid header encountered for codec: " | 511 LOG(ERROR) << "Invalid header encountered for codec: " |
| 507 << AudioCodecToAndroidMimeType(codec); | 512 << AudioCodecToAndroidMimeType(codec); |
| 508 return false; | 513 return false; |
| 509 } | 514 } |
| 510 return true; | 515 return true; |
| 511 } | 516 } |
| 512 | 517 |
| 513 int64 AudioCodecBridge::PlayOutputBuffer(int index, | 518 int64_t AudioCodecBridge::PlayOutputBuffer(int index, |
| 514 size_t size, | 519 size_t size, |
| 515 size_t offset, | 520 size_t offset, |
| 516 bool postpone) { | 521 bool postpone) { |
| 517 DCHECK_LE(0, index); | 522 DCHECK_LE(0, index); |
| 518 int numBytes = base::checked_cast<int>(size); | 523 int numBytes = base::checked_cast<int>(size); |
| 519 | 524 |
| 520 void* buffer = nullptr; | 525 void* buffer = nullptr; |
| 521 int capacity = GetOutputBufferAddress(index, offset, &buffer); | 526 int capacity = GetOutputBufferAddress(index, offset, &buffer); |
| 522 numBytes = std::min(capacity, numBytes); | 527 numBytes = std::min(capacity, numBytes); |
| 523 CHECK_GE(numBytes, 0); | 528 CHECK_GE(numBytes, 0); |
| 524 | 529 |
| 525 JNIEnv* env = AttachCurrentThread(); | 530 JNIEnv* env = AttachCurrentThread(); |
| 526 ScopedJavaLocalRef<jbyteArray> byte_array = base::android::ToJavaByteArray( | 531 ScopedJavaLocalRef<jbyteArray> byte_array = base::android::ToJavaByteArray( |
| 527 env, static_cast<uint8*>(buffer), numBytes); | 532 env, static_cast<uint8_t*>(buffer), numBytes); |
| 528 return Java_MediaCodecBridge_playOutputBuffer(env, media_codec(), | 533 return Java_MediaCodecBridge_playOutputBuffer(env, media_codec(), |
| 529 byte_array.obj(), postpone); | 534 byte_array.obj(), postpone); |
| 530 } | 535 } |
| 531 | 536 |
| 532 void AudioCodecBridge::SetVolume(double volume) { | 537 void AudioCodecBridge::SetVolume(double volume) { |
| 533 JNIEnv* env = AttachCurrentThread(); | 538 JNIEnv* env = AttachCurrentThread(); |
| 534 Java_MediaCodecBridge_setVolume(env, media_codec(), volume); | 539 Java_MediaCodecBridge_setVolume(env, media_codec(), volume); |
| 535 } | 540 } |
| 536 | 541 |
| 537 // static | 542 // static |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 629 if (adaptive_playback_supported_for_testing_ == 0) | 634 if (adaptive_playback_supported_for_testing_ == 0) |
| 630 return false; | 635 return false; |
| 631 else if (adaptive_playback_supported_for_testing_ > 0) | 636 else if (adaptive_playback_supported_for_testing_ > 0) |
| 632 return true; | 637 return true; |
| 633 JNIEnv* env = AttachCurrentThread(); | 638 JNIEnv* env = AttachCurrentThread(); |
| 634 return Java_MediaCodecBridge_isAdaptivePlaybackSupported(env, media_codec(), | 639 return Java_MediaCodecBridge_isAdaptivePlaybackSupported(env, media_codec(), |
| 635 width, height); | 640 width, height); |
| 636 } | 641 } |
| 637 | 642 |
| 638 } // namespace media | 643 } // namespace media |
| OLD | NEW |