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

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

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

Powered by Google App Engine
This is Rietveld 408576698