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

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

Issue 1338033003: Log to webrtc logging stream from java code. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@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
OLDNEW
1 /* 1 /*
2 * libjingle 2 * libjingle
3 * Copyright 2014 Google Inc. 3 * Copyright 2014 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 19 matching lines...) Expand all
30 import android.graphics.SurfaceTexture; 30 import android.graphics.SurfaceTexture;
31 import android.media.MediaCodec; 31 import android.media.MediaCodec;
32 import android.media.MediaCodecInfo; 32 import android.media.MediaCodecInfo;
33 import android.media.MediaCodecInfo.CodecCapabilities; 33 import android.media.MediaCodecInfo.CodecCapabilities;
34 import android.media.MediaCodecList; 34 import android.media.MediaCodecList;
35 import android.media.MediaFormat; 35 import android.media.MediaFormat;
36 import android.opengl.EGLContext; 36 import android.opengl.EGLContext;
37 import android.opengl.GLES11Ext; 37 import android.opengl.GLES11Ext;
38 import android.opengl.GLES20; 38 import android.opengl.GLES20;
39 import android.os.Build; 39 import android.os.Build;
40 import android.util.Log;
41 import android.view.Surface; 40 import android.view.Surface;
42 41
42 import org.webrtc.Logging;
43
43 import java.nio.ByteBuffer; 44 import java.nio.ByteBuffer;
44 45
45 // Java-side of peerconnection_jni.cc:MediaCodecVideoDecoder. 46 // Java-side of peerconnection_jni.cc:MediaCodecVideoDecoder.
46 // This class is an implementation detail of the Java PeerConnection API. 47 // 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 48 // MediaCodec is thread-hostile so this class must be operated on a single
48 // thread. 49 // thread.
49 public class MediaCodecVideoDecoder { 50 public class MediaCodecVideoDecoder {
50 // This class is constructed, operated, and destroyed by its C++ incarnation, 51 // This class is constructed, operated, and destroyed by its C++ incarnation,
51 // so the class and its methods have non-public visibility. The API this 52 // so the class and its methods have non-public visibility. The API this
52 // class exposes aims to mimic the webrtc::VideoDecoder API as closely as 53 // class exposes aims to mimic the webrtc::VideoDecoder API as closely as
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 String name = null; 122 String name = null;
122 for (String mimeType : info.getSupportedTypes()) { 123 for (String mimeType : info.getSupportedTypes()) {
123 if (mimeType.equals(mime)) { 124 if (mimeType.equals(mime)) {
124 name = info.getName(); 125 name = info.getName();
125 break; 126 break;
126 } 127 }
127 } 128 }
128 if (name == null) { 129 if (name == null) {
129 continue; // No HW support in this codec; try the next one. 130 continue; // No HW support in this codec; try the next one.
130 } 131 }
131 Log.v(TAG, "Found candidate decoder " + name); 132 Logging.v(TAG, "Found candidate decoder " + name);
132 133
133 // Check if this is supported decoder. 134 // Check if this is supported decoder.
134 boolean supportedCodec = false; 135 boolean supportedCodec = false;
135 for (String codecPrefix : supportedCodecPrefixes) { 136 for (String codecPrefix : supportedCodecPrefixes) {
136 if (name.startsWith(codecPrefix)) { 137 if (name.startsWith(codecPrefix)) {
137 supportedCodec = true; 138 supportedCodec = true;
138 break; 139 break;
139 } 140 }
140 } 141 }
141 if (!supportedCodec) { 142 if (!supportedCodec) {
142 continue; 143 continue;
143 } 144 }
144 145
145 // Check if codec supports either yuv420 or nv12. 146 // Check if codec supports either yuv420 or nv12.
146 CodecCapabilities capabilities = 147 CodecCapabilities capabilities =
147 info.getCapabilitiesForType(mime); 148 info.getCapabilitiesForType(mime);
148 for (int colorFormat : capabilities.colorFormats) { 149 for (int colorFormat : capabilities.colorFormats) {
149 Log.v(TAG, " Color: 0x" + Integer.toHexString(colorFormat)); 150 Logging.v(TAG, " Color: 0x" + Integer.toHexString(colorFormat));
150 } 151 }
151 for (int supportedColorFormat : supportedColorList) { 152 for (int supportedColorFormat : supportedColorList) {
152 for (int codecColorFormat : capabilities.colorFormats) { 153 for (int codecColorFormat : capabilities.colorFormats) {
153 if (codecColorFormat == supportedColorFormat) { 154 if (codecColorFormat == supportedColorFormat) {
154 // Found supported HW decoder. 155 // Found supported HW decoder.
155 Log.d(TAG, "Found target decoder " + name + 156 Logging.d(TAG, "Found target decoder " + name +
156 ". Color: 0x" + Integer.toHexString(codecColorFormat)); 157 ". Color: 0x" + Integer.toHexString(codecColorFormat));
157 return new DecoderProperties(name, codecColorFormat); 158 return new DecoderProperties(name, codecColorFormat);
158 } 159 }
159 } 160 }
160 } 161 }
161 } 162 }
162 return null; // No HW decoder. 163 return null; // No HW decoder.
163 } 164 }
164 165
165 public static boolean isVp8HwSupported() { 166 public static boolean isVp8HwSupported() {
(...skipping 26 matching lines...) Expand all
192 } else if (type == VideoCodecType.VIDEO_CODEC_H264) { 193 } else if (type == VideoCodecType.VIDEO_CODEC_H264) {
193 mime = H264_MIME_TYPE; 194 mime = H264_MIME_TYPE;
194 supportedCodecPrefixes = supportedH264HwCodecPrefixes; 195 supportedCodecPrefixes = supportedH264HwCodecPrefixes;
195 } else { 196 } else {
196 throw new RuntimeException("Non supported codec " + type); 197 throw new RuntimeException("Non supported codec " + type);
197 } 198 }
198 DecoderProperties properties = findDecoder(mime, supportedCodecPrefixes); 199 DecoderProperties properties = findDecoder(mime, supportedCodecPrefixes);
199 if (properties == null) { 200 if (properties == null) {
200 throw new RuntimeException("Cannot find HW decoder for " + type); 201 throw new RuntimeException("Cannot find HW decoder for " + type);
201 } 202 }
202 Log.d(TAG, "Java initDecode: " + type + " : "+ width + " x " + height + 203 Logging.d(TAG, "Java initDecode: " + type + " : "+ width + " x " + height +
203 ". Color: 0x" + Integer.toHexString(properties.colorFormat) + 204 ". Color: 0x" + Integer.toHexString(properties.colorFormat) +
204 ". Use Surface: " + useSurface); 205 ". Use Surface: " + useSurface);
205 if (sharedContext != null) { 206 if (sharedContext != null) {
206 Log.d(TAG, "Decoder shared EGL Context: " + sharedContext); 207 Logging.d(TAG, "Decoder shared EGL Context: " + sharedContext);
207 } 208 }
208 mediaCodecThread = Thread.currentThread(); 209 mediaCodecThread = Thread.currentThread();
209 try { 210 try {
210 Surface decodeSurface = null; 211 Surface decodeSurface = null;
211 this.width = width; 212 this.width = width;
212 this.height = height; 213 this.height = height;
213 stride = width; 214 stride = width;
214 sliceHeight = height; 215 sliceHeight = height;
215 216
216 if (useSurface) { 217 if (useSurface) {
217 // Create shared EGL context. 218 // Create shared EGL context.
218 eglBase = new EglBase(sharedContext, EglBase.ConfigType.PIXEL_BUFFER); 219 eglBase = new EglBase(sharedContext, EglBase.ConfigType.PIXEL_BUFFER);
219 eglBase.createDummyPbufferSurface(); 220 eglBase.createDummyPbufferSurface();
220 eglBase.makeCurrent(); 221 eglBase.makeCurrent();
221 222
222 // Create output surface 223 // Create output surface
223 textureID = GlUtil.generateTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES); 224 textureID = GlUtil.generateTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES);
224 Log.d(TAG, "Video decoder TextureID = " + textureID); 225 Logging.d(TAG, "Video decoder TextureID = " + textureID);
225 surfaceTexture = new SurfaceTexture(textureID); 226 surfaceTexture = new SurfaceTexture(textureID);
226 surface = new Surface(surfaceTexture); 227 surface = new Surface(surfaceTexture);
227 decodeSurface = surface; 228 decodeSurface = surface;
228 } 229 }
229 230
230 MediaFormat format = MediaFormat.createVideoFormat(mime, width, height); 231 MediaFormat format = MediaFormat.createVideoFormat(mime, width, height);
231 if (!useSurface) { 232 if (!useSurface) {
232 format.setInteger(MediaFormat.KEY_COLOR_FORMAT, properties.colorFormat); 233 format.setInteger(MediaFormat.KEY_COLOR_FORMAT, properties.colorFormat);
233 } 234 }
234 Log.d(TAG, " Format: " + format); 235 Logging.d(TAG, " Format: " + format);
235 mediaCodec = 236 mediaCodec =
236 MediaCodecVideoEncoder.createByCodecName(properties.codecName); 237 MediaCodecVideoEncoder.createByCodecName(properties.codecName);
237 if (mediaCodec == null) { 238 if (mediaCodec == null) {
238 return false; 239 return false;
239 } 240 }
240 mediaCodec.configure(format, decodeSurface, null, 0); 241 mediaCodec.configure(format, decodeSurface, null, 0);
241 mediaCodec.start(); 242 mediaCodec.start();
242 colorFormat = properties.colorFormat; 243 colorFormat = properties.colorFormat;
243 outputBuffers = mediaCodec.getOutputBuffers(); 244 outputBuffers = mediaCodec.getOutputBuffers();
244 inputBuffers = mediaCodec.getInputBuffers(); 245 inputBuffers = mediaCodec.getInputBuffers();
245 Log.d(TAG, "Input buffers: " + inputBuffers.length + 246 Logging.d(TAG, "Input buffers: " + inputBuffers.length +
246 ". Output buffers: " + outputBuffers.length); 247 ". Output buffers: " + outputBuffers.length);
247 return true; 248 return true;
248 } catch (IllegalStateException e) { 249 } catch (IllegalStateException e) {
249 Log.e(TAG, "initDecode failed", e); 250 Logging.e(TAG, "initDecode failed", e);
250 return false; 251 return false;
251 } 252 }
252 } 253 }
253 254
254 private void release() { 255 private void release() {
255 Log.d(TAG, "Java releaseDecoder"); 256 Logging.d(TAG, "Java releaseDecoder");
256 checkOnMediaCodecThread(); 257 checkOnMediaCodecThread();
257 try { 258 try {
258 mediaCodec.stop(); 259 mediaCodec.stop();
259 mediaCodec.release(); 260 mediaCodec.release();
260 } catch (IllegalStateException e) { 261 } catch (IllegalStateException e) {
261 Log.e(TAG, "release failed", e); 262 Logging.e(TAG, "release failed", e);
262 } 263 }
263 mediaCodec = null; 264 mediaCodec = null;
264 mediaCodecThread = null; 265 mediaCodecThread = null;
265 if (useSurface) { 266 if (useSurface) {
266 surface.release(); 267 surface.release();
267 if (textureID != 0) { 268 if (textureID != 0) {
268 Log.d(TAG, "Delete video decoder TextureID " + textureID); 269 Logging.d(TAG, "Delete video decoder TextureID " + textureID);
269 GLES20.glDeleteTextures(1, new int[] {textureID}, 0); 270 GLES20.glDeleteTextures(1, new int[] {textureID}, 0);
270 textureID = 0; 271 textureID = 0;
271 } 272 }
272 eglBase.release(); 273 eglBase.release();
273 eglBase = null; 274 eglBase = null;
274 } 275 }
275 } 276 }
276 277
277 // Dequeue an input buffer and return its index, -1 if no input buffer is 278 // Dequeue an input buffer and return its index, -1 if no input buffer is
278 // available, or -2 if the codec is no longer operative. 279 // available, or -2 if the codec is no longer operative.
279 private int dequeueInputBuffer() { 280 private int dequeueInputBuffer() {
280 checkOnMediaCodecThread(); 281 checkOnMediaCodecThread();
281 try { 282 try {
282 return mediaCodec.dequeueInputBuffer(DEQUEUE_INPUT_TIMEOUT); 283 return mediaCodec.dequeueInputBuffer(DEQUEUE_INPUT_TIMEOUT);
283 } catch (IllegalStateException e) { 284 } catch (IllegalStateException e) {
284 Log.e(TAG, "dequeueIntputBuffer failed", e); 285 Logging.e(TAG, "dequeueIntputBuffer failed", e);
285 return -2; 286 return -2;
286 } 287 }
287 } 288 }
288 289
289 private boolean queueInputBuffer( 290 private boolean queueInputBuffer(
290 int inputBufferIndex, int size, long timestampUs) { 291 int inputBufferIndex, int size, long timestampUs) {
291 checkOnMediaCodecThread(); 292 checkOnMediaCodecThread();
292 try { 293 try {
293 inputBuffers[inputBufferIndex].position(0); 294 inputBuffers[inputBufferIndex].position(0);
294 inputBuffers[inputBufferIndex].limit(size); 295 inputBuffers[inputBufferIndex].limit(size);
295 mediaCodec.queueInputBuffer(inputBufferIndex, 0, size, timestampUs, 0); 296 mediaCodec.queueInputBuffer(inputBufferIndex, 0, size, timestampUs, 0);
296 return true; 297 return true;
297 } 298 }
298 catch (IllegalStateException e) { 299 catch (IllegalStateException e) {
299 Log.e(TAG, "decode failed", e); 300 Logging.e(TAG, "decode failed", e);
300 return false; 301 return false;
301 } 302 }
302 } 303 }
303 304
304 // Helper struct for dequeueOutputBuffer() below. 305 // Helper struct for dequeueOutputBuffer() below.
305 private static class DecoderOutputBufferInfo { 306 private static class DecoderOutputBufferInfo {
306 public DecoderOutputBufferInfo( 307 public DecoderOutputBufferInfo(
307 int index, int offset, int size, long presentationTimestampUs) { 308 int index, int offset, int size, long presentationTimestampUs) {
308 this.index = index; 309 this.index = index;
309 this.offset = offset; 310 this.offset = offset;
(...skipping 11 matching lines...) Expand all
321 // buffer available or -2 if error happened. 322 // buffer available or -2 if error happened.
322 private DecoderOutputBufferInfo dequeueOutputBuffer(int dequeueTimeoutUs) { 323 private DecoderOutputBufferInfo dequeueOutputBuffer(int dequeueTimeoutUs) {
323 checkOnMediaCodecThread(); 324 checkOnMediaCodecThread();
324 try { 325 try {
325 MediaCodec.BufferInfo info = new MediaCodec.BufferInfo(); 326 MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
326 int result = mediaCodec.dequeueOutputBuffer(info, dequeueTimeoutUs); 327 int result = mediaCodec.dequeueOutputBuffer(info, dequeueTimeoutUs);
327 while (result == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED || 328 while (result == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED ||
328 result == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { 329 result == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
329 if (result == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) { 330 if (result == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
330 outputBuffers = mediaCodec.getOutputBuffers(); 331 outputBuffers = mediaCodec.getOutputBuffers();
331 Log.d(TAG, "Decoder output buffers changed: " + outputBuffers.length); 332 Logging.d(TAG, "Decoder output buffers changed: " + outputBuffers.leng th);
332 } else if (result == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { 333 } else if (result == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
333 MediaFormat format = mediaCodec.getOutputFormat(); 334 MediaFormat format = mediaCodec.getOutputFormat();
334 Log.d(TAG, "Decoder format changed: " + format.toString()); 335 Logging.d(TAG, "Decoder format changed: " + format.toString());
335 width = format.getInteger(MediaFormat.KEY_WIDTH); 336 width = format.getInteger(MediaFormat.KEY_WIDTH);
336 height = format.getInteger(MediaFormat.KEY_HEIGHT); 337 height = format.getInteger(MediaFormat.KEY_HEIGHT);
337 if (!useSurface && format.containsKey(MediaFormat.KEY_COLOR_FORMAT)) { 338 if (!useSurface && format.containsKey(MediaFormat.KEY_COLOR_FORMAT)) {
338 colorFormat = format.getInteger(MediaFormat.KEY_COLOR_FORMAT); 339 colorFormat = format.getInteger(MediaFormat.KEY_COLOR_FORMAT);
339 Log.d(TAG, "Color: 0x" + Integer.toHexString(colorFormat)); 340 Logging.d(TAG, "Color: 0x" + Integer.toHexString(colorFormat));
340 // Check if new color space is supported. 341 // Check if new color space is supported.
341 boolean validColorFormat = false; 342 boolean validColorFormat = false;
342 for (int supportedColorFormat : supportedColorList) { 343 for (int supportedColorFormat : supportedColorList) {
343 if (colorFormat == supportedColorFormat) { 344 if (colorFormat == supportedColorFormat) {
344 validColorFormat = true; 345 validColorFormat = true;
345 break; 346 break;
346 } 347 }
347 } 348 }
348 if (!validColorFormat) { 349 if (!validColorFormat) {
349 Log.e(TAG, "Non supported color format"); 350 Logging.e(TAG, "Non supported color format");
350 return new DecoderOutputBufferInfo(-1, 0, 0, -1); 351 return new DecoderOutputBufferInfo(-1, 0, 0, -1);
351 } 352 }
352 } 353 }
353 if (format.containsKey("stride")) { 354 if (format.containsKey("stride")) {
354 stride = format.getInteger("stride"); 355 stride = format.getInteger("stride");
355 } 356 }
356 if (format.containsKey("slice-height")) { 357 if (format.containsKey("slice-height")) {
357 sliceHeight = format.getInteger("slice-height"); 358 sliceHeight = format.getInteger("slice-height");
358 } 359 }
359 Log.d(TAG, "Frame stride and slice height: " 360 Logging.d(TAG, "Frame stride and slice height: "
360 + stride + " x " + sliceHeight); 361 + stride + " x " + sliceHeight);
361 stride = Math.max(width, stride); 362 stride = Math.max(width, stride);
362 sliceHeight = Math.max(height, sliceHeight); 363 sliceHeight = Math.max(height, sliceHeight);
363 } 364 }
364 result = mediaCodec.dequeueOutputBuffer(info, dequeueTimeoutUs); 365 result = mediaCodec.dequeueOutputBuffer(info, dequeueTimeoutUs);
365 } 366 }
366 if (result >= 0) { 367 if (result >= 0) {
367 return new DecoderOutputBufferInfo(result, info.offset, info.size, 368 return new DecoderOutputBufferInfo(result, info.offset, info.size,
368 info.presentationTimeUs); 369 info.presentationTimeUs);
369 } 370 }
370 return null; 371 return null;
371 } catch (IllegalStateException e) { 372 } catch (IllegalStateException e) {
372 Log.e(TAG, "dequeueOutputBuffer failed", e); 373 Logging.e(TAG, "dequeueOutputBuffer failed", e);
373 return new DecoderOutputBufferInfo(-1, 0, 0, -1); 374 return new DecoderOutputBufferInfo(-1, 0, 0, -1);
374 } 375 }
375 } 376 }
376 377
377 // Release a dequeued output buffer back to the codec for re-use. Return 378 // Release a dequeued output buffer back to the codec for re-use. Return
378 // false if the codec is no longer operable. 379 // false if the codec is no longer operable.
379 private boolean releaseOutputBuffer(int index) { 380 private boolean releaseOutputBuffer(int index) {
380 checkOnMediaCodecThread(); 381 checkOnMediaCodecThread();
381 try { 382 try {
382 mediaCodec.releaseOutputBuffer(index, useSurface); 383 mediaCodec.releaseOutputBuffer(index, useSurface);
383 return true; 384 return true;
384 } catch (IllegalStateException e) { 385 } catch (IllegalStateException e) {
385 Log.e(TAG, "releaseOutputBuffer failed", e); 386 Logging.e(TAG, "releaseOutputBuffer failed", e);
386 return false; 387 return false;
387 } 388 }
388 } 389 }
389 } 390 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698