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

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

Issue 2697643003: media: Clean up MediaCodecBridge and remove subclasses (Closed)
Patch Set: 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) {
watk 2017/02/14 01:40:50 Moved to MediaCodecUtil
48 switch (codec) {
49 case kCodecMP3:
50 return "audio/mpeg";
51 case kCodecVorbis:
52 return "audio/vorbis";
53 case kCodecOpus:
54 return "audio/opus";
55 case kCodecAAC:
56 return "audio/mp4a-latm";
57 case kCodecAC3:
58 return "audio/ac3";
59 case kCodecEAC3:
60 return "audio/eac3";
61 default:
62 return std::string();
63 }
64 }
65
66 const std::string VideoCodecToAndroidMimeType(const VideoCodec& codec) {
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> 50 static ScopedJavaLocalRef<jintArray>
82 ToJavaIntArray(JNIEnv* env, std::unique_ptr<jint[]> native_array, int size) { 51 ToJavaIntArray(JNIEnv* env, std::unique_ptr<jint[]> native_array, int size) {
83 ScopedJavaLocalRef<jintArray> j_array(env, env->NewIntArray(size)); 52 ScopedJavaLocalRef<jintArray> j_array(env, env->NewIntArray(size));
84 env->SetIntArrayRegion(j_array.obj(), 0, size, native_array.get()); 53 env->SetIntArrayRegion(j_array.obj(), 0, size, native_array.get());
85 return j_array; 54 return j_array;
86 } 55 }
87 56
57 // Parses |extra_data| and sets the appropriate fields of the given MediaFormat.
58 bool ConfigureMediaFormatForAudio(jobject j_format,
watk 2017/02/14 01:40:50 Unchanged; moved only
59 AudioCodec codec,
60 const uint8_t* extra_data,
61 size_t extra_data_size,
62 int64_t codec_delay_ns,
63 int64_t seek_preroll_ns) {
64 if (extra_data_size == 0 && codec != kCodecOpus)
65 return true;
66
67 JNIEnv* env = AttachCurrentThread();
68 switch (codec) {
69 case kCodecVorbis: {
70 if (extra_data[0] != 2) {
71 LOG(ERROR) << "Invalid number of vorbis headers before the codec "
72 << "header: " << extra_data[0];
73 return false;
74 }
75
76 size_t header_length[2];
77 // |total_length| keeps track of the total number of bytes before the last
78 // header.
79 size_t total_length = 1;
80 const uint8_t* current_pos = extra_data;
81 // Calculate the length of the first 2 headers.
82 for (int i = 0; i < 2; ++i) {
83 header_length[i] = 0;
84 while (total_length < extra_data_size) {
85 size_t size = *(++current_pos);
86 total_length += 1 + size;
87 if (total_length > 0x80000000) {
88 LOG(ERROR) << "Vorbis header size too large";
89 return false;
90 }
91 header_length[i] += size;
92 if (size < 0xFF)
93 break;
94 }
95 if (total_length >= extra_data_size) {
96 LOG(ERROR) << "Invalid vorbis header size in the extra data";
97 return false;
98 }
99 }
100 current_pos++;
101 // The first header is identification header.
102 ScopedJavaLocalRef<jbyteArray> first_header =
103 base::android::ToJavaByteArray(env, current_pos, header_length[0]);
104 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0,
105 first_header);
106 // The last header is codec header.
107 ScopedJavaLocalRef<jbyteArray> last_header =
108 base::android::ToJavaByteArray(env, extra_data + total_length,
109 extra_data_size - total_length);
110 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 1, last_header);
111 break;
112 }
113 case kCodecAAC: {
114 media::BitReader reader(extra_data, extra_data_size);
115
116 // The following code is copied from aac.cc
117 // TODO(qinmin): refactor the code in aac.cc to make it more reusable.
118 uint8_t profile = 0;
119 uint8_t frequency_index = 0;
120 uint8_t channel_config = 0;
121 RETURN_ON_ERROR(reader.ReadBits(5, &profile));
122 RETURN_ON_ERROR(reader.ReadBits(4, &frequency_index));
123
124 if (0xf == frequency_index)
125 RETURN_ON_ERROR(reader.SkipBits(24));
126 RETURN_ON_ERROR(reader.ReadBits(4, &channel_config));
127
128 if (profile == 5 || profile == 29) {
129 // Read extension config.
130 RETURN_ON_ERROR(reader.ReadBits(4, &frequency_index));
131 if (frequency_index == 0xf)
132 RETURN_ON_ERROR(reader.SkipBits(24));
133 RETURN_ON_ERROR(reader.ReadBits(5, &profile));
134 }
135
136 if (profile < 1 || profile > 4 || frequency_index == 0xf ||
137 channel_config > 7) {
138 LOG(ERROR) << "Invalid AAC header";
139 return false;
140 }
141
142 const size_t kCsdLength = 2;
143 uint8_t csd[kCsdLength];
144 csd[0] = profile << 3 | frequency_index >> 1;
145 csd[1] = (frequency_index & 0x01) << 7 | channel_config << 3;
146 ScopedJavaLocalRef<jbyteArray> byte_array =
147 base::android::ToJavaByteArray(env, csd, kCsdLength);
148 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0, byte_array);
149
150 // TODO(qinmin): pass an extra variable to this function to determine
151 // whether we need to call this.
152 Java_MediaCodecBridge_setFrameHasADTSHeader(env, j_format);
153 break;
154 }
155 case kCodecOpus: {
156 if (!extra_data || extra_data_size == 0 || codec_delay_ns < 0 ||
157 seek_preroll_ns < 0) {
158 LOG(ERROR) << "Invalid Opus Header";
159 return false;
160 }
161
162 // csd0 - Opus Header
163 ScopedJavaLocalRef<jbyteArray> csd0 =
164 base::android::ToJavaByteArray(env, extra_data, extra_data_size);
165 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0, csd0);
166
167 // csd1 - Codec Delay
168 ScopedJavaLocalRef<jbyteArray> csd1 = base::android::ToJavaByteArray(
169 env, reinterpret_cast<const uint8_t*>(&codec_delay_ns),
170 sizeof(int64_t));
171 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 1, csd1);
172
173 // csd2 - Seek Preroll
174 ScopedJavaLocalRef<jbyteArray> csd2 = base::android::ToJavaByteArray(
175 env, reinterpret_cast<const uint8_t*>(&seek_preroll_ns),
176 sizeof(int64_t));
177 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 2, csd2);
178 break;
179 }
180 default:
181 LOG(ERROR) << "Invalid header encountered for codec: "
182 << GetCodecName(codec);
183 return false;
184 }
185 return true;
186 }
187
88 } // namespace 188 } // namespace
89 189
190 // static
191 std::unique_ptr<MediaCodecBridge> MediaCodecBridgeImpl::CreateAudioDecoder(
watk 2017/02/14 01:40:50 This used to be two separate calls: Create() and C
192 const AudioDecoderConfig& config,
193 jobject media_crypto) {
194 DVLOG(2) << __func__ << ": " << config.AsHumanReadableString()
195 << " media_crypto:" << media_crypto;
196
197 if (!MediaCodecUtil::IsMediaCodecAvailable())
198 return nullptr;
199
200 const std::string mime =
201 MediaCodecUtil::CodecToAndroidMimeType(config.codec());
202 if (mime.empty())
203 return false;
204
205 auto bridge = base::WrapUnique(new MediaCodecBridgeImpl(
206 mime, false, MediaCodecDirection::DECODER, false));
207 if (bridge->j_bridge_.is_null())
208 return nullptr;
209
210 JNIEnv* env = AttachCurrentThread();
211 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
212
213 const int channel_count =
214 ChannelLayoutToChannelCount(config.channel_layout());
215 ScopedJavaLocalRef<jobject> j_format(Java_MediaCodecBridge_createAudioFormat(
216 env, j_mime, config.samples_per_second(), channel_count));
217 DCHECK(!j_format.is_null());
218
219 const int64_t codec_delay_ns = config.codec_delay() /
220 config.samples_per_second() *
221 base::Time::kNanosecondsPerSecond;
222 const int64_t seek_preroll_ns = config.seek_preroll().InMicroseconds() *
223 base::Time::kNanosecondsPerMicrosecond;
224 if (!ConfigureMediaFormatForAudio(
225 j_format.obj(), config.codec(), config.extra_data().data(),
226 config.extra_data().size(), codec_delay_ns, seek_preroll_ns)) {
227 return false;
228 }
229
230 if (!Java_MediaCodecBridge_configureAudio(env, bridge->j_bridge_, j_format,
231 media_crypto, 0)) {
232 return false;
233 }
234
235 return bridge->Start() ? std::move(bridge) : nullptr;
236 }
237
238 // static
239 std::unique_ptr<MediaCodecBridge> MediaCodecBridgeImpl::CreateVideoDecoder(
240 VideoCodec codec,
241 bool is_secure,
242 const gfx::Size& size,
243 jobject surface,
244 jobject media_crypto,
245 const std::vector<uint8_t>& csd0,
246 const std::vector<uint8_t>& csd1,
247 bool allow_adaptive_playback,
248 bool require_software_codec) {
249 if (!MediaCodecUtil::IsMediaCodecAvailable())
250 return nullptr;
251
252 const std::string mime = MediaCodecUtil::CodecToAndroidMimeType(codec);
253 if (mime.empty())
254 return nullptr;
255
256 std::unique_ptr<MediaCodecBridgeImpl> bridge(new MediaCodecBridgeImpl(
257 mime, is_secure, MediaCodecDirection::DECODER, require_software_codec));
258 if (bridge->j_bridge_.is_null())
259 return nullptr;
260
261 JNIEnv* env = AttachCurrentThread();
262 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
263 ScopedJavaLocalRef<jobject> j_format(
264 Java_MediaCodecBridge_createVideoDecoderFormat(env, j_mime, size.width(),
265 size.height()));
266 DCHECK(!j_format.is_null());
267
268 if (!csd0.empty()) {
269 ScopedJavaLocalRef<jbyteArray> j_csd0 =
270 base::android::ToJavaByteArray(env, csd0.data(), csd0.size());
271 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0, j_csd0);
272 }
273
274 if (!csd1.empty()) {
275 ScopedJavaLocalRef<jbyteArray> j_csd1 =
276 base::android::ToJavaByteArray(env, csd1.data(), csd1.size());
277 Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 1, j_csd1);
278 }
279
280 if (!Java_MediaCodecBridge_configureVideo(env, bridge->j_bridge_, j_format,
281 surface, media_crypto, 0,
282 allow_adaptive_playback)) {
283 return nullptr;
284 }
285
286 return bridge->Start() ? std::move(bridge) : nullptr;
287 }
288
289 // static
290 std::unique_ptr<MediaCodecBridge> MediaCodecBridgeImpl::CreateVideoEncoder(
291 VideoCodec codec,
292 const gfx::Size& size,
293 int bit_rate,
294 int frame_rate,
295 int i_frame_interval,
296 int color_format) {
297 if (!MediaCodecUtil::IsMediaCodecAvailable())
298 return nullptr;
299
300 const std::string mime = MediaCodecUtil::CodecToAndroidMimeType(codec);
301 if (mime.empty())
302 return nullptr;
303
304 std::unique_ptr<MediaCodecBridgeImpl> bridge(new MediaCodecBridgeImpl(
305 mime, false, MediaCodecDirection::ENCODER, false));
306 if (bridge->j_bridge_.is_null())
307 return nullptr;
308
309 JNIEnv* env = AttachCurrentThread();
310 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
311 ScopedJavaLocalRef<jobject> j_format(
312 Java_MediaCodecBridge_createVideoEncoderFormat(
313 env, bridge->j_bridge_, j_mime, size.width(), size.height(), bit_rate,
314 frame_rate, i_frame_interval, color_format));
315 DCHECK(!j_format.is_null());
316 if (!Java_MediaCodecBridge_configureVideo(env, bridge->j_bridge_, j_format,
317 nullptr, nullptr,
318 kConfigureFlagEncode, true)) {
319 return nullptr;
320 }
321
322 return bridge->Start() ? std::move(bridge) : nullptr;
323 }
324
90 MediaCodecBridgeImpl::MediaCodecBridgeImpl(const std::string& mime, 325 MediaCodecBridgeImpl::MediaCodecBridgeImpl(const std::string& mime,
91 bool is_secure, 326 bool is_secure,
92 MediaCodecDirection direction, 327 MediaCodecDirection direction,
93 bool require_software_codec) { 328 bool require_software_codec) {
94 JNIEnv* env = AttachCurrentThread(); 329 JNIEnv* env = AttachCurrentThread();
95 DCHECK(!mime.empty()); 330 DCHECK(!mime.empty());
96 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime); 331 ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
97 j_media_codec_.Reset(Java_MediaCodecBridge_create( 332 j_bridge_.Reset(Java_MediaCodecBridge_create(env, j_mime, is_secure,
98 env, j_mime, is_secure, direction, require_software_codec)); 333 static_cast<int>(direction),
334 require_software_codec));
99 } 335 }
100 336
101 MediaCodecBridgeImpl::~MediaCodecBridgeImpl() { 337 MediaCodecBridgeImpl::~MediaCodecBridgeImpl() {
102 JNIEnv* env = AttachCurrentThread(); 338 JNIEnv* env = AttachCurrentThread();
103 if (j_media_codec_.obj()) 339 if (j_bridge_.obj())
104 Java_MediaCodecBridge_release(env, j_media_codec_); 340 Java_MediaCodecBridge_release(env, j_bridge_);
105 } 341 }
106 342
107 bool MediaCodecBridgeImpl::Start() { 343 bool MediaCodecBridgeImpl::Start() {
108 JNIEnv* env = AttachCurrentThread(); 344 JNIEnv* env = AttachCurrentThread();
109 return Java_MediaCodecBridge_start(env, j_media_codec_); 345 return Java_MediaCodecBridge_start(env, j_bridge_);
110 } 346 }
111 347
112 void MediaCodecBridgeImpl::Stop() { 348 void MediaCodecBridgeImpl::Stop() {
113 JNIEnv* env = AttachCurrentThread(); 349 JNIEnv* env = AttachCurrentThread();
114 Java_MediaCodecBridge_stop(env, j_media_codec_); 350 Java_MediaCodecBridge_stop(env, j_bridge_);
115 } 351 }
116 352
117 MediaCodecStatus MediaCodecBridgeImpl::Flush() { 353 MediaCodecStatus MediaCodecBridgeImpl::Flush() {
118 JNIEnv* env = AttachCurrentThread(); 354 JNIEnv* env = AttachCurrentThread();
119 return static_cast<MediaCodecStatus>( 355 return static_cast<MediaCodecStatus>(
120 Java_MediaCodecBridge_flush(env, j_media_codec_)); 356 Java_MediaCodecBridge_flush(env, j_bridge_));
121 } 357 }
122 358
123 MediaCodecStatus MediaCodecBridgeImpl::GetOutputSize(gfx::Size* size) { 359 MediaCodecStatus MediaCodecBridgeImpl::GetOutputSize(gfx::Size* size) {
124 JNIEnv* env = AttachCurrentThread(); 360 JNIEnv* env = AttachCurrentThread();
125 ScopedJavaLocalRef<jobject> result = 361 ScopedJavaLocalRef<jobject> result =
126 Java_MediaCodecBridge_getOutputFormat(env, j_media_codec_); 362 Java_MediaCodecBridge_getOutputFormat(env, j_bridge_);
127 MediaCodecStatus status = static_cast<MediaCodecStatus>( 363 MediaCodecStatus status = static_cast<MediaCodecStatus>(
128 Java_GetOutputFormatResult_status(env, result)); 364 Java_GetOutputFormatResult_status(env, result));
129 if (status == MEDIA_CODEC_OK) { 365 if (status == MEDIA_CODEC_OK) {
130 size->SetSize(Java_GetOutputFormatResult_width(env, result), 366 size->SetSize(Java_GetOutputFormatResult_width(env, result),
131 Java_GetOutputFormatResult_height(env, result)); 367 Java_GetOutputFormatResult_height(env, result));
132 } 368 }
133 return status; 369 return status;
134 } 370 }
135 371
136 MediaCodecStatus MediaCodecBridgeImpl::GetOutputSamplingRate( 372 MediaCodecStatus MediaCodecBridgeImpl::GetOutputSamplingRate(
137 int* sampling_rate) { 373 int* sampling_rate) {
138 JNIEnv* env = AttachCurrentThread(); 374 JNIEnv* env = AttachCurrentThread();
139 ScopedJavaLocalRef<jobject> result = 375 ScopedJavaLocalRef<jobject> result =
140 Java_MediaCodecBridge_getOutputFormat(env, j_media_codec_); 376 Java_MediaCodecBridge_getOutputFormat(env, j_bridge_);
141 MediaCodecStatus status = static_cast<MediaCodecStatus>( 377 MediaCodecStatus status = static_cast<MediaCodecStatus>(
142 Java_GetOutputFormatResult_status(env, result)); 378 Java_GetOutputFormatResult_status(env, result));
143 if (status == MEDIA_CODEC_OK) 379 if (status == MEDIA_CODEC_OK)
144 *sampling_rate = Java_GetOutputFormatResult_sampleRate(env, result); 380 *sampling_rate = Java_GetOutputFormatResult_sampleRate(env, result);
145 return status; 381 return status;
146 } 382 }
147 383
148 MediaCodecStatus MediaCodecBridgeImpl::GetOutputChannelCount( 384 MediaCodecStatus MediaCodecBridgeImpl::GetOutputChannelCount(
149 int* channel_count) { 385 int* channel_count) {
150 JNIEnv* env = AttachCurrentThread(); 386 JNIEnv* env = AttachCurrentThread();
151 ScopedJavaLocalRef<jobject> result = 387 ScopedJavaLocalRef<jobject> result =
152 Java_MediaCodecBridge_getOutputFormat(env, j_media_codec_); 388 Java_MediaCodecBridge_getOutputFormat(env, j_bridge_);
153 MediaCodecStatus status = static_cast<MediaCodecStatus>( 389 MediaCodecStatus status = static_cast<MediaCodecStatus>(
154 Java_GetOutputFormatResult_status(env, result)); 390 Java_GetOutputFormatResult_status(env, result));
155 if (status == MEDIA_CODEC_OK) 391 if (status == MEDIA_CODEC_OK)
156 *channel_count = Java_GetOutputFormatResult_channelCount(env, result); 392 *channel_count = Java_GetOutputFormatResult_channelCount(env, result);
157 return status; 393 return status;
158 } 394 }
159 395
160 MediaCodecStatus MediaCodecBridgeImpl::QueueInputBuffer( 396 MediaCodecStatus MediaCodecBridgeImpl::QueueInputBuffer(
161 int index, 397 int index,
162 const uint8_t* data, 398 const uint8_t* data,
163 size_t data_size, 399 size_t data_size,
164 base::TimeDelta presentation_time) { 400 base::TimeDelta presentation_time) {
165 DVLOG(3) << __func__ << " " << index << ": " << data_size; 401 DVLOG(3) << __func__ << " " << index << ": " << data_size;
166 if (data_size > 402 if (data_size >
167 base::checked_cast<size_t>(std::numeric_limits<int32_t>::max())) { 403 base::checked_cast<size_t>(std::numeric_limits<int32_t>::max())) {
168 return MEDIA_CODEC_ERROR; 404 return MEDIA_CODEC_ERROR;
169 } 405 }
170 if (data && !FillInputBuffer(index, data, data_size)) 406 if (data && !FillInputBuffer(index, data, data_size))
171 return MEDIA_CODEC_ERROR; 407 return MEDIA_CODEC_ERROR;
172 JNIEnv* env = AttachCurrentThread(); 408 JNIEnv* env = AttachCurrentThread();
173 return static_cast<MediaCodecStatus>(Java_MediaCodecBridge_queueInputBuffer( 409 return static_cast<MediaCodecStatus>(Java_MediaCodecBridge_queueInputBuffer(
174 env, j_media_codec_, index, 0, data_size, 410 env, j_bridge_, index, 0, data_size, presentation_time.InMicroseconds(),
175 presentation_time.InMicroseconds(), 0)); 411 0));
176 } 412 }
177 413
178 MediaCodecStatus MediaCodecBridgeImpl::QueueSecureInputBuffer( 414 MediaCodecStatus MediaCodecBridgeImpl::QueueSecureInputBuffer(
179 int index, 415 int index,
180 const uint8_t* data, 416 const uint8_t* data,
181 size_t data_size, 417 size_t data_size,
182 const std::string& key_id, 418 const std::string& key_id,
183 const std::string& iv, 419 const std::string& iv,
184 const std::vector<SubsampleEntry>& subsamples, 420 const std::vector<SubsampleEntry>& subsamples,
185 const EncryptionScheme& encryption_scheme, 421 const EncryptionScheme& encryption_scheme,
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 } 459 }
224 } 460 }
225 461
226 ScopedJavaLocalRef<jintArray> clear_array = 462 ScopedJavaLocalRef<jintArray> clear_array =
227 ToJavaIntArray(env, std::move(native_clear_array), num_subsamples); 463 ToJavaIntArray(env, std::move(native_clear_array), num_subsamples);
228 ScopedJavaLocalRef<jintArray> cypher_array = 464 ScopedJavaLocalRef<jintArray> cypher_array =
229 ToJavaIntArray(env, std::move(native_cypher_array), num_subsamples); 465 ToJavaIntArray(env, std::move(native_cypher_array), num_subsamples);
230 466
231 return static_cast<MediaCodecStatus>( 467 return static_cast<MediaCodecStatus>(
232 Java_MediaCodecBridge_queueSecureInputBuffer( 468 Java_MediaCodecBridge_queueSecureInputBuffer(
233 env, j_media_codec_.obj(), index, 0, j_iv.obj(), j_key_id.obj(), 469 env, j_bridge_.obj(), index, 0, j_iv.obj(), j_key_id.obj(),
234 clear_array, cypher_array, num_subsamples, 470 clear_array, cypher_array, num_subsamples,
235 static_cast<int>(encryption_scheme.mode()), 471 static_cast<int>(encryption_scheme.mode()),
236 static_cast<int>(encryption_scheme.pattern().encrypt_blocks()), 472 static_cast<int>(encryption_scheme.pattern().encrypt_blocks()),
237 static_cast<int>(encryption_scheme.pattern().skip_blocks()), 473 static_cast<int>(encryption_scheme.pattern().skip_blocks()),
238 presentation_time.InMicroseconds())); 474 presentation_time.InMicroseconds()));
239 } 475 }
240 476
241 void MediaCodecBridgeImpl::QueueEOS(int input_buffer_index) { 477 void MediaCodecBridgeImpl::QueueEOS(int input_buffer_index) {
242 DVLOG(3) << __func__ << ": " << input_buffer_index; 478 DVLOG(3) << __func__ << ": " << input_buffer_index;
243 JNIEnv* env = AttachCurrentThread(); 479 JNIEnv* env = AttachCurrentThread();
244 Java_MediaCodecBridge_queueInputBuffer( 480 Java_MediaCodecBridge_queueInputBuffer(env, j_bridge_, input_buffer_index, 0,
245 env, j_media_codec_, input_buffer_index, 0, 0, 0, kBufferFlagEndOfStream); 481 0, 0, kBufferFlagEndOfStream);
246 } 482 }
247 483
248 MediaCodecStatus MediaCodecBridgeImpl::DequeueInputBuffer( 484 MediaCodecStatus MediaCodecBridgeImpl::DequeueInputBuffer(
249 base::TimeDelta timeout, 485 base::TimeDelta timeout,
250 int* index) { 486 int* index) {
251 JNIEnv* env = AttachCurrentThread(); 487 JNIEnv* env = AttachCurrentThread();
252 ScopedJavaLocalRef<jobject> result = Java_MediaCodecBridge_dequeueInputBuffer( 488 ScopedJavaLocalRef<jobject> result = Java_MediaCodecBridge_dequeueInputBuffer(
253 env, j_media_codec_, timeout.InMicroseconds()); 489 env, j_bridge_, timeout.InMicroseconds());
254 *index = Java_DequeueInputResult_index(env, result); 490 *index = Java_DequeueInputResult_index(env, result);
255 MediaCodecStatus status = static_cast<MediaCodecStatus>( 491 MediaCodecStatus status = static_cast<MediaCodecStatus>(
256 Java_DequeueInputResult_status(env, result)); 492 Java_DequeueInputResult_status(env, result));
257 DVLOG(3) << __func__ << ": status: " << status << ", index: " << *index; 493 DVLOG(3) << __func__ << ": status: " << status << ", index: " << *index;
258 return status; 494 return status;
259 } 495 }
260 496
261 MediaCodecStatus MediaCodecBridgeImpl::DequeueOutputBuffer( 497 MediaCodecStatus MediaCodecBridgeImpl::DequeueOutputBuffer(
262 base::TimeDelta timeout, 498 base::TimeDelta timeout,
263 int* index, 499 int* index,
264 size_t* offset, 500 size_t* offset,
265 size_t* size, 501 size_t* size,
266 base::TimeDelta* presentation_time, 502 base::TimeDelta* presentation_time,
267 bool* end_of_stream, 503 bool* end_of_stream,
268 bool* key_frame) { 504 bool* key_frame) {
269 JNIEnv* env = AttachCurrentThread(); 505 JNIEnv* env = AttachCurrentThread();
270 ScopedJavaLocalRef<jobject> result = 506 ScopedJavaLocalRef<jobject> result =
271 Java_MediaCodecBridge_dequeueOutputBuffer(env, j_media_codec_, 507 Java_MediaCodecBridge_dequeueOutputBuffer(env, j_bridge_,
272 timeout.InMicroseconds()); 508 timeout.InMicroseconds());
273 *index = Java_DequeueOutputResult_index(env, result); 509 *index = Java_DequeueOutputResult_index(env, result);
274 *offset = 510 *offset =
275 base::checked_cast<size_t>(Java_DequeueOutputResult_offset(env, result)); 511 base::checked_cast<size_t>(Java_DequeueOutputResult_offset(env, result));
276 *size = base::checked_cast<size_t>( 512 *size = base::checked_cast<size_t>(
277 Java_DequeueOutputResult_numBytes(env, result)); 513 Java_DequeueOutputResult_numBytes(env, result));
278 if (presentation_time) { 514 if (presentation_time) {
279 *presentation_time = base::TimeDelta::FromMicroseconds( 515 *presentation_time = base::TimeDelta::FromMicroseconds(
280 Java_DequeueOutputResult_presentationTimeMicroseconds(env, result)); 516 Java_DequeueOutputResult_presentationTimeMicroseconds(env, result));
281 } 517 }
282 int flags = Java_DequeueOutputResult_flags(env, result); 518 int flags = Java_DequeueOutputResult_flags(env, result);
283 if (end_of_stream) 519 if (end_of_stream)
284 *end_of_stream = flags & kBufferFlagEndOfStream; 520 *end_of_stream = flags & kBufferFlagEndOfStream;
285 if (key_frame) 521 if (key_frame)
286 *key_frame = flags & kBufferFlagSyncFrame; 522 *key_frame = flags & kBufferFlagSyncFrame;
287 MediaCodecStatus status = static_cast<MediaCodecStatus>( 523 MediaCodecStatus status = static_cast<MediaCodecStatus>(
288 Java_DequeueOutputResult_status(env, result)); 524 Java_DequeueOutputResult_status(env, result));
289 DVLOG(3) << __func__ << ": status: " << status << ", index: " << *index 525 DVLOG(3) << __func__ << ": status: " << status << ", index: " << *index
290 << ", offset: " << *offset << ", size: " << *size 526 << ", offset: " << *offset << ", size: " << *size
291 << ", flags: " << flags; 527 << ", flags: " << flags;
292 return status; 528 return status;
293 } 529 }
294 530
295 void MediaCodecBridgeImpl::ReleaseOutputBuffer(int index, bool render) { 531 void MediaCodecBridgeImpl::ReleaseOutputBuffer(int index, bool render) {
296 DVLOG(3) << __func__ << ": " << index; 532 DVLOG(3) << __func__ << ": " << index;
297 JNIEnv* env = AttachCurrentThread(); 533 JNIEnv* env = AttachCurrentThread();
298 Java_MediaCodecBridge_releaseOutputBuffer(env, j_media_codec_, index, render); 534 Java_MediaCodecBridge_releaseOutputBuffer(env, j_bridge_, index, render);
299 } 535 }
300 536
301 MediaCodecStatus MediaCodecBridgeImpl::GetInputBuffer(int input_buffer_index, 537 MediaCodecStatus MediaCodecBridgeImpl::GetInputBuffer(int input_buffer_index,
302 uint8_t** data, 538 uint8_t** data,
303 size_t* capacity) { 539 size_t* capacity) {
304 JNIEnv* env = AttachCurrentThread(); 540 JNIEnv* env = AttachCurrentThread();
305 ScopedJavaLocalRef<jobject> j_buffer(Java_MediaCodecBridge_getInputBuffer( 541 ScopedJavaLocalRef<jobject> j_buffer(
306 env, j_media_codec_, input_buffer_index)); 542 Java_MediaCodecBridge_getInputBuffer(env, j_bridge_, input_buffer_index));
307 if (j_buffer.is_null()) 543 if (j_buffer.is_null())
308 return MEDIA_CODEC_ERROR; 544 return MEDIA_CODEC_ERROR;
309 545
310 *data = static_cast<uint8_t*>(env->GetDirectBufferAddress(j_buffer.obj())); 546 *data = static_cast<uint8_t*>(env->GetDirectBufferAddress(j_buffer.obj()));
311 *capacity = 547 *capacity =
312 base::checked_cast<size_t>(env->GetDirectBufferCapacity(j_buffer.obj())); 548 base::checked_cast<size_t>(env->GetDirectBufferCapacity(j_buffer.obj()));
313 return MEDIA_CODEC_OK; 549 return MEDIA_CODEC_OK;
314 } 550 }
315 551
316 MediaCodecStatus MediaCodecBridgeImpl::CopyFromOutputBuffer(int index, 552 MediaCodecStatus MediaCodecBridgeImpl::CopyFromOutputBuffer(int index,
(...skipping 11 matching lines...) Expand all
328 return status; 564 return status;
329 } 565 }
330 566
331 MediaCodecStatus MediaCodecBridgeImpl::GetOutputBufferAddress( 567 MediaCodecStatus MediaCodecBridgeImpl::GetOutputBufferAddress(
332 int index, 568 int index,
333 size_t offset, 569 size_t offset,
334 const uint8_t** addr, 570 const uint8_t** addr,
335 size_t* capacity) { 571 size_t* capacity) {
336 JNIEnv* env = AttachCurrentThread(); 572 JNIEnv* env = AttachCurrentThread();
337 ScopedJavaLocalRef<jobject> j_buffer( 573 ScopedJavaLocalRef<jobject> j_buffer(
338 Java_MediaCodecBridge_getOutputBuffer(env, j_media_codec_, index)); 574 Java_MediaCodecBridge_getOutputBuffer(env, j_bridge_, index));
339 if (j_buffer.is_null()) 575 if (j_buffer.is_null())
340 return MEDIA_CODEC_ERROR; 576 return MEDIA_CODEC_ERROR;
341 const size_t total_capacity = env->GetDirectBufferCapacity(j_buffer.obj()); 577 const size_t total_capacity = env->GetDirectBufferCapacity(j_buffer.obj());
342 CHECK_GE(total_capacity, offset); 578 CHECK_GE(total_capacity, offset);
343 *addr = reinterpret_cast<const uint8_t*>( 579 *addr = reinterpret_cast<const uint8_t*>(
344 env->GetDirectBufferAddress(j_buffer.obj())) + 580 env->GetDirectBufferAddress(j_buffer.obj())) +
345 offset; 581 offset;
346 *capacity = total_capacity - offset; 582 *capacity = total_capacity - offset;
347 return MEDIA_CODEC_OK; 583 return MEDIA_CODEC_OK;
348 } 584 }
349 585
350 std::string MediaCodecBridgeImpl::GetName() { 586 std::string MediaCodecBridgeImpl::GetName() {
351 if (base::android::BuildInfo::GetInstance()->sdk_int() < 18) 587 if (base::android::BuildInfo::GetInstance()->sdk_int() < 18)
352 return ""; 588 return "";
353 JNIEnv* env = AttachCurrentThread(); 589 JNIEnv* env = AttachCurrentThread();
354 ScopedJavaLocalRef<jstring> j_name = 590 ScopedJavaLocalRef<jstring> j_name =
355 Java_MediaCodecBridge_getName(env, j_media_codec_); 591 Java_MediaCodecBridge_getName(env, j_bridge_);
356 return ConvertJavaStringToUTF8(env, j_name); 592 return ConvertJavaStringToUTF8(env, j_name);
357 } 593 }
358 594
595 bool MediaCodecBridgeImpl::SetSurface(jobject surface) {
596 DCHECK_GE(base::android::BuildInfo::GetInstance()->sdk_int(), 23);
597 JNIEnv* env = AttachCurrentThread();
598 return Java_MediaCodecBridge_setSurface(env, j_bridge_, surface);
599 }
600
601 void MediaCodecBridgeImpl::SetVideoBitrate(int bps, int frame_rate) {
602 JNIEnv* env = AttachCurrentThread();
603 Java_MediaCodecBridge_setVideoBitrate(env, j_bridge_, bps, frame_rate);
604 }
605
606 void MediaCodecBridgeImpl::RequestKeyFrameSoon() {
607 JNIEnv* env = AttachCurrentThread();
608 Java_MediaCodecBridge_requestKeyFrameSoon(env, j_bridge_);
609 }
610
611 bool MediaCodecBridgeImpl::IsAdaptivePlaybackSupported() {
612 JNIEnv* env = AttachCurrentThread();
613 return Java_MediaCodecBridge_isAdaptivePlaybackSupported(env, j_bridge_);
614 }
615
359 bool MediaCodecBridgeImpl::FillInputBuffer(int index, 616 bool MediaCodecBridgeImpl::FillInputBuffer(int index,
360 const uint8_t* data, 617 const uint8_t* data,
361 size_t size) { 618 size_t size) {
362 uint8_t* dst = nullptr; 619 uint8_t* dst = nullptr;
363 size_t capacity = 0; 620 size_t capacity = 0;
364 if (GetInputBuffer(index, &dst, &capacity) != MEDIA_CODEC_OK) { 621 if (GetInputBuffer(index, &dst, &capacity) != MEDIA_CODEC_OK) {
365 LOG(ERROR) << "GetInputBuffer failed"; 622 LOG(ERROR) << "GetInputBuffer failed";
366 return false; 623 return false;
367 } 624 }
368 CHECK(dst); 625 CHECK(dst);
369 626
370 if (size > capacity) { 627 if (size > capacity) {
371 LOG(ERROR) << "Input buffer size " << size 628 LOG(ERROR) << "Input buffer size " << size
372 << " exceeds MediaCodec input buffer capacity: " << capacity; 629 << " exceeds MediaCodec input buffer capacity: " << capacity;
373 return false; 630 return false;
374 } 631 }
375 632
376 memcpy(dst, data, size); 633 memcpy(dst, data, size);
377 return true; 634 return true;
378 } 635 }
379 636
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 637
722 } // namespace media 638 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698