| 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" |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 186 JNIEnv* env = AttachCurrentThread(); | 186 JNIEnv* env = AttachCurrentThread(); |
| 187 DCHECK(AudioCodecToMimeType(codec)); | 187 DCHECK(AudioCodecToMimeType(codec)); |
| 188 | 188 |
| 189 ScopedJavaLocalRef<jstring> j_mime = | 189 ScopedJavaLocalRef<jstring> j_mime = |
| 190 ConvertUTF8ToJavaString(env, AudioCodecToMimeType(codec)); | 190 ConvertUTF8ToJavaString(env, AudioCodecToMimeType(codec)); |
| 191 ScopedJavaLocalRef<jobject> j_format( | 191 ScopedJavaLocalRef<jobject> j_format( |
| 192 Java_MediaCodecBridge_createAudioFormat( | 192 Java_MediaCodecBridge_createAudioFormat( |
| 193 env, j_mime.obj(), sample_rate, channel_count)); | 193 env, j_mime.obj(), sample_rate, channel_count)); |
| 194 DCHECK(!j_format.is_null()); | 194 DCHECK(!j_format.is_null()); |
| 195 | 195 |
| 196 if (extra_data_size > 0) { | 196 if (!ConfigureMediaFormat(j_format.obj(), codec, extra_data, extra_data_size)) |
| 197 DCHECK_EQ(kCodecVorbis, codec); | 197 return false; |
| 198 if (extra_data[0] != 2) { | |
| 199 LOG(ERROR) << "Invalid number of headers before the codec header: " | |
| 200 << extra_data[0]; | |
| 201 return false; | |
| 202 } | |
| 203 | |
| 204 size_t header_length[2]; | |
| 205 // |total_length| keeps track of the total number of bytes before the last | |
| 206 // header. | |
| 207 size_t total_length = 1; | |
| 208 const uint8* current_pos = extra_data; | |
| 209 // Calculate the length of the first 2 headers. | |
| 210 for (int i = 0; i < 2; ++i) { | |
| 211 header_length[i] = 0; | |
| 212 while (total_length < extra_data_size) { | |
| 213 size_t size = *(++current_pos); | |
| 214 total_length += 1 + size; | |
| 215 if (total_length > 0x80000000) { | |
| 216 LOG(ERROR) << "Header size too large"; | |
| 217 return false; | |
| 218 } | |
| 219 header_length[i] += size; | |
| 220 if (size < 0xFF) | |
| 221 break; | |
| 222 } | |
| 223 if (total_length >= extra_data_size) { | |
| 224 LOG(ERROR) << "Invalid header size in the extra data"; | |
| 225 return false; | |
| 226 } | |
| 227 } | |
| 228 current_pos++; | |
| 229 // The first header is identification header. | |
| 230 jobject identification_header = env->NewDirectByteBuffer( | |
| 231 const_cast<uint8*>(current_pos), header_length[0]); | |
| 232 Java_MediaCodecBridge_setCodecSpecificData( | |
| 233 env, j_format.obj(), 0, identification_header); | |
| 234 // The last header is codec header. | |
| 235 jobject codec_header = env->NewDirectByteBuffer( | |
| 236 const_cast<uint8*>(extra_data + total_length), | |
| 237 extra_data_size - total_length); | |
| 238 Java_MediaCodecBridge_setCodecSpecificData( | |
| 239 env, j_format.obj(), 1, codec_header); | |
| 240 env->DeleteLocalRef(codec_header); | |
| 241 env->DeleteLocalRef(identification_header); | |
| 242 } | |
| 243 | 198 |
| 244 Java_MediaCodecBridge_configureAudio( | 199 Java_MediaCodecBridge_configureAudio( |
| 245 env, media_codec(), j_format.obj(), NULL, 0, play_audio); | 200 env, media_codec(), j_format.obj(), NULL, 0, play_audio); |
| 246 StartInternal(); | 201 StartInternal(); |
| 247 return true; | 202 return true; |
| 248 } | 203 } |
| 249 | 204 |
| 205 bool AudioCodecBridge::ConfigureMediaFormat( |
| 206 jobject j_format, const AudioCodec codec, const uint8* extra_data, |
| 207 size_t extra_data_size) { |
| 208 if (extra_data_size == 0) |
| 209 return true; |
| 210 |
| 211 JNIEnv* env = AttachCurrentThread(); |
| 212 switch(codec) { |
| 213 case kCodecVorbis: |
| 214 { |
| 215 if (extra_data[0] != 2) { |
| 216 LOG(ERROR) << "Invalid number of vorbis headers before the codec " |
| 217 << "header: " << extra_data[0]; |
| 218 return false; |
| 219 } |
| 220 |
| 221 size_t header_length[2]; |
| 222 // |total_length| keeps track of the total number of bytes before the last |
| 223 // header. |
| 224 size_t total_length = 1; |
| 225 const uint8* current_pos = extra_data; |
| 226 // Calculate the length of the first 2 headers. |
| 227 for (int i = 0; i < 2; ++i) { |
| 228 header_length[i] = 0; |
| 229 while (total_length < extra_data_size) { |
| 230 size_t size = *(++current_pos); |
| 231 total_length += 1 + size; |
| 232 if (total_length > 0x80000000) { |
| 233 LOG(ERROR) << "Vorbis header size too large"; |
| 234 return false; |
| 235 } |
| 236 header_length[i] += size; |
| 237 if (size < 0xFF) |
| 238 break; |
| 239 } |
| 240 if (total_length >= extra_data_size) { |
| 241 LOG(ERROR) << "Invalid vorbis header size in the extra data"; |
| 242 return false; |
| 243 } |
| 244 } |
| 245 current_pos++; |
| 246 // The first header is identification header. |
| 247 jobject identification_header = env->NewDirectByteBuffer( |
| 248 const_cast<uint8*>(current_pos), header_length[0]); |
| 249 Java_MediaCodecBridge_setCodecSpecificData( |
| 250 env, j_format, 0, identification_header); |
| 251 // The last header is codec header. |
| 252 jobject codec_header = env->NewDirectByteBuffer( |
| 253 const_cast<uint8*>(extra_data + total_length), |
| 254 extra_data_size - total_length); |
| 255 Java_MediaCodecBridge_setCodecSpecificData( |
| 256 env, j_format, 1, codec_header); |
| 257 env->DeleteLocalRef(codec_header); |
| 258 env->DeleteLocalRef(identification_header); |
| 259 break; |
| 260 } |
| 261 case kCodecAAC: |
| 262 { |
| 263 DCHECK_EQ(2u, extra_data_size); |
| 264 jobject header = env->NewDirectByteBuffer( |
| 265 const_cast<uint8*>(extra_data), extra_data_size); |
| 266 Java_MediaCodecBridge_setCodecSpecificData( |
| 267 env, j_format, 0, header); |
| 268 // TODO(qinmin): pass an extra variable to this function to determine |
| 269 // whether we need to call this. |
| 270 Java_MediaCodecBridge_setFrameHasADTSHeader(env, j_format); |
| 271 env->DeleteLocalRef(header); |
| 272 break; |
| 273 } |
| 274 default: |
| 275 LOG(ERROR) << "Invalid header encountered for codec: " |
| 276 << AudioCodecToMimeType(codec); |
| 277 return false; |
| 278 } |
| 279 return true; |
| 280 } |
| 281 |
| 250 void AudioCodecBridge::PlayOutputBuffer(int index, size_t size) { | 282 void AudioCodecBridge::PlayOutputBuffer(int index, size_t size) { |
| 251 DCHECK_LE(0, index); | 283 DCHECK_LE(0, index); |
| 252 int numBytes = base::checked_numeric_cast<int>(size); | 284 int numBytes = base::checked_numeric_cast<int>(size); |
| 253 JNIEnv* env = AttachCurrentThread(); | 285 JNIEnv* env = AttachCurrentThread(); |
| 254 ScopedJavaLocalRef<jobject> buf = | 286 ScopedJavaLocalRef<jobject> buf = |
| 255 Java_MediaCodecBridge_getOutputBuffer(env, media_codec(), index); | 287 Java_MediaCodecBridge_getOutputBuffer(env, media_codec(), index); |
| 256 uint8* buffer = static_cast<uint8*>(env->GetDirectBufferAddress(buf.obj())); | 288 uint8* buffer = static_cast<uint8*>(env->GetDirectBufferAddress(buf.obj())); |
| 257 | 289 |
| 258 ScopedJavaLocalRef<jbyteArray> byte_array = | 290 ScopedJavaLocalRef<jbyteArray> byte_array = |
| 259 base::android::ToJavaByteArray(env, buffer, numBytes); | 291 base::android::ToJavaByteArray(env, buffer, numBytes); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 const char* mime = VideoCodecToMimeType(codec); | 323 const char* mime = VideoCodecToMimeType(codec); |
| 292 return mime ? new VideoCodecBridge(mime) : NULL; | 324 return mime ? new VideoCodecBridge(mime) : NULL; |
| 293 } | 325 } |
| 294 | 326 |
| 295 bool MediaCodecBridge::RegisterMediaCodecBridge(JNIEnv* env) { | 327 bool MediaCodecBridge::RegisterMediaCodecBridge(JNIEnv* env) { |
| 296 return RegisterNativesImpl(env); | 328 return RegisterNativesImpl(env); |
| 297 } | 329 } |
| 298 | 330 |
| 299 } // namespace media | 331 } // namespace media |
| 300 | 332 |
| OLD | NEW |