summaryrefslogtreecommitdiff
path: root/include/gst/audio/gstnonstreamaudiodecoder.h
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2022-08-03 21:02:36 +0300
committerGeorge Hazan <ghazan@miranda.im>2022-08-03 21:02:36 +0300
commit5323a782c4e8c42781f22ce2f488962a18f82554 (patch)
treef71537197b16f0f8fd0d6937f7120d018d220814 /include/gst/audio/gstnonstreamaudiodecoder.h
parent50acf9d37183f86f6f623aad410003392b0af41f (diff)
Jabber: initial version of Jingle support
Diffstat (limited to 'include/gst/audio/gstnonstreamaudiodecoder.h')
-rw-r--r--include/gst/audio/gstnonstreamaudiodecoder.h412
1 files changed, 412 insertions, 0 deletions
diff --git a/include/gst/audio/gstnonstreamaudiodecoder.h b/include/gst/audio/gstnonstreamaudiodecoder.h
new file mode 100644
index 0000000000..4de1fc7ee9
--- /dev/null
+++ b/include/gst/audio/gstnonstreamaudiodecoder.h
@@ -0,0 +1,412 @@
+/* GStreamer
+ * Copyright (C) <2017> Carlos Rafael Giani <dv at pseudoterminal dot org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef __GST_NONSTREAM_AUDIO_DECODER_H__
+#define __GST_NONSTREAM_AUDIO_DECODER_H__
+
+#include <gst/gst.h>
+#include <gst/base/gstadapter.h>
+#include <gst/audio/audio.h>
+#include <gst/audio/audio-bad-prelude.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _GstNonstreamAudioDecoder GstNonstreamAudioDecoder;
+typedef struct _GstNonstreamAudioDecoderClass GstNonstreamAudioDecoderClass;
+
+
+/**
+ * GstNonstreamAudioOutputMode:
+ * @GST_NONSTREAM_AUDIO_OUTPUT_MODE_LOOPING: Playback position is moved back to the beginning of the loop
+ * @GST_NONSTREAM_AUDIO_OUTPUT_MODE_STEADY: Playback position increases steadily, even when looping
+ *
+ * The output mode defines how the output behaves with regards to looping. Either the playback position is
+ * moved back to the beginning of the loop, acting like a backwards seek, or it increases steadily, as if
+ * loop were "unrolled".
+ */
+typedef enum
+{
+ GST_NONSTREAM_AUDIO_OUTPUT_MODE_LOOPING,
+ GST_NONSTREAM_AUDIO_OUTPUT_MODE_STEADY
+} GstNonstreamAudioOutputMode;
+
+
+/**
+ * GstNonstreamAudioSubsongMode:
+ * @GST_NONSTREAM_AUDIO_SUBSONG_MODE_SINGLE: Only the current subsong is played
+ * @GST_NONSTREAM_AUDIO_SUBSONG_MODE_ALL: All subsongs are played (current subsong index is ignored)
+ * @GST_NONSTREAM_AUDIO_SUBSONG_MODE_DECODER_DEFAULT: Use decoder specific default behavior
+ *
+ * The subsong mode defines how the decoder shall handle subsongs.
+ */
+typedef enum
+{
+ GST_NONSTREAM_AUDIO_SUBSONG_MODE_SINGLE,
+ GST_NONSTREAM_AUDIO_SUBSONG_MODE_ALL,
+ GST_NONSTREAM_AUDIO_SUBSONG_MODE_DECODER_DEFAULT
+} GstNonstreamAudioSubsongMode;
+
+
+#define GST_TYPE_NONSTREAM_AUDIO_DECODER (gst_nonstream_audio_decoder_get_type())
+#define GST_NONSTREAM_AUDIO_DECODER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_NONSTREAM_AUDIO_DECODER, GstNonstreamAudioDecoder))
+#define GST_NONSTREAM_AUDIO_DECODER_CAST(obj) ((GstNonstreamAudioDecoder *)(obj))
+#define GST_NONSTREAM_AUDIO_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_NONSTREAM_AUDIO_DECODER, GstNonstreamAudioDecoderClass))
+#define GST_NONSTREAM_AUDIO_DECODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GST_TYPE_NONSTREAM_AUDIO_DECODER, GstNonstreamAudioDecoderClass))
+#define GST_IS_NONSTREAM_AUDIO_DECODER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_NONSTREAM_AUDIO_DECODER))
+#define GST_IS_NONSTREAM_AUDIO_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_NONSTREAM_AUDIO_DECODER))
+
+/**
+ * GST_NONSTREAM_AUDIO_DECODER_SINK_NAME:
+ *
+ * The name of the template for the sink pad.
+ */
+#define GST_NONSTREAM_AUDIO_DECODER_SINK_NAME "sink"
+/**
+ * GST_NONSTREAM_AUDIO_DECODER_SRC_NAME:
+ *
+ * The name of the template for the source pad.
+ */
+#define GST_NONSTREAM_AUDIO_DECODER_SRC_NAME "src"
+
+/**
+ * GST_NONSTREAM_AUDIO_DECODER_SINK_PAD:
+ * @obj: base nonstream audio codec instance
+ *
+ * Gives the pointer to the sink #GstPad object of the element.
+ */
+#define GST_NONSTREAM_AUDIO_DECODER_SINK_PAD(obj) (((GstNonstreamAudioDecoder *) (obj))->sinkpad)
+/**
+ * GST_NONSTREAM_AUDIO_DECODER_SRC_PAD:
+ * @obj: base nonstream audio codec instance
+ *
+ * Gives the pointer to the source #GstPad object of the element.
+ */
+#define GST_NONSTREAM_AUDIO_DECODER_SRC_PAD(obj) (((GstNonstreamAudioDecoder *) (obj))->srcpad)
+
+
+/**
+ * GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX:
+ * @obj: base nonstream audio codec instance
+ *
+ * Locks the decoder mutex.
+ *
+ * Internally, the mutex is locked before one of the class vfuncs are
+ * called, when position and duration queries are handled, and when
+ * properties are set/retrieved.
+ *
+ * Derived classes should call lock during decoder related modifications
+ * (for example, setting/clearing filter banks), when at the same time
+ * audio might get decoded. An example are configuration changes that
+ * happen when properties are set. Properties might be set from another
+ * thread, so while the derived decoder is reconfigured, the mutex
+ * should be locked.
+ */
+#define GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX(obj) g_mutex_lock(&(((GstNonstreamAudioDecoder *)(obj))->mutex))
+#define GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX(obj) g_mutex_unlock(&(((GstNonstreamAudioDecoder *)(obj))->mutex))
+
+
+/**
+ * GstNonstreamAudioDecoder:
+ *
+ * The opaque #GstNonstreamAudioDecoder data structure.
+ */
+struct _GstNonstreamAudioDecoder
+{
+ GstElement element;
+
+ /*< protected > */
+
+ /* source and sink pads */
+ GstPad *sinkpad, *srcpad;
+
+ /* loading information */
+ gint64 upstream_size;
+ gboolean loaded_mode;
+ GstAdapter *input_data_adapter;
+
+ /* subsong states */
+ guint current_subsong;
+ GstNonstreamAudioSubsongMode subsong_mode;
+ GstClockTime subsong_duration;
+
+ /* output states */
+ GstNonstreamAudioOutputMode output_mode;
+ gint num_loops;
+ gboolean output_format_changed;
+ GstAudioInfo output_audio_info;
+ /* The difference between these two values is: cur_pos_in_samples is
+ * used for the GstBuffer offsets, while num_decoded_samples is used
+ * for the segment base time values.
+ * cur_pos_in_samples is reset after seeking, looping (when output mode
+ * is LOOPING) and switching subsongs, while num_decoded is only reset
+ * to 0 after a flushing seek (because flushing seeks alter the
+ * pipeline's base_time). */
+ guint64 cur_pos_in_samples, num_decoded_samples;
+ GstSegment cur_segment;
+ gboolean discont;
+
+ /* metadata */
+ GstToc *toc;
+
+ /* allocation */
+ GstAllocator *allocator;
+ GstAllocationParams allocation_params;
+
+ /* thread safety */
+ GMutex mutex;
+};
+
+
+/**
+ * GstNonstreamAudioDecoderClass:
+ * @element_class: The parent class structure
+ * @seek: Optional.
+ * Called when a seek event is received by the parent class.
+ * new_position is a pointer to a GstClockTime integer which
+ * contains a position relative to the current subsong.
+ * Minimum is 0, maximum is the subsong length.
+ * After this function finishes, new_position is set to the
+ * actual new position (which may differ from the request
+ * position, depending on the decoder).
+ * @tell: Optional.
+ * Called when a position query is received by the parent class.
+ * The position that this function returns must be relative to
+ * the current subsong. Thus, the minimum is 0, and the maximum
+ * is the subsong length.
+ * @load_from_buffer: Required if loads_from_sinkpad is set to TRUE (the default value).
+ * Loads the media from the given buffer. The entire media is supplied at once,
+ * so after this call, loading should be finished. This function
+ * can also make use of a suggested initial subsong & subsong mode and initial
+ * playback position (but isn't required to). In case it chooses a different starting
+ * position, the function must pass this position to *initial_position.
+ * The subclass does not have to unref the input buffer; the base class does that
+ * already.
+ * @load_from_custom: Required if loads_from_sinkpad is set to FALSE.
+ * Loads the media in a way defined by the custom sink. Data is not supplied;
+ * the derived class has to handle this on its own. Otherwise, this function is
+ * identical to @load_from_buffer.
+ * @get_main_tags: Optional.
+ * Returns a tag list containing the main song tags, or NULL if there are
+ * no such tags. Returned tags will be unref'd. Use this vfunc instead of
+ * manually pushing a tag event downstream to avoid edge cases where not yet
+ * pushed sticky tag events get overwritten before they are pushed (can for
+ * example happen with decodebin if tags are pushed downstream before the
+ * decodebin pads are linked).
+ * @set_current_subsong: Optional.
+ * Sets the current subsong. This function is allowed to switch to a different
+ * subsong than the required one, and can optionally make use of the suggested initial
+ * position. In case it chooses a different starting position, the function must pass
+ * this position to *initial_position.
+ * This function switches the subsong mode to GST_NONSTREAM_AUDIO_SUBSONG_MODE_SINGLE
+ * automatically.
+ * If this function is implemented by the subclass, @get_current_subsong and
+ * @get_num_subsongs should be implemented as well.
+ * @get_current_subsong: Optional.
+ * Returns the current subsong.
+ * If the current subsong mode is not GST_NONSTREAM_AUDIO_SUBSONG_MODE_SINGLE, this
+ * function's return value is undefined.
+ * If this function is implemented by the subclass,
+ * @get_num_subsongs should be implemented as well.
+ * @get_num_subsongs: Optional.
+ * Returns the number of subsongs available.
+ * The return values 0 and 1 have a similar, but distinct, meaning.
+ * If this function returns 0, then this decoder does not support subsongs at all.
+ * @get_current_subsong must then also always return 0. In other words, this function
+ * either never returns 0, or never returns anything else than 0.
+ * A return value of 1 means that the media contains either only one or no subsongs
+ * (the entire song is then considered to be one single subsong). 1 also means that only
+ * this very media has no or just one subsong, and the decoder itself can
+ * support multiple subsongs.
+ * @get_subsong_duration: Optional.
+ * Returns the duration of a subsong. Returns GST_CLOCK_TIME_NONE if duration is unknown.
+ * @get_subsong_tags: Optional.
+ * Returns tags for a subsong, or NULL if there are no tags.
+ * Returned tags will be unref'd.
+ * @set_subsong_mode: Optional.
+ * Sets the current subsong mode. Since this might influence the current playback position,
+ * this function must set the initial_position integer argument to a defined value.
+ * If the playback position is not affected at all, it must be set to GST_CLOCK_TIME_NONE.
+ * If the subsong is restarted after the mode switch, it is recommended to set the value
+ * to the position in the playback right after the switch (or 0 if the subsongs are always
+ * reset back to the beginning).
+ * @set_num_loops: Optional.
+ * Sets the number of loops for playback. If this is called during playback,
+ * the subclass must set any internal loop counters to zero. A loop value of -1
+ * means infinite looping; 0 means no looping; and when the num_loops is greater than 0,
+ * playback should loop exactly num_loops times. If this function is implemented,
+ * @get_num_loops should be implemented as well. The function can ignore the given values
+ * and choose another; however, @get_num_loops should return this other value afterwards.
+ * It is up to the subclass to define where the loop starts and ends. It can mean that only
+ * a subset at the end or in the middle of a song is repeated, for example.
+ * If the current subsong mode is GST_NONSTREAM_AUDIO_SUBSONG_MODE_SINGLE, then the subsong
+ * is repeated this many times. If it is GST_NONSTREAM_AUDIO_SUBSONG_MODE_ALL, then all
+ * subsongs are repeated this many times. With GST_NONSTREAM_AUDIO_SUBSONG_MODE_DECODER_DEFAULT,
+ * the behavior is decoder specific.
+ * @get_num_loops: Optional.
+ * Returns the number of loops for playback.
+ * @get_supported_output_modes: Always required.
+ * Returns a bitmask containing the output modes the subclass supports.
+ * The mask is formed by a bitwise OR combination of integers, which can be calculated
+ * this way: 1 << GST_NONSTREAM_AUDIO_OUTPUT_MODE_<mode> , where mode is either STEADY or LOOPING
+ * @set_output_mode: Optional.
+ * Sets the output mode the subclass has to use. Unlike with most other functions, the subclass
+ * cannot choose a different mode; it must use the requested one.
+ * If the output mode is set to LOOPING, @gst_nonstream_audio_decoder_handle_loop
+ * must be called after playback moved back to the start of a loop.
+ * @decode: Always required.
+ * Allocates an output buffer, fills it with decoded audio samples, and must be passed on to
+ * *buffer . The number of decoded samples must be passed on to *num_samples.
+ * If decoding finishes or the decoding is no longer possible (for example, due to an
+ * unrecoverable error), this function returns FALSE, otherwise TRUE.
+ * @decide_allocation: Optional.
+ * Sets up the allocation parameters for allocating output
+ * buffers. The passed in query contains the result of the
+ * downstream allocation query.
+ * Subclasses should chain up to the parent implementation to
+ * invoke the default handler.
+ * @propose_allocation: Optional.
+ * Proposes buffer allocation parameters for upstream elements.
+ * Subclasses should chain up to the parent implementation to
+ * invoke the default handler.
+ *
+ * Subclasses can override any of the available optional virtual methods or not, as
+ * needed. At minimum, @load_from_buffer (or @load_from_custom), @get_supported_output_modes,
+ * and @decode need to be overridden.
+ *
+ * All functions are called with a locked decoder mutex.
+ *
+ * > If GST_ELEMENT_ERROR, GST_ELEMENT_WARNING, or GST_ELEMENT_INFO are called from
+ * > inside one of these functions, it is strongly recommended to unlock the decoder mutex
+ * > before and re-lock it after these macros to prevent potential deadlocks in case the
+ * > application does something with the element when it receives an ERROR/WARNING/INFO
+ * > message. Same goes for gst_element_post_message() calls and non-serialized events.
+ *
+ * By default, this class works by reading media data from the sinkpad, and then commencing
+ * playback. Some decoders cannot be given data from a memory block, so the usual way of
+ * reading all upstream data and passing it to @load_from_buffer doesn't work then. In this case,
+ * set the value of loads_from_sinkpad to FALSE. This changes the way this class operates;
+ * it does not require a sinkpad to exist anymore, and will call @load_from_custom instead.
+ * One example of a decoder where this makes sense is UADE (Unix Amiga Delitracker Emulator).
+ * For some formats (such as TFMX), it needs to do the file loading by itself.
+ * Since most decoders can read input data from a memory block, the default value of
+ * loads_from_sinkpad is TRUE.
+ */
+struct _GstNonstreamAudioDecoderClass
+{
+ GstElementClass element_class;
+
+ gboolean loads_from_sinkpad;
+
+ /*< public > */
+ /* virtual methods for subclasses */
+
+ gboolean (*seek) (GstNonstreamAudioDecoder * dec,
+ GstClockTime * new_position);
+ GstClockTime (*tell) (GstNonstreamAudioDecoder * dec);
+
+ gboolean (*load_from_buffer) (GstNonstreamAudioDecoder * dec,
+ GstBuffer * source_data,
+ guint initial_subsong,
+ GstNonstreamAudioSubsongMode initial_subsong_mode,
+ GstClockTime * initial_position,
+ GstNonstreamAudioOutputMode * initial_output_mode,
+ gint * initial_num_loops);
+ gboolean (*load_from_custom) (GstNonstreamAudioDecoder * dec,
+ guint initial_subsong,
+ GstNonstreamAudioSubsongMode initial_subsong_mode,
+ GstClockTime * initial_position,
+ GstNonstreamAudioOutputMode * initial_output_mode,
+ gint * initial_num_loops);
+
+ GstTagList * (*get_main_tags) (GstNonstreamAudioDecoder * dec);
+
+ gboolean (*set_current_subsong) (GstNonstreamAudioDecoder * dec,
+ guint subsong,
+ GstClockTime * initial_position);
+ guint (*get_current_subsong) (GstNonstreamAudioDecoder * dec);
+
+ guint (*get_num_subsongs) (GstNonstreamAudioDecoder * dec);
+ GstClockTime (*get_subsong_duration) (GstNonstreamAudioDecoder * dec,
+ guint subsong);
+ GstTagList * (*get_subsong_tags) (GstNonstreamAudioDecoder * dec,
+ guint subsong);
+ gboolean (*set_subsong_mode) (GstNonstreamAudioDecoder * dec,
+ GstNonstreamAudioSubsongMode mode,
+ GstClockTime * initial_position);
+
+ gboolean (*set_num_loops) (GstNonstreamAudioDecoder * dec,
+ gint num_loops);
+ gint (*get_num_loops) (GstNonstreamAudioDecoder * dec);
+
+ guint (*get_supported_output_modes) (GstNonstreamAudioDecoder * dec);
+ gboolean (*set_output_mode) (GstNonstreamAudioDecoder * dec,
+ GstNonstreamAudioOutputMode mode,
+ GstClockTime * current_position);
+
+ gboolean (*decode) (GstNonstreamAudioDecoder * dec,
+ GstBuffer ** buffer,
+ guint * num_samples);
+
+ gboolean (*negotiate) (GstNonstreamAudioDecoder * dec);
+
+ gboolean (*decide_allocation) (GstNonstreamAudioDecoder * dec,
+ GstQuery * query);
+ gboolean (*propose_allocation) (GstNonstreamAudioDecoder * dec,
+ GstQuery * query);
+
+ /*< private > */
+ gpointer _gst_reserved[GST_PADDING_LARGE];
+};
+
+
+GST_AUDIO_BAD_API
+GType gst_nonstream_audio_decoder_get_type (void);
+
+
+GST_AUDIO_BAD_API
+void gst_nonstream_audio_decoder_handle_loop (GstNonstreamAudioDecoder * dec,
+ GstClockTime new_position);
+
+GST_AUDIO_BAD_API
+gboolean gst_nonstream_audio_decoder_set_output_format (GstNonstreamAudioDecoder * dec,
+ GstAudioInfo const *audio_info);
+
+GST_AUDIO_BAD_API
+gboolean gst_nonstream_audio_decoder_set_output_format_simple (GstNonstreamAudioDecoder * dec,
+ guint sample_rate,
+ GstAudioFormat sample_format,
+ guint num_channels);
+
+GST_AUDIO_BAD_API
+void gst_nonstream_audio_decoder_get_downstream_info (GstNonstreamAudioDecoder * dec,
+ GstAudioFormat * format,
+ gint * sample_rate,
+ gint * num_channels);
+
+GST_AUDIO_BAD_API
+GstBuffer *gst_nonstream_audio_decoder_allocate_output_buffer (GstNonstreamAudioDecoder * dec,
+ gsize size);
+
+
+G_END_DECLS
+
+
+#endif /* __GST_NONSTREAM_AUDIO_DECODER_H__ */