summaryrefslogtreecommitdiffstats
path: root/media/base/android/media_codec_bridge.cc
diff options
context:
space:
mode:
Diffstat (limited to 'media/base/android/media_codec_bridge.cc')
-rw-r--r--media/base/android/media_codec_bridge.cc150
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;