1
1
/*
2
- * Copyright (C) 2019 Neil C Smith
2
+ * Copyright (C) 2020 Neil C Smith
3
3
* Copyright (C) 2018 Antonio Morales
4
4
* Copyright (C) 2014 Tom Greenwood <[email protected] >
5
5
* Copyright (C) 2009 Tamas Korodi <[email protected] >
28
28
import com .sun .jna .Pointer ;
29
29
import java .util .HashSet ;
30
30
import java .util .Set ;
31
+ import org .freedesktop .gstreamer .glib .NativeFlags ;
31
32
import org .freedesktop .gstreamer .glib .Natives ;
32
33
33
34
import org .freedesktop .gstreamer .lowlevel .GstAPI .GstCallback ;
80
81
public class Pad extends GstObject {
81
82
82
83
public static final String GTYPE_NAME = "GstPad" ;
83
-
84
+
84
85
private static final int EVENT_HAS_INFO_MASK = GstPadAPI .GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM | GstPadAPI .GST_PAD_PROBE_TYPE_EVENT_UPSTREAM ;
85
86
private final Handle handle ;
86
87
@@ -95,7 +96,7 @@ private Pad(Handle handle, boolean needRef) {
95
96
super (handle , needRef );
96
97
this .handle = handle ;
97
98
}
98
-
99
+
99
100
/**
100
101
* Creates a new pad with the given name in the given direction. If name is
101
102
* null, a guaranteed unique name (across all pads) will be assigned.
@@ -190,7 +191,7 @@ public Pad getPeer() {
190
191
* filter contains the caps accepted by downstream in the preferred order.
191
192
* filter might be NULL but if it is not NULL the returned caps will be a
192
193
* subset of filter .
193
- *
194
+ *
194
195
* @param filter Caps to filter by, or null
195
196
* @return the {@link Caps} of the peer pad, or null if there is no peer
196
197
* pad.
@@ -386,6 +387,85 @@ public void disconnect(UNLINKED listener) {
386
387
disconnect (UNLINKED .class , listener );
387
388
}
388
389
390
+ /**
391
+ * Be notified of different states of pads. The provided callback is called
392
+ * for every state that matches mask.
393
+ * <p>
394
+ * Probes are called in groups: First {@link PadProbeType#BLOCK} probes are
395
+ * called, then others, then finally {@link PadProbeType#IDLE}. The only
396
+ * exception here are IDLE probes that are called immediately if the pad is
397
+ * already idle while calling addProbe(). In each of the groups, probes are
398
+ * called in the order in which they were added.
399
+ *
400
+ * @param mask set of mask flags for probe - common options are fields of
401
+ * {@link PadProbeType}
402
+ * @param callback callback that will be called with notifications of the
403
+ * pad state
404
+ */
405
+ public void addProbe (final Set <PadProbeType > mask , PROBE callback ) {
406
+ addProbe (NativeFlags .toInt (mask ), callback );
407
+ }
408
+
409
+ /**
410
+ * Be notified of different states of pads. The provided callback is called
411
+ * for every state that matches mask.
412
+ * <p>
413
+ * Probes are called in groups: First {@link PadProbeType#BLOCK} probes are
414
+ * called, then others, then finally {@link PadProbeType#IDLE}. The only
415
+ * exception here are IDLE probes that are called immediately if the pad is
416
+ * already idle while calling addProbe(). In each of the groups, probes are
417
+ * called in the order in which they were added.
418
+ *
419
+ * @param mask mask flag for probe
420
+ * @param callback callback that will be called with notifications of the
421
+ * pad state
422
+ */
423
+ public void addProbe (PadProbeType mask , PROBE callback ) {
424
+ addProbe (mask .intValue (), callback );
425
+ }
426
+
427
+ synchronized void addProbe (int mask , PROBE callback ) {
428
+ final GstPadAPI .PadProbeCallback probe = new GstPadAPI .PadProbeCallback () {
429
+ @ Override
430
+ public PadProbeReturn callback (Pad pad , GstPadProbeInfo probeInfo , Pointer user_data ) {
431
+ PadProbeInfo info = new PadProbeInfo (probeInfo );
432
+ PadProbeReturn ret = callback .probeCallback (pad , info );
433
+ info .invalidate ();
434
+ if (ret == PadProbeReturn .REMOVE ) {
435
+ // don't want handle to try and remove in GCallback::disconnect
436
+ // @TODO move to Map<PROBE, NativeLong> of probes over callback
437
+ handle .probes .remove (probeInfo .id );
438
+ removeCallback (PROBE .class , callback );
439
+ }
440
+ return ret ;
441
+ }
442
+ };
443
+
444
+ NativeLong id = handle .addProbe (mask , probe );
445
+ if (id .longValue () == 0 ) {
446
+ // the Probe was an IDLE-Probe and it was already handled synchronously in handle.addProbe,
447
+ // so no Callback needs to be registered
448
+ return ;
449
+ }
450
+
451
+ GCallback cb = new GCallback (id , probe ) {
452
+ @ Override
453
+ protected void disconnect () {
454
+ handle .removeProbe (id );
455
+ }
456
+ };
457
+ addCallback (PROBE .class , callback , cb );
458
+ }
459
+
460
+ /**
461
+ * Remove the provided probe callback from the Pad.
462
+ *
463
+ * @param callback callback to remove
464
+ */
465
+ public synchronized void removeProbe (PROBE callback ) {
466
+ removeCallback (PROBE .class , callback );
467
+ }
468
+
389
469
public void addEventProbe (final EVENT_PROBE listener ) {
390
470
final int mask = GstPadAPI .GST_PAD_PROBE_TYPE_EVENT_BOTH | GstPadAPI .GST_PAD_PROBE_TYPE_EVENT_FLUSH ;
391
471
addEventProbe (listener , mask );
@@ -394,16 +474,20 @@ public void addEventProbe(final EVENT_PROBE listener) {
394
474
synchronized void addEventProbe (final EVENT_PROBE listener , final int mask ) {
395
475
final GstPadAPI .PadProbeCallback probe = new GstPadAPI .PadProbeCallback () {
396
476
public PadProbeReturn callback (Pad pad , GstPadProbeInfo probeInfo , Pointer user_data ) {
397
- // System.out.println("CALLBACK " + probeInfo.padProbeType);
398
477
if ((probeInfo .padProbeType & mask ) != 0 ) {
399
478
Event event = null ;
400
479
if ((probeInfo .padProbeType & EVENT_HAS_INFO_MASK ) != 0 ) {
401
480
event = GSTPAD_API .gst_pad_probe_info_get_event (probeInfo );
402
481
}
403
- return listener .eventReceived (pad , event );
482
+ PadProbeReturn ret = listener .eventReceived (pad , event );
483
+ if (ret == PadProbeReturn .REMOVE ) {
484
+ // don't want handle to try and remove in GCallback::disconnect
485
+ handle .probes .remove (probeInfo .id );
486
+ removeCallback (EVENT_PROBE .class , listener );
487
+ }
488
+ return ret ;
404
489
}
405
490
406
- //We have to negate the return value to keep consistency with gstreamer's API
407
491
return PadProbeReturn .OK ;
408
492
}
409
493
};
@@ -434,10 +518,15 @@ public synchronized void addDataProbe(final DATA_PROBE listener) {
434
518
public PadProbeReturn callback (Pad pad , GstPadProbeInfo probeInfo , Pointer user_data ) {
435
519
if ((probeInfo .padProbeType & GstPadAPI .GST_PAD_PROBE_TYPE_BUFFER ) != 0 ) {
436
520
Buffer buffer = GSTPAD_API .gst_pad_probe_info_get_buffer (probeInfo );
437
- return listener .dataReceived (pad , buffer );
521
+ PadProbeReturn ret = listener .dataReceived (pad , buffer );
522
+ if (ret == PadProbeReturn .REMOVE ) {
523
+ // don't want handle to try and remove in GCallback::disconnect
524
+ handle .probes .remove (probeInfo .id );
525
+ removeCallback (DATA_PROBE .class , listener );
526
+ }
527
+ return ret ;
438
528
}
439
529
440
- //We have to negate the return value to keep consistency with gstreamer's API
441
530
return PadProbeReturn .OK ;
442
531
}
443
532
};
@@ -609,7 +698,6 @@ public PadTemplate getTemplate() {
609
698
public boolean hasCurrentCaps () {
610
699
return GSTPAD_API .gst_pad_has_current_caps (this );
611
700
}
612
-
613
701
614
702
/**
615
703
* Signal emitted when new this {@link Pad} is linked to another {@link Pad}
@@ -647,31 +735,55 @@ public static interface UNLINKED {
647
735
}
648
736
649
737
/**
650
- * Signal emitted when an event passes through this <tt>Pad</tt>.
738
+ * Callback used by
739
+ * {@link #addProbe(java.util.EnumSet, org.freedesktop.gstreamer.Pad.PROBE)}
740
+ */
741
+ public static interface PROBE {
742
+
743
+ /**
744
+ * Callback used by
745
+ * {@link #addProbe(java.util.EnumSet, org.freedesktop.gstreamer.Pad.PROBE)}.
746
+ * Gets called to notify about the current blocking type.
747
+ * <p>
748
+ * <b>The PadProbeInfo and any Buffer, Event or Query referenced from
749
+ * it, is only valid for the duration of the callback.</b>
750
+ *
751
+ * @param pad Pad that is blocked
752
+ * @param info PadProbeInfo with access to underlying data
753
+ * @return PadProbeReturn value
754
+ */
755
+ public PadProbeReturn probeCallback (Pad pad , PadProbeInfo info );
756
+
757
+ }
758
+
759
+ /**
760
+ * Probe for listening when an event passes through this Pad.
651
761
*
652
762
* @see #addEventProbe(EVENT_PROBE)
653
763
* @see #removeEventProbe(EVENT_PROBE)
654
764
*/
655
765
public static interface EVENT_PROBE {
656
766
657
767
public PadProbeReturn eventReceived (Pad pad , Event event );
768
+
658
769
}
659
770
660
771
/**
661
- * Signal emitted when new data is available on the {@link Pad}
772
+ * Probe for listening when new data is available on the Pad.
662
773
*
663
774
* @see #addDataProbe(DATA_PROBE)
664
775
* @see #removeDataProbe(DATA_PROBE)
665
776
*/
666
777
public static interface DATA_PROBE {
667
778
668
779
public PadProbeReturn dataReceived (Pad pad , Buffer buffer );
780
+
669
781
}
670
-
782
+
671
783
private static class Handle extends GstObject .Handle {
672
-
784
+
673
785
private final Set <NativeLong > probes ;
674
-
786
+
675
787
private Handle (GstPadPtr ptr , boolean ownsHandle ) {
676
788
super (ptr , ownsHandle );
677
789
probes = new HashSet <>();
@@ -681,21 +793,21 @@ private Handle(GstPadPtr ptr, boolean ownsHandle) {
681
793
protected GstPadPtr getPointer () {
682
794
return (GstPadPtr ) super .getPointer ();
683
795
}
684
-
796
+
685
797
private synchronized NativeLong addProbe (int mask , GstPadAPI .PadProbeCallback probe ) {
686
798
NativeLong id = GSTPAD_API .gst_pad_add_probe (getPointer (), mask , probe , null , null );
687
799
if (id .longValue () != 0 ) {
688
800
probes .add (id );
689
801
}
690
802
return id ;
691
803
}
692
-
804
+
693
805
private synchronized void removeProbe (NativeLong id ) {
694
806
if (probes .remove (id )) {
695
807
GSTPAD_API .gst_pad_remove_probe (getPointer (), id );
696
808
}
697
809
}
698
-
810
+
699
811
private synchronized void clearProbes () {
700
812
probes .forEach (id -> GSTPAD_API .gst_pad_remove_probe (getPointer (), id ));
701
813
probes .clear ();
@@ -712,7 +824,6 @@ public void dispose() {
712
824
clearProbes ();
713
825
super .dispose ();
714
826
}
715
-
716
-
827
+
717
828
}
718
829
}
0 commit comments