|
1 | 1 | /* |
| 2 | + * Copyright (c) 2019 Neil C Smith |
2 | 3 | * Copyright (c) 2007 Wayne Meissner |
3 | 4 | * |
4 | 5 | * This file is part of gstreamer-java. |
|
15 | 16 | * You should have received a copy of the GNU Lesser General Public License |
16 | 17 | * version 3 along with this work. If not, see <http://www.gnu.org/licenses/>. |
17 | 18 | */ |
18 | | - |
19 | 19 | package org.freedesktop.gstreamer.elements; |
20 | 20 |
|
21 | | -import java.util.concurrent.TimeUnit; |
22 | | - |
23 | | -import org.freedesktop.gstreamer.Buffer; |
24 | | -import org.freedesktop.gstreamer.ClockReturn; |
25 | | -import org.freedesktop.gstreamer.ClockTime; |
26 | 21 | import org.freedesktop.gstreamer.Element; |
27 | | -import org.freedesktop.gstreamer.FlowReturn; |
28 | | -import org.freedesktop.gstreamer.MiniObject; |
29 | | -import org.freedesktop.gstreamer.Pad; |
30 | | -import org.freedesktop.gstreamer.lowlevel.BaseSinkAPI; |
31 | | -import org.freedesktop.gstreamer.lowlevel.BaseSinkAPI.GstBaseSinkClass; |
32 | | -import org.freedesktop.gstreamer.lowlevel.BaseSinkAPI.GstBaseSinkStruct; |
33 | | -import org.freedesktop.gstreamer.lowlevel.BaseSinkAPI.ProposeAllocation; |
34 | | -import org.freedesktop.gstreamer.lowlevel.GstAPI; |
35 | | -import org.freedesktop.gstreamer.query.AllocationQuery; |
36 | | - |
37 | | -import com.sun.jna.Pointer; |
38 | 22 |
|
| 23 | +/** |
| 24 | + * A base class for sink elements. |
| 25 | + * <p> |
| 26 | + * See upstream documentation at |
| 27 | + * <a href="https://gstreamer.freedesktop.org/data/doc/gstreamer/stable/gstreamer-libs/html/GstBaseSink.html" |
| 28 | + * >https://gstreamer.freedesktop.org/data/doc/gstreamer/stable/gstreamer-libs/html/GstBaseSink.html</a> |
| 29 | + * <p> |
| 30 | + */ |
39 | 31 | public class BaseSink extends Element { |
| 32 | + |
40 | 33 | public static final String GTYPE_NAME = "GstBaseSink"; |
41 | 34 |
|
42 | | - private static final BaseSinkAPI gst() { return BaseSinkAPI.BASESINK_API; } |
43 | | - |
44 | | - public BaseSink(Initializer init) { |
| 35 | + protected BaseSink(Initializer init) { |
45 | 36 | super(init); |
46 | 37 | } |
47 | | - |
48 | | - public FlowReturn preroll(MiniObject obj) { |
49 | | - return gst().gst_base_sink_do_preroll(this, obj); |
50 | | - } |
51 | | - public FlowReturn waitPreroll() { |
52 | | - return gst().gst_base_sink_wait_preroll(this); |
53 | | - } |
54 | | - public void setSync(boolean sync) { |
55 | | - gst().gst_base_sink_set_sync(this, sync); |
56 | | - } |
57 | | - public boolean isSync() { |
58 | | - return gst().gst_base_sink_get_sync(this); |
59 | | - } |
60 | | - public void setMaximumLateness(long lateness, TimeUnit units) { |
61 | | - gst().gst_base_sink_set_max_lateness(this, units.toNanos(lateness)); |
62 | | - } |
63 | | - public long getMaximumLateness(TimeUnit units) { |
64 | | - return units.convert(gst().gst_base_sink_get_max_lateness(this),TimeUnit.NANOSECONDS); |
65 | | - } |
66 | | - public void setQOSEnabled(boolean qos) { |
67 | | - gst().gst_base_sink_set_qos_enabled(this, qos); |
68 | | - } |
69 | | - public boolean isQOSEnabled() { |
70 | | - return gst().gst_base_sink_is_qos_enabled(this); |
71 | | - } |
72 | | - public void enableAsync(boolean enabled) { |
73 | | - gst().gst_base_sink_set_async_enabled(this, enabled); |
74 | | - } |
75 | | - public boolean isAsync() { |
76 | | - return gst().gst_base_sink_is_async_enabled(this); |
77 | | - } |
78 | | - public void setTsOffset(long offset) { |
79 | | - gst().gst_base_sink_set_ts_offset(this, offset); |
80 | | - } |
81 | | - public long getTsOffset() { |
82 | | - return gst().gst_base_sink_get_ts_offset(this); |
83 | | - } |
84 | | - public Buffer getLastBuffer() { |
85 | | - return gst().gst_base_sink_get_last_buffer(this); |
86 | | - } |
87 | | - public void enableLastBuffer(boolean enable) { |
88 | | - gst().gst_base_sink_set_last_buffer_enabled(this, enable); |
89 | | - } |
90 | | - public boolean isLastBufferEnabled() { |
91 | | - return gst().gst_base_sink_is_last_buffer_enabled(this); |
92 | | - } |
93 | | - public boolean queryLatency(boolean live, boolean upstream_live, ClockTime min_latency, ClockTime max_latency) { |
94 | | - return gst().gst_base_sink_query_latency(this, live, upstream_live, min_latency, max_latency); |
95 | | - } |
96 | | - public ClockTime getLatency() { |
97 | | - return gst().gst_base_sink_get_latency(this); |
98 | | - } |
99 | | - public void setRenderDelay(ClockTime delay) { |
100 | | - gst().gst_base_sink_set_render_delay(this, delay); |
101 | | - } |
102 | | - public ClockTime getRenderDelay() { |
103 | | - return gst().gst_base_sink_get_render_delay(this); |
104 | | - } |
105 | | - public void setBlocksize(int blocksize) { |
106 | | - gst().gst_base_sink_set_blocksize(this, blocksize); |
107 | | - } |
108 | | - public int getBlocksize() { |
109 | | - return gst().gst_base_sink_get_blocksize(this); |
110 | | - } |
111 | | - public ClockReturn waitClock(ClockTime time, /* GstClockTimeDiff */ Pointer jitter) { |
112 | | - return gst().gst_base_sink_wait_clock(this, time, jitter); |
113 | | - } |
114 | | - public FlowReturn waitEOS(ClockTime time, /* GstClockTimeDiff */ Pointer jitter) { |
115 | | - return gst().gst_base_sink_wait_eos(this, time, jitter); |
116 | | - } |
117 | | - |
118 | | - /** |
119 | | - * Signal emitted when this {@link BaseSink} has a {@link Buffer} ready. |
120 | | - * |
121 | | - * @see #connect(HANDOFF) |
122 | | - * @see #disconnect(HANDOFF) |
123 | | - */ |
124 | | - public static interface HANDOFF { |
125 | | - /** |
126 | | - * Called when an {@link BaseSink} has a {@link Buffer} ready. |
127 | | - * |
128 | | - * @param sink the sink which has a buffer ready. |
129 | | - * @param buffer the buffer for the data. |
130 | | - * @param pad the pad on the element. |
131 | | - */ |
132 | | - public void handoff(BaseSink sink, Buffer buffer, Pad pad); |
133 | | - } |
134 | 38 |
|
135 | | - private static class HANDOFFCallback implements GstAPI.GstCallback { |
136 | | - final HANDOFF listener; |
137 | | - public HANDOFFCallback(final HANDOFF listener) { |
138 | | - this.listener = listener; |
139 | | - //Native.setCallbackThreadInitializer(this, new CallbackThreadInitializer(true, false, "BaseSink Handoff")); |
140 | | - } |
141 | | - @SuppressWarnings("unused") |
142 | | - public void callback(BaseSink sink, Buffer buffer, Pad pad) { |
143 | | - listener.handoff(sink, buffer, pad); |
144 | | -// if (last) |
145 | | -// Native.detach(true); |
146 | | - } |
147 | | - } |
148 | | - /** |
149 | | - * Add a listener for the <code>handoff</code> signal on this sink |
150 | | - * |
151 | | - * @param listener The listener to be called when a {@link Buffer} is ready. |
152 | | - */ |
153 | | - public void connect(final HANDOFF listener) { |
154 | | - connect(HANDOFF.class, listener, new HANDOFFCallback(listener)); |
155 | | - } |
156 | | - /** |
157 | | - * Remove a listener for the <code>handoff</code> signal |
158 | | - * |
159 | | - * @param listener The listener that was previously added. |
160 | | - */ |
161 | | - public void disconnect(HANDOFF listener) { |
162 | | - disconnect(HANDOFF.class, listener); |
163 | | - } |
164 | | - |
165 | | - private static class PrerollHandoff implements GstAPI.GstCallback { |
166 | | - final PREROLL_HANDOFF listener; |
167 | | - public PrerollHandoff(final PREROLL_HANDOFF listener) { |
168 | | - this.listener = listener; |
169 | | - //Native.setCallbackThreadInitializer(this, new CallbackThreadInitializer(true, false, "BaseSink Preroll Handoff")); |
170 | | - } |
171 | | - @SuppressWarnings("unused") |
172 | | - public void callback(BaseSink sink, Buffer buffer, Pad pad) { |
173 | | - listener.prerollHandoff(sink, buffer, pad); |
174 | | -// if (last) |
175 | | -// Native.detach(true); |
176 | | - } |
177 | | - } |
178 | | - /** |
179 | | - * Signal emitted when this {@link BaseSink} has a {@link Buffer} ready. |
180 | | - * |
181 | | - * @see #connect(PREROLL_HANDOFF) |
182 | | - * @see #disconnect(PREROLL_HANDOFF) |
183 | | - */ |
184 | | - public static interface PREROLL_HANDOFF { |
185 | | - /** |
186 | | - * Called when a {@link BaseSink} has a {@link Buffer} ready. |
187 | | - * |
188 | | - * @param sink the sink instance. |
189 | | - * @param buffer the buffer that just has been received. |
190 | | - * @param pad the pad that received it. |
191 | | - */ |
192 | | - public void prerollHandoff(BaseSink sink, Buffer buffer, Pad pad); |
193 | | - } |
194 | | - /** |
195 | | - * Add a listener for the <code>preroll-handoff</code> signal. |
196 | | - * |
197 | | - * @param listener The listener to be called when a {@link Buffer} is ready. |
198 | | - */ |
199 | | - public void connect(final PREROLL_HANDOFF listener) { |
200 | | - connect(PREROLL_HANDOFF.class, listener, new PrerollHandoff(listener)); |
201 | | - } |
202 | | - /** |
203 | | - * Remove a listener for the <code>preroll-handoff</code> signal. |
204 | | - * |
205 | | - * @param listener The listener that was previously added. |
206 | | - */ |
207 | | - public void disconnect(PREROLL_HANDOFF listener) { |
208 | | - disconnect(PREROLL_HANDOFF.class, listener); |
209 | | - } |
| 39 | + // @TODO review - all properties are available by set / get mechanism |
| 40 | + // some other methods require the preroll lock, but we don't have a way to |
| 41 | + // access. Methods for subclasses should probably be protected. |
210 | 42 |
|
211 | | - /** |
212 | | - * Signal emitted when this {@link BaseSink} received a {@link ProposeAllocation} query. |
213 | | - * |
214 | | - * @see #setProposeAllocationHandler(ProposeAllocationHandler) |
215 | | - */ |
216 | | - public static interface ProposeAllocationHandler { |
217 | | - public boolean proposeAllocation(BaseSink sink, AllocationQuery query); |
218 | | - } |
219 | | - |
220 | | - /** |
221 | | - * Set a handler for the {@link ProposeAllocation} query on this sink |
222 | | - * |
223 | | - * @param handler The handler to be called when a {@link ProposeAllocation} is received. |
224 | | - */ |
225 | | - public void setProposeAllocationHandler(final ProposeAllocationHandler handler) { |
226 | | - GstBaseSinkStruct struct = new GstBaseSinkStruct(handle()); |
227 | | - struct.readField("element"); |
228 | | - GstBaseSinkClass basesinkClass = new GstBaseSinkClass(struct.element.object.object.g_type_instance.g_class.getPointer()); |
229 | | - basesinkClass.propose_allocation = new ProposeAllocation() { |
230 | | - @Override |
231 | | - public boolean callback(BaseSink sink, AllocationQuery query) { |
232 | | - return handler.proposeAllocation(sink, query); |
233 | | - } |
234 | | - }; |
235 | | - basesinkClass.writeField("propose_allocation"); |
236 | | - } |
| 43 | +// public FlowReturn doPreroll(MiniObject obj) { |
| 44 | +// return BASESINK_API.gst_base_sink_do_preroll(this, obj); |
| 45 | +// } |
| 46 | +// |
| 47 | +// public FlowReturn waitPreroll() { |
| 48 | +// return BASESINK_API.gst_base_sink_wait_preroll(this); |
| 49 | +// } |
| 50 | +// |
| 51 | +// public void setSync(boolean sync) { |
| 52 | +// BASESINK_API.gst_base_sink_set_sync(this, sync); |
| 53 | +// } |
| 54 | +// |
| 55 | +// public boolean isSync() { |
| 56 | +// return BASESINK_API.gst_base_sink_get_sync(this); |
| 57 | +// } |
| 58 | +// |
| 59 | +// public void setMaximumLateness(long lateness, TimeUnit units) { |
| 60 | +// BASESINK_API.gst_base_sink_set_max_lateness(this, units.toNanos(lateness)); |
| 61 | +// } |
| 62 | +// |
| 63 | +// public long getMaximumLateness(TimeUnit units) { |
| 64 | +// return units.convert(BASESINK_API.gst_base_sink_get_max_lateness(this), TimeUnit.NANOSECONDS); |
| 65 | +// } |
| 66 | +// |
| 67 | +// public void setQOSEnabled(boolean qos) { |
| 68 | +// BASESINK_API.gst_base_sink_set_qos_enabled(this, qos); |
| 69 | +// } |
| 70 | +// |
| 71 | +// public boolean isQOSEnabled() { |
| 72 | +// return BASESINK_API.gst_base_sink_is_qos_enabled(this); |
| 73 | +// } |
| 74 | +// |
| 75 | +// public void enableAsync(boolean enabled) { |
| 76 | +// BASESINK_API.gst_base_sink_set_async_enabled(this, enabled); |
| 77 | +// } |
| 78 | +// |
| 79 | +// public boolean isAsync() { |
| 80 | +// return BASESINK_API.gst_base_sink_is_async_enabled(this); |
| 81 | +// } |
| 82 | +// |
| 83 | +// public void setTsOffset(long offset) { |
| 84 | +// BASESINK_API.gst_base_sink_set_ts_offset(this, offset); |
| 85 | +// } |
| 86 | +// |
| 87 | +// public long getTsOffset() { |
| 88 | +// return BASESINK_API.gst_base_sink_get_ts_offset(this); |
| 89 | +// } |
| 90 | +// |
| 91 | +// public Buffer getLastBuffer() { |
| 92 | +// return BASESINK_API.gst_base_sink_get_last_buffer(this); |
| 93 | +// } |
| 94 | +// |
| 95 | +// public void enableLastBuffer(boolean enable) { |
| 96 | +// BASESINK_API.gst_base_sink_set_last_buffer_enabled(this, enable); |
| 97 | +// } |
| 98 | +// |
| 99 | +// public boolean isLastBufferEnabled() { |
| 100 | +// return BASESINK_API.gst_base_sink_is_last_buffer_enabled(this); |
| 101 | +// } |
| 102 | +// |
| 103 | +// public boolean queryLatency(boolean live, boolean upstream_live, ClockTime min_latency, ClockTime max_latency) { |
| 104 | +// return BASESINK_API.gst_base_sink_query_latency(this, live, upstream_live, min_latency, max_latency); |
| 105 | +// } |
| 106 | +// |
| 107 | +// public ClockTime getLatency() { |
| 108 | +// return BASESINK_API.gst_base_sink_get_latency(this); |
| 109 | +// } |
| 110 | +// |
| 111 | +// public void setRenderDelay(ClockTime delay) { |
| 112 | +// BASESINK_API.gst_base_sink_set_render_delay(this, delay); |
| 113 | +// } |
| 114 | +// |
| 115 | +// public ClockTime getRenderDelay() { |
| 116 | +// return BASESINK_API.gst_base_sink_get_render_delay(this); |
| 117 | +// } |
| 118 | +// |
| 119 | +// public void setBlocksize(int blocksize) { |
| 120 | +// BASESINK_API.gst_base_sink_set_blocksize(this, blocksize); |
| 121 | +// } |
| 122 | +// |
| 123 | +// public int getBlocksize() { |
| 124 | +// return BASESINK_API.gst_base_sink_get_blocksize(this); |
| 125 | +// } |
| 126 | +// |
| 127 | +// public ClockReturn waitClock(ClockTime time, /* GstClockTimeDiff */ Pointer jitter) { |
| 128 | +// return BASESINK_API.gst_base_sink_wait_clock(this, time, jitter); |
| 129 | +// } |
| 130 | +// |
| 131 | +// public FlowReturn waitEOS(ClockTime time, /* GstClockTimeDiff */ Pointer jitter) { |
| 132 | +// return BASESINK_API.gst_base_sink_wait_eos(this, time, jitter); |
| 133 | +// } |
237 | 134 |
|
| 135 | +// @TODO work out strategy for overriding methods |
| 136 | +// |
| 137 | +// /** |
| 138 | +// * Signal emitted when this {@link BaseSink} received a {@link ProposeAllocation} query. |
| 139 | +// * |
| 140 | +// * @see #setProposeAllocationHandler(ProposeAllocationHandler) |
| 141 | +// */ |
| 142 | +// public static interface ProposeAllocationHandler { |
| 143 | +// public boolean proposeAllocation(BaseSink sink, AllocationQuery query); |
| 144 | +// } |
| 145 | +// |
| 146 | +// /** |
| 147 | +// * Set a handler for the {@link ProposeAllocation} query on this sink |
| 148 | +// * |
| 149 | +// * @param handler The handler to be called when a {@link ProposeAllocation} is received. |
| 150 | +// */ |
| 151 | +// public void setProposeAllocationHandler(final ProposeAllocationHandler handler) { |
| 152 | +// GstBaseSinkStruct struct = new GstBaseSinkStruct(handle()); |
| 153 | +// struct.readField("element"); |
| 154 | +// GstBaseSinkClass basesinkClass = new GstBaseSinkClass(struct.element.object.object.g_type_instance.g_class.getPointer()); |
| 155 | +// basesinkClass.propose_allocation = new ProposeAllocation() { |
| 156 | +// @Override |
| 157 | +// public boolean callback(BaseSink sink, AllocationQuery query) { |
| 158 | +// return handler.proposeAllocation(sink, query); |
| 159 | +// } |
| 160 | +// }; |
| 161 | +// basesinkClass.writeField("propose_allocation"); |
| 162 | +// } |
238 | 163 | } |
0 commit comments