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 ByteBuffer[] yuvPlanes; | 45 public final ByteBuffer[] yuvPlanes; |
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; | |
51 | 49 |
52 // rotationDegree is the degree that the frame must be rotated clockwisely | 50 // rotationDegree is the degree that the frame must be rotated clockwisely |
53 // to be rendered correctly. | 51 // to be rendered correctly. |
54 public int rotationDegree; | 52 public int rotationDegree; |
55 | 53 |
56 /** | 54 /** |
57 * Construct a frame of the given dimensions with the specified planar | 55 * Construct a frame of the given dimensions with the specified planar |
58 * data. If |yuvPlanes| is null, new planes of the appropriate sizes are | 56 * data. If |yuvPlanes| is null, new planes of the appropriate sizes are |
59 * allocated. | 57 * allocated. |
60 */ | 58 */ |
61 public I420Frame( | 59 public I420Frame( |
62 int width, int height, int rotationDegree, | 60 int width, int height, int rotationDegree, |
63 int[] yuvStrides, ByteBuffer[] yuvPlanes, long nativeFramePointer) { | 61 int[] yuvStrides, ByteBuffer[] yuvPlanes) { |
64 this.width = width; | 62 this.width = width; |
65 this.height = height; | 63 this.height = height; |
66 this.yuvStrides = yuvStrides; | 64 this.yuvStrides = yuvStrides; |
67 if (yuvPlanes == null) { | 65 if (yuvPlanes == null) { |
68 yuvPlanes = new ByteBuffer[3]; | 66 yuvPlanes = new ByteBuffer[3]; |
69 yuvPlanes[0] = ByteBuffer.allocateDirect(yuvStrides[0] * height); | 67 yuvPlanes[0] = ByteBuffer.allocateDirect(yuvStrides[0] * height); |
70 yuvPlanes[1] = ByteBuffer.allocateDirect(yuvStrides[1] * height / 2); | 68 yuvPlanes[1] = ByteBuffer.allocateDirect(yuvStrides[1] * height / 2); |
71 yuvPlanes[2] = ByteBuffer.allocateDirect(yuvStrides[2] * height / 2); | 69 yuvPlanes[2] = ByteBuffer.allocateDirect(yuvStrides[2] * height / 2); |
72 } | 70 } |
73 this.yuvPlanes = yuvPlanes; | 71 this.yuvPlanes = yuvPlanes; |
74 this.yuvFrame = true; | 72 this.yuvFrame = true; |
75 this.rotationDegree = rotationDegree; | 73 this.rotationDegree = rotationDegree; |
76 this.nativeFramePointer = nativeFramePointer; | |
77 if (rotationDegree % 90 != 0) { | 74 if (rotationDegree % 90 != 0) { |
78 throw new IllegalArgumentException("Rotation degree not multiple of 90:
" + rotationDegree); | 75 throw new IllegalArgumentException("Rotation degree not multiple of 90:
" + rotationDegree); |
79 } | 76 } |
80 } | 77 } |
81 | 78 |
82 /** | 79 /** |
83 * Construct a texture frame of the given dimensions with data in SurfaceTex
ture | 80 * Construct a texture frame of the given dimensions with data in SurfaceTex
ture |
84 */ | 81 */ |
85 public I420Frame( | 82 public I420Frame( |
86 int width, int height, int rotationDegree, | 83 int width, int height, int rotationDegree, |
87 Object textureObject, int textureId, long nativeFramePointer) { | 84 Object textureObject, int textureId) { |
88 this.width = width; | 85 this.width = width; |
89 this.height = height; | 86 this.height = height; |
90 this.yuvStrides = null; | 87 this.yuvStrides = null; |
91 this.yuvPlanes = null; | 88 this.yuvPlanes = null; |
92 this.textureObject = textureObject; | 89 this.textureObject = textureObject; |
93 this.textureId = textureId; | 90 this.textureId = textureId; |
94 this.yuvFrame = false; | 91 this.yuvFrame = false; |
95 this.rotationDegree = rotationDegree; | 92 this.rotationDegree = rotationDegree; |
96 this.nativeFramePointer = nativeFramePointer; | |
97 if (rotationDegree % 90 != 0) { | 93 if (rotationDegree % 90 != 0) { |
98 throw new IllegalArgumentException("Rotation degree not multiple of 90:
" + rotationDegree); | 94 throw new IllegalArgumentException("Rotation degree not multiple of 90:
" + rotationDegree); |
99 } | 95 } |
100 } | 96 } |
101 | 97 |
102 public int rotatedWidth() { | 98 public int rotatedWidth() { |
103 return (rotationDegree % 180 == 0) ? width : height; | 99 return (rotationDegree % 180 == 0) ? width : height; |
104 } | 100 } |
105 | 101 |
106 public int rotatedHeight() { | 102 public int rotatedHeight() { |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 } | 157 } |
162 | 158 |
163 @Override | 159 @Override |
164 public String toString() { | 160 public String toString() { |
165 return width + "x" + height + ":" + yuvStrides[0] + ":" + yuvStrides[1] + | 161 return width + "x" + height + ":" + yuvStrides[0] + ":" + yuvStrides[1] + |
166 ":" + yuvStrides[2]; | 162 ":" + yuvStrides[2]; |
167 } | 163 } |
168 } | 164 } |
169 | 165 |
170 // Helper native function to do a video frame plane copying. | 166 // Helper native function to do a video frame plane copying. |
171 public static native void nativeCopyPlane(ByteBuffer src, int width, | 167 private static native void nativeCopyPlane(ByteBuffer src, int width, |
172 int height, int srcStride, ByteBuffer dst, int dstStride); | 168 int height, int srcStride, ByteBuffer dst, int dstStride); |
173 | 169 |
174 /** The real meat of VideoRendererInterface. */ | 170 /** The real meat of VideoRendererInterface. */ |
175 public static interface Callbacks { | 171 public static interface Callbacks { |
176 // |frame| might have pending rotation and implementation of Callbacks | 172 // |frame| might have pending rotation and implementation of Callbacks |
177 // should handle that by applying rotation during rendering. The callee | 173 // should handle that by applying rotation during rendering. |
178 // is responsible for signaling when it is done with |frame| by calling | |
179 // renderFrameDone(frame). | |
180 public void renderFrame(I420Frame frame); | 174 public void renderFrame(I420Frame frame); |
181 // TODO(guoweis): Remove this once chrome code base is updated. | 175 // TODO(guoweis): Remove this once chrome code base is updated. |
182 public boolean canApplyRotation(); | 176 public boolean canApplyRotation(); |
183 } | 177 } |
184 | 178 |
185 /** | |
186 * This must be called after every renderFrame() to release the frame. | |
187 */ | |
188 public static void renderFrameDone(I420Frame frame) { | |
189 frame.yuvPlanes = null; | |
190 frame.textureObject = null; | |
191 frame.textureId = 0; | |
192 if (frame.nativeFramePointer != 0) { | |
193 releaseNativeFrame(frame.nativeFramePointer); | |
194 frame.nativeFramePointer = 0; | |
195 } | |
196 } | |
197 | |
198 // |this| either wraps a native (GUI) renderer or a client-supplied Callbacks | 179 // |this| either wraps a native (GUI) renderer or a client-supplied Callbacks |
199 // (Java) implementation; so exactly one of these will be non-0/null. | 180 // (Java) implementation; so exactly one of these will be non-0/null. |
200 final long nativeVideoRenderer; | 181 final long nativeVideoRenderer; |
201 private final Callbacks callbacks; | 182 private final Callbacks callbacks; |
202 | 183 |
203 public static VideoRenderer createGui(int x, int y) { | 184 public static VideoRenderer createGui(int x, int y) { |
204 long nativeVideoRenderer = nativeCreateGuiVideoRenderer(x, y); | 185 long nativeVideoRenderer = nativeCreateGuiVideoRenderer(x, y); |
205 if (nativeVideoRenderer == 0) { | 186 if (nativeVideoRenderer == 0) { |
206 return null; | 187 return null; |
207 } | 188 } |
(...skipping 16 matching lines...) Expand all Loading... |
224 } else { | 205 } else { |
225 freeWrappedVideoRenderer(nativeVideoRenderer); | 206 freeWrappedVideoRenderer(nativeVideoRenderer); |
226 } | 207 } |
227 } | 208 } |
228 | 209 |
229 private static native long nativeCreateGuiVideoRenderer(int x, int y); | 210 private static native long nativeCreateGuiVideoRenderer(int x, int y); |
230 private static native long nativeWrapVideoRenderer(Callbacks callbacks); | 211 private static native long nativeWrapVideoRenderer(Callbacks callbacks); |
231 | 212 |
232 private static native void freeGuiVideoRenderer(long nativeVideoRenderer); | 213 private static native void freeGuiVideoRenderer(long nativeVideoRenderer); |
233 private static native void freeWrappedVideoRenderer(long nativeVideoRenderer); | 214 private static native void freeWrappedVideoRenderer(long nativeVideoRenderer); |
234 | |
235 private static native void releaseNativeFrame(long nativeFramePointer); | |
236 } | 215 } |
OLD | NEW |