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 3 // found in the LICENSE file. 4 5 #include "media/base/android/media_codec_bridge.h" 6 7 #include <jni.h> 8 #include <string> 9 10 #include "base/android/build_info.h" 11 #include "base/android/jni_android.h" 12 #include "base/android/jni_array.h" 13 #include "base/android/jni_string.h" 14 #include "base/basictypes.h" 15 #include "base/lazy_instance.h" 16 #include "base/logging.h" 17 #include "base/safe_numerics.h" 18 #include "base/strings/string_util.h" 19 #include "base/strings/stringprintf.h" 20 #include "jni/MediaCodecBridge_jni.h" 21 #include "media/base/bit_reader.h" 22 #include "media/base/decrypt_config.h" 23 24 using base::android::AttachCurrentThread; 25 using base::android::ConvertJavaStringToUTF8; 26 using base::android::ConvertUTF8ToJavaString; 27 using base::android::ScopedJavaLocalRef; 28 29 namespace media { 30 31 enum { 32 kBufferFlagSyncFrame = 1, // BUFFER_FLAG_SYNC_FRAME 33 kBufferFlagEndOfStream = 4, // BUFFER_FLAG_END_OF_STREAM 34 kConfigureFlagEncode = 1, // CONFIGURE_FLAG_ENCODE 35 }; 36 37 static const std::string AudioCodecToAndroidMimeType(const AudioCodec& codec) { 38 switch (codec) { 39 case kCodecMP3: 40 return "audio/mpeg"; 41 case kCodecVorbis: 42 return "audio/vorbis"; 43 case kCodecAAC: 44 return "audio/mp4a-latm"; 45 default: 46 return std::string(); 47 } 48 } 49 50 static const std::string VideoCodecToAndroidMimeType(const VideoCodec& codec) { 51 switch (codec) { 52 case kCodecH264: 53 return "video/avc"; 54 case kCodecVP8: 55 return "video/x-vnd.on2.vp8"; 56 case kCodecVP9: 57 return "video/x-vnd.on2.vp9"; 58 default: 59 return std::string(); 60 } 61 } 62 63 static const std::string CodecTypeToAndroidMimeType(const std::string& codec) { 64 // TODO(xhwang): Shall we handle more detailed strings like "mp4a.40.2"? 65 if (codec == "avc1") 66 return "video/avc"; 67 if (codec == "mp4a") 68 return "audio/mp4a-latm"; 69 if (codec == "vp8" || codec == "vp8.0") 70 return "video/x-vnd.on2.vp8"; 71 if (codec == "vp9" || codec == "vp9.0") 72 return "video/x-vnd.on2.vp9"; 73 if (codec == "vorbis") 74 return "audio/vorbis"; 75 return std::string(); 76 } 77 78 // TODO(qinmin): using a map to help all the conversions in this class. 79 static const std::string AndroidMimeTypeToCodecType(const std::string& mime) { 80 if (mime == "video/mp4v-es") 81 return "mp4v"; 82 if (mime == "video/avc") 83 return "avc1"; 84 if (mime == "video/x-vnd.on2.vp8") 85 return "vp8"; 86 if (mime == "video/x-vnd.on2.vp9") 87 return "vp9"; 88 if (mime == "audio/mp4a-latm") 89 return "mp4a"; 90 if (mime == "audio/mpeg") 91 return "mp3"; 92 if (mime == "audio/vorbis") 93 return "vorbis"; 94 return std::string(); 95 } 96 97 static ScopedJavaLocalRef<jintArray> 98 ToJavaIntArray(JNIEnv* env, scoped_ptr<jint[]> native_array, int size) { 99 ScopedJavaLocalRef<jintArray> j_array(env, env->NewIntArray(size)); 100 env->SetIntArrayRegion(j_array.obj(), 0, size, native_array.get()); 101 return j_array; 102 } 103 104 // static 105 bool MediaCodecBridge::IsAvailable() { 106 // MediaCodec is only available on JB and greater. 107 return base::android::BuildInfo::GetInstance()->sdk_int() >= 16; 108 } 109 110 // static 111 bool MediaCodecBridge::SupportsSetParameters() { 112 // MediaCodec.setParameters() is only available starting with K. 113 return base::android::BuildInfo::GetInstance()->sdk_int() >= 19; 114 } 115 116 // static 117 std::vector<MediaCodecBridge::CodecsInfo> MediaCodecBridge::GetCodecsInfo() { 118 std::vector<CodecsInfo> codecs_info; 119 JNIEnv* env = AttachCurrentThread(); 120 if (!IsAvailable()) 121 return codecs_info; 122 123 std::string mime_type; 124 std::string codec_name; 125 ScopedJavaLocalRef<jobjectArray> j_codec_info_array = 126 Java_MediaCodecBridge_getCodecsInfo(env); 127 jsize len = env->GetArrayLength(j_codec_info_array.obj()); 128 for (jsize i = 0; i < len; ++i) { 129 ScopedJavaLocalRef<jobject> j_info( 130 env, env->GetObjectArrayElement(j_codec_info_array.obj(), i)); 131 ScopedJavaLocalRef<jstring> j_codec_type = 132 Java_CodecInfo_codecType(env, j_info.obj()); 133 ConvertJavaStringToUTF8(env, j_codec_type.obj(), &mime_type); 134 ScopedJavaLocalRef<jstring> j_codec_name = 135 Java_CodecInfo_codecName(env, j_info.obj()); 136 CodecsInfo info; 137 info.codecs = AndroidMimeTypeToCodecType(mime_type); 138 ConvertJavaStringToUTF8(env, j_codec_name.obj(), &info.name); 139 info.direction = static_cast<MediaCodecDirection>( 140 Java_CodecInfo_direction(env, j_info.obj())); 141 codecs_info.push_back(info); 142 } 143 return codecs_info; 144 } 145 146 // static 147 bool MediaCodecBridge::CanDecode(const std::string& codec, bool is_secure) { 148 JNIEnv* env = AttachCurrentThread(); 149 std::string mime = CodecTypeToAndroidMimeType(codec); 150 if (mime.empty()) 151 return false; 152 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime); 153 ScopedJavaLocalRef<jobject> j_media_codec_bridge = 154 Java_MediaCodecBridge_create(env, j_mime.obj(), is_secure, false); 155 if (!j_media_codec_bridge.is_null()) { 156 Java_MediaCodecBridge_release(env, j_media_codec_bridge.obj()); 157 return true; 158 } 159 return false; 160 } 161 162 // static 163 bool MediaCodecBridge::IsKnownUnaccelerated(const std::string& mime_type, 164 MediaCodecDirection direction) { 165 std::string codec_type = AndroidMimeTypeToCodecType(mime_type); 166 std::vector<media::MediaCodecBridge::CodecsInfo> codecs_info = 167 MediaCodecBridge::GetCodecsInfo(); 168 for (size_t i = 0; i < codecs_info.size(); ++i) { 169 if (codecs_info[i].codecs == codec_type && 170 codecs_info[i].direction == direction) { 171 // It would be nice if MediaCodecInfo externalized some notion of 172 // HW-acceleration but it doesn't. Android Media guidance is that the 173 // prefix below is always used for SW decoders, so that's what we use. 174 return StartsWithASCII(codecs_info[i].name, "OMX.google.", true); 175 } 176 } 177 return true; 178 } 179 180 MediaCodecBridge::MediaCodecBridge(const std::string& mime, 181 bool is_secure, 182 MediaCodecDirection direction) { 183 JNIEnv* env = AttachCurrentThread(); 184 CHECK(env); 185 DCHECK(!mime.empty()); 186 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime); 187 j_media_codec_.Reset( 188 Java_MediaCodecBridge_create(env, j_mime.obj(), is_secure, direction)); 189 } 190 191 MediaCodecBridge::~MediaCodecBridge() { 192 JNIEnv* env = AttachCurrentThread(); 193 CHECK(env); 194 if (j_media_codec_.obj()) 195 Java_MediaCodecBridge_release(env, j_media_codec_.obj()); 196 } 197 198 bool MediaCodecBridge::StartInternal() { 199 JNIEnv* env = AttachCurrentThread(); 200 return Java_MediaCodecBridge_start(env, j_media_codec_.obj()) && 201 GetOutputBuffers(); 202 } 203 204 MediaCodecStatus MediaCodecBridge::Reset() { 205 JNIEnv* env = AttachCurrentThread(); 206 return static_cast<MediaCodecStatus>( 207 Java_MediaCodecBridge_flush(env, j_media_codec_.obj())); 208 } 209 210 void MediaCodecBridge::Stop() { 211 JNIEnv* env = AttachCurrentThread(); 212 Java_MediaCodecBridge_stop(env, j_media_codec_.obj()); 213 } 214 215 void MediaCodecBridge::GetOutputFormat(int* width, int* height) { 216 JNIEnv* env = AttachCurrentThread(); 217 218 *width = Java_MediaCodecBridge_getOutputWidth(env, j_media_codec_.obj()); 219 *height = Java_MediaCodecBridge_getOutputHeight(env, j_media_codec_.obj()); 220 } 221 222 MediaCodecStatus MediaCodecBridge::QueueInputBuffer( 223 int index, 224 const uint8* data, 225 size_t data_size, 226 const base::TimeDelta& presentation_time) { 227 DVLOG(3) << __PRETTY_FUNCTION__ << index << ": " << data_size; 228 if (data_size > base::checked_numeric_cast<size_t>(kint32max)) 229 return MEDIA_CODEC_ERROR; 230 if (data && !FillInputBuffer(index, data, data_size)) 231 return MEDIA_CODEC_ERROR; 232 JNIEnv* env = AttachCurrentThread(); 233 return static_cast<MediaCodecStatus>( 234 Java_MediaCodecBridge_queueInputBuffer(env, 235 j_media_codec_.obj(), 236 index, 237 0, 238 data_size, 239 presentation_time.InMicroseconds(), 240 0)); 241 } 242 243 MediaCodecStatus MediaCodecBridge::QueueSecureInputBuffer( 244 int index, 245 const uint8* data, 246 size_t data_size, 247 const uint8* key_id, 248 int key_id_size, 249 const uint8* iv, 250 int iv_size, 251 const SubsampleEntry* subsamples, 252 int subsamples_size, 253 const base::TimeDelta& presentation_time) { 254 DVLOG(3) << __PRETTY_FUNCTION__ << index << ": " << data_size; 255 if (data_size > base::checked_numeric_cast<size_t>(kint32max)) 256 return MEDIA_CODEC_ERROR; 257 if (data && !FillInputBuffer(index, data, data_size)) 258 return MEDIA_CODEC_ERROR; 259 260 JNIEnv* env = AttachCurrentThread(); 261 ScopedJavaLocalRef<jbyteArray> j_key_id = 262 base::android::ToJavaByteArray(env, key_id, key_id_size); 263 ScopedJavaLocalRef<jbyteArray> j_iv = 264 base::android::ToJavaByteArray(env, iv, iv_size); 265 266 // MediaCodec.CryptoInfo documentations says passing NULL for |clear_array| 267 // to indicate that all data is encrypted. But it doesn't specify what 268 // |cypher_array| and |subsamples_size| should be in that case. Passing 269 // one subsample here just to be on the safe side. 270 int new_subsamples_size = subsamples_size == 0 ? 1 : subsamples_size; 271 272 scoped_ptr<jint[]> native_clear_array(new jint[new_subsamples_size]); 273 scoped_ptr<jint[]> native_cypher_array(new jint[new_subsamples_size]); 274 275 if (subsamples_size == 0) { 276 DCHECK(!subsamples); 277 native_clear_array[0] = 0; 278 native_cypher_array[0] = data_size; 279 } else { 280 DCHECK_GT(subsamples_size, 0); 281 DCHECK(subsamples); 282 for (int i = 0; i < subsamples_size; ++i) { 283 DCHECK(subsamples[i].clear_bytes <= std::numeric_limits<uint16>::max()); 284 if (subsamples[i].cypher_bytes > 285 static_cast<uint32>(std::numeric_limits<jint>::max())) { 286 return MEDIA_CODEC_ERROR; 287 } 288 289 native_clear_array[i] = subsamples[i].clear_bytes; 290 native_cypher_array[i] = subsamples[i].cypher_bytes; 291 } 292 } 293 294 ScopedJavaLocalRef<jintArray> clear_array = 295 ToJavaIntArray(env, native_clear_array.Pass(), new_subsamples_size); 296 ScopedJavaLocalRef<jintArray> cypher_array = 297 ToJavaIntArray(env, native_cypher_array.Pass(), new_subsamples_size); 298 299 return static_cast<MediaCodecStatus>( 300 Java_MediaCodecBridge_queueSecureInputBuffer( 301 env, 302 j_media_codec_.obj(), 303 index, 304 0, 305 j_iv.obj(), 306 j_key_id.obj(), 307 clear_array.obj(), 308 cypher_array.obj(), 309 new_subsamples_size, 310 presentation_time.InMicroseconds())); 311 } 312 313 void MediaCodecBridge::QueueEOS(int input_buffer_index) { 314 DVLOG(3) << __PRETTY_FUNCTION__ << ": " << input_buffer_index; 315 JNIEnv* env = AttachCurrentThread(); 316 Java_MediaCodecBridge_queueInputBuffer(env, 317 j_media_codec_.obj(), 318 input_buffer_index, 319 0, 320 0, 321 0, 322 kBufferFlagEndOfStream); 323 } 324 325 MediaCodecStatus MediaCodecBridge::DequeueInputBuffer( 326 const base::TimeDelta& timeout, 327 int* index) { 328 JNIEnv* env = AttachCurrentThread(); 329 ScopedJavaLocalRef<jobject> result = Java_MediaCodecBridge_dequeueInputBuffer( 330 env, j_media_codec_.obj(), timeout.InMicroseconds()); 331 *index = Java_DequeueInputResult_index(env, result.obj()); 332 MediaCodecStatus status = static_cast<MediaCodecStatus>( 333 Java_DequeueInputResult_status(env, result.obj())); 334 DVLOG(3) << __PRETTY_FUNCTION__ << ": status: " << status 335 << ", index: " << *index; 336 return status; 337 } 338 339 MediaCodecStatus MediaCodecBridge::DequeueOutputBuffer( 340 const base::TimeDelta& timeout, 341 int* index, 342 size_t* offset, 343 size_t* size, 344 base::TimeDelta* presentation_time, 345 bool* end_of_stream, 346 bool* key_frame) { 347 JNIEnv* env = AttachCurrentThread(); 348 ScopedJavaLocalRef<jobject> result = 349 Java_MediaCodecBridge_dequeueOutputBuffer( 350 env, j_media_codec_.obj(), timeout.InMicroseconds()); 351 *index = Java_DequeueOutputResult_index(env, result.obj()); 352 *offset = base::checked_numeric_cast<size_t>( 353 Java_DequeueOutputResult_offset(env, result.obj())); 354 *size = base::checked_numeric_cast<size_t>( 355 Java_DequeueOutputResult_numBytes(env, result.obj())); 356 if (presentation_time) { 357 *presentation_time = base::TimeDelta::FromMicroseconds( 358 Java_DequeueOutputResult_presentationTimeMicroseconds(env, 359 result.obj())); 360 } 361 int flags = Java_DequeueOutputResult_flags(env, result.obj()); 362 if (end_of_stream) 363 *end_of_stream = flags & kBufferFlagEndOfStream; 364 if (key_frame) 365 *key_frame = flags & kBufferFlagSyncFrame; 366 MediaCodecStatus status = static_cast<MediaCodecStatus>( 367 Java_DequeueOutputResult_status(env, result.obj())); 368 DVLOG(3) << __PRETTY_FUNCTION__ << ": status: " << status 369 << ", index: " << *index << ", offset: " << *offset 370 << ", size: " << *size << ", flags: " << flags; 371 return status; 372 } 373 374 void MediaCodecBridge::ReleaseOutputBuffer(int index, bool render) { 375 DVLOG(3) << __PRETTY_FUNCTION__ << ": " << index; 376 JNIEnv* env = AttachCurrentThread(); 377 CHECK(env); 378 379 Java_MediaCodecBridge_releaseOutputBuffer( 380 env, j_media_codec_.obj(), index, render); 381 } 382 383 int MediaCodecBridge::GetInputBuffersCount() { 384 JNIEnv* env = AttachCurrentThread(); 385 return Java_MediaCodecBridge_getInputBuffersCount(env, j_media_codec_.obj()); 386 } 387 388 int MediaCodecBridge::GetOutputBuffersCount() { 389 JNIEnv* env = AttachCurrentThread(); 390 return Java_MediaCodecBridge_getOutputBuffersCount(env, j_media_codec_.obj()); 391 } 392 393 size_t MediaCodecBridge::GetOutputBuffersCapacity() { 394 JNIEnv* env = AttachCurrentThread(); 395 return Java_MediaCodecBridge_getOutputBuffersCapacity(env, 396 j_media_codec_.obj()); 397 } 398 399 bool MediaCodecBridge::GetOutputBuffers() { 400 JNIEnv* env = AttachCurrentThread(); 401 return Java_MediaCodecBridge_getOutputBuffers(env, j_media_codec_.obj()); 402 } 403 404 void MediaCodecBridge::GetInputBuffer(int input_buffer_index, 405 uint8** data, 406 size_t* capacity) { 407 JNIEnv* env = AttachCurrentThread(); 408 ScopedJavaLocalRef<jobject> j_buffer(Java_MediaCodecBridge_getInputBuffer( 409 env, j_media_codec_.obj(), input_buffer_index)); 410 *data = static_cast<uint8*>(env->GetDirectBufferAddress(j_buffer.obj())); 411 *capacity = base::checked_numeric_cast<size_t>( 412 env->GetDirectBufferCapacity(j_buffer.obj())); 413 } 414 415 bool MediaCodecBridge::CopyFromOutputBuffer(int index, 416 size_t offset, 417 void* dst, 418 int dst_size) { 419 JNIEnv* env = AttachCurrentThread(); 420 ScopedJavaLocalRef<jobject> j_buffer( 421 Java_MediaCodecBridge_getOutputBuffer(env, j_media_codec_.obj(), index)); 422 void* src_data = 423 reinterpret_cast<uint8*>(env->GetDirectBufferAddress(j_buffer.obj())) + 424 offset; 425 int src_capacity = env->GetDirectBufferCapacity(j_buffer.obj()) - offset; 426 if (src_capacity < dst_size) 427 return false; 428 memcpy(dst, src_data, dst_size); 429 return true; 430 } 431 432 bool MediaCodecBridge::FillInputBuffer(int index, 433 const uint8* data, 434 size_t size) { 435 uint8* dst = NULL; 436 size_t capacity = 0; 437 GetInputBuffer(index, &dst, &capacity); 438 CHECK(dst); 439 440 if (size > capacity) { 441 LOG(ERROR) << "Input buffer size " << size 442 << " exceeds MediaCodec input buffer capacity: " << capacity; 443 return false; 444 } 445 446 memcpy(dst, data, size); 447 return true; 448 } 449 450 AudioCodecBridge::AudioCodecBridge(const std::string& mime) 451 // Audio codec doesn't care about security level and there is no need for 452 // audio encoding yet. 453 : MediaCodecBridge(mime, false, MEDIA_CODEC_DECODER) {} 454 455 bool AudioCodecBridge::Start(const AudioCodec& codec, 456 int sample_rate, 457 int channel_count, 458 const uint8* extra_data, 459 size_t extra_data_size, 460 bool play_audio, 461 jobject media_crypto) { 462 JNIEnv* env = AttachCurrentThread(); 463 464 if (!media_codec()) 465 return false; 466 467 std::string codec_string = AudioCodecToAndroidMimeType(codec); 468 if (codec_string.empty()) 469 return false; 470 471 ScopedJavaLocalRef<jstring> j_mime = 472 ConvertUTF8ToJavaString(env, codec_string); 473 ScopedJavaLocalRef<jobject> j_format(Java_MediaCodecBridge_createAudioFormat( 474 env, j_mime.obj(), sample_rate, channel_count)); 475 DCHECK(!j_format.is_null()); 476 477 if (!ConfigureMediaFormat(j_format.obj(), codec, extra_data, extra_data_size)) 478 return false; 479 480 if (!Java_MediaCodecBridge_configureAudio( 481 env, media_codec(), j_format.obj(), media_crypto, 0, play_audio)) { 482 return false; 483 } 484 485 return StartInternal(); 486 } 487 488 bool AudioCodecBridge::ConfigureMediaFormat(jobject j_format, 489 const AudioCodec& codec, 490 const uint8* extra_data, 491 size_t extra_data_size) { 492 if (extra_data_size == 0) 493 return true; 494 495 JNIEnv* env = AttachCurrentThread(); 496 switch (codec) { 497 case kCodecVorbis: { 498 if (extra_data[0] != 2) { 499 LOG(ERROR) << "Invalid number of vorbis headers before the codec " 500 << "header: " << extra_data[0]; 501 return false; 502 } 503 504 size_t header_length[2]; 505 // |total_length| keeps track of the total number of bytes before the last 506 // header. 507 size_t total_length = 1; 508 const uint8* current_pos = extra_data; 509 // Calculate the length of the first 2 headers. 510 for (int i = 0; i < 2; ++i) { 511 header_length[i] = 0; 512 while (total_length < extra_data_size) { 513 size_t size = *(++current_pos); 514 total_length += 1 + size; 515 if (total_length > 0x80000000) { 516 LOG(ERROR) << "Vorbis header size too large"; 517 return false; 518 } 519 header_length[i] += size; 520 if (size < 0xFF) 521 break; 522 } 523 if (total_length >= extra_data_size) { 524 LOG(ERROR) << "Invalid vorbis header size in the extra data"; 525 return false; 526 } 527 } 528 current_pos++; 529 // The first header is identification header. 530 ScopedJavaLocalRef<jbyteArray> first_header = 531 base::android::ToJavaByteArray(env, current_pos, header_length[0]); 532 Java_MediaCodecBridge_setCodecSpecificData( 533 env, j_format, 0, first_header.obj()); 534 // The last header is codec header. 535 ScopedJavaLocalRef<jbyteArray> last_header = 536 base::android::ToJavaByteArray( 537 env, extra_data + total_length, extra_data_size - total_length); 538 Java_MediaCodecBridge_setCodecSpecificData( 539 env, j_format, 1, last_header.obj()); 540 break; 541 } 542 case kCodecAAC: { 543 media::BitReader reader(extra_data, extra_data_size); 544 545 // The following code is copied from aac.cc 546 // TODO(qinmin): refactor the code in aac.cc to make it more reusable. 547 uint8 profile = 0; 548 uint8 frequency_index = 0; 549 uint8 channel_config = 0; 550 if (!reader.ReadBits(5, &profile) || 551 !reader.ReadBits(4, &frequency_index)) { 552 LOG(ERROR) << "Unable to parse AAC header"; 553 return false; 554 } 555 if (0xf == frequency_index && !reader.SkipBits(24)) { 556 LOG(ERROR) << "Unable to parse AAC header"; 557 return false; 558 } 559 if (!reader.ReadBits(4, &channel_config)) { 560 LOG(ERROR) << "Unable to parse AAC header"; 561 return false; 562 } 563 564 if (profile < 1 || profile > 4 || frequency_index == 0xf || 565 channel_config > 7) { 566 LOG(ERROR) << "Invalid AAC header"; 567 return false; 568 } 569 const size_t kCsdLength = 2; 570 uint8 csd[kCsdLength]; 571 csd[0] = profile << 3 | frequency_index >> 1; 572 csd[1] = (frequency_index & 0x01) << 7 | channel_config << 3; 573 ScopedJavaLocalRef<jbyteArray> byte_array = 574 base::android::ToJavaByteArray(env, csd, kCsdLength); 575 Java_MediaCodecBridge_setCodecSpecificData( 576 env, j_format, 0, byte_array.obj()); 577 578 // TODO(qinmin): pass an extra variable to this function to determine 579 // whether we need to call this. 580 Java_MediaCodecBridge_setFrameHasADTSHeader(env, j_format); 581 break; 582 } 583 default: 584 LOG(ERROR) << "Invalid header encountered for codec: " 585 << AudioCodecToAndroidMimeType(codec); 586 return false; 587 } 588 return true; 589 } 590 591 void AudioCodecBridge::PlayOutputBuffer(int index, size_t size) { 592 DCHECK_LE(0, index); 593 int numBytes = base::checked_numeric_cast<int>(size); 594 JNIEnv* env = AttachCurrentThread(); 595 ScopedJavaLocalRef<jobject> buf = 596 Java_MediaCodecBridge_getOutputBuffer(env, media_codec(), index); 597 uint8* buffer = static_cast<uint8*>(env->GetDirectBufferAddress(buf.obj())); 598 599 ScopedJavaLocalRef<jbyteArray> byte_array = 600 base::android::ToJavaByteArray(env, buffer, numBytes); 601 Java_MediaCodecBridge_playOutputBuffer(env, media_codec(), byte_array.obj()); 602 } 603 604 void AudioCodecBridge::SetVolume(double volume) { 605 JNIEnv* env = AttachCurrentThread(); 606 Java_MediaCodecBridge_setVolume(env, media_codec(), volume); 607 } 608 609 AudioCodecBridge* AudioCodecBridge::Create(const AudioCodec& codec) { 610 const std::string mime = AudioCodecToAndroidMimeType(codec); 611 return mime.empty() ? NULL : new AudioCodecBridge(mime); 612 } 613 614 // static 615 bool AudioCodecBridge::IsKnownUnaccelerated(const AudioCodec& codec) { 616 return MediaCodecBridge::IsKnownUnaccelerated( 617 AudioCodecToAndroidMimeType(codec), MEDIA_CODEC_DECODER); 618 } 619 620 // static 621 bool VideoCodecBridge::IsKnownUnaccelerated(const VideoCodec& codec, 622 MediaCodecDirection direction) { 623 return MediaCodecBridge::IsKnownUnaccelerated( 624 VideoCodecToAndroidMimeType(codec), direction); 625 } 626 627 VideoCodecBridge* VideoCodecBridge::CreateDecoder(const VideoCodec& codec, 628 bool is_secure, 629 const gfx::Size& size, 630 jobject surface, 631 jobject media_crypto) { 632 JNIEnv* env = AttachCurrentThread(); 633 const std::string mime = VideoCodecToAndroidMimeType(codec); 634 if (mime.empty()) 635 return NULL; 636 637 scoped_ptr<VideoCodecBridge> bridge( 638 new VideoCodecBridge(mime, is_secure, MEDIA_CODEC_DECODER)); 639 if (!bridge->media_codec()) 640 return NULL; 641 642 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime); 643 ScopedJavaLocalRef<jobject> j_format( 644 Java_MediaCodecBridge_createVideoDecoderFormat( 645 env, j_mime.obj(), size.width(), size.height())); 646 DCHECK(!j_format.is_null()); 647 if (!Java_MediaCodecBridge_configureVideo(env, 648 bridge->media_codec(), 649 j_format.obj(), 650 surface, 651 media_crypto, 652 0)) { 653 return NULL; 654 } 655 656 return bridge->StartInternal() ? bridge.release() : NULL; 657 } 658 659 VideoCodecBridge* VideoCodecBridge::CreateEncoder(const VideoCodec& codec, 660 const gfx::Size& size, 661 int bit_rate, 662 int frame_rate, 663 int i_frame_interval, 664 int color_format) { 665 JNIEnv* env = AttachCurrentThread(); 666 const std::string mime = VideoCodecToAndroidMimeType(codec); 667 if (mime.empty()) 668 return NULL; 669 670 scoped_ptr<VideoCodecBridge> bridge( 671 new VideoCodecBridge(mime, false, MEDIA_CODEC_ENCODER)); 672 if (!bridge->media_codec()) 673 return NULL; 674 675 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime); 676 ScopedJavaLocalRef<jobject> j_format( 677 Java_MediaCodecBridge_createVideoEncoderFormat(env, 678 j_mime.obj(), 679 size.width(), 680 size.height(), 681 bit_rate, 682 frame_rate, 683 i_frame_interval, 684 color_format)); 685 DCHECK(!j_format.is_null()); 686 if (!Java_MediaCodecBridge_configureVideo(env, 687 bridge->media_codec(), 688 j_format.obj(), 689 NULL, 690 NULL, 691 kConfigureFlagEncode)) { 692 return NULL; 693 } 694 695 return bridge->StartInternal() ? bridge.release() : NULL; 696 } 697 698 VideoCodecBridge::VideoCodecBridge(const std::string& mime, 699 bool is_secure, 700 MediaCodecDirection direction) 701 : MediaCodecBridge(mime, is_secure, direction) {} 702 703 void VideoCodecBridge::SetVideoBitrate(int bps) { 704 JNIEnv* env = AttachCurrentThread(); 705 Java_MediaCodecBridge_setVideoBitrate(env, media_codec(), bps); 706 } 707 708 void VideoCodecBridge::RequestKeyFrameSoon() { 709 JNIEnv* env = AttachCurrentThread(); 710 Java_MediaCodecBridge_requestKeyFrameSoon(env, media_codec()); 711 } 712 713 bool MediaCodecBridge::RegisterMediaCodecBridge(JNIEnv* env) { 714 return RegisterNativesImpl(env); 715 } 716 717 } // namespace media 718