diff --git a/app/meson.build b/app/meson.build index 82105876..9f73b434 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/frame_source.c', 'src/trait/packet_source.c', 'src/util/acksync.c', 'src/util/bytebuf.c', diff --git a/app/src/trait/frame_source.c b/app/src/trait/frame_source.c new file mode 100644 index 00000000..416eccd9 --- /dev/null +++ b/app/src/trait/frame_source.c @@ -0,0 +1,59 @@ +#include "frame_source.h" + +void +sc_frame_source_init(struct sc_frame_source *source) { + source->sink_count = 0; +} + +void +sc_frame_source_add_sink(struct sc_frame_source *source, + struct sc_frame_sink *sink) { + assert(source->sink_count < SC_FRAME_SOURCE_MAX_SINKS); + assert(sink); + assert(sink->ops); + source->sinks[source->sink_count++] = sink; +} + +static void +sc_frame_source_sinks_close_firsts(struct sc_frame_source *source, + unsigned count) { + while (count) { + struct sc_frame_sink *sink = source->sinks[--count]; + sink->ops->close(sink); + } +} + +bool +sc_frame_source_sinks_open(struct sc_frame_source *source, + const AVCodecContext *ctx) { + assert(source->sink_count); + for (unsigned i = 0; i < source->sink_count; ++i) { + struct sc_frame_sink *sink = source->sinks[i]; + if (!sink->ops->open(sink, ctx)) { + sc_frame_source_sinks_close_firsts(source, i); + return false; + } + } + + return true; +} + +void +sc_frame_source_sinks_close(struct sc_frame_source *source) { + assert(source->sink_count); + sc_frame_source_sinks_close_firsts(source, source->sink_count); +} + +bool +sc_frame_source_sinks_push(struct sc_frame_source *source, + const AVFrame *frame) { + assert(source->sink_count); + for (unsigned i = 0; i < source->sink_count; ++i) { + struct sc_frame_sink *sink = source->sinks[i]; + if (!sink->ops->push(sink, frame)) { + return false; + } + } + + return true; +} diff --git a/app/src/trait/frame_source.h b/app/src/trait/frame_source.h new file mode 100644 index 00000000..94222af0 --- /dev/null +++ b/app/src/trait/frame_source.h @@ -0,0 +1,38 @@ +#ifndef SC_FRAME_SOURCE_H +#define SC_FRAME_SOURCE_H + +#include "common.h" + +#include "frame_sink.h" + +#define SC_FRAME_SOURCE_MAX_SINKS 2 + +/** + * Frame source trait + * + * Component able to send AVFrames should implement this trait. + */ +struct sc_frame_source { + struct sc_frame_sink *sinks[SC_FRAME_SOURCE_MAX_SINKS]; + unsigned sink_count; +}; + +void +sc_frame_source_init(struct sc_frame_source *source); + +void +sc_frame_source_add_sink(struct sc_frame_source *source, + struct sc_frame_sink *sink); + +bool +sc_frame_source_sinks_open(struct sc_frame_source *source, + const AVCodecContext *ctx); + +void +sc_frame_source_sinks_close(struct sc_frame_source *source); + +bool +sc_frame_source_sinks_push(struct sc_frame_source *source, + const AVFrame *frame); + +#endif