• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/media_codec_bridge.h"
6 
7 #include <jni.h>
8 #include <string>
9 
10 #include "base/android/build_info.h"
11 #include "base/android/jni_android.h"
12 #include "base/android/jni_array.h"
13 #include "base/android/jni_string.h"
14 #include "base/basictypes.h"
15 #include "base/lazy_instance.h"
16 #include "base/logging.h"
17 #include "base/numerics/safe_conversions.h"
18 #include "base/strings/string_util.h"
19 #include "base/strings/stringprintf.h"
20 #include "jni/MediaCodecBridge_jni.h"
21 #include "media/base/bit_reader.h"
22 #include "media/base/decrypt_config.h"
23 
24 using base::android::AttachCurrentThread;
25 using base::android::ConvertJavaStringToUTF8;
26 using base::android::ConvertUTF8ToJavaString;
27 using base::android::ScopedJavaLocalRef;
28 
29 namespace media {
30 
31 enum {
32   kBufferFlagSyncFrame = 1,    // BUFFER_FLAG_SYNC_FRAME
33   kBufferFlagEndOfStream = 4,  // BUFFER_FLAG_END_OF_STREAM
34   kConfigureFlagEncode = 1,    // CONFIGURE_FLAG_ENCODE
35 };
36 
AudioCodecToAndroidMimeType(const AudioCodec & codec)37 static const std::string AudioCodecToAndroidMimeType(const AudioCodec& codec) {
38   switch (codec) {
39     case kCodecMP3:
40       return "audio/mpeg";
41     case kCodecVorbis:
42       return "audio/vorbis";
43     case kCodecAAC:
44       return "audio/mp4a-latm";
45     default:
46       return std::string();
47   }
48 }
49 
VideoCodecToAndroidMimeType(const VideoCodec & codec)50 static const std::string VideoCodecToAndroidMimeType(const VideoCodec& codec) {
51   switch (codec) {
52     case kCodecH264:
53       return "video/avc";
54     case kCodecVP8:
55       return "video/x-vnd.on2.vp8";
56     case kCodecVP9:
57       return "video/x-vnd.on2.vp9";
58     default:
59       return std::string();
60   }
61 }
62 
CodecTypeToAndroidMimeType(const std::string & codec)63 static const std::string CodecTypeToAndroidMimeType(const std::string& codec) {
64   // TODO(xhwang): Shall we handle more detailed strings like "mp4a.40.2"?
65   if (codec == "avc1")
66     return "video/avc";
67   if (codec == "mp4a")
68     return "audio/mp4a-latm";
69   if (codec == "vp8" || codec == "vp8.0")
70     return "video/x-vnd.on2.vp8";
71   if (codec == "vp9" || codec == "vp9.0")
72     return "video/x-vnd.on2.vp9";
73   if (codec == "vorbis")
74     return "audio/vorbis";
75   return std::string();
76 }
77 
78 // TODO(qinmin): using a map to help all the conversions in this class.
AndroidMimeTypeToCodecType(const std::string & mime)79 static const std::string AndroidMimeTypeToCodecType(const std::string& mime) {
80   if (mime == "video/mp4v-es")
81     return "mp4v";
82   if (mime == "video/avc")
83     return "avc1";
84   if (mime == "video/x-vnd.on2.vp8")
85     return "vp8";
86   if (mime == "video/x-vnd.on2.vp9")
87     return "vp9";
88   if (mime == "audio/mp4a-latm")
89     return "mp4a";
90   if (mime == "audio/mpeg")
91     return "mp3";
92   if (mime == "audio/vorbis")
93     return "vorbis";
94   return std::string();
95 }
96 
97 static ScopedJavaLocalRef<jintArray>
ToJavaIntArray(JNIEnv * env,scoped_ptr<jint[]> native_array,int size)98 ToJavaIntArray(JNIEnv* env, scoped_ptr<jint[]> native_array, int size) {
99   ScopedJavaLocalRef<jintArray> j_array(env, env->NewIntArray(size));
100   env->SetIntArrayRegion(j_array.obj(), 0, size, native_array.get());
101   return j_array;
102 }
103 
104 // static
IsAvailable()105 bool MediaCodecBridge::IsAvailable() {
106   // MediaCodec is only available on JB and greater.
107   if (base::android::BuildInfo::GetInstance()->sdk_int() < 16)
108     return false;
109   // Blacklist some devices on Jellybean as for MediaCodec support is buggy.
110   // http://crbug.com/365494.
111   if (base::android::BuildInfo::GetInstance()->sdk_int() == 16) {
112     std::string model(base::android::BuildInfo::GetInstance()->model());
113     return model != "GT-I9100" && model != "GT-I9300" && model != "GT-N7000";
114   }
115   return true;
116 }
117 
118 // static
SupportsSetParameters()119 bool MediaCodecBridge::SupportsSetParameters() {
120   // MediaCodec.setParameters() is only available starting with K.
121   return base::android::BuildInfo::GetInstance()->sdk_int() >= 19;
122 }
123 
124 // static
SupportsGetName()125 bool MediaCodecBridge::SupportsGetName() {
126   // MediaCodec.getName() is only available on JB MR2 and greater.
127   return base::android::BuildInfo::GetInstance()->sdk_int() >= 18;
128 }
129 
130 // static
GetCodecsInfo()131 std::vector<MediaCodecBridge::CodecsInfo> MediaCodecBridge::GetCodecsInfo() {
132   std::vector<CodecsInfo> codecs_info;
133   if (!IsAvailable())
134     return codecs_info;
135 
136   JNIEnv* env = AttachCurrentThread();
137   std::string mime_type;
138   ScopedJavaLocalRef<jobjectArray> j_codec_info_array =
139       Java_MediaCodecBridge_getCodecsInfo(env);
140   jsize len = env->GetArrayLength(j_codec_info_array.obj());
141   for (jsize i = 0; i < len; ++i) {
142     ScopedJavaLocalRef<jobject> j_info(
143         env, env->GetObjectArrayElement(j_codec_info_array.obj(), i));
144     ScopedJavaLocalRef<jstring> j_codec_type =
145         Java_CodecInfo_codecType(env, j_info.obj());
146     ConvertJavaStringToUTF8(env, j_codec_type.obj(), &mime_type);
147     ScopedJavaLocalRef<jstring> j_codec_name =
148         Java_CodecInfo_codecName(env, j_info.obj());
149     CodecsInfo info;
150     info.codecs = AndroidMimeTypeToCodecType(mime_type);
151     ConvertJavaStringToUTF8(env, j_codec_name.obj(), &info.name);
152     info.direction = static_cast<MediaCodecDirection>(
153         Java_CodecInfo_direction(env, j_info.obj()));
154     codecs_info.push_back(info);
155   }
156   return codecs_info;
157 }
158 
159 // static
GetDefaultCodecName(const std::string & mime_type,MediaCodecDirection direction)160 std::string MediaCodecBridge::GetDefaultCodecName(
161     const std::string& mime_type,
162     MediaCodecDirection direction) {
163   if (!IsAvailable())
164     return std::string();
165 
166   JNIEnv* env = AttachCurrentThread();
167   ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime_type);
168   ScopedJavaLocalRef<jstring> j_codec_name =
169       Java_MediaCodecBridge_getDefaultCodecName(env, j_mime.obj(), direction);
170   return ConvertJavaStringToUTF8(env, j_codec_name.obj());
171 }
172 
173 // static
CanDecode(const std::string & codec,bool is_secure)174 bool MediaCodecBridge::CanDecode(const std::string& codec, bool is_secure) {
175   if (!IsAvailable())
176     return false;
177 
178   JNIEnv* env = AttachCurrentThread();
179   std::string mime = CodecTypeToAndroidMimeType(codec);
180   if (mime.empty())
181     return false;
182   ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
183   ScopedJavaLocalRef<jobject> j_media_codec_bridge =
184       Java_MediaCodecBridge_create(env, j_mime.obj(), is_secure, false);
185   if (!j_media_codec_bridge.is_null()) {
186     Java_MediaCodecBridge_release(env, j_media_codec_bridge.obj());
187     return true;
188   }
189   return false;
190 }
191 
192 // static
IsKnownUnaccelerated(const std::string & mime_type,MediaCodecDirection direction)193 bool MediaCodecBridge::IsKnownUnaccelerated(const std::string& mime_type,
194                                             MediaCodecDirection direction) {
195   if (!IsAvailable())
196     return true;
197 
198   std::string codec_name;
199   if (SupportsGetName()) {
200     codec_name = GetDefaultCodecName(mime_type, direction);
201   } else {
202     std::string codec_type = AndroidMimeTypeToCodecType(mime_type);
203     std::vector<media::MediaCodecBridge::CodecsInfo> codecs_info =
204         MediaCodecBridge::GetCodecsInfo();
205     for (size_t i = 0; i < codecs_info.size(); ++i) {
206       if (codecs_info[i].codecs == codec_type &&
207           codecs_info[i].direction == direction) {
208         codec_name = codecs_info[i].name;
209         break;
210       }
211     }
212   }
213   DVLOG(1) << __PRETTY_FUNCTION__ << "Default codec for " << mime_type <<
214       " : " << codec_name;
215   // It would be nice if MediaCodecInfo externalized some notion of
216   // HW-acceleration but it doesn't. Android Media guidance is that the
217   // "OMX.google" prefix is always used for SW decoders, so that's what we
218   // use. "OMX.SEC.*" codec is Samsung software implementation - report it
219   // as unaccelerated as well.
220   if (codec_name.length() > 0) {
221     return (StartsWithASCII(codec_name, "OMX.google.", true) ||
222         StartsWithASCII(codec_name, "OMX.SEC.", true));
223   }
224   return true;
225 }
226 
MediaCodecBridge(const std::string & mime,bool is_secure,MediaCodecDirection direction)227 MediaCodecBridge::MediaCodecBridge(const std::string& mime,
228                                    bool is_secure,
229                                    MediaCodecDirection direction) {
230   JNIEnv* env = AttachCurrentThread();
231   CHECK(env);
232   DCHECK(!mime.empty());
233   ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
234   j_media_codec_.Reset(
235       Java_MediaCodecBridge_create(env, j_mime.obj(), is_secure, direction));
236 }
237 
~MediaCodecBridge()238 MediaCodecBridge::~MediaCodecBridge() {
239   JNIEnv* env = AttachCurrentThread();
240   CHECK(env);
241   if (j_media_codec_.obj())
242     Java_MediaCodecBridge_release(env, j_media_codec_.obj());
243 }
244 
StartInternal()245 bool MediaCodecBridge::StartInternal() {
246   JNIEnv* env = AttachCurrentThread();
247   return Java_MediaCodecBridge_start(env, j_media_codec_.obj()) &&
248          GetOutputBuffers();
249 }
250 
Reset()251 MediaCodecStatus MediaCodecBridge::Reset() {
252   JNIEnv* env = AttachCurrentThread();
253   return static_cast<MediaCodecStatus>(
254       Java_MediaCodecBridge_flush(env, j_media_codec_.obj()));
255 }
256 
Stop()257 void MediaCodecBridge::Stop() {
258   JNIEnv* env = AttachCurrentThread();
259   Java_MediaCodecBridge_stop(env, j_media_codec_.obj());
260 }
261 
GetOutputFormat(int * width,int * height)262 void MediaCodecBridge::GetOutputFormat(int* width, int* height) {
263   JNIEnv* env = AttachCurrentThread();
264 
265   *width = Java_MediaCodecBridge_getOutputWidth(env, j_media_codec_.obj());
266   *height = Java_MediaCodecBridge_getOutputHeight(env, j_media_codec_.obj());
267 }
268 
QueueInputBuffer(int index,const uint8 * data,size_t data_size,const base::TimeDelta & presentation_time)269 MediaCodecStatus MediaCodecBridge::QueueInputBuffer(
270     int index,
271     const uint8* data,
272     size_t data_size,
273     const base::TimeDelta& presentation_time) {
274   DVLOG(3) << __PRETTY_FUNCTION__ << index << ": " << data_size;
275   if (data_size > base::checked_cast<size_t>(kint32max))
276     return MEDIA_CODEC_ERROR;
277   if (data && !FillInputBuffer(index, data, data_size))
278     return MEDIA_CODEC_ERROR;
279   JNIEnv* env = AttachCurrentThread();
280   return static_cast<MediaCodecStatus>(
281       Java_MediaCodecBridge_queueInputBuffer(env,
282                                              j_media_codec_.obj(),
283                                              index,
284                                              0,
285                                              data_size,
286                                              presentation_time.InMicroseconds(),
287                                              0));
288 }
289 
QueueSecureInputBuffer(int index,const uint8 * data,size_t data_size,const uint8 * key_id,int key_id_size,const uint8 * iv,int iv_size,const SubsampleEntry * subsamples,int subsamples_size,const base::TimeDelta & presentation_time)290 MediaCodecStatus MediaCodecBridge::QueueSecureInputBuffer(
291     int index,
292     const uint8* data,
293     size_t data_size,
294     const uint8* key_id,
295     int key_id_size,
296     const uint8* iv,
297     int iv_size,
298     const SubsampleEntry* subsamples,
299     int subsamples_size,
300     const base::TimeDelta& presentation_time) {
301   DVLOG(3) << __PRETTY_FUNCTION__ << index << ": " << data_size;
302   if (data_size > base::checked_cast<size_t>(kint32max))
303     return MEDIA_CODEC_ERROR;
304   if (data && !FillInputBuffer(index, data, data_size))
305     return MEDIA_CODEC_ERROR;
306 
307   JNIEnv* env = AttachCurrentThread();
308   ScopedJavaLocalRef<jbyteArray> j_key_id =
309       base::android::ToJavaByteArray(env, key_id, key_id_size);
310   ScopedJavaLocalRef<jbyteArray> j_iv =
311       base::android::ToJavaByteArray(env, iv, iv_size);
312 
313   // MediaCodec.CryptoInfo documentations says passing NULL for |clear_array|
314   // to indicate that all data is encrypted. But it doesn't specify what
315   // |cypher_array| and |subsamples_size| should be in that case. Passing
316   // one subsample here just to be on the safe side.
317   int new_subsamples_size = subsamples_size == 0 ? 1 : subsamples_size;
318 
319   scoped_ptr<jint[]> native_clear_array(new jint[new_subsamples_size]);
320   scoped_ptr<jint[]> native_cypher_array(new jint[new_subsamples_size]);
321 
322   if (subsamples_size == 0) {
323     DCHECK(!subsamples);
324     native_clear_array[0] = 0;
325     native_cypher_array[0] = data_size;
326   } else {
327     DCHECK_GT(subsamples_size, 0);
328     DCHECK(subsamples);
329     for (int i = 0; i < subsamples_size; ++i) {
330       DCHECK(subsamples[i].clear_bytes <= std::numeric_limits<uint16>::max());
331       if (subsamples[i].cypher_bytes >
332           static_cast<uint32>(std::numeric_limits<jint>::max())) {
333         return MEDIA_CODEC_ERROR;
334       }
335 
336       native_clear_array[i] = subsamples[i].clear_bytes;
337       native_cypher_array[i] = subsamples[i].cypher_bytes;
338     }
339   }
340 
341   ScopedJavaLocalRef<jintArray> clear_array =
342       ToJavaIntArray(env, native_clear_array.Pass(), new_subsamples_size);
343   ScopedJavaLocalRef<jintArray> cypher_array =
344       ToJavaIntArray(env, native_cypher_array.Pass(), new_subsamples_size);
345 
346   return static_cast<MediaCodecStatus>(
347       Java_MediaCodecBridge_queueSecureInputBuffer(
348           env,
349           j_media_codec_.obj(),
350           index,
351           0,
352           j_iv.obj(),
353           j_key_id.obj(),
354           clear_array.obj(),
355           cypher_array.obj(),
356           new_subsamples_size,
357           presentation_time.InMicroseconds()));
358 }
359 
QueueEOS(int input_buffer_index)360 void MediaCodecBridge::QueueEOS(int input_buffer_index) {
361   DVLOG(3) << __PRETTY_FUNCTION__ << ": " << input_buffer_index;
362   JNIEnv* env = AttachCurrentThread();
363   Java_MediaCodecBridge_queueInputBuffer(env,
364                                          j_media_codec_.obj(),
365                                          input_buffer_index,
366                                          0,
367                                          0,
368                                          0,
369                                          kBufferFlagEndOfStream);
370 }
371 
DequeueInputBuffer(const base::TimeDelta & timeout,int * index)372 MediaCodecStatus MediaCodecBridge::DequeueInputBuffer(
373     const base::TimeDelta& timeout,
374     int* index) {
375   JNIEnv* env = AttachCurrentThread();
376   ScopedJavaLocalRef<jobject> result = Java_MediaCodecBridge_dequeueInputBuffer(
377       env, j_media_codec_.obj(), timeout.InMicroseconds());
378   *index = Java_DequeueInputResult_index(env, result.obj());
379   MediaCodecStatus status = static_cast<MediaCodecStatus>(
380       Java_DequeueInputResult_status(env, result.obj()));
381   DVLOG(3) << __PRETTY_FUNCTION__ << ": status: " << status
382            << ", index: " << *index;
383   return status;
384 }
385 
DequeueOutputBuffer(const base::TimeDelta & timeout,int * index,size_t * offset,size_t * size,base::TimeDelta * presentation_time,bool * end_of_stream,bool * key_frame)386 MediaCodecStatus MediaCodecBridge::DequeueOutputBuffer(
387     const base::TimeDelta& timeout,
388     int* index,
389     size_t* offset,
390     size_t* size,
391     base::TimeDelta* presentation_time,
392     bool* end_of_stream,
393     bool* key_frame) {
394   JNIEnv* env = AttachCurrentThread();
395   ScopedJavaLocalRef<jobject> result =
396       Java_MediaCodecBridge_dequeueOutputBuffer(
397           env, j_media_codec_.obj(), timeout.InMicroseconds());
398   *index = Java_DequeueOutputResult_index(env, result.obj());
399   *offset = base::checked_cast<size_t>(
400       Java_DequeueOutputResult_offset(env, result.obj()));
401   *size = base::checked_cast<size_t>(
402       Java_DequeueOutputResult_numBytes(env, result.obj()));
403   if (presentation_time) {
404     *presentation_time = base::TimeDelta::FromMicroseconds(
405         Java_DequeueOutputResult_presentationTimeMicroseconds(env,
406                                                               result.obj()));
407   }
408   int flags = Java_DequeueOutputResult_flags(env, result.obj());
409   if (end_of_stream)
410     *end_of_stream = flags & kBufferFlagEndOfStream;
411   if (key_frame)
412     *key_frame = flags & kBufferFlagSyncFrame;
413   MediaCodecStatus status = static_cast<MediaCodecStatus>(
414       Java_DequeueOutputResult_status(env, result.obj()));
415   DVLOG(3) << __PRETTY_FUNCTION__ << ": status: " << status
416            << ", index: " << *index << ", offset: " << *offset
417            << ", size: " << *size << ", flags: " << flags;
418   return status;
419 }
420 
ReleaseOutputBuffer(int index,bool render)421 void MediaCodecBridge::ReleaseOutputBuffer(int index, bool render) {
422   DVLOG(3) << __PRETTY_FUNCTION__ << ": " << index;
423   JNIEnv* env = AttachCurrentThread();
424   CHECK(env);
425 
426   Java_MediaCodecBridge_releaseOutputBuffer(
427       env, j_media_codec_.obj(), index, render);
428 }
429 
GetInputBuffersCount()430 int MediaCodecBridge::GetInputBuffersCount() {
431   JNIEnv* env = AttachCurrentThread();
432   return Java_MediaCodecBridge_getInputBuffersCount(env, j_media_codec_.obj());
433 }
434 
GetOutputBuffersCount()435 int MediaCodecBridge::GetOutputBuffersCount() {
436   JNIEnv* env = AttachCurrentThread();
437   return Java_MediaCodecBridge_getOutputBuffersCount(env, j_media_codec_.obj());
438 }
439 
GetOutputBuffersCapacity()440 size_t MediaCodecBridge::GetOutputBuffersCapacity() {
441   JNIEnv* env = AttachCurrentThread();
442   return Java_MediaCodecBridge_getOutputBuffersCapacity(env,
443                                                         j_media_codec_.obj());
444 }
445 
GetOutputBuffers()446 bool MediaCodecBridge::GetOutputBuffers() {
447   JNIEnv* env = AttachCurrentThread();
448   return Java_MediaCodecBridge_getOutputBuffers(env, j_media_codec_.obj());
449 }
450 
GetInputBuffer(int input_buffer_index,uint8 ** data,size_t * capacity)451 void MediaCodecBridge::GetInputBuffer(int input_buffer_index,
452                                       uint8** data,
453                                       size_t* capacity) {
454   JNIEnv* env = AttachCurrentThread();
455   ScopedJavaLocalRef<jobject> j_buffer(Java_MediaCodecBridge_getInputBuffer(
456       env, j_media_codec_.obj(), input_buffer_index));
457   *data = static_cast<uint8*>(env->GetDirectBufferAddress(j_buffer.obj()));
458   *capacity = base::checked_cast<size_t>(
459       env->GetDirectBufferCapacity(j_buffer.obj()));
460 }
461 
CopyFromOutputBuffer(int index,size_t offset,void * dst,int dst_size)462 bool MediaCodecBridge::CopyFromOutputBuffer(int index,
463                                             size_t offset,
464                                             void* dst,
465                                             int dst_size) {
466   JNIEnv* env = AttachCurrentThread();
467   ScopedJavaLocalRef<jobject> j_buffer(
468       Java_MediaCodecBridge_getOutputBuffer(env, j_media_codec_.obj(), index));
469   void* src_data =
470       reinterpret_cast<uint8*>(env->GetDirectBufferAddress(j_buffer.obj())) +
471       offset;
472   int src_capacity = env->GetDirectBufferCapacity(j_buffer.obj()) - offset;
473   if (src_capacity < dst_size)
474     return false;
475   memcpy(dst, src_data, dst_size);
476   return true;
477 }
478 
FillInputBuffer(int index,const uint8 * data,size_t size)479 bool MediaCodecBridge::FillInputBuffer(int index,
480                                        const uint8* data,
481                                        size_t size) {
482   uint8* dst = NULL;
483   size_t capacity = 0;
484   GetInputBuffer(index, &dst, &capacity);
485   CHECK(dst);
486 
487   if (size > capacity) {
488     LOG(ERROR) << "Input buffer size " << size
489                << " exceeds MediaCodec input buffer capacity: " << capacity;
490     return false;
491   }
492 
493   memcpy(dst, data, size);
494   return true;
495 }
496 
AudioCodecBridge(const std::string & mime)497 AudioCodecBridge::AudioCodecBridge(const std::string& mime)
498     // Audio codec doesn't care about security level and there is no need for
499     // audio encoding yet.
500     : MediaCodecBridge(mime, false, MEDIA_CODEC_DECODER) {}
501 
Start(const AudioCodec & codec,int sample_rate,int channel_count,const uint8 * extra_data,size_t extra_data_size,bool play_audio,jobject media_crypto)502 bool AudioCodecBridge::Start(const AudioCodec& codec,
503                              int sample_rate,
504                              int channel_count,
505                              const uint8* extra_data,
506                              size_t extra_data_size,
507                              bool play_audio,
508                              jobject media_crypto) {
509   JNIEnv* env = AttachCurrentThread();
510 
511   if (!media_codec())
512     return false;
513 
514   std::string codec_string = AudioCodecToAndroidMimeType(codec);
515   if (codec_string.empty())
516     return false;
517 
518   ScopedJavaLocalRef<jstring> j_mime =
519       ConvertUTF8ToJavaString(env, codec_string);
520   ScopedJavaLocalRef<jobject> j_format(Java_MediaCodecBridge_createAudioFormat(
521       env, j_mime.obj(), sample_rate, channel_count));
522   DCHECK(!j_format.is_null());
523 
524   if (!ConfigureMediaFormat(j_format.obj(), codec, extra_data, extra_data_size))
525     return false;
526 
527   if (!Java_MediaCodecBridge_configureAudio(
528            env, media_codec(), j_format.obj(), media_crypto, 0, play_audio)) {
529     return false;
530   }
531 
532   return StartInternal();
533 }
534 
ConfigureMediaFormat(jobject j_format,const AudioCodec & codec,const uint8 * extra_data,size_t extra_data_size)535 bool AudioCodecBridge::ConfigureMediaFormat(jobject j_format,
536                                             const AudioCodec& codec,
537                                             const uint8* extra_data,
538                                             size_t extra_data_size) {
539   if (extra_data_size == 0)
540     return true;
541 
542   JNIEnv* env = AttachCurrentThread();
543   switch (codec) {
544     case kCodecVorbis: {
545       if (extra_data[0] != 2) {
546         LOG(ERROR) << "Invalid number of vorbis headers before the codec "
547                    << "header: " << extra_data[0];
548         return false;
549       }
550 
551       size_t header_length[2];
552       // |total_length| keeps track of the total number of bytes before the last
553       // header.
554       size_t total_length = 1;
555       const uint8* current_pos = extra_data;
556       // Calculate the length of the first 2 headers.
557       for (int i = 0; i < 2; ++i) {
558         header_length[i] = 0;
559         while (total_length < extra_data_size) {
560           size_t size = *(++current_pos);
561           total_length += 1 + size;
562           if (total_length > 0x80000000) {
563             LOG(ERROR) << "Vorbis header size too large";
564             return false;
565           }
566           header_length[i] += size;
567           if (size < 0xFF)
568             break;
569         }
570         if (total_length >= extra_data_size) {
571           LOG(ERROR) << "Invalid vorbis header size in the extra data";
572           return false;
573         }
574       }
575       current_pos++;
576       // The first header is identification header.
577       ScopedJavaLocalRef<jbyteArray> first_header =
578           base::android::ToJavaByteArray(env, current_pos, header_length[0]);
579       Java_MediaCodecBridge_setCodecSpecificData(
580           env, j_format, 0, first_header.obj());
581       // The last header is codec header.
582       ScopedJavaLocalRef<jbyteArray> last_header =
583           base::android::ToJavaByteArray(
584               env, extra_data + total_length, extra_data_size - total_length);
585       Java_MediaCodecBridge_setCodecSpecificData(
586           env, j_format, 1, last_header.obj());
587       break;
588     }
589     case kCodecAAC: {
590       media::BitReader reader(extra_data, extra_data_size);
591 
592       // The following code is copied from aac.cc
593       // TODO(qinmin): refactor the code in aac.cc to make it more reusable.
594       uint8 profile = 0;
595       uint8 frequency_index = 0;
596       uint8 channel_config = 0;
597       if (!reader.ReadBits(5, &profile) ||
598           !reader.ReadBits(4, &frequency_index)) {
599         LOG(ERROR) << "Unable to parse AAC header";
600         return false;
601       }
602       if (0xf == frequency_index && !reader.SkipBits(24)) {
603         LOG(ERROR) << "Unable to parse AAC header";
604         return false;
605       }
606       if (!reader.ReadBits(4, &channel_config)) {
607         LOG(ERROR) << "Unable to parse AAC header";
608         return false;
609       }
610 
611       if (profile < 1 || profile > 4 || frequency_index == 0xf ||
612           channel_config > 7) {
613         LOG(ERROR) << "Invalid AAC header";
614         return false;
615       }
616       const size_t kCsdLength = 2;
617       uint8 csd[kCsdLength];
618       csd[0] = profile << 3 | frequency_index >> 1;
619       csd[1] = (frequency_index & 0x01) << 7 | channel_config << 3;
620       ScopedJavaLocalRef<jbyteArray> byte_array =
621           base::android::ToJavaByteArray(env, csd, kCsdLength);
622       Java_MediaCodecBridge_setCodecSpecificData(
623           env, j_format, 0, byte_array.obj());
624 
625       // TODO(qinmin): pass an extra variable to this function to determine
626       // whether we need to call this.
627       Java_MediaCodecBridge_setFrameHasADTSHeader(env, j_format);
628       break;
629     }
630     default:
631       LOG(ERROR) << "Invalid header encountered for codec: "
632                  << AudioCodecToAndroidMimeType(codec);
633       return false;
634   }
635   return true;
636 }
637 
PlayOutputBuffer(int index,size_t size)638 int64 AudioCodecBridge::PlayOutputBuffer(int index, size_t size) {
639   DCHECK_LE(0, index);
640   int numBytes = base::checked_cast<int>(size);
641   JNIEnv* env = AttachCurrentThread();
642   ScopedJavaLocalRef<jobject> buf =
643       Java_MediaCodecBridge_getOutputBuffer(env, media_codec(), index);
644   uint8* buffer = static_cast<uint8*>(env->GetDirectBufferAddress(buf.obj()));
645 
646   ScopedJavaLocalRef<jbyteArray> byte_array =
647       base::android::ToJavaByteArray(env, buffer, numBytes);
648   return Java_MediaCodecBridge_playOutputBuffer(
649       env, media_codec(), byte_array.obj());
650 }
651 
SetVolume(double volume)652 void AudioCodecBridge::SetVolume(double volume) {
653   JNIEnv* env = AttachCurrentThread();
654   Java_MediaCodecBridge_setVolume(env, media_codec(), volume);
655 }
656 
657 // static
Create(const AudioCodec & codec)658 AudioCodecBridge* AudioCodecBridge::Create(const AudioCodec& codec) {
659   if (!MediaCodecBridge::IsAvailable())
660     return NULL;
661 
662   const std::string mime = AudioCodecToAndroidMimeType(codec);
663   return mime.empty() ? NULL : new AudioCodecBridge(mime);
664 }
665 
666 // static
IsKnownUnaccelerated(const AudioCodec & codec)667 bool AudioCodecBridge::IsKnownUnaccelerated(const AudioCodec& codec) {
668   return MediaCodecBridge::IsKnownUnaccelerated(
669       AudioCodecToAndroidMimeType(codec), MEDIA_CODEC_DECODER);
670 }
671 
672 // static
IsKnownUnaccelerated(const VideoCodec & codec,MediaCodecDirection direction)673 bool VideoCodecBridge::IsKnownUnaccelerated(const VideoCodec& codec,
674                                             MediaCodecDirection direction) {
675   return MediaCodecBridge::IsKnownUnaccelerated(
676       VideoCodecToAndroidMimeType(codec), direction);
677 }
678 
679 // static
CreateDecoder(const VideoCodec & codec,bool is_secure,const gfx::Size & size,jobject surface,jobject media_crypto)680 VideoCodecBridge* VideoCodecBridge::CreateDecoder(const VideoCodec& codec,
681                                                   bool is_secure,
682                                                   const gfx::Size& size,
683                                                   jobject surface,
684                                                   jobject media_crypto) {
685   if (!MediaCodecBridge::IsAvailable())
686     return NULL;
687 
688   const std::string mime = VideoCodecToAndroidMimeType(codec);
689   if (mime.empty())
690     return NULL;
691 
692   scoped_ptr<VideoCodecBridge> bridge(
693       new VideoCodecBridge(mime, is_secure, MEDIA_CODEC_DECODER));
694   if (!bridge->media_codec())
695     return NULL;
696 
697   JNIEnv* env = AttachCurrentThread();
698   ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
699   ScopedJavaLocalRef<jobject> j_format(
700       Java_MediaCodecBridge_createVideoDecoderFormat(
701           env, j_mime.obj(), size.width(), size.height()));
702   DCHECK(!j_format.is_null());
703   if (!Java_MediaCodecBridge_configureVideo(env,
704                                             bridge->media_codec(),
705                                             j_format.obj(),
706                                             surface,
707                                             media_crypto,
708                                             0)) {
709     return NULL;
710   }
711 
712   return bridge->StartInternal() ? bridge.release() : NULL;
713 }
714 
715 // static
CreateEncoder(const VideoCodec & codec,const gfx::Size & size,int bit_rate,int frame_rate,int i_frame_interval,int color_format)716 VideoCodecBridge* VideoCodecBridge::CreateEncoder(const VideoCodec& codec,
717                                                   const gfx::Size& size,
718                                                   int bit_rate,
719                                                   int frame_rate,
720                                                   int i_frame_interval,
721                                                   int color_format) {
722   if (!MediaCodecBridge::IsAvailable())
723     return NULL;
724 
725   const std::string mime = VideoCodecToAndroidMimeType(codec);
726   if (mime.empty())
727     return NULL;
728 
729   scoped_ptr<VideoCodecBridge> bridge(
730       new VideoCodecBridge(mime, false, MEDIA_CODEC_ENCODER));
731   if (!bridge->media_codec())
732     return NULL;
733 
734   JNIEnv* env = AttachCurrentThread();
735   ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
736   ScopedJavaLocalRef<jobject> j_format(
737       Java_MediaCodecBridge_createVideoEncoderFormat(env,
738                                                      j_mime.obj(),
739                                                      size.width(),
740                                                      size.height(),
741                                                      bit_rate,
742                                                      frame_rate,
743                                                      i_frame_interval,
744                                                      color_format));
745   DCHECK(!j_format.is_null());
746   if (!Java_MediaCodecBridge_configureVideo(env,
747                                             bridge->media_codec(),
748                                             j_format.obj(),
749                                             NULL,
750                                             NULL,
751                                             kConfigureFlagEncode)) {
752     return NULL;
753   }
754 
755   return bridge->StartInternal() ? bridge.release() : NULL;
756 }
757 
VideoCodecBridge(const std::string & mime,bool is_secure,MediaCodecDirection direction)758 VideoCodecBridge::VideoCodecBridge(const std::string& mime,
759                                    bool is_secure,
760                                    MediaCodecDirection direction)
761     : MediaCodecBridge(mime, is_secure, direction),
762       adaptive_playback_supported_for_testing_(-1) {}
763 
SetVideoBitrate(int bps)764 void VideoCodecBridge::SetVideoBitrate(int bps) {
765   JNIEnv* env = AttachCurrentThread();
766   Java_MediaCodecBridge_setVideoBitrate(env, media_codec(), bps);
767 }
768 
RequestKeyFrameSoon()769 void VideoCodecBridge::RequestKeyFrameSoon() {
770   JNIEnv* env = AttachCurrentThread();
771   Java_MediaCodecBridge_requestKeyFrameSoon(env, media_codec());
772 }
773 
IsAdaptivePlaybackSupported(int width,int height)774 bool VideoCodecBridge::IsAdaptivePlaybackSupported(int width, int height) {
775   if (adaptive_playback_supported_for_testing_ == 0)
776     return false;
777   else if (adaptive_playback_supported_for_testing_ > 0)
778     return true;
779   JNIEnv* env = AttachCurrentThread();
780   return Java_MediaCodecBridge_isAdaptivePlaybackSupported(
781       env, media_codec(), width, height);
782 }
783 
RegisterMediaCodecBridge(JNIEnv * env)784 bool MediaCodecBridge::RegisterMediaCodecBridge(JNIEnv* env) {
785   return RegisterNativesImpl(env);
786 }
787 
788 }  // namespace media
789