| 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/sdk_media_codec_bridge.h" | 5 #include "media/base/android/sdk_media_codec_bridge.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <memory> | 9 #include <memory> |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 82 | 82 |
| 83 SdkMediaCodecBridge::SdkMediaCodecBridge(const std::string& mime, | 83 SdkMediaCodecBridge::SdkMediaCodecBridge(const std::string& mime, |
| 84 bool is_secure, | 84 bool is_secure, |
| 85 MediaCodecDirection direction, | 85 MediaCodecDirection direction, |
| 86 bool require_software_codec) { | 86 bool require_software_codec) { |
| 87 JNIEnv* env = AttachCurrentThread(); | 87 JNIEnv* env = AttachCurrentThread(); |
| 88 CHECK(env); | 88 CHECK(env); |
| 89 DCHECK(!mime.empty()); | 89 DCHECK(!mime.empty()); |
| 90 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime); | 90 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime); |
| 91 j_media_codec_.Reset(Java_MediaCodecBridge_create( | 91 j_media_codec_.Reset(Java_MediaCodecBridge_create( |
| 92 env, j_mime.obj(), is_secure, direction, require_software_codec)); | 92 env, j_mime, is_secure, direction, require_software_codec)); |
| 93 } | 93 } |
| 94 | 94 |
| 95 SdkMediaCodecBridge::~SdkMediaCodecBridge() { | 95 SdkMediaCodecBridge::~SdkMediaCodecBridge() { |
| 96 JNIEnv* env = AttachCurrentThread(); | 96 JNIEnv* env = AttachCurrentThread(); |
| 97 CHECK(env); | 97 CHECK(env); |
| 98 if (j_media_codec_.obj()) | 98 if (j_media_codec_.obj()) |
| 99 Java_MediaCodecBridge_release(env, j_media_codec_.obj()); | 99 Java_MediaCodecBridge_release(env, j_media_codec_); |
| 100 } | 100 } |
| 101 | 101 |
| 102 bool SdkMediaCodecBridge::Start() { | 102 bool SdkMediaCodecBridge::Start() { |
| 103 JNIEnv* env = AttachCurrentThread(); | 103 JNIEnv* env = AttachCurrentThread(); |
| 104 return Java_MediaCodecBridge_start(env, j_media_codec_.obj()); | 104 return Java_MediaCodecBridge_start(env, j_media_codec_); |
| 105 } | 105 } |
| 106 | 106 |
| 107 void SdkMediaCodecBridge::Stop() { | 107 void SdkMediaCodecBridge::Stop() { |
| 108 JNIEnv* env = AttachCurrentThread(); | 108 JNIEnv* env = AttachCurrentThread(); |
| 109 Java_MediaCodecBridge_stop(env, j_media_codec_.obj()); | 109 Java_MediaCodecBridge_stop(env, j_media_codec_); |
| 110 } | 110 } |
| 111 | 111 |
| 112 MediaCodecStatus SdkMediaCodecBridge::Flush() { | 112 MediaCodecStatus SdkMediaCodecBridge::Flush() { |
| 113 JNIEnv* env = AttachCurrentThread(); | 113 JNIEnv* env = AttachCurrentThread(); |
| 114 return static_cast<MediaCodecStatus>( | 114 return static_cast<MediaCodecStatus>( |
| 115 Java_MediaCodecBridge_flush(env, j_media_codec_.obj())); | 115 Java_MediaCodecBridge_flush(env, j_media_codec_)); |
| 116 } | 116 } |
| 117 | 117 |
| 118 MediaCodecStatus SdkMediaCodecBridge::GetOutputSize(gfx::Size* size) { | 118 MediaCodecStatus SdkMediaCodecBridge::GetOutputSize(gfx::Size* size) { |
| 119 JNIEnv* env = AttachCurrentThread(); | 119 JNIEnv* env = AttachCurrentThread(); |
| 120 ScopedJavaLocalRef<jobject> result = | 120 ScopedJavaLocalRef<jobject> result = |
| 121 Java_MediaCodecBridge_getOutputFormat(env, j_media_codec_.obj()); | 121 Java_MediaCodecBridge_getOutputFormat(env, j_media_codec_); |
| 122 MediaCodecStatus status = static_cast<MediaCodecStatus>( | 122 MediaCodecStatus status = static_cast<MediaCodecStatus>( |
| 123 Java_GetOutputFormatResult_status(env, result.obj())); | 123 Java_GetOutputFormatResult_status(env, result)); |
| 124 if (status == MEDIA_CODEC_OK) { | 124 if (status == MEDIA_CODEC_OK) { |
| 125 size->SetSize(Java_GetOutputFormatResult_width(env, result.obj()), | 125 size->SetSize(Java_GetOutputFormatResult_width(env, result), |
| 126 Java_GetOutputFormatResult_height(env, result.obj())); | 126 Java_GetOutputFormatResult_height(env, result)); |
| 127 } | 127 } |
| 128 return status; | 128 return status; |
| 129 } | 129 } |
| 130 | 130 |
| 131 MediaCodecStatus SdkMediaCodecBridge::GetOutputSamplingRate( | 131 MediaCodecStatus SdkMediaCodecBridge::GetOutputSamplingRate( |
| 132 int* sampling_rate) { | 132 int* sampling_rate) { |
| 133 JNIEnv* env = AttachCurrentThread(); | 133 JNIEnv* env = AttachCurrentThread(); |
| 134 ScopedJavaLocalRef<jobject> result = | 134 ScopedJavaLocalRef<jobject> result = |
| 135 Java_MediaCodecBridge_getOutputFormat(env, j_media_codec_.obj()); | 135 Java_MediaCodecBridge_getOutputFormat(env, j_media_codec_); |
| 136 MediaCodecStatus status = static_cast<MediaCodecStatus>( | 136 MediaCodecStatus status = static_cast<MediaCodecStatus>( |
| 137 Java_GetOutputFormatResult_status(env, result.obj())); | 137 Java_GetOutputFormatResult_status(env, result)); |
| 138 if (status == MEDIA_CODEC_OK) | 138 if (status == MEDIA_CODEC_OK) |
| 139 *sampling_rate = Java_GetOutputFormatResult_sampleRate(env, result.obj()); | 139 *sampling_rate = Java_GetOutputFormatResult_sampleRate(env, result); |
| 140 return status; | 140 return status; |
| 141 } | 141 } |
| 142 | 142 |
| 143 MediaCodecStatus SdkMediaCodecBridge::GetOutputChannelCount( | 143 MediaCodecStatus SdkMediaCodecBridge::GetOutputChannelCount( |
| 144 int* channel_count) { | 144 int* channel_count) { |
| 145 JNIEnv* env = AttachCurrentThread(); | 145 JNIEnv* env = AttachCurrentThread(); |
| 146 ScopedJavaLocalRef<jobject> result = | 146 ScopedJavaLocalRef<jobject> result = |
| 147 Java_MediaCodecBridge_getOutputFormat(env, j_media_codec_.obj()); | 147 Java_MediaCodecBridge_getOutputFormat(env, j_media_codec_); |
| 148 MediaCodecStatus status = static_cast<MediaCodecStatus>( | 148 MediaCodecStatus status = static_cast<MediaCodecStatus>( |
| 149 Java_GetOutputFormatResult_status(env, result.obj())); | 149 Java_GetOutputFormatResult_status(env, result)); |
| 150 if (status == MEDIA_CODEC_OK) | 150 if (status == MEDIA_CODEC_OK) |
| 151 *channel_count = Java_GetOutputFormatResult_channelCount(env, result.obj()); | 151 *channel_count = Java_GetOutputFormatResult_channelCount(env, result); |
| 152 return status; | 152 return status; |
| 153 } | 153 } |
| 154 | 154 |
| 155 MediaCodecStatus SdkMediaCodecBridge::QueueInputBuffer( | 155 MediaCodecStatus SdkMediaCodecBridge::QueueInputBuffer( |
| 156 int index, | 156 int index, |
| 157 const uint8_t* data, | 157 const uint8_t* data, |
| 158 size_t data_size, | 158 size_t data_size, |
| 159 base::TimeDelta presentation_time) { | 159 base::TimeDelta presentation_time) { |
| 160 DVLOG(3) << __PRETTY_FUNCTION__ << index << ": " << data_size; | 160 DVLOG(3) << __PRETTY_FUNCTION__ << index << ": " << data_size; |
| 161 if (data_size > | 161 if (data_size > |
| 162 base::checked_cast<size_t>(std::numeric_limits<int32_t>::max())) { | 162 base::checked_cast<size_t>(std::numeric_limits<int32_t>::max())) { |
| 163 return MEDIA_CODEC_ERROR; | 163 return MEDIA_CODEC_ERROR; |
| 164 } | 164 } |
| 165 if (data && !FillInputBuffer(index, data, data_size)) | 165 if (data && !FillInputBuffer(index, data, data_size)) |
| 166 return MEDIA_CODEC_ERROR; | 166 return MEDIA_CODEC_ERROR; |
| 167 JNIEnv* env = AttachCurrentThread(); | 167 JNIEnv* env = AttachCurrentThread(); |
| 168 return static_cast<MediaCodecStatus>(Java_MediaCodecBridge_queueInputBuffer( | 168 return static_cast<MediaCodecStatus>(Java_MediaCodecBridge_queueInputBuffer( |
| 169 env, j_media_codec_.obj(), index, 0, data_size, | 169 env, j_media_codec_, index, 0, data_size, |
| 170 presentation_time.InMicroseconds(), 0)); | 170 presentation_time.InMicroseconds(), 0)); |
| 171 } | 171 } |
| 172 | 172 |
| 173 // TODO(timav): Combine this and above methods together keeping only the first | 173 // TODO(timav): Combine this and above methods together keeping only the first |
| 174 // interface after we switch to Spitzer pipeline. | 174 // interface after we switch to Spitzer pipeline. |
| 175 MediaCodecStatus SdkMediaCodecBridge::QueueSecureInputBuffer( | 175 MediaCodecStatus SdkMediaCodecBridge::QueueSecureInputBuffer( |
| 176 int index, | 176 int index, |
| 177 const uint8_t* data, | 177 const uint8_t* data, |
| 178 size_t data_size, | 178 size_t data_size, |
| 179 const std::vector<char>& key_id, | 179 const std::vector<char>& key_id, |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 224 } | 224 } |
| 225 | 225 |
| 226 ScopedJavaLocalRef<jintArray> clear_array = | 226 ScopedJavaLocalRef<jintArray> clear_array = |
| 227 ToJavaIntArray(env, std::move(native_clear_array), new_subsamples_size); | 227 ToJavaIntArray(env, std::move(native_clear_array), new_subsamples_size); |
| 228 ScopedJavaLocalRef<jintArray> cypher_array = | 228 ScopedJavaLocalRef<jintArray> cypher_array = |
| 229 ToJavaIntArray(env, std::move(native_cypher_array), new_subsamples_size); | 229 ToJavaIntArray(env, std::move(native_cypher_array), new_subsamples_size); |
| 230 | 230 |
| 231 return static_cast<MediaCodecStatus>( | 231 return static_cast<MediaCodecStatus>( |
| 232 Java_MediaCodecBridge_queueSecureInputBuffer( | 232 Java_MediaCodecBridge_queueSecureInputBuffer( |
| 233 env, j_media_codec_.obj(), index, 0, j_iv.obj(), j_key_id.obj(), | 233 env, j_media_codec_.obj(), index, 0, j_iv.obj(), j_key_id.obj(), |
| 234 clear_array.obj(), cypher_array.obj(), new_subsamples_size, | 234 clear_array, cypher_array, new_subsamples_size, |
| 235 presentation_time.InMicroseconds())); | 235 presentation_time.InMicroseconds())); |
| 236 } | 236 } |
| 237 | 237 |
| 238 void SdkMediaCodecBridge::QueueEOS(int input_buffer_index) { | 238 void SdkMediaCodecBridge::QueueEOS(int input_buffer_index) { |
| 239 DVLOG(3) << __PRETTY_FUNCTION__ << ": " << input_buffer_index; | 239 DVLOG(3) << __PRETTY_FUNCTION__ << ": " << input_buffer_index; |
| 240 JNIEnv* env = AttachCurrentThread(); | 240 JNIEnv* env = AttachCurrentThread(); |
| 241 Java_MediaCodecBridge_queueInputBuffer(env, j_media_codec_.obj(), | 241 Java_MediaCodecBridge_queueInputBuffer( |
| 242 input_buffer_index, 0, 0, 0, | 242 env, j_media_codec_, input_buffer_index, 0, 0, 0, kBufferFlagEndOfStream); |
| 243 kBufferFlagEndOfStream); | |
| 244 } | 243 } |
| 245 | 244 |
| 246 MediaCodecStatus SdkMediaCodecBridge::DequeueInputBuffer( | 245 MediaCodecStatus SdkMediaCodecBridge::DequeueInputBuffer( |
| 247 base::TimeDelta timeout, | 246 base::TimeDelta timeout, |
| 248 int* index) { | 247 int* index) { |
| 249 JNIEnv* env = AttachCurrentThread(); | 248 JNIEnv* env = AttachCurrentThread(); |
| 250 ScopedJavaLocalRef<jobject> result = Java_MediaCodecBridge_dequeueInputBuffer( | 249 ScopedJavaLocalRef<jobject> result = Java_MediaCodecBridge_dequeueInputBuffer( |
| 251 env, j_media_codec_.obj(), timeout.InMicroseconds()); | 250 env, j_media_codec_, timeout.InMicroseconds()); |
| 252 *index = Java_DequeueInputResult_index(env, result.obj()); | 251 *index = Java_DequeueInputResult_index(env, result); |
| 253 MediaCodecStatus status = static_cast<MediaCodecStatus>( | 252 MediaCodecStatus status = static_cast<MediaCodecStatus>( |
| 254 Java_DequeueInputResult_status(env, result.obj())); | 253 Java_DequeueInputResult_status(env, result)); |
| 255 DVLOG(3) << __PRETTY_FUNCTION__ << ": status: " << status | 254 DVLOG(3) << __PRETTY_FUNCTION__ << ": status: " << status |
| 256 << ", index: " << *index; | 255 << ", index: " << *index; |
| 257 return status; | 256 return status; |
| 258 } | 257 } |
| 259 | 258 |
| 260 MediaCodecStatus SdkMediaCodecBridge::DequeueOutputBuffer( | 259 MediaCodecStatus SdkMediaCodecBridge::DequeueOutputBuffer( |
| 261 base::TimeDelta timeout, | 260 base::TimeDelta timeout, |
| 262 int* index, | 261 int* index, |
| 263 size_t* offset, | 262 size_t* offset, |
| 264 size_t* size, | 263 size_t* size, |
| 265 base::TimeDelta* presentation_time, | 264 base::TimeDelta* presentation_time, |
| 266 bool* end_of_stream, | 265 bool* end_of_stream, |
| 267 bool* key_frame) { | 266 bool* key_frame) { |
| 268 JNIEnv* env = AttachCurrentThread(); | 267 JNIEnv* env = AttachCurrentThread(); |
| 269 ScopedJavaLocalRef<jobject> result = | 268 ScopedJavaLocalRef<jobject> result = |
| 270 Java_MediaCodecBridge_dequeueOutputBuffer(env, j_media_codec_.obj(), | 269 Java_MediaCodecBridge_dequeueOutputBuffer(env, j_media_codec_, |
| 271 timeout.InMicroseconds()); | 270 timeout.InMicroseconds()); |
| 272 *index = Java_DequeueOutputResult_index(env, result.obj()); | 271 *index = Java_DequeueOutputResult_index(env, result); |
| 273 *offset = base::checked_cast<size_t>( | 272 *offset = |
| 274 Java_DequeueOutputResult_offset(env, result.obj())); | 273 base::checked_cast<size_t>(Java_DequeueOutputResult_offset(env, result)); |
| 275 *size = base::checked_cast<size_t>( | 274 *size = base::checked_cast<size_t>( |
| 276 Java_DequeueOutputResult_numBytes(env, result.obj())); | 275 Java_DequeueOutputResult_numBytes(env, result)); |
| 277 if (presentation_time) { | 276 if (presentation_time) { |
| 278 *presentation_time = base::TimeDelta::FromMicroseconds( | 277 *presentation_time = base::TimeDelta::FromMicroseconds( |
| 279 Java_DequeueOutputResult_presentationTimeMicroseconds(env, | 278 Java_DequeueOutputResult_presentationTimeMicroseconds(env, result)); |
| 280 result.obj())); | |
| 281 } | 279 } |
| 282 int flags = Java_DequeueOutputResult_flags(env, result.obj()); | 280 int flags = Java_DequeueOutputResult_flags(env, result); |
| 283 if (end_of_stream) | 281 if (end_of_stream) |
| 284 *end_of_stream = flags & kBufferFlagEndOfStream; | 282 *end_of_stream = flags & kBufferFlagEndOfStream; |
| 285 if (key_frame) | 283 if (key_frame) |
| 286 *key_frame = flags & kBufferFlagSyncFrame; | 284 *key_frame = flags & kBufferFlagSyncFrame; |
| 287 MediaCodecStatus status = static_cast<MediaCodecStatus>( | 285 MediaCodecStatus status = static_cast<MediaCodecStatus>( |
| 288 Java_DequeueOutputResult_status(env, result.obj())); | 286 Java_DequeueOutputResult_status(env, result)); |
| 289 DVLOG(3) << __PRETTY_FUNCTION__ << ": status: " << status | 287 DVLOG(3) << __PRETTY_FUNCTION__ << ": status: " << status |
| 290 << ", index: " << *index << ", offset: " << *offset | 288 << ", index: " << *index << ", offset: " << *offset |
| 291 << ", size: " << *size << ", flags: " << flags; | 289 << ", size: " << *size << ", flags: " << flags; |
| 292 return status; | 290 return status; |
| 293 } | 291 } |
| 294 | 292 |
| 295 void SdkMediaCodecBridge::ReleaseOutputBuffer(int index, bool render) { | 293 void SdkMediaCodecBridge::ReleaseOutputBuffer(int index, bool render) { |
| 296 DVLOG(3) << __PRETTY_FUNCTION__ << ": " << index; | 294 DVLOG(3) << __PRETTY_FUNCTION__ << ": " << index; |
| 297 JNIEnv* env = AttachCurrentThread(); | 295 JNIEnv* env = AttachCurrentThread(); |
| 298 CHECK(env); | 296 CHECK(env); |
| 299 | 297 |
| 300 Java_MediaCodecBridge_releaseOutputBuffer(env, j_media_codec_.obj(), index, | 298 Java_MediaCodecBridge_releaseOutputBuffer(env, j_media_codec_, index, render); |
| 301 render); | |
| 302 } | 299 } |
| 303 | 300 |
| 304 MediaCodecStatus SdkMediaCodecBridge::GetInputBuffer(int input_buffer_index, | 301 MediaCodecStatus SdkMediaCodecBridge::GetInputBuffer(int input_buffer_index, |
| 305 uint8_t** data, | 302 uint8_t** data, |
| 306 size_t* capacity) { | 303 size_t* capacity) { |
| 307 JNIEnv* env = AttachCurrentThread(); | 304 JNIEnv* env = AttachCurrentThread(); |
| 308 ScopedJavaLocalRef<jobject> j_buffer(Java_MediaCodecBridge_getInputBuffer( | 305 ScopedJavaLocalRef<jobject> j_buffer(Java_MediaCodecBridge_getInputBuffer( |
| 309 env, j_media_codec_.obj(), input_buffer_index)); | 306 env, j_media_codec_, input_buffer_index)); |
| 310 if (j_buffer.is_null()) | 307 if (j_buffer.is_null()) |
| 311 return MEDIA_CODEC_ERROR; | 308 return MEDIA_CODEC_ERROR; |
| 312 | 309 |
| 313 *data = static_cast<uint8_t*>(env->GetDirectBufferAddress(j_buffer.obj())); | 310 *data = static_cast<uint8_t*>(env->GetDirectBufferAddress(j_buffer.obj())); |
| 314 *capacity = | 311 *capacity = |
| 315 base::checked_cast<size_t>(env->GetDirectBufferCapacity(j_buffer.obj())); | 312 base::checked_cast<size_t>(env->GetDirectBufferCapacity(j_buffer.obj())); |
| 316 return MEDIA_CODEC_OK; | 313 return MEDIA_CODEC_OK; |
| 317 } | 314 } |
| 318 | 315 |
| 319 MediaCodecStatus SdkMediaCodecBridge::GetOutputBufferAddress( | 316 MediaCodecStatus SdkMediaCodecBridge::GetOutputBufferAddress( |
| 320 int index, | 317 int index, |
| 321 size_t offset, | 318 size_t offset, |
| 322 const uint8_t** addr, | 319 const uint8_t** addr, |
| 323 size_t* capacity) { | 320 size_t* capacity) { |
| 324 JNIEnv* env = AttachCurrentThread(); | 321 JNIEnv* env = AttachCurrentThread(); |
| 325 ScopedJavaLocalRef<jobject> j_buffer( | 322 ScopedJavaLocalRef<jobject> j_buffer( |
| 326 Java_MediaCodecBridge_getOutputBuffer(env, j_media_codec_.obj(), index)); | 323 Java_MediaCodecBridge_getOutputBuffer(env, j_media_codec_, index)); |
| 327 if (j_buffer.is_null()) | 324 if (j_buffer.is_null()) |
| 328 return MEDIA_CODEC_ERROR; | 325 return MEDIA_CODEC_ERROR; |
| 329 const size_t total_capacity = env->GetDirectBufferCapacity(j_buffer.obj()); | 326 const size_t total_capacity = env->GetDirectBufferCapacity(j_buffer.obj()); |
| 330 CHECK_GE(total_capacity, offset); | 327 CHECK_GE(total_capacity, offset); |
| 331 *addr = reinterpret_cast<const uint8_t*>( | 328 *addr = reinterpret_cast<const uint8_t*>( |
| 332 env->GetDirectBufferAddress(j_buffer.obj())) + | 329 env->GetDirectBufferAddress(j_buffer.obj())) + |
| 333 offset; | 330 offset; |
| 334 *capacity = total_capacity - offset; | 331 *capacity = total_capacity - offset; |
| 335 return MEDIA_CODEC_OK; | 332 return MEDIA_CODEC_OK; |
| 336 } | 333 } |
| 337 | 334 |
| 338 std::string SdkMediaCodecBridge::GetName() { | 335 std::string SdkMediaCodecBridge::GetName() { |
| 339 if (base::android::BuildInfo::GetInstance()->sdk_int() < 18) | 336 if (base::android::BuildInfo::GetInstance()->sdk_int() < 18) |
| 340 return ""; | 337 return ""; |
| 341 JNIEnv* env = AttachCurrentThread(); | 338 JNIEnv* env = AttachCurrentThread(); |
| 342 ScopedJavaLocalRef<jstring> j_name = | 339 ScopedJavaLocalRef<jstring> j_name = |
| 343 Java_MediaCodecBridge_getName(env, j_media_codec_.obj()); | 340 Java_MediaCodecBridge_getName(env, j_media_codec_); |
| 344 return ConvertJavaStringToUTF8(env, j_name.obj()); | 341 return ConvertJavaStringToUTF8(env, j_name); |
| 345 } | 342 } |
| 346 | 343 |
| 347 // static | 344 // static |
| 348 AudioCodecBridge* AudioCodecBridge::Create(const AudioCodec& codec) { | 345 AudioCodecBridge* AudioCodecBridge::Create(const AudioCodec& codec) { |
| 349 if (!MediaCodecUtil::IsMediaCodecAvailable()) | 346 if (!MediaCodecUtil::IsMediaCodecAvailable()) |
| 350 return nullptr; | 347 return nullptr; |
| 351 | 348 |
| 352 const std::string mime = AudioCodecToAndroidMimeType(codec); | 349 const std::string mime = AudioCodecToAndroidMimeType(codec); |
| 353 if (mime.empty()) | 350 if (mime.empty()) |
| 354 return nullptr; | 351 return nullptr; |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 409 | 406 |
| 410 std::string codec_string = AudioCodecToAndroidMimeType(codec); | 407 std::string codec_string = AudioCodecToAndroidMimeType(codec); |
| 411 if (codec_string.empty()) | 408 if (codec_string.empty()) |
| 412 return false; | 409 return false; |
| 413 | 410 |
| 414 JNIEnv* env = AttachCurrentThread(); | 411 JNIEnv* env = AttachCurrentThread(); |
| 415 | 412 |
| 416 ScopedJavaLocalRef<jstring> j_mime = | 413 ScopedJavaLocalRef<jstring> j_mime = |
| 417 ConvertUTF8ToJavaString(env, codec_string); | 414 ConvertUTF8ToJavaString(env, codec_string); |
| 418 ScopedJavaLocalRef<jobject> j_format(Java_MediaCodecBridge_createAudioFormat( | 415 ScopedJavaLocalRef<jobject> j_format(Java_MediaCodecBridge_createAudioFormat( |
| 419 env, j_mime.obj(), sample_rate, channel_count)); | 416 env, j_mime, sample_rate, channel_count)); |
| 420 DCHECK(!j_format.is_null()); | 417 DCHECK(!j_format.is_null()); |
| 421 | 418 |
| 422 if (!ConfigureMediaFormat(j_format.obj(), codec, extra_data, extra_data_size, | 419 if (!ConfigureMediaFormat(j_format.obj(), codec, extra_data, extra_data_size, |
| 423 codec_delay_ns, seek_preroll_ns)) { | 420 codec_delay_ns, seek_preroll_ns)) { |
| 424 return false; | 421 return false; |
| 425 } | 422 } |
| 426 | 423 |
| 427 if (!Java_MediaCodecBridge_configureAudio(env, media_codec(), j_format.obj(), | 424 if (!Java_MediaCodecBridge_configureAudio(env, media_codec(), j_format, |
| 428 media_crypto, 0, play_audio)) { | 425 media_crypto, 0, play_audio)) { |
| 429 return false; | 426 return false; |
| 430 } | 427 } |
| 431 | 428 |
| 432 return Start(); | 429 return Start(); |
| 433 } | 430 } |
| 434 | 431 |
| 435 bool AudioCodecBridge::ConfigureMediaFormat(jobject j_format, | 432 bool AudioCodecBridge::ConfigureMediaFormat(jobject j_format, |
| 436 const AudioCodec& codec, | 433 const AudioCodec& codec, |
| 437 const uint8_t* extra_data, | 434 const uint8_t* extra_data, |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 472 if (total_length >= extra_data_size) { | 469 if (total_length >= extra_data_size) { |
| 473 LOG(ERROR) << "Invalid vorbis header size in the extra data"; | 470 LOG(ERROR) << "Invalid vorbis header size in the extra data"; |
| 474 return false; | 471 return false; |
| 475 } | 472 } |
| 476 } | 473 } |
| 477 current_pos++; | 474 current_pos++; |
| 478 // The first header is identification header. | 475 // The first header is identification header. |
| 479 ScopedJavaLocalRef<jbyteArray> first_header = | 476 ScopedJavaLocalRef<jbyteArray> first_header = |
| 480 base::android::ToJavaByteArray(env, current_pos, header_length[0]); | 477 base::android::ToJavaByteArray(env, current_pos, header_length[0]); |
| 481 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0, | 478 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0, |
| 482 first_header.obj()); | 479 first_header); |
| 483 // The last header is codec header. | 480 // The last header is codec header. |
| 484 ScopedJavaLocalRef<jbyteArray> last_header = | 481 ScopedJavaLocalRef<jbyteArray> last_header = |
| 485 base::android::ToJavaByteArray(env, extra_data + total_length, | 482 base::android::ToJavaByteArray(env, extra_data + total_length, |
| 486 extra_data_size - total_length); | 483 extra_data_size - total_length); |
| 487 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 1, | 484 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 1, last_header); |
| 488 last_header.obj()); | |
| 489 break; | 485 break; |
| 490 } | 486 } |
| 491 case kCodecAAC: { | 487 case kCodecAAC: { |
| 492 media::BitReader reader(extra_data, extra_data_size); | 488 media::BitReader reader(extra_data, extra_data_size); |
| 493 | 489 |
| 494 // The following code is copied from aac.cc | 490 // The following code is copied from aac.cc |
| 495 // TODO(qinmin): refactor the code in aac.cc to make it more reusable. | 491 // TODO(qinmin): refactor the code in aac.cc to make it more reusable. |
| 496 uint8_t profile = 0; | 492 uint8_t profile = 0; |
| 497 uint8_t frequency_index = 0; | 493 uint8_t frequency_index = 0; |
| 498 uint8_t channel_config = 0; | 494 uint8_t channel_config = 0; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 516 LOG(ERROR) << "Invalid AAC header"; | 512 LOG(ERROR) << "Invalid AAC header"; |
| 517 return false; | 513 return false; |
| 518 } | 514 } |
| 519 | 515 |
| 520 const size_t kCsdLength = 2; | 516 const size_t kCsdLength = 2; |
| 521 uint8_t csd[kCsdLength]; | 517 uint8_t csd[kCsdLength]; |
| 522 csd[0] = profile << 3 | frequency_index >> 1; | 518 csd[0] = profile << 3 | frequency_index >> 1; |
| 523 csd[1] = (frequency_index & 0x01) << 7 | channel_config << 3; | 519 csd[1] = (frequency_index & 0x01) << 7 | channel_config << 3; |
| 524 ScopedJavaLocalRef<jbyteArray> byte_array = | 520 ScopedJavaLocalRef<jbyteArray> byte_array = |
| 525 base::android::ToJavaByteArray(env, csd, kCsdLength); | 521 base::android::ToJavaByteArray(env, csd, kCsdLength); |
| 526 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0, | 522 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0, byte_array); |
| 527 byte_array.obj()); | |
| 528 | 523 |
| 529 // TODO(qinmin): pass an extra variable to this function to determine | 524 // TODO(qinmin): pass an extra variable to this function to determine |
| 530 // whether we need to call this. | 525 // whether we need to call this. |
| 531 Java_MediaCodecBridge_setFrameHasADTSHeader(env, j_format); | 526 Java_MediaCodecBridge_setFrameHasADTSHeader(env, j_format); |
| 532 break; | 527 break; |
| 533 } | 528 } |
| 534 case kCodecOpus: { | 529 case kCodecOpus: { |
| 535 if (!extra_data || extra_data_size == 0 || codec_delay_ns < 0 || | 530 if (!extra_data || extra_data_size == 0 || codec_delay_ns < 0 || |
| 536 seek_preroll_ns < 0) { | 531 seek_preroll_ns < 0) { |
| 537 LOG(ERROR) << "Invalid Opus Header"; | 532 LOG(ERROR) << "Invalid Opus Header"; |
| 538 return false; | 533 return false; |
| 539 } | 534 } |
| 540 | 535 |
| 541 // csd0 - Opus Header | 536 // csd0 - Opus Header |
| 542 ScopedJavaLocalRef<jbyteArray> csd0 = | 537 ScopedJavaLocalRef<jbyteArray> csd0 = |
| 543 base::android::ToJavaByteArray(env, extra_data, extra_data_size); | 538 base::android::ToJavaByteArray(env, extra_data, extra_data_size); |
| 544 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0, csd0.obj()); | 539 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0, csd0); |
| 545 | 540 |
| 546 // csd1 - Codec Delay | 541 // csd1 - Codec Delay |
| 547 ScopedJavaLocalRef<jbyteArray> csd1 = base::android::ToJavaByteArray( | 542 ScopedJavaLocalRef<jbyteArray> csd1 = base::android::ToJavaByteArray( |
| 548 env, reinterpret_cast<const uint8_t*>(&codec_delay_ns), | 543 env, reinterpret_cast<const uint8_t*>(&codec_delay_ns), |
| 549 sizeof(int64_t)); | 544 sizeof(int64_t)); |
| 550 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 1, csd1.obj()); | 545 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 1, csd1); |
| 551 | 546 |
| 552 // csd2 - Seek Preroll | 547 // csd2 - Seek Preroll |
| 553 ScopedJavaLocalRef<jbyteArray> csd2 = base::android::ToJavaByteArray( | 548 ScopedJavaLocalRef<jbyteArray> csd2 = base::android::ToJavaByteArray( |
| 554 env, reinterpret_cast<const uint8_t*>(&seek_preroll_ns), | 549 env, reinterpret_cast<const uint8_t*>(&seek_preroll_ns), |
| 555 sizeof(int64_t)); | 550 sizeof(int64_t)); |
| 556 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 2, csd2.obj()); | 551 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 2, csd2); |
| 557 break; | 552 break; |
| 558 } | 553 } |
| 559 default: | 554 default: |
| 560 LOG(ERROR) << "Invalid header encountered for codec: " | 555 LOG(ERROR) << "Invalid header encountered for codec: " |
| 561 << AudioCodecToAndroidMimeType(codec); | 556 << AudioCodecToAndroidMimeType(codec); |
| 562 return false; | 557 return false; |
| 563 } | 558 } |
| 564 return true; | 559 return true; |
| 565 } | 560 } |
| 566 | 561 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 590 << ": GetOutputBufferAddress() failed for index:" << index; | 585 << ": GetOutputBufferAddress() failed for index:" << index; |
| 591 return status; | 586 return status; |
| 592 } | 587 } |
| 593 | 588 |
| 594 numBytes = std::min(base::checked_cast<int>(capacity), numBytes); | 589 numBytes = std::min(base::checked_cast<int>(capacity), numBytes); |
| 595 CHECK_GE(numBytes, 0); | 590 CHECK_GE(numBytes, 0); |
| 596 | 591 |
| 597 JNIEnv* env = AttachCurrentThread(); | 592 JNIEnv* env = AttachCurrentThread(); |
| 598 ScopedJavaLocalRef<jbyteArray> byte_array = | 593 ScopedJavaLocalRef<jbyteArray> byte_array = |
| 599 base::android::ToJavaByteArray(env, buffer, numBytes); | 594 base::android::ToJavaByteArray(env, buffer, numBytes); |
| 600 *playback_pos = Java_MediaCodecBridge_playOutputBuffer( | 595 *playback_pos = Java_MediaCodecBridge_playOutputBuffer(env, media_codec(), |
| 601 env, media_codec(), byte_array.obj(), postpone); | 596 byte_array, postpone); |
| 602 return status; | 597 return status; |
| 603 } | 598 } |
| 604 | 599 |
| 605 void AudioCodecBridge::SetVolume(double volume) { | 600 void AudioCodecBridge::SetVolume(double volume) { |
| 606 JNIEnv* env = AttachCurrentThread(); | 601 JNIEnv* env = AttachCurrentThread(); |
| 607 Java_MediaCodecBridge_setVolume(env, media_codec(), volume); | 602 Java_MediaCodecBridge_setVolume(env, media_codec(), volume); |
| 608 } | 603 } |
| 609 | 604 |
| 610 // static | 605 // static |
| 611 bool VideoCodecBridge::IsKnownUnaccelerated(const VideoCodec& codec, | 606 bool VideoCodecBridge::IsKnownUnaccelerated(const VideoCodec& codec, |
| (...skipping 18 matching lines...) Expand all Loading... |
| 630 return nullptr; | 625 return nullptr; |
| 631 | 626 |
| 632 std::unique_ptr<VideoCodecBridge> bridge(new VideoCodecBridge( | 627 std::unique_ptr<VideoCodecBridge> bridge(new VideoCodecBridge( |
| 633 mime, is_secure, MEDIA_CODEC_DECODER, require_software_codec)); | 628 mime, is_secure, MEDIA_CODEC_DECODER, require_software_codec)); |
| 634 if (!bridge->media_codec()) | 629 if (!bridge->media_codec()) |
| 635 return nullptr; | 630 return nullptr; |
| 636 | 631 |
| 637 JNIEnv* env = AttachCurrentThread(); | 632 JNIEnv* env = AttachCurrentThread(); |
| 638 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime); | 633 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime); |
| 639 ScopedJavaLocalRef<jobject> j_format( | 634 ScopedJavaLocalRef<jobject> j_format( |
| 640 Java_MediaCodecBridge_createVideoDecoderFormat( | 635 Java_MediaCodecBridge_createVideoDecoderFormat(env, j_mime, size.width(), |
| 641 env, j_mime.obj(), size.width(), size.height())); | 636 size.height())); |
| 642 DCHECK(!j_format.is_null()); | 637 DCHECK(!j_format.is_null()); |
| 643 if (!Java_MediaCodecBridge_configureVideo( | 638 if (!Java_MediaCodecBridge_configureVideo(env, bridge->media_codec(), |
| 644 env, bridge->media_codec(), j_format.obj(), surface, media_crypto, 0, | 639 j_format, surface, media_crypto, 0, |
| 645 allow_adaptive_playback)) { | 640 allow_adaptive_playback)) { |
| 646 return nullptr; | 641 return nullptr; |
| 647 } | 642 } |
| 648 | 643 |
| 649 return bridge->Start() ? bridge.release() : nullptr; | 644 return bridge->Start() ? bridge.release() : nullptr; |
| 650 } | 645 } |
| 651 | 646 |
| 652 // static | 647 // static |
| 653 VideoCodecBridge* VideoCodecBridge::CreateEncoder(const VideoCodec& codec, | 648 VideoCodecBridge* VideoCodecBridge::CreateEncoder(const VideoCodec& codec, |
| 654 const gfx::Size& size, | 649 const gfx::Size& size, |
| 655 int bit_rate, | 650 int bit_rate, |
| 656 int frame_rate, | 651 int frame_rate, |
| 657 int i_frame_interval, | 652 int i_frame_interval, |
| 658 int color_format) { | 653 int color_format) { |
| 659 if (!MediaCodecUtil::IsMediaCodecAvailable()) | 654 if (!MediaCodecUtil::IsMediaCodecAvailable()) |
| 660 return nullptr; | 655 return nullptr; |
| 661 | 656 |
| 662 const std::string mime = VideoCodecToAndroidMimeType(codec); | 657 const std::string mime = VideoCodecToAndroidMimeType(codec); |
| 663 if (mime.empty()) | 658 if (mime.empty()) |
| 664 return nullptr; | 659 return nullptr; |
| 665 | 660 |
| 666 std::unique_ptr<VideoCodecBridge> bridge( | 661 std::unique_ptr<VideoCodecBridge> bridge( |
| 667 new VideoCodecBridge(mime, false, MEDIA_CODEC_ENCODER, false)); | 662 new VideoCodecBridge(mime, false, MEDIA_CODEC_ENCODER, false)); |
| 668 if (!bridge->media_codec()) | 663 if (!bridge->media_codec()) |
| 669 return nullptr; | 664 return nullptr; |
| 670 | 665 |
| 671 JNIEnv* env = AttachCurrentThread(); | 666 JNIEnv* env = AttachCurrentThread(); |
| 672 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime); | 667 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime); |
| 673 ScopedJavaLocalRef<jobject> j_format( | 668 ScopedJavaLocalRef<jobject> j_format( |
| 674 Java_MediaCodecBridge_createVideoEncoderFormat( | 669 Java_MediaCodecBridge_createVideoEncoderFormat( |
| 675 env, j_mime.obj(), size.width(), size.height(), bit_rate, frame_rate, | 670 env, j_mime, size.width(), size.height(), bit_rate, frame_rate, |
| 676 i_frame_interval, color_format)); | 671 i_frame_interval, color_format)); |
| 677 DCHECK(!j_format.is_null()); | 672 DCHECK(!j_format.is_null()); |
| 678 if (!Java_MediaCodecBridge_configureVideo(env, bridge->media_codec(), | 673 if (!Java_MediaCodecBridge_configureVideo(env, bridge->media_codec(), |
| 679 j_format.obj(), nullptr, nullptr, | 674 j_format, nullptr, nullptr, |
| 680 kConfigureFlagEncode, true)) { | 675 kConfigureFlagEncode, true)) { |
| 681 return nullptr; | 676 return nullptr; |
| 682 } | 677 } |
| 683 | 678 |
| 684 return bridge->Start() ? bridge.release() : nullptr; | 679 return bridge->Start() ? bridge.release() : nullptr; |
| 685 } | 680 } |
| 686 | 681 |
| 687 VideoCodecBridge::VideoCodecBridge(const std::string& mime, | 682 VideoCodecBridge::VideoCodecBridge(const std::string& mime, |
| 688 bool is_secure, | 683 bool is_secure, |
| 689 MediaCodecDirection direction, | 684 MediaCodecDirection direction, |
| (...skipping 15 matching lines...) Expand all Loading... |
| 705 if (adaptive_playback_supported_for_testing_ == 0) | 700 if (adaptive_playback_supported_for_testing_ == 0) |
| 706 return false; | 701 return false; |
| 707 else if (adaptive_playback_supported_for_testing_ > 0) | 702 else if (adaptive_playback_supported_for_testing_ > 0) |
| 708 return true; | 703 return true; |
| 709 JNIEnv* env = AttachCurrentThread(); | 704 JNIEnv* env = AttachCurrentThread(); |
| 710 return Java_MediaCodecBridge_isAdaptivePlaybackSupported(env, media_codec(), | 705 return Java_MediaCodecBridge_isAdaptivePlaybackSupported(env, media_codec(), |
| 711 width, height); | 706 width, height); |
| 712 } | 707 } |
| 713 | 708 |
| 714 } // namespace media | 709 } // namespace media |
| OLD | NEW |