Asterisk - The Open Source Telephony Project  18.5.0
test_stream.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2017, Digium, Inc.
5  *
6  * Joshua Colp <[email protected]>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*!
20  * \file
21  * \brief Media Stream API Unit Tests
22  *
23  * \author Joshua Colp <[email protected]>
24  *
25  */
26 
27 /*** MODULEINFO
28  <depend>TEST_FRAMEWORK</depend>
29  <support_level>core</support_level>
30  ***/
31 
32 #include "asterisk.h"
33 
34 #include "asterisk/test.h"
35 #include "asterisk/module.h"
36 #include "asterisk/stream.h"
37 #include "asterisk/format.h"
38 #include "asterisk/format_cap.h"
39 #include "asterisk/format_cache.h"
40 #include "asterisk/channel.h"
41 #include "asterisk/uuid.h"
42 
43 AST_TEST_DEFINE(stream_create)
44 {
45  RAII_VAR(struct ast_stream *, stream, NULL, ast_stream_free);
46 
47  switch (cmd) {
48  case TEST_INIT:
49  info->name = "stream_create";
50  info->category = "/main/stream/";
51  info->summary = "stream create unit test";
52  info->description =
53  "Test that creating a stream results in a stream with the expected values";
54  return AST_TEST_NOT_RUN;
55  case TEST_EXECUTE:
56  break;
57  }
58 
59  stream = ast_stream_alloc("test", AST_MEDIA_TYPE_AUDIO);
60  if (!stream) {
61  ast_test_status_update(test, "Failed to create media stream given proper arguments\n");
62  return AST_TEST_FAIL;
63  }
64 
66  ast_test_status_update(test, "Newly created stream does not have expected inactive stream state\n");
67  return AST_TEST_FAIL;
68  }
69 
71  ast_test_status_update(test, "Newly created stream does not have expected audio media type\n");
72  return AST_TEST_FAIL;
73  }
74 
75  if (strcmp(ast_stream_get_name(stream), "test")) {
76  ast_test_status_update(test, "Newly created stream does not have expected name of test\n");
77  return AST_TEST_FAIL;
78  }
79 
80  return AST_TEST_PASS;
81 }
82 
83 AST_TEST_DEFINE(stream_create_no_name)
84 {
85  RAII_VAR(struct ast_stream *, stream, NULL, ast_stream_free);
86 
87  switch (cmd) {
88  case TEST_INIT:
89  info->name = "stream_create_no_name";
90  info->category = "/main/stream/";
91  info->summary = "stream create (without a name) unit test";
92  info->description =
93  "Test that creating a stream with no name works";
94  return AST_TEST_NOT_RUN;
95  case TEST_EXECUTE:
96  break;
97  }
98 
100  if (!stream) {
101  ast_test_status_update(test, "Failed to create media stream given proper arguments\n");
102  return AST_TEST_FAIL;
103  }
104 
105  return AST_TEST_PASS;
106 }
107 
108 AST_TEST_DEFINE(stream_set_type)
109 {
110  RAII_VAR(struct ast_stream *, stream, NULL, ast_stream_free);
111 
112  switch (cmd) {
113  case TEST_INIT:
114  info->name = "stream_set_type";
115  info->category = "/main/stream/";
116  info->summary = "stream type setting unit test";
117  info->description =
118  "Test that changing the type of a stream works";
119  return AST_TEST_NOT_RUN;
120  case TEST_EXECUTE:
121  break;
122  }
123 
124  stream = ast_stream_alloc("test", AST_MEDIA_TYPE_AUDIO);
125  if (!stream) {
126  ast_test_status_update(test, "Failed to create media stream given proper arguments\n");
127  return AST_TEST_FAIL;
128  }
129 
130  if (ast_stream_get_type(stream) != AST_MEDIA_TYPE_AUDIO) {
131  ast_test_status_update(test, "Newly created stream does not have expected audio media type\n");
132  return AST_TEST_FAIL;
133  }
134 
136 
137  if (ast_stream_get_type(stream) != AST_MEDIA_TYPE_VIDEO) {
138  ast_test_status_update(test, "Changed stream does not have expected video media type\n");
139  return AST_TEST_FAIL;
140  }
141 
142  return AST_TEST_PASS;
143 }
144 
145 AST_TEST_DEFINE(stream_set_formats)
146 {
147  RAII_VAR(struct ast_stream *, stream, NULL, ast_stream_free);
148  RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
149 
150  switch (cmd) {
151  case TEST_INIT:
152  info->name = "stream_set_formats";
153  info->category = "/main/stream/";
154  info->summary = "stream formats setting unit test";
155  info->description =
156  "Test that changing the formats of a stream works";
157  return AST_TEST_NOT_RUN;
158  case TEST_EXECUTE:
159  break;
160  }
161 
163  if (!caps) {
164  ast_test_status_update(test, "Failed to create a format capabilities structure for testing\n");
165  return AST_TEST_FAIL;
166  }
167 
168  stream = ast_stream_alloc("test", AST_MEDIA_TYPE_AUDIO);
169  if (!stream) {
170  ast_test_status_update(test, "Failed to create media stream given proper arguments\n");
171  return AST_TEST_FAIL;
172  }
173 
174  ast_stream_set_formats(stream, caps);
175 
176  if (ast_stream_get_formats(stream) != caps) {
177  ast_test_status_update(test, "Changed stream does not have expected formats\n");
178  return AST_TEST_FAIL;
179  }
180 
181  ast_stream_set_formats(stream, NULL);
182 
183  if (ast_stream_get_formats(stream)) {
184  ast_test_status_update(test, "Retrieved formats from stream despite removing them\n");
185  return AST_TEST_FAIL;
186  }
187 
188  return AST_TEST_PASS;
189 }
190 
191 AST_TEST_DEFINE(stream_set_state)
192 {
193  RAII_VAR(struct ast_stream *, stream, NULL, ast_stream_free);
194 
195  switch (cmd) {
196  case TEST_INIT:
197  info->name = "stream_set_state";
198  info->category = "/main/stream/";
199  info->summary = "stream state setting unit test";
200  info->description =
201  "Test that changing the state of a stream works";
202  return AST_TEST_NOT_RUN;
203  case TEST_EXECUTE:
204  break;
205  }
206 
207  stream = ast_stream_alloc("test", AST_MEDIA_TYPE_AUDIO);
208  if (!stream) {
209  ast_test_status_update(test, "Failed to create media stream given proper arguments\n");
210  return AST_TEST_FAIL;
211  }
212 
214  ast_test_status_update(test, "Newly created stream does not have expected inactive stream state\n");
215  return AST_TEST_FAIL;
216  }
217 
219 
221  ast_test_status_update(test, "Changed stream does not have expected sendrecv state\n");
222  return AST_TEST_FAIL;
223  }
224 
225  return AST_TEST_PASS;
226 }
227 
228 AST_TEST_DEFINE(stream_metadata)
229 {
230  RAII_VAR(struct ast_stream *, stream, NULL, ast_stream_free);
231  char track_label[AST_UUID_STR_LEN + 1];
232  const char *stream_track_label;
233  int rc;
234 
235  switch (cmd) {
236  case TEST_INIT:
237  info->name = "stream_metadata";
238  info->category = "/main/stream/";
239  info->summary = "stream metadata unit test";
240  info->description =
241  "Test that metadata operations on a stream works";
242  return AST_TEST_NOT_RUN;
243  case TEST_EXECUTE:
244  break;
245  }
246 
247  stream = ast_stream_alloc("test", AST_MEDIA_TYPE_AUDIO);
248  if (!stream) {
249  ast_test_status_update(test, "Failed to create media stream given proper arguments\n");
250  return AST_TEST_FAIL;
251  }
252 
253  stream_track_label = ast_stream_get_metadata(stream, "AST_STREAM_METADATA_TRACK_LABEL");
254  if (stream_track_label) {
255  ast_test_status_update(test, "New stream HAD a track label\n");
256  return AST_TEST_FAIL;
257  }
258 
259  ast_uuid_generate_str(track_label, sizeof(track_label));
260  rc = ast_stream_set_metadata(stream, "AST_STREAM_METADATA_TRACK_LABEL", track_label);
261  if (rc != 0) {
262  ast_test_status_update(test, "Failed to add track label\n");
263  return AST_TEST_FAIL;
264  }
265 
266  stream_track_label = ast_stream_get_metadata(stream, "AST_STREAM_METADATA_TRACK_LABEL");
267  if (!stream_track_label) {
268  ast_test_status_update(test, "Changed stream does not have a track label\n");
269  return AST_TEST_FAIL;
270  }
271 
272  if (strcmp(stream_track_label, track_label) != 0) {
273  ast_test_status_update(test, "Changed stream did not return same track label\n");
274  return AST_TEST_FAIL;
275  }
276 
277  rc = ast_stream_set_metadata(stream, "AST_STREAM_METADATA_TRACK_LABEL", NULL);
278  if (rc != 0) {
279  ast_test_status_update(test, "Failed to remove track label\n");
280  return AST_TEST_FAIL;
281  }
282 
283  stream_track_label = ast_stream_get_metadata(stream, "AST_STREAM_METADATA_TRACK_LABEL");
284  if (stream_track_label) {
285  ast_test_status_update(test, "Changed stream still had a track label after we removed it\n");
286  return AST_TEST_FAIL;
287  }
288 
289  return AST_TEST_PASS;
290 }
291 
292 AST_TEST_DEFINE(stream_topology_create)
293 {
295 
296  switch (cmd) {
297  case TEST_INIT:
298  info->name = "stream_topology_create";
299  info->category = "/main/stream/";
300  info->summary = "stream topology creation unit test";
301  info->description =
302  "Test that creating a stream topology works";
303  return AST_TEST_NOT_RUN;
304  case TEST_EXECUTE:
305  break;
306  }
307 
308  topology = ast_stream_topology_alloc();
309  if (!topology) {
310  ast_test_status_update(test, "Failed to create media stream topology\n");
311  return AST_TEST_FAIL;
312  }
313 
314  return AST_TEST_PASS;
315 }
316 
317 AST_TEST_DEFINE(stream_topology_clone)
318 {
321  struct ast_stream *audio_stream, *video_stream;
322  char audio_track_label[AST_UUID_STR_LEN + 1];
323  char video_track_label[AST_UUID_STR_LEN + 1];
324  const char *original_track_label;
325  const char *cloned_track_label;
326  int rc;
327 
328  switch (cmd) {
329  case TEST_INIT:
330  info->name = "stream_topology_clone";
331  info->category = "/main/stream/";
332  info->summary = "stream topology cloning unit test";
333  info->description =
334  "Test that cloning a stream topology results in a clone with the same contents";
335  return AST_TEST_NOT_RUN;
336  case TEST_EXECUTE:
337  break;
338  }
339 
340  topology = ast_stream_topology_alloc();
341  if (!topology) {
342  ast_test_status_update(test, "Failed to create media stream topology\n");
343  return AST_TEST_FAIL;
344  }
345 
346  audio_stream = ast_stream_alloc("audio", AST_MEDIA_TYPE_AUDIO);
347  if (!audio_stream) {
348  ast_test_status_update(test, "Failed to create an audio stream for testing stream topology\n");
349  return AST_TEST_FAIL;
350  }
351 
352  ast_uuid_generate_str(audio_track_label, sizeof(audio_track_label));
353  rc = ast_stream_set_metadata(audio_stream, "AST_STREAM_METADATA_TRACK_LABEL", audio_track_label);
354  if (rc != 0) {
355  ast_test_status_update(test, "Failed to add track label\n");
356  return AST_TEST_FAIL;
357  }
358 
359  if (ast_stream_topology_append_stream(topology, audio_stream) == -1) {
360  ast_test_status_update(test, "Failed to append valid audio stream to stream topology\n");
361  ast_stream_free(audio_stream);
362  return AST_TEST_FAIL;
363  }
364 
365  video_stream = ast_stream_alloc("video", AST_MEDIA_TYPE_VIDEO);
366  if (!video_stream) {
367  ast_test_status_update(test, "Failed to create a video stream for testing stream topology\n");
368  return AST_TEST_FAIL;
369  }
370 
371  ast_uuid_generate_str(video_track_label, sizeof(video_track_label));
372  rc = ast_stream_set_metadata(video_stream, "AST_STREAM_METADATA_TRACK_LABEL", video_track_label);
373  if (rc != 0) {
374  ast_test_status_update(test, "Failed to add track label\n");
375  return AST_TEST_FAIL;
376  }
377 
378  if (ast_stream_topology_append_stream(topology, video_stream) == -1) {
379  ast_test_status_update(test, "Failed to append valid video stream to stream topology\n");
380  ast_stream_free(video_stream);
381  return AST_TEST_FAIL;
382  }
383 
384  cloned = ast_stream_topology_clone(topology);
385  if (!cloned) {
386  ast_test_status_update(test, "Failed to clone a perfectly good stream topology\n");
387  return AST_TEST_FAIL;
388  }
389 
391  ast_test_status_update(test, "Cloned stream topology does not contain same number of streams as original\n");
392  return AST_TEST_FAIL;
393  }
394 
396  ast_test_status_update(test, "Cloned audio stream does not contain same type as original\n");
397  return AST_TEST_FAIL;
398  }
399 
400  original_track_label = ast_stream_get_metadata(ast_stream_topology_get_stream(topology, 0),
401  "AST_STREAM_METADATA_TRACK_LABEL");
402  if (!original_track_label) {
403  ast_test_status_update(test, "Original topology stream 0 does not contain metadata\n");
404  return AST_TEST_FAIL;
405  }
406  cloned_track_label = ast_stream_get_metadata(ast_stream_topology_get_stream(cloned, 0),
407  "AST_STREAM_METADATA_TRACK_LABEL");
408  if (!cloned_track_label) {
409  ast_test_status_update(test, "Cloned topology stream 0 does not contain metadata\n");
410  return AST_TEST_FAIL;
411  }
412  if (strcmp(original_track_label, cloned_track_label) != 0) {
413  ast_test_status_update(test, "Cloned topology stream 0 track label was not the same as the original\n");
414  return AST_TEST_FAIL;
415  }
416 
418  ast_test_status_update(test, "Cloned video stream does not contain same type as original\n");
419  return AST_TEST_FAIL;
420  }
421 
422  original_track_label = ast_stream_get_metadata(ast_stream_topology_get_stream(topology, 1),
423  "AST_STREAM_METADATA_TRACK_LABEL");
424  if (!original_track_label) {
425  ast_test_status_update(test, "Original topology stream 1 does not contain metadata\n");
426  return AST_TEST_FAIL;
427  }
428  cloned_track_label = ast_stream_get_metadata(ast_stream_topology_get_stream(cloned, 1),
429  "AST_STREAM_METADATA_TRACK_LABEL");
430  if (!cloned_track_label) {
431  ast_test_status_update(test, "Cloned topology stream 1 does not contain metadata\n");
432  return AST_TEST_FAIL;
433  }
434  if (strcmp(original_track_label, cloned_track_label) != 0) {
435  ast_test_status_update(test, "Cloned topology stream 1 track label was not the same as the original\n");
436  return AST_TEST_FAIL;
437  }
438 
439  return AST_TEST_PASS;
440 }
441 
442 AST_TEST_DEFINE(stream_topology_append_stream)
443 {
445  struct ast_stream *audio_stream, *video_stream;
446  int position;
447 
448  switch (cmd) {
449  case TEST_INIT:
450  info->name = "stream_topology_append_stream";
451  info->category = "/main/stream/";
452  info->summary = "stream topology stream appending unit test";
453  info->description =
454  "Test that appending streams to a stream topology works";
455  return AST_TEST_NOT_RUN;
456  case TEST_EXECUTE:
457  break;
458  }
459 
460  topology = ast_stream_topology_alloc();
461  if (!topology) {
462  ast_test_status_update(test, "Failed to create media stream topology\n");
463  return AST_TEST_FAIL;
464  }
465 
466  audio_stream = ast_stream_alloc("audio", AST_MEDIA_TYPE_AUDIO);
467  if (!audio_stream) {
468  ast_test_status_update(test, "Failed to create an audio stream for testing stream topology\n");
469  return AST_TEST_FAIL;
470  }
471 
472  position = ast_stream_topology_append_stream(topology, audio_stream);
473  if (position == -1) {
474  ast_test_status_update(test, "Failed to append valid audio stream to stream topology\n");
475  ast_stream_free(audio_stream);
476  return AST_TEST_FAIL;
477  } else if (position != 0) {
478  ast_test_status_update(test, "Appended audio stream to stream topology but position is '%d' instead of 0\n",
479  position);
480  return AST_TEST_FAIL;
481  }
482 
483  if (ast_stream_topology_get_count(topology) != 1) {
484  ast_test_status_update(test, "Appended an audio stream to the stream topology but stream count is '%d' on it, not 1\n",
486  return AST_TEST_FAIL;
487  }
488 
489  if (ast_stream_topology_get_stream(topology, 0) != audio_stream) {
490  ast_test_status_update(test, "Appended an audio stream to the stream topology but returned stream doesn't match\n");
491  return AST_TEST_FAIL;
492  }
493 
494  if (ast_stream_get_position(audio_stream) != 0) {
495  ast_test_status_update(test, "Appended audio stream says it is at position '%d' instead of 0\n",
496  ast_stream_get_position(audio_stream));
497  return AST_TEST_FAIL;
498  }
499 
500  video_stream = ast_stream_alloc("video", AST_MEDIA_TYPE_VIDEO);
501  if (!video_stream) {
502  ast_test_status_update(test, "Failed to create a video stream for testing stream topology\n");
503  return AST_TEST_FAIL;
504  }
505 
506  position = ast_stream_topology_append_stream(topology, video_stream);
507  if (position == -1) {
508  ast_test_status_update(test, "Failed to append valid video stream to stream topology\n");
509  ast_stream_free(video_stream);
510  return AST_TEST_FAIL;
511  } else if (position != 1) {
512  ast_test_status_update(test, "Appended video stream to stream topology but position is '%d' instead of 1\n",
513  position);
514  return AST_TEST_FAIL;
515  }
516 
517  if (ast_stream_topology_get_count(topology) != 2) {
518  ast_test_status_update(test, "Appended a video stream to the stream topology but stream count is '%d' on it, not 2\n",
520  return AST_TEST_FAIL;
521  }
522 
523  if (ast_stream_topology_get_stream(topology, 1) != video_stream) {
524  ast_test_status_update(test, "Appended a video stream to the stream topology but returned stream doesn't match\n");
525  return AST_TEST_FAIL;
526  }
527 
528  if (ast_stream_get_position(video_stream) != 1) {
529  ast_test_status_update(test, "Appended video stream says it is at position '%d' instead of 1\n",
530  ast_stream_get_position(video_stream));
531  return AST_TEST_FAIL;
532  }
533 
534  return AST_TEST_PASS;
535 }
536 
537 AST_TEST_DEFINE(stream_topology_set_stream)
538 {
540  struct ast_stream *audio_stream, *video_stream;
541 
542  switch (cmd) {
543  case TEST_INIT:
544  info->name = "stream_topology_set_stream";
545  info->category = "/main/stream/";
546  info->summary = "stream topology stream setting unit test";
547  info->description =
548  "Test that setting streams at a specific position in a topology works";
549  return AST_TEST_NOT_RUN;
550  case TEST_EXECUTE:
551  break;
552  }
553 
554  topology = ast_stream_topology_alloc();
555  if (!topology) {
556  ast_test_status_update(test, "Failed to create media stream topology\n");
557  return AST_TEST_FAIL;
558  }
559 
560  audio_stream = ast_stream_alloc("audio", AST_MEDIA_TYPE_AUDIO);
561  if (!audio_stream) {
562  ast_test_status_update(test, "Failed to create an audio stream for testing stream topology\n");
563  return AST_TEST_FAIL;
564  }
565 
566  if (ast_stream_topology_set_stream(topology, 0, audio_stream)) {
567  ast_test_status_update(test, "Failed to set an audio stream to a position where it is permitted\n");
568  ast_stream_free(audio_stream);
569  return AST_TEST_FAIL;
570  }
571 
572  if (ast_stream_topology_get_count(topology) != 1) {
573  ast_test_status_update(test, "Set an audio stream on the stream topology but stream count is '%d' on it, not 1\n",
575  return AST_TEST_FAIL;
576  }
577 
578  if (ast_stream_topology_get_stream(topology, 0) != audio_stream) {
579  ast_test_status_update(test, "Set an audio stream on the stream topology but returned stream doesn't match\n");
580  return AST_TEST_FAIL;
581  }
582 
583  if (ast_stream_get_position(audio_stream) != 0) {
584  ast_test_status_update(test, "Set audio stream says it is at position '%d' instead of 0\n",
585  ast_stream_get_position(audio_stream));
586  return AST_TEST_FAIL;
587  }
588 
589  video_stream = ast_stream_alloc("video", AST_MEDIA_TYPE_VIDEO);
590  if (!video_stream) {
591  ast_test_status_update(test, "Failed to create a video stream for testing stream topology\n");
592  return AST_TEST_FAIL;
593  }
594 
595  if (ast_stream_topology_set_stream(topology, 0, video_stream)) {
596  ast_test_status_update(test, "Failed to set a video stream to a position where it is permitted\n");
597  ast_stream_free(video_stream);
598  return AST_TEST_FAIL;
599  }
600 
601  if (ast_stream_topology_get_count(topology) != 1) {
602  ast_test_status_update(test, "Set a video stream on the stream topology but stream count is '%d' on it, not 1\n",
604  return AST_TEST_FAIL;
605  }
606 
607  if (ast_stream_topology_get_stream(topology, 0) != video_stream) {
608  ast_test_status_update(test, "Set a video stream on the stream topology but returned stream doesn't match\n");
609  return AST_TEST_FAIL;
610  }
611 
612  if (ast_stream_get_position(video_stream) != 0) {
613  ast_test_status_update(test, "Set video stream says it is at position '%d' instead of 0\n",
614  ast_stream_get_position(video_stream));
615  return AST_TEST_FAIL;
616  }
617 
618  audio_stream = ast_stream_alloc("audio", AST_MEDIA_TYPE_AUDIO);
619  if (!audio_stream) {
620  ast_test_status_update(test, "Failed to create an audio stream for testing stream topology\n");
621  return AST_TEST_FAIL;
622  }
623 
624  if (ast_stream_topology_set_stream(topology, 1, audio_stream)) {
625  ast_test_status_update(test, "Failed to set an audio stream to a position where it is permitted\n");
626  ast_stream_free(audio_stream);
627  return AST_TEST_FAIL;
628  }
629 
630  if (ast_stream_topology_get_count(topology) != 2) {
631  ast_test_status_update(test, "Set an audio stream on the stream topology but stream count is '%d' on it, not 2\n",
633  return AST_TEST_FAIL;
634  }
635 
636  if (ast_stream_topology_get_stream(topology, 1) != audio_stream) {
637  ast_test_status_update(test, "Set an audio stream on the stream topology but returned stream doesn't match\n");
638  return AST_TEST_FAIL;
639  }
640 
641  if (ast_stream_get_position(audio_stream) != 1) {
642  ast_test_status_update(test, "Set audio stream says it is at position '%d' instead of 1\n",
643  ast_stream_get_position(audio_stream));
644  return AST_TEST_FAIL;
645  }
646 
647  return AST_TEST_PASS;
648 }
649 
650 static int check_stream_positions(struct ast_test *test, const struct ast_stream_topology *topology)
651 {
652  const struct ast_stream *stream;
653  int idx;
654  int pos;
655  enum ast_media_type type;
656 
657  for (idx = 0; idx < ast_stream_topology_get_count(topology); ++idx) {
658  stream = ast_stream_topology_get_stream(topology, idx);
659  pos = ast_stream_get_position(stream);
660  if (idx != pos) {
661  type = ast_stream_get_type(stream);
662  ast_test_status_update(test, "Failed: '%s' stream says it is at position %d instead of %d\n",
663  ast_codec_media_type2str(type), pos, idx);
664  return -1;
665  }
666  }
667  return 0;
668 }
669 
670 AST_TEST_DEFINE(stream_topology_del_stream)
671 {
673  struct ast_stream *stream;
674  enum ast_media_type type;
675  int idx;
676 
677  switch (cmd) {
678  case TEST_INIT:
679  info->name = "stream_topology_del_stream";
680  info->category = "/main/stream/";
681  info->summary = "stream topology stream delete unit test";
682  info->description =
683  "Test that deleting streams at a specific position in a topology works";
684  return AST_TEST_NOT_RUN;
685  case TEST_EXECUTE:
686  break;
687  }
688 
689  topology = ast_stream_topology_alloc();
690  if (!topology) {
691  ast_test_status_update(test, "Failed to create media stream topology\n");
692  return AST_TEST_FAIL;
693  }
694 
695  /* Create streams */
696  for (type = AST_MEDIA_TYPE_UNKNOWN; type < AST_MEDIA_TYPE_END; ++type) {
697  stream = ast_stream_alloc(ast_codec_media_type2str(type), type);
698  if (!stream) {
699  ast_test_status_update(test, "Failed to create '%s' stream for testing stream topology\n",
701  return AST_TEST_FAIL;
702  }
703  if (ast_stream_topology_append_stream(topology, stream) == -1) {
704  ast_test_status_update(test, "Failed to append '%s' stream to topology\n",
706  ast_stream_free(stream);
707  return AST_TEST_FAIL;
708  }
709  }
710 
711  /* Check initial stream positions and types for sanity. */
712  type = AST_MEDIA_TYPE_UNKNOWN;
713  for (idx = 0; idx < ast_stream_topology_get_count(topology); ++idx, ++type) {
714  stream = ast_stream_topology_get_stream(topology, idx);
715  if (type != ast_stream_get_type(stream)) {
716  ast_test_status_update(test, "Initial topology types failed: Expected:%s Got:%s\n",
719  return AST_TEST_FAIL;
720  }
721  }
722  if (check_stream_positions(test, topology)) {
723  ast_test_status_update(test, "Initial topology positions failed.\n");
724  return AST_TEST_FAIL;
725  }
726 
727  /* Try to delete outside of topology size */
729  ast_test_status_update(test, "Deleting stream outside of topology succeeded!\n");
730  return AST_TEST_FAIL;
731  }
732 
733  /* Try to delete the last topology stream */
734  if (ast_stream_topology_del_stream(topology, ast_stream_topology_get_count(topology) - 1)) {
735  ast_test_status_update(test, "Failed deleting last stream of topology.\n");
736  return AST_TEST_FAIL;
737  }
738  if (check_stream_positions(test, topology)) {
739  ast_test_status_update(test, "Last stream delete topology positions failed.\n");
740  return AST_TEST_FAIL;
741  }
742  stream = ast_stream_topology_get_stream(topology, ast_stream_topology_get_count(topology) - 1);
743  type = ast_stream_get_type(stream);
744  if (type != AST_MEDIA_TYPE_END - 2) {
745  ast_test_status_update(test, "Last stream delete types failed: Expected:%s Got:%s\n",
746  ast_codec_media_type2str(AST_MEDIA_TYPE_END - 2),
748  return AST_TEST_FAIL;
749  }
750 
751  /* Try to delete the second stream in the topology */
752  if (ast_stream_topology_del_stream(topology, 1)) {
753  ast_test_status_update(test, "Failed deleting second stream in topology.\n");
754  return AST_TEST_FAIL;
755  }
756  if (check_stream_positions(test, topology)) {
757  ast_test_status_update(test, "Second stream delete topology positions failed.\n");
758  return AST_TEST_FAIL;
759  }
760  stream = ast_stream_topology_get_stream(topology, 1);
761  type = ast_stream_get_type(stream);
762  if (type != AST_MEDIA_TYPE_UNKNOWN + 2) {
763  ast_test_status_update(test, "Second stream delete types failed: Expected:%s Got:%s\n",
766  return AST_TEST_FAIL;
767  }
768 
769  /* Try to delete the first stream in the topology */
770  if (ast_stream_topology_del_stream(topology, 0)) {
771  ast_test_status_update(test, "Failed deleting first stream in topology.\n");
772  return AST_TEST_FAIL;
773  }
774  if (check_stream_positions(test, topology)) {
775  ast_test_status_update(test, "First stream delete topology positions failed.\n");
776  return AST_TEST_FAIL;
777  }
778  stream = ast_stream_topology_get_stream(topology, 0);
779  type = ast_stream_get_type(stream);
780  if (type != AST_MEDIA_TYPE_UNKNOWN + 2) {
781  ast_test_status_update(test, "First stream delete types failed: Expected:%s Got:%s\n",
784  return AST_TEST_FAIL;
785  }
786 
787  return AST_TEST_PASS;
788 }
789 
790 AST_TEST_DEFINE(stream_topology_create_from_format_cap)
791 {
793  RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
794 
795  switch (cmd) {
796  case TEST_INIT:
797  info->name = "stream_topology_create_from_format_cap";
798  info->category = "/main/stream/";
799  info->summary = "stream topology creation from format capabilities unit test";
800  info->description =
801  "Test that creating a stream topology from format capabilities results in the expected streams";
802  return AST_TEST_NOT_RUN;
803  case TEST_EXECUTE:
804  break;
805  }
806 
808  if (!caps) {
809  ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
810  return AST_TEST_FAIL;
811  }
812 
813  if (ast_format_cap_append(caps, ast_format_ulaw, 0)) {
814  ast_test_status_update(test, "Failed to append a ulaw format to capabilities for stream topology creation\n");
815  return AST_TEST_FAIL;
816  }
817 
818  if (ast_format_cap_append(caps, ast_format_alaw, 0)) {
819  ast_test_status_update(test, "Failed to append an alaw format to capabilities for stream topology creation\n");
820  return AST_TEST_FAIL;
821  }
822 
824  if (!topology) {
825  ast_test_status_update(test, "Failed to create a stream topology using a perfectly good format capabilities\n");
826  return AST_TEST_FAIL;
827  }
828 
829  if (ast_stream_topology_get_count(topology) != 1) {
830  ast_test_status_update(test, "Expected a stream topology with 1 stream but it has %d streams\n",
832  return AST_TEST_FAIL;
833  }
834 
836  ast_test_status_update(test, "Produced stream topology has a single stream of type %s instead of audio\n",
838  return AST_TEST_FAIL;
839  }
840 
841  ast_stream_topology_free(topology);
842  topology = NULL;
843 
845 
847  if (!topology) {
848  ast_test_status_update(test, "Failed to create a stream topology using a perfectly good format capabilities\n");
849  return AST_TEST_FAIL;
850  }
851 
852  if (ast_stream_topology_get_count(topology) != 2) {
853  ast_test_status_update(test, "Expected a stream topology with 2 streams but it has %d streams\n",
855  return AST_TEST_FAIL;
856  }
857 
859  ast_test_status_update(test, "Produced stream topology has a first stream of type %s instead of audio\n",
861  return AST_TEST_FAIL;
862  }
863 
865  ast_test_status_update(test, "Produced stream topology has a second stream of type %s instead of video\n",
867  return AST_TEST_FAIL;
868  }
869 
870  return AST_TEST_PASS;
871 }
872 
873 AST_TEST_DEFINE(stream_topology_get_first_stream_by_type)
874 {
876  struct ast_stream *first_stream;
877  struct ast_stream *second_stream;
878  struct ast_stream *third_stream;
879  struct ast_stream *fourth_stream;
880  struct ast_stream *fifth_stream;
881  struct ast_stream *sixth_stream;
882 
883  switch (cmd) {
884  case TEST_INIT:
885  info->name = "stream_topology_get_first_stream_by_type";
886  info->category = "/main/stream/";
887  info->summary = "stream topology getting first stream by type unit test";
888  info->description =
889  "Test that getting the first stream by type from a topology actually returns the first stream";
890  return AST_TEST_NOT_RUN;
891  case TEST_EXECUTE:
892  break;
893  }
894 
895  topology = ast_stream_topology_alloc();
896  if (!topology) {
897  ast_test_status_update(test, "Failed to create media stream topology\n");
898  return AST_TEST_FAIL;
899  }
900 
901  first_stream = ast_stream_alloc("audio", AST_MEDIA_TYPE_AUDIO);
902  if (!first_stream) {
903  ast_test_status_update(test, "Failed to create an audio stream for testing stream topology\n");
904  return AST_TEST_FAIL;
905  }
907 
908  if (ast_stream_topology_append_stream(topology, first_stream) == -1) {
909  ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
910  ast_stream_free(first_stream);
911  return AST_TEST_FAIL;
912  }
913 
914  second_stream = ast_stream_alloc("audio2", AST_MEDIA_TYPE_AUDIO);
915  if (!second_stream) {
916  ast_test_status_update(test, "Failed to create a second audio stream for testing stream topology\n");
917  return AST_TEST_FAIL;
918  }
919 
920  if (ast_stream_topology_append_stream(topology, second_stream) == -1) {
921  ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
922  ast_stream_free(second_stream);
923  return AST_TEST_FAIL;
924  }
925 
926  third_stream = ast_stream_alloc("audio3", AST_MEDIA_TYPE_AUDIO);
927  if (!third_stream) {
928  ast_test_status_update(test, "Failed to create a third audio stream for testing stream topology\n");
929  return AST_TEST_FAIL;
930  }
931 
932  if (ast_stream_topology_append_stream(topology, third_stream) == -1) {
933  ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
934  ast_stream_free(third_stream);
935  return AST_TEST_FAIL;
936  }
937 
938  fourth_stream = ast_stream_alloc("video", AST_MEDIA_TYPE_VIDEO);
939  if (!fourth_stream) {
940  ast_test_status_update(test, "Failed to create a video stream for testing stream topology\n");
941  return AST_TEST_FAIL;
942  }
944 
945  if (ast_stream_topology_append_stream(topology, fourth_stream) == -1) {
946  ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
947  ast_stream_free(fourth_stream);
948  return AST_TEST_FAIL;
949  }
950 
951  fifth_stream = ast_stream_alloc("video2", AST_MEDIA_TYPE_VIDEO);
952  if (!fifth_stream) {
953  ast_test_status_update(test, "Failed to create a second video stream for testing stream topology\n");
954  return AST_TEST_FAIL;
955  }
956 
957  if (ast_stream_topology_append_stream(topology, fifth_stream) == -1) {
958  ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
959  ast_stream_free(fifth_stream);
960  return AST_TEST_FAIL;
961  }
962 
963  sixth_stream = ast_stream_alloc("video3", AST_MEDIA_TYPE_VIDEO);
964  if (!sixth_stream) {
965  ast_test_status_update(test, "Failed to create a third video stream for testing stream topology\n");
966  return AST_TEST_FAIL;
967  }
968 
969  if (ast_stream_topology_append_stream(topology, sixth_stream) == -1) {
970  ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
971  ast_stream_free(sixth_stream);
972  return AST_TEST_FAIL;
973  }
974 
975  if (ast_stream_topology_get_first_stream_by_type(topology, AST_MEDIA_TYPE_AUDIO) != second_stream) {
976  ast_test_status_update(test, "Retrieved first audio stream from topology but it is not the correct one\n");
977  return AST_TEST_FAIL;
978  }
979 
981  ast_test_status_update(test, "Retrieved first video stream from topology but it is not the correct one\n");
982  return AST_TEST_FAIL;
983  }
984 
985  return AST_TEST_PASS;
986 }
987 
988 static const struct ast_channel_tech mock_channel_tech = {
989 };
990 
991 AST_TEST_DEFINE(stream_topology_create_from_channel_nativeformats)
992 {
994  RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
995  struct ast_channel *mock_channel;
997  struct ast_str *codec_have_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
998  struct ast_str *codec_wanted_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
999 
1000  switch (cmd) {
1001  case TEST_INIT:
1002  info->name = "stream_topology_create_from_channel_nativeformats";
1003  info->category = "/main/stream/";
1004  info->summary = "stream topology creation from channel native formats unit test";
1005  info->description =
1006  "Test that creating a stream topology from the setting of channel nativeformats results in the expected streams";
1007  return AST_TEST_NOT_RUN;
1008  case TEST_EXECUTE:
1009  break;
1010  }
1011 
1013  if (!caps) {
1014  ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
1015  return AST_TEST_FAIL;
1016  }
1017 
1018  if (ast_format_cap_append(caps, ast_format_ulaw, 0)) {
1019  ast_test_status_update(test, "Failed to append a ulaw format to capabilities for channel nativeformats\n");
1020  return AST_TEST_FAIL;
1021  }
1022 
1023  if (ast_format_cap_append(caps, ast_format_alaw, 0)) {
1024  ast_test_status_update(test, "Failed to append an alaw format to capabilities for channel nativeformats\n");
1025  return AST_TEST_FAIL;
1026  }
1027 
1028  if (ast_format_cap_append(caps, ast_format_h264, 0)) {
1029  ast_test_status_update(test, "Failed to append an h264 format to capabilities for channel nativeformats\n");
1030  return AST_TEST_FAIL;
1031  }
1032 
1033  mock_channel = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, "TestChannel");
1034  if (!mock_channel) {
1035  ast_test_status_update(test, "Failed to create a mock channel for testing\n");
1036  return AST_TEST_FAIL;
1037  }
1038 
1039  ast_channel_tech_set(mock_channel, &mock_channel_tech);
1040  ast_channel_nativeformats_set(mock_channel, caps);
1041 
1042  if (!ast_channel_get_stream_topology(mock_channel)) {
1043  ast_test_status_update(test, "Set nativeformats with ulaw, alaw, and h264 on channel but it did not create a topology\n");
1044  goto end;
1045  }
1046 
1048  ast_test_status_update(test, "Set nativeformats on a channel to ulaw, alaw, and h264 and received '%d' streams instead of expected 2\n",
1050  goto end;
1051  }
1052 
1054  ast_test_status_update(test, "First stream on channel is of %s when it should be audio\n",
1056  goto end;
1057  }
1058 
1061  ast_test_status_update(test, "Formats on audio stream of channel are '%s' when they should be '%s'\n",
1063  ast_format_cap_get_names(caps, &codec_wanted_buf));
1064  goto end;
1065  }
1066 
1068  ast_test_status_update(test, "Second stream on channel is of type %s when it should be video\n",
1070  goto end;
1071  }
1072 
1074 
1075  if (ast_format_cap_append(caps, ast_format_h264, 0)) {
1076  ast_test_status_update(test, "Failed to append h264 video codec to capabilities for capabilities comparison\n");
1077  goto end;
1078  }
1079 
1081  ast_test_status_update(test, "Formats on video stream of channel are '%s' when they should be '%s'\n",
1083  ast_format_cap_get_names(caps, &codec_wanted_buf));
1084  goto end;
1085  }
1086 
1087  res = AST_TEST_PASS;
1088 
1089 end:
1090  ast_channel_unlock(mock_channel);
1091  ast_hangup(mock_channel);
1092 
1093  return res;
1094 }
1095 
1097  int mallocd;
1098  unsigned int wrote;
1099  unsigned int wrote_stream;
1103  int streams;
1106  unsigned int indicated_changed;
1107 };
1108 
1109 static struct ast_frame *mock_channel_read(struct ast_channel *chan)
1110 {
1111  struct mock_channel_pvt *pvt = ast_channel_tech_pvt(chan);
1112  struct ast_frame f = { 0, };
1113  struct ast_frame *head_frame = NULL;
1114  struct ast_frame *tail_frame = NULL;
1115  int i;
1116 
1117  if (pvt->frames_per_read == 0) {
1118  pvt->frames_per_read = 1;
1119  }
1120  for (i = 0; i < pvt->frames_per_read && pvt->frame_count < pvt->frame_limit; i++) {
1121  struct ast_frame *fr;
1122 
1123  if (pvt->frame_count % 2 == 0) {
1126  } else {
1129  }
1130  f.seqno = pvt->frame_count;
1131  f.stream_num = pvt->frame_count % pvt->streams;
1132  pvt->frame_count++;
1133  fr = ast_frdup(&f);
1134  if (!head_frame) {
1135  head_frame = fr;
1136  } else {
1137  tail_frame->frame_list.next = fr;
1138  }
1139  tail_frame = fr;
1140  }
1141 
1142  return(head_frame);
1143 }
1144 
1145 static int mock_channel_write(struct ast_channel *chan, struct ast_frame *fr)
1146 {
1147  struct mock_channel_pvt *pvt = ast_channel_tech_pvt(chan);
1148 
1149  pvt->wrote = 1;
1150 
1151  return 0;
1152 }
1153 
1154 static int mock_channel_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
1155 {
1156  struct mock_channel_pvt *pvt = ast_channel_tech_pvt(chan);
1157 
1158  if (condition == AST_CONTROL_STREAM_TOPOLOGY_REQUEST_CHANGE) {
1159  pvt->indicated_change_request = 1;
1160  } else if (condition == AST_CONTROL_STREAM_TOPOLOGY_CHANGED) {
1161  pvt->indicated_changed = 1;
1162  }
1163 
1164  return 0;
1165 }
1166 
1167 static int mock_channel_write_stream(struct ast_channel *chan, int stream_num, struct ast_frame *fr)
1168 {
1169  struct mock_channel_pvt *pvt = ast_channel_tech_pvt(chan);
1170 
1171  pvt->wrote_stream = 1;
1172  pvt->stream_num = stream_num;
1173 
1174  return 0;
1175 }
1176 
1179  .write_stream = mock_channel_write_stream,
1180 };
1181 
1182 AST_TEST_DEFINE(stream_topology_channel_set)
1183 {
1185  struct ast_channel *mock_channel;
1187 
1188  switch (cmd) {
1189  case TEST_INIT:
1190  info->name = "stream_topology_channel_set";
1191  info->category = "/main/stream/";
1192  info->summary = "stream topology setting on a channel unit test";
1193  info->description =
1194  "Test that setting a stream topology on a channel works";
1195  return AST_TEST_NOT_RUN;
1196  case TEST_EXECUTE:
1197  break;
1198  }
1199 
1200  topology = ast_stream_topology_alloc();
1201  if (!topology) {
1202  ast_test_status_update(test, "Failed to create media stream topology\n");
1203  return AST_TEST_FAIL;
1204  }
1205 
1206  mock_channel = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, "TestChannel");
1207  if (!mock_channel) {
1208  ast_test_status_update(test, "Failed to create a mock channel for testing\n");
1209  return AST_TEST_FAIL;
1210  }
1211 
1212  ast_channel_tech_set(mock_channel, &mock_stream_channel_tech);
1213  ast_channel_set_stream_topology(mock_channel, topology);
1214 
1215  if (ast_channel_get_stream_topology(mock_channel) != topology) {
1216  ast_test_status_update(test, "Set an explicit stream topology on a channel but the returned one did not match it\n");
1217  res = AST_TEST_FAIL;
1218  }
1219 
1220  topology = NULL;
1221  ast_channel_unlock(mock_channel);
1222  ast_hangup(mock_channel);
1223 
1224  return res;
1225 }
1226 
1227 static int mock_channel_hangup(struct ast_channel *chan)
1228 {
1229  struct mock_channel_pvt *pvt = ast_channel_tech_pvt(chan);
1230 
1231  if (pvt->mallocd) {
1232  ast_free(pvt);
1233  }
1234 
1236  return 0;
1237 }
1238 
1241  .write_video = mock_channel_write,
1242  .hangup = mock_channel_hangup,
1243 };
1244 
1245 AST_TEST_DEFINE(stream_write_non_multistream)
1246 {
1247  RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
1248  struct ast_channel *mock_channel;
1249  struct mock_channel_pvt pvt = { 0, };
1251  struct ast_frame frame = { 0, };
1252 
1253  switch (cmd) {
1254  case TEST_INIT:
1255  info->name = "stream_write_non_multistream";
1256  info->category = "/main/stream/";
1257  info->summary = "stream writing to non-multistream capable channel test";
1258  info->description =
1259  "Test that writing frames to a non-multistream channel works as expected";
1260  return AST_TEST_NOT_RUN;
1261  case TEST_EXECUTE:
1262  break;
1263  }
1264 
1266  if (!caps) {
1267  ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
1268  return AST_TEST_FAIL;
1269  }
1270 
1271  if (ast_format_cap_append(caps, ast_format_ulaw, 0)) {
1272  ast_test_status_update(test, "Failed to append a ulaw format to capabilities for channel nativeformats\n");
1273  return AST_TEST_FAIL;
1274  }
1275 
1276  if (ast_format_cap_append(caps, ast_format_h264, 0)) {
1277  ast_test_status_update(test, "Failed to append an h264 format to capabilities for channel nativeformats\n");
1278  return AST_TEST_FAIL;
1279  }
1280 
1281  mock_channel = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, "TestChannel");
1282  if (!mock_channel) {
1283  ast_test_status_update(test, "Failed to create a mock channel for testing\n");
1284  return AST_TEST_FAIL;
1285  }
1286 
1287  ast_channel_tech_set(mock_channel, &mock_channel_old_write_tech);
1288  ast_channel_nativeformats_set(mock_channel, caps);
1289 
1290  pvt.wrote = 0;
1291  ast_channel_tech_pvt_set(mock_channel, &pvt);
1292  ast_channel_unlock(mock_channel);
1293 
1294  frame.frametype = AST_FRAME_VOICE;
1296 
1297  if (ast_write(mock_channel, &frame)) {
1298  ast_test_status_update(test, "Failed to write a ulaw frame to the mock channel when it should be fine\n");
1299  goto end;
1300  }
1301 
1302  if (!pvt.wrote) {
1303  ast_test_status_update(test, "Successfully wrote a frame of ulaw but it never reached the channel driver\n");
1304  goto end;
1305  }
1306 
1307  pvt.wrote = 0;
1308 
1309  if (!ast_write_stream(mock_channel, 2, &frame) || pvt.wrote) {
1310  ast_test_status_update(test, "Successfully wrote a frame of ulaw to a non-existent stream\n");
1311  goto end;
1312  }
1313 
1314  frame.frametype = AST_FRAME_VIDEO;
1316 
1317  if (ast_write(mock_channel, &frame)) {
1318  ast_test_status_update(test, "Failed to write an h264 frame to the mock channel when it should be fine\n");
1319  goto end;
1320  }
1321 
1322  if (!pvt.wrote) {
1323  ast_test_status_update(test, "Successfully wrote a frame of h264 but it never reached the channel driver\n");
1324  goto end;
1325  }
1326 
1327  res = AST_TEST_PASS;
1328 
1329 end:
1330  ast_hangup(mock_channel);
1331 
1332  return res;
1333 }
1334 
1337  .write_video = mock_channel_write,
1338  .write_stream = mock_channel_write_stream,
1339  .read_stream = mock_channel_read,
1340  .hangup = mock_channel_hangup,
1341 };
1342 
1343 AST_TEST_DEFINE(stream_write_multistream)
1344 {
1345  RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
1347  struct ast_stream *stream;
1348  struct ast_channel *mock_channel;
1349  struct mock_channel_pvt pvt = { 0, };
1351  struct ast_frame frame = { 0, };
1352 
1353  switch (cmd) {
1354  case TEST_INIT:
1355  info->name = "stream_write_multistream";
1356  info->category = "/main/stream/";
1357  info->summary = "stream writing to multistream capable channel test";
1358  info->description =
1359  "Test that writing frames to a multistream channel works as expected";
1360  return AST_TEST_NOT_RUN;
1361  case TEST_EXECUTE:
1362  break;
1363  }
1364 
1365  topology = ast_stream_topology_alloc();
1366  if (!topology) {
1367  ast_test_status_update(test, "Failed to create media stream topology\n");
1368  return AST_TEST_FAIL;
1369  }
1370 
1371  stream = ast_stream_alloc("audio", AST_MEDIA_TYPE_AUDIO);
1372  if (!stream) {
1373  ast_test_status_update(test, "Failed to create an audio stream for testing multistream writing\n");
1374  return AST_TEST_FAIL;
1375  }
1376 
1377  if (ast_stream_topology_append_stream(topology, stream) == -1) {
1378  ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
1379  ast_stream_free(stream);
1380  return AST_TEST_FAIL;
1381  }
1382 
1383  stream = ast_stream_alloc("audio2", AST_MEDIA_TYPE_AUDIO);
1384  if (!stream) {
1385  ast_test_status_update(test, "Failed to create an audio stream for testing multistream writing\n");
1386  return AST_TEST_FAIL;
1387  }
1388 
1389  if (ast_stream_topology_append_stream(topology, stream) == -1) {
1390  ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
1391  ast_stream_free(stream);
1392  return AST_TEST_FAIL;
1393  }
1394 
1395  stream = ast_stream_alloc("video", AST_MEDIA_TYPE_VIDEO);
1396  if (!stream) {
1397  ast_test_status_update(test, "Failed to create a video stream for testing multistream writing\n");
1398  return AST_TEST_FAIL;
1399  }
1400 
1401  if (ast_stream_topology_append_stream(topology, stream) == -1) {
1402  ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
1403  ast_stream_free(stream);
1404  return AST_TEST_FAIL;
1405  }
1406 
1407  stream = ast_stream_alloc("video2", AST_MEDIA_TYPE_VIDEO);
1408  if (!stream) {
1409  ast_test_status_update(test, "Failed to create a video stream for testing multistream writing\n");
1410  return AST_TEST_FAIL;
1411  }
1412 
1413  if (ast_stream_topology_append_stream(topology, stream) == -1) {
1414  ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
1415  ast_stream_free(stream);
1416  return AST_TEST_FAIL;
1417  }
1418 
1420  if (!caps) {
1421  ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
1422  return AST_TEST_FAIL;
1423  }
1424 
1425  if (ast_format_cap_append(caps, ast_format_ulaw, 0)) {
1426  ast_test_status_update(test, "Failed to append a ulaw format to capabilities for channel nativeformats\n");
1427  return AST_TEST_FAIL;
1428  }
1429 
1430  if (ast_format_cap_append(caps, ast_format_h264, 0)) {
1431  ast_test_status_update(test, "Failed to append an h264 format to capabilities for channel nativeformats\n");
1432  return AST_TEST_FAIL;
1433  }
1434 
1435  mock_channel = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, "TestChannel");
1436  if (!mock_channel) {
1437  ast_test_status_update(test, "Failed to create a mock channel for testing\n");
1438  return AST_TEST_FAIL;
1439  }
1440 
1441  ast_channel_tech_set(mock_channel, &mock_channel_write_stream_tech);
1442  ast_channel_set_stream_topology(mock_channel, topology);
1443  ast_channel_nativeformats_set(mock_channel, caps);
1444  topology = NULL;
1445 
1446  ast_channel_tech_pvt_set(mock_channel, &pvt);
1447  ast_channel_unlock(mock_channel);
1448 
1449  frame.frametype = AST_FRAME_VOICE;
1451  pvt.stream_num = -1;
1452 
1453  if (ast_write(mock_channel, &frame)) {
1454  ast_test_status_update(test, "Failed to write a ulaw frame to the mock channel when it should be fine\n");
1455  goto end;
1456  }
1457 
1458  if (pvt.wrote) {
1459  ast_test_status_update(test, "Successfully wrote a frame of ulaw but it ended up on the old write callback instead of write_stream\n");
1460  goto end;
1461  }
1462 
1463  if (!pvt.wrote_stream) {
1464  ast_test_status_update(test, "Successfully wrote a frame of ulaw but it never reached the channel driver\n");
1465  goto end;
1466  }
1467 
1468  if (pvt.stream_num != 0) {
1469  ast_test_status_update(test, "Successfully wrote a frame of ulaw to the default stream but it ended up on stream %d and not 0\n",
1470  pvt.stream_num);
1471  goto end;
1472  }
1473 
1474  pvt.wrote_stream = 0;
1475  pvt.stream_num = -1;
1476 
1477  if (ast_write_stream(mock_channel, 0, &frame)) {
1478  ast_test_status_update(test, "Failed to write a ulaw frame to the first audio stream\n");
1479  goto end;
1480  }
1481 
1482  if (pvt.wrote) {
1483  ast_test_status_update(test, "Successfully wrote a frame of ulaw to the first audio stream but it ended up on the old write callback instead of write_stream\n");
1484  goto end;
1485  }
1486 
1487  if (!pvt.wrote_stream) {
1488  ast_test_status_update(test, "Successfully wrote a frame of ulaw to the first audio stream but it never reached the channel driver\n");
1489  goto end;
1490  }
1491 
1492  if (pvt.stream_num != 0) {
1493  ast_test_status_update(test, "Successfully wrote a frame of ulaw to the first audio stream but it ended up on stream %d and not 0\n",
1494  pvt.stream_num);
1495  goto end;
1496  }
1497 
1498  pvt.wrote_stream = 0;
1499  pvt.stream_num = -1;
1500 
1501  if (ast_write_stream(mock_channel, 1, &frame)) {
1502  ast_test_status_update(test, "Failed to write a ulaw frame to the second audio stream\n");
1503  goto end;
1504  }
1505 
1506  if (pvt.wrote) {
1507  ast_test_status_update(test, "Successfully wrote a frame of ulaw to the second audio stream but it ended up on the old write callback instead of write_stream\n");
1508  goto end;
1509  }
1510 
1511  if (!pvt.wrote_stream) {
1512  ast_test_status_update(test, "Successfully wrote a frame of ulaw to the second audio stream but it never reached the channel driver\n");
1513  goto end;
1514  }
1515 
1516  if (pvt.stream_num != 1) {
1517  ast_test_status_update(test, "Successfully wrote a frame of ulaw to the second audio stream but it ended up on stream %d and not 1\n",
1518  pvt.stream_num);
1519  goto end;
1520  }
1521 
1522  pvt.wrote_stream = 0;
1523  pvt.stream_num = -1;
1524 
1525  frame.frametype = AST_FRAME_VIDEO;
1527 
1528  if (ast_write(mock_channel, &frame)) {
1529  ast_test_status_update(test, "Failed to write an h264 frame to the mock channel when it should be fine\n");
1530  goto end;
1531  }
1532 
1533  if (pvt.wrote) {
1534  ast_test_status_update(test, "Successfully wrote a frame of h264 but it ended up on the old write callback instead of write_stream\n");
1535  goto end;
1536  }
1537 
1538  if (!pvt.wrote_stream) {
1539  ast_test_status_update(test, "Successfully wrote a frame of h264 but it never reached the channel driver\n");
1540  goto end;
1541  }
1542 
1543  if (pvt.stream_num != 2) {
1544  ast_test_status_update(test, "Successfully wrote a frame of h264 to the default stream but it ended up on stream %d and not 2\n",
1545  pvt.stream_num);
1546  goto end;
1547  }
1548 
1549  pvt.wrote_stream = 0;
1550  pvt.stream_num = -1;
1551 
1552  if (ast_write_stream(mock_channel, 2, &frame)) {
1553  ast_test_status_update(test, "Failed to write an h264 frame to the first video stream\n");
1554  goto end;
1555  }
1556 
1557  if (pvt.wrote) {
1558  ast_test_status_update(test, "Successfully wrote a frame of h264 to the first video stream but it ended up on the old write callback instead of write_stream\n");
1559  goto end;
1560  }
1561 
1562  if (!pvt.wrote_stream) {
1563  ast_test_status_update(test, "Successfully wrote a frame of h264 to the first video stream but it never reached the channel driver\n");
1564  goto end;
1565  }
1566 
1567  if (pvt.stream_num != 2) {
1568  ast_test_status_update(test, "Successfully wrote a frame of h264 to the first video stream but it ended up on stream %d and not 2\n",
1569  pvt.stream_num);
1570  goto end;
1571  }
1572 
1573  pvt.wrote_stream = 0;
1574  pvt.stream_num = -1;
1575 
1576  if (ast_write_stream(mock_channel, 3, &frame)) {
1577  ast_test_status_update(test, "Failed to write an h264 frame to the second video stream\n");
1578  goto end;
1579  }
1580 
1581  if (pvt.wrote) {
1582  ast_test_status_update(test, "Successfully wrote a frame of h264 to the second video stream but it ended up on the old write callback instead of write_stream\n");
1583  goto end;
1584  }
1585 
1586  if (!pvt.wrote_stream) {
1587  ast_test_status_update(test, "Successfully wrote a frame of h264 to the second video stream but it never reached the channel driver\n");
1588  goto end;
1589  }
1590 
1591  if (pvt.stream_num != 3) {
1592  ast_test_status_update(test, "Successfully wrote a frame of h264 to the second video stream but it ended up on stream %d and not 3\n",
1593  pvt.stream_num);
1594  goto end;
1595  }
1596 
1597  pvt.wrote_stream = 0;
1598  pvt.stream_num = -1;
1599 
1600  if (!ast_write_stream(mock_channel, 9, &frame)) {
1601  ast_test_status_update(test, "Successfully wrote a frame of h264 to a non-existent stream\n");
1602  goto end;
1603  }
1604 
1605  if (pvt.wrote) {
1606  ast_test_status_update(test, "Successfully wrote a frame of h264 to a non-existent stream and it ended up on the old write callback\n");
1607  goto end;
1608  }
1609 
1610  if (pvt.wrote_stream) {
1611  ast_test_status_update(test, "Successfully wrote a frame of h264 to a non-existent stream and it ended up on the write_stream callback\n");
1612  goto end;
1613  }
1614 
1615  res = AST_TEST_PASS;
1616 
1617 end:
1618  ast_hangup(mock_channel);
1619 
1620  return res;
1621 }
1622 
1623 static int load_stream_readqueue(struct ast_channel *chan, int frames)
1624 {
1625  struct mock_channel_pvt *pvt = ast_channel_tech_pvt(chan);
1626  struct ast_frame f = { 0, };
1627  struct ast_frame *frame = NULL;
1628  int i;
1629 
1630  while ((frame = AST_LIST_REMOVE_HEAD(ast_channel_readq(chan), frame_list)))
1631  ast_frfree(frame);
1632 
1633  for (i = 0; i < frames; i++) {
1634  if (pvt->frame_count % 2 == 0) {
1637  } else {
1640  }
1641  f.stream_num = pvt->frame_count % pvt->streams;
1642  f.seqno = pvt->frame_count;
1643  ast_queue_frame(chan, &f);
1644  pvt->frame_count++;
1645  }
1646 
1647  return 0;
1648 }
1649 
1650 static struct ast_channel *make_channel(struct ast_test *test, int streams,
1651  struct ast_channel_tech *tech)
1652 {
1653  RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
1654  struct ast_channel *mock_channel = NULL;
1655  struct mock_channel_pvt *pvt = NULL;
1656  struct ast_stream_topology *topology = NULL;
1657  struct ast_stream *stream;
1659  int i;
1660 
1661  mock_channel = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, "TestChannel");
1662  ast_test_validate_cleanup(test, mock_channel, res, done);
1663  ast_channel_tech_set(mock_channel, tech);
1664 
1665  if (tech->read_stream) {
1666  topology = ast_stream_topology_alloc();
1667  ast_test_validate_cleanup(test, topology, res, done);
1668 
1669  for (i = 0; i < streams; i++) {
1670  stream = ast_stream_alloc((i % 2 ? "video": "audio"), (i % 2 ? AST_MEDIA_TYPE_VIDEO : AST_MEDIA_TYPE_AUDIO));
1671  ast_test_validate_cleanup(test, stream, res, done);
1672  ast_test_validate_cleanup(test, ast_stream_topology_append_stream(topology, stream) == i, res, done);
1673  }
1674  ast_test_validate_cleanup(test, ast_stream_topology_get_count(topology) == streams, res, done);
1675  ast_channel_set_stream_topology(mock_channel, topology);
1676  topology = NULL;
1677  } else {
1679  ast_test_validate_cleanup(test, caps, res, done);
1680 
1681  ast_test_validate_cleanup(test, ast_format_cap_append(caps, ast_format_ulaw, 0) == 0, res, done);
1682  ast_test_validate_cleanup(test, ast_format_cap_append(caps, ast_format_h264, 0) == 0, res, done);
1683  ast_channel_nativeformats_set(mock_channel, caps);
1684  }
1685 
1686  pvt = ast_calloc(1, sizeof(*pvt));
1687  ast_test_validate_cleanup(test, pvt, res, done);
1688  pvt->mallocd = 1;
1689  ast_channel_tech_pvt_set(mock_channel, pvt);
1690 
1691  ast_channel_unlock(mock_channel);
1692 
1693 done:
1694  ast_stream_topology_free(topology);
1695  if (res == AST_TEST_FAIL && mock_channel) {
1696  ast_hangup(mock_channel);
1697  }
1698 
1699  return mock_channel;
1700 }
1701 
1705 };
1706 
1707 static struct ast_frame *read_from_chan(enum CHANNEL_READ_TYPE rt, struct ast_channel *chan)
1708 {
1709  if (rt == CHANNEL_READ_STREAM) {
1710  return ast_read_stream(chan);
1711  } else {
1712  return ast_read(chan);
1713  }
1714 }
1715 
1717  enum CHANNEL_READ_TYPE rt, int streams, int frames, int frames_per_read, int expected_nulls)
1718 {
1719  struct ast_channel *mock_channel;
1720  struct mock_channel_pvt *pvt;
1721  struct ast_frame *fr = NULL;
1723  int i = 0;
1724  int null_frames = 0;
1725 
1726  ast_test_status_update(test, "ChanType: %s ReadType: %s Streams: %d Frames: %d Frames per read: %d Expected Nulls: %d\n",
1727  tech->read_stream ? "MULTI" : "NON-MULTI",
1728  rt == CHANNEL_READ_STREAM ? "STREAM" : "NON-STREAM",
1729  streams, frames, frames_per_read, expected_nulls);
1730  mock_channel = make_channel(test, 4, tech);
1731  ast_test_validate_cleanup(test, mock_channel, res, done);
1732 
1733  pvt = ast_channel_tech_pvt(mock_channel);
1734  pvt->frame_count = 0;
1735  pvt->frame_limit = frames;
1736  pvt->streams = streams;
1738 
1739  load_stream_readqueue(mock_channel, frames / 2);
1740  ast_channel_fdno_set(mock_channel, 0);
1741 
1742  while ((fr = read_from_chan(rt, mock_channel))) {
1743  ast_channel_fdno_set(mock_channel, 0);
1744  if (fr->frametype != AST_FRAME_NULL) {
1745  ast_test_validate_cleanup(test, i == fr->seqno, res, done);
1746  ast_test_validate_cleanup(test, fr->frametype == ( i % 2 ? AST_FRAME_VIDEO : AST_FRAME_VOICE), res, done);
1747  ast_test_validate_cleanup(test, fr->stream_num == ( i % streams ), res, done);
1748  ast_frfree(fr);
1749  } else {
1750  null_frames++;
1751  }
1752  fr = NULL;
1753  i++;
1754  }
1755  ast_test_validate_cleanup(test, i == frames, res, done);
1756  ast_test_validate_cleanup(test, null_frames == expected_nulls, res, done);
1757 
1758 done:
1759  ast_test_status_update(test, " Frames read: %d NULL frames: %d\n", i, null_frames);
1760  ast_hangup(mock_channel);
1761 
1762  return res;
1763 }
1764 
1765 AST_TEST_DEFINE(stream_read_non_multistream)
1766 {
1767  struct ast_channel_tech tech = {
1769  .hangup = mock_channel_hangup,
1770  };
1771 
1773 
1774  switch (cmd) {
1775  case TEST_INIT:
1776  info->name = "stream_read_non_multistream";
1777  info->category = "/main/stream/";
1778  info->summary = "stream reading from non-multistream capable channel test";
1779  info->description =
1780  "Test that reading frames from a non-multistream channel works as expected";
1781  return AST_TEST_NOT_RUN;
1782  case TEST_EXECUTE:
1783  break;
1784  }
1785 
1786  res = read_test(test, &tech, CHANNEL_READ, 2, 16, 1, 0);
1787  ast_test_validate(test, res == AST_TEST_PASS, "non multi, non read stream, 2 stream");
1788 
1789  res = read_test(test, &tech, CHANNEL_READ_STREAM, 2, 16, 1, 0);
1790  ast_test_validate(test, res == AST_TEST_PASS, "non multi, read stream, 2 stream");
1791 
1792  res = read_test(test, &tech, CHANNEL_READ, 2, 16, 3, 0);
1793  ast_test_validate(test, res == AST_TEST_PASS, "non multi, non read stream, 2 stream, 3 frames per read");
1794 
1795  res = read_test(test, &tech, CHANNEL_READ_STREAM, 2, 16, 3, 0);
1796  ast_test_validate(test, res == AST_TEST_PASS, "non multi, read stream, 2 stream, 3 frames per read");
1797 
1798  return res;
1799 }
1800 
1801 AST_TEST_DEFINE(stream_read_multistream)
1802 {
1803  struct ast_channel_tech tech = {
1805  .write_stream = mock_channel_write_stream,
1806  .hangup = mock_channel_hangup,
1807  };
1809 
1810  switch (cmd) {
1811  case TEST_INIT:
1812  info->name = "stream_read_multistream";
1813  info->category = "/main/stream/";
1814  info->summary = "stream reading from multistream capable channel test";
1815  info->description =
1816  "Test that reading frames from a multistream channel works as expected";
1817  return AST_TEST_NOT_RUN;
1818  case TEST_EXECUTE:
1819  break;
1820  }
1821 
1822  res = read_test(test, &tech, CHANNEL_READ, 2, 16, 1, 0);
1823  ast_test_validate(test, res == AST_TEST_PASS, "multi, non read stream, 2 stream");
1824 
1825  res = read_test(test, &tech, CHANNEL_READ_STREAM, 2, 16, 1, 0);
1826  ast_test_validate(test, res == AST_TEST_PASS, "multi, read stream, 2 stream");
1827 
1828  res = read_test(test, &tech, CHANNEL_READ, 4, 16, 1, 8);
1829  ast_test_validate(test, res == AST_TEST_PASS, "multi, non read stream, 4 stream");
1830 
1831  res = read_test(test, &tech, CHANNEL_READ_STREAM, 4, 16, 1, 0);
1832  ast_test_validate(test, res == AST_TEST_PASS, "multi, read stream, 4 stream");
1833 
1834  res = read_test(test, &tech, CHANNEL_READ, 2, 16, 3, 0);
1835  ast_test_validate(test, res == AST_TEST_PASS, "multi, non read stream, 2 stream, 3 frames per read");
1836 
1837  res = read_test(test, &tech, CHANNEL_READ_STREAM, 2, 16, 3, 0);
1838  ast_test_validate(test, res == AST_TEST_PASS, "multi, read stream, 2 stream, 3 frames per read");
1839 
1840  res = read_test(test, &tech, CHANNEL_READ, 4, 16, 3, 8);
1841  ast_test_validate(test, res == AST_TEST_PASS, "multi, non read stream, 4 stream, 3 frames per read");
1842 
1843  res = read_test(test, &tech, CHANNEL_READ_STREAM, 4, 16, 3, 0);
1844  ast_test_validate(test, res == AST_TEST_PASS, "multi, read stream, 4 stream, 3 frames per read");
1845 
1846  return res;
1847 }
1848 
1849 AST_TEST_DEFINE(stream_topology_change_request_from_application_non_multistream)
1850 {
1851  struct ast_channel_tech tech = {
1853  .indicate = mock_channel_indicate,
1854  .hangup = mock_channel_hangup,
1855  };
1856  struct ast_channel *mock_channel;
1857  struct mock_channel_pvt *pvt;
1859  int change_res;
1861 
1862  switch (cmd) {
1863  case TEST_INIT:
1864  info->name = "stream_topology_change_request_from_application_non_multistream";
1865  info->category = "/main/stream/";
1866  info->summary = "stream topology changing on non-multistream channel test";
1867  info->description =
1868  "Test that an application trying to change the stream topology of a non-multistream channel gets a failure";
1869  return AST_TEST_NOT_RUN;
1870  case TEST_EXECUTE:
1871  break;
1872  }
1873 
1874  mock_channel = make_channel(test, 1, &tech);
1875  ast_test_validate_cleanup(test, mock_channel, res, done);
1876 
1877  pvt = ast_channel_tech_pvt(mock_channel);
1878  pvt->indicated_change_request = 0;
1879  pvt->indicated_changed = 0;
1880 
1881  topology = ast_stream_topology_alloc();
1882  ast_test_validate_cleanup(test, topology, res, done);
1883 
1884  change_res = ast_channel_request_stream_topology_change(mock_channel, topology, NULL);
1885 
1886  ast_test_validate_cleanup(test, change_res == -1, res, done);
1887  ast_test_validate_cleanup(test, !pvt->indicated_change_request, res, done);
1888 
1889  ast_channel_lock(mock_channel);
1890  change_res = ast_channel_stream_topology_changed(mock_channel, topology);
1891  ast_channel_unlock(mock_channel);
1892 
1893  ast_test_validate_cleanup(test, change_res == -1, res, done);
1894  ast_test_validate_cleanup(test, !pvt->indicated_changed, res, done);
1895 
1896 done:
1897  ast_hangup(mock_channel);
1898 
1899  return res;
1900 }
1901 
1902 AST_TEST_DEFINE(stream_topology_change_request_from_channel_non_multistream)
1903 {
1904  struct ast_channel_tech tech = {
1906  .write_stream = mock_channel_write_stream,
1907  .indicate = mock_channel_indicate,
1908  .hangup = mock_channel_hangup,
1909  };
1910  struct ast_channel *mock_channel;
1911  struct mock_channel_pvt *pvt;
1914  struct ast_frame request_change = {
1916  .subclass.integer = AST_CONTROL_STREAM_TOPOLOGY_REQUEST_CHANGE,
1917  };
1918  struct ast_frame *fr = NULL;
1919 
1920  switch (cmd) {
1921  case TEST_INIT:
1922  info->name = "stream_topology_change_request_from_channel_non_multistream";
1923  info->category = "/main/stream/";
1924  info->summary = "channel requesting stream topology change to non-multistream application test";
1925  info->description =
1926  "Test that a channel requesting a stream topology change from a non-multistream application does not work";
1927  return AST_TEST_NOT_RUN;
1928  case TEST_EXECUTE:
1929  break;
1930  }
1931 
1932  mock_channel = make_channel(test, 1, &tech);
1933  ast_test_validate_cleanup(test, mock_channel, res, done);
1934 
1935  pvt = ast_channel_tech_pvt(mock_channel);
1936  pvt->indicated_changed = 0;
1937 
1938  topology = ast_stream_topology_alloc();
1939  ast_test_validate_cleanup(test, topology, res, done);
1940 
1941  request_change.data.ptr = topology;
1942  ast_queue_frame(mock_channel, &request_change);
1943 
1944  fr = ast_read(mock_channel);
1945  ast_test_validate_cleanup(test, fr, res, done);
1946  ast_test_validate_cleanup(test, fr == &ast_null_frame, res, done);
1947  ast_test_validate_cleanup(test, pvt->indicated_changed, res, done);
1948 
1949 done:
1950  if (fr) {
1951  ast_frfree(fr);
1952  }
1953  ast_hangup(mock_channel);
1954 
1955  return res;
1956 }
1957 
1958 AST_TEST_DEFINE(stream_topology_change_request_from_application)
1959 {
1960  struct ast_channel_tech tech = {
1962  .write_stream = mock_channel_write_stream,
1963  .indicate = mock_channel_indicate,
1964  .hangup = mock_channel_hangup,
1965  };
1966  struct ast_channel *mock_channel;
1967  struct mock_channel_pvt *pvt;
1969  int change_res;
1971 
1972  switch (cmd) {
1973  case TEST_INIT:
1974  info->name = "stream_topology_change_request_from_application";
1975  info->category = "/main/stream/";
1976  info->summary = "stream topology change request from application test";
1977  info->description =
1978  "Test that an application changing the stream topology of a multistream capable channel receives success";
1979  return AST_TEST_NOT_RUN;
1980  case TEST_EXECUTE:
1981  break;
1982  }
1983 
1984  mock_channel = make_channel(test, 1, &tech);
1985  ast_test_validate_cleanup(test, mock_channel, res, done);
1986 
1987  pvt = ast_channel_tech_pvt(mock_channel);
1988  pvt->indicated_change_request = 0;
1989  pvt->indicated_changed = 0;
1990 
1991  topology = ast_stream_topology_alloc();
1992  ast_test_validate_cleanup(test, topology, res, done);
1993 
1994  change_res = ast_channel_request_stream_topology_change(mock_channel, topology, NULL);
1995 
1996  ast_test_validate_cleanup(test, !change_res, res, done);
1997  ast_test_validate_cleanup(test, pvt->indicated_change_request, res, done);
1998 
1999  ast_channel_lock(mock_channel);
2000  change_res = ast_channel_stream_topology_changed(mock_channel, topology);
2001  ast_channel_unlock(mock_channel);
2002 
2003  ast_test_validate_cleanup(test, !change_res, res, done);
2004  ast_test_validate_cleanup(test, pvt->indicated_changed, res, done);
2005 
2006 done:
2007  ast_hangup(mock_channel);
2008 
2009  return res;
2010 }
2011 
2012 AST_TEST_DEFINE(stream_topology_change_request_from_channel)
2013 {
2014  struct ast_channel_tech tech = {
2016  .write_stream = mock_channel_write_stream,
2017  .indicate = mock_channel_indicate,
2018  .hangup = mock_channel_hangup,
2019  };
2020  struct ast_channel *mock_channel;
2021  struct mock_channel_pvt *pvt;
2024  struct ast_frame request_change = {
2026  .subclass.integer = AST_CONTROL_STREAM_TOPOLOGY_REQUEST_CHANGE,
2027  };
2028  struct ast_frame *fr = NULL;
2029 
2030  switch (cmd) {
2031  case TEST_INIT:
2032  info->name = "stream_topology_change_request_from_channel";
2033  info->category = "/main/stream/";
2034  info->summary = "channel requesting stream topology change to multistream application test";
2035  info->description =
2036  "Test that a channel requesting a stream topology change from a multistream application works";
2037  return AST_TEST_NOT_RUN;
2038  case TEST_EXECUTE:
2039  break;
2040  }
2041 
2042  mock_channel = make_channel(test, 1, &tech);
2043  ast_test_validate_cleanup(test, mock_channel, res, done);
2044 
2045  pvt = ast_channel_tech_pvt(mock_channel);
2046  pvt->indicated_changed = 0;
2047 
2048  topology = ast_stream_topology_alloc();
2049  ast_test_validate_cleanup(test, topology, res, done);
2050 
2051  request_change.data.ptr = topology;
2052  ast_queue_frame(mock_channel, &request_change);
2053 
2054  fr = ast_read_stream(mock_channel);
2055  ast_test_validate_cleanup(test, fr, res, done);
2056  ast_test_validate_cleanup(test, fr->frametype == AST_FRAME_CONTROL, res, done);
2057  ast_test_validate_cleanup(test, fr->subclass.integer == AST_CONTROL_STREAM_TOPOLOGY_REQUEST_CHANGE, res, done);
2058  ast_test_validate_cleanup(test, !pvt->indicated_changed, res, done);
2059 
2060 done:
2061  if (fr) {
2062  ast_frfree(fr);
2063  }
2064  ast_hangup(mock_channel);
2065 
2066  return res;
2067 }
2068 
2069 AST_TEST_DEFINE(format_cap_from_stream_topology)
2070 {
2071  RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
2072  RAII_VAR(struct ast_format_cap *, stream_caps, NULL, ao2_cleanup);
2073  struct ast_stream_topology *topology;
2074  struct ast_stream *stream;
2075  struct ast_format_cap *new_cap;
2076 
2077  switch (cmd) {
2078  case TEST_INIT:
2079  info->name = "format_cap_from_stream_topology";
2080  info->category = "/main/stream/";
2081  info->summary = "stream topology to format capabilities conversion test";
2082  info->description =
2083  "Test that converting a stream topology to format capabilities results in expected formats";
2084  return AST_TEST_NOT_RUN;
2085  case TEST_EXECUTE:
2086  break;
2087  }
2088 
2090  if (!caps) {
2091  ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
2092  return AST_TEST_FAIL;
2093  }
2094 
2095  if (ast_format_cap_append(caps, ast_format_ulaw, 0)) {
2096  ast_test_status_update(test, "Failed to append ulaw format to capabilities\n");
2097  return AST_TEST_FAIL;
2098  }
2099 
2100  if (ast_format_cap_append(caps, ast_format_h264, 0)) {
2101  ast_test_status_update(test, "Failed to append h264 format to capabilities\n");
2102  return AST_TEST_FAIL;
2103  }
2104 
2106  if (!topology) {
2107  ast_test_status_update(test, "Failed to create a stream topology from format capabilities of ulaw and h264\n");
2108  return AST_TEST_FAIL;
2109  }
2110 
2111  /*
2112  * Append declined stream with formats that should not be included
2113  * in combined topology caps.
2114  */
2115  stream = ast_stream_alloc("audio", AST_MEDIA_TYPE_AUDIO);
2116  if (!stream) {
2117  ast_test_status_update(test, "Failed to create an audio stream for testing stream topology\n");
2118  ast_stream_topology_free(topology);
2119  return AST_TEST_FAIL;
2120  }
2123  if (!new_cap) {
2124  ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n");
2125  ast_stream_free(stream);
2126  ast_stream_topology_free(topology);
2127  return AST_TEST_FAIL;
2128  }
2129  if (ast_format_cap_append(new_cap, ast_format_alaw, 0)) {
2130  ast_test_status_update(test, "Failed to append alaw format to capabilities\n");
2131  ao2_cleanup(new_cap);
2132  ast_stream_free(stream);
2133  ast_stream_topology_free(topology);
2134  return AST_TEST_FAIL;
2135  }
2136  ast_stream_set_formats(stream, new_cap);
2137  ao2_cleanup(new_cap);
2138  if (ast_stream_topology_append_stream(topology, stream) == -1) {
2139  ast_test_status_update(test, "Failed to append a perfectly good stream to a topology\n");
2140  ast_stream_free(stream);
2141  ast_stream_topology_free(topology);
2142  return AST_TEST_FAIL;
2143  }
2144 
2145  stream_caps = ast_stream_topology_get_formats(topology);
2146  if (!stream_caps) {
2147  ast_test_status_update(test, "Failed to create a format capabilities from a stream topology\n");
2148  ast_stream_topology_free(topology);
2149  return AST_TEST_FAIL;
2150  }
2151 
2152  ast_stream_topology_free(topology);
2153 
2154  if (!ast_format_cap_identical(caps, stream_caps)) {
2155  ast_test_status_update(test, "Converting format capabilities into topology and back resulted in different formats\n");
2156  return AST_TEST_FAIL;
2157  }
2158 
2159  return AST_TEST_PASS;
2160 }
2161 
2162 #define topology_append_stream(topology, name, type, res, label) \
2163  do { \
2164  struct ast_stream *__stream = ast_stream_alloc((name), (type)); \
2165  ast_test_validate_cleanup(test, __stream, res, label); \
2166  if (ast_stream_topology_append_stream((topology), __stream) < 0) { \
2167  ast_stream_free(__stream); \
2168  res = AST_TEST_FAIL; \
2169  goto label; \
2170  } \
2171  } while(0)
2172 
2173 AST_TEST_DEFINE(stream_topology_map_create)
2174 {
2176 
2177  struct ast_vector_int types = { NULL };
2178  struct ast_vector_int v0 = { NULL };
2179  struct ast_vector_int v1 = { NULL };
2180 
2182 
2183  switch (cmd) {
2184  case TEST_INIT:
2185  info->name = "stream_topology_map_create";
2186  info->category = "/main/stream/";
2187  info->summary = "stream topology map creation unit test";
2188  info->description =
2189  "Test that creating a stream topology map works";
2190  return AST_TEST_NOT_RUN;
2191  case TEST_EXECUTE:
2192  break;
2193  }
2194 
2195  ast_test_validate(test, AST_VECTOR_INIT(&types, 5) == 0);
2196 
2197  /* Map a first topology and check that it mapped one to one */
2198  ast_test_validate_cleanup(test, (t0 = ast_stream_topology_alloc()), res, done);
2199  topology_append_stream(t0, "audio", AST_MEDIA_TYPE_AUDIO, res, done);
2200  topology_append_stream(t0, "video", AST_MEDIA_TYPE_VIDEO, res, done);
2201 
2202  ast_stream_topology_map(t0, &types, &v0, &v1);
2203  ast_test_validate_cleanup(test, AST_VECTOR_SIZE(&types) == 2, res, done);
2204  ast_test_validate_cleanup(test, AST_VECTOR_GET(&types, 0) == AST_MEDIA_TYPE_AUDIO, res, done);
2205  ast_test_validate_cleanup(test, AST_VECTOR_GET(&types, 1) == AST_MEDIA_TYPE_VIDEO, res, done);
2206  ast_test_validate_cleanup(test, AST_VECTOR_GET(&v0, 0) == 0, res, done);
2207  ast_test_validate_cleanup(test, AST_VECTOR_GET(&v0, 1) == 1, res, done);
2208  ast_test_validate_cleanup(test, AST_VECTOR_GET(&v1, 0) == 0, res, done);
2209  ast_test_validate_cleanup(test, AST_VECTOR_GET(&v1, 1) == 1, res, done);
2210 
2211  /* Map a second topology and check that it merged */
2213  ast_test_validate_cleanup(test, (t0 = ast_stream_topology_alloc()), res, done);
2214  topology_append_stream(t0, "video", AST_MEDIA_TYPE_VIDEO, res, done);
2215  topology_append_stream(t0, "audio", AST_MEDIA_TYPE_AUDIO, res, done);
2216 
2217  ast_stream_topology_map(t0, &types, &v0, &v1);
2218  ast_test_validate_cleanup(test, AST_VECTOR_SIZE(&types) == 2, res, done);
2219  ast_test_validate_cleanup(test, AST_VECTOR_GET(&types, 0) == AST_MEDIA_TYPE_AUDIO, res, done);
2220  ast_test_validate_cleanup(test, AST_VECTOR_GET(&types, 1) == AST_MEDIA_TYPE_VIDEO, res, done);
2221  ast_test_validate_cleanup(test, AST_VECTOR_GET(&v0, 0) == 1, res, done);
2222  ast_test_validate_cleanup(test, AST_VECTOR_GET(&v0, 1) == 0, res, done);
2223  ast_test_validate_cleanup(test, AST_VECTOR_GET(&v1, 0) == 1, res, done);
2224  ast_test_validate_cleanup(test, AST_VECTOR_GET(&v1, 1) == 0, res, done);
2225 
2226  /* Map a third topology with more streams and check that it merged */
2228  ast_test_validate_cleanup(test, (t0 = ast_stream_topology_alloc()), res, done);
2229  topology_append_stream(t0, "video", AST_MEDIA_TYPE_VIDEO, res, done);
2230  topology_append_stream(t0, "audio", AST_MEDIA_TYPE_AUDIO, res, done);
2231  topology_append_stream(t0, "audio", AST_MEDIA_TYPE_AUDIO, res, done);
2232 
2233  ast_stream_topology_map(t0, &types, &v0, &v1);
2234  ast_test_validate_cleanup(test, AST_VECTOR_SIZE(&types) == 3, res, done);
2235  ast_test_validate_cleanup(test, AST_VECTOR_GET(&types, 0) == AST_MEDIA_TYPE_AUDIO, res, done);
2236  ast_test_validate_cleanup(test, AST_VECTOR_GET(&types, 1) == AST_MEDIA_TYPE_VIDEO, res, done);
2237  ast_test_validate_cleanup(test, AST_VECTOR_GET(&types, 2) == AST_MEDIA_TYPE_AUDIO, res, done);
2238  ast_test_validate_cleanup(test, AST_VECTOR_GET(&v0, 0) == 1, res, done);
2239  ast_test_validate_cleanup(test, AST_VECTOR_GET(&v0, 1) == 0, res, done);
2240  ast_test_validate_cleanup(test, AST_VECTOR_GET(&v0, 2) == 2, res, done);
2241  ast_test_validate_cleanup(test, AST_VECTOR_GET(&v1, 0) == 1, res, done);
2242  ast_test_validate_cleanup(test, AST_VECTOR_GET(&v1, 1) == 0, res, done);
2243  ast_test_validate_cleanup(test, AST_VECTOR_GET(&v1, 2) == 2, res, done);
2244 
2245 done:
2246  AST_VECTOR_FREE(&v1);
2247  AST_VECTOR_FREE(&v0);
2248  AST_VECTOR_FREE(&types);
2249 
2250  return res;
2251 }
2252 
2253 static int unload_module(void)
2254 {
2255  AST_TEST_UNREGISTER(stream_create);
2256  AST_TEST_UNREGISTER(stream_create_no_name);
2257  AST_TEST_UNREGISTER(stream_set_type);
2258  AST_TEST_UNREGISTER(stream_set_formats);
2259  AST_TEST_UNREGISTER(stream_set_state);
2260  AST_TEST_UNREGISTER(stream_metadata);
2261  AST_TEST_UNREGISTER(stream_topology_create);
2262  AST_TEST_UNREGISTER(stream_topology_clone);
2263  AST_TEST_UNREGISTER(stream_topology_clone);
2264  AST_TEST_UNREGISTER(stream_topology_append_stream);
2265  AST_TEST_UNREGISTER(stream_topology_set_stream);
2266  AST_TEST_UNREGISTER(stream_topology_del_stream);
2267  AST_TEST_UNREGISTER(stream_topology_create_from_format_cap);
2268  AST_TEST_UNREGISTER(stream_topology_get_first_stream_by_type);
2269  AST_TEST_UNREGISTER(stream_topology_create_from_channel_nativeformats);
2270  AST_TEST_UNREGISTER(stream_topology_channel_set);
2271  AST_TEST_UNREGISTER(stream_write_non_multistream);
2272  AST_TEST_UNREGISTER(stream_write_multistream);
2273  AST_TEST_UNREGISTER(stream_read_non_multistream);
2274  AST_TEST_UNREGISTER(stream_read_multistream);
2275  AST_TEST_UNREGISTER(stream_topology_change_request_from_application_non_multistream);
2276  AST_TEST_UNREGISTER(stream_topology_change_request_from_channel_non_multistream);
2277  AST_TEST_UNREGISTER(stream_topology_change_request_from_application);
2278  AST_TEST_UNREGISTER(stream_topology_change_request_from_channel);
2279  AST_TEST_UNREGISTER(format_cap_from_stream_topology);
2280  AST_TEST_UNREGISTER(stream_topology_map_create);
2281  return 0;
2282 }
2283 
2284 static int load_module(void)
2285 {
2286  AST_TEST_REGISTER(stream_create);
2287  AST_TEST_REGISTER(stream_create_no_name);
2288  AST_TEST_REGISTER(stream_set_type);
2289  AST_TEST_REGISTER(stream_set_formats);
2290  AST_TEST_REGISTER(stream_set_state);
2291  AST_TEST_REGISTER(stream_metadata);
2292  AST_TEST_REGISTER(stream_topology_create);
2293  AST_TEST_REGISTER(stream_topology_clone);
2294  AST_TEST_REGISTER(stream_topology_append_stream);
2295  AST_TEST_REGISTER(stream_topology_set_stream);
2296  AST_TEST_REGISTER(stream_topology_del_stream);
2297  AST_TEST_REGISTER(stream_topology_create_from_format_cap);
2298  AST_TEST_REGISTER(stream_topology_get_first_stream_by_type);
2299  AST_TEST_REGISTER(stream_topology_create_from_channel_nativeformats);
2300  AST_TEST_REGISTER(stream_topology_channel_set);
2301  AST_TEST_REGISTER(stream_write_non_multistream);
2302  AST_TEST_REGISTER(stream_write_multistream);
2303  AST_TEST_REGISTER(stream_read_non_multistream);
2304  AST_TEST_REGISTER(stream_read_multistream);
2305  AST_TEST_REGISTER(stream_topology_change_request_from_application_non_multistream);
2306  AST_TEST_REGISTER(stream_topology_change_request_from_channel_non_multistream);
2307  AST_TEST_REGISTER(stream_topology_change_request_from_application);
2308  AST_TEST_REGISTER(stream_topology_change_request_from_channel);
2309  AST_TEST_REGISTER(format_cap_from_stream_topology);
2310  AST_TEST_REGISTER(stream_topology_map_create);
2311  return AST_MODULE_LOAD_SUCCESS;
2312 }
2313 
2314 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Media Stream API test module");
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
CHANNEL_READ_TYPE
Definition: test_stream.c:1702
static const char type[]
Definition: chan_ooh323.c:109
void ast_channel_fdno_set(struct ast_channel *chan, int value)
#define ast_channel_lock(chan)
Definition: channel.h:2945
Main Channel structure associated with a channel.
#define ast_frdup(fr)
Copies a frame.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:567
Asterisk main include file. File version handling, generic pbx functions.
unsigned int indicated_change_request
Definition: test_stream.c:1105
struct ast_stream_topology * ast_channel_get_stream_topology(const struct ast_channel *chan)
Retrieve the topology of streams on a channel.
#define AST_UUID_STR_LEN
Definition: uuid.h:27
struct ast_format_cap * ast_stream_topology_get_formats(struct ast_stream_topology *topology)
Create a format capabilities structure representing the topology.
Definition: stream.c:930
void * ast_channel_tech_pvt(const struct ast_channel *chan)
int(*const write)(struct ast_channel *chan, struct ast_frame *frame)
Write a frame, in standard format (see frame.h)
Definition: channel.h:751
static enum ast_test_result_state read_test(struct ast_test *test, struct ast_channel_tech *tech, enum CHANNEL_READ_TYPE rt, int streams, int frames, int frames_per_read, int expected_nulls)
Definition: test_stream.c:1716
static int mock_channel_write_stream(struct ast_channel *chan, int stream_num, struct ast_frame *fr)
Definition: test_stream.c:1167
enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
Get the media type of a stream.
Definition: stream.c:316
struct ast_format * ast_format_ulaw
Built-in cached ulaw format.
Definition: format_cache.c:86
#define AST_FORMAT_CAP_NAMES_LEN
Definition: format_cap.h:326
const char * ast_codec_media_type2str(enum ast_media_type type)
Conversion function to take a media type and turn it into a string.
Definition: codec.c:347
struct ast_frame *(*const read_stream)(struct ast_channel *chan)
Read a frame (or chain of frames from the same stream), in standard format (see frame.h), with stream num.
Definition: channel.h:748
struct ast_frame::@264 frame_list
Universally unique identifier support.
Set when the stream has been removed/declined.
Definition: stream.h:78
Test Framework API.
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4302
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
struct ast_frame * ast_read_stream(struct ast_channel *chan)
Reads a frame, but does not filter to just the default streams.
Definition: channel.c:4307
struct ast_stream_topology * ast_stream_topology_create_from_format_cap(struct ast_format_cap *cap)
A helper function that, given a format capabilities structure, creates a topology and separates the m...
Definition: stream.c:848
Set when the stream is not sending OR receiving media.
Definition: stream.h:94
#define ast_str_alloca(init_len)
Definition: strings.h:800
int ast_channel_request_stream_topology_change(struct ast_channel *chan, struct ast_stream_topology *topology, void *change_source)
Request that the stream topology of a channel change.
Definition: channel.c:11167
struct ast_stream * ast_stream_topology_get_stream(const struct ast_stream_topology *topology, unsigned int position)
Get a specific stream from the topology.
Definition: stream.c:788
#define NULL
Definition: resample.c:96
int ast_stream_topology_append_stream(struct ast_stream_topology *topology, struct ast_stream *stream)
Append a stream to the topology.
Definition: stream.c:748
char * end
Definition: eagi_proxy.c:73
void ast_stream_set_formats(struct ast_stream *stream, struct ast_format_cap *caps)
Set the current negotiated formats of a stream.
Definition: stream.c:365
static struct ast_frame * mock_channel_read(struct ast_channel *chan)
Definition: test_stream.c:1109
int ast_stream_topology_set_stream(struct ast_stream_topology *topology, unsigned int position, struct ast_stream *stream)
Set a specific position in a topology.
Definition: stream.c:796
int ast_write_stream(struct ast_channel *chan, int stream_num, struct ast_frame *frame)
Write a frame to a stream This function writes the given frame to the indicated stream on the channel...
Definition: channel.c:5194
struct ast_frame_subclass subclass
Media Stream API.
Media Format API.
void ast_channel_tech_set(struct ast_channel *chan, const struct ast_channel_tech *value)
int done
Definition: test_amihooks.c:48
const struct ast_channel_tech * tech
struct ast_readq_list * ast_channel_readq(struct ast_channel *chan)
static int unload_module(void)
Definition: test_stream.c:2253
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
struct ast_stream * ast_stream_topology_get_first_stream_by_type(const struct ast_stream_topology *topology, enum ast_media_type type)
Gets the first active stream of a specific type from the topology.
Definition: stream.c:964
static const struct ast_channel_tech mock_channel_old_write_tech
Definition: test_stream.c:1239
General Asterisk PBX channel definitions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
static int frames
Definition: parser.c:51
#define ast_format_cap_append(cap, format, framing)
Definition: format_cap.h:103
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
const struct ast_format_cap * ast_stream_get_formats(const struct ast_stream *stream)
Get the current negotiated formats of a stream.
Definition: stream.c:330
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
Structure to describe a channel "technology", ie a channel driver See for examples: ...
Definition: channel.h:629
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel&#39;s frame queue.
Definition: channel.c:1139
static const struct ast_channel_tech mock_channel_write_stream_tech
Definition: test_stream.c:1335
void ast_format_cap_remove_by_type(struct ast_format_cap *cap, enum ast_media_type type)
Remove all formats matching a specific format type.
Definition: format_cap.c:525
Format Capabilities API.
static int load_stream_readqueue(struct ast_channel *chan, int frames)
Definition: test_stream.c:1623
Set when the stream is sending and receiving media.
Definition: stream.h:82
int ast_channel_stream_topology_changed(struct ast_channel *chan, struct ast_stream_topology *topology)
Provide notice to a channel that the stream topology has changed.
Definition: channel.c:11197
struct ast_stream_topology * ast_channel_set_stream_topology(struct ast_channel *chan, struct ast_stream_topology *topology)
Set the topology of streams on a channel.
void ast_stream_set_type(struct ast_stream *stream, enum ast_media_type type)
Change the media type of a stream.
Definition: stream.c:323
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
static int mock_channel_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Definition: test_stream.c:1154
struct ast_stream_topology * ast_stream_topology_alloc(void)
Create a stream topology.
Definition: stream.c:650
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
def info(msg)
unsigned int wrote_stream
Definition: test_stream.c:1099
struct ast_format * ast_format_h264
Built-in cached h264 format.
Definition: format_cache.c:181
const char * ast_format_cap_get_names(const struct ast_format_cap *cap, struct ast_str **buf)
Get the names of codecs of a set of formats.
Definition: format_cap.c:736
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
int ast_format_cap_identical(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2)
Determine if two capabilities structures are identical.
Definition: format_cap.c:689
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2548
void ast_stream_set_state(struct ast_stream *stream, enum ast_stream_state state)
Set the state of a stream.
Definition: stream.c:380
char * ast_uuid_generate_str(char *buf, size_t size)
Generate a UUID string.
Definition: uuid.c:143
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
Definition: channel.c:5189
unsigned int wrote
Definition: test_stream.c:1098
static struct ast_frame * read_from_chan(enum CHANNEL_READ_TYPE rt, struct ast_channel *chan)
Definition: test_stream.c:1707
static const struct ast_channel_tech mock_stream_channel_tech
Definition: test_stream.c:1177
unsigned int indicated_changed
Definition: test_stream.c:1106
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition: stream.c:765
struct ast_frame *(*const read)(struct ast_channel *chan)
Read a frame (or chain of frames from the same stream), in standard format (see frame.h)
Definition: channel.h:735
AST_TEST_DEFINE(stream_create)
Definition: test_stream.c:43
struct ast_stream_topology * ast_stream_topology_clone(const struct ast_stream_topology *topology)
Create a deep clone of an existing stream topology.
Definition: stream.c:667
struct ast_frame ast_null_frame
Definition: main/frame.c:79
void ast_stream_free(struct ast_stream *stream)
Destroy a media stream representation.
Definition: stream.c:292
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
struct ast_stream * ast_stream_alloc(const char *name, enum ast_media_type type)
Create a new media stream representation.
Definition: stream.c:233
static int load_module(void)
Definition: test_stream.c:2284
Definition: test.c:65
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static int mock_channel_write(struct ast_channel *chan, struct ast_frame *fr)
Definition: test_stream.c:1145
struct ast_format * ast_format_alaw
Built-in cached alaw format.
Definition: format_cache.c:91
struct ast_frame * next
int ast_stream_set_metadata(struct ast_stream *stream, const char *m_key, const char *value)
Set a stream metadata value.
Definition: stream.c:460
#define ast_frfree(fr)
const char * ast_stream_get_metadata(const struct ast_stream *stream, const char *m_key)
Get a stream metadata value.
Definition: stream.c:423
Data structure associated with a single frame of data.
union ast_frame::@263 data
ast_media_type
Types of media.
Definition: codec.h:30
void ast_stream_topology_map(const struct ast_stream_topology *topology, struct ast_vector_int *types, struct ast_vector_int *v0, struct ast_vector_int *v1)
Map a given topology&#39;s streams to the given types.
Definition: stream.c:985
enum ast_frame_type frametype
#define topology_append_stream(topology, name, type, res, label)
Definition: test_stream.c:2162
struct ast_format * format
void ast_stream_topology_free(struct ast_stream_topology *topology)
Unreference and destroy a stream topology.
Definition: stream.c:743
int ast_stream_get_position(const struct ast_stream *stream)
Get the position of the stream in the topology.
Definition: stream.c:500
const char * ast_stream_get_name(const struct ast_stream *stream)
Get the name of a stream.
Definition: stream.c:309
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
static const struct ast_channel_tech mock_channel_tech
Definition: test_stream.c:988
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition: channel.h:1259
Asterisk module definitions.
static int check_stream_positions(struct ast_test *test, const struct ast_stream_topology *topology)
Definition: test_stream.c:650
void ast_channel_tech_pvt_set(struct ast_channel *chan, void *value)
static int mock_channel_hangup(struct ast_channel *chan)
Definition: test_stream.c:1227
static struct ast_channel * make_channel(struct ast_test *test, int streams, struct ast_channel_tech *tech)
Definition: test_stream.c:1650
int ast_stream_topology_del_stream(struct ast_stream_topology *topology, unsigned int position)
Delete a specified stream from the given topology.
Definition: stream.c:825
enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
Get the current state of a stream.
Definition: stream.c:373
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611
unsigned int position
The position of the stream in the topology.
Definition: stream.c:90
ast_test_result_state
Definition: test.h:200
Media Format Cache API.