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 |