rtp-payloading.c 28.5 KB
Newer Older
1
/* GStreamer RTP payloader unit tests
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
 * Copyright (C) 2008 Nokia Corporation and its subsidary(-ies)
 *               contact: <stefan.kost@nokia.com>
 *
 * 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
Tim-Philipp Müller's avatar
Tim-Philipp Müller committed
17 18
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA 02110-1301, USA.
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
 */
#include <gst/check/gstcheck.h>
#include <stdlib.h>
#include <unistd.h>

#define RELEASE_ELEMENT(x) if(x) {gst_object_unref(x); x = NULL;}

#define LOOP_COUNT 1

/*
 * RTP pipeline structure to store the required elements.
 */
typedef struct
{
  GstElement *pipeline;
34
  GstElement *appsrc;
35 36 37
  GstElement *rtppay;
  GstElement *rtpdepay;
  GstElement *fakesink;
38
  const guint8 *frame_data;
39 40 41 42
  int frame_data_size;
  int frame_count;
} rtp_pipeline;

43 44 45 46 47 48 49 50 51
/*
 * Number of bytes received in the chain list function when using buffer lists
 */
static guint chain_list_bytes_received;

/*
 * Chain list function for testing buffer lists
 */
static GstFlowReturn
Wim Taymans's avatar
Wim Taymans committed
52
rtp_pipeline_chain_list (GstPad * pad, GstObject * parent, GstBufferList * list)
53
{
Wim Taymans's avatar
Wim Taymans committed
54
  guint i, len;
55 56 57 58 59

  fail_if (!list);
  /*
   * Count the size of the payload in the buffer list.
   */
Wim Taymans's avatar
Wim Taymans committed
60
  len = gst_buffer_list_length (list);
61 62

  /* Loop through all groups */
Wim Taymans's avatar
Wim Taymans committed
63
  for (i = 0; i < len; i++) {
64
    GstBuffer *paybuf;
65 66
    GstMemory *mem;
    gint size;
67

Wim Taymans's avatar
Wim Taymans committed
68
    paybuf = gst_buffer_list_get (list, i);
69 70 71 72 73 74 75
    /* only count real data which is expected in last memory block */
    fail_unless (gst_buffer_n_memory (paybuf) > 1);
    mem = gst_buffer_get_memory_range (paybuf, gst_buffer_n_memory (paybuf) - 1,
        1);
    size = gst_memory_get_sizes (mem, NULL, NULL);
    gst_memory_unref (mem);
    chain_list_bytes_received += size;
76 77 78 79 80 81
  }
  gst_buffer_list_unref (list);

  return GST_FLOW_OK;
}

82 83 84
/*
 * RTP bus callback.
 */
85
static gboolean
86 87 88 89 90 91 92 93
rtp_bus_callback (GstBus * bus, GstMessage * message, gpointer data)
{
  GMainLoop *mainloop = (GMainLoop *) data;

  switch (GST_MESSAGE_TYPE (message)) {
    case GST_MESSAGE_ERROR:
    {
      GError *err;
94

95
      gchar *debug;
96

97
      gchar *element_name;
98

99
      element_name = (message->src) ? gst_object_get_name (message->src) : NULL;
100
      gst_message_parse_error (message, &err, &debug);
101 102
      g_print ("\nError from element %s: %s\n%s\n\n",
          GST_STR_NULL (element_name), err->message, (debug) ? debug : "");
103 104
      g_error_free (err);
      g_free (debug);
105
      g_free (element_name);
106

107 108
      fail_if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ERROR);

109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
      g_main_loop_quit (mainloop);
    }
      break;

    case GST_MESSAGE_EOS:
    {
      g_main_loop_quit (mainloop);
    }
      break;
      break;

    default:
    {
    }
      break;
  }

  return TRUE;
}

/*
 * Creates a RTP pipeline for one test.
 * @param frame_data Pointer to the frame data which is used to pass thru pay/depayloaders.
 * @param frame_data_size Frame data size in bytes.
 * @param frame_count Frame count.
 * @param filtercaps Caps filters.
 * @param pay Payloader name.
 * @param depay Depayloader name.
 * @return
 * Returns pointer to the RTP pipeline.
 * The user must free the RTP pipeline when it's not used anymore.
 */
141
static rtp_pipeline *
142
rtp_pipeline_create (const guint8 * frame_data, int frame_data_size,
143 144
    int frame_count, const char *filtercaps, const char *pay, const char *depay)
{
145
  gchar *pipeline_name;
146 147 148
  rtp_pipeline *p;
  GstCaps *caps;

149 150 151 152 153 154
  /* Check parameters. */
  if (!frame_data || !pay || !depay) {
    return NULL;
  }

  /* Allocate memory for the RTP pipeline. */
155
  p = (rtp_pipeline *) malloc (sizeof (rtp_pipeline));
156 157 158 159 160 161

  p->frame_data = frame_data;
  p->frame_data_size = frame_data_size;
  p->frame_count = frame_count;

  /* Create elements. */
162 163 164
  pipeline_name = g_strdup_printf ("%s-%s-pipeline", pay, depay);
  p->pipeline = gst_pipeline_new (pipeline_name);
  g_free (pipeline_name);
165
  p->appsrc = gst_element_factory_make ("appsrc", NULL);
166 167 168 169 170
  p->rtppay = gst_element_factory_make (pay, NULL);
  p->rtpdepay = gst_element_factory_make (depay, NULL);
  p->fakesink = gst_element_factory_make ("fakesink", NULL);

  /* One or more elements are not created successfully or failed to create p? */
171
  if (!p->pipeline || !p->appsrc || !p->rtppay || !p->rtpdepay || !p->fakesink) {
172 173
    /* Release created elements. */
    RELEASE_ELEMENT (p->pipeline);
174
    RELEASE_ELEMENT (p->appsrc);
175 176 177 178 179 180 181 182 183 184
    RELEASE_ELEMENT (p->rtppay);
    RELEASE_ELEMENT (p->rtpdepay);
    RELEASE_ELEMENT (p->fakesink);

    /* Release allocated memory. */
    free (p);

    return NULL;
  }

185
  /* Set src properties. */
186
  caps = gst_caps_from_string (filtercaps);
187 188
  g_object_set (p->appsrc, "do-timestamp", TRUE, "caps", caps,
      "format", GST_FORMAT_TIME, NULL);
189 190 191
  gst_caps_unref (caps);

  /* Add elements to the pipeline. */
192
  gst_bin_add (GST_BIN (p->pipeline), p->appsrc);
193 194 195 196 197
  gst_bin_add (GST_BIN (p->pipeline), p->rtppay);
  gst_bin_add (GST_BIN (p->pipeline), p->rtpdepay);
  gst_bin_add (GST_BIN (p->pipeline), p->fakesink);

  /* Link elements. */
198
  gst_element_link (p->appsrc, p->rtppay);
199 200 201 202 203 204 205 206 207 208
  gst_element_link (p->rtppay, p->rtpdepay);
  gst_element_link (p->rtpdepay, p->fakesink);

  return p;
}

/*
 * Destroys the RTP pipeline.
 * @param p Pointer to the RTP pipeline.
 */
209
static void
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
rtp_pipeline_destroy (rtp_pipeline * p)
{
  /* Check parameters. */
  if (p == NULL) {
    return;
  }

  /* Release pipeline. */
  RELEASE_ELEMENT (p->pipeline);

  /* Release allocated memory. */
  free (p);
}

/*
 * Runs the RTP pipeline.
 * @param p Pointer to the RTP pipeline.
 */
228
static void
229 230
rtp_pipeline_run (rtp_pipeline * p)
{
231
  GstFlowReturn flow_ret;
232
  GMainLoop *mainloop = NULL;
233
  GstBus *bus;
234
  gint i, j;
235

236 237 238 239 240 241 242 243 244 245 246 247
  /* Check parameters. */
  if (p == NULL) {
    return;
  }

  /* Create mainloop. */
  mainloop = g_main_loop_new (NULL, FALSE);
  if (!mainloop) {
    return;
  }

  /* Add bus callback. */
248
  bus = gst_pipeline_get_bus (GST_PIPELINE (p->pipeline));
249 250 251 252 253 254 255

  gst_bus_add_watch (bus, rtp_bus_callback, (gpointer) mainloop);
  gst_object_unref (bus);

  /* Set pipeline to PLAYING. */
  gst_element_set_state (p->pipeline, GST_STATE_PLAYING);

256
  /* Push data into the pipeline */
257
  for (i = 0; i < LOOP_COUNT; i++) {
258 259 260 261 262
    const guint8 *data = p->frame_data;

    for (j = 0; j < p->frame_count; j++) {
      GstBuffer *buf;

Wim Taymans's avatar
Wim Taymans committed
263
      buf =
264 265 266
          gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
          (guint8 *) data, p->frame_data_size, 0, p->frame_data_size, NULL,
          NULL);
267 268 269 270 271 272

      g_signal_emit_by_name (p->appsrc, "push-buffer", buf, &flow_ret);
      fail_unless_equals_int (flow_ret, GST_FLOW_OK);
      data += p->frame_data_size;

      gst_buffer_unref (buf);
273 274 275
    }
  }

276 277
  g_signal_emit_by_name (p->appsrc, "end-of-stream", &flow_ret);

278 279 280 281 282 283 284 285 286 287
  /* Run mainloop. */
  g_main_loop_run (mainloop);

  /* Set pipeline to NULL. */
  gst_element_set_state (p->pipeline, GST_STATE_NULL);

  /* Release mainloop. */
  g_main_loop_unref (mainloop);
}

288
/*
289
 * Enables buffer lists and adds a chain_list_function to the depayloader.
290 291 292 293 294
 * @param p Pointer to the RTP pipeline.
 */
static void
rtp_pipeline_enable_lists (rtp_pipeline * p, guint mtu_size)
{
295 296
  GstPad *pad;

297 298 299 300 301 302
  /* set mtu size if needed */
  if (mtu_size) {
    g_object_set (p->rtppay, "mtu", mtu_size, NULL);
  }

  /* Add chain list function for the buffer list tests */
303 304 305 306
  pad = gst_element_get_static_pad (p->rtpdepay, "sink");
  gst_pad_set_chain_list_function (pad,
      GST_DEBUG_FUNCPTR (rtp_pipeline_chain_list));
  gst_object_unref (pad);
307 308
}

309 310 311 312 313 314 315 316
/*
 * Creates the RTP pipeline and runs the test using the pipeline.
 * @param frame_data Pointer to the frame data which is used to pass thru pay/depayloaders.
 * @param frame_data_size Frame data size in bytes.
 * @param frame_count Frame count.
 * @param filtercaps Caps filters.
 * @param pay Payloader name.
 * @param depay Depayloader name.
317 318 319
 * @bytes_sent bytes that will be sent, used when testing buffer lists
 * @mtu_size set mtu size when testing lists
 * @use_lists enable buffer lists
320
 */
321
static void
322 323
rtp_pipeline_test (const guint8 * frame_data, int frame_data_size,
    int frame_count, const char *filtercaps, const char *pay, const char *depay,
324
    guint bytes_sent, guint mtu_size, gboolean use_lists)
325 326 327 328 329
{
  /* Create RTP pipeline. */
  rtp_pipeline *p =
      rtp_pipeline_create (frame_data, frame_data_size, frame_count, filtercaps,
      pay, depay);
330

331 332 333 334
  if (p == NULL) {
    return;
  }

335 336 337 338 339
  if (use_lists) {
    rtp_pipeline_enable_lists (p, mtu_size);
    chain_list_bytes_received = 0;
  }

340 341 342 343 344
  /* Run RTP pipeline. */
  rtp_pipeline_run (p);

  /* Destroy RTP pipeline. */
  rtp_pipeline_destroy (p);
345 346 347 348 349

  if (use_lists) {
    /* 'next NAL' indicator is 4 bytes */
    fail_if (chain_list_bytes_received != bytes_sent * LOOP_COUNT);
  }
350 351
}

352
static const guint8 rtp_ilbc_frame_data[] =
353
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
354 355
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
356

357
static int rtp_ilbc_frame_data_size = 20;
358

359 360 361 362 363 364
static int rtp_ilbc_frame_count = 1;

GST_START_TEST (rtp_ilbc)
{
  rtp_pipeline_test (rtp_ilbc_frame_data, rtp_ilbc_frame_data_size,
      rtp_ilbc_frame_count, "audio/x-iLBC,mode=20", "rtpilbcpay",
365
      "rtpilbcdepay", 0, 0, FALSE);
366
}
367 368

GST_END_TEST;
369
static const guint8 rtp_gsm_frame_data[] =
370
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
371 372
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
373

374
static int rtp_gsm_frame_data_size = 20;
375

376 377 378 379 380 381
static int rtp_gsm_frame_count = 1;

GST_START_TEST (rtp_gsm)
{
  rtp_pipeline_test (rtp_gsm_frame_data, rtp_gsm_frame_data_size,
      rtp_gsm_frame_count, "audio/x-gsm,rate=8000,channels=1", "rtpgsmpay",
382
      "rtpgsmdepay", 0, 0, FALSE);
383
}
384 385

GST_END_TEST;
386
static const guint8 rtp_amr_frame_data[] =
Wim Taymans's avatar
Wim Taymans committed
387 388 389
    { 0x3c, 0x24, 0x03, 0xb3, 0x48, 0x10, 0x68, 0x46, 0x6c, 0xec, 0x03,
  0x7a, 0x37, 0x16, 0x41, 0x41, 0xc0, 0x00, 0x0d, 0xcd, 0x12, 0xed,
  0xad, 0x80, 0x00, 0x00, 0x11, 0x31, 0x00, 0x00, 0x0d, 0xa0
390
};
391

Wim Taymans's avatar
Wim Taymans committed
392
static int rtp_amr_frame_data_size = 32;
393

394 395 396 397 398 399
static int rtp_amr_frame_count = 1;

GST_START_TEST (rtp_amr)
{
  rtp_pipeline_test (rtp_amr_frame_data, rtp_amr_frame_data_size,
      rtp_amr_frame_count, "audio/AMR,channels=1,rate=8000", "rtpamrpay",
400
      "rtpamrdepay", 0, 0, FALSE);
401
}
402 403

GST_END_TEST;
404
static const guint8 rtp_pcma_frame_data[] =
405
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
406 407
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
408

409
static int rtp_pcma_frame_data_size = 20;
410

411 412 413 414 415 416
static int rtp_pcma_frame_count = 1;

GST_START_TEST (rtp_pcma)
{
  rtp_pipeline_test (rtp_pcma_frame_data, rtp_pcma_frame_data_size,
      rtp_pcma_frame_count, "audio/x-alaw,channels=1,rate=8000", "rtppcmapay",
417
      "rtppcmadepay", 0, 0, FALSE);
418
}
419 420

GST_END_TEST;
421
static const guint8 rtp_pcmu_frame_data[] =
422
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
423 424
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
425

426
static int rtp_pcmu_frame_data_size = 20;
427

428 429 430 431 432 433
static int rtp_pcmu_frame_count = 1;

GST_START_TEST (rtp_pcmu)
{
  rtp_pipeline_test (rtp_pcmu_frame_data, rtp_pcmu_frame_data_size,
      rtp_pcmu_frame_count, "audio/x-mulaw,channels=1,rate=8000", "rtppcmupay",
434
      "rtppcmudepay", 0, 0, FALSE);
435
}
436 437

GST_END_TEST;
438
static const guint8 rtp_mpa_frame_data[] =
439
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
440 441
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
442

443
static int rtp_mpa_frame_data_size = 20;
444

445 446 447 448 449
static int rtp_mpa_frame_count = 1;

GST_START_TEST (rtp_mpa)
{
  rtp_pipeline_test (rtp_mpa_frame_data, rtp_mpa_frame_data_size,
450 451
      rtp_mpa_frame_count, "audio/mpeg,mpegversion=1", "rtpmpapay",
      "rtpmpadepay", 0, 0, FALSE);
452
}
453 454

GST_END_TEST;
455
static const guint8 rtp_h263_frame_data[] =
456
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
457 458
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
459

460
static int rtp_h263_frame_data_size = 20;
461

462 463 464 465 466
static int rtp_h263_frame_count = 1;

GST_START_TEST (rtp_h263)
{
  rtp_pipeline_test (rtp_h263_frame_data, rtp_h263_frame_data_size,
467
      rtp_h263_frame_count, "video/x-h263,variant=(string)itu,h263version=h263",
468
      "rtph263pay", "rtph263depay", 0, 0, FALSE);
469
}
470 471

GST_END_TEST;
472
static const guint8 rtp_h263p_frame_data[] =
473
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
474 475
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
476

477
static int rtp_h263p_frame_data_size = 20;
478

479 480 481 482 483
static int rtp_h263p_frame_count = 1;

GST_START_TEST (rtp_h263p)
{
  rtp_pipeline_test (rtp_h263p_frame_data, rtp_h263p_frame_data_size,
484 485
      rtp_h263p_frame_count, "video/x-h263,variant=(string)itu,"
      "h263version=(string)h263", "rtph263ppay", "rtph263pdepay", 0, 0, FALSE);
486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505

  /* payloader should accept any input that matches the template caps
   * if there's just a udpsink or fakesink downstream */
  rtp_pipeline_test (rtp_h263p_frame_data, rtp_h263p_frame_data_size,
      rtp_h263p_frame_count, "video/x-h263,variant=(string)itu,"
      "h263version=(string)h263", "rtph263ppay", "identity", 0, 0, FALSE);

  /* default output of avenc_h263p */
  rtp_pipeline_test (rtp_h263p_frame_data, rtp_h263p_frame_data_size,
      rtp_h263p_frame_count, "video/x-h263,variant=(string)itu,"
      "h263version=(string)h263p, annex-f=(boolean)true, "
      "annex-j=(boolean)true, annex-i=(boolean)true, annex-t=(boolean)true",
      "rtph263ppay", "identity", 0, 0, FALSE);

  /* pay ! depay should also work with any input */
  rtp_pipeline_test (rtp_h263p_frame_data, rtp_h263p_frame_data_size,
      rtp_h263p_frame_count, "video/x-h263,variant=(string)itu,"
      "h263version=(string)h263p, annex-f=(boolean)true, "
      "annex-j=(boolean)true, annex-i=(boolean)true, annex-t=(boolean)true",
      "rtph263ppay", "rtph263pdepay", 0, 0, FALSE);
506
}
507 508

GST_END_TEST;
509
static const guint8 rtp_h264_frame_data[] =
510
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
511 512
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
513

514
static int rtp_h264_frame_data_size = 20;
515

516 517 518 519
static int rtp_h264_frame_count = 1;

GST_START_TEST (rtp_h264)
{
520
  /* FIXME 0.11: fully specify h264 caps (and make payloader check) */
521
  rtp_pipeline_test (rtp_h264_frame_data, rtp_h264_frame_data_size,
522
      rtp_h264_frame_count,
523 524
      "video/x-h264,stream-format=(string)byte-stream,alignment=(string)nal",
      "rtph264pay", "rtph264depay", 0, 0, FALSE);
525 526 527
}

GST_END_TEST;
528
static const guint8 rtp_h264_list_lt_mtu_frame_data[] =
529 530
    /* not packetized, next NAL starts with 0001 */
{ 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
531
  0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
532 533 534 535 536 537 538
  0xad, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00
};

static int rtp_h264_list_lt_mtu_frame_data_size = 16;

static int rtp_h264_list_lt_mtu_frame_count = 2;

539 540 541
/* NAL = 4 bytes */
/* also 2 bytes FU-A header each time */
static int rtp_h264_list_lt_mtu_bytes_sent = 2 * (16 - 4);
542 543 544 545 546

static int rtp_h264_list_lt_mtu_mtu_size = 1024;

GST_START_TEST (rtp_h264_list_lt_mtu)
{
547
  /* FIXME 0.11: fully specify h264 caps (and make payloader check) */
548 549
  rtp_pipeline_test (rtp_h264_list_lt_mtu_frame_data,
      rtp_h264_list_lt_mtu_frame_data_size, rtp_h264_list_lt_mtu_frame_count,
550 551
      "video/x-h264,stream-format=(string)byte-stream,alignment=(string)nal",
      "rtph264pay", "rtph264depay",
552 553 554
      rtp_h264_list_lt_mtu_bytes_sent, rtp_h264_list_lt_mtu_mtu_size, TRUE);
}

555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573
GST_END_TEST;
static const guint8 rtp_h264_list_lt_mtu_frame_data_avc[] =
    /* packetized data */
{ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
  0xad, 0x80, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x0d, 0x00
};

/* NAL = 4 bytes */
static int rtp_h264_list_lt_mtu_bytes_sent_avc = 2 * (16 - 2 * 4);

//static int rtp_h264_list_lt_mtu_mtu_size = 1024;

GST_START_TEST (rtp_h264_list_lt_mtu_avc)
{
  /* FIXME 0.11: fully specify h264 caps (and make payloader check) */
  rtp_pipeline_test (rtp_h264_list_lt_mtu_frame_data_avc,
      rtp_h264_list_lt_mtu_frame_data_size, rtp_h264_list_lt_mtu_frame_count,
      "video/x-h264,stream-format=(string)avc,alignment=(string)au,"
574 575 576
      "codec_data=(buffer)01640014ffe1001867640014acd94141fb0110000003001773594000f142996001000568ebecb22c",
      "rtph264pay", "rtph264depay",
      rtp_h264_list_lt_mtu_bytes_sent_avc, rtp_h264_list_lt_mtu_mtu_size, TRUE);
577 578
}

579
GST_END_TEST;
580
static const guint8 rtp_h264_list_gt_mtu_frame_data[] =
581 582 583 584 585 586 587 588 589 590 591 592 593 594
    /* not packetized, next NAL starts with 0001 */
{ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

static int rtp_h264_list_gt_mtu_frame_data_size = 64;

static int rtp_h264_list_gt_mtu_frame_count = 1;

/* NAL = 4 bytes. When data does not fit into 1 mtu, 1 byte will be skipped */
595
static int rtp_h264_list_gt_mtu_bytes_sent = 1 * (64 - 4) - 1;
596 597 598 599 600

static int rtp_h264_list_gt_mtu_mty_size = 28;

GST_START_TEST (rtp_h264_list_gt_mtu)
{
601
  /* FIXME 0.11: fully specify h264 caps (and make payloader check) */
602 603
  rtp_pipeline_test (rtp_h264_list_gt_mtu_frame_data,
      rtp_h264_list_gt_mtu_frame_data_size, rtp_h264_list_gt_mtu_frame_count,
604 605
      "video/x-h264,stream-format=(string)byte-stream,alignment=(string)nal",
      "rtph264pay", "rtph264depay",
606
      rtp_h264_list_gt_mtu_bytes_sent, rtp_h264_list_gt_mtu_mty_size, TRUE);
607
}
608 609

GST_END_TEST;
610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628
static const guint8 rtp_h264_list_gt_mtu_frame_data_avc[] =
    /* packetized data */
{ 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

/* NAL = 4 bytes. When data does not fit into 1 mtu, 1 byte will be skipped */
static int rtp_h264_list_gt_mtu_bytes_sent_avc = 1 * (64 - 2 * 4 - 2 * 1);

GST_START_TEST (rtp_h264_list_gt_mtu_avc)
{
  /* FIXME 0.11: fully specify h264 caps (and make payloader check) */
  rtp_pipeline_test (rtp_h264_list_gt_mtu_frame_data_avc,
      rtp_h264_list_gt_mtu_frame_data_size, rtp_h264_list_gt_mtu_frame_count,
      "video/x-h264,stream-format=(string)avc,alignment=(string)au,"
629 630 631
      "codec_data=(buffer)01640014ffe1001867640014acd94141fb0110000003001773594000f142996001000568ebecb22c",
      "rtph264pay", "rtph264depay",
      rtp_h264_list_gt_mtu_bytes_sent_avc, rtp_h264_list_gt_mtu_mty_size, TRUE);
632 633 634 635
}

GST_END_TEST;

636
static const guint8 rtp_L16_frame_data[] =
637
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638 639
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
640

641
static int rtp_L16_frame_data_size = 20;
642

643 644 645 646 647 648
static int rtp_L16_frame_count = 1;

GST_START_TEST (rtp_L16)
{
  rtp_pipeline_test (rtp_L16_frame_data, rtp_L16_frame_data_size,
      rtp_L16_frame_count,
649
      "audio/x-raw,format=S16BE,rate=1,channels=1,layout=(string)interleaved",
650
      "rtpL16pay", "rtpL16depay", 0, 0, FALSE);
651
}
652 653

GST_END_TEST;
654
static const guint8 rtp_mp2t_frame_data[] =
655
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
656 657
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
658

659
static int rtp_mp2t_frame_data_size = 20;
660

661 662 663 664 665 666
static int rtp_mp2t_frame_count = 1;

GST_START_TEST (rtp_mp2t)
{
  rtp_pipeline_test (rtp_mp2t_frame_data, rtp_mp2t_frame_data_size,
      rtp_mp2t_frame_count, "video/mpegts,packetsize=188,systemstream=true",
667
      "rtpmp2tpay", "rtpmp2tdepay", 0, 0, FALSE);
668
}
669 670

GST_END_TEST;
671
static const guint8 rtp_mp4v_frame_data[] =
672
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
673 674
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
675

676
static int rtp_mp4v_frame_data_size = 20;
677

678 679 680 681 682 683
static int rtp_mp4v_frame_count = 1;

GST_START_TEST (rtp_mp4v)
{
  rtp_pipeline_test (rtp_mp4v_frame_data, rtp_mp4v_frame_data_size,
      rtp_mp4v_frame_count, "video/mpeg,mpegversion=4,systemstream=false",
684 685 686 687
      "rtpmp4vpay", "rtpmp4vdepay", 0, 0, FALSE);
}

GST_END_TEST;
688
static const guint8 rtp_mp4v_list_frame_data[] =
689 690 691 692 693 694 695 696 697 698 699 700 701 702
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

static int rtp_mp4v_list_frame_data_size = 20;

static int rtp_mp4v_list_frame_count = 1;

static int rtp_mp4v_list_bytes_sent = 1 * 20;

GST_START_TEST (rtp_mp4v_list)
{
  rtp_pipeline_test (rtp_mp4v_list_frame_data, rtp_mp4v_list_frame_data_size,
      rtp_mp4v_list_frame_count,
703
      "video/mpeg,mpegversion=4,systemstream=false,codec_data=(buffer)000001b001",
704
      "rtpmp4vpay", "rtpmp4vdepay", rtp_mp4v_list_bytes_sent, 0, TRUE);
705
}
706 707

GST_END_TEST;
708
static const guint8 rtp_mp4g_frame_data[] =
709
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
710 711
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
712

713
static int rtp_mp4g_frame_data_size = 20;
714

715 716 717 718 719
static int rtp_mp4g_frame_count = 1;

GST_START_TEST (rtp_mp4g)
{
  rtp_pipeline_test (rtp_mp4g_frame_data, rtp_mp4g_frame_data_size,
Wim Taymans's avatar
Wim Taymans committed
720
      rtp_mp4g_frame_count,
721 722
      "video/mpeg,mpegversion=4,systemstream=false,codec_data=(buffer)000001b001",
      "rtpmp4gpay", "rtpmp4gdepay", 0, 0, FALSE);
723
}
724 725

GST_END_TEST;
726
static const guint8 rtp_theora_frame_data[] =
727
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
728 729
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
730

731
static int rtp_theora_frame_data_size = 20;
732

733 734 735 736 737 738
static int rtp_theora_frame_count = 1;

GST_START_TEST (rtp_theora)
{
  rtp_pipeline_test (rtp_theora_frame_data, rtp_theora_frame_data_size,
      rtp_theora_frame_count, "video/x-theora", "rtptheorapay",
739
      "rtptheoradepay", 0, 0, FALSE);
740
}
741 742

GST_END_TEST;
743
static const guint8 rtp_vorbis_frame_data[] =
744
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
745 746
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
747

748
static int rtp_vorbis_frame_data_size = 20;
749

750 751 752 753 754 755
static int rtp_vorbis_frame_count = 1;

GST_START_TEST (rtp_vorbis)
{
  rtp_pipeline_test (rtp_vorbis_frame_data, rtp_vorbis_frame_data_size,
      rtp_vorbis_frame_count, "audio/x-vorbis", "rtpvorbispay",
756 757 758 759
      "rtpvorbisdepay", 0, 0, FALSE);
}

GST_END_TEST;
760
static const guint8 rtp_jpeg_frame_data[] =
761
    { /* SOF */ 0xFF, 0xC0, 0x00, 0x11, 0x08, 0x00, 0x08, 0x00, 0x08,
Wim Taymans's avatar
Wim Taymans committed
762 763 764 765 766 767 768 769 770 771
  0x03, 0x00, 0x21, 0x08, 0x01, 0x11, 0x08, 0x02, 0x11, 0x08,
  /* DQT */ 0xFF, 0xDB, 0x00, 0x43, 0x08,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
772 773 774
  /* DATA */ 0x00, 0x00, 0x00, 0x00, 0x00
};

Wim Taymans's avatar
Wim Taymans committed
775
static int rtp_jpeg_frame_data_size = sizeof (rtp_jpeg_frame_data);
776 777 778 779 780 781

static int rtp_jpeg_frame_count = 1;

GST_START_TEST (rtp_jpeg)
{
  rtp_pipeline_test (rtp_jpeg_frame_data, rtp_jpeg_frame_data_size,
782 783
      rtp_jpeg_frame_count, "video/x-jpeg,height=640,width=480", "rtpjpegpay",
      "rtpjpegdepay", 0, 0, FALSE);
784 785 786
}

GST_END_TEST;
Jonas Holmberg's avatar
Jonas Holmberg committed
787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814

GST_START_TEST (rtp_jpeg_width_greater_than_2040)
{
  rtp_pipeline_test (rtp_jpeg_frame_data, rtp_jpeg_frame_data_size,
      rtp_jpeg_frame_count, "video/x-jpeg,height=2048,width=480", "rtpjpegpay",
      "rtpjpegdepay", 0, 0, FALSE);
}

GST_END_TEST;

GST_START_TEST (rtp_jpeg_height_greater_than_2040)
{
  rtp_pipeline_test (rtp_jpeg_frame_data, rtp_jpeg_frame_data_size,
      rtp_jpeg_frame_count, "video/x-jpeg,height=640,width=2048", "rtpjpegpay",
      "rtpjpegdepay", 0, 0, FALSE);
}

GST_END_TEST;

GST_START_TEST (rtp_jpeg_width_and_height_greater_than_2040)
{
  rtp_pipeline_test (rtp_jpeg_frame_data, rtp_jpeg_frame_data_size,
      rtp_jpeg_frame_count, "video/x-jpeg,height=2048,width=2048", "rtpjpegpay",
      "rtpjpegdepay", 0, 0, FALSE);
}

GST_END_TEST;

815
static const guint8 rtp_jpeg_list_frame_data[] =
816
    { /* SOF */ 0xFF, 0xC0, 0x00, 0x11, 0x08, 0x00, 0x08, 0x00, 0x08,
Wim Taymans's avatar
Wim Taymans committed
817 818 819 820 821 822 823 824 825 826
  0x03, 0x00, 0x21, 0x08, 0x01, 0x11, 0x08, 0x02, 0x11, 0x08,
  /* DQT */ 0xFF, 0xDB, 0x00, 0x43, 0x08,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
827 828 829
  /* DATA */ 0x00, 0x00, 0x00, 0x00, 0x00
};

Wim Taymans's avatar
Wim Taymans committed
830
static int rtp_jpeg_list_frame_data_size = sizeof (rtp_jpeg_list_frame_data);
831 832 833

static int rtp_jpeg_list_frame_count = 1;

Wim Taymans's avatar
Wim Taymans committed
834
static int rtp_jpeg_list_bytes_sent = 1 * sizeof (rtp_jpeg_list_frame_data);
835 836 837 838 839 840

GST_START_TEST (rtp_jpeg_list)
{
  rtp_pipeline_test (rtp_jpeg_list_frame_data, rtp_jpeg_list_frame_data_size,
      rtp_jpeg_list_frame_count, "video/x-jpeg,height=640,width=480",
      "rtpjpegpay", "rtpjpegdepay", rtp_jpeg_list_bytes_sent, 0, TRUE);
841 842
}

843
GST_END_TEST;
Jonas Holmberg's avatar
Jonas Holmberg committed
844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871

GST_START_TEST (rtp_jpeg_list_width_greater_than_2040)
{
  rtp_pipeline_test (rtp_jpeg_list_frame_data, rtp_jpeg_list_frame_data_size,
      rtp_jpeg_list_frame_count, "video/x-jpeg,height=2048,width=480",
      "rtpjpegpay", "rtpjpegdepay", rtp_jpeg_list_bytes_sent, 0, TRUE);
}

GST_END_TEST;

GST_START_TEST (rtp_jpeg_list_height_greater_than_2040)
{
  rtp_pipeline_test (rtp_jpeg_list_frame_data, rtp_jpeg_list_frame_data_size,
      rtp_jpeg_list_frame_count, "video/x-jpeg,height=640,width=2048",
      "rtpjpegpay", "rtpjpegdepay", rtp_jpeg_list_bytes_sent, 0, TRUE);
}

GST_END_TEST;

GST_START_TEST (rtp_jpeg_list_width_and_height_greater_than_2040)
{
  rtp_pipeline_test (rtp_jpeg_list_frame_data, rtp_jpeg_list_frame_data_size,
      rtp_jpeg_list_frame_count, "video/x-jpeg,height=2048,width=2048",
      "rtpjpegpay", "rtpjpegdepay", rtp_jpeg_list_bytes_sent, 0, TRUE);
}

GST_END_TEST;

872
static const guint8 rtp_g729_frame_data[] =
873 874 875 876 877 878 879 880 881 882 883
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

static int rtp_g729_frame_data_size = 22;

static int rtp_g729_frame_count = 1;

GST_START_TEST (rtp_g729)
{
  rtp_pipeline_test (rtp_g729_frame_data, rtp_g729_frame_data_size,
884
      rtp_g729_frame_count, "audio/G729,rate=8000,channels=1", "rtpg729pay",
885 886 887 888 889
      "rtpg729depay", 0, 0, FALSE);
}

GST_END_TEST;

890 891 892 893 894
/*
 * Creates the test suite.
 *
 * Returns: pointer to the test suite.
 */
895
static Suite *
896
rtp_payloading_suite (void)
897 898
{
  Suite *s = suite_create ("rtp_data_test");
899

900 901 902 903 904 905 906 907 908 909 910 911 912 913 914
  TCase *tc_chain = tcase_create ("linear");

  /* Set timeout to 60 seconds. */
  tcase_set_timeout (tc_chain, 60);

  suite_add_tcase (s, tc_chain);
  tcase_add_test (tc_chain, rtp_ilbc);
  tcase_add_test (tc_chain, rtp_gsm);
  tcase_add_test (tc_chain, rtp_amr);
  tcase_add_test (tc_chain, rtp_pcma);
  tcase_add_test (tc_chain, rtp_pcmu);
  tcase_add_test (tc_chain, rtp_mpa);
  tcase_add_test (tc_chain, rtp_h263);
  tcase_add_test (tc_chain, rtp_h263p);
  tcase_add_test (tc_chain, rtp_h264);
915
  tcase_add_test (tc_chain, rtp_h264_list_lt_mtu);
916
  tcase_add_test (tc_chain, rtp_h264_list_lt_mtu_avc);
917
  tcase_add_test (tc_chain, rtp_h264_list_gt_mtu);
918
  tcase_add_test (tc_chain, rtp_h264_list_gt_mtu_avc);
919 920 921
  tcase_add_test (tc_chain, rtp_L16);
  tcase_add_test (tc_chain, rtp_mp2t);
  tcase_add_test (tc_chain, rtp_mp4v);
922
  tcase_add_test (tc_chain, rtp_mp4v_list);
923 924 925
  tcase_add_test (tc_chain, rtp_mp4g);
  tcase_add_test (tc_chain, rtp_theora);
  tcase_add_test (tc_chain, rtp_vorbis);
926
  tcase_add_test (tc_chain, rtp_jpeg);
Jonas Holmberg's avatar
Jonas Holmberg committed
927 928 929
  tcase_add_test (tc_chain, rtp_jpeg_width_greater_than_2040);
  tcase_add_test (tc_chain, rtp_jpeg_height_greater_than_2040);
  tcase_add_test (tc_chain, rtp_jpeg_width_and_height_greater_than_2040);
930
  tcase_add_test (tc_chain, rtp_jpeg_list);
Jonas Holmberg's avatar
Jonas Holmberg committed
931 932 933
  tcase_add_test (tc_chain, rtp_jpeg_list_width_greater_than_2040);
  tcase_add_test (tc_chain, rtp_jpeg_list_height_greater_than_2040);
  tcase_add_test (tc_chain, rtp_jpeg_list_width_and_height_greater_than_2040);
934
  tcase_add_test (tc_chain, rtp_g729);
935 936 937
  return s;
}

938
GST_CHECK_MAIN (rtp_payloading)