/* A generic test engine for elements based upon GstAdaptiveDemux * * Copyright (c) <2015> YouView TV Ltd * * 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_ADAPTIVE_DEMUX_TEST_ENGINE_H__ #define __GST_ADAPTIVE_DEMUX_TEST_ENGINE_H__ #include #include #include "test_http_src.h" G_BEGIN_DECLS typedef struct _GstAdaptiveDemuxTestEngine GstAdaptiveDemuxTestEngine; typedef struct _GstAdaptiveDemuxTestOutputStream { /* the GstAppSink element getting the data for this stream */ GstAppSink *appsink; GstPad *pad; /* the internal pad of adaptivedemux element used to send data to the GstAppSink element */ GstPad *internal_pad; gulong internal_pad_probe; /* current segment start offset */ guint64 segment_start; /* the size received so far on this segment */ guint64 segment_received_size; /* the total size received so far on this stream, excluding current segment */ guint64 total_received_size; } GstAdaptiveDemuxTestOutputStream; /* GstAdaptiveDemuxTestCallbacks: contains various callbacks that can * be registered by a test. Not all callbacks needs to be configured * by a test. A callback that is not required by a test must be set * to NULL. */ typedef struct _GstAdaptiveDemuxTestCallbacks { /** * pre_test: called before starting the pipeline * @engine: #GstAdaptiveDemuxTestEngine * @user_data: the user_data passed to gst_adaptive_demux_test_run() */ void (*pre_test) (GstAdaptiveDemuxTestEngine *engine, gpointer user_data); /** * post_test: called after stopping the pipeline. * @engine: #GstAdaptiveDemuxTestEngine * @user_data: the user_data passed to gst_adaptive_demux_test_run() */ void (*post_test) (GstAdaptiveDemuxTestEngine *engine, gpointer user_data); /** * appsink_received_data: called each time AppSink receives data * @engine: #GstAdaptiveDemuxTestEngine * @stream: #GstAdaptiveDemuxTestOutputStream * @buffer: the #GstBuffer that was recevied by #GstAppSink * @user_data: the user_data passed to gst_adaptive_demux_test_run() * Returns: #TRUE to continue processing, #FALSE to cause EOS * * Can be used by a test to perform additional operations (eg validate * output data) */ gboolean (*appsink_received_data) (GstAdaptiveDemuxTestEngine *engine, GstAdaptiveDemuxTestOutputStream * stream, GstBuffer * buffer, gpointer user_data); /** * appsink_eos: called each time AppSink receives eos * @engine: #GstAdaptiveDemuxTestEngine * @stream: #GstAdaptiveDemuxTestOutputStream * @user_data: the user_data passed to gst_adaptive_demux_test_run() * * Can be used by a test to perform additional operations (eg validate * output data) */ void (*appsink_eos) (GstAdaptiveDemuxTestEngine *engine, GstAdaptiveDemuxTestOutputStream * stream, gpointer user_data); /** * appsink_event: called when an event is received by appsink * @engine: #GstAdaptiveDemuxTestEngine * @stream: #GstAdaptiveDemuxTestOutputStream * @event: the #GstEvent that was pushed in the demuxer pad * @user_data: the user_data passed to gst_adaptive_demux_test_run() * * Can be used by a test to do some checks on the events */ void (*appsink_event) (GstAdaptiveDemuxTestEngine *engine, GstAdaptiveDemuxTestOutputStream * stream, GstEvent * event, gpointer user_data); /** * demux_pad_added: called each time the demux creates a new pad * @engine: #GstAdaptiveDemuxTestEngine * @stream: the #GstAdaptiveDemuxTestOutputStream that has been created * @user_data: the user_data passed to gst_adaptive_demux_test_run() */ void (*demux_pad_added) (GstAdaptiveDemuxTestEngine * engine, GstAdaptiveDemuxTestOutputStream * stream, gpointer user_data); /** * demux_pad_removed: called each time the demux removes a pad * @engine: #GstAdaptiveDemuxTestEngine * @stream: the #GstAdaptiveDemuxTestOutputStream that will no longer * be used * @user_data: the user_data passed to gst_adaptive_demux_test_run() */ void (*demux_pad_removed) (GstAdaptiveDemuxTestEngine * engine, GstAdaptiveDemuxTestOutputStream * stream, gpointer user_data); /** * demux_sent_data: called each time the demux sends data to AppSink * @engine: #GstAdaptiveDemuxTestEngine * @stream: #GstAdaptiveDemuxTestOutputStream * @buffer: the #GstBuffer that was sent by demux * @user_data: the user_data passed to gst_adaptive_demux_test_run() */ gboolean (*demux_sent_data) (GstAdaptiveDemuxTestEngine *engine, GstAdaptiveDemuxTestOutputStream * stream, GstBuffer * buffer, gpointer user_data); /** * demux_sent_event: called each time the demux sends event to AppSink * @engine: #GstAdaptiveDemuxTestEngine * @stream: #GstAdaptiveDemuxTestOutputStream * @event: the #GstEvent that was sent by demux * @user_data: the user_data passed to gst_adaptive_demux_test_run() */ gboolean (*demux_sent_event) (GstAdaptiveDemuxTestEngine *engine, GstAdaptiveDemuxTestOutputStream * stream, GstEvent * event, gpointer user_data); /** * bus_error_message: called if an error is posted to the bus * @engine: #GstAdaptiveDemuxTestEngine * @msg: the #GstMessage that contains the error * @user_data: the user_data passed to gst_adaptive_demux_test_run() * * The callback can decide if this error is expected, or to fail * the test */ void (*bus_error_message)(GstAdaptiveDemuxTestEngine *engine, GstMessage * msg, gpointer user_data); } GstAdaptiveDemuxTestCallbacks; /* structure containing all data used by a test * Any callback defined by a test will receive this as first parameter */ struct _GstAdaptiveDemuxTestEngine { GstElement *pipeline; GstClock *clock; GstElement *demux; GstElement *manifest_source; GMainLoop *loop; GPtrArray *output_streams; /* GPtrArray */ /* mutex to lock accesses to this structure when data is shared * between threads */ GMutex lock; }; /** * gst_adaptive_demux_test_run: * @element_name: The name of the demux element (e.g. "dashdemux") * @manifest_uri: The URI of the manifest to load * @callbacks: The callbacks to use while the test is in operating * @user_data: Opaque pointer that is passed to every callback * * Creates a pipeline with the specified demux element in it, * connect a testhttpsrc element to this demux element and * request manifest_uri. When the demux element adds a new * pad, the engine will create an AppSink element and attach * it to this pad. * * Information about these pads is collected in * GstAdaptiveDemuxTestEngine::output_streams */ void gst_adaptive_demux_test_run (const gchar * element_name, const gchar * manifest_uri, const GstAdaptiveDemuxTestCallbacks * callbacks, gpointer user_data); G_END_DECLS #endif /* __GST_ADAPTIVE_DEMUX_TEST_ENGINE_H__ */