1 /* A generic test engine for elements based upon GstAdaptiveDemux
2  *
3  * Copyright (c) <2015> YouView TV Ltd
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 
21 #ifndef __GST_ADAPTIVE_DEMUX_TEST_ENGINE_H__
22 #define __GST_ADAPTIVE_DEMUX_TEST_ENGINE_H__
23 
24 #include <gst/gst.h>
25 #include <gst/app/gstappsink.h>
26 #include "test_http_src.h"
27 
28 G_BEGIN_DECLS
29 
30 typedef struct _GstAdaptiveDemuxTestEngine GstAdaptiveDemuxTestEngine;
31 
32 typedef struct _GstAdaptiveDemuxTestOutputStream {
33   gchar *name;
34 
35   /* the GstAppSink element getting the data for this stream */
36   GstAppSink *appsink;
37   GstPad *pad;
38   /* the internal pad of adaptivedemux element used to send data to the GstAppSink element */
39   GstPad *internal_pad;
40   gulong internal_pad_probe;
41   /* current segment start offset */
42   guint64 segment_start;
43   /* the size received so far on this segment */
44   guint64 segment_received_size;
45   /* the total size received so far on this stream, excluding current segment */
46   guint64 total_received_size;
47 } GstAdaptiveDemuxTestOutputStream;
48 
49 /* GstAdaptiveDemuxTestCallbacks: contains various callbacks that can
50  * be registered by a test. Not all callbacks needs to be configured
51  * by a test. A callback that is not required by a test must be set
52  * to NULL.
53  */
54 typedef struct _GstAdaptiveDemuxTestCallbacks
55 {
56   /**
57    * pre_test: called before starting the pipeline
58    * @engine: #GstAdaptiveDemuxTestEngine
59    * @user_data: the user_data passed to gst_adaptive_demux_test_run()
60    */
61   void (*pre_test) (GstAdaptiveDemuxTestEngine *engine, gpointer user_data);
62 
63   /**
64    * post_test: called after stopping the pipeline.
65    * @engine: #GstAdaptiveDemuxTestEngine
66    * @user_data: the user_data passed to gst_adaptive_demux_test_run()
67    */
68   void (*post_test) (GstAdaptiveDemuxTestEngine *engine, gpointer user_data);
69 
70   /**
71    * appsink_received_data: called each time AppSink receives data
72    * @engine: #GstAdaptiveDemuxTestEngine
73    * @stream: #GstAdaptiveDemuxTestOutputStream
74    * @buffer: the #GstBuffer that was recevied by #GstAppSink
75    * @user_data: the user_data passed to gst_adaptive_demux_test_run()
76    * Returns: %TRUE to continue processing, %FALSE to cause EOS
77    *
78    * Can be used by a test to perform additional operations (eg validate
79    * output data)
80    */
81   gboolean (*appsink_received_data) (GstAdaptiveDemuxTestEngine *engine,
82       GstAdaptiveDemuxTestOutputStream * stream,
83       GstBuffer * buffer, gpointer user_data);
84 
85   /**
86    * appsink_eos: called each time AppSink receives eos
87    * @engine: #GstAdaptiveDemuxTestEngine
88    * @stream: #GstAdaptiveDemuxTestOutputStream
89    * @user_data: the user_data passed to gst_adaptive_demux_test_run()
90    *
91    * Can be used by a test to perform additional operations (eg validate
92    * output data)
93    */
94   void (*appsink_eos) (GstAdaptiveDemuxTestEngine *engine,
95       GstAdaptiveDemuxTestOutputStream * stream, gpointer user_data);
96 
97   /**
98    * appsink_event: called when an event is received by appsink
99    * @engine: #GstAdaptiveDemuxTestEngine
100    * @stream: #GstAdaptiveDemuxTestOutputStream
101    * @event: the #GstEvent that was pushed in the demuxer pad
102    * @user_data: the user_data passed to gst_adaptive_demux_test_run()
103    *
104    * Can be used by a test to do some checks on the events
105    */
106   void (*appsink_event) (GstAdaptiveDemuxTestEngine *engine,
107       GstAdaptiveDemuxTestOutputStream * stream,
108       GstEvent * event, gpointer user_data);
109 
110   /**
111    * demux_pad_added: called each time the demux creates a new pad
112    * @engine: #GstAdaptiveDemuxTestEngine
113    * @stream: the #GstAdaptiveDemuxTestOutputStream that has been created
114    * @user_data: the user_data passed to gst_adaptive_demux_test_run()
115    */
116   void (*demux_pad_added) (GstAdaptiveDemuxTestEngine * engine,
117       GstAdaptiveDemuxTestOutputStream * stream, gpointer user_data);
118 
119   /**
120    * demux_pad_removed: called each time the demux removes a pad
121    * @engine: #GstAdaptiveDemuxTestEngine
122    * @stream: the #GstAdaptiveDemuxTestOutputStream that will no longer
123    * be used
124    * @user_data: the user_data passed to gst_adaptive_demux_test_run()
125    */
126   void (*demux_pad_removed) (GstAdaptiveDemuxTestEngine * engine,
127       GstAdaptiveDemuxTestOutputStream * stream, gpointer user_data);
128 
129   /**
130    * demux_sent_data: called each time the demux sends data to AppSink
131    * @engine: #GstAdaptiveDemuxTestEngine
132    * @stream: #GstAdaptiveDemuxTestOutputStream
133    * @buffer: the #GstBuffer that was sent by demux
134    * @user_data: the user_data passed to gst_adaptive_demux_test_run()
135    */
136   gboolean (*demux_sent_data) (GstAdaptiveDemuxTestEngine *engine,
137       GstAdaptiveDemuxTestOutputStream * stream,
138       GstBuffer * buffer, gpointer user_data);
139 
140   /**
141    * demux_sent_event: called each time the demux sends event to AppSink
142    * @engine: #GstAdaptiveDemuxTestEngine
143    * @stream: #GstAdaptiveDemuxTestOutputStream
144    * @event: the #GstEvent that was sent by demux
145    * @user_data: the user_data passed to gst_adaptive_demux_test_run()
146    */
147   gboolean (*demux_sent_event) (GstAdaptiveDemuxTestEngine *engine,
148       GstAdaptiveDemuxTestOutputStream * stream,
149       GstEvent * event, gpointer user_data);
150 
151   /**
152    * bus_error_message: called if an error is posted to the bus
153    * @engine: #GstAdaptiveDemuxTestEngine
154    * @msg: the #GstMessage that contains the error
155    * @user_data: the user_data passed to gst_adaptive_demux_test_run()
156    *
157    * The callback can decide if this error is expected, or to fail
158    * the test
159    */
160   void (*bus_error_message)(GstAdaptiveDemuxTestEngine *engine,
161       GstMessage * msg, gpointer user_data);
162 } GstAdaptiveDemuxTestCallbacks;
163 
164 /* structure containing all data used by a test
165  * Any callback defined by a test will receive this as first parameter
166  */
167 struct _GstAdaptiveDemuxTestEngine
168 {
169   GstElement *pipeline;
170   GstClock *clock;
171   GstElement *demux;
172   GstElement *manifest_source;
173   GMainLoop *loop;
174   GPtrArray *output_streams; /* GPtrArray<GstAdaptiveDemuxTestOutputStream> */
175   /* mutex to lock accesses to this structure when data is shared
176    * between threads */
177   GMutex lock;
178 };
179 
180 /**
181  * gst_adaptive_demux_test_run:
182  * @element_name: The name of the demux element (e.g. "dashdemux")
183  * @manifest_uri: The URI of the manifest to load
184  * @callbacks: The callbacks to use while the test is in operating
185  * @user_data: Opaque pointer that is passed to every callback
186  *
187  * Creates a pipeline with the specified demux element in it,
188  * connect a testhttpsrc element to this demux element and
189  * request manifest_uri. When the demux element adds a new
190  * pad, the engine will create an AppSink element and attach
191  * it to this pad.
192  *
193  * Information about these pads is collected in
194  * GstAdaptiveDemuxTestEngine::output_streams
195  */
196 void gst_adaptive_demux_test_run (const gchar * element_name,
197     const gchar * manifest_uri,
198     const GstAdaptiveDemuxTestCallbacks * callbacks,
199     gpointer user_data);
200 
201 G_END_DECLS
202 #endif /* __GST_ADAPTIVE_DEMUX_TEST_ENGINE_H__ */
203