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 |