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

Side by Side Diff: talk/app/webrtc/java/src/org/webrtc/MediaCodecVideoEncoder.java

Issue 1343163003: Partial revert of r9936. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc@master
Patch Set: Created 5 years, 3 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
« no previous file with comments | « talk/app/webrtc/java/src/org/webrtc/MediaCodecVideoDecoder.java ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * libjingle 2 * libjingle
3 * Copyright 2013 Google Inc. 3 * Copyright 2013 Google Inc.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright notice, 8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer. 9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice, 10 * 2. Redistributions in binary form must reproduce the above copyright notice,
(...skipping 17 matching lines...) Expand all
28 28
29 package org.webrtc; 29 package org.webrtc;
30 30
31 import android.media.MediaCodec; 31 import android.media.MediaCodec;
32 import android.media.MediaCodecInfo.CodecCapabilities; 32 import android.media.MediaCodecInfo.CodecCapabilities;
33 import android.media.MediaCodecInfo; 33 import android.media.MediaCodecInfo;
34 import android.media.MediaCodecList; 34 import android.media.MediaCodecList;
35 import android.media.MediaFormat; 35 import android.media.MediaFormat;
36 import android.os.Build; 36 import android.os.Build;
37 import android.os.Bundle; 37 import android.os.Bundle;
38 38 import android.util.Log;
39 import org.webrtc.Logging;
40 39
41 import java.nio.ByteBuffer; 40 import java.nio.ByteBuffer;
42 import java.util.Arrays; 41 import java.util.Arrays;
43 import java.util.List; 42 import java.util.List;
44 43
45 // Java-side of peerconnection_jni.cc:MediaCodecVideoEncoder. 44 // Java-side of peerconnection_jni.cc:MediaCodecVideoEncoder.
46 // This class is an implementation detail of the Java PeerConnection API. 45 // This class is an implementation detail of the Java PeerConnection API.
47 // MediaCodec is thread-hostile so this class must be operated on a single 46 // MediaCodec is thread-hostile so this class must be operated on a single
48 // thread. 47 // thread.
49 public class MediaCodecVideoEncoder { 48 public class MediaCodecVideoEncoder {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 // MediaCodec.setParameters is missing for JB and below, so bitrate 118 // MediaCodec.setParameters is missing for JB and below, so bitrate
120 // can not be adjusted dynamically. 119 // can not be adjusted dynamically.
121 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { 120 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
122 return null; 121 return null;
123 } 122 }
124 123
125 // Check if device is in H.264 exception list. 124 // Check if device is in H.264 exception list.
126 if (mime.equals(H264_MIME_TYPE)) { 125 if (mime.equals(H264_MIME_TYPE)) {
127 List<String> exceptionModels = Arrays.asList(H264_HW_EXCEPTION_MODELS); 126 List<String> exceptionModels = Arrays.asList(H264_HW_EXCEPTION_MODELS);
128 if (exceptionModels.contains(Build.MODEL)) { 127 if (exceptionModels.contains(Build.MODEL)) {
129 Logging.w(TAG, "Model: " + Build.MODEL + 128 Log.w(TAG, "Model: " + Build.MODEL +
130 " has black listed H.264 encoder."); 129 " has black listed H.264 encoder.");
131 return null; 130 return null;
132 } 131 }
133 } 132 }
134 133
135 for (int i = 0; i < MediaCodecList.getCodecCount(); ++i) { 134 for (int i = 0; i < MediaCodecList.getCodecCount(); ++i) {
136 MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i); 135 MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
137 if (!info.isEncoder()) { 136 if (!info.isEncoder()) {
138 continue; 137 continue;
139 } 138 }
140 String name = null; 139 String name = null;
141 for (String mimeType : info.getSupportedTypes()) { 140 for (String mimeType : info.getSupportedTypes()) {
142 if (mimeType.equals(mime)) { 141 if (mimeType.equals(mime)) {
143 name = info.getName(); 142 name = info.getName();
144 break; 143 break;
145 } 144 }
146 } 145 }
147 if (name == null) { 146 if (name == null) {
148 continue; // No HW support in this codec; try the next one. 147 continue; // No HW support in this codec; try the next one.
149 } 148 }
150 Logging.v(TAG, "Found candidate encoder " + name); 149 Log.v(TAG, "Found candidate encoder " + name);
151 150
152 // Check if this is supported HW encoder. 151 // Check if this is supported HW encoder.
153 boolean supportedCodec = false; 152 boolean supportedCodec = false;
154 for (String hwCodecPrefix : supportedHwCodecPrefixes) { 153 for (String hwCodecPrefix : supportedHwCodecPrefixes) {
155 if (name.startsWith(hwCodecPrefix)) { 154 if (name.startsWith(hwCodecPrefix)) {
156 supportedCodec = true; 155 supportedCodec = true;
157 break; 156 break;
158 } 157 }
159 } 158 }
160 if (!supportedCodec) { 159 if (!supportedCodec) {
161 continue; 160 continue;
162 } 161 }
163 162
164 CodecCapabilities capabilities = info.getCapabilitiesForType(mime); 163 CodecCapabilities capabilities = info.getCapabilitiesForType(mime);
165 for (int colorFormat : capabilities.colorFormats) { 164 for (int colorFormat : capabilities.colorFormats) {
166 Logging.v(TAG, " Color: 0x" + Integer.toHexString(colorFormat)); 165 Log.v(TAG, " Color: 0x" + Integer.toHexString(colorFormat));
167 } 166 }
168 167
169 // Check if codec supports either yuv420 or nv12. 168 // Check if codec supports either yuv420 or nv12.
170 for (int supportedColorFormat : supportedColorList) { 169 for (int supportedColorFormat : supportedColorList) {
171 for (int codecColorFormat : capabilities.colorFormats) { 170 for (int codecColorFormat : capabilities.colorFormats) {
172 if (codecColorFormat == supportedColorFormat) { 171 if (codecColorFormat == supportedColorFormat) {
173 // Found supported HW encoder. 172 // Found supported HW encoder.
174 Logging.d(TAG, "Found target encoder for mime " + mime + " : " + nam e + 173 Log.d(TAG, "Found target encoder for mime " + mime + " : " + name +
175 ". Color: 0x" + Integer.toHexString(codecColorFormat)); 174 ". Color: 0x" + Integer.toHexString(codecColorFormat));
176 return new EncoderProperties(name, codecColorFormat); 175 return new EncoderProperties(name, codecColorFormat);
177 } 176 }
178 } 177 }
179 } 178 }
180 } 179 }
181 return null; // No HW VP8 encoder. 180 return null; // No HW VP8 encoder.
182 } 181 }
183 182
184 public static boolean isVp8HwSupported() { 183 public static boolean isVp8HwSupported() {
(...skipping 18 matching lines...) Expand all
203 // both cases catch an exception. 202 // both cases catch an exception.
204 return MediaCodec.createByCodecName(codecName); 203 return MediaCodec.createByCodecName(codecName);
205 } catch (Exception e) { 204 } catch (Exception e) {
206 return null; 205 return null;
207 } 206 }
208 } 207 }
209 208
210 // Return the array of input buffers, or null on failure. 209 // Return the array of input buffers, or null on failure.
211 private ByteBuffer[] initEncode( 210 private ByteBuffer[] initEncode(
212 VideoCodecType type, int width, int height, int kbps, int fps) { 211 VideoCodecType type, int width, int height, int kbps, int fps) {
213 Logging.d(TAG, "Java initEncode: " + type + " : " + width + " x " + height + 212 Log.d(TAG, "Java initEncode: " + type + " : " + width + " x " + height +
214 ". @ " + kbps + " kbps. Fps: " + fps + 213 ". @ " + kbps + " kbps. Fps: " + fps +
215 ". Color: 0x" + Integer.toHexString(colorFormat)); 214 ". Color: 0x" + Integer.toHexString(colorFormat));
216 if (mediaCodecThread != null) { 215 if (mediaCodecThread != null) {
217 throw new RuntimeException("Forgot to release()?"); 216 throw new RuntimeException("Forgot to release()?");
218 } 217 }
219 this.type = type; 218 this.type = type;
220 EncoderProperties properties = null; 219 EncoderProperties properties = null;
221 String mime = null; 220 String mime = null;
222 int keyFrameIntervalSec = 0; 221 int keyFrameIntervalSec = 0;
223 if (type == VideoCodecType.VIDEO_CODEC_VP8) { 222 if (type == VideoCodecType.VIDEO_CODEC_VP8) {
224 mime = VP8_MIME_TYPE; 223 mime = VP8_MIME_TYPE;
225 properties = findHwEncoder(VP8_MIME_TYPE, supportedVp8HwCodecPrefixes); 224 properties = findHwEncoder(VP8_MIME_TYPE, supportedVp8HwCodecPrefixes);
226 keyFrameIntervalSec = 100; 225 keyFrameIntervalSec = 100;
227 } else if (type == VideoCodecType.VIDEO_CODEC_H264) { 226 } else if (type == VideoCodecType.VIDEO_CODEC_H264) {
228 mime = H264_MIME_TYPE; 227 mime = H264_MIME_TYPE;
229 properties = findHwEncoder(H264_MIME_TYPE, supportedH264HwCodecPrefixes); 228 properties = findHwEncoder(H264_MIME_TYPE, supportedH264HwCodecPrefixes);
230 keyFrameIntervalSec = 20; 229 keyFrameIntervalSec = 20;
231 } 230 }
232 if (properties == null) { 231 if (properties == null) {
233 throw new RuntimeException("Can not find HW encoder for " + type); 232 throw new RuntimeException("Can not find HW encoder for " + type);
234 } 233 }
235 mediaCodecThread = Thread.currentThread(); 234 mediaCodecThread = Thread.currentThread();
236 try { 235 try {
237 MediaFormat format = MediaFormat.createVideoFormat(mime, width, height); 236 MediaFormat format = MediaFormat.createVideoFormat(mime, width, height);
238 format.setInteger(MediaFormat.KEY_BIT_RATE, 1000 * kbps); 237 format.setInteger(MediaFormat.KEY_BIT_RATE, 1000 * kbps);
239 format.setInteger("bitrate-mode", VIDEO_ControlRateConstant); 238 format.setInteger("bitrate-mode", VIDEO_ControlRateConstant);
240 format.setInteger(MediaFormat.KEY_COLOR_FORMAT, properties.colorFormat); 239 format.setInteger(MediaFormat.KEY_COLOR_FORMAT, properties.colorFormat);
241 format.setInteger(MediaFormat.KEY_FRAME_RATE, fps); 240 format.setInteger(MediaFormat.KEY_FRAME_RATE, fps);
242 format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, keyFrameIntervalSec); 241 format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, keyFrameIntervalSec);
243 Logging.d(TAG, " Format: " + format); 242 Log.d(TAG, " Format: " + format);
244 mediaCodec = createByCodecName(properties.codecName); 243 mediaCodec = createByCodecName(properties.codecName);
245 if (mediaCodec == null) { 244 if (mediaCodec == null) {
246 return null; 245 return null;
247 } 246 }
248 mediaCodec.configure( 247 mediaCodec.configure(
249 format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); 248 format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
250 mediaCodec.start(); 249 mediaCodec.start();
251 colorFormat = properties.colorFormat; 250 colorFormat = properties.colorFormat;
252 outputBuffers = mediaCodec.getOutputBuffers(); 251 outputBuffers = mediaCodec.getOutputBuffers();
253 ByteBuffer[] inputBuffers = mediaCodec.getInputBuffers(); 252 ByteBuffer[] inputBuffers = mediaCodec.getInputBuffers();
254 Logging.d(TAG, "Input buffers: " + inputBuffers.length + 253 Log.d(TAG, "Input buffers: " + inputBuffers.length +
255 ". Output buffers: " + outputBuffers.length); 254 ". Output buffers: " + outputBuffers.length);
256 return inputBuffers; 255 return inputBuffers;
257 } catch (IllegalStateException e) { 256 } catch (IllegalStateException e) {
258 Logging.e(TAG, "initEncode failed", e); 257 Log.e(TAG, "initEncode failed", e);
259 return null; 258 return null;
260 } 259 }
261 } 260 }
262 261
263 private boolean encode( 262 private boolean encode(
264 boolean isKeyframe, int inputBuffer, int size, 263 boolean isKeyframe, int inputBuffer, int size,
265 long presentationTimestampUs) { 264 long presentationTimestampUs) {
266 checkOnMediaCodecThread(); 265 checkOnMediaCodecThread();
267 try { 266 try {
268 if (isKeyframe) { 267 if (isKeyframe) {
269 // Ideally MediaCodec would honor BUFFER_FLAG_SYNC_FRAME so we could 268 // Ideally MediaCodec would honor BUFFER_FLAG_SYNC_FRAME so we could
270 // indicate this in queueInputBuffer() below and guarantee _this_ frame 269 // indicate this in queueInputBuffer() below and guarantee _this_ frame
271 // be encoded as a key frame, but sadly that flag is ignored. Instead, 270 // be encoded as a key frame, but sadly that flag is ignored. Instead,
272 // we request a key frame "soon". 271 // we request a key frame "soon".
273 Logging.d(TAG, "Sync frame request"); 272 Log.d(TAG, "Sync frame request");
274 Bundle b = new Bundle(); 273 Bundle b = new Bundle();
275 b.putInt(MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME, 0); 274 b.putInt(MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME, 0);
276 mediaCodec.setParameters(b); 275 mediaCodec.setParameters(b);
277 } 276 }
278 mediaCodec.queueInputBuffer( 277 mediaCodec.queueInputBuffer(
279 inputBuffer, 0, size, presentationTimestampUs, 0); 278 inputBuffer, 0, size, presentationTimestampUs, 0);
280 return true; 279 return true;
281 } 280 }
282 catch (IllegalStateException e) { 281 catch (IllegalStateException e) {
283 Logging.e(TAG, "encode failed", e); 282 Log.e(TAG, "encode failed", e);
284 return false; 283 return false;
285 } 284 }
286 } 285 }
287 286
288 private void release() { 287 private void release() {
289 Logging.d(TAG, "Java releaseEncoder"); 288 Log.d(TAG, "Java releaseEncoder");
290 checkOnMediaCodecThread(); 289 checkOnMediaCodecThread();
291 try { 290 try {
292 mediaCodec.stop(); 291 mediaCodec.stop();
293 mediaCodec.release(); 292 mediaCodec.release();
294 } catch (IllegalStateException e) { 293 } catch (IllegalStateException e) {
295 Logging.e(TAG, "release failed", e); 294 Log.e(TAG, "release failed", e);
296 } 295 }
297 mediaCodec = null; 296 mediaCodec = null;
298 mediaCodecThread = null; 297 mediaCodecThread = null;
299 } 298 }
300 299
301 private boolean setRates(int kbps, int frameRateIgnored) { 300 private boolean setRates(int kbps, int frameRateIgnored) {
302 // frameRate argument is ignored - HW encoder is supposed to use 301 // frameRate argument is ignored - HW encoder is supposed to use
303 // video frame timestamps for bit allocation. 302 // video frame timestamps for bit allocation.
304 checkOnMediaCodecThread(); 303 checkOnMediaCodecThread();
305 Logging.v(TAG, "setRates: " + kbps + " kbps. Fps: " + frameRateIgnored); 304 Log.v(TAG, "setRates: " + kbps + " kbps. Fps: " + frameRateIgnored);
306 try { 305 try {
307 Bundle params = new Bundle(); 306 Bundle params = new Bundle();
308 params.putInt(MediaCodec.PARAMETER_KEY_VIDEO_BITRATE, 1000 * kbps); 307 params.putInt(MediaCodec.PARAMETER_KEY_VIDEO_BITRATE, 1000 * kbps);
309 mediaCodec.setParameters(params); 308 mediaCodec.setParameters(params);
310 return true; 309 return true;
311 } catch (IllegalStateException e) { 310 } catch (IllegalStateException e) {
312 Logging.e(TAG, "setRates failed", e); 311 Log.e(TAG, "setRates failed", e);
313 return false; 312 return false;
314 } 313 }
315 } 314 }
316 315
317 // Dequeue an input buffer and return its index, -1 if no input buffer is 316 // Dequeue an input buffer and return its index, -1 if no input buffer is
318 // available, or -2 if the codec is no longer operative. 317 // available, or -2 if the codec is no longer operative.
319 private int dequeueInputBuffer() { 318 private int dequeueInputBuffer() {
320 checkOnMediaCodecThread(); 319 checkOnMediaCodecThread();
321 try { 320 try {
322 return mediaCodec.dequeueInputBuffer(DEQUEUE_TIMEOUT); 321 return mediaCodec.dequeueInputBuffer(DEQUEUE_TIMEOUT);
323 } catch (IllegalStateException e) { 322 } catch (IllegalStateException e) {
324 Logging.e(TAG, "dequeueIntputBuffer failed", e); 323 Log.e(TAG, "dequeueIntputBuffer failed", e);
325 return -2; 324 return -2;
326 } 325 }
327 } 326 }
328 327
329 // Helper struct for dequeueOutputBuffer() below. 328 // Helper struct for dequeueOutputBuffer() below.
330 private static class OutputBufferInfo { 329 private static class OutputBufferInfo {
331 public OutputBufferInfo( 330 public OutputBufferInfo(
332 int index, ByteBuffer buffer, 331 int index, ByteBuffer buffer,
333 boolean isKeyFrame, long presentationTimestampUs) { 332 boolean isKeyFrame, long presentationTimestampUs) {
334 this.index = index; 333 this.index = index;
(...skipping 13 matching lines...) Expand all
348 private OutputBufferInfo dequeueOutputBuffer() { 347 private OutputBufferInfo dequeueOutputBuffer() {
349 checkOnMediaCodecThread(); 348 checkOnMediaCodecThread();
350 try { 349 try {
351 MediaCodec.BufferInfo info = new MediaCodec.BufferInfo(); 350 MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
352 int result = mediaCodec.dequeueOutputBuffer(info, DEQUEUE_TIMEOUT); 351 int result = mediaCodec.dequeueOutputBuffer(info, DEQUEUE_TIMEOUT);
353 // Check if this is config frame and save configuration data. 352 // Check if this is config frame and save configuration data.
354 if (result >= 0) { 353 if (result >= 0) {
355 boolean isConfigFrame = 354 boolean isConfigFrame =
356 (info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0; 355 (info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0;
357 if (isConfigFrame) { 356 if (isConfigFrame) {
358 Logging.d(TAG, "Config frame generated. Offset: " + info.offset + 357 Log.d(TAG, "Config frame generated. Offset: " + info.offset +
359 ". Size: " + info.size); 358 ". Size: " + info.size);
360 configData = ByteBuffer.allocateDirect(info.size); 359 configData = ByteBuffer.allocateDirect(info.size);
361 outputBuffers[result].position(info.offset); 360 outputBuffers[result].position(info.offset);
362 outputBuffers[result].limit(info.offset + info.size); 361 outputBuffers[result].limit(info.offset + info.size);
363 configData.put(outputBuffers[result]); 362 configData.put(outputBuffers[result]);
364 // Release buffer back. 363 // Release buffer back.
365 mediaCodec.releaseOutputBuffer(result, false); 364 mediaCodec.releaseOutputBuffer(result, false);
366 // Query next output. 365 // Query next output.
367 result = mediaCodec.dequeueOutputBuffer(info, DEQUEUE_TIMEOUT); 366 result = mediaCodec.dequeueOutputBuffer(info, DEQUEUE_TIMEOUT);
368 } 367 }
369 } 368 }
370 if (result >= 0) { 369 if (result >= 0) {
371 // MediaCodec doesn't care about Buffer position/remaining/etc so we can 370 // MediaCodec doesn't care about Buffer position/remaining/etc so we can
372 // mess with them to get a slice and avoid having to pass extra 371 // mess with them to get a slice and avoid having to pass extra
373 // (BufferInfo-related) parameters back to C++. 372 // (BufferInfo-related) parameters back to C++.
374 ByteBuffer outputBuffer = outputBuffers[result].duplicate(); 373 ByteBuffer outputBuffer = outputBuffers[result].duplicate();
375 outputBuffer.position(info.offset); 374 outputBuffer.position(info.offset);
376 outputBuffer.limit(info.offset + info.size); 375 outputBuffer.limit(info.offset + info.size);
377 // Check key frame flag. 376 // Check key frame flag.
378 boolean isKeyFrame = 377 boolean isKeyFrame =
379 (info.flags & MediaCodec.BUFFER_FLAG_SYNC_FRAME) != 0; 378 (info.flags & MediaCodec.BUFFER_FLAG_SYNC_FRAME) != 0;
380 if (isKeyFrame) { 379 if (isKeyFrame) {
381 Logging.d(TAG, "Sync frame generated"); 380 Log.d(TAG, "Sync frame generated");
382 } 381 }
383 if (isKeyFrame && type == VideoCodecType.VIDEO_CODEC_H264) { 382 if (isKeyFrame && type == VideoCodecType.VIDEO_CODEC_H264) {
384 Logging.d(TAG, "Appending config frame of size " + configData.capacity () + 383 Log.d(TAG, "Appending config frame of size " + configData.capacity() +
385 " to output buffer with offset " + info.offset + ", size " + 384 " to output buffer with offset " + info.offset + ", size " +
386 info.size); 385 info.size);
387 // For H.264 key frame append SPS and PPS NALs at the start 386 // For H.264 key frame append SPS and PPS NALs at the start
388 ByteBuffer keyFrameBuffer = ByteBuffer.allocateDirect( 387 ByteBuffer keyFrameBuffer = ByteBuffer.allocateDirect(
389 configData.capacity() + info.size); 388 configData.capacity() + info.size);
390 configData.rewind(); 389 configData.rewind();
391 keyFrameBuffer.put(configData); 390 keyFrameBuffer.put(configData);
392 keyFrameBuffer.put(outputBuffer); 391 keyFrameBuffer.put(outputBuffer);
393 keyFrameBuffer.position(0); 392 keyFrameBuffer.position(0);
394 return new OutputBufferInfo(result, keyFrameBuffer, 393 return new OutputBufferInfo(result, keyFrameBuffer,
395 isKeyFrame, info.presentationTimeUs); 394 isKeyFrame, info.presentationTimeUs);
396 } else { 395 } else {
397 return new OutputBufferInfo(result, outputBuffer.slice(), 396 return new OutputBufferInfo(result, outputBuffer.slice(),
398 isKeyFrame, info.presentationTimeUs); 397 isKeyFrame, info.presentationTimeUs);
399 } 398 }
400 } else if (result == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) { 399 } else if (result == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
401 outputBuffers = mediaCodec.getOutputBuffers(); 400 outputBuffers = mediaCodec.getOutputBuffers();
402 return dequeueOutputBuffer(); 401 return dequeueOutputBuffer();
403 } else if (result == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { 402 } else if (result == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
404 return dequeueOutputBuffer(); 403 return dequeueOutputBuffer();
405 } else if (result == MediaCodec.INFO_TRY_AGAIN_LATER) { 404 } else if (result == MediaCodec.INFO_TRY_AGAIN_LATER) {
406 return null; 405 return null;
407 } 406 }
408 throw new RuntimeException("dequeueOutputBuffer: " + result); 407 throw new RuntimeException("dequeueOutputBuffer: " + result);
409 } catch (IllegalStateException e) { 408 } catch (IllegalStateException e) {
410 Logging.e(TAG, "dequeueOutputBuffer failed", e); 409 Log.e(TAG, "dequeueOutputBuffer failed", e);
411 return new OutputBufferInfo(-1, null, false, -1); 410 return new OutputBufferInfo(-1, null, false, -1);
412 } 411 }
413 } 412 }
414 413
415 // Release a dequeued output buffer back to the codec for re-use. Return 414 // Release a dequeued output buffer back to the codec for re-use. Return
416 // false if the codec is no longer operable. 415 // false if the codec is no longer operable.
417 private boolean releaseOutputBuffer(int index) { 416 private boolean releaseOutputBuffer(int index) {
418 checkOnMediaCodecThread(); 417 checkOnMediaCodecThread();
419 try { 418 try {
420 mediaCodec.releaseOutputBuffer(index, false); 419 mediaCodec.releaseOutputBuffer(index, false);
421 return true; 420 return true;
422 } catch (IllegalStateException e) { 421 } catch (IllegalStateException e) {
423 Logging.e(TAG, "releaseOutputBuffer failed", e); 422 Log.e(TAG, "releaseOutputBuffer failed", e);
424 return false; 423 return false;
425 } 424 }
426 } 425 }
427 } 426 }
OLDNEW
« no previous file with comments | « talk/app/webrtc/java/src/org/webrtc/MediaCodecVideoDecoder.java ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698