~ubuntu-branches/ubuntu/quantal/gst-plugins-bad0.10/quantal-proposed

« back to all changes in this revision

Viewing changes to tests/check/elements/qtmux.c

  • Committer: Bazaar Package Importer
  • Author(s): Ken VanDine
  • Date: 2011-07-19 14:32:43 UTC
  • mfrom: (18.4.21 sid)
  • Revision ID: james.westby@ubuntu.com-20110719143243-p7pnkh45akfp0ihk
Tags: 0.10.22-2ubuntu1
* Rebased on debian unstable, remaining changes:
  - debian/gstreamer-plugins-bad.install
    * don't include dtmf, liveadder, rtpmux, autoconvert and shm, we include 
      them in -good

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* GStreamer
2
 
 *
3
 
 * unit test for qtmux
4
 
 *
5
 
 * Copyright (C) <2008> Mark Nauwelaerts <mnauw@users.sf.net>
6
 
 *
7
 
 * This library is free software; you can redistribute it and/or
8
 
 * modify it under the terms of the GNU Library General Public
9
 
 * License as published by the Free Software Foundation; either
10
 
 * version 2 of the License, or (at your option) any later version.
11
 
 *
12
 
 * This library is distributed in the hope that it will be useful,
13
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 
 * Library General Public License for more details.
16
 
 *
17
 
 * You should have received a copy of the GNU Library General Public
18
 
 * License along with this library; if not, write to the
19
 
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20
 
 * Boston, MA 02111-1307, USA.
21
 
 */
22
 
 
23
 
#include <unistd.h>
24
 
 
25
 
#include <gst/check/gstcheck.h>
26
 
 
27
 
/* For ease of programming we use globals to keep refs for our floating
28
 
 * src and sink pads we create; otherwise we always have to do get_pad,
29
 
 * get_peer, and then remove references in every test function */
30
 
static GstPad *mysrcpad, *mysinkpad;
31
 
 
32
 
#define AUDIO_CAPS_STRING "audio/mpeg, " \
33
 
                        "mpegversion = (int) 1, " \
34
 
                        "layer = (int) 3, " \
35
 
                        "channels = (int) 2, " \
36
 
                        "rate = (int) 48000"
37
 
#define VIDEO_CAPS_STRING "video/mpeg, " \
38
 
                           "mpegversion = (int) 4, " \
39
 
                           "width = (int) 384, " \
40
 
                           "height = (int) 288, " \
41
 
                           "framerate = (fraction) 25/1"
42
 
 
43
 
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
44
 
    GST_PAD_SINK,
45
 
    GST_PAD_ALWAYS,
46
 
    GST_STATIC_CAPS ("video/quicktime"));
47
 
static GstStaticPadTemplate srcvideotemplate = GST_STATIC_PAD_TEMPLATE ("src",
48
 
    GST_PAD_SRC,
49
 
    GST_PAD_ALWAYS,
50
 
    GST_STATIC_CAPS (VIDEO_CAPS_STRING));
51
 
 
52
 
static GstStaticPadTemplate srcaudiotemplate = GST_STATIC_PAD_TEMPLATE ("src",
53
 
    GST_PAD_SRC,
54
 
    GST_PAD_ALWAYS,
55
 
    GST_STATIC_CAPS (AUDIO_CAPS_STRING));
56
 
 
57
 
 
58
 
/* setup and teardown needs some special handling for muxer */
59
 
static GstPad *
60
 
setup_src_pad (GstElement * element,
61
 
    GstStaticPadTemplate * template, GstCaps * caps, const gchar * sinkname)
62
 
{
63
 
  GstPad *srcpad, *sinkpad;
64
 
 
65
 
  GST_DEBUG_OBJECT (element, "setting up sending pad");
66
 
  /* sending pad */
67
 
  srcpad = gst_pad_new_from_static_template (template, "src");
68
 
  fail_if (srcpad == NULL, "Could not create a srcpad");
69
 
  ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 1);
70
 
 
71
 
  if (!(sinkpad = gst_element_get_static_pad (element, sinkname)))
72
 
    sinkpad = gst_element_get_request_pad (element, sinkname);
73
 
  fail_if (sinkpad == NULL, "Could not get sink pad from %s",
74
 
      GST_ELEMENT_NAME (element));
75
 
  /* references are owned by: 1) us, 2) qtmux, 3) collect pads */
76
 
  ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 3);
77
 
  if (caps)
78
 
    fail_unless (gst_pad_set_caps (srcpad, caps));
79
 
  fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK,
80
 
      "Could not link source and %s sink pads", GST_ELEMENT_NAME (element));
81
 
  gst_object_unref (sinkpad);   /* because we got it higher up */
82
 
 
83
 
  /* references are owned by: 1) qtmux, 2) collect pads */
84
 
  ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 2);
85
 
 
86
 
  return srcpad;
87
 
}
88
 
 
89
 
static void
90
 
teardown_src_pad (GstPad * srcpad)
91
 
{
92
 
  GstPad *sinkpad;
93
 
 
94
 
  /* clean up floating src pad */
95
 
  sinkpad = gst_pad_get_peer (srcpad);
96
 
  fail_if (sinkpad == NULL);
97
 
  /* pad refs held by 1) qtmux 2) collectpads and 3) us (through _get_peer) */
98
 
  ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 3);
99
 
 
100
 
  gst_pad_unlink (srcpad, sinkpad);
101
 
 
102
 
  /* after unlinking, pad refs still held by
103
 
   * 1) qtmux and 2) collectpads and 3) us (through _get_peer) */
104
 
  ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 3);
105
 
  gst_object_unref (sinkpad);
106
 
  /* one more ref is held by element itself */
107
 
 
108
 
  /* pad refs held by creator */
109
 
  ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 1);
110
 
  gst_object_unref (srcpad);
111
 
}
112
 
 
113
 
static GstElement *
114
 
setup_qtmux (GstStaticPadTemplate * srctemplate, const gchar * sinkname)
115
 
{
116
 
  GstElement *qtmux;
117
 
 
118
 
  GST_DEBUG ("setup_qtmux");
119
 
  qtmux = gst_check_setup_element ("qtmux");
120
 
  mysrcpad = setup_src_pad (qtmux, srctemplate, NULL, sinkname);
121
 
  mysinkpad = gst_check_setup_sink_pad (qtmux, &sinktemplate, NULL);
122
 
  gst_pad_set_active (mysrcpad, TRUE);
123
 
  gst_pad_set_active (mysinkpad, TRUE);
124
 
 
125
 
  return qtmux;
126
 
}
127
 
 
128
 
static void
129
 
cleanup_qtmux (GstElement * qtmux, const gchar * sinkname)
130
 
{
131
 
  GST_DEBUG ("cleanup_qtmux");
132
 
  gst_element_set_state (qtmux, GST_STATE_NULL);
133
 
 
134
 
  gst_pad_set_active (mysrcpad, FALSE);
135
 
  gst_pad_set_active (mysinkpad, FALSE);
136
 
  teardown_src_pad (mysrcpad);
137
 
  gst_check_teardown_sink_pad (qtmux);
138
 
  gst_check_teardown_element (qtmux);
139
 
}
140
 
 
141
 
static void
142
 
check_qtmux_pad (GstStaticPadTemplate * srctemplate, const gchar * sinkname)
143
 
{
144
 
  GstElement *qtmux;
145
 
  GstBuffer *inbuffer, *outbuffer;
146
 
  GstCaps *caps;
147
 
  int num_buffers;
148
 
  int i;
149
 
  guint8 data0[12] = "\000\000\000\024ftypqt  ";
150
 
  guint8 data1[8] = "\000\000\000\001mdat";
151
 
  guint8 data2[4] = "moov";
152
 
 
153
 
  qtmux = setup_qtmux (srctemplate, sinkname);
154
 
  fail_unless (gst_element_set_state (qtmux,
155
 
          GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
156
 
      "could not set to playing");
157
 
 
158
 
  inbuffer = gst_buffer_new_and_alloc (1);
159
 
  caps = gst_caps_copy (gst_pad_get_pad_template_caps (mysrcpad));
160
 
  gst_buffer_set_caps (inbuffer, caps);
161
 
  gst_caps_unref (caps);
162
 
  GST_BUFFER_TIMESTAMP (inbuffer) = 0;
163
 
  GST_BUFFER_DURATION (inbuffer) = 40 * GST_MSECOND;
164
 
  ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
165
 
  fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
166
 
 
167
 
  /* send eos to have moov written */
168
 
  fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()) == TRUE);
169
 
 
170
 
  num_buffers = g_list_length (buffers);
171
 
  /* at least expect ftyp, mdat header, buffer chunk and moov */
172
 
  fail_unless (num_buffers >= 4);
173
 
 
174
 
  for (i = 0; i < num_buffers; ++i) {
175
 
    outbuffer = GST_BUFFER (buffers->data);
176
 
    fail_if (outbuffer == NULL);
177
 
    buffers = g_list_remove (buffers, outbuffer);
178
 
 
179
 
    switch (i) {
180
 
      case 0:
181
 
      {
182
 
        /* ftyp header */
183
 
        guint8 *data = GST_BUFFER_DATA (outbuffer);
184
 
 
185
 
        fail_unless (GST_BUFFER_SIZE (outbuffer) >= 20);
186
 
        fail_unless (memcmp (data, data0, sizeof (data0)) == 0);
187
 
        fail_unless (memcmp (data + 16, data0 + 8, 4) == 0);
188
 
        break;
189
 
      }
190
 
      case 1:                  /* mdat header */
191
 
        fail_unless (GST_BUFFER_SIZE (outbuffer) == 16);
192
 
        fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), data1, sizeof (data1))
193
 
            == 0);
194
 
        break;
195
 
      case 2:                  /* buffer we put in */
196
 
        fail_unless (GST_BUFFER_SIZE (outbuffer) == 1);
197
 
        break;
198
 
      case 3:                  /* moov */
199
 
        fail_unless (GST_BUFFER_SIZE (outbuffer) > 8);
200
 
        fail_unless (memcmp (GST_BUFFER_DATA (outbuffer) + 4, data2,
201
 
                sizeof (data2)) == 0);
202
 
        break;
203
 
      default:
204
 
        break;
205
 
    }
206
 
 
207
 
    ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1);
208
 
    gst_buffer_unref (outbuffer);
209
 
    outbuffer = NULL;
210
 
  }
211
 
 
212
 
  g_list_free (buffers);
213
 
  buffers = NULL;
214
 
 
215
 
  cleanup_qtmux (qtmux, sinkname);
216
 
}
217
 
 
218
 
static void
219
 
check_qtmux_pad_fragmented (GstStaticPadTemplate * srctemplate,
220
 
    const gchar * sinkname, gboolean streamable)
221
 
{
222
 
  GstElement *qtmux;
223
 
  GstBuffer *inbuffer, *outbuffer;
224
 
  GstCaps *caps;
225
 
  int num_buffers;
226
 
  int i;
227
 
  guint8 data0[12] = "\000\000\000\024ftypqt  ";
228
 
  guint8 data1[4] = "mdat";
229
 
  guint8 data2[4] = "moov";
230
 
  guint8 data3[4] = "moof";
231
 
  guint8 data4[4] = "mfra";
232
 
 
233
 
  qtmux = setup_qtmux (srctemplate, sinkname);
234
 
  g_object_set (qtmux, "fragment-duration", 2000, NULL);
235
 
  g_object_set (qtmux, "streamable", streamable, NULL);
236
 
  fail_unless (gst_element_set_state (qtmux,
237
 
          GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
238
 
      "could not set to playing");
239
 
 
240
 
  inbuffer = gst_buffer_new_and_alloc (1);
241
 
  caps = gst_caps_copy (gst_pad_get_pad_template_caps (mysrcpad));
242
 
  gst_buffer_set_caps (inbuffer, caps);
243
 
  gst_caps_unref (caps);
244
 
  GST_BUFFER_TIMESTAMP (inbuffer) = 0;
245
 
  GST_BUFFER_DURATION (inbuffer) = 40 * GST_MSECOND;
246
 
  ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
247
 
  fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
248
 
 
249
 
  /* send eos to have all written */
250
 
  fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()) == TRUE);
251
 
 
252
 
  num_buffers = g_list_length (buffers);
253
 
  /* at least expect ftyp, moov, moof, mdat header, buffer chunk
254
 
   * and optionally mfra */
255
 
  fail_unless (num_buffers >= 5);
256
 
 
257
 
  for (i = 0; i < num_buffers; ++i) {
258
 
    outbuffer = GST_BUFFER (buffers->data);
259
 
    fail_if (outbuffer == NULL);
260
 
    buffers = g_list_remove (buffers, outbuffer);
261
 
 
262
 
    switch (i) {
263
 
      case 0:
264
 
      {
265
 
        /* ftyp header */
266
 
        guint8 *data = GST_BUFFER_DATA (outbuffer);
267
 
 
268
 
        fail_unless (GST_BUFFER_SIZE (outbuffer) >= 20);
269
 
        fail_unless (memcmp (data, data0, sizeof (data0)) == 0);
270
 
        fail_unless (memcmp (data + 16, data0 + 8, 4) == 0);
271
 
        break;
272
 
      }
273
 
      case 1:                  /* moov */
274
 
        fail_unless (GST_BUFFER_SIZE (outbuffer) > 8);
275
 
        fail_unless (memcmp (GST_BUFFER_DATA (outbuffer) + 4, data2,
276
 
                sizeof (data2)) == 0);
277
 
        break;
278
 
      case 2:                  /* moof */
279
 
        fail_unless (GST_BUFFER_SIZE (outbuffer) > 8);
280
 
        fail_unless (memcmp (GST_BUFFER_DATA (outbuffer) + 4, data3,
281
 
                sizeof (data3)) == 0);
282
 
        break;
283
 
      case 3:                  /* mdat header */
284
 
        fail_unless (GST_BUFFER_SIZE (outbuffer) == 8);
285
 
        fail_unless (memcmp (GST_BUFFER_DATA (outbuffer) + 4, data1,
286
 
                sizeof (data1)) == 0);
287
 
        break;
288
 
      case 4:                  /* buffer we put in */
289
 
        fail_unless (GST_BUFFER_SIZE (outbuffer) == 1);
290
 
        break;
291
 
      case 5:                  /* mfra */
292
 
        fail_unless (GST_BUFFER_SIZE (outbuffer) > 8);
293
 
        fail_unless (memcmp (GST_BUFFER_DATA (outbuffer) + 4, data4,
294
 
                sizeof (data4)) == 0);
295
 
        break;
296
 
      default:
297
 
        break;
298
 
    }
299
 
 
300
 
    ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1);
301
 
    gst_buffer_unref (outbuffer);
302
 
    outbuffer = NULL;
303
 
  }
304
 
 
305
 
  g_list_free (buffers);
306
 
  buffers = NULL;
307
 
 
308
 
  cleanup_qtmux (qtmux, sinkname);
309
 
}
310
 
 
311
 
 
312
 
GST_START_TEST (test_video_pad)
313
 
{
314
 
  check_qtmux_pad (&srcvideotemplate, "video_%d");
315
 
}
316
 
 
317
 
GST_END_TEST;
318
 
 
319
 
GST_START_TEST (test_audio_pad)
320
 
{
321
 
  check_qtmux_pad (&srcaudiotemplate, "audio_%d");
322
 
}
323
 
 
324
 
GST_END_TEST;
325
 
 
326
 
 
327
 
GST_START_TEST (test_video_pad_frag)
328
 
{
329
 
  check_qtmux_pad_fragmented (&srcvideotemplate, "video_%d", FALSE);
330
 
}
331
 
 
332
 
GST_END_TEST;
333
 
 
334
 
GST_START_TEST (test_audio_pad_frag)
335
 
{
336
 
  check_qtmux_pad_fragmented (&srcaudiotemplate, "audio_%d", FALSE);
337
 
}
338
 
 
339
 
GST_END_TEST;
340
 
 
341
 
 
342
 
GST_START_TEST (test_video_pad_frag_streamable)
343
 
{
344
 
  check_qtmux_pad_fragmented (&srcvideotemplate, "video_%d", TRUE);
345
 
}
346
 
 
347
 
GST_END_TEST;
348
 
 
349
 
 
350
 
GST_START_TEST (test_audio_pad_frag_streamable)
351
 
{
352
 
  check_qtmux_pad_fragmented (&srcaudiotemplate, "audio_%d", TRUE);
353
 
}
354
 
 
355
 
GST_END_TEST;
356
 
 
357
 
 
358
 
GST_START_TEST (test_reuse)
359
 
{
360
 
  GstElement *qtmux = setup_qtmux (&srcvideotemplate, "video_%d");
361
 
  GstBuffer *inbuffer;
362
 
  GstCaps *caps;
363
 
 
364
 
  gst_element_set_state (qtmux, GST_STATE_PLAYING);
365
 
  gst_element_set_state (qtmux, GST_STATE_NULL);
366
 
  gst_element_set_state (qtmux, GST_STATE_PLAYING);
367
 
  gst_pad_set_active (mysrcpad, TRUE);
368
 
  gst_pad_set_active (mysinkpad, TRUE);
369
 
 
370
 
  inbuffer = gst_buffer_new_and_alloc (1);
371
 
  fail_unless (inbuffer != NULL);
372
 
  caps = gst_caps_copy (gst_pad_get_pad_template_caps (mysrcpad));
373
 
  gst_buffer_set_caps (inbuffer, caps);
374
 
  gst_caps_unref (caps);
375
 
  GST_BUFFER_TIMESTAMP (inbuffer) = 0;
376
 
  GST_BUFFER_DURATION (inbuffer) = 40 * GST_MSECOND;
377
 
  ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
378
 
  fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
379
 
 
380
 
  /* send eos to have all written */
381
 
  fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()) == TRUE);
382
 
 
383
 
  cleanup_qtmux (qtmux, "video_%d");
384
 
}
385
 
 
386
 
GST_END_TEST;
387
 
 
388
 
static Suite *
389
 
qtmux_suite (void)
390
 
{
391
 
  Suite *s = suite_create ("qtmux");
392
 
  TCase *tc_chain = tcase_create ("general");
393
 
 
394
 
  suite_add_tcase (s, tc_chain);
395
 
  tcase_add_test (tc_chain, test_video_pad);
396
 
  tcase_add_test (tc_chain, test_audio_pad);
397
 
  tcase_add_test (tc_chain, test_video_pad_frag);
398
 
  tcase_add_test (tc_chain, test_audio_pad_frag);
399
 
  tcase_add_test (tc_chain, test_video_pad_frag_streamable);
400
 
  tcase_add_test (tc_chain, test_audio_pad_frag_streamable);
401
 
 
402
 
  tcase_add_test (tc_chain, test_reuse);
403
 
 
404
 
  return s;
405
 
}
406
 
 
407
 
int
408
 
main (int argc, char **argv)
409
 
{
410
 
  int nf;
411
 
 
412
 
  Suite *s = qtmux_suite ();
413
 
  SRunner *sr = srunner_create (s);
414
 
 
415
 
  gst_check_init (&argc, &argv);
416
 
 
417
 
  srunner_run_all (sr, CK_NORMAL);
418
 
  nf = srunner_ntests_failed (sr);
419
 
  srunner_free (sr);
420
 
 
421
 
  return nf;
422
 
}