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