diff --git a/gst/constants.go b/gst/constants.go index fb0fa5e9..cc6e154e 100644 --- a/gst/constants.go +++ b/gst/constants.go @@ -1052,3 +1052,46 @@ const ( TypeFindNearlyCertain TypeFindProbability = C.GST_TYPE_FIND_NEARLY_CERTAIN // (99) – nearly certain that a type was detected. TypeFindMaximum TypeFindProbability = C.GST_TYPE_FIND_MAXIMUM // (100) – very certain a type was detected. ) + +// MpegtsSectionType represents a GstMpegtsSectionType +type MpegtsSectionType int + +// Type castings of GstMpegtsSectionType +// For more information see: https://gstreamer.freedesktop.org/documentation/mpegts/gstmpegtssection.html?gi-language=c#GstMpegtsSectionType +const ( + MpegtsSectionUnknown MpegtsSectionType = C.GST_MPEGTS_SECTION_UNKNOWN // (0) – Unknown section type + MpegtsSectionPAT MpegtsSectionType = C.GST_MPEGTS_SECTION_PAT // (1) – Program Association Table (ISO/IEC 13818-1) + MpegtsSectionPMT MpegtsSectionType = C.GST_MPEGTS_SECTION_PMT // (2) – Program Map Table (ISO/IEC 13818-1) + MpegtsSectionCAT MpegtsSectionType = C.GST_MPEGTS_SECTION_CAT // (3) – Conditional Access Table (ISO/IEC 13818-1) + MpegtsSectionTSDT MpegtsSectionType = C.GST_MPEGTS_SECTION_TSDT // (4) – Transport Stream Description Table (ISO/IEC 13818-1) + MpegtsSectionEIT MpegtsSectionType = C.GST_MPEGTS_SECTION_EIT // (5) – Event Information Table (EN 300 468) + MpegtsSectionNIT MpegtsSectionType = C.GST_MPEGTS_SECTION_NIT // (6) – Network Information Table (ISO/IEC 13818-1 / EN 300 468) + MpegtsSectionBAT MpegtsSectionType = C.GST_MPEGTS_SECTION_BAT // (7) – Bouquet Association Table ((EN 300 468) + MpegtsSectionSDT MpegtsSectionType = C.GST_MPEGTS_SECTION_SDT // (8) – Service Description Table (EN 300 468) + MpegtsSectionTDT MpegtsSectionType = C.GST_MPEGTS_SECTION_TDT // (9) – Time and Date Table (EN 300 468) + MpegtsSectionTOT MpegtsSectionType = C.GST_MPEGTS_SECTION_TOT // (10) – Time Offset Table (EN 300 468) + MpegtsSectionSIT MpegtsSectionType = C.GST_MPEGTS_SECTION_SIT // (11) – Selection Information Table (EN 300 468) (Since: 1.20) + MpegtsSectionATSCTVCT MpegtsSectionType = C.GST_MPEGTS_SECTION_ATSC_TVCT // (12) – ATSC Terrestrial Virtual Channel Table (A65) + MpegtsSectionATSCCVCT MpegtsSectionType = C.GST_MPEGTS_SECTION_ATSC_CVCT // (13) – ATSC Cable Virtual Channel Table (A65) + MpegtsSectionATSCMGT MpegtsSectionType = C.GST_MPEGTS_SECTION_ATSC_MGT // (14) – ATSC Master Guide Table (A65) + MpegtsSectionATSCETT MpegtsSectionType = C.GST_MPEGTS_SECTION_ATSC_ETT // (15) – ATSC Extended Text Table (A65) + MpegtsSectionATSCEIT MpegtsSectionType = C.GST_MPEGTS_SECTION_ATSC_EIT // (16) – ATSC Event Information Table (A65) + MpegtsSectionATSCSTT MpegtsSectionType = C.GST_MPEGTS_SECTION_ATSC_STT // (17) – ATSC System Time Table (A65) + MpegtsSectionATSCRRT MpegtsSectionType = C.GST_MPEGTS_SECTION_ATSC_RRT // (18) – ATSC Rating Region Table (A65) + MpegtsSectionSCTESIT MpegtsSectionType = C.GST_MPEGTS_SECTION_SCTE_SIT // (19) - SCTE Splice Information Table (SCTE-35) +) + +// MpegtsSCTESpliceCommandType represents a GstMpegtsSCTESpliceCommandType +type MpegtsSCTESpliceCommandType int + +// Type castig of GstMpegtsSCTESpliceCommandType +// For more informartion see: https://gstreamer.freedesktop.org/documentation/mpegts/gst-scte-section.html?gi-language=c + +const ( + MpegtsSCTESpliceCommandNull MpegtsSCTESpliceCommandType = C.GST_MTS_SCTE_SPLICE_COMMAND_NULL // (0) + MpegtsSCTESpliceCommandSchedule MpegtsSCTESpliceCommandType = C.GST_MTS_SCTE_SPLICE_COMMAND_SCHEDULE // (4) + MpegtsSCTESpliceCommandInsert MpegtsSCTESpliceCommandType = C.GST_MTS_SCTE_SPLICE_COMMAND_INSERT // (5) + MpegtsSCTESpliceCommandTime MpegtsSCTESpliceCommandType = C.GST_MTS_SCTE_SPLICE_COMMAND_TIME // (6) + MpegtsSCTESpliceCommandBandwidth MpegtsSCTESpliceCommandType = C.GST_MTS_SCTE_SPLICE_COMMAND_BANDWIDTH // (7) + MpegtsSCTESpliceCommandPrivate MpegtsSCTESpliceCommandType = C.GST_MTS_SCTE_SPLICE_COMMAND_PRIVATE // (255) +) diff --git a/gst/gst.go.c b/gst/gst.go.c index 46684c23..d153ae49 100644 --- a/gst/gst.go.c +++ b/gst/gst.go.c @@ -25,6 +25,7 @@ GstMemory * toGstMemory (void *p) { re GstMessage * toGstMessage (void *p) { return (GST_MESSAGE(p)); } GstMeta * toGstMeta (void *p) { return (GST_META_CAST(p)); } GstMiniObject * toGstMiniObject (void *p) { return (GST_MINI_OBJECT(p)); } +GstMpegtsSection * toGstMpegtsSection (void *p) { return (GST_MPEGTS_SECTION(p)); } GstObject * toGstObject (void *p) { return (GST_OBJECT(p)); } GstPad * toGstPad (void *p) { return (GST_PAD(p)); } GstPadTemplate * toGstPadTemplate (void *p) { return (GST_PAD_TEMPLATE(p)); } @@ -166,6 +167,9 @@ GstSample * getSampleValue (GValue * val) return gst_value_get_sample(val); } +/* MpegtsSection Utilities */ +GstMpegtsSection * mpegtsSectionRef (GstMpegtsSection * section) { return gst_mpegts_section_ref(section); } +void mpegtsSectionUnref (GstMpegtsSection * section) { gst_mpegts_section_unref(section); } /* Misc */ diff --git a/gst/gst.go.h b/gst/gst.go.h index 4602fe8e..a6083cc1 100644 --- a/gst/gst.go.h +++ b/gst/gst.go.h @@ -1,11 +1,14 @@ #ifndef __GST_GO_H__ #define __GST_GO_H__ +#define GST_USE_UNSTABLE_API // mpegts APIs are unstable + #include #include #include #include #include +#include typedef struct _PadDestroyNotifyInfo { gpointer pad_ptr; @@ -41,6 +44,7 @@ extern GstMemory * toGstMemory (void * extern GstMessage * toGstMessage (void *p); extern GstMeta * toGstMeta (void *p); extern GstMiniObject * toGstMiniObject (void *p); +extern GstMpegtsSection * toGstMpegtsSection (void *p); extern GstObject * toGstObject (void *p); extern GstPad * toGstPad (void *p); extern GstPadTemplate * toGstPadTemplate (void *p); @@ -133,6 +137,9 @@ extern gboolean gstElementIsURIHandler (GstElement * elem); extern GstTocSetter * toTocSetter (GstElement * elem); extern GstTagSetter * toTagSetter (GstElement *elem); +/* MpegtsSection Utilities */ +extern GstMpegtsSection * mpegtsSectionRef (GstMpegtsSection * section); +extern void mpegtsSectionUnref (GstMpegtsSection * section); /* Misc */ diff --git a/gst/gst_event.go b/gst/gst_event.go index 8ee8f143..a2dc4acb 100644 --- a/gst/gst_event.go +++ b/gst/gst_event.go @@ -315,6 +315,16 @@ func (e *Event) ParseTOCSelect() string { return C.GoString((*C.char)(unsafe.Pointer(idPtr))) } +// ParseMpegtsSection parses a MPEG TS section event +func (e *Event) ParseMpegtsSection() *MpegtsSection { + ptr := C.gst_event_parse_mpegts_section(e.Instance()) + if ptr == nil { + return nil + } + + return FromGstMpegtsSectionUnsafeFull(unsafe.Pointer(ptr)) +} + // Ref increases the ref count on the event by one. func (e *Event) Ref() *Event { C.gst_event_ref(e.Instance()) diff --git a/gst/gst_message.go b/gst/gst_message.go index 91fcfd88..8ae588e1 100644 --- a/gst/gst_message.go +++ b/gst/gst_message.go @@ -506,3 +506,13 @@ func (m *Message) ParseHaveContext() *Context { C.gst_message_parse_have_context(m.Instance(), &ctx) return FromGstContextUnsafeFull(unsafe.Pointer(ctx)) } + +// ParseMpegtsSection parses a MPEG TS section message +func (m *Message) ParseMpegtsSection() *MpegtsSection { + ptr := C.gst_message_parse_mpegts_section(m.Instance()) + if ptr == nil { + return nil + } + + return FromGstMpegtsSectionUnsafeFull(unsafe.Pointer(ptr)) +} diff --git a/gst/gst_mpegts_section.go b/gst/gst_mpegts_section.go new file mode 100644 index 00000000..344719eb --- /dev/null +++ b/gst/gst_mpegts_section.go @@ -0,0 +1,154 @@ +package gst + +/* +#include "gst.go.h" +*/ +import "C" +import ( + "runtime" + "unsafe" +) + +// MpegtsSection is a go representation of a GstMpegtsSection +type MpegtsSection struct { + section *C.GstMpegtsSection +} + +// FromGstMpegtsSectionUnsafeFull wraps the given unsafe.Pointer in a MpegtsSection. No ref is taken +// and a finalizer is placed on the resulting object. +func FromGstMpegtsSectionUnsafeFull(section unsafe.Pointer) *MpegtsSection { + gosection := ToGstMpegtsSection(section) + runtime.SetFinalizer(gosection, (*MpegtsSection).Unref) + return gosection +} + +// ToGstMpegtsSection converts the given pointer into a MpegtsSection without affecting the ref count or +// placing finalizers. +func ToGstMpegtsSection(section unsafe.Pointer) *MpegtsSection { + return wrapMpegtsSection((*C.GstMpegtsSection)(section)) +} + +// Instance returns the underlying GstMpegtsSection instance. +func (m *MpegtsSection) Instance() *C.GstMpegtsSection { + return C.toGstMpegtsSection(unsafe.Pointer(m.section)) +} + +// Unref will call `gst_mpegts_section_unref` on the underlying GstMpegtsSection, freeing it from memory. +func (m *MpegtsSection) Unref() { C.mpegtsSectionUnref(m.Instance()) } + +// Ref will increase the ref count on this MpegtsSection. This increases the total amount of times +// Unref needs to be called before the object is freed from memory. It returns the underlying +// MpegtsSection object for convenience. +func (m *MpegtsSection) Ref() *MpegtsSection { + C.mpegtsSectionRef(m.Instance()) + return m +} + +func (m *MpegtsSection) SectionType() MpegtsSectionType { + return MpegtsSectionType(m.Instance().section_type) +} + +func (m *MpegtsSection) GetSCTESIT() *MpegtsSCTESIT { + scteSit := C.gst_mpegts_section_get_scte_sit(m.Instance()) + if scteSit == nil { + return nil + } + + ret := ToGstMpegtsSCTESIT(unsafe.Pointer(scteSit)) + + // Take a reference on the underlying GstMpegtsSection to ensure that the parsed table stays vaild until MpegtsSCTESIT gets finalized + ret.section = m + + return ret +} + +// MpegtsSCTESIT is a go representation of a SCTE SIT MpegTS section +type MpegtsSCTESIT struct { + scteSit *C.GstMpegtsSCTESIT + section *MpegtsSection // keep a reference to the underlying MpegTSSection object to make sure the GstMpegtsSCTESIT doesn't get freed as it is not independently reference counted +} + +// ToGstMpegtsSCTESIT converts the given pointer into a MpegtsSCTESIT without affecting the ref count or +// placing finalizers (GstMpegtsSCTESIT is not a reference counted object) +func ToGstMpegtsSCTESIT(scteSit unsafe.Pointer) *MpegtsSCTESIT { + return wrapMpegtsSCTESIT((*C.GstMpegtsSCTESIT)(scteSit)) +} + +// Instance returns the underlying GstMpegtsSCTESIT instance. +func (m *MpegtsSCTESIT) Instance() *C.GstMpegtsSCTESIT { + return m.scteSit +} + +func (m *MpegtsSCTESIT) SpliceCommandType() MpegtsSCTESpliceCommandType { + return MpegtsSCTESpliceCommandType(m.Instance().splice_command_type) +} + +func (m *MpegtsSCTESIT) SpliceTimeSpecified() bool { + return gobool(m.Instance().splice_time_specified) +} + +func (m *MpegtsSCTESIT) SpliceTime() uint64 { + return uint64(m.Instance().splice_time) +} + +func (m *MpegtsSCTESIT) Splices() []*MpegtsSCTESpliceEvent { + if m.Instance().splices == nil { + return nil + } + + ret := []*MpegtsSCTESpliceEvent{} + for i := uint(0); i < uint(m.Instance().splices.len); i++ { + ptr := *(**C.GstMpegtsSCTESpliceEvent)(unsafe.Pointer(uintptr(unsafe.Pointer(m.Instance().splices.pdata)) + unsafe.Sizeof(*m.Instance().splices.pdata)*uintptr(i))) + obj := ToGstMpegtsSCTESpliceEvent(unsafe.Pointer(ptr)) + obj.scteSit = m + + ret = append(ret, obj) + } + + return ret +} + +// MpegtsSCTESpliceEvent is a go representation of a SCTE Splice event +type MpegtsSCTESpliceEvent struct { + spliceEv *C.GstMpegtsSCTESpliceEvent + scteSit *MpegtsSCTESIT // keep a reference to the underlying MpegtsSCTESIT to make sure the GstMpegtsSCTESIT doesn't get freed as it is not independently reference counted +} + +// ToMpegtsSCTESpliceEvent converts the given pointer into a MpegtsSCTESpliceEvent without affecting the ref count or +// placing finalizers (GstMpegtsSCTESpliceEvent is not a reference counted object) +func ToGstMpegtsSCTESpliceEvent(spliceEv unsafe.Pointer) *MpegtsSCTESpliceEvent { + return wrapMpegtsSCTESpliceEvent((*C.GstMpegtsSCTESpliceEvent)(spliceEv)) +} + +// Instance returns the underlying GstMpegtsSCTESIT instance. +func (ev *MpegtsSCTESpliceEvent) Instance() *C.GstMpegtsSCTESpliceEvent { + return ev.spliceEv +} + +func (ev *MpegtsSCTESpliceEvent) SpliceEventId() uint32 { + return uint32(ev.Instance().splice_event_id) +} + +func (ev *MpegtsSCTESpliceEvent) SpliceEventCancelIndicator() bool { + return gobool(ev.Instance().splice_event_cancel_indicator) +} + +func (ev *MpegtsSCTESpliceEvent) OutOfNetworkIndicator() bool { + return gobool(ev.Instance().out_of_network_indicator) +} + +func (ev *MpegtsSCTESpliceEvent) SpliceImmediateFlag() bool { + return gobool(ev.Instance().splice_immediate_flag) +} + +func (ev *MpegtsSCTESpliceEvent) ProgramSpliceFlag() bool { + return gobool(ev.Instance().program_splice_flag) +} + +func (ev *MpegtsSCTESpliceEvent) ProgramSpliceTimeSpecified() bool { + return gobool(ev.Instance().program_splice_time_specified) +} + +func (ev *MpegtsSCTESpliceEvent) ProgramSpliceTime() uint64 { + return uint64(ev.Instance().program_splice_time) +} diff --git a/gst/gst_pad.go b/gst/gst_pad.go index 98fcf1eb..379d5f63 100644 --- a/gst/gst_pad.go +++ b/gst/gst_pad.go @@ -887,7 +887,7 @@ func (p *Pad) SetEventFullFunction(f PadEventFullFunc) { notifyInfo := p.registerCallback(f, padEventFullFuncs) C.gst_pad_set_event_full_function_full( p.Instance(), - C.GstPadActivateFunction(C.cgoGstPadEventFullFunction), + C.GstPadEventFullFunction(C.cgoGstPadEventFullFunction), (C.gpointer)(unsafe.Pointer(notifyInfo)), C.GDestroyNotify(C.cgoPadFuncDestroyNotify), ) @@ -903,7 +903,7 @@ func (p *Pad) SetEventFunction(f PadEventFunc) { notifyInfo := p.registerCallback(f, padEventFuncs) C.gst_pad_set_event_function_full( p.Instance(), - C.GstPadActivateFunction(C.cgoGstPadEventFunction), + C.GstPadEventFunction(C.cgoGstPadEventFunction), (C.gpointer)(unsafe.Pointer(notifyInfo)), C.GDestroyNotify(C.cgoPadFuncDestroyNotify), ) diff --git a/gst/gst_pad_exports.go b/gst/gst_pad_exports.go index 0a123ea0..c258471e 100644 --- a/gst/gst_pad_exports.go +++ b/gst/gst_pad_exports.go @@ -80,7 +80,6 @@ func goGstPadChainListFunction(pad *C.GstPad, parent *C.GstObject, list *C.GstBu func goGstPadEventFullFunction(pad *C.GstPad, parent *C.GstObject, event *C.GstEvent) C.GstFlowReturn { f := padEventFullFuncs.FuncForPad(unsafe.Pointer(pad)).(PadEventFullFunc) ev := FromGstEventUnsafeFull(unsafe.Pointer(event)) - defer ev.Unref() return C.GstFlowReturn(f( wrapPad(toGObject(unsafe.Pointer(pad))), getParent(parent), @@ -92,7 +91,6 @@ func goGstPadEventFullFunction(pad *C.GstPad, parent *C.GstObject, event *C.GstE func goGstPadEventFunction(pad *C.GstPad, parent *C.GstObject, event *C.GstEvent) C.gboolean { f := padEventFuncs.FuncForPad(unsafe.Pointer(pad)).(PadEventFunc) ev := FromGstEventUnsafeFull(unsafe.Pointer(event)) - defer ev.Unref() return gboolean(f( wrapPad(toGObject(unsafe.Pointer(pad))), getParent(parent), diff --git a/gst/gst_wrappers.go b/gst/gst_wrappers.go index fa20121e..5c6eaf5f 100644 --- a/gst/gst_wrappers.go +++ b/gst/gst_wrappers.go @@ -62,6 +62,18 @@ func wrapAllocationParams(obj *C.GstAllocationParams) *AllocationParams { return &AllocationParams{ptr: obj} } +func wrapMpegtsSCTESIT(scteSit *C.GstMpegtsSCTESIT) *MpegtsSCTESIT { + return &MpegtsSCTESIT{scteSit: scteSit} +} + +func wrapMpegtsSCTESpliceEvent(spliceEv *C.GstMpegtsSCTESpliceEvent) *MpegtsSCTESpliceEvent { + return &MpegtsSCTESpliceEvent{spliceEv: spliceEv} +} + +func wrapMpegtsSection(section *C.GstMpegtsSection) *MpegtsSection { + return &MpegtsSection{section: section} +} + // Marshallers func registerMarshalers() { diff --git a/gst/pkg_config.go b/gst/pkg_config.go index 4ffb2d64..7702c14d 100644 --- a/gst/pkg_config.go +++ b/gst/pkg_config.go @@ -1,8 +1,8 @@ package gst /* -#cgo pkg-config: gstreamer-1.0 gstreamer-controller-1.0 +#cgo pkg-config: gstreamer-1.0 gstreamer-controller-1.0 gstreamer-mpegts-1.0 #cgo CFLAGS: -Wno-deprecated-declarations -Wno-format-security -g -Wall -Wno-unused-variable -#cgo LDFLAGS: -lm +#cgo LDFLAGS: -lm -lgstmpegts-1.0 */ import "C"