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

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

Issue 1307973002: AndroidVideoCapturerJni: Fix threading issues (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Addressing tommi@s comments 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 2015 Google Inc. 3 * Copyright 2015 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 702 matching lines...) Expand 10 before | Expand all | Expand 10 after
713 private void onOutputFormatRequestOnCameraThread( 713 private void onOutputFormatRequestOnCameraThread(
714 int width, int height, int fps) { 714 int width, int height, int fps) {
715 if (camera == null) { 715 if (camera == null) {
716 return; 716 return;
717 } 717 }
718 Log.d(TAG, "onOutputFormatRequestOnCameraThread: " + width + "x" + height + 718 Log.d(TAG, "onOutputFormatRequestOnCameraThread: " + width + "x" + height +
719 "@" + fps); 719 "@" + fps);
720 frameObserver.OnOutputFormatRequest(width, height, fps); 720 frameObserver.OnOutputFormatRequest(width, height, fps);
721 } 721 }
722 722
723 synchronized void returnBuffer(final long timeStamp) { 723 void returnBuffer(long timeStamp) {
724 if (cameraThreadHandler == null) { 724 videoBuffers.returnBuffer(timeStamp);
725 // The camera has been stopped.
726 videoBuffers.returnBuffer(timeStamp);
727 return;
728 }
729 cameraThreadHandler.post(new Runnable() {
730 @Override public void run() {
731 videoBuffers.returnBuffer(timeStamp);
732 }
733 });
734 } 725 }
735 726
736 private int getDeviceOrientation() { 727 private int getDeviceOrientation() {
737 int orientation = 0; 728 int orientation = 0;
738 729
739 WindowManager wm = (WindowManager) applicationContext.getSystemService( 730 WindowManager wm = (WindowManager) applicationContext.getSystemService(
740 Context.WINDOW_SERVICE); 731 Context.WINDOW_SERVICE);
741 switch(wm.getDefaultDisplay().getRotation()) { 732 switch(wm.getDefaultDisplay().getRotation()) {
742 case Surface.ROTATION_90: 733 case Surface.ROTATION_90:
743 orientation = 90; 734 orientation = 90;
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
847 // RuntimeExceptions (since we expect never to see these). 838 // RuntimeExceptions (since we expect never to see these).
848 private static <T> T exchange(Exchanger<T> exchanger, T value) { 839 private static <T> T exchange(Exchanger<T> exchanger, T value) {
849 try { 840 try {
850 return exchanger.exchange(value); 841 return exchanger.exchange(value);
851 } catch (InterruptedException e) { 842 } catch (InterruptedException e) {
852 throw new RuntimeException(e); 843 throw new RuntimeException(e);
853 } 844 }
854 } 845 }
855 846
856 // Class used for allocating and bookkeeping video frames. All buffers are 847 // Class used for allocating and bookkeeping video frames. All buffers are
857 // direct allocated so that they can be directly used from native code. 848 // direct allocated so that they can be directly used from native code. This c lass is
849 // synchronized and can be called from multiple threads.
858 private static class FramePool { 850 private static class FramePool {
859 // Arbitrary queue depth. Higher number means more memory allocated & held, 851 // Arbitrary queue depth. Higher number means more memory allocated & held,
860 // lower number means more sensitivity to processing time in the client (and 852 // lower number means more sensitivity to processing time in the client (and
861 // potentially stalling the capturer if it runs out of buffers to write to). 853 // potentially stalling the capturer if it runs out of buffers to write to).
862 private static final int numCaptureBuffers = 3; 854 private static final int numCaptureBuffers = 3;
863 // This container tracks the buffers added as camera callback buffers. It is needed for finding 855 // This container tracks the buffers added as camera callback buffers. It is needed for finding
864 // the corresponding ByteBuffer given a byte[]. 856 // the corresponding ByteBuffer given a byte[].
865 private final Map<byte[], ByteBuffer> queuedBuffers = new IdentityHashMap<by te[], ByteBuffer>(); 857 private final Map<byte[], ByteBuffer> queuedBuffers = new IdentityHashMap<by te[], ByteBuffer>();
866 // This container tracks the frames that have been sent but not returned. It is needed for 858 // This container tracks the frames that have been sent but not returned. It is needed for
867 // keeping the buffers alive and for finding the corresponding ByteBuffer gi ven a timestamp. 859 // keeping the buffers alive and for finding the corresponding ByteBuffer gi ven a timestamp.
868 private final Map<Long, ByteBuffer> pendingBuffers = new HashMap<Long, ByteB uffer>(); 860 private final Map<Long, ByteBuffer> pendingBuffers = new HashMap<Long, ByteB uffer>();
869 private int frameSize = 0; 861 private int frameSize = 0;
870 private Camera camera; 862 private Camera camera;
871 863
872 int numCaptureBuffersAvailable() { 864 synchronized int numCaptureBuffersAvailable() {
873 return queuedBuffers.size(); 865 return queuedBuffers.size();
874 } 866 }
875 867
876 // Discards previous queued buffers and adds new callback buffers to camera. 868 // Discards previous queued buffers and adds new callback buffers to camera.
877 void queueCameraBuffers(int frameSize, Camera camera) { 869 synchronized void queueCameraBuffers(int frameSize, Camera camera) {
878 this.camera = camera; 870 this.camera = camera;
879 this.frameSize = frameSize; 871 this.frameSize = frameSize;
880 872
881 queuedBuffers.clear(); 873 queuedBuffers.clear();
882 for (int i = 0; i < numCaptureBuffers; ++i) { 874 for (int i = 0; i < numCaptureBuffers; ++i) {
883 final ByteBuffer buffer = ByteBuffer.allocateDirect(frameSize); 875 final ByteBuffer buffer = ByteBuffer.allocateDirect(frameSize);
884 camera.addCallbackBuffer(buffer.array()); 876 camera.addCallbackBuffer(buffer.array());
885 queuedBuffers.put(buffer.array(), buffer); 877 queuedBuffers.put(buffer.array(), buffer);
886 } 878 }
887 Log.d(TAG, "queueCameraBuffers enqueued " + numCaptureBuffers 879 Log.d(TAG, "queueCameraBuffers enqueued " + numCaptureBuffers
888 + " buffers of size " + frameSize + "."); 880 + " buffers of size " + frameSize + ".");
889 } 881 }
890 882
891 String pendingFramesTimeStamps() { 883 synchronized String pendingFramesTimeStamps() {
892 List<Long> timeStampsMs = new ArrayList<Long>(); 884 List<Long> timeStampsMs = new ArrayList<Long>();
893 for (Long timeStampNs : pendingBuffers.keySet()) { 885 for (Long timeStampNs : pendingBuffers.keySet()) {
894 timeStampsMs.add(TimeUnit.NANOSECONDS.toMillis(timeStampNs)); 886 timeStampsMs.add(TimeUnit.NANOSECONDS.toMillis(timeStampNs));
895 } 887 }
896 return timeStampsMs.toString(); 888 return timeStampsMs.toString();
897 } 889 }
898 890
899 void stopReturnBuffersToCamera() { 891 synchronized void stopReturnBuffersToCamera() {
900 this.camera = null; 892 this.camera = null;
901 queuedBuffers.clear(); 893 queuedBuffers.clear();
902 // Frames in |pendingBuffers| need to be kept alive until they are returne d. 894 // Frames in |pendingBuffers| need to be kept alive until they are returne d.
903 Log.d(TAG, "stopReturnBuffersToCamera called." 895 Log.d(TAG, "stopReturnBuffersToCamera called."
904 + (pendingBuffers.isEmpty() ? 896 + (pendingBuffers.isEmpty() ?
905 " All buffers have been returned." 897 " All buffers have been returned."
906 : " Pending buffers: " + pendingFramesTimeStamps() + ".")); 898 : " Pending buffers: " + pendingFramesTimeStamps() + "."));
907 } 899 }
908 900
909 boolean reserveByteBuffer(byte[] data, long timeStamp) { 901 synchronized boolean reserveByteBuffer(byte[] data, long timeStamp) {
910 final ByteBuffer buffer = queuedBuffers.remove(data); 902 final ByteBuffer buffer = queuedBuffers.remove(data);
911 if (buffer == null) { 903 if (buffer == null) {
912 // Frames might be posted to |onPreviewFrame| with the previous format w hile changing 904 // Frames might be posted to |onPreviewFrame| with the previous format w hile changing
913 // capture format in |startPreviewOnCameraThread|. Drop these old frames . 905 // capture format in |startPreviewOnCameraThread|. Drop these old frames .
914 Log.w(TAG, "Received callback buffer from previous configuration with le ngth: " 906 Log.w(TAG, "Received callback buffer from previous configuration with le ngth: "
915 + (data == null ? "null" : data.length)); 907 + (data == null ? "null" : data.length));
916 return false; 908 return false;
917 } 909 }
918 if (buffer.capacity() != frameSize) { 910 if (buffer.capacity() != frameSize) {
919 throw new IllegalStateException("Callback buffer has unexpected frame si ze"); 911 throw new IllegalStateException("Callback buffer has unexpected frame si ze");
920 } 912 }
921 if (pendingBuffers.containsKey(timeStamp)) { 913 if (pendingBuffers.containsKey(timeStamp)) {
922 Log.e(TAG, "Timestamp already present in pending buffers - they need to be unique"); 914 Log.e(TAG, "Timestamp already present in pending buffers - they need to be unique");
923 return false; 915 return false;
924 } 916 }
925 pendingBuffers.put(timeStamp, buffer); 917 pendingBuffers.put(timeStamp, buffer);
926 if (queuedBuffers.isEmpty()) { 918 if (queuedBuffers.isEmpty()) {
927 Log.v(TAG, "Camera is running out of capture buffers." 919 Log.v(TAG, "Camera is running out of capture buffers."
928 + " Pending buffers: " + pendingFramesTimeStamps()); 920 + " Pending buffers: " + pendingFramesTimeStamps());
929 } 921 }
930 return true; 922 return true;
931 } 923 }
932 924
933 void returnBuffer(long timeStamp) { 925 synchronized void returnBuffer(long timeStamp) {
934 final ByteBuffer returnedFrame = pendingBuffers.remove(timeStamp); 926 final ByteBuffer returnedFrame = pendingBuffers.remove(timeStamp);
935 if (returnedFrame == null) { 927 if (returnedFrame == null) {
936 throw new RuntimeException("unknown data buffer with time stamp " 928 throw new RuntimeException("unknown data buffer with time stamp "
937 + timeStamp + "returned?!?"); 929 + timeStamp + "returned?!?");
938 } 930 }
939 931
940 if (camera != null && returnedFrame.capacity() == frameSize) { 932 if (camera != null && returnedFrame.capacity() == frameSize) {
941 camera.addCallbackBuffer(returnedFrame.array()); 933 camera.addCallbackBuffer(returnedFrame.array());
942 if (queuedBuffers.isEmpty()) { 934 if (queuedBuffers.isEmpty()) {
943 Log.v(TAG, "Frame returned when camera is running out of capture" 935 Log.v(TAG, "Frame returned when camera is running out of capture"
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1005 } 997 }
1006 998
1007 private native void nativeCapturerStarted(long nativeCapturer, 999 private native void nativeCapturerStarted(long nativeCapturer,
1008 boolean success); 1000 boolean success);
1009 private native void nativeOnFrameCaptured(long nativeCapturer, 1001 private native void nativeOnFrameCaptured(long nativeCapturer,
1010 byte[] data, int length, int width, int height, int rotation, long timeS tamp); 1002 byte[] data, int length, int width, int height, int rotation, long timeS tamp);
1011 private native void nativeOnOutputFormatRequest(long nativeCapturer, 1003 private native void nativeOnOutputFormatRequest(long nativeCapturer,
1012 int width, int height, int fps); 1004 int width, int height, int fps);
1013 } 1005 }
1014 } 1006 }
OLDNEW
« no previous file with comments | « talk/app/webrtc/java/jni/androidvideocapturer_jni.cc ('k') | webrtc/common_video/interface/video_frame_buffer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698