diff options
Diffstat (limited to 'media/base/android/media_codec_bridge.cc')
-rw-r--r-- | media/base/android/media_codec_bridge.cc | 150 |
1 files changed, 50 insertions, 100 deletions
diff --git a/media/base/android/media_codec_bridge.cc b/media/base/android/media_codec_bridge.cc index bd4c274..37949f4 100644 --- a/media/base/android/media_codec_bridge.cc +++ b/media/base/android/media_codec_bridge.cc @@ -13,70 +13,24 @@ #include "base/basictypes.h" #include "base/lazy_instance.h" #include "base/logging.h" +#include "base/safe_numerics.h" #include "base/stringprintf.h" -#include "jni/MediaCodec_jni.h" +#include "jni/MediaCodecBridge_jni.h" #include "jni/MediaFormat_jni.h" - using base::android::AttachCurrentThread; using base::android::ConvertUTF8ToJavaString; using base::android::ScopedJavaLocalRef; namespace { -static jclass g_MediaCodecBufferInfo_clazz = NULL; - -static const char kMediaCodecBufferInfoClassPath[] = - "android/media/MediaCodec$BufferInfo"; - -static bool MediaCodecBufferInfo_RegisterNativesImpl(JNIEnv* env) { - g_MediaCodecBufferInfo_clazz = reinterpret_cast<jclass>(env->NewGlobalRef( - base::android::GetClass(env, kMediaCodecBufferInfoClassPath).obj())); - base::android::CheckException(env); - return true; -} - -static void GetBufferInfo(JNIEnv* env, jobject buffer_info, int* offset, - int* size, int64* presentation_time, int* flags) { - static jfieldID offset_id = - env->GetFieldID(g_MediaCodecBufferInfo_clazz, "offset", "I"); - static jfieldID size_id = - env->GetFieldID(g_MediaCodecBufferInfo_clazz, "size", "I"); - static jfieldID presentation_time_id = - env->GetFieldID(g_MediaCodecBufferInfo_clazz, "presentationTimeUs", "J"); - static jfieldID flags_id = - env->GetFieldID(g_MediaCodecBufferInfo_clazz, "flags", "I"); - - *offset = env->GetIntField(buffer_info, offset_id); - *size = env->GetIntField(buffer_info, size_id); - *presentation_time = env->GetLongField(buffer_info, presentation_time_id); - *flags = env->GetIntField(buffer_info, flags_id); -} - -static base::subtle::AtomicWord g_MediaCodecBufferInfo_Constructor = 0; -static ScopedJavaLocalRef<jobject> Java_MediaCodecBufferInfo_Constructor( - JNIEnv* env) { - /* Must call RegisterNativesImpl() */ - DCHECK(g_MediaCodecBufferInfo_clazz); - jmethodID method_id = - base::android::MethodID::LazyGet<base::android::MethodID::TYPE_INSTANCE>( - env, g_MediaCodecBufferInfo_clazz, - "<init>", "()V", - &g_MediaCodecBufferInfo_Constructor); - - jobject ret = env->NewObject(g_MediaCodecBufferInfo_clazz, method_id); - base::android::CheckException(env); - return ScopedJavaLocalRef<jobject>(env, ret); -} - class MediaCodecNativeRegisterer { public: MediaCodecNativeRegisterer() { JNIEnv* env = AttachCurrentThread(); jni_initialized_ = - MediaCodecBufferInfo_RegisterNativesImpl(env) && - JNI_MediaCodec::RegisterNativesImpl(env) && + media::RegisterNativesImpl(env) && JNI_MediaFormat::RegisterNativesImpl(env); } @@ -141,44 +95,37 @@ MediaCodecBridge::MediaCodecBridge(const char* mime) { CHECK(g_native_registerer.Pointer()->IsRegistered()); DCHECK(mime); - ScopedJavaLocalRef<jstring> j_type = - ConvertUTF8ToJavaString(env, mime); - - ScopedJavaLocalRef<jobject> tmp( - JNI_MediaCodec::Java_MediaCodec_createDecoderByType(env, j_type.obj())); - DCHECK(!tmp.is_null()); - j_media_codec_.Reset(tmp); + ScopedJavaLocalRef<jstring> j_type = ConvertUTF8ToJavaString(env, mime); + j_media_codec_.Reset(Java_MediaCodecBridge_create( + env, j_type.obj())); } MediaCodecBridge::~MediaCodecBridge() { JNIEnv* env = AttachCurrentThread(); CHECK(env); - - JNI_MediaCodec::Java_MediaCodec_release(env, j_media_codec_.obj()); + Java_MediaCodecBridge_release(env, j_media_codec_.obj()); } void MediaCodecBridge::StartInternal() { JNIEnv* env = AttachCurrentThread(); - JNI_MediaCodec::Java_MediaCodec_start(env, j_media_codec_.obj()); - GetInputBuffers(); + Java_MediaCodecBridge_start(env, j_media_codec_.obj()); } void MediaCodecBridge::Reset() { JNIEnv* env = AttachCurrentThread(); - JNI_MediaCodec::Java_MediaCodec_flush(env, j_media_codec_.obj()); + Java_MediaCodecBridge_flush(env, j_media_codec_.obj()); } void MediaCodecBridge::Stop() { JNIEnv* env = AttachCurrentThread(); - JNI_MediaCodec::Java_MediaCodec_stop(env, j_media_codec_.obj()); + Java_MediaCodecBridge_stop(env, j_media_codec_.obj()); } void MediaCodecBridge::GetOutputFormat(int* width, int* height) { JNIEnv* env = AttachCurrentThread(); ScopedJavaLocalRef<jobject> j_format( - JNI_MediaCodec::Java_MediaCodec_getOutputFormat( - env, j_media_codec_.obj())); + Java_MediaCodecBridge_getOutputFormat(env, j_media_codec_.obj())); if (!j_format.is_null()) { ScopedJavaLocalRef<jstring> j_key_width = ConvertUTF8ToJavaString(env, "width"); @@ -198,17 +145,17 @@ size_t MediaCodecBridge::QueueInputBuffer( JNIEnv* env = AttachCurrentThread(); ScopedJavaLocalRef<jobject> j_buffer( - env, env->GetObjectArrayElement(j_input_buffers_.obj(), index)); + Java_MediaCodecBridge_getInputBuffer(env, j_media_codec_.obj(), index)); uint8* direct_buffer = static_cast<uint8*>(env->GetDirectBufferAddress(j_buffer.obj())); int64 buffer_capacity = env->GetDirectBufferCapacity(j_buffer.obj()); size_t size_to_copy = (buffer_capacity < size) ? buffer_capacity : size; + if (size_to_copy > 0) memcpy(direct_buffer, data, size_to_copy); - - JNI_MediaCodec::Java_MediaCodec_queueInputBuffer( + Java_MediaCodecBridge_queueInputBuffer( env, j_media_codec_.obj(), index, 0, size_to_copy, presentation_time.InMicroseconds(), 0); return size_to_copy; @@ -216,32 +163,36 @@ size_t MediaCodecBridge::QueueInputBuffer( void MediaCodecBridge::QueueEOS(int input_buffer_index) { JNIEnv* env = AttachCurrentThread(); - JNI_MediaCodec::Java_MediaCodec_queueInputBuffer( + Java_MediaCodecBridge_queueInputBuffer( env, j_media_codec_.obj(), input_buffer_index, 0, 0, 0, kBufferFlagEndOfStream); } int MediaCodecBridge::DequeueInputBuffer(base::TimeDelta timeout) { JNIEnv* env = AttachCurrentThread(); - return JNI_MediaCodec::Java_MediaCodec_dequeueInputBuffer( + return Java_MediaCodecBridge_dequeueInputBuffer( env, j_media_codec_.obj(), timeout.InMicroseconds()); } int MediaCodecBridge::DequeueOutputBuffer( - base::TimeDelta timeout, int* offset, int* size, + base::TimeDelta timeout, size_t* offset, size_t* size, base::TimeDelta* presentation_time, bool* end_of_stream) { JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef<jobject> j_info( - Java_MediaCodecBufferInfo_Constructor(env)); - jint j_buffer = JNI_MediaCodec::Java_MediaCodec_dequeueOutputBuffer( - env, j_media_codec_.obj(), j_info.obj(), timeout.InMicroseconds()); + ScopedJavaLocalRef<jobject> result = + Java_MediaCodecBridge_dequeueOutputBuffer(env, j_media_codec_.obj(), + timeout.InMicroseconds()); + int j_buffer = Java_DequeueOutputResult_index(env, result.obj()); if (j_buffer >= 0) { - int64 presentation_time_us; - int flags; - GetBufferInfo( - env, j_info.obj(), offset, size, &presentation_time_us, &flags); + int64 presentation_time_us = + Java_DequeueOutputResult_presentationTimeMicroseconds( + env, result.obj()); + int flags = Java_DequeueOutputResult_flags(env, result.obj()); + *offset = base::checked_numeric_cast<size_t>( + Java_DequeueOutputResult_offset(env, result.obj())); + *size = base::checked_numeric_cast<size_t>( + Java_DequeueOutputResult_numBytes(env, result.obj())); *presentation_time = base::TimeDelta::FromMicroseconds(presentation_time_us); *end_of_stream = flags & kBufferFlagEndOfStream; @@ -253,28 +204,13 @@ void MediaCodecBridge::ReleaseOutputBuffer(int index, bool render) { JNIEnv* env = AttachCurrentThread(); CHECK(env); - JNI_MediaCodec::Java_MediaCodec_releaseOutputBuffer( + Java_MediaCodecBridge_releaseOutputBuffer( env, j_media_codec_.obj(), index, render); } -int MediaCodecBridge::GetInputBuffers() { - JNIEnv* env = AttachCurrentThread(); - - j_input_buffers_.Reset( - JNI_MediaCodec::Java_MediaCodec_getInputBuffers( - env, j_media_codec_.obj())); - - return env->GetArrayLength(j_input_buffers_.obj()); -} - -int MediaCodecBridge::GetOutputBuffers() { +void MediaCodecBridge::GetOutputBuffers() { JNIEnv* env = AttachCurrentThread(); - - j_output_buffers_.Reset( - JNI_MediaCodec::Java_MediaCodec_getOutputBuffers( - env, j_media_codec_.obj())); - - return env->GetArrayLength(j_output_buffers_.obj()); + Java_MediaCodecBridge_getOutputBuffers(env, j_media_codec_.obj()); } AudioCodecBridge::AudioCodecBridge(const AudioCodec codec) @@ -283,7 +219,7 @@ AudioCodecBridge::AudioCodecBridge(const AudioCodec codec) bool AudioCodecBridge::Start( const AudioCodec codec, int sample_rate, int channel_count, - const uint8* extra_data, size_t extra_data_size) { + const uint8* extra_data, size_t extra_data_size, bool play_audio) { JNIEnv* env = AttachCurrentThread(); DCHECK(AudioCodecToMimeType(codec)); @@ -344,12 +280,26 @@ bool AudioCodecBridge::Start( env->DeleteLocalRef(identification_header); } - JNI_MediaCodec::Java_MediaCodec_configure( - env, media_codec(), j_format.obj(), NULL, NULL, 0); + Java_MediaCodecBridge_configureAudio( + env, media_codec(), j_format.obj(), NULL, 0, play_audio); StartInternal(); return true; } +void AudioCodecBridge::PlayOutputBuffer(int index, size_t size) { + DCHECK_LE(0, index); + int numBytes = base::checked_numeric_cast<int>(size); + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jobject> buf = + Java_MediaCodecBridge_getOutputBuffer(env, media_codec(), index); + uint8* buffer = static_cast<uint8*>(env->GetDirectBufferAddress(buf.obj())); + + ScopedJavaLocalRef<jbyteArray> byte_array = + base::android::ToJavaByteArray(env, buffer, numBytes); + Java_MediaCodecBridge_playOutputBuffer( + env, media_codec(), byte_array.obj()); +} + VideoCodecBridge::VideoCodecBridge(const VideoCodec codec) : MediaCodecBridge(VideoCodecToMimeType(codec)) { } @@ -365,7 +315,7 @@ bool VideoCodecBridge::Start( JNI_MediaFormat::Java_MediaFormat_createVideoFormat( env, j_mime.obj(), size.width(), size.height())); DCHECK(!j_format.is_null()); - JNI_MediaCodec::Java_MediaCodec_configure( + Java_MediaCodecBridge_configureVideo( env, media_codec(), j_format.obj(), surface, NULL, 0); StartInternal(); return true; |