| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |