Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(285)

Side by Side Diff: media/base/android/sdk_media_codec_bridge.cc

Issue 2672313006: media: Remove the unused NdkMediaCodecBridge (Closed)
Patch Set: rebase past conflict Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "media/base/android/sdk_media_codec_bridge.h"
6
7 #include <algorithm>
8 #include <limits>
9 #include <memory>
10 #include <utility>
11
12 #include "base/android/build_info.h"
13 #include "base/android/jni_android.h"
14 #include "base/android/jni_array.h"
15 #include "base/android/jni_string.h"
16 #include "base/logging.h"
17 #include "base/numerics/safe_conversions.h"
18 #include "base/strings/string_util.h"
19 #include "jni/MediaCodecBridge_jni.h"
20 #include "media/base/android/media_codec_util.h"
21 #include "media/base/bit_reader.h"
22 #include "media/base/subsample_entry.h"
23
24 using base::android::AttachCurrentThread;
25 using base::android::ConvertJavaStringToUTF8;
26 using base::android::ConvertUTF8ToJavaString;
27 using base::android::JavaIntArrayToIntVector;
28 using base::android::ScopedJavaLocalRef;
29
30 #define RETURN_ON_ERROR(condition) \
31 do { \
32 if (!(condition)) { \
33 LOG(ERROR) << "Unable to parse AAC header: " #condition; \
34 return false; \
35 } \
36 } while (0)
37
38 namespace media {
39
40 enum {
41 kBufferFlagSyncFrame = 1, // BUFFER_FLAG_SYNC_FRAME
42 kBufferFlagEndOfStream = 4, // BUFFER_FLAG_END_OF_STREAM
43 kConfigureFlagEncode = 1, // CONFIGURE_FLAG_ENCODE
44 };
45
46 static ScopedJavaLocalRef<jintArray>
47 ToJavaIntArray(JNIEnv* env, std::unique_ptr<jint[]> native_array, int size) {
48 ScopedJavaLocalRef<jintArray> j_array(env, env->NewIntArray(size));
49 env->SetIntArrayRegion(j_array.obj(), 0, size, native_array.get());
50 return j_array;
51 }
52
53 static const std::string AudioCodecToAndroidMimeType(const AudioCodec& codec) {
54 switch (codec) {
55 case kCodecMP3:
56 return "audio/mpeg";
57 case kCodecVorbis:
58 return "audio/vorbis";
59 case kCodecOpus:
60 return "audio/opus";
61 case kCodecAAC:
62 return "audio/mp4a-latm";
63 case kCodecAC3:
64 return "audio/ac3";
65 case kCodecEAC3:
66 return "audio/eac3";
67 default:
68 return std::string();
69 }
70 }
71
72 static const std::string VideoCodecToAndroidMimeType(const VideoCodec& codec) {
73 switch (codec) {
74 case kCodecH264:
75 return "video/avc";
76 case kCodecHEVC:
77 return "video/hevc";
78 case kCodecVP8:
79 return "video/x-vnd.on2.vp8";
80 case kCodecVP9:
81 return "video/x-vnd.on2.vp9";
82 default:
83 return std::string();
84 }
85 }
86
87 SdkMediaCodecBridge::SdkMediaCodecBridge(const std::string& mime,
88 bool is_secure,
89 MediaCodecDirection direction,
90 bool require_software_codec) {
91 JNIEnv* env = AttachCurrentThread();
92 DCHECK(!mime.empty());
93 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
94 j_media_codec_.Reset(Java_MediaCodecBridge_create(
95 env, j_mime, is_secure, direction, require_software_codec));
96 }
97
98 SdkMediaCodecBridge::~SdkMediaCodecBridge() {
99 JNIEnv* env = AttachCurrentThread();
100 if (j_media_codec_.obj())
101 Java_MediaCodecBridge_release(env, j_media_codec_);
102 }
103
104 bool SdkMediaCodecBridge::Start() {
105 JNIEnv* env = AttachCurrentThread();
106 return Java_MediaCodecBridge_start(env, j_media_codec_);
107 }
108
109 void SdkMediaCodecBridge::Stop() {
110 JNIEnv* env = AttachCurrentThread();
111 Java_MediaCodecBridge_stop(env, j_media_codec_);
112 }
113
114 MediaCodecStatus SdkMediaCodecBridge::Flush() {
115 JNIEnv* env = AttachCurrentThread();
116 return static_cast<MediaCodecStatus>(
117 Java_MediaCodecBridge_flush(env, j_media_codec_));
118 }
119
120 MediaCodecStatus SdkMediaCodecBridge::GetOutputSize(gfx::Size* size) {
121 JNIEnv* env = AttachCurrentThread();
122 ScopedJavaLocalRef<jobject> result =
123 Java_MediaCodecBridge_getOutputFormat(env, j_media_codec_);
124 MediaCodecStatus status = static_cast<MediaCodecStatus>(
125 Java_GetOutputFormatResult_status(env, result));
126 if (status == MEDIA_CODEC_OK) {
127 size->SetSize(Java_GetOutputFormatResult_width(env, result),
128 Java_GetOutputFormatResult_height(env, result));
129 }
130 return status;
131 }
132
133 MediaCodecStatus SdkMediaCodecBridge::GetOutputSamplingRate(
134 int* sampling_rate) {
135 JNIEnv* env = AttachCurrentThread();
136 ScopedJavaLocalRef<jobject> result =
137 Java_MediaCodecBridge_getOutputFormat(env, j_media_codec_);
138 MediaCodecStatus status = static_cast<MediaCodecStatus>(
139 Java_GetOutputFormatResult_status(env, result));
140 if (status == MEDIA_CODEC_OK)
141 *sampling_rate = Java_GetOutputFormatResult_sampleRate(env, result);
142 return status;
143 }
144
145 MediaCodecStatus SdkMediaCodecBridge::GetOutputChannelCount(
146 int* channel_count) {
147 JNIEnv* env = AttachCurrentThread();
148 ScopedJavaLocalRef<jobject> result =
149 Java_MediaCodecBridge_getOutputFormat(env, j_media_codec_);
150 MediaCodecStatus status = static_cast<MediaCodecStatus>(
151 Java_GetOutputFormatResult_status(env, result));
152 if (status == MEDIA_CODEC_OK)
153 *channel_count = Java_GetOutputFormatResult_channelCount(env, result);
154 return status;
155 }
156
157 MediaCodecStatus SdkMediaCodecBridge::QueueInputBuffer(
158 int index,
159 const uint8_t* data,
160 size_t data_size,
161 base::TimeDelta presentation_time) {
162 DVLOG(3) << __func__ << index << ": " << data_size;
163 if (data_size >
164 base::checked_cast<size_t>(std::numeric_limits<int32_t>::max())) {
165 return MEDIA_CODEC_ERROR;
166 }
167 if (data && !FillInputBuffer(index, data, data_size))
168 return MEDIA_CODEC_ERROR;
169 JNIEnv* env = AttachCurrentThread();
170 return static_cast<MediaCodecStatus>(Java_MediaCodecBridge_queueInputBuffer(
171 env, j_media_codec_, index, 0, data_size,
172 presentation_time.InMicroseconds(), 0));
173 }
174
175 // TODO(timav): Combine this and above methods together keeping only the first
176 // interface after we switch to Spitzer pipeline.
177 MediaCodecStatus SdkMediaCodecBridge::QueueSecureInputBuffer(
178 int index,
179 const uint8_t* data,
180 size_t data_size,
181 const std::vector<char>& key_id,
182 const std::vector<char>& iv,
183 const SubsampleEntry* subsamples,
184 int subsamples_size,
185 const EncryptionScheme& encryption_scheme,
186 base::TimeDelta presentation_time) {
187 DVLOG(3) << __func__ << index << ": " << data_size;
188 if (data_size >
189 base::checked_cast<size_t>(std::numeric_limits<int32_t>::max())) {
190 return MEDIA_CODEC_ERROR;
191 }
192 if (data && !FillInputBuffer(index, data, data_size))
193 return MEDIA_CODEC_ERROR;
194
195 JNIEnv* env = AttachCurrentThread();
196 ScopedJavaLocalRef<jbyteArray> j_key_id = base::android::ToJavaByteArray(
197 env, reinterpret_cast<const uint8_t*>(key_id.data()), key_id.size());
198 ScopedJavaLocalRef<jbyteArray> j_iv = base::android::ToJavaByteArray(
199 env, reinterpret_cast<const uint8_t*>(iv.data()), iv.size());
200
201 // MediaCodec.CryptoInfo documentations says passing NULL for |clear_array|
202 // to indicate that all data is encrypted. But it doesn't specify what
203 // |cypher_array| and |subsamples_size| should be in that case. Passing
204 // one subsample here just to be on the safe side.
205 int new_subsamples_size = subsamples_size == 0 ? 1 : subsamples_size;
206
207 std::unique_ptr<jint[]> native_clear_array(new jint[new_subsamples_size]);
208 std::unique_ptr<jint[]> native_cypher_array(new jint[new_subsamples_size]);
209
210 if (subsamples_size == 0) {
211 DCHECK(!subsamples);
212 native_clear_array[0] = 0;
213 native_cypher_array[0] = data_size;
214 } else {
215 DCHECK_GT(subsamples_size, 0);
216 DCHECK(subsamples);
217 for (int i = 0; i < subsamples_size; ++i) {
218 DCHECK(subsamples[i].clear_bytes <= std::numeric_limits<uint16_t>::max());
219 if (subsamples[i].cypher_bytes >
220 static_cast<uint32_t>(std::numeric_limits<jint>::max())) {
221 return MEDIA_CODEC_ERROR;
222 }
223
224 native_clear_array[i] = subsamples[i].clear_bytes;
225 native_cypher_array[i] = subsamples[i].cypher_bytes;
226 }
227 }
228
229 ScopedJavaLocalRef<jintArray> clear_array =
230 ToJavaIntArray(env, std::move(native_clear_array), new_subsamples_size);
231 ScopedJavaLocalRef<jintArray> cypher_array =
232 ToJavaIntArray(env, std::move(native_cypher_array), new_subsamples_size);
233
234 return static_cast<MediaCodecStatus>(
235 Java_MediaCodecBridge_queueSecureInputBuffer(
236 env, j_media_codec_.obj(), index, 0, j_iv.obj(), j_key_id.obj(),
237 clear_array, cypher_array, new_subsamples_size,
238 static_cast<int>(encryption_scheme.mode()),
239 static_cast<int>(encryption_scheme.pattern().encrypt_blocks()),
240 static_cast<int>(encryption_scheme.pattern().skip_blocks()),
241 presentation_time.InMicroseconds()));
242 }
243
244 void SdkMediaCodecBridge::QueueEOS(int input_buffer_index) {
245 DVLOG(3) << __func__ << ": " << input_buffer_index;
246 JNIEnv* env = AttachCurrentThread();
247 Java_MediaCodecBridge_queueInputBuffer(
248 env, j_media_codec_, input_buffer_index, 0, 0, 0, kBufferFlagEndOfStream);
249 }
250
251 MediaCodecStatus SdkMediaCodecBridge::DequeueInputBuffer(
252 base::TimeDelta timeout,
253 int* index) {
254 JNIEnv* env = AttachCurrentThread();
255 ScopedJavaLocalRef<jobject> result = Java_MediaCodecBridge_dequeueInputBuffer(
256 env, j_media_codec_, timeout.InMicroseconds());
257 *index = Java_DequeueInputResult_index(env, result);
258 MediaCodecStatus status = static_cast<MediaCodecStatus>(
259 Java_DequeueInputResult_status(env, result));
260 DVLOG(3) << __func__ << ": status: " << status << ", index: " << *index;
261 return status;
262 }
263
264 MediaCodecStatus SdkMediaCodecBridge::DequeueOutputBuffer(
265 base::TimeDelta timeout,
266 int* index,
267 size_t* offset,
268 size_t* size,
269 base::TimeDelta* presentation_time,
270 bool* end_of_stream,
271 bool* key_frame) {
272 JNIEnv* env = AttachCurrentThread();
273 ScopedJavaLocalRef<jobject> result =
274 Java_MediaCodecBridge_dequeueOutputBuffer(env, j_media_codec_,
275 timeout.InMicroseconds());
276 *index = Java_DequeueOutputResult_index(env, result);
277 *offset =
278 base::checked_cast<size_t>(Java_DequeueOutputResult_offset(env, result));
279 *size = base::checked_cast<size_t>(
280 Java_DequeueOutputResult_numBytes(env, result));
281 if (presentation_time) {
282 *presentation_time = base::TimeDelta::FromMicroseconds(
283 Java_DequeueOutputResult_presentationTimeMicroseconds(env, result));
284 }
285 int flags = Java_DequeueOutputResult_flags(env, result);
286 if (end_of_stream)
287 *end_of_stream = flags & kBufferFlagEndOfStream;
288 if (key_frame)
289 *key_frame = flags & kBufferFlagSyncFrame;
290 MediaCodecStatus status = static_cast<MediaCodecStatus>(
291 Java_DequeueOutputResult_status(env, result));
292 DVLOG(3) << __func__ << ": status: " << status << ", index: " << *index
293 << ", offset: " << *offset << ", size: " << *size
294 << ", flags: " << flags;
295 return status;
296 }
297
298 void SdkMediaCodecBridge::ReleaseOutputBuffer(int index, bool render) {
299 DVLOG(3) << __func__ << ": " << index;
300 JNIEnv* env = AttachCurrentThread();
301 Java_MediaCodecBridge_releaseOutputBuffer(env, j_media_codec_, index, render);
302 }
303
304 MediaCodecStatus SdkMediaCodecBridge::GetInputBuffer(int input_buffer_index,
305 uint8_t** data,
306 size_t* capacity) {
307 JNIEnv* env = AttachCurrentThread();
308 ScopedJavaLocalRef<jobject> j_buffer(Java_MediaCodecBridge_getInputBuffer(
309 env, j_media_codec_, input_buffer_index));
310 if (j_buffer.is_null())
311 return MEDIA_CODEC_ERROR;
312
313 *data = static_cast<uint8_t*>(env->GetDirectBufferAddress(j_buffer.obj()));
314 *capacity =
315 base::checked_cast<size_t>(env->GetDirectBufferCapacity(j_buffer.obj()));
316 return MEDIA_CODEC_OK;
317 }
318
319 MediaCodecStatus SdkMediaCodecBridge::GetOutputBufferAddress(
320 int index,
321 size_t offset,
322 const uint8_t** addr,
323 size_t* capacity) {
324 JNIEnv* env = AttachCurrentThread();
325 ScopedJavaLocalRef<jobject> j_buffer(
326 Java_MediaCodecBridge_getOutputBuffer(env, j_media_codec_, index));
327 if (j_buffer.is_null())
328 return MEDIA_CODEC_ERROR;
329 const size_t total_capacity = env->GetDirectBufferCapacity(j_buffer.obj());
330 CHECK_GE(total_capacity, offset);
331 *addr = reinterpret_cast<const uint8_t*>(
332 env->GetDirectBufferAddress(j_buffer.obj())) +
333 offset;
334 *capacity = total_capacity - offset;
335 return MEDIA_CODEC_OK;
336 }
337
338 std::string SdkMediaCodecBridge::GetName() {
339 if (base::android::BuildInfo::GetInstance()->sdk_int() < 18)
340 return "";
341 JNIEnv* env = AttachCurrentThread();
342 ScopedJavaLocalRef<jstring> j_name =
343 Java_MediaCodecBridge_getName(env, j_media_codec_);
344 return ConvertJavaStringToUTF8(env, j_name);
345 }
346
347 // static
348 AudioCodecBridge* AudioCodecBridge::Create(const AudioCodec& codec) {
349 if (!MediaCodecUtil::IsMediaCodecAvailable())
350 return nullptr;
351
352 const std::string mime = AudioCodecToAndroidMimeType(codec);
353 if (mime.empty())
354 return nullptr;
355
356 std::unique_ptr<AudioCodecBridge> bridge(new AudioCodecBridge(mime));
357 if (!bridge->media_codec())
358 return nullptr;
359
360 return bridge.release();
361 }
362
363 // static
364 bool AudioCodecBridge::IsKnownUnaccelerated(const AudioCodec& codec) {
365 return MediaCodecUtil::IsKnownUnaccelerated(
366 AudioCodecToAndroidMimeType(codec), MEDIA_CODEC_DECODER);
367 }
368
369 AudioCodecBridge::AudioCodecBridge(const std::string& mime)
370 // Audio codec doesn't care about security level and there is no need for
371 // audio encoding yet.
372 : SdkMediaCodecBridge(mime, false, MEDIA_CODEC_DECODER, false) {}
373
374 bool AudioCodecBridge::ConfigureAndStart(const AudioDecoderConfig& config,
375 jobject media_crypto) {
376 const int channel_count =
377 ChannelLayoutToChannelCount(config.channel_layout());
378 const int64_t codec_delay_ns = base::Time::kNanosecondsPerSecond *
379 config.codec_delay() /
380 config.samples_per_second();
381 const int64_t seek_preroll_ns =
382 1000LL * config.seek_preroll().InMicroseconds();
383
384 return ConfigureAndStart(config.codec(), config.samples_per_second(),
385 channel_count, config.extra_data().data(),
386 config.extra_data().size(), codec_delay_ns,
387 seek_preroll_ns, media_crypto);
388 }
389
390 bool AudioCodecBridge::ConfigureAndStart(const AudioCodec& codec,
391 int sample_rate,
392 int channel_count,
393 const uint8_t* extra_data,
394 size_t extra_data_size,
395 int64_t codec_delay_ns,
396 int64_t seek_preroll_ns,
397 jobject media_crypto) {
398 DVLOG(2) << __func__ << ": "
399 << " codec:" << GetCodecName(codec)
400 << " samples_per_second:" << sample_rate
401 << " channel_count:" << channel_count
402 << " codec_delay_ns:" << codec_delay_ns
403 << " seek_preroll_ns:" << seek_preroll_ns
404 << " extra data size:" << extra_data_size
405 << " media_crypto:" << media_crypto;
406 DCHECK(media_codec());
407
408 std::string codec_string = AudioCodecToAndroidMimeType(codec);
409 if (codec_string.empty())
410 return false;
411
412 JNIEnv* env = AttachCurrentThread();
413
414 ScopedJavaLocalRef<jstring> j_mime =
415 ConvertUTF8ToJavaString(env, codec_string);
416 ScopedJavaLocalRef<jobject> j_format(Java_MediaCodecBridge_createAudioFormat(
417 env, j_mime, sample_rate, channel_count));
418 DCHECK(!j_format.is_null());
419
420 if (!ConfigureMediaFormat(j_format.obj(), codec, extra_data, extra_data_size,
421 codec_delay_ns, seek_preroll_ns)) {
422 return false;
423 }
424
425 if (!Java_MediaCodecBridge_configureAudio(env, media_codec(), j_format,
426 media_crypto, 0)) {
427 return false;
428 }
429
430 return Start();
431 }
432
433 bool AudioCodecBridge::ConfigureMediaFormat(jobject j_format,
434 const AudioCodec& codec,
435 const uint8_t* extra_data,
436 size_t extra_data_size,
437 int64_t codec_delay_ns,
438 int64_t seek_preroll_ns) {
439 if (extra_data_size == 0 && codec != kCodecOpus)
440 return true;
441
442 JNIEnv* env = AttachCurrentThread();
443 switch (codec) {
444 case kCodecVorbis: {
445 if (extra_data[0] != 2) {
446 LOG(ERROR) << "Invalid number of vorbis headers before the codec "
447 << "header: " << extra_data[0];
448 return false;
449 }
450
451 size_t header_length[2];
452 // |total_length| keeps track of the total number of bytes before the last
453 // header.
454 size_t total_length = 1;
455 const uint8_t* current_pos = extra_data;
456 // Calculate the length of the first 2 headers.
457 for (int i = 0; i < 2; ++i) {
458 header_length[i] = 0;
459 while (total_length < extra_data_size) {
460 size_t size = *(++current_pos);
461 total_length += 1 + size;
462 if (total_length > 0x80000000) {
463 LOG(ERROR) << "Vorbis header size too large";
464 return false;
465 }
466 header_length[i] += size;
467 if (size < 0xFF)
468 break;
469 }
470 if (total_length >= extra_data_size) {
471 LOG(ERROR) << "Invalid vorbis header size in the extra data";
472 return false;
473 }
474 }
475 current_pos++;
476 // The first header is identification header.
477 ScopedJavaLocalRef<jbyteArray> first_header =
478 base::android::ToJavaByteArray(env, current_pos, header_length[0]);
479 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0,
480 first_header);
481 // The last header is codec header.
482 ScopedJavaLocalRef<jbyteArray> last_header =
483 base::android::ToJavaByteArray(env, extra_data + total_length,
484 extra_data_size - total_length);
485 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 1, last_header);
486 break;
487 }
488 case kCodecAAC: {
489 media::BitReader reader(extra_data, extra_data_size);
490
491 // The following code is copied from aac.cc
492 // TODO(qinmin): refactor the code in aac.cc to make it more reusable.
493 uint8_t profile = 0;
494 uint8_t frequency_index = 0;
495 uint8_t channel_config = 0;
496 RETURN_ON_ERROR(reader.ReadBits(5, &profile));
497 RETURN_ON_ERROR(reader.ReadBits(4, &frequency_index));
498
499 if (0xf == frequency_index)
500 RETURN_ON_ERROR(reader.SkipBits(24));
501 RETURN_ON_ERROR(reader.ReadBits(4, &channel_config));
502
503 if (profile == 5 || profile == 29) {
504 // Read extension config.
505 RETURN_ON_ERROR(reader.ReadBits(4, &frequency_index));
506 if (frequency_index == 0xf)
507 RETURN_ON_ERROR(reader.SkipBits(24));
508 RETURN_ON_ERROR(reader.ReadBits(5, &profile));
509 }
510
511 if (profile < 1 || profile > 4 || frequency_index == 0xf ||
512 channel_config > 7) {
513 LOG(ERROR) << "Invalid AAC header";
514 return false;
515 }
516
517 const size_t kCsdLength = 2;
518 uint8_t csd[kCsdLength];
519 csd[0] = profile << 3 | frequency_index >> 1;
520 csd[1] = (frequency_index & 0x01) << 7 | channel_config << 3;
521 ScopedJavaLocalRef<jbyteArray> byte_array =
522 base::android::ToJavaByteArray(env, csd, kCsdLength);
523 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0, byte_array);
524
525 // TODO(qinmin): pass an extra variable to this function to determine
526 // whether we need to call this.
527 Java_MediaCodecBridge_setFrameHasADTSHeader(env, j_format);
528 break;
529 }
530 case kCodecOpus: {
531 if (!extra_data || extra_data_size == 0 || codec_delay_ns < 0 ||
532 seek_preroll_ns < 0) {
533 LOG(ERROR) << "Invalid Opus Header";
534 return false;
535 }
536
537 // csd0 - Opus Header
538 ScopedJavaLocalRef<jbyteArray> csd0 =
539 base::android::ToJavaByteArray(env, extra_data, extra_data_size);
540 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0, csd0);
541
542 // csd1 - Codec Delay
543 ScopedJavaLocalRef<jbyteArray> csd1 = base::android::ToJavaByteArray(
544 env, reinterpret_cast<const uint8_t*>(&codec_delay_ns),
545 sizeof(int64_t));
546 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 1, csd1);
547
548 // csd2 - Seek Preroll
549 ScopedJavaLocalRef<jbyteArray> csd2 = base::android::ToJavaByteArray(
550 env, reinterpret_cast<const uint8_t*>(&seek_preroll_ns),
551 sizeof(int64_t));
552 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 2, csd2);
553 break;
554 }
555 default:
556 LOG(ERROR) << "Invalid header encountered for codec: "
557 << AudioCodecToAndroidMimeType(codec);
558 return false;
559 }
560 return true;
561 }
562
563 // static
564 bool VideoCodecBridge::IsKnownUnaccelerated(const VideoCodec& codec,
565 MediaCodecDirection direction) {
566 return MediaCodecUtil::IsKnownUnaccelerated(
567 VideoCodecToAndroidMimeType(codec), direction);
568 }
569
570 // static
571 VideoCodecBridge* VideoCodecBridge::CreateDecoder(
572 const VideoCodec& codec,
573 bool is_secure,
574 const gfx::Size& size,
575 jobject surface,
576 jobject media_crypto,
577 const std::vector<uint8_t>& csd0,
578 const std::vector<uint8_t>& csd1,
579 bool allow_adaptive_playback,
580 bool require_software_codec) {
581 if (!MediaCodecUtil::IsMediaCodecAvailable())
582 return nullptr;
583
584 const std::string mime = VideoCodecToAndroidMimeType(codec);
585 if (mime.empty())
586 return nullptr;
587
588 std::unique_ptr<VideoCodecBridge> bridge(new VideoCodecBridge(
589 mime, is_secure, MEDIA_CODEC_DECODER, require_software_codec));
590 if (!bridge->media_codec())
591 return nullptr;
592
593 JNIEnv* env = AttachCurrentThread();
594 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
595 ScopedJavaLocalRef<jobject> j_format(
596 Java_MediaCodecBridge_createVideoDecoderFormat(env, j_mime, size.width(),
597 size.height()));
598 DCHECK(!j_format.is_null());
599
600 if (!csd0.empty()) {
601 ScopedJavaLocalRef<jbyteArray> j_csd0 =
602 base::android::ToJavaByteArray(env, csd0.data(), csd0.size());
603 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0, j_csd0);
604 }
605
606 if (!csd1.empty()) {
607 ScopedJavaLocalRef<jbyteArray> j_csd1 =
608 base::android::ToJavaByteArray(env, csd1.data(), csd1.size());
609 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 1, j_csd1);
610 }
611
612 if (!Java_MediaCodecBridge_configureVideo(env, bridge->media_codec(),
613 j_format, surface, media_crypto, 0,
614 allow_adaptive_playback)) {
615 return nullptr;
616 }
617
618 return bridge->Start() ? bridge.release() : nullptr;
619 }
620
621 // static
622 VideoCodecBridge* VideoCodecBridge::CreateEncoder(const VideoCodec& codec,
623 const gfx::Size& size,
624 int bit_rate,
625 int frame_rate,
626 int i_frame_interval,
627 int color_format) {
628 if (!MediaCodecUtil::IsMediaCodecAvailable())
629 return nullptr;
630
631 const std::string mime = VideoCodecToAndroidMimeType(codec);
632 if (mime.empty())
633 return nullptr;
634
635 std::unique_ptr<VideoCodecBridge> bridge(
636 new VideoCodecBridge(mime, false, MEDIA_CODEC_ENCODER, false));
637 if (!bridge->media_codec())
638 return nullptr;
639
640 JNIEnv* env = AttachCurrentThread();
641 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
642 ScopedJavaLocalRef<jobject> j_format(
643 Java_MediaCodecBridge_createVideoEncoderFormat(
644 env, bridge->media_codec(), j_mime, size.width(), size.height(),
645 bit_rate, frame_rate, i_frame_interval, color_format));
646 DCHECK(!j_format.is_null());
647 if (!Java_MediaCodecBridge_configureVideo(env, bridge->media_codec(),
648 j_format, nullptr, nullptr,
649 kConfigureFlagEncode, true)) {
650 return nullptr;
651 }
652
653 return bridge->Start() ? bridge.release() : nullptr;
654 }
655
656 VideoCodecBridge::VideoCodecBridge(const std::string& mime,
657 bool is_secure,
658 MediaCodecDirection direction,
659 bool require_software_codec)
660 : SdkMediaCodecBridge(mime, is_secure, direction, require_software_codec),
661 adaptive_playback_supported_for_testing_(-1) {}
662
663 bool VideoCodecBridge::SetSurface(jobject surface) {
664 DCHECK_GE(base::android::BuildInfo::GetInstance()->sdk_int(), 23);
665 JNIEnv* env = AttachCurrentThread();
666 return Java_MediaCodecBridge_setSurface(env, media_codec(), surface);
667 }
668
669 void VideoCodecBridge::SetVideoBitrate(int bps, int frame_rate) {
670 JNIEnv* env = AttachCurrentThread();
671 Java_MediaCodecBridge_setVideoBitrate(env, media_codec(), bps, frame_rate);
672 }
673
674 void VideoCodecBridge::RequestKeyFrameSoon() {
675 JNIEnv* env = AttachCurrentThread();
676 Java_MediaCodecBridge_requestKeyFrameSoon(env, media_codec());
677 }
678
679 bool VideoCodecBridge::IsAdaptivePlaybackSupported(int width, int height) {
680 if (adaptive_playback_supported_for_testing_ == 0)
681 return false;
682 else if (adaptive_playback_supported_for_testing_ > 0)
683 return true;
684 JNIEnv* env = AttachCurrentThread();
685 return Java_MediaCodecBridge_isAdaptivePlaybackSupported(env, media_codec(),
686 width, height);
687 }
688
689 } // namespace media
OLDNEW
« no previous file with comments | « media/base/android/sdk_media_codec_bridge.h ('k') | media/base/android/sdk_media_codec_bridge_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698