blob: 372431e43873808f45fb26617b284b5cfd41698b [file] [log] [blame]
/* 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 <gst/gst.h>
#include <gst/app/gstappsink.h>
#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<GstAdaptiveDemuxTestOutputStream> */
/* 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__ */