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

Side by Side Diff: media/base/android/java/src/org/chromium/media/MediaCodecBridge.java

Issue 74563002: AndroidVideoEncodeAccelerator is born! (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Added blacklist-based disabling Created 7 years 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 | Annotate | Revision Log
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 package org.chromium.media; 5 package org.chromium.media;
6 6
7 import android.media.AudioFormat; 7 import android.media.AudioFormat;
8 import android.media.AudioManager; 8 import android.media.AudioManager;
9 import android.media.AudioTrack; 9 import android.media.AudioTrack;
10 import android.media.MediaCodec; 10 import android.media.MediaCodec;
11 import android.media.MediaCodecInfo; 11 import android.media.MediaCodecInfo;
12 import android.media.MediaCodecList; 12 import android.media.MediaCodecList;
13 import android.media.MediaCrypto; 13 import android.media.MediaCrypto;
14 import android.media.MediaFormat; 14 import android.media.MediaFormat;
15 import android.os.Build; 15 import android.os.Build;
16 import android.os.Bundle;
16 import android.util.Log; 17 import android.util.Log;
17 import android.view.Surface; 18 import android.view.Surface;
18 19
19 import java.io.IOException; 20 import java.io.IOException;
20 import java.nio.ByteBuffer; 21 import java.nio.ByteBuffer;
21 import java.util.ArrayList; 22 import java.util.ArrayList;
23 import java.util.Collection;
22 import java.util.HashMap; 24 import java.util.HashMap;
23 import java.util.Map; 25 import java.util.Map;
24 26
25 import org.chromium.base.CalledByNative; 27 import org.chromium.base.CalledByNative;
26 import org.chromium.base.JNINamespace; 28 import org.chromium.base.JNINamespace;
27 29
28 /** 30 /**
29 * A wrapper of the MediaCodec class to facilitate exception capturing and 31 * A wrapper of the MediaCodec class to facilitate exception capturing and
30 * audio rendering. 32 * audio rendering.
31 */ 33 */
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 @CalledByNative("DequeueInputResult") 79 @CalledByNative("DequeueInputResult")
78 private int index() { return mIndex; } 80 private int index() { return mIndex; }
79 } 81 }
80 82
81 /** 83 /**
82 * This class represents supported android codec information. 84 * This class represents supported android codec information.
83 */ 85 */
84 private static class CodecInfo { 86 private static class CodecInfo {
85 private final String mCodecType; // e.g. "video/x-vnd.on2.vp8". 87 private final String mCodecType; // e.g. "video/x-vnd.on2.vp8".
86 private final String mCodecName; // e.g. "OMX.google.vp8.decoder". 88 private final String mCodecName; // e.g. "OMX.google.vp8.decoder".
89 private final boolean mIsEncoder;
87 90
88 private CodecInfo(String codecType, String codecName) { 91 private CodecInfo(String codecType, String codecName,
92 boolean isEncoder) {
89 mCodecType = codecType; 93 mCodecType = codecType;
90 mCodecName = codecName; 94 mCodecName = codecName;
95 mIsEncoder = isEncoder;
91 } 96 }
92 97
93 @CalledByNative("CodecInfo") 98 @CalledByNative("CodecInfo")
94 private String codecType() { return mCodecType; } 99 private String codecType() { return mCodecType; }
95 100
96 @CalledByNative("CodecInfo") 101 @CalledByNative("CodecInfo")
97 private String codecName() { return mCodecName; } 102 private String codecName() { return mCodecName; }
103
104 @CalledByNative("CodecInfo")
105 private boolean isEncoder() { return mIsEncoder; }
98 } 106 }
99 107
100 private static class DequeueOutputResult { 108 private static class DequeueOutputResult {
101 private final int mStatus; 109 private final int mStatus;
102 private final int mIndex; 110 private final int mIndex;
103 private final int mFlags; 111 private final int mFlags;
104 private final int mOffset; 112 private final int mOffset;
105 private final long mPresentationTimeMicroseconds; 113 private final long mPresentationTimeMicroseconds;
106 private final int mNumBytes; 114 private final int mNumBytes;
107 115
(...skipping 24 matching lines...) Expand all
132 140
133 @CalledByNative("DequeueOutputResult") 141 @CalledByNative("DequeueOutputResult")
134 private int numBytes() { return mNumBytes; } 142 private int numBytes() { return mNumBytes; }
135 } 143 }
136 144
137 /** 145 /**
138 * Get a list of supported android codec mimes. 146 * Get a list of supported android codec mimes.
139 */ 147 */
140 @CalledByNative 148 @CalledByNative
141 private static CodecInfo[] getCodecsInfo() { 149 private static CodecInfo[] getCodecsInfo() {
142 Map<String, CodecInfo> CodecInfoMap = new HashMap<String, CodecInfo>(); 150 // Return the first (highest-priority) codec for each MIME type.
151 Map<String, CodecInfo> encoderInfoMap = new HashMap<String, CodecInfo>() ;
152 Map<String, CodecInfo> decoderInfoMap = new HashMap<String, CodecInfo>() ;
143 int count = MediaCodecList.getCodecCount(); 153 int count = MediaCodecList.getCodecCount();
144 for (int i = 0; i < count; ++i) { 154 for (int i = 0; i < count; ++i) {
145 MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i); 155 MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
146 if (info.isEncoder()) { 156 boolean isEncoder = info.isEncoder();
147 continue;
148 }
149
150 String codecString = info.getName(); 157 String codecString = info.getName();
151 String[] supportedTypes = info.getSupportedTypes(); 158 String[] supportedTypes = info.getSupportedTypes();
152 for (int j = 0; j < supportedTypes.length; ++j) { 159 for (int j = 0; j < supportedTypes.length; ++j) {
153 if (!CodecInfoMap.containsKey(supportedTypes[j])) { 160 Map<String, CodecInfo> map = isEncoder ? encoderInfoMap : decode rInfoMap;
154 CodecInfoMap.put(supportedTypes[j], new CodecInfo( 161 if (!map.containsKey(supportedTypes[j])) {
155 supportedTypes[j], codecString)); 162 map.put(supportedTypes[j], new CodecInfo(
163 supportedTypes[j], codecString, isEncoder));
156 } 164 }
157 } 165 }
158 } 166 }
159 return CodecInfoMap.values().toArray( 167 ArrayList<CodecInfo> codecInfos = new ArrayList<CodecInfo>(
160 new CodecInfo[CodecInfoMap.size()]); 168 decoderInfoMap.size() + encoderInfoMap.size());
169 codecInfos.addAll(encoderInfoMap.values());
170 codecInfos.addAll(decoderInfoMap.values());
171 return codecInfos.toArray(new CodecInfo[codecInfos.size()]);
161 } 172 }
162 173
163 private static String getSecureDecoderNameForMime(String mime) { 174 private static String getSecureDecoderNameForMime(String mime) {
164 int count = MediaCodecList.getCodecCount(); 175 int count = MediaCodecList.getCodecCount();
165 for (int i = 0; i < count; ++i) { 176 for (int i = 0; i < count; ++i) {
166 MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i); 177 MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
167 if (info.isEncoder()) { 178 if (info.isEncoder()) {
168 continue; 179 continue;
169 } 180 }
170 181
171 String[] supportedTypes = info.getSupportedTypes(); 182 String[] supportedTypes = info.getSupportedTypes();
172 for (int j = 0; j < supportedTypes.length; ++j) { 183 for (int j = 0; j < supportedTypes.length; ++j) {
173 if (supportedTypes[j].equalsIgnoreCase(mime)) { 184 if (supportedTypes[j].equalsIgnoreCase(mime)) {
174 return info.getName() + ".secure"; 185 return info.getName() + ".secure";
175 } 186 }
176 } 187 }
177 } 188 }
178 189
179 return null; 190 return null;
180 } 191 }
181 192
182 private MediaCodecBridge(MediaCodec mediaCodec) { 193 private MediaCodecBridge(MediaCodec mediaCodec) {
183 assert(mediaCodec != null); 194 assert(mediaCodec != null);
184 mMediaCodec = mediaCodec; 195 mMediaCodec = mediaCodec;
185 mLastPresentationTimeUs = 0; 196 mLastPresentationTimeUs = 0;
186 mFlushed = true; 197 mFlushed = true;
187 } 198 }
188 199
189 @CalledByNative 200 @CalledByNative
190 private static MediaCodecBridge create(String mime, boolean isSecure) { 201 private static MediaCodecBridge create(String mime, boolean isSecure, boolea n isEncoder) {
191 // Creation of ".secure" codecs sometimes crash instead of throwing exce ptions 202 // Creation of ".secure" codecs sometimes crash instead of throwing exce ptions
192 // on pre-JBMR2 devices. 203 // on pre-JBMR2 devices.
193 if (isSecure && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_M R2) { 204 if (isSecure && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_M R2) {
194 return null; 205 return null;
195 } 206 }
196 MediaCodec mediaCodec = null; 207 MediaCodec mediaCodec = null;
197 try { 208 try {
198 // |isSecure| only applies to video decoders. 209 // |isSecure| only applies to video decoders.
199 if (mime.startsWith("video") && isSecure) { 210 if (mime.startsWith("video") && isSecure && !isEncoder) {
200 mediaCodec = MediaCodec.createByCodecName(getSecureDecoderNameFo rMime(mime)); 211 mediaCodec = MediaCodec.createByCodecName(getSecureDecoderNameFo rMime(mime));
201 } else { 212 } else {
202 mediaCodec = MediaCodec.createDecoderByType(mime); 213 if (isEncoder) {
214 mediaCodec = MediaCodec.createEncoderByType(mime);
215 } else {
216 mediaCodec = MediaCodec.createDecoderByType(mime);
217 }
203 } 218 }
204 } catch (Exception e) { 219 } catch (Exception e) {
205 Log.e(TAG, "Failed to create MediaCodec: " + mime + ", isSecure: " 220 Log.e(TAG, "Failed to create MediaCodec: " + mime + ", isSecure: "
206 + isSecure + ", " + e.toString()); 221 + isSecure + ", isEncoder: " + isEncoder, e);
207 } 222 }
208 223
209 if (mediaCodec == null) { 224 if (mediaCodec == null) {
210 return null; 225 return null;
211 } 226 }
212 227
213 return new MediaCodecBridge(mediaCodec); 228 return new MediaCodecBridge(mediaCodec);
214 } 229 }
215 230
216 @CalledByNative 231 @CalledByNative
217 private void release() { 232 private void release() {
233 String name = mMediaCodec.getName();
234 mMediaCodec.stop();
218 mMediaCodec.release(); 235 mMediaCodec.release();
236 mMediaCodec = null;
219 if (mAudioTrack != null) { 237 if (mAudioTrack != null) {
220 mAudioTrack.release(); 238 mAudioTrack.release();
221 } 239 }
222 } 240 }
223 241
224 @CalledByNative 242 @CalledByNative
225 private boolean start() { 243 private boolean start() {
226 try { 244 try {
227 mMediaCodec.start(); 245 mMediaCodec.start();
228 mInputBuffers = mMediaCodec.getInputBuffers(); 246 mInputBuffers = mMediaCodec.getInputBuffers();
229 } catch (IllegalStateException e) { 247 } catch (IllegalStateException e) {
230 Log.e(TAG, "Cannot start the media codec " + e.toString()); 248 Log.e(TAG, "Cannot start the media codec", e);
231 return false; 249 return false;
232 } 250 }
233 return true; 251 return true;
234 } 252 }
235 253
236 @CalledByNative 254 @CalledByNative
237 private DequeueInputResult dequeueInputBuffer(long timeoutUs) { 255 private DequeueInputResult dequeueInputBuffer(long timeoutUs) {
238 int status = MEDIA_CODEC_ERROR; 256 int status = MEDIA_CODEC_ERROR;
239 int index = -1; 257 int index = -1;
240 try { 258 try {
241 int index_or_status = mMediaCodec.dequeueInputBuffer(timeoutUs); 259 int index_or_status = mMediaCodec.dequeueInputBuffer(timeoutUs);
242 if (index_or_status >= 0) { // index! 260 if (index_or_status >= 0) { // index!
243 status = MEDIA_CODEC_OK; 261 status = MEDIA_CODEC_OK;
244 index = index_or_status; 262 index = index_or_status;
245 } else if (index_or_status == MediaCodec.INFO_TRY_AGAIN_LATER) { 263 } else if (index_or_status == MediaCodec.INFO_TRY_AGAIN_LATER) {
246 Log.e(TAG, "dequeueInputBuffer: MediaCodec.INFO_TRY_AGAIN_LATER" ); 264 Log.e(TAG, "dequeueInputBuffer: MediaCodec.INFO_TRY_AGAIN_LATER" );
247 status = MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER; 265 status = MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER;
248 } else { 266 } else {
267 Log.e(TAG, "Unexpected index_or_status: " + index_or_status);
249 assert(false); 268 assert(false);
250 } 269 }
251 } catch(Exception e) { 270 } catch(Exception e) {
252 Log.e(TAG, "Failed to dequeue input buffer: " + e.toString()); 271 Log.e(TAG, "Failed to dequeue input buffer", e);
253 } 272 }
254 return new DequeueInputResult(status, index); 273 return new DequeueInputResult(status, index);
255 } 274 }
256 275
257 @CalledByNative 276 @CalledByNative
258 private int flush() { 277 private int flush() {
259 try { 278 try {
260 mFlushed = true; 279 mFlushed = true;
261 if (mAudioTrack != null) { 280 if (mAudioTrack != null) {
262 mAudioTrack.flush(); 281 mAudioTrack.flush();
263 } 282 }
264 mMediaCodec.flush(); 283 mMediaCodec.flush();
265 } catch(IllegalStateException e) { 284 } catch(IllegalStateException e) {
266 Log.e(TAG, "Failed to flush MediaCodec " + e.toString()); 285 Log.e(TAG, "Failed to flush MediaCodec", e);
267 return MEDIA_CODEC_ERROR; 286 return MEDIA_CODEC_ERROR;
268 } 287 }
269 return MEDIA_CODEC_OK; 288 return MEDIA_CODEC_OK;
270 } 289 }
271 290
272 @CalledByNative 291 @CalledByNative
273 private void stop() { 292 private void stop() {
274 mMediaCodec.stop(); 293 mMediaCodec.stop();
275 if (mAudioTrack != null) { 294 if (mAudioTrack != null) {
276 mAudioTrack.pause(); 295 mAudioTrack.pause();
(...skipping 14 matching lines...) Expand all
291 private ByteBuffer getInputBuffer(int index) { 310 private ByteBuffer getInputBuffer(int index) {
292 return mInputBuffers[index]; 311 return mInputBuffers[index];
293 } 312 }
294 313
295 @CalledByNative 314 @CalledByNative
296 private ByteBuffer getOutputBuffer(int index) { 315 private ByteBuffer getOutputBuffer(int index) {
297 return mOutputBuffers[index]; 316 return mOutputBuffers[index];
298 } 317 }
299 318
300 @CalledByNative 319 @CalledByNative
320 private int getInputBuffersCount() {
321 return mInputBuffers.length;
322 }
323
324 @CalledByNative
325 private int getOutputBuffersCount() {
326 return mOutputBuffers != null ? mOutputBuffers.length : -1;
327 }
328
329 @CalledByNative
330 private int getOutputBuffersCapacity() {
331 return mOutputBuffers != null ? mOutputBuffers[0].capacity() : -1;
332 }
333
334 @CalledByNative
335 private boolean getOutputBuffers() {
336 try {
337 mOutputBuffers = mMediaCodec.getOutputBuffers();
338 } catch (IllegalStateException e) {
339 Log.e(TAG, "Cannot get output buffers", e);
340 return false;
341 }
342 return true;
343 }
344
345 @CalledByNative
301 private int queueInputBuffer( 346 private int queueInputBuffer(
302 int index, int offset, int size, long presentationTimeUs, int flags) { 347 int index, int offset, int size, long presentationTimeUs, int flags) {
303 resetLastPresentationTimeIfNeeded(presentationTimeUs); 348 resetLastPresentationTimeIfNeeded(presentationTimeUs);
304 try { 349 try {
305 mMediaCodec.queueInputBuffer(index, offset, size, presentationTimeUs , flags); 350 mMediaCodec.queueInputBuffer(index, offset, size, presentationTimeUs , flags);
306 } catch(Exception e) { 351 } catch(Exception e) {
307 Log.e(TAG, "Failed to queue input buffer: " + e.toString()); 352 Log.e(TAG, "Failed to queue input buffer", e);
308 return MEDIA_CODEC_ERROR; 353 return MEDIA_CODEC_ERROR;
309 } 354 }
310 return MEDIA_CODEC_OK; 355 return MEDIA_CODEC_OK;
311 } 356 }
312 357
313 @CalledByNative 358 @CalledByNative
359 private void setVideoBitrate(int bps) {
360 Bundle b = new Bundle();
361 b.putInt(MediaCodec.PARAMETER_KEY_VIDEO_BITRATE, bps);
362 mMediaCodec.setParameters(b);
363 }
364
365 @CalledByNative
366 private void requestKeyFrameSoon() {
367 Bundle b = new Bundle();
368 b.putInt(MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME, 0);
369 mMediaCodec.setParameters(b);
370 }
371
372 @CalledByNative
314 private int queueSecureInputBuffer( 373 private int queueSecureInputBuffer(
315 int index, int offset, byte[] iv, byte[] keyId, int[] numBytesOfClea rData, 374 int index, int offset, byte[] iv, byte[] keyId, int[] numBytesOfClea rData,
316 int[] numBytesOfEncryptedData, int numSubSamples, long presentationT imeUs) { 375 int[] numBytesOfEncryptedData, int numSubSamples, long presentationT imeUs) {
317 resetLastPresentationTimeIfNeeded(presentationTimeUs); 376 resetLastPresentationTimeIfNeeded(presentationTimeUs);
318 try { 377 try {
319 MediaCodec.CryptoInfo cryptoInfo = new MediaCodec.CryptoInfo(); 378 MediaCodec.CryptoInfo cryptoInfo = new MediaCodec.CryptoInfo();
320 cryptoInfo.set(numSubSamples, numBytesOfClearData, numBytesOfEncrypt edData, 379 cryptoInfo.set(numSubSamples, numBytesOfClearData, numBytesOfEncrypt edData,
321 keyId, iv, MediaCodec.CRYPTO_MODE_AES_CTR); 380 keyId, iv, MediaCodec.CRYPTO_MODE_AES_CTR);
322 mMediaCodec.queueSecureInputBuffer(index, offset, cryptoInfo, presen tationTimeUs, 0); 381 mMediaCodec.queueSecureInputBuffer(index, offset, cryptoInfo, presen tationTimeUs, 0);
323 } catch (MediaCodec.CryptoException e) { 382 } catch (MediaCodec.CryptoException e) {
324 Log.e(TAG, "Failed to queue secure input buffer: " + e.toString()); 383 Log.e(TAG, "Failed to queue secure input buffer", e);
325 // TODO(xhwang): Replace hard coded value with constant/enum. 384 // TODO(xhwang): Replace hard coded value with constant/enum.
326 if (e.getErrorCode() == 1) { 385 if (e.getErrorCode() == 1) {
327 Log.e(TAG, "No key available."); 386 Log.e(TAG, "No key available.");
328 return MEDIA_CODEC_NO_KEY; 387 return MEDIA_CODEC_NO_KEY;
329 } 388 }
330 return MEDIA_CODEC_ERROR; 389 return MEDIA_CODEC_ERROR;
331 } catch(IllegalStateException e) { 390 } catch(IllegalStateException e) {
332 Log.e(TAG, "Failed to queue secure input buffer: " + e.toString()); 391 Log.e(TAG, "Failed to queue secure input buffer", e);
333 return MEDIA_CODEC_ERROR; 392 return MEDIA_CODEC_ERROR;
334 } 393 }
335 return MEDIA_CODEC_OK; 394 return MEDIA_CODEC_OK;
336 } 395 }
337 396
338 @CalledByNative 397 @CalledByNative
339 private void releaseOutputBuffer(int index, boolean render) { 398 private void releaseOutputBuffer(int index, boolean render) {
340 mMediaCodec.releaseOutputBuffer(index, render); 399 mMediaCodec.releaseOutputBuffer(index, render);
341 } 400 }
342 401
343 @CalledByNative 402 @CalledByNative
344 private boolean getOutputBuffers() {
345 try {
346 mOutputBuffers = mMediaCodec.getOutputBuffers();
347 } catch (IllegalStateException e) {
348 Log.e(TAG, "Cannot get output buffers " + e.toString());
349 return false;
350 }
351 return true;
352 }
353
354 @CalledByNative
355 private DequeueOutputResult dequeueOutputBuffer(long timeoutUs) { 403 private DequeueOutputResult dequeueOutputBuffer(long timeoutUs) {
356 MediaCodec.BufferInfo info = new MediaCodec.BufferInfo(); 404 MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
357 int status = MEDIA_CODEC_ERROR; 405 int status = MEDIA_CODEC_ERROR;
358 int index = -1; 406 int index = -1;
359 try { 407 try {
360 int index_or_status = mMediaCodec.dequeueOutputBuffer(info, timeoutU s); 408 int index_or_status = mMediaCodec.dequeueOutputBuffer(info, timeoutU s);
361 if (info.presentationTimeUs < mLastPresentationTimeUs) { 409 if (info.presentationTimeUs < mLastPresentationTimeUs) {
362 // TODO(qinmin): return a special code through DequeueOutputResu lt 410 // TODO(qinmin): return a special code through DequeueOutputResu lt
363 // to notify the native code the the frame has a wrong presentat ion 411 // to notify the native code the the frame has a wrong presentat ion
364 // timestamp and should be skipped. 412 // timestamp and should be skipped.
365 info.presentationTimeUs = mLastPresentationTimeUs; 413 info.presentationTimeUs = mLastPresentationTimeUs;
366 } 414 }
367 mLastPresentationTimeUs = info.presentationTimeUs; 415 mLastPresentationTimeUs = info.presentationTimeUs;
368 416
369 if (index_or_status >= 0) { // index! 417 if (index_or_status >= 0) { // index!
370 status = MEDIA_CODEC_OK; 418 status = MEDIA_CODEC_OK;
371 index = index_or_status; 419 index = index_or_status;
372 } else if (index_or_status == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED ) { 420 } else if (index_or_status == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED ) {
373 status = MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED; 421 status = MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED;
374 } else if (index_or_status == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { 422 } else if (index_or_status == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
375 status = MEDIA_CODEC_OUTPUT_FORMAT_CHANGED; 423 status = MEDIA_CODEC_OUTPUT_FORMAT_CHANGED;
376 } else if (index_or_status == MediaCodec.INFO_TRY_AGAIN_LATER) { 424 } else if (index_or_status == MediaCodec.INFO_TRY_AGAIN_LATER) {
377 status = MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER; 425 status = MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER;
378 } else { 426 } else {
427 Log.e(TAG, "Unexpected index_or_status: " + index_or_status);
379 assert(false); 428 assert(false);
380 } 429 }
381 } catch (IllegalStateException e) { 430 } catch (IllegalStateException e) {
382 Log.e(TAG, "Failed to dequeue output buffer: " + e.toString()); 431 Log.e(TAG, "Failed to dequeue output buffer", e);
383 } 432 }
384 433
385 return new DequeueOutputResult( 434 return new DequeueOutputResult(
386 status, index, info.flags, info.offset, info.presentationTimeUs, info.size); 435 status, index, info.flags, info.offset, info.presentationTimeUs, info.size);
387 } 436 }
388 437
389 @CalledByNative 438 @CalledByNative
390 private boolean configureVideo(MediaFormat format, Surface surface, MediaCry pto crypto, 439 private boolean configureVideo(MediaFormat format, Surface surface, MediaCry pto crypto,
391 int flags) { 440 int flags) {
392 try { 441 try {
393 mMediaCodec.configure(format, surface, crypto, flags); 442 mMediaCodec.configure(format, surface, crypto, flags);
394 return true; 443 return true;
395 } catch (IllegalStateException e) { 444 } catch (IllegalStateException e) {
396 Log.e(TAG, "Cannot configure the video codec " + e.toString()); 445 Log.e(TAG, "Cannot configure the video codec", e);
397 } 446 }
398 return false; 447 return false;
399 } 448 }
400 449
401 @CalledByNative 450 @CalledByNative
402 private static MediaFormat createAudioFormat(String mime, int SampleRate, in t ChannelCount) { 451 private static MediaFormat createAudioFormat(String mime, int SampleRate, in t ChannelCount) {
403 return MediaFormat.createAudioFormat(mime, SampleRate, ChannelCount); 452 return MediaFormat.createAudioFormat(mime, SampleRate, ChannelCount);
404 } 453 }
405 454
406 @CalledByNative 455 @CalledByNative
407 private static MediaFormat createVideoFormat(String mime, int width, int hei ght) { 456 private static MediaFormat createVideoDecoderFormat(String mime, int width, int height) {
408 return MediaFormat.createVideoFormat(mime, width, height); 457 return MediaFormat.createVideoFormat(mime, width, height);
409 } 458 }
410 459
411 @CalledByNative 460 @CalledByNative
461 private static MediaFormat createVideoEncoderFormat(String mime, int width, int height,
462 int bitRate, int frameRate, int iFrameInterval, int colorFormat) {
463 MediaFormat format = MediaFormat.createVideoFormat(mime, width, height);
464 format.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
465 format.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate);
466 format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, iFrameInterval);
467 format.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat);
468 return format;
469 }
470
471 @CalledByNative
412 private static void setCodecSpecificData(MediaFormat format, int index, byte [] bytes) { 472 private static void setCodecSpecificData(MediaFormat format, int index, byte [] bytes) {
413 String name = null; 473 String name = null;
414 if (index == 0) { 474 if (index == 0) {
415 name = "csd-0"; 475 name = "csd-0";
416 } else if (index == 1) { 476 } else if (index == 1) {
417 name = "csd-1"; 477 name = "csd-1";
418 } 478 }
419 if (name != null) { 479 if (name != null) {
420 format.setByteBuffer(name, ByteBuffer.wrap(bytes)); 480 format.setByteBuffer(name, ByteBuffer.wrap(bytes));
421 } 481 }
(...skipping 16 matching lines...) Expand all
438 AudioFormat.CHANNEL_OUT_STEREO; 498 AudioFormat.CHANNEL_OUT_STEREO;
439 // Using 16bit PCM for output. Keep this value in sync with 499 // Using 16bit PCM for output. Keep this value in sync with
440 // kBytesPerAudioOutputSample in media_codec_bridge.cc. 500 // kBytesPerAudioOutputSample in media_codec_bridge.cc.
441 int minBufferSize = AudioTrack.getMinBufferSize(sampleRate, chan nelConfig, 501 int minBufferSize = AudioTrack.getMinBufferSize(sampleRate, chan nelConfig,
442 AudioFormat.ENCODING_PCM_16BIT); 502 AudioFormat.ENCODING_PCM_16BIT);
443 mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRa te, channelConfig, 503 mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRa te, channelConfig,
444 AudioFormat.ENCODING_PCM_16BIT, minBufferSize, AudioTrac k.MODE_STREAM); 504 AudioFormat.ENCODING_PCM_16BIT, minBufferSize, AudioTrac k.MODE_STREAM);
445 } 505 }
446 return true; 506 return true;
447 } catch (IllegalStateException e) { 507 } catch (IllegalStateException e) {
448 Log.e(TAG, "Cannot configure the audio codec " + e.toString()); 508 Log.e(TAG, "Cannot configure the audio codec", e);
449 } 509 }
450 return false; 510 return false;
451 } 511 }
452 512
453 @CalledByNative 513 @CalledByNative
454 private void playOutputBuffer(byte[] buf) { 514 private void playOutputBuffer(byte[] buf) {
455 if (mAudioTrack != null) { 515 if (mAudioTrack != null) {
456 if (AudioTrack.PLAYSTATE_PLAYING != mAudioTrack.getPlayState()) { 516 if (AudioTrack.PLAYSTATE_PLAYING != mAudioTrack.getPlayState()) {
457 mAudioTrack.play(); 517 mAudioTrack.play();
458 } 518 }
(...skipping 13 matching lines...) Expand all
472 } 532 }
473 533
474 private void resetLastPresentationTimeIfNeeded(long presentationTimeUs) { 534 private void resetLastPresentationTimeIfNeeded(long presentationTimeUs) {
475 if (mFlushed) { 535 if (mFlushed) {
476 mLastPresentationTimeUs = 536 mLastPresentationTimeUs =
477 Math.max(presentationTimeUs - MAX_PRESENTATION_TIMESTAMP_SHI FT_US, 0); 537 Math.max(presentationTimeUs - MAX_PRESENTATION_TIMESTAMP_SHI FT_US, 0);
478 mFlushed = false; 538 mFlushed = false;
479 } 539 }
480 } 540 }
481 } 541 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698