• 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/safe_numerics.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   return base::android::BuildInfo::GetInstance()->sdk_int() >= 16;
108 }
109 
110 // static
SupportsSetParameters()111 bool MediaCodecBridge::SupportsSetParameters() {
112   // MediaCodec.setParameters() is only available starting with K.
113   return base::android::BuildInfo::GetInstance()->sdk_int() >= 19;
114 }
115 
116 // static
GetCodecsInfo()117 std::vector<MediaCodecBridge::CodecsInfo> MediaCodecBridge::GetCodecsInfo() {
118   std::vector<CodecsInfo> codecs_info;
119   JNIEnv* env = AttachCurrentThread();
120   if (!IsAvailable())
121     return codecs_info;
122 
123   std::string mime_type;
124   std::string codec_name;
125   ScopedJavaLocalRef<jobjectArray> j_codec_info_array =
126       Java_MediaCodecBridge_getCodecsInfo(env);
127   jsize len = env->GetArrayLength(j_codec_info_array.obj());
128   for (jsize i = 0; i < len; ++i) {
129     ScopedJavaLocalRef<jobject> j_info(
130         env, env->GetObjectArrayElement(j_codec_info_array.obj(), i));
131     ScopedJavaLocalRef<jstring> j_codec_type =
132         Java_CodecInfo_codecType(env, j_info.obj());
133     ConvertJavaStringToUTF8(env, j_codec_type.obj(), &mime_type);
134     ScopedJavaLocalRef<jstring> j_codec_name =
135         Java_CodecInfo_codecName(env, j_info.obj());
136     CodecsInfo info;
137     info.codecs = AndroidMimeTypeToCodecType(mime_type);
138     ConvertJavaStringToUTF8(env, j_codec_name.obj(), &info.name);
139     info.direction = static_cast<MediaCodecDirection>(
140         Java_CodecInfo_direction(env, j_info.obj()));
141     codecs_info.push_back(info);
142   }
143   return codecs_info;
144 }
145 
146 // static
CanDecode(const std::string & codec,bool is_secure)147 bool MediaCodecBridge::CanDecode(const std::string& codec, bool is_secure) {
148   JNIEnv* env = AttachCurrentThread();
149   std::string mime = CodecTypeToAndroidMimeType(codec);
150   if (mime.empty())
151     return false;
152   ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
153   ScopedJavaLocalRef<jobject> j_media_codec_bridge =
154       Java_MediaCodecBridge_create(env, j_mime.obj(), is_secure, false);
155   if (!j_media_codec_bridge.is_null()) {
156     Java_MediaCodecBridge_release(env, j_media_codec_bridge.obj());
157     return true;
158   }
159   return false;
160 }
161 
162 // static
IsKnownUnaccelerated(const std::string & mime_type,MediaCodecDirection direction)163 bool MediaCodecBridge::IsKnownUnaccelerated(const std::string& mime_type,
164                                             MediaCodecDirection direction) {
165   std::string codec_type = AndroidMimeTypeToCodecType(mime_type);
166   std::vector<media::MediaCodecBridge::CodecsInfo> codecs_info =
167       MediaCodecBridge::GetCodecsInfo();
168   for (size_t i = 0; i < codecs_info.size(); ++i) {
169     if (codecs_info[i].codecs == codec_type &&
170         codecs_info[i].direction == direction) {
171       // It would be nice if MediaCodecInfo externalized some notion of
172       // HW-acceleration but it doesn't. Android Media guidance is that the
173       // prefix below is always used for SW decoders, so that's what we use.
174       return StartsWithASCII(codecs_info[i].name, "OMX.google.", true);
175     }
176   }
177   return true;
178 }
179 
MediaCodecBridge(const std::string & mime,bool is_secure,MediaCodecDirection direction)180 MediaCodecBridge::MediaCodecBridge(const std::string& mime,
181                                    bool is_secure,
182                                    MediaCodecDirection direction) {
183   JNIEnv* env = AttachCurrentThread();
184   CHECK(env);
185   DCHECK(!mime.empty());
186   ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
187   j_media_codec_.Reset(
188       Java_MediaCodecBridge_create(env, j_mime.obj(), is_secure, direction));
189 }
190 
~MediaCodecBridge()191 MediaCodecBridge::~MediaCodecBridge() {
192   JNIEnv* env = AttachCurrentThread();
193   CHECK(env);
194   if (j_media_codec_.obj())
195     Java_MediaCodecBridge_release(env, j_media_codec_.obj());
196 }
197 
StartInternal()198 bool MediaCodecBridge::StartInternal() {
199   JNIEnv* env = AttachCurrentThread();
200   return Java_MediaCodecBridge_start(env, j_media_codec_.obj()) &&
201          GetOutputBuffers();
202 }
203 
Reset()204 MediaCodecStatus MediaCodecBridge::Reset() {
205   JNIEnv* env = AttachCurrentThread();
206   return static_cast<MediaCodecStatus>(
207       Java_MediaCodecBridge_flush(env, j_media_codec_.obj()));
208 }
209 
Stop()210 void MediaCodecBridge::Stop() {
211   JNIEnv* env = AttachCurrentThread();
212   Java_MediaCodecBridge_stop(env, j_media_codec_.obj());
213 }
214 
GetOutputFormat(int * width,int * height)215 void MediaCodecBridge::GetOutputFormat(int* width, int* height) {
216   JNIEnv* env = AttachCurrentThread();
217 
218   *width = Java_MediaCodecBridge_getOutputWidth(env, j_media_codec_.obj());
219   *height = Java_MediaCodecBridge_getOutputHeight(env, j_media_codec_.obj());
220 }
221 
QueueInputBuffer(int index,const uint8 * data,size_t data_size,const base::TimeDelta & presentation_time)222 MediaCodecStatus MediaCodecBridge::QueueInputBuffer(
223     int index,
224     const uint8* data,
225     size_t data_size,
226     const base::TimeDelta& presentation_time) {
227   DVLOG(3) << __PRETTY_FUNCTION__ << index << ": " << data_size;
228   if (data_size > base::checked_numeric_cast<size_t>(kint32max))
229     return MEDIA_CODEC_ERROR;
230   if (data && !FillInputBuffer(index, data, data_size))
231     return MEDIA_CODEC_ERROR;
232   JNIEnv* env = AttachCurrentThread();
233   return static_cast<MediaCodecStatus>(
234       Java_MediaCodecBridge_queueInputBuffer(env,
235                                              j_media_codec_.obj(),
236                                              index,
237                                              0,
238                                              data_size,
239                                              presentation_time.InMicroseconds(),
240                                              0));
241 }
242 
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)243 MediaCodecStatus MediaCodecBridge::QueueSecureInputBuffer(
244     int index,
245     const uint8* data,
246     size_t data_size,
247     const uint8* key_id,
248     int key_id_size,
249     const uint8* iv,
250     int iv_size,
251     const SubsampleEntry* subsamples,
252     int subsamples_size,
253     const base::TimeDelta& presentation_time) {
254   DVLOG(3) << __PRETTY_FUNCTION__ << index << ": " << data_size;
255   if (data_size > base::checked_numeric_cast<size_t>(kint32max))
256     return MEDIA_CODEC_ERROR;
257   if (data && !FillInputBuffer(index, data, data_size))
258     return MEDIA_CODEC_ERROR;
259 
260   JNIEnv* env = AttachCurrentThread();
261   ScopedJavaLocalRef<jbyteArray> j_key_id =
262       base::android::ToJavaByteArray(env, key_id, key_id_size);
263   ScopedJavaLocalRef<jbyteArray> j_iv =
264       base::android::ToJavaByteArray(env, iv, iv_size);
265 
266   // MediaCodec.CryptoInfo documentations says passing NULL for |clear_array|
267   // to indicate that all data is encrypted. But it doesn't specify what
268   // |cypher_array| and |subsamples_size| should be in that case. Passing
269   // one subsample here just to be on the safe side.
270   int new_subsamples_size = subsamples_size == 0 ? 1 : subsamples_size;
271 
272   scoped_ptr<jint[]> native_clear_array(new jint[new_subsamples_size]);
273   scoped_ptr<jint[]> native_cypher_array(new jint[new_subsamples_size]);
274 
275   if (subsamples_size == 0) {
276     DCHECK(!subsamples);
277     native_clear_array[0] = 0;
278     native_cypher_array[0] = data_size;
279   } else {
280     DCHECK_GT(subsamples_size, 0);
281     DCHECK(subsamples);
282     for (int i = 0; i < subsamples_size; ++i) {
283       DCHECK(subsamples[i].clear_bytes <= std::numeric_limits<uint16>::max());
284       if (subsamples[i].cypher_bytes >
285           static_cast<uint32>(std::numeric_limits<jint>::max())) {
286         return MEDIA_CODEC_ERROR;
287       }
288 
289       native_clear_array[i] = subsamples[i].clear_bytes;
290       native_cypher_array[i] = subsamples[i].cypher_bytes;
291     }
292   }
293 
294   ScopedJavaLocalRef<jintArray> clear_array =
295       ToJavaIntArray(env, native_clear_array.Pass(), new_subsamples_size);
296   ScopedJavaLocalRef<jintArray> cypher_array =
297       ToJavaIntArray(env, native_cypher_array.Pass(), new_subsamples_size);
298 
299   return static_cast<MediaCodecStatus>(
300       Java_MediaCodecBridge_queueSecureInputBuffer(
301           env,
302           j_media_codec_.obj(),
303           index,
304           0,
305           j_iv.obj(),
306           j_key_id.obj(),
307           clear_array.obj(),
308           cypher_array.obj(),
309           new_subsamples_size,
310           presentation_time.InMicroseconds()));
311 }
312 
QueueEOS(int input_buffer_index)313 void MediaCodecBridge::QueueEOS(int input_buffer_index) {
314   DVLOG(3) << __PRETTY_FUNCTION__ << ": " << input_buffer_index;
315   JNIEnv* env = AttachCurrentThread();
316   Java_MediaCodecBridge_queueInputBuffer(env,
317                                          j_media_codec_.obj(),
318                                          input_buffer_index,
319                                          0,
320                                          0,
321                                          0,
322                                          kBufferFlagEndOfStream);
323 }
324 
DequeueInputBuffer(const base::TimeDelta & timeout,int * index)325 MediaCodecStatus MediaCodecBridge::DequeueInputBuffer(
326     const base::TimeDelta& timeout,
327     int* index) {
328   JNIEnv* env = AttachCurrentThread();
329   ScopedJavaLocalRef<jobject> result = Java_MediaCodecBridge_dequeueInputBuffer(
330       env, j_media_codec_.obj(), timeout.InMicroseconds());
331   *index = Java_DequeueInputResult_index(env, result.obj());
332   MediaCodecStatus status = static_cast<MediaCodecStatus>(
333       Java_DequeueInputResult_status(env, result.obj()));
334   DVLOG(3) << __PRETTY_FUNCTION__ << ": status: " << status
335            << ", index: " << *index;
336   return status;
337 }
338 
DequeueOutputBuffer(const base::TimeDelta & timeout,int * index,size_t * offset,size_t * size,base::TimeDelta * presentation_time,bool * end_of_stream,bool * key_frame)339 MediaCodecStatus MediaCodecBridge::DequeueOutputBuffer(
340     const base::TimeDelta& timeout,
341     int* index,
342     size_t* offset,
343     size_t* size,
344     base::TimeDelta* presentation_time,
345     bool* end_of_stream,
346     bool* key_frame) {
347   JNIEnv* env = AttachCurrentThread();
348   ScopedJavaLocalRef<jobject> result =
349       Java_MediaCodecBridge_dequeueOutputBuffer(
350           env, j_media_codec_.obj(), timeout.InMicroseconds());
351   *index = Java_DequeueOutputResult_index(env, result.obj());
352   *offset = base::checked_numeric_cast<size_t>(
353       Java_DequeueOutputResult_offset(env, result.obj()));
354   *size = base::checked_numeric_cast<size_t>(
355       Java_DequeueOutputResult_numBytes(env, result.obj()));
356   if (presentation_time) {
357     *presentation_time = base::TimeDelta::FromMicroseconds(
358         Java_DequeueOutputResult_presentationTimeMicroseconds(env,
359                                                               result.obj()));
360   }
361   int flags = Java_DequeueOutputResult_flags(env, result.obj());
362   if (end_of_stream)
363     *end_of_stream = flags & kBufferFlagEndOfStream;
364   if (key_frame)
365     *key_frame = flags & kBufferFlagSyncFrame;
366   MediaCodecStatus status = static_cast<MediaCodecStatus>(
367       Java_DequeueOutputResult_status(env, result.obj()));
368   DVLOG(3) << __PRETTY_FUNCTION__ << ": status: " << status
369            << ", index: " << *index << ", offset: " << *offset
370            << ", size: " << *size << ", flags: " << flags;
371   return status;
372 }
373 
ReleaseOutputBuffer(int index,bool render)374 void MediaCodecBridge::ReleaseOutputBuffer(int index, bool render) {
375   DVLOG(3) << __PRETTY_FUNCTION__ << ": " << index;
376   JNIEnv* env = AttachCurrentThread();
377   CHECK(env);
378 
379   Java_MediaCodecBridge_releaseOutputBuffer(
380       env, j_media_codec_.obj(), index, render);
381 }
382 
GetInputBuffersCount()383 int MediaCodecBridge::GetInputBuffersCount() {
384   JNIEnv* env = AttachCurrentThread();
385   return Java_MediaCodecBridge_getInputBuffersCount(env, j_media_codec_.obj());
386 }
387 
GetOutputBuffersCount()388 int MediaCodecBridge::GetOutputBuffersCount() {
389   JNIEnv* env = AttachCurrentThread();
390   return Java_MediaCodecBridge_getOutputBuffersCount(env, j_media_codec_.obj());
391 }
392 
GetOutputBuffersCapacity()393 size_t MediaCodecBridge::GetOutputBuffersCapacity() {
394   JNIEnv* env = AttachCurrentThread();
395   return Java_MediaCodecBridge_getOutputBuffersCapacity(env,
396                                                         j_media_codec_.obj());
397 }
398 
GetOutputBuffers()399 bool MediaCodecBridge::GetOutputBuffers() {
400   JNIEnv* env = AttachCurrentThread();
401   return Java_MediaCodecBridge_getOutputBuffers(env, j_media_codec_.obj());
402 }
403 
GetInputBuffer(int input_buffer_index,uint8 ** data,size_t * capacity)404 void MediaCodecBridge::GetInputBuffer(int input_buffer_index,
405                                       uint8** data,
406                                       size_t* capacity) {
407   JNIEnv* env = AttachCurrentThread();
408   ScopedJavaLocalRef<jobject> j_buffer(Java_MediaCodecBridge_getInputBuffer(
409       env, j_media_codec_.obj(), input_buffer_index));
410   *data = static_cast<uint8*>(env->GetDirectBufferAddress(j_buffer.obj()));
411   *capacity = base::checked_numeric_cast<size_t>(
412       env->GetDirectBufferCapacity(j_buffer.obj()));
413 }
414 
CopyFromOutputBuffer(int index,size_t offset,void * dst,int dst_size)415 bool MediaCodecBridge::CopyFromOutputBuffer(int index,
416                                             size_t offset,
417                                             void* dst,
418                                             int dst_size) {
419   JNIEnv* env = AttachCurrentThread();
420   ScopedJavaLocalRef<jobject> j_buffer(
421       Java_MediaCodecBridge_getOutputBuffer(env, j_media_codec_.obj(), index));
422   void* src_data =
423       reinterpret_cast<uint8*>(env->GetDirectBufferAddress(j_buffer.obj())) +
424       offset;
425   int src_capacity = env->GetDirectBufferCapacity(j_buffer.obj()) - offset;
426   if (src_capacity < dst_size)
427     return false;
428   memcpy(dst, src_data, dst_size);
429   return true;
430 }
431 
FillInputBuffer(int index,const uint8 * data,size_t size)432 bool MediaCodecBridge::FillInputBuffer(int index,
433                                        const uint8* data,
434                                        size_t size) {
435   uint8* dst = NULL;
436   size_t capacity = 0;
437   GetInputBuffer(index, &dst, &capacity);
438   CHECK(dst);
439 
440   if (size > capacity) {
441     LOG(ERROR) << "Input buffer size " << size
442                << " exceeds MediaCodec input buffer capacity: " << capacity;
443     return false;
444   }
445 
446   memcpy(dst, data, size);
447   return true;
448 }
449 
AudioCodecBridge(const std::string & mime)450 AudioCodecBridge::AudioCodecBridge(const std::string& mime)
451     // Audio codec doesn't care about security level and there is no need for
452     // audio encoding yet.
453     : MediaCodecBridge(mime, false, MEDIA_CODEC_DECODER) {}
454 
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)455 bool AudioCodecBridge::Start(const AudioCodec& codec,
456                              int sample_rate,
457                              int channel_count,
458                              const uint8* extra_data,
459                              size_t extra_data_size,
460                              bool play_audio,
461                              jobject media_crypto) {
462   JNIEnv* env = AttachCurrentThread();
463 
464   if (!media_codec())
465     return false;
466 
467   std::string codec_string = AudioCodecToAndroidMimeType(codec);
468   if (codec_string.empty())
469     return false;
470 
471   ScopedJavaLocalRef<jstring> j_mime =
472       ConvertUTF8ToJavaString(env, codec_string);
473   ScopedJavaLocalRef<jobject> j_format(Java_MediaCodecBridge_createAudioFormat(
474       env, j_mime.obj(), sample_rate, channel_count));
475   DCHECK(!j_format.is_null());
476 
477   if (!ConfigureMediaFormat(j_format.obj(), codec, extra_data, extra_data_size))
478     return false;
479 
480   if (!Java_MediaCodecBridge_configureAudio(
481            env, media_codec(), j_format.obj(), media_crypto, 0, play_audio)) {
482     return false;
483   }
484 
485   return StartInternal();
486 }
487 
ConfigureMediaFormat(jobject j_format,const AudioCodec & codec,const uint8 * extra_data,size_t extra_data_size)488 bool AudioCodecBridge::ConfigureMediaFormat(jobject j_format,
489                                             const AudioCodec& codec,
490                                             const uint8* extra_data,
491                                             size_t extra_data_size) {
492   if (extra_data_size == 0)
493     return true;
494 
495   JNIEnv* env = AttachCurrentThread();
496   switch (codec) {
497     case kCodecVorbis: {
498       if (extra_data[0] != 2) {
499         LOG(ERROR) << "Invalid number of vorbis headers before the codec "
500                    << "header: " << extra_data[0];
501         return false;
502       }
503 
504       size_t header_length[2];
505       // |total_length| keeps track of the total number of bytes before the last
506       // header.
507       size_t total_length = 1;
508       const uint8* current_pos = extra_data;
509       // Calculate the length of the first 2 headers.
510       for (int i = 0; i < 2; ++i) {
511         header_length[i] = 0;
512         while (total_length < extra_data_size) {
513           size_t size = *(++current_pos);
514           total_length += 1 + size;
515           if (total_length > 0x80000000) {
516             LOG(ERROR) << "Vorbis header size too large";
517             return false;
518           }
519           header_length[i] += size;
520           if (size < 0xFF)
521             break;
522         }
523         if (total_length >= extra_data_size) {
524           LOG(ERROR) << "Invalid vorbis header size in the extra data";
525           return false;
526         }
527       }
528       current_pos++;
529       // The first header is identification header.
530       ScopedJavaLocalRef<jbyteArray> first_header =
531           base::android::ToJavaByteArray(env, current_pos, header_length[0]);
532       Java_MediaCodecBridge_setCodecSpecificData(
533           env, j_format, 0, first_header.obj());
534       // The last header is codec header.
535       ScopedJavaLocalRef<jbyteArray> last_header =
536           base::android::ToJavaByteArray(
537               env, extra_data + total_length, extra_data_size - total_length);
538       Java_MediaCodecBridge_setCodecSpecificData(
539           env, j_format, 1, last_header.obj());
540       break;
541     }
542     case kCodecAAC: {
543       media::BitReader reader(extra_data, extra_data_size);
544 
545       // The following code is copied from aac.cc
546       // TODO(qinmin): refactor the code in aac.cc to make it more reusable.
547       uint8 profile = 0;
548       uint8 frequency_index = 0;
549       uint8 channel_config = 0;
550       if (!reader.ReadBits(5, &profile) ||
551           !reader.ReadBits(4, &frequency_index)) {
552         LOG(ERROR) << "Unable to parse AAC header";
553         return false;
554       }
555       if (0xf == frequency_index && !reader.SkipBits(24)) {
556         LOG(ERROR) << "Unable to parse AAC header";
557         return false;
558       }
559       if (!reader.ReadBits(4, &channel_config)) {
560         LOG(ERROR) << "Unable to parse AAC header";
561         return false;
562       }
563 
564       if (profile < 1 || profile > 4 || frequency_index == 0xf ||
565           channel_config > 7) {
566         LOG(ERROR) << "Invalid AAC header";
567         return false;
568       }
569       const size_t kCsdLength = 2;
570       uint8 csd[kCsdLength];
571       csd[0] = profile << 3 | frequency_index >> 1;
572       csd[1] = (frequency_index & 0x01) << 7 | channel_config << 3;
573       ScopedJavaLocalRef<jbyteArray> byte_array =
574           base::android::ToJavaByteArray(env, csd, kCsdLength);
575       Java_MediaCodecBridge_setCodecSpecificData(
576           env, j_format, 0, byte_array.obj());
577 
578       // TODO(qinmin): pass an extra variable to this function to determine
579       // whether we need to call this.
580       Java_MediaCodecBridge_setFrameHasADTSHeader(env, j_format);
581       break;
582     }
583     default:
584       LOG(ERROR) << "Invalid header encountered for codec: "
585                  << AudioCodecToAndroidMimeType(codec);
586       return false;
587   }
588   return true;
589 }
590 
PlayOutputBuffer(int index,size_t size)591 void AudioCodecBridge::PlayOutputBuffer(int index, size_t size) {
592   DCHECK_LE(0, index);
593   int numBytes = base::checked_numeric_cast<int>(size);
594   JNIEnv* env = AttachCurrentThread();
595   ScopedJavaLocalRef<jobject> buf =
596       Java_MediaCodecBridge_getOutputBuffer(env, media_codec(), index);
597   uint8* buffer = static_cast<uint8*>(env->GetDirectBufferAddress(buf.obj()));
598 
599   ScopedJavaLocalRef<jbyteArray> byte_array =
600       base::android::ToJavaByteArray(env, buffer, numBytes);
601   Java_MediaCodecBridge_playOutputBuffer(env, media_codec(), byte_array.obj());
602 }
603 
SetVolume(double volume)604 void AudioCodecBridge::SetVolume(double volume) {
605   JNIEnv* env = AttachCurrentThread();
606   Java_MediaCodecBridge_setVolume(env, media_codec(), volume);
607 }
608 
Create(const AudioCodec & codec)609 AudioCodecBridge* AudioCodecBridge::Create(const AudioCodec& codec) {
610   const std::string mime = AudioCodecToAndroidMimeType(codec);
611   return mime.empty() ? NULL : new AudioCodecBridge(mime);
612 }
613 
614 // static
IsKnownUnaccelerated(const AudioCodec & codec)615 bool AudioCodecBridge::IsKnownUnaccelerated(const AudioCodec& codec) {
616   return MediaCodecBridge::IsKnownUnaccelerated(
617       AudioCodecToAndroidMimeType(codec), MEDIA_CODEC_DECODER);
618 }
619 
620 // static
IsKnownUnaccelerated(const VideoCodec & codec,MediaCodecDirection direction)621 bool VideoCodecBridge::IsKnownUnaccelerated(const VideoCodec& codec,
622                                             MediaCodecDirection direction) {
623   return MediaCodecBridge::IsKnownUnaccelerated(
624       VideoCodecToAndroidMimeType(codec), direction);
625 }
626 
CreateDecoder(const VideoCodec & codec,bool is_secure,const gfx::Size & size,jobject surface,jobject media_crypto)627 VideoCodecBridge* VideoCodecBridge::CreateDecoder(const VideoCodec& codec,
628                                                   bool is_secure,
629                                                   const gfx::Size& size,
630                                                   jobject surface,
631                                                   jobject media_crypto) {
632   JNIEnv* env = AttachCurrentThread();
633   const std::string mime = VideoCodecToAndroidMimeType(codec);
634   if (mime.empty())
635     return NULL;
636 
637   scoped_ptr<VideoCodecBridge> bridge(
638       new VideoCodecBridge(mime, is_secure, MEDIA_CODEC_DECODER));
639   if (!bridge->media_codec())
640     return NULL;
641 
642   ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
643   ScopedJavaLocalRef<jobject> j_format(
644       Java_MediaCodecBridge_createVideoDecoderFormat(
645           env, j_mime.obj(), size.width(), size.height()));
646   DCHECK(!j_format.is_null());
647   if (!Java_MediaCodecBridge_configureVideo(env,
648                                             bridge->media_codec(),
649                                             j_format.obj(),
650                                             surface,
651                                             media_crypto,
652                                             0)) {
653     return NULL;
654   }
655 
656   return bridge->StartInternal() ? bridge.release() : NULL;
657 }
658 
CreateEncoder(const VideoCodec & codec,const gfx::Size & size,int bit_rate,int frame_rate,int i_frame_interval,int color_format)659 VideoCodecBridge* VideoCodecBridge::CreateEncoder(const VideoCodec& codec,
660                                                   const gfx::Size& size,
661                                                   int bit_rate,
662                                                   int frame_rate,
663                                                   int i_frame_interval,
664                                                   int color_format) {
665   JNIEnv* env = AttachCurrentThread();
666   const std::string mime = VideoCodecToAndroidMimeType(codec);
667   if (mime.empty())
668     return NULL;
669 
670   scoped_ptr<VideoCodecBridge> bridge(
671       new VideoCodecBridge(mime, false, MEDIA_CODEC_ENCODER));
672   if (!bridge->media_codec())
673     return NULL;
674 
675   ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
676   ScopedJavaLocalRef<jobject> j_format(
677       Java_MediaCodecBridge_createVideoEncoderFormat(env,
678                                                      j_mime.obj(),
679                                                      size.width(),
680                                                      size.height(),
681                                                      bit_rate,
682                                                      frame_rate,
683                                                      i_frame_interval,
684                                                      color_format));
685   DCHECK(!j_format.is_null());
686   if (!Java_MediaCodecBridge_configureVideo(env,
687                                             bridge->media_codec(),
688                                             j_format.obj(),
689                                             NULL,
690                                             NULL,
691                                             kConfigureFlagEncode)) {
692     return NULL;
693   }
694 
695   return bridge->StartInternal() ? bridge.release() : NULL;
696 }
697 
VideoCodecBridge(const std::string & mime,bool is_secure,MediaCodecDirection direction)698 VideoCodecBridge::VideoCodecBridge(const std::string& mime,
699                                    bool is_secure,
700                                    MediaCodecDirection direction)
701     : MediaCodecBridge(mime, is_secure, direction) {}
702 
SetVideoBitrate(int bps)703 void VideoCodecBridge::SetVideoBitrate(int bps) {
704   JNIEnv* env = AttachCurrentThread();
705   Java_MediaCodecBridge_setVideoBitrate(env, media_codec(), bps);
706 }
707 
RequestKeyFrameSoon()708 void VideoCodecBridge::RequestKeyFrameSoon() {
709   JNIEnv* env = AttachCurrentThread();
710   Java_MediaCodecBridge_requestKeyFrameSoon(env, media_codec());
711 }
712 
RegisterMediaCodecBridge(JNIEnv * env)713 bool MediaCodecBridge::RegisterMediaCodecBridge(JNIEnv* env) {
714   return RegisterNativesImpl(env);
715 }
716 
717 }  // namespace media
718