diff --git a/app/meson.build b/app/meson.build index 7749d664..82105876 100644 --- a/app/meson.build +++ b/app/meson.build @@ -30,6 +30,7 @@ src = [ 'src/server.c', 'src/version.c', 'src/video_buffer.c', + 'src/trait/packet_source.c', 'src/util/acksync.c', 'src/util/bytebuf.c', 'src/util/file.c', diff --git a/app/src/trait/packet_source.c b/app/src/trait/packet_source.c new file mode 100644 index 00000000..df678e16 --- /dev/null +++ b/app/src/trait/packet_source.c @@ -0,0 +1,70 @@ +#include "packet_source.h" + +void +sc_packet_source_init(struct sc_packet_source *source) { + source->sink_count = 0; +} + +void +sc_packet_source_add_sink(struct sc_packet_source *source, + struct sc_packet_sink *sink) { + assert(source->sink_count < SC_PACKET_SOURCE_MAX_SINKS); + assert(sink); + assert(sink->ops); + source->sinks[source->sink_count++] = sink; +} + +static void +sc_packet_source_sinks_close_firsts(struct sc_packet_source *source, + unsigned count) { + while (count) { + struct sc_packet_sink *sink = source->sinks[--count]; + sink->ops->close(sink); + } +} + +bool +sc_packet_source_sinks_open(struct sc_packet_source *source, + const AVCodec *codec) { + assert(source->sink_count); + for (unsigned i = 0; i < source->sink_count; ++i) { + struct sc_packet_sink *sink = source->sinks[i]; + if (!sink->ops->open(sink, codec)) { + sc_packet_source_sinks_close_firsts(source, i); + return false; + } + } + + return true; +} + +void +sc_packet_source_sinks_close(struct sc_packet_source *source) { + assert(source->sink_count); + sc_packet_source_sinks_close_firsts(source, source->sink_count); +} + +bool +sc_packet_source_sinks_push(struct sc_packet_source *source, + const AVPacket *packet) { + assert(source->sink_count); + for (unsigned i = 0; i < source->sink_count; ++i) { + struct sc_packet_sink *sink = source->sinks[i]; + if (!sink->ops->push(sink, packet)) { + return false; + } + } + + return true; +} + +void +sc_packet_source_sinks_disable(struct sc_packet_source *source) { + assert(source->sink_count); + for (unsigned i = 0; i < source->sink_count; ++i) { + struct sc_packet_sink *sink = source->sinks[i]; + if (sink->ops->disable) { + sink->ops->disable(sink); + } + } +} diff --git a/app/src/trait/packet_source.h b/app/src/trait/packet_source.h new file mode 100644 index 00000000..c34aa5d3 --- /dev/null +++ b/app/src/trait/packet_source.h @@ -0,0 +1,41 @@ +#ifndef SC_PACKET_SOURCE_H +#define SC_PACKET_SOURCE_H + +#include "common.h" + +#include "packet_sink.h" + +#define SC_PACKET_SOURCE_MAX_SINKS 2 + +/** + * Packet source trait + * + * Component able to send AVPackets should implement this trait. + */ +struct sc_packet_source { + struct sc_packet_sink *sinks[SC_PACKET_SOURCE_MAX_SINKS]; + unsigned sink_count; +}; + +void +sc_packet_source_init(struct sc_packet_source *source); + +void +sc_packet_source_add_sink(struct sc_packet_source *source, + struct sc_packet_sink *sink); + +bool +sc_packet_source_sinks_open(struct sc_packet_source *source, + const AVCodec *codec); + +void +sc_packet_source_sinks_close(struct sc_packet_source *source); + +bool +sc_packet_source_sinks_push(struct sc_packet_source *source, + const AVPacket *packet); + +void +sc_packet_source_sinks_disable(struct sc_packet_source *source); + +#endif