OLD | NEW |
---|---|
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 24 matching lines...) Expand all Loading... | |
35 * class also provides a createGui() method for creating a GUI-rendering window | 35 * class also provides a createGui() method for creating a GUI-rendering window |
36 * on various platforms. | 36 * on various platforms. |
37 */ | 37 */ |
38 public class VideoRenderer { | 38 public class VideoRenderer { |
39 | 39 |
40 /** Java version of cricket::VideoFrame. */ | 40 /** Java version of cricket::VideoFrame. */ |
41 public static class I420Frame { | 41 public static class I420Frame { |
42 public final int width; | 42 public final int width; |
43 public final int height; | 43 public final int height; |
44 public final int[] yuvStrides; | 44 public final int[] yuvStrides; |
45 public final ByteBuffer[] yuvPlanes; | 45 public ByteBuffer[] yuvPlanes; |
AlexG
2015/08/26 23:27:25
why not to keep final?
magjed_webrtc
2015/08/27 15:52:20
I set it to null in renderFrameDone() to make sure
| |
46 public final boolean yuvFrame; | 46 public final boolean yuvFrame; |
47 public Object textureObject; | 47 public Object textureObject; |
48 public int textureId; | 48 public int textureId; |
49 // If |nativeFramePointer| is non-zero, the memory is allocated on the C++ s ide. | |
50 private long nativeFramePointer; | |
49 | 51 |
50 // rotationDegree is the degree that the frame must be rotated clockwisely | 52 // rotationDegree is the degree that the frame must be rotated clockwisely |
51 // to be rendered correctly. | 53 // to be rendered correctly. |
52 public int rotationDegree; | 54 public int rotationDegree; |
53 | 55 |
54 /** | 56 /** |
55 * Construct a frame of the given dimensions with the specified planar | 57 * Construct a frame of the given dimensions with the specified planar |
56 * data. If |yuvPlanes| is null, new planes of the appropriate sizes are | 58 * data. If |yuvPlanes| is null, new planes of the appropriate sizes are |
57 * allocated. | 59 * allocated. |
58 */ | 60 */ |
59 public I420Frame( | 61 public I420Frame( |
60 int width, int height, int rotationDegree, | 62 int width, int height, int rotationDegree, |
61 int[] yuvStrides, ByteBuffer[] yuvPlanes) { | 63 int[] yuvStrides, ByteBuffer[] yuvPlanes, long nativeFramePointer) { |
62 this.width = width; | 64 this.width = width; |
63 this.height = height; | 65 this.height = height; |
64 this.yuvStrides = yuvStrides; | 66 this.yuvStrides = yuvStrides; |
65 if (yuvPlanes == null) { | 67 if (yuvPlanes == null) { |
66 yuvPlanes = new ByteBuffer[3]; | 68 yuvPlanes = new ByteBuffer[3]; |
67 yuvPlanes[0] = ByteBuffer.allocateDirect(yuvStrides[0] * height); | 69 yuvPlanes[0] = ByteBuffer.allocateDirect(yuvStrides[0] * height); |
68 yuvPlanes[1] = ByteBuffer.allocateDirect(yuvStrides[1] * height / 2); | 70 yuvPlanes[1] = ByteBuffer.allocateDirect(yuvStrides[1] * height / 2); |
69 yuvPlanes[2] = ByteBuffer.allocateDirect(yuvStrides[2] * height / 2); | 71 yuvPlanes[2] = ByteBuffer.allocateDirect(yuvStrides[2] * height / 2); |
70 } | 72 } |
71 this.yuvPlanes = yuvPlanes; | 73 this.yuvPlanes = yuvPlanes; |
72 this.yuvFrame = true; | 74 this.yuvFrame = true; |
73 this.rotationDegree = rotationDegree; | 75 this.rotationDegree = rotationDegree; |
76 this.nativeFramePointer = nativeFramePointer; | |
74 if (rotationDegree % 90 != 0) { | 77 if (rotationDegree % 90 != 0) { |
75 throw new IllegalArgumentException("Rotation degree not multiple of 90: " + rotationDegree); | 78 throw new IllegalArgumentException("Rotation degree not multiple of 90: " + rotationDegree); |
76 } | 79 } |
77 } | 80 } |
78 | 81 |
79 /** | 82 /** |
80 * Construct a texture frame of the given dimensions with data in SurfaceTex ture | 83 * Construct a texture frame of the given dimensions with data in SurfaceTex ture |
81 */ | 84 */ |
82 public I420Frame( | 85 public I420Frame( |
83 int width, int height, int rotationDegree, | 86 int width, int height, int rotationDegree, |
84 Object textureObject, int textureId) { | 87 Object textureObject, int textureId, long nativeFramePointer) { |
85 this.width = width; | 88 this.width = width; |
86 this.height = height; | 89 this.height = height; |
87 this.yuvStrides = null; | 90 this.yuvStrides = null; |
88 this.yuvPlanes = null; | 91 this.yuvPlanes = null; |
89 this.textureObject = textureObject; | 92 this.textureObject = textureObject; |
90 this.textureId = textureId; | 93 this.textureId = textureId; |
91 this.yuvFrame = false; | 94 this.yuvFrame = false; |
92 this.rotationDegree = rotationDegree; | 95 this.rotationDegree = rotationDegree; |
96 this.nativeFramePointer = nativeFramePointer; | |
93 if (rotationDegree % 90 != 0) { | 97 if (rotationDegree % 90 != 0) { |
94 throw new IllegalArgumentException("Rotation degree not multiple of 90: " + rotationDegree); | 98 throw new IllegalArgumentException("Rotation degree not multiple of 90: " + rotationDegree); |
95 } | 99 } |
96 } | 100 } |
97 | 101 |
98 public int rotatedWidth() { | 102 public int rotatedWidth() { |
99 return (rotationDegree % 180 == 0) ? width : height; | 103 return (rotationDegree % 180 == 0) ? width : height; |
100 } | 104 } |
101 | 105 |
102 public int rotatedHeight() { | 106 public int rotatedHeight() { |
(...skipping 10 matching lines...) Expand all Loading... | |
113 if (width != source.width || height != source.height) { | 117 if (width != source.width || height != source.height) { |
114 throw new RuntimeException("Mismatched dimensions! Source: " + | 118 throw new RuntimeException("Mismatched dimensions! Source: " + |
115 source.toString() + ", destination: " + toString()); | 119 source.toString() + ", destination: " + toString()); |
116 } | 120 } |
117 nativeCopyPlane(source.yuvPlanes[0], width, height, | 121 nativeCopyPlane(source.yuvPlanes[0], width, height, |
118 source.yuvStrides[0], yuvPlanes[0], yuvStrides[0]); | 122 source.yuvStrides[0], yuvPlanes[0], yuvStrides[0]); |
119 nativeCopyPlane(source.yuvPlanes[1], width / 2, height / 2, | 123 nativeCopyPlane(source.yuvPlanes[1], width / 2, height / 2, |
120 source.yuvStrides[1], yuvPlanes[1], yuvStrides[1]); | 124 source.yuvStrides[1], yuvPlanes[1], yuvStrides[1]); |
121 nativeCopyPlane(source.yuvPlanes[2], width / 2, height / 2, | 125 nativeCopyPlane(source.yuvPlanes[2], width / 2, height / 2, |
122 source.yuvStrides[2], yuvPlanes[2], yuvStrides[2]); | 126 source.yuvStrides[2], yuvPlanes[2], yuvStrides[2]); |
123 rotationDegree = source.rotationDegree; | 127 rotationDegree = source.rotationDegree; |
AlexG
2015/08/26 23:27:25
Add a comment why nativeFramePointer is not copied
magjed_webrtc
2015/08/27 15:52:20
Done.
| |
124 return this; | 128 return this; |
125 } else if (!source.yuvFrame && !yuvFrame) { | 129 } else if (!source.yuvFrame && !yuvFrame) { |
126 textureObject = source.textureObject; | 130 textureObject = source.textureObject; |
127 textureId = source.textureId; | 131 textureId = source.textureId; |
128 rotationDegree = source.rotationDegree; | 132 rotationDegree = source.rotationDegree; |
129 return this; | 133 return this; |
130 } else { | 134 } else { |
131 throw new RuntimeException("Mismatched frame types! Source: " + | 135 throw new RuntimeException("Mismatched frame types! Source: " + |
132 source.toString() + ", destination: " + toString()); | 136 source.toString() + ", destination: " + toString()); |
133 } | 137 } |
(...skipping 29 matching lines...) Expand all Loading... | |
163 } | 167 } |
164 } | 168 } |
165 | 169 |
166 // Helper native function to do a video frame plane copying. | 170 // Helper native function to do a video frame plane copying. |
167 private static native void nativeCopyPlane(ByteBuffer src, int width, | 171 private static native void nativeCopyPlane(ByteBuffer src, int width, |
168 int height, int srcStride, ByteBuffer dst, int dstStride); | 172 int height, int srcStride, ByteBuffer dst, int dstStride); |
169 | 173 |
170 /** The real meat of VideoRendererInterface. */ | 174 /** The real meat of VideoRendererInterface. */ |
171 public static interface Callbacks { | 175 public static interface Callbacks { |
172 // |frame| might have pending rotation and implementation of Callbacks | 176 // |frame| might have pending rotation and implementation of Callbacks |
173 // should handle that by applying rotation during rendering. | 177 // should handle that by applying rotation during rendering. The callee |
178 // is responsible for signaling when it is done with |frame| by calling | |
179 // renderFrameDone(frame). | |
174 public void renderFrame(I420Frame frame); | 180 public void renderFrame(I420Frame frame); |
175 } | 181 } |
176 | 182 |
183 /** | |
184 * This must be called after every renderFrame() to release the frame. | |
185 */ | |
186 public static void renderFrameDone(I420Frame frame) { | |
187 frame.yuvPlanes = null; | |
188 frame.textureObject = null; | |
189 frame.textureId = 0; | |
190 if (frame.nativeFramePointer != 0) { | |
191 releaseNativeFrame(frame.nativeFramePointer); | |
192 frame.nativeFramePointer = 0; | |
193 } | |
194 } | |
195 | |
177 // |this| either wraps a native (GUI) renderer or a client-supplied Callbacks | 196 // |this| either wraps a native (GUI) renderer or a client-supplied Callbacks |
178 // (Java) implementation; this is indicated by |isWrappedVideoRenderer|. | 197 // (Java) implementation; this is indicated by |isWrappedVideoRenderer|. |
179 long nativeVideoRenderer; | 198 long nativeVideoRenderer; |
180 private final boolean isWrappedVideoRenderer; | 199 private final boolean isWrappedVideoRenderer; |
181 | 200 |
182 public static VideoRenderer createGui(int x, int y) { | 201 public static VideoRenderer createGui(int x, int y) { |
183 long nativeVideoRenderer = nativeCreateGuiVideoRenderer(x, y); | 202 long nativeVideoRenderer = nativeCreateGuiVideoRenderer(x, y); |
184 if (nativeVideoRenderer == 0) { | 203 if (nativeVideoRenderer == 0) { |
185 return null; | 204 return null; |
186 } | 205 } |
(...skipping 21 matching lines...) Expand all Loading... | |
208 freeWrappedVideoRenderer(nativeVideoRenderer); | 227 freeWrappedVideoRenderer(nativeVideoRenderer); |
209 } | 228 } |
210 nativeVideoRenderer = 0; | 229 nativeVideoRenderer = 0; |
211 } | 230 } |
212 | 231 |
213 private static native long nativeCreateGuiVideoRenderer(int x, int y); | 232 private static native long nativeCreateGuiVideoRenderer(int x, int y); |
214 private static native long nativeWrapVideoRenderer(Callbacks callbacks); | 233 private static native long nativeWrapVideoRenderer(Callbacks callbacks); |
215 | 234 |
216 private static native void freeGuiVideoRenderer(long nativeVideoRenderer); | 235 private static native void freeGuiVideoRenderer(long nativeVideoRenderer); |
217 private static native void freeWrappedVideoRenderer(long nativeVideoRenderer); | 236 private static native void freeWrappedVideoRenderer(long nativeVideoRenderer); |
237 | |
238 private static native void releaseNativeFrame(long nativeFramePointer); | |
218 } | 239 } |
OLD | NEW |