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/media_codec_bridge.h" | 5 #include "media/base/android/media_codec_bridge.h" |
6 | 6 |
7 #include <jni.h> | 7 #include <jni.h> |
8 | 8 |
9 #include "base/android/build_info.h" | 9 #include "base/android/build_info.h" |
10 #include "base/android/jni_android.h" | 10 #include "base/android/jni_android.h" |
11 #include "base/android/jni_array.h" | 11 #include "base/android/jni_array.h" |
12 #include "base/android/jni_string.h" | 12 #include "base/android/jni_string.h" |
13 #include "base/basictypes.h" | 13 #include "base/basictypes.h" |
14 #include "base/lazy_instance.h" | 14 #include "base/lazy_instance.h" |
15 #include "base/logging.h" | 15 #include "base/logging.h" |
16 #include "base/safe_numerics.h" | 16 #include "base/safe_numerics.h" |
17 #include "base/stringprintf.h" | 17 #include "base/stringprintf.h" |
18 | 18 |
19 #include "jni/MediaCodecBridge_jni.h" | 19 #include "jni/MediaCodecBridge_jni.h" |
20 #include "jni/MediaFormat_jni.h" | 20 #include "jni/MediaFormat_jni.h" |
21 | 21 |
22 using base::android::AttachCurrentThread; | 22 using base::android::AttachCurrentThread; |
23 using base::android::ConvertUTF8ToJavaString; | 23 using base::android::ConvertUTF8ToJavaString; |
24 using base::android::ScopedJavaLocalRef; | 24 using base::android::ScopedJavaLocalRef; |
25 | 25 |
26 namespace { | |
27 | |
28 class MediaCodecNativeRegisterer { | |
29 public: | |
30 MediaCodecNativeRegisterer() { | |
31 JNIEnv* env = AttachCurrentThread(); | |
32 jni_initialized_ = | |
33 media::RegisterNativesImpl(env) && | |
34 JNI_MediaFormat::RegisterNativesImpl(env); | |
35 } | |
36 | |
37 bool IsRegistered() { | |
38 return jni_initialized_; | |
39 } | |
40 | |
41 private: | |
42 bool jni_initialized_; | |
43 }; | |
44 | |
45 static base::LazyInstance<MediaCodecNativeRegisterer> g_native_registerer = | |
46 LAZY_INSTANCE_INITIALIZER; | |
47 | |
48 } // namespace | |
49 | |
50 namespace media { | 26 namespace media { |
51 | 27 |
52 enum { kBufferFlagEndOfStream = 4 }; | 28 enum { kBufferFlagEndOfStream = 4 }; |
53 | 29 |
54 static const char* AudioCodecToMimeType(const AudioCodec codec) { | 30 static const char* AudioCodecToMimeType(const AudioCodec codec) { |
55 switch (codec) { | 31 switch (codec) { |
56 case kCodecMP3: | 32 case kCodecMP3: |
57 return "audio/mpeg"; | 33 return "audio/mpeg"; |
58 case kCodecVorbis: | 34 case kCodecVorbis: |
59 return "audio/vorbis"; | 35 return "audio/vorbis"; |
(...skipping 25 matching lines...) Expand all Loading... |
85 | 61 |
86 // static | 62 // static |
87 bool MediaCodecBridge::IsAvailable() { | 63 bool MediaCodecBridge::IsAvailable() { |
88 // MediaCodec is only available on JB and greater. | 64 // MediaCodec is only available on JB and greater. |
89 return base::android::BuildInfo::GetInstance()->sdk_int() >= 16; | 65 return base::android::BuildInfo::GetInstance()->sdk_int() >= 16; |
90 } | 66 } |
91 | 67 |
92 MediaCodecBridge::MediaCodecBridge(const char* mime) { | 68 MediaCodecBridge::MediaCodecBridge(const char* mime) { |
93 JNIEnv* env = AttachCurrentThread(); | 69 JNIEnv* env = AttachCurrentThread(); |
94 CHECK(env); | 70 CHECK(env); |
95 CHECK(g_native_registerer.Pointer()->IsRegistered()); | |
96 DCHECK(mime); | 71 DCHECK(mime); |
97 | 72 |
98 ScopedJavaLocalRef<jstring> j_type = ConvertUTF8ToJavaString(env, mime); | 73 ScopedJavaLocalRef<jstring> j_type = ConvertUTF8ToJavaString(env, mime); |
99 j_media_codec_.Reset(Java_MediaCodecBridge_create( | 74 j_media_codec_.Reset(Java_MediaCodecBridge_create( |
100 env, j_type.obj())); | 75 env, j_type.obj())); |
101 } | 76 } |
102 | 77 |
103 MediaCodecBridge::~MediaCodecBridge() { | 78 MediaCodecBridge::~MediaCodecBridge() { |
104 JNIEnv* env = AttachCurrentThread(); | 79 JNIEnv* env = AttachCurrentThread(); |
105 CHECK(env); | 80 CHECK(env); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
206 | 181 |
207 Java_MediaCodecBridge_releaseOutputBuffer( | 182 Java_MediaCodecBridge_releaseOutputBuffer( |
208 env, j_media_codec_.obj(), index, render); | 183 env, j_media_codec_.obj(), index, render); |
209 } | 184 } |
210 | 185 |
211 void MediaCodecBridge::GetOutputBuffers() { | 186 void MediaCodecBridge::GetOutputBuffers() { |
212 JNIEnv* env = AttachCurrentThread(); | 187 JNIEnv* env = AttachCurrentThread(); |
213 Java_MediaCodecBridge_getOutputBuffers(env, j_media_codec_.obj()); | 188 Java_MediaCodecBridge_getOutputBuffers(env, j_media_codec_.obj()); |
214 } | 189 } |
215 | 190 |
216 AudioCodecBridge::AudioCodecBridge(const AudioCodec codec) | 191 AudioCodecBridge::AudioCodecBridge(const char* mime) |
217 : MediaCodecBridge(AudioCodecToMimeType(codec)) { | 192 : MediaCodecBridge(mime) { |
218 } | 193 } |
219 | 194 |
220 bool AudioCodecBridge::Start( | 195 bool AudioCodecBridge::Start( |
221 const AudioCodec codec, int sample_rate, int channel_count, | 196 const AudioCodec codec, int sample_rate, int channel_count, |
222 const uint8* extra_data, size_t extra_data_size, bool play_audio) { | 197 const uint8* extra_data, size_t extra_data_size, bool play_audio) { |
223 JNIEnv* env = AttachCurrentThread(); | 198 JNIEnv* env = AttachCurrentThread(); |
224 DCHECK(AudioCodecToMimeType(codec)); | 199 DCHECK(AudioCodecToMimeType(codec)); |
225 | 200 |
226 ScopedJavaLocalRef<jstring> j_mime = | 201 ScopedJavaLocalRef<jstring> j_mime = |
227 ConvertUTF8ToJavaString(env, AudioCodecToMimeType(codec)); | 202 ConvertUTF8ToJavaString(env, AudioCodecToMimeType(codec)); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
293 ScopedJavaLocalRef<jobject> buf = | 268 ScopedJavaLocalRef<jobject> buf = |
294 Java_MediaCodecBridge_getOutputBuffer(env, media_codec(), index); | 269 Java_MediaCodecBridge_getOutputBuffer(env, media_codec(), index); |
295 uint8* buffer = static_cast<uint8*>(env->GetDirectBufferAddress(buf.obj())); | 270 uint8* buffer = static_cast<uint8*>(env->GetDirectBufferAddress(buf.obj())); |
296 | 271 |
297 ScopedJavaLocalRef<jbyteArray> byte_array = | 272 ScopedJavaLocalRef<jbyteArray> byte_array = |
298 base::android::ToJavaByteArray(env, buffer, numBytes); | 273 base::android::ToJavaByteArray(env, buffer, numBytes); |
299 Java_MediaCodecBridge_playOutputBuffer( | 274 Java_MediaCodecBridge_playOutputBuffer( |
300 env, media_codec(), byte_array.obj()); | 275 env, media_codec(), byte_array.obj()); |
301 } | 276 } |
302 | 277 |
303 VideoCodecBridge::VideoCodecBridge(const VideoCodec codec) | 278 VideoCodecBridge::VideoCodecBridge(const char* mime) |
304 : MediaCodecBridge(VideoCodecToMimeType(codec)) { | 279 : MediaCodecBridge(mime) { |
305 } | 280 } |
306 | 281 |
307 bool VideoCodecBridge::Start( | 282 bool VideoCodecBridge::Start( |
308 const VideoCodec codec, const gfx::Size& size, jobject surface) { | 283 const VideoCodec codec, const gfx::Size& size, jobject surface) { |
309 JNIEnv* env = AttachCurrentThread(); | 284 JNIEnv* env = AttachCurrentThread(); |
310 DCHECK(VideoCodecToMimeType(codec)); | 285 DCHECK(VideoCodecToMimeType(codec)); |
311 | 286 |
312 ScopedJavaLocalRef<jstring> j_mime = | 287 ScopedJavaLocalRef<jstring> j_mime = |
313 ConvertUTF8ToJavaString(env, VideoCodecToMimeType(codec)); | 288 ConvertUTF8ToJavaString(env, VideoCodecToMimeType(codec)); |
314 ScopedJavaLocalRef<jobject> j_format( | 289 ScopedJavaLocalRef<jobject> j_format( |
315 JNI_MediaFormat::Java_MediaFormat_createVideoFormat( | 290 JNI_MediaFormat::Java_MediaFormat_createVideoFormat( |
316 env, j_mime.obj(), size.width(), size.height())); | 291 env, j_mime.obj(), size.width(), size.height())); |
317 DCHECK(!j_format.is_null()); | 292 DCHECK(!j_format.is_null()); |
318 Java_MediaCodecBridge_configureVideo( | 293 Java_MediaCodecBridge_configureVideo( |
319 env, media_codec(), j_format.obj(), surface, NULL, 0); | 294 env, media_codec(), j_format.obj(), surface, NULL, 0); |
320 StartInternal(); | 295 StartInternal(); |
321 return true; | 296 return true; |
322 } | 297 } |
323 | 298 |
| 299 AudioCodecBridge* AudioCodecBridge::Create(const AudioCodec codec) { |
| 300 const char* mime = AudioCodecToMimeType(codec); |
| 301 return mime ? new AudioCodecBridge(mime) : NULL; |
| 302 } |
| 303 |
| 304 VideoCodecBridge* VideoCodecBridge::Create(const VideoCodec codec) { |
| 305 const char* mime = VideoCodecToMimeType(codec); |
| 306 return mime ? new VideoCodecBridge(mime) : NULL; |
| 307 } |
| 308 |
| 309 bool MediaCodecBridge::RegisterMediaCodecBridge(JNIEnv* env) { |
| 310 if (!MediaCodecBridge::IsAvailable()) |
| 311 return false; |
| 312 return RegisterNativesImpl(env) && JNI_MediaFormat::RegisterNativesImpl(env); |
| 313 } |
| 314 |
324 } // namespace media | 315 } // namespace media |
325 | 316 |
OLD | NEW |