RTS API Documentation  1.10.11
switch_core_media_bug.c
Go to the documentation of this file.
1 /*
2  * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3  * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
4  *
5  * Version: MPL 1.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18  *
19  * The Initial Developer of the Original Code is
20  * Anthony Minessale II <anthm@freeswitch.org>
21  * Portions created by the Initial Developer are Copyright (C)
22  * the Initial Developer. All Rights Reserved.
23  *
24  * Contributor(s):
25  *
26  * Anthony Minessale II <anthm@freeswitch.org>
27  * Michael Jerris <mike@jerris.com>
28  * Paul D. Tinsley <pdt at jackhammer.org>
29  *
30  *
31  * switch_core_media_bug.c -- Main Core Library (Media Bugs)
32  *
33  */
34 
35 #include "switch.h"
37 
39 {
40  switch_event_t *event = NULL;
41  switch_media_bug_t *bp = *bug;
42 
43  *bug = NULL;
44 
45  if (bp->text_buffer) {
48  }
49 
50  switch_img_free(&bp->spy_img[0]);
51  switch_img_free(&bp->spy_img[1]);
52 
53  if (bp->video_bug_thread) {
54  switch_status_t st;
55  int i;
56 
57  for (i = 0; i < 2; i++) {
58  void *pop;
59  switch_image_t *img;
60 
61  if (bp->spy_video_queue[i]) {
62  while (switch_queue_trypop(bp->spy_video_queue[i], &pop) == SWITCH_STATUS_SUCCESS && pop) {
63  img = (switch_image_t *) pop;
64  switch_img_free(&img);
65  }
66  }
67  }
68 
70  }
71 
74  }
75 
76  if (bp->raw_read_buffer) {
78  }
79 
80  if (bp->raw_write_buffer) {
82  }
83 
85  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Media-Bug-Function", "%s", bp->function);
86  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Media-Bug-Target", "%s", bp->target);
88  switch_event_fire(&event);
89  }
90 }
91 
93 {
95 }
96 
98 {
100 }
101 
103 {
104  return switch_test_flag(bug, flag);
105 }
106 
108 {
109  if ((flag & SMBF_PRUNE)) {
111  }
112  return switch_set_flag(bug, flag);
113 }
114 
116 {
117  return switch_clear_flag(bug, flag);
118 }
119 
121 {
122  bug->mm = *mm;
123 }
124 
126 {
127  *mm = bug->mm;
128 }
129 
131 {
132  return bug->session;
133 }
134 
136 {
137  return bug->text_framedata;
138 }
139 
141 {
142  return bug->video_ping_frame;
143 }
144 
146 {
147  return bug->write_replace_frame_in;
148 }
149 
151 {
152  bug->write_replace_frame_out = frame;
153 }
154 
156 {
157  return bug->read_replace_frame_in;
158 }
159 
161 {
162  return bug->native_read_frame;
163 }
164 
166 {
167  return bug->native_write_frame;
168 }
169 
171 {
172  bug->read_replace_frame_out = frame;
173 }
174 
176 {
177  bug->read_demux_frame = frame;
178 }
179 
181 {
182  return bug->user_data;
183 }
184 
186 {
187 
188  bug->record_pre_buffer_count = 0;
189 
190  if (bug->raw_read_buffer) {
194  }
195 
196  if (bug->raw_write_buffer) {
200  }
201 
202  bug->record_frame_size = 0;
203  bug->record_pre_buffer_count = 0;
204 }
205 
207 {
210  *readp = bug->raw_read_buffer ? switch_buffer_inuse(bug->raw_read_buffer) : 0;
212  } else {
213  *readp = 0;
214  }
215 
218  *writep = bug->raw_write_buffer ? switch_buffer_inuse(bug->raw_write_buffer) : 0;
220  } else {
221  *writep = 0;
222  }
223 }
224 
226 {
227  bug->record_pre_buffer_max = framecount;
228 
229  return SWITCH_STATUS_SUCCESS;
230 }
231 
233 {
234  switch_size_t bytes = 0, datalen = 0;
235  int16_t *dp, *fp;
236  uint32_t x;
237  size_t rlen = 0;
238  size_t wlen = 0;
239  uint32_t blen;
241  int16_t *tp;
242  switch_size_t do_read = 0, do_write = 0, has_read = 0, has_write = 0, fill_read = 0, fill_write = 0;
243 
244  switch_core_session_get_read_impl(bug->session, &read_impl);
245 
246  bytes = read_impl.decoded_bytes_per_packet;
247 
248  if (frame->buflen < bytes) {
251  return SWITCH_STATUS_FALSE;
252  }
253 
254  if ((!bug->raw_read_buffer && (!bug->raw_write_buffer || !switch_test_flag(bug, SMBF_WRITE_STREAM)))) {
256  "%s Buffer Error (raw_read_buffer=%p, raw_write_buffer=%p, read=%s, write=%s)\n",
258  (void *)bug->raw_read_buffer, (void *)bug->raw_write_buffer,
259  switch_test_flag(bug, SMBF_READ_STREAM) ? "yes" : "no",
260  switch_test_flag(bug, SMBF_WRITE_STREAM) ? "yes" : "no");
261  return SWITCH_STATUS_FALSE;
262  }
263 
264  frame->flags = 0;
265  frame->datalen = 0;
266 
268  has_read = 1;
270  do_read = switch_buffer_inuse(bug->raw_read_buffer);
272  }
273 
275  has_write = 1;
277  do_write = switch_buffer_inuse(bug->raw_write_buffer);
279  }
280 
281 
282  if (bug->record_frame_size && bug->record_pre_buffer_max && (do_read || do_write) && bug->record_pre_buffer_count < bug->record_pre_buffer_max) {
284  return SWITCH_STATUS_FALSE;
285  } else {
286  uint32_t frame_size;
287  switch_codec_implementation_t read_impl = { 0 };
288 
289  switch_core_session_get_read_impl(bug->session, &read_impl);
290  frame_size = read_impl.decoded_bytes_per_packet;
291  bug->record_frame_size = frame_size;
292  }
293 
294  if (bug->record_frame_size && do_write > do_read && do_write > (bug->record_frame_size * 2)) {
297  do_write = switch_buffer_inuse(bug->raw_write_buffer);
299  }
300 
301 
302 
303  if ((has_read && !do_read)) {
304  fill_read = 1;
305  }
306 
307  if ((has_write && !do_write)) {
308  fill_write = 1;
309  }
310 
311 
312  if (bug->record_frame_size) {
313  if ((do_read && do_read < bug->record_frame_size) || (do_write && do_write < bug->record_frame_size)) {
314  return SWITCH_STATUS_FALSE;
315  }
316 
317  if (do_read && do_read > bug->record_frame_size) {
318  do_read = bug->record_frame_size;
319  }
320 
321  if (do_write && do_write > bug->record_frame_size) {
322  do_write = bug->record_frame_size;
323  }
324  }
325 
326  if ((fill_read && fill_write) || (fill && (fill_read || fill_write))) {
327  return SWITCH_STATUS_FALSE;
328  }
329 
330  if (do_read && do_read > SWITCH_RECOMMENDED_BUFFER_SIZE) {
331  do_read = 1280;
332  }
333 
334  if (do_write && do_write > SWITCH_RECOMMENDED_BUFFER_SIZE) {
335  do_write = 1280;
336  }
337 
338  if (do_read) {
340  frame->datalen = (uint32_t) switch_buffer_read(bug->raw_read_buffer, frame->data, do_read);
341  if (frame->datalen != do_read) {
345  return SWITCH_STATUS_FALSE;
346  }
348  } else if (fill_read) {
349  frame->datalen = (uint32_t)bytes;
350  memset(frame->data, 255, frame->datalen);
351  }
352 
353  if (do_write) {
356  datalen = (uint32_t) switch_buffer_read(bug->raw_write_buffer, bug->data, do_write);
357  if (datalen != do_write) {
361  return SWITCH_STATUS_FALSE;
362  }
364  } else if (fill_write) {
365  datalen = bytes;
366  memset(bug->data, 255, datalen);
367  }
368 
369  tp = bug->tmp;
370  dp = (int16_t *) bug->data;
371  fp = (int16_t *) frame->data;
372  rlen = frame->datalen / 2;
373  wlen = datalen / 2;
374  blen = (uint32_t)(bytes / 2);
375 
376  if (switch_test_flag(bug, SMBF_STEREO)) {
377  int16_t *left, *right;
378  size_t left_len, right_len;
380  left = dp; /* write stream */
381  left_len = wlen;
382  right = fp; /* read stream */
383  right_len = rlen;
384  } else {
385  left = fp; /* read stream */
386  left_len = rlen;
387  right = dp; /* write stream */
388  right_len = wlen;
389  }
390  for (x = 0; x < blen; x++) {
391  if (x < left_len) {
392  *(tp++) = *(left + x);
393  } else {
394  *(tp++) = 0;
395  }
396  if (x < right_len) {
397  *(tp++) = *(right + x);
398  } else {
399  *(tp++) = 0;
400  }
401  }
402  memcpy(frame->data, bug->tmp, bytes * 2);
403  } else {
404  for (x = 0; x < blen; x++) {
405  int32_t w = 0, r = 0, z = 0;
406 
407  if (x < rlen) {
408  r = (int32_t) * (fp + x);
409  }
410 
411  if (x < wlen) {
412  w = (int32_t) * (dp + x);
413  }
414 
415  z = w + r;
416 
417  if (z > SWITCH_SMAX || z < SWITCH_SMIN) {
418  if (r) z += (r/2);
419  if (w) z += (w/2);
420  }
421 
423 
424  *(fp + x) = (int16_t) z;
425  }
426  }
427 
428  frame->datalen = (uint32_t)bytes;
429  frame->samples = (uint32_t)(bytes / sizeof(int16_t) / read_impl.number_of_channels);
430  frame->rate = read_impl.actual_samples_per_second;
431  frame->codec = NULL;
432 
433  if (switch_test_flag(bug, SMBF_STEREO)) {
434  frame->datalen *= 2;
435  frame->channels = 2;
436  } else {
437  frame->channels = read_impl.number_of_channels;
438  }
439 
440  return SWITCH_STATUS_SUCCESS;
441 }
442 
444 {
445  if (zstr(name)) goto end;
446 
447  if (!strcasecmp(name, "dual-crop")) {
448  return SPY_DUAL_CROP;
449  }
450 
451  if (!strcasecmp(name, "lower-right-large")) {
452  return SPY_LOWER_RIGHT_LARGE;
453  }
454 
455  end:
456 
457  return SPY_LOWER_RIGHT_SMALL;
458 }
459 
461 {
462  bug->spy_fmt = spy_fmt;
463 }
464 
466 {
467  switch_queue_t *spy_q = NULL;
468  int w = 0, h = 0;
469  void *pop;
470  int i;
471 
472  for (i = 0; i < 2; i++) {
473  if (!bug->spy_video_queue[i]) {
475  }
476  }
477 
478  spy_q = bug->spy_video_queue[rw];
479 
480  while(switch_queue_size(spy_q) > 0) {
481  if (switch_queue_trypop(spy_q, &pop) == SWITCH_STATUS_SUCCESS) {
482  switch_img_free(&bug->spy_img[rw]);
483  if (!(bug->spy_img[rw] = (switch_image_t *) pop)) {
484  break;
485  }
486  }
487  }
488 
489  w = img->d_w;
490  h = img->d_h;
491 
492  if (bug->spy_img[rw]) {
493 
494  switch (bug->spy_fmt) {
495  case SPY_DUAL_CROP:
496  {
497  switch_image_t *spy_tmp = NULL;
498  switch_image_t *img_tmp = NULL;
499  switch_image_t *img_dup = NULL;
500  int x = 0, y = 0;
501  float aspect169 = (float)1920 / 1080;
502  switch_rgb_color_t bgcolor = { 0 };
503 
504  if ((float)w/h == aspect169) {
505  if ((float)bug->spy_img[rw]->d_w / bug->spy_img[rw]->d_h == aspect169) {
506  spy_tmp = switch_img_copy_rect(bug->spy_img[rw], bug->spy_img[rw]->d_w / 4, 0, bug->spy_img[rw]->d_w / 2, bug->spy_img[rw]->d_h);
507 
508  } else {
509  switch_img_copy(bug->spy_img[rw], &spy_tmp);
510  }
511  } else {
512  if ((float)bug->spy_img[rw]->d_w / bug->spy_img[rw]->d_h == aspect169) {
513  spy_tmp = switch_img_copy_rect(bug->spy_img[rw], bug->spy_img[rw]->d_w / 6, 0, bug->spy_img[rw]->d_w / 4, bug->spy_img[rw]->d_h);
514  } else {
515  spy_tmp = switch_img_copy_rect(bug->spy_img[rw], bug->spy_img[rw]->d_w / 4, 0, bug->spy_img[rw]->d_w / 2, bug->spy_img[rw]->d_h);
516  }
517  }
518 
519  switch_img_copy(img, &img_dup);
520  img_tmp = switch_img_copy_rect(img_dup, w / 4, 0, w / 2, h);
521 
522  switch_img_fit(&spy_tmp, w / 2, h, SWITCH_FIT_SIZE);
523  switch_img_fit(&img_tmp, w / 2, h, SWITCH_FIT_SIZE);
524 
525  switch_color_set_rgb(&bgcolor, "#000000");
526  switch_img_fill(img, 0, 0, img->d_w, img->d_h, &bgcolor);
527 
528  switch_img_find_position(POS_CENTER_MID, w / 2, h, img_tmp->d_w, img_tmp->d_h, &x, &y);
529  switch_img_patch(img, img_tmp, x, y);
530 
531  switch_img_find_position(POS_CENTER_MID, w / 2, h, spy_tmp->d_w, spy_tmp->d_h, &x, &y);
532  switch_img_patch(img, spy_tmp, x + w / 2, y);
533 
534 
535  switch_img_free(&img_tmp);
536  switch_img_free(&img_dup);
537  switch_img_free(&spy_tmp);
538  }
539  break;
542  default:
543  {
544  float scaler = 0.125f;
545  int spyw, spyh;
546 
547  if (bug->spy_fmt == SPY_LOWER_RIGHT_LARGE) {
548  scaler = 0.25f;
549  }
550 
551  spyw = (int) (float)w * scaler;
552  spyh = (int) (float)h * scaler;
553 
554  if (bug->spy_img[rw]->d_w != spyw || bug->spy_img[rw]->d_h != spyh) {
555  switch_image_t *tmp_img = NULL;
556 
557  switch_img_scale(bug->spy_img[rw], &tmp_img, spyw, spyh);
558  switch_img_free(&bug->spy_img[rw]);
559  bug->spy_img[rw] = tmp_img;
560  }
561 
562  switch_img_patch(img, bug->spy_img[rw], w - spyw, h - spyh);
563  }
564  break;
565  }
566 
567  return SWITCH_STATUS_SUCCESS;
568  }
569 
570  return SWITCH_STATUS_FALSE;
571 }
572 
573 static int flush_video_queue(switch_queue_t *q, int min)
574 {
575  void *pop;
576 
577  if (switch_queue_size(q) > min) {
578  while (switch_queue_trypop(q, &pop) == SWITCH_STATUS_SUCCESS) {
579  switch_image_t *img = (switch_image_t *) pop;
580  switch_img_free(&img);
581  if (min && switch_queue_size(q) <= min) {
582  break;
583  }
584  }
585  }
586 
587  return switch_queue_size(q);
588 }
589 
591 {
592  switch_media_bug_t *bug = (switch_media_bug_t *) obj;
593  switch_queue_t *main_q = NULL, *other_q = NULL;
594  switch_image_t *IMG = NULL, *img = NULL, *other_img = NULL;
595  void *pop, *other_pop;
596  uint8_t *buf;
598  switch_frame_t frame = { 0 };
599  switch_timer_t timer = { 0 };
600  switch_mm_t mm = { 0 };
601  int vw = 1280;
602  int vh = 720;
603  int last_w = 0, last_h = 0, other_last_w = 0, other_last_h = 0;
604  switch_fps_t fps_data = { 0 };
605  float fps;
606  switch_rgb_color_t color = { 0 };
607  switch_color_set_rgb(&color, "#000000");
608 
609  buf = switch_core_session_alloc(bug->session, buflen);
610  frame.packet = buf;
611  frame.data = buf + 12;
612  frame.packetlen = buflen;
613  frame.buflen = buflen - 12;
614  frame.flags = SFF_RAW_RTP;
615 
617  main_q = bug->read_video_queue;
618 
620  other_q = bug->write_video_queue;
621  }
622  } else if (switch_test_flag(bug, SMBF_WRITE_VIDEO_STREAM)) {
623  main_q = bug->write_video_queue;
624  } else {
625  return NULL;
626  }
627 
629 
630  if (mm.vw) vw = mm.vw;
631  if (mm.vh) vh = mm.vh;
632 
633  if (mm.fps) {
634  fps = mm.fps;
635  } else {
636  fps = 15;
637  }
638  switch_calc_video_fps(&fps_data, fps);
639 
640  switch_core_timer_init(&timer, "soft", fps_data.ms, fps_data.samples, NULL);
641 
642  while (bug->ready) {
643  int w = 0, h = 0, ok = 1, new_main = 0, new_other = 0, new_canvas = 0;
644 
645  switch_core_timer_next(&timer);
646 
648  flush_video_queue(main_q, 0);
649  if (other_q) flush_video_queue(other_q, 0);
650  continue;
651  }
652 
653  flush_video_queue(main_q, 1);
654 
655  w = vw / 2;
656  h = vh;
657 
658  if (switch_queue_trypop(main_q, &pop) == SWITCH_STATUS_SUCCESS) {
659  switch_img_free(&img);
660 
661  if (!pop) {
662  goto end;
663  }
664 
665  img = (switch_image_t *) pop;
666  new_main = 1;
667 
668  if (IMG && !(last_w == img->d_w && last_h == img->d_h)) {
669  switch_img_fill(IMG, 0, 0, w, h, &color);
670  }
671 
672  last_w = img->d_w;
673  last_h = img->d_h;
674  }
675 
676  if (other_q) {
677  flush_video_queue(other_q, 1);
678 
679  if (switch_queue_trypop(other_q, &other_pop) == SWITCH_STATUS_SUCCESS) {
680  switch_img_free(&other_img);
681  other_img = (switch_image_t *) other_pop;
682 
683  if (IMG && !(other_last_w == other_img->d_w && other_last_h == other_img->d_h)) {
684  switch_img_fill(IMG, w, 0, w, h, &color);
685  }
686 
687  other_last_w = other_img->d_w;
688  other_last_h = other_img->d_h;
689  new_other = 1;
690  }
691 
692 
693  if (img && new_main) {
694  switch_img_fit(&img, w, h, SWITCH_FIT_SIZE);
695  }
696 
697  if (other_img && new_other) {
698  switch_img_fit(&other_img, w, h, SWITCH_FIT_SIZE);
699  }
700 
701  if (!IMG) {
702  IMG = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, vw, vh, 1);
703  new_canvas = 1;
704  switch_img_fill(IMG, 0, 0, IMG->d_w, IMG->d_h, &color);
705  }
706  }
707 
708 
709  if (IMG) {
710 
711 
712  if (img && (new_canvas || new_main)) {
713  int x = 0, y = 0;
714  switch_img_find_position(POS_CENTER_MID, w, h, img->d_w, img->d_h, &x, &y);
715 
716  switch_img_patch(IMG, img, x, y);
717  }
718 
719  if (other_img && (new_canvas || new_other)) {
720  int x = 0, y = 0;
721  switch_img_find_position(POS_CENTER_MID, w, h, other_img->d_w, other_img->d_h, &x, &y);
722 
723  switch_img_patch(IMG, other_img, w + x, y);
724  }
725  }
726 
727  if (IMG || img) {
729  frame.img = other_q ? IMG : img;
730 
731  bug->video_ping_frame = &frame;
732 
733  if (bug->callback) {
735  || (bug->stop_time && bug->stop_time <= switch_epoch_time_now(NULL))) {
736  ok = SWITCH_FALSE;
737  }
738  }
739 
740  bug->video_ping_frame = NULL;
742 
743  if (!ok) {
745  goto end;
746  }
747  }
748  }
749 
750  end:
751 
753 
754  switch_img_free(&IMG);
755  switch_img_free(&img);
756  switch_img_free(&other_img);
757 
758  while (switch_queue_trypop(main_q, &pop) == SWITCH_STATUS_SUCCESS && pop) {
759  img = (switch_image_t *) pop;
760  switch_img_free(&img);
761  }
762 
763  if (other_q) {
764  while (switch_queue_trypop(other_q, &pop) == SWITCH_STATUS_SUCCESS && pop) {
765  img = (switch_image_t *) pop;
766  switch_img_free(&img);
767  }
768  }
769 
770  return NULL;
771 }
772 
774 {
775 
776  switch_assert(bug);
777  switch_assert(frame);
778 
779  if (bug->spy_video_queue[rw] && frame->img) {
780  switch_image_t *img = NULL;
781 
782  switch_img_copy(frame->img, &img);
783 
784  if (img) {
785  switch_queue_push(bug->spy_video_queue[rw], img);
786  return SWITCH_STATUS_SUCCESS;
787  }
788  }
789 
790  return SWITCH_STATUS_FALSE;
791 }
792 
793 #define MAX_BUG_BUFFER 1024 * 512
795  const char *function,
796  const char *target,
798  void *user_data, time_t stop_time,
800  switch_media_bug_t **new_bug)
801 {
802  switch_media_bug_t *bug, *bp;
803  switch_size_t bytes;
804  switch_event_t *event;
805  int tap_only = 1, punt = 0, added = 0;
806 
807  const char *p;
808 
809  if (!zstr(function)) {
810  if ((flags & SMBF_ONE_ONLY)) {
812  for (bp = session->bugs; bp; bp = bp->next) {
813  if (!zstr(bp->function) && !strcasecmp(function, bp->function)) {
814  punt = 1;
815  break;
816  }
817  }
819  }
820  }
821 
822  if (punt) {
823  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Only one bug of this type allowed!\n");
824  return SWITCH_STATUS_GENERR;
825  }
826 
827 
828  if (!switch_channel_media_ready(session->channel)) {
830  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot establish media. Media bug add failed.\n");
831  return SWITCH_STATUS_FALSE;
832  }
833  }
834 
835 
836 
837  *new_bug = NULL;
838 
839 
840  if ((p = switch_channel_get_variable(session->channel, "media_bug_answer_req")) && switch_true(p)) {
841  flags |= SMBF_ANSWER_REQ;
842  }
843 #if 0
844  if (flags & SMBF_WRITE_REPLACE) {
846  for (bp = session->bugs; bp; bp = bp->next) {
847  if (switch_test_flag(bp, SMBF_WRITE_REPLACE)) {
848  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Only one bug of this type allowed!\n");
850  return SWITCH_STATUS_GENERR;
851  }
852  }
854  }
855 
856  if (flags & SMBF_READ_REPLACE) {
858  for (bp = session->bugs; bp; bp = bp->next) {
859  if (switch_test_flag(bp, SMBF_READ_REPLACE)) {
860  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Only one bug of this type allowed!\n");
862  return SWITCH_STATUS_GENERR;
863  }
864  }
866  }
867 #endif
868 
869  if (!(bug = switch_core_session_alloc(session, sizeof(*bug)))) {
870  return SWITCH_STATUS_MEMERR;
871  }
872 
873  bug->callback = callback;
874  bug->user_data = user_data;
875  bug->session = session;
876  bug->flags = flags;
877  bug->function = "N/A";
878  bug->target = "N/A";
879 
882 
883  if (function) {
884  bug->function = switch_core_session_strdup(session, function);
885  }
886 
887  if (target) {
888  bug->target = switch_core_session_strdup(session, target);
889  }
890 
891  bug->stop_time = stop_time;
892 
893  if (!(bytes = bug->read_impl.decoded_bytes_per_packet)) {
894  bytes = 320;
895  }
896 
897  if (!bug->flags) {
899  }
900 
904  }
905 
907 
911  }
912 
913  if ((bug->flags & SMBF_THREAD_LOCK)) {
914  bug->thread_id = switch_thread_self();
915  }
916 
919 
922  }
923 
926  }
927  }
928 
932  }
933 
935 
936  switch_buffer_create_dynamic(&bug->text_buffer, 512, 1024, 0);
937  switch_zmalloc(bug->text_framedata, 1024);
938  bug->text_framesize = 1024;
939 
940  }
941 
944 
947  }
948 
951  }
952  }
953 
954 
955  if (bug->callback) {
956  switch_bool_t result = bug->callback(bug, bug->user_data, SWITCH_ABC_TYPE_INIT);
957  if (result == SWITCH_FALSE) {
959  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error attaching BUG to %s\n",
960  switch_channel_get_name(session->channel));
961  return SWITCH_STATUS_GENERR;
962  }
963  }
964 
965  bug->ready = 1;
966 
968  switch_threadattr_t *thd_attr = NULL;
970  switch_threadattr_create(&thd_attr, pool);
972  switch_thread_create(&bug->video_bug_thread, thd_attr, video_bug_thread, bug, pool);
973 
974  }
975 
978 
979  if (!session->bugs) {
980  session->bugs = bug;
981  added = 1;
982  }
983 
984  if (!added && switch_test_flag(bug, SMBF_FIRST)) {
985  bug->next = session->bugs;
986  session->bugs = bug;
987  added = 1;
988  }
989 
990  for(bp = session->bugs; bp; bp = bp->next) {
992  tap_only = 0;
993  }
994 
995  if (!added && !bp->next) {
996  bp->next = bug;
997  break;
998  }
999  }
1000 
1002  *new_bug = bug;
1003 
1004  if (tap_only) {
1006  } else {
1008  }
1009 
1012  }
1013 
1015  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Media-Bug-Function", "%s", bug->function);
1016  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Media-Bug-Target", "%s", bug->target);
1017  switch_channel_event_set_data(session->channel, event);
1018  switch_event_fire(&event);
1019  }
1020 
1022 
1023  return SWITCH_STATUS_SUCCESS;
1024 }
1025 
1026 
1028 {
1029  switch_media_bug_t *bp;
1030 
1031  if (session->bugs) {
1033  for (bp = session->bugs; bp; bp = bp->next) {
1035  }
1037  return SWITCH_STATUS_SUCCESS;
1038  }
1039 
1040  return SWITCH_STATUS_FALSE;
1041 }
1042 
1043 
1045  switch_media_bug_callback_t callback, void * (*user_data_dup_func) (switch_core_session_t *, void *))
1046 {
1047  switch_media_bug_t *new_bug = NULL, *cur = NULL, *bp = NULL, *last = NULL, *old_last_next = NULL, *old_bugs = NULL;
1048  int total = 0;
1049 
1050  if (!switch_channel_media_ready(new_session->channel)) {
1051  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(orig_session), SWITCH_LOG_WARNING, "Cannot transfer media bugs to a channel with no media.\n");
1052  return SWITCH_STATUS_FALSE;
1053  }
1054 
1055  switch_thread_rwlock_wrlock(orig_session->bug_rwlock);
1056  bp = orig_session->bugs;
1057  while (bp) {
1058  cur = bp;
1059  bp = bp->next;
1060 
1061  if (cur->callback == callback) {
1062  if (last) {
1063  old_last_next = last->next;
1064  last->next = cur->next;
1065  } else {
1066  old_bugs = orig_session->bugs;
1067  orig_session->bugs = cur->next;
1068  }
1069 
1070  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(orig_session), SWITCH_LOG_DEBUG, "Transfering %s from %s to %s\n", cur->target,
1071  switch_core_session_get_name(orig_session), switch_core_session_get_name(new_session));
1072 
1073  if ((switch_core_media_bug_add(new_session, cur->function, cur->target, cur->callback,
1074  user_data_dup_func(new_session, cur->user_data),
1075  cur->stop_time, cur->flags, &new_bug) == SWITCH_STATUS_SUCCESS)) {
1077  total++;
1078  } else {
1079  /* Call the dup function again to revert to original session */
1080  user_data_dup_func(orig_session, cur->user_data);
1081  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(orig_session), SWITCH_LOG_DEBUG, "Adding a bug failed: abort transfering %s from %s to %s\n", cur->target,
1082  switch_core_session_get_name(orig_session), switch_core_session_get_name(new_session));
1083 
1084  /* Put the old bug back to the original session's list of bugs */
1085  if (last) {
1086  last->next = old_last_next;
1087  } else {
1088  orig_session->bugs = old_bugs;
1089  }
1090 
1091  last = cur;
1092  }
1093  } else {
1094  last = cur;
1095  }
1096  }
1097 
1098  if (!orig_session->bugs && switch_core_codec_ready(&orig_session->bug_codec)) {
1099  switch_core_codec_destroy(&orig_session->bug_codec);
1100  }
1101 
1102  switch_thread_rwlock_unlock(orig_session->bug_rwlock);
1103 
1104 
1105  return total ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
1106 }
1107 
1108 
1110 {
1111  switch_media_bug_t *bp;
1112 
1113  if (orig_session->bugs) {
1114  switch_thread_rwlock_wrlock(orig_session->bug_rwlock);
1115  for (bp = orig_session->bugs; bp; bp = bp->next) {
1116  if (!strcmp(bp->function, function)) {
1118  break;
1119  }
1120  }
1121  switch_thread_rwlock_unlock(orig_session->bug_rwlock);
1122 
1123  if (bp) {
1124  *pop = bp;
1125  return SWITCH_STATUS_SUCCESS;
1126  } else {
1127  *pop = NULL;
1128  }
1129  }
1130 
1131  return SWITCH_STATUS_FALSE;
1132 }
1133 
1134 
1135 SWITCH_DECLARE(uint32_t) switch_core_media_bug_count(switch_core_session_t *orig_session, const char *function)
1136 {
1137  switch_media_bug_t *bp;
1138  uint32_t x = 0;
1139 
1140  if (orig_session->bugs) {
1141  switch_thread_rwlock_rdlock(orig_session->bug_rwlock);
1142  for (bp = orig_session->bugs; bp; bp = bp->next) {
1143  if (!switch_test_flag(bp, SMBF_PRUNE) && !switch_test_flag(bp, SMBF_LOCK) && !strcmp(bp->function, function)) {
1144  x++;
1145  }
1146  }
1147  switch_thread_rwlock_unlock(orig_session->bug_rwlock);
1148  }
1149 
1150  return x;
1151 }
1152 
1154 {
1155  switch_media_bug_t *bp;
1156  uint32_t x = 0, ok = SWITCH_TRUE, prune = 0;
1157 
1158  if (orig_session->bugs) {
1159  switch_thread_rwlock_rdlock(orig_session->bug_rwlock);
1160  for (bp = orig_session->bugs; bp; bp = bp->next) {
1161  if (!switch_test_flag(bp, SMBF_PRUNE) && !switch_test_flag(bp, SMBF_LOCK) && !strcmp(bp->function, "patch:video")) {
1162  if (bp->ready && frame->img && switch_test_flag(bp, SMBF_VIDEO_PATCH)) {
1163  bp->video_ping_frame = frame;
1164  if (bp->callback) {
1166  || (bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL))) {
1167  ok = SWITCH_FALSE;
1168  }
1169  }
1170  bp->video_ping_frame = NULL;
1171  }
1172 
1173  if (ok == SWITCH_FALSE) {
1175  prune++;
1176  } else x++;
1177  }
1178  }
1179  switch_thread_rwlock_unlock(orig_session->bug_rwlock);
1180  if (prune) {
1181  switch_core_media_bug_prune(orig_session);
1182  }
1183  }
1184 
1185  return x;
1186 }
1187 
1189  const char *function, switch_media_bug_exec_cb_t cb, void *user_data)
1190 {
1191  switch_media_bug_t *bp;
1192  int x = 0;
1193 
1194  switch_assert(cb);
1195 
1196  if (orig_session->bugs) {
1197  switch_thread_rwlock_wrlock(orig_session->bug_rwlock);
1198  for (bp = orig_session->bugs; bp; bp = bp->next) {
1199  if (!switch_test_flag(bp, SMBF_PRUNE) && !switch_test_flag(bp, SMBF_LOCK) && !strcmp(bp->function, function)) {
1200  cb(bp, user_data);
1201  x++;
1202  }
1203  }
1204  switch_thread_rwlock_unlock(orig_session->bug_rwlock);
1205  }
1206 
1208 }
1209 
1211 {
1212  switch_media_bug_t *bp;
1213 
1214  stream->write_function(stream, "<media-bugs>\n");
1215 
1216  if (session->bugs) {
1218  for (bp = session->bugs; bp; bp = bp->next) {
1219  int thread_locked = (bp->thread_id && bp->thread_id == switch_thread_self());
1220  stream->write_function(stream,
1221  " <media-bug>\n"
1222  " <function>%s</function>\n"
1223  " <target>%s</target>\n"
1224  " <thread-locked>%d</thread-locked>\n"
1225  " </media-bug>\n",
1226  bp->function, bp->target, thread_locked);
1227 
1228  }
1230  }
1231 
1232  stream->write_function(stream, "</media-bugs>\n");
1233 
1234  return SWITCH_STATUS_SUCCESS;
1235 }
1236 
1238 {
1239  switch_media_bug_t *bp, *last = NULL, *next = NULL;
1241  switch_media_bug_t *closed = NULL;
1242 
1244  if (session->bugs) {
1245  for (bp = session->bugs; bp; bp = next) {
1246  next = bp->next;
1247 
1248  if (!switch_test_flag(session, SSF_DESTROYABLE) &&
1249  ((bp->thread_id && bp->thread_id != switch_thread_self()) || switch_test_flag(bp, SMBF_LOCK))) {
1250  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "BUG is thread locked skipping.\n");
1251  last = bp;
1252  continue;
1253  }
1254 
1255  if (!zstr(function) && strcmp(bp->function, function)) {
1256  last = bp;
1257  continue;
1258  }
1259 
1260  if (last) {
1261  last->next = bp->next;
1262  } else {
1263  session->bugs = bp->next;
1264  }
1265 
1266  bp->next = closed;
1267  closed = bp;
1268 
1270  }
1271  status = SWITCH_STATUS_SUCCESS;
1272  }
1274 
1275 
1276  if (closed) {
1277  for (bp = closed; bp; bp = next) {
1278  next = bp->next;
1280  }
1281  }
1282 
1283  if (switch_core_codec_ready(&session->bug_codec)) {
1285  }
1286 
1287  return status;
1288 }
1289 
1291 {
1292  switch_media_bug_t *bp = *bug;
1293 
1294  if (bp) {
1295  if ((bp->thread_id && bp->thread_id != switch_thread_self()) || switch_test_flag(bp, SMBF_LOCK)) {
1297  return SWITCH_STATUS_FALSE;
1298  }
1299 
1300  if (bp->callback) {
1302  }
1303 
1306 
1309  }
1310 
1313  }
1314  }
1315 
1316  bp->ready = 0;
1317 
1318  if (bp->read_video_queue) {
1320  }
1321 
1322  if (bp->write_video_queue) {
1324  }
1325 
1328 
1329  if (destroy) {
1331  }
1332 
1333  return SWITCH_STATUS_SUCCESS;
1334  }
1335 
1336  return SWITCH_STATUS_FALSE;
1337 }
1338 
1340 {
1341  switch_media_bug_t *bp = NULL, *bp2 = NULL, *last = NULL;
1343  int tap_only = 0;
1344 
1346  return status;
1347  }
1348 
1350  if (session->bugs) {
1351  for (bp = session->bugs; bp; bp = bp->next) {
1352  if ((!bp->thread_id || bp->thread_id == switch_thread_self()) && bp->ready && bp == *bug) {
1353  if (last) {
1354  last->next = bp->next;
1355  } else {
1356  session->bugs = bp->next;
1357  }
1358  break;
1359  }
1360 
1361  last = bp;
1362  }
1363  }
1364 
1365  if (!session->bugs && switch_core_codec_ready(&session->bug_codec)) {
1367  }
1368 
1369  if (session->bugs) {
1370  for(bp2 = session->bugs; bp2; bp2 = bp2->next) {
1371  if (bp2->ready && !switch_test_flag(bp2, SMBF_TAP_NATIVE_READ) && !switch_test_flag(bp2, SMBF_TAP_NATIVE_WRITE)) {
1372  tap_only = 0;
1373  }
1374  }
1375  }
1376 
1377  if (tap_only) {
1379  } else {
1381  }
1382 
1384 
1385  if (bp) {
1387  }
1388 
1389  return status;
1390 }
1391 
1392 
1394 {
1395  switch_media_bug_t *bp = NULL, *last = NULL;
1396  int ttl = 0;
1397 
1398 
1399  top:
1400 
1402  if (session->bugs) {
1403  for (bp = session->bugs; bp; bp = bp->next) {
1405  if (last) {
1406  last->next = bp->next;
1407  } else {
1408  session->bugs = bp->next;
1409  }
1410  break;
1411  }
1412 
1413  last = bp;
1414  }
1415  }
1416 
1417  if (!session->bugs && switch_core_codec_ready(&session->bug_codec)) {
1419  }
1420 
1422 
1423  if (bp) {
1425  bp->thread_id = 0;
1427  ttl++;
1428  goto top;
1429  }
1430 
1431  return ttl;
1432 }
1433 
1434 
1436 {
1437  switch_media_bug_t *cur = NULL, *bp = NULL, *last = NULL, *closed = NULL, *next = NULL;
1438  int total = 0;
1439 
1441  if (session->bugs) {
1442  bp = session->bugs;
1443  while (bp) {
1444  cur = bp;
1445  bp = bp->next;
1446 
1447  if ((!cur->thread_id || cur->thread_id == switch_thread_self()) && cur->ready && cur->callback == callback) {
1448  if (last) {
1449  last->next = cur->next;
1450  } else {
1451  session->bugs = cur->next;
1452  }
1454  total++;
1455  }
1456 
1457  cur->next = closed;
1458  closed = cur;
1459 
1460  } else {
1461  last = cur;
1462  }
1463  }
1464  }
1466 
1467  if (closed) {
1468  for (bp = closed; bp; bp = next) {
1469  next = bp->next;
1471  }
1472  }
1473 
1474  if (!session->bugs && switch_core_codec_ready(&session->bug_codec)) {
1476  }
1477 
1478  return total ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
1479 }
1480 
1481 /* For Emacs:
1482  * Local Variables:
1483  * mode:c
1484  * indent-tabs-mode:t
1485  * tab-width:4
1486  * c-basic-offset:4
1487  * End:
1488  * For VIM:
1489  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
1490  */
switch_frame_t * write_replace_frame_out
switch_frame_t * switch_core_media_bug_get_video_ping_frame(switch_media_bug_t *bug)
#define switch_event_fire(event)
Fire an event filling in most of the arguements with obvious values.
Definition: switch_event.h:413
unsigned int switch_queue_size(switch_queue_t *queue)
Definition: switch_apr.c:1238
void switch_channel_set_flag_recursive(switch_channel_t *channel, switch_channel_flag_t flag)
switch_status_t switch_thread_rwlock_unlock(switch_thread_rwlock_t *rwlock)
Definition: switch_apr.c:286
switch_status_t switch_core_media_bug_read(switch_media_bug_t *bug, switch_frame_t *frame, switch_bool_t fill)
#define SWITCH_BUFFER_START_FRAMES
static switch_bool_t switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:519
switch_codec_implementation_t read_impl
#define SWITCH_CHANNEL_SESSION_LOG(x)
Image Descriptor.
Definition: switch_image.h:88
void switch_img_patch(switch_image_t *IMG, switch_image_t *img, int x, int y)
patch a small img to a big IMG at position x,y
switch_thread_rwlock_t * bug_rwlock
#define switch_set_flag(obj, flag)
Set a flag on an arbitrary object.
Definition: switch_utils.h:700
#define SWITCH_THREAD_FUNC
switch_thread_id_t thread_id
switch_status_t switch_core_timer_init(switch_timer_t *timer, const char *timer_name, int interval, int samples, switch_memory_pool_t *pool)
Request a timer handle using given time module.
switch_size_t switch_buffer_read(_In_ switch_buffer_t *buffer, _In_ void *data, _In_ switch_size_t datalen)
Read data from a switch_buffer_t up to the ammount of datalen if it is available. Remove read data fr...
switch_frame_t * read_replace_frame_in
void switch_img_free(switch_image_t **img)
Close an image descriptor.
switch_session_flag_t flags
switch_status_t switch_buffer_create_dynamic(_Out_ switch_buffer_t **buffer, _In_ switch_size_t blocksize, _In_ switch_size_t start_len, _In_ switch_size_t max_len)
Allocate a new dynamic switch_buffer.
switch_frame_t * switch_core_media_bug_get_native_read_frame(switch_media_bug_t *bug)
static int flush_video_queue(switch_queue_t *q, int min)
#define SWITCH_RECOMMENDED_BUFFER_SIZE
Definition: switch_types.h:590
uint32_t record_pre_buffer_count
void switch_channel_event_set_data(_In_ switch_channel_t *channel, _In_ switch_event_t *event)
Add information about a given channel to an event object.
switch_bool_t
Definition: switch_types.h:437
switch_bool_t(* switch_media_bug_callback_t)(switch_media_bug_t *, void *, switch_abc_type_t)
void switch_core_media_bug_set_media_params(switch_media_bug_t *bug, switch_mm_t *mm)
static void switch_core_media_bug_destroy(switch_media_bug_t **bug)
switch_codec_t * video_read_codec
switch_status_t switch_threadattr_stacksize_set(switch_threadattr_t *attr, switch_size_t stacksize)
Definition: switch_apr.c:683
switch_memory_pool_t * pool
void switch_core_media_bug_inuse(switch_media_bug_t *bug, switch_size_t *readp, switch_size_t *writep)
switch_status_t switch_event_add_header(switch_event_t *event, switch_stack_t stack, const char *header_name, const char *fmt,...) PRINTF_FUNCTION(4
Add a header to an event.
Representation of an event.
Definition: switch_event.h:80
switch_status_t switch_core_media_bug_set_pre_buffer_framecount(switch_media_bug_t *bug, uint32_t framecount)
void switch_media_bug_set_spy_fmt(switch_media_bug_t *bug, switch_vid_spy_fmt_t spy_fmt)
switch_queue_t * read_video_queue
#define SWITCH_RTP_MAX_BUF_LEN
Definition: switch_rtp.h:45
switch_status_t switch_queue_trypop(switch_queue_t *queue, void **data)
Definition: switch_apr.c:1264
switch_core_session_t * session
uint32_t switch_core_media_bug_count(switch_core_session_t *orig_session, const char *function)
#define switch_channel_media_ready(_channel)
uint32_t switch_core_media_bug_clear_flag(switch_media_bug_t *bug, uint32_t flag)
switch_buffer_t * raw_write_buffer
void switch_core_media_bug_pause(switch_core_session_t *session)
Pause a media bug on the session.
static void *SWITCH_THREAD_FUNC video_bug_thread(switch_thread_t *thread, void *obj)
switch_buffer_t * text_buffer
switch_status_t switch_core_codec_destroy(switch_codec_t *codec)
Destroy an initalized codec handle.
#define switch_calc_video_fps(fpsP, fps)
#define switch_core_session_get_name(_s)
Definition: switch_core.h:265
switch_status_t switch_core_media_bug_patch_spy_frame(switch_media_bug_t *bug, switch_image_t *img, switch_rw_t rw)
pack cur
Abstract handler to a timer module.
static switch_thread_t * thread
Definition: switch_log.c:486
switch_status_t switch_core_media_bug_enumerate(switch_core_session_t *session, switch_stream_handle_t *stream)
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
void switch_img_find_position(switch_img_position_t pos, int sw, int sh, int iw, int ih, int *xP, int *yP)
switch_codec_t * codec
Definition: switch_frame.h:56
switch_media_bug_callback_t callback
switch_image_t * switch_img_alloc(switch_image_t *img, switch_img_fmt_t fmt, unsigned int d_w, unsigned int d_h, unsigned int align)
Open a descriptor, allocating storage for the underlying image.
#define zstr(x)
Definition: switch_utils.h:314
const char * switch_core_media_bug_get_text(switch_media_bug_t *bug)
unsigned int d_w
Definition: switch_image.h:99
switch_core_session_t * switch_core_media_bug_get_session(switch_media_bug_t *bug)
switch_queue_t * write_video_queue
switch_mutex_t * read_mutex
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:313
switch_status_t switch_thread_rwlock_rdlock(switch_thread_rwlock_t *rwlock)
Definition: switch_apr.c:250
switch_status_t switch_core_session_get_read_impl(switch_core_session_t *session, switch_codec_implementation_t *impp)
#define switch_clear_flag(obj, flag)
Clear a flag on an arbitrary object while locked.
Definition: switch_utils.h:724
#define SWITCH_MUTEX_NESTED
Definition: switch_apr.h:318
switch_status_t switch_thread_rwlock_wrlock(switch_thread_rwlock_t *rwlock)
Definition: switch_apr.c:260
switch_status_t switch_core_media_bug_pop(switch_core_session_t *orig_session, const char *function, switch_media_bug_t **pop)
switch_size_t switch_buffer_toss(_In_ switch_buffer_t *buffer, _In_ switch_size_t datalen)
Remove data from the buffer.
switch_frame_t * switch_core_media_bug_get_read_replace_frame(switch_media_bug_t *bug)
switch_rw_t
Definition: switch_types.h:598
uint32_t buflen
Definition: switch_frame.h:70
switch_status_t switch_core_media_bug_transfer_callback(switch_core_session_t *orig_session, switch_core_session_t *new_session, switch_media_bug_callback_t callback, void *(*user_data_dup_func)(switch_core_session_t *, void *))
#define MAX_BUG_BUFFER
switch_byte_t switch_byte_t * buf
uint32_t switch_core_media_bug_prune(switch_core_session_t *session)
switch_channel_t * channel
uint32_t datalen
Definition: switch_frame.h:68
#define SWITCH_CORE_QUEUE_LEN
Definition: switch_types.h:593
uint32_t packetlen
Definition: switch_frame.h:62
switch_frame_flag_t flags
Definition: switch_frame.h:85
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:308
switch_status_t switch_core_media_bug_push_spy_frame(switch_media_bug_t *bug, switch_frame_t *frame, switch_rw_t rw)
uint32_t rate
Definition: switch_frame.h:74
#define switch_channel_get_variable(_c, _v)
#define SWITCH_THREAD_STACKSIZE
Definition: switch_types.h:584
switch_status_t switch_core_media_bug_remove_callback(switch_core_session_t *session, switch_media_bug_callback_t callback)
Remove media bug callback.
switch_thread_t * video_bug_thread
switch_status_t switch_core_media_bug_add(switch_core_session_t *session, const char *function, const char *target, switch_media_bug_callback_t callback, void *user_data, time_t stop_time, switch_media_bug_flag_t flags, switch_media_bug_t **new_bug)
switch_queue_t * spy_video_queue[2]
#define switch_zmalloc(ptr, len)
void switch_img_copy(switch_image_t *img, switch_image_t **new_img)
Copy image to a new image.
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:885
switch_status_t switch_img_fit(switch_image_t **srcP, int width, int height, switch_img_fit_t fit)
switch_frame_t * write_replace_frame_in
switch_image_t * spy_img[2]
switch_status_t switch_mutex_init(switch_mutex_t **lock, unsigned int flags, switch_memory_pool_t *pool)
Definition: switch_apr.c:293
switch_status_t switch_thread_join(switch_status_t *retval, switch_thread_t *thd)
Definition: switch_apr.c:1379
switch_media_bug_t * bugs
void switch_buffer_zero(_In_ switch_buffer_t *buffer)
Remove all data from the buffer.
An abstraction of a data frame.
Definition: switch_frame.h:54
uintptr_t switch_size_t
switch_frame_t * video_ping_frame
switch_frame_t * switch_core_media_bug_get_write_replace_frame(switch_media_bug_t *bug)
switch_image_t * switch_img_copy_rect(switch_image_t *img, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
Copy part of an image to a new image.
struct switch_media_bug * next
switch_vid_spy_fmt_t switch_media_bug_parse_spy_fmt(const char *name)
void switch_core_media_hard_mute(switch_core_session_t *session, switch_bool_t on)
switch_byte_t switch_byte_t uint32_t buflen
switch_status_t switch_img_scale(switch_image_t *src, switch_image_t **destP, int width, int height)
switch_status_t switch_core_session_get_write_impl(switch_core_session_t *session, switch_codec_implementation_t *impp)
void switch_color_set_rgb(switch_rgb_color_t *color, const char *color_str)
Set RGB color with a string.
switch_status_t switch_core_timer_destroy(switch_timer_t *timer)
Destroy an allocated timer.
uint32_t switch_core_media_bug_test_flag(switch_media_bug_t *bug, uint32_t flag)
void switch_core_media_bug_get_media_params(switch_media_bug_t *bug, switch_mm_t *mm)
#define SWITCH_SMAX
Definition: switch_utils.h:290
switch_codec_t bug_codec
switch_status_t switch_core_timer_next(switch_timer_t *timer)
Wait for one cycle on an existing timer.
switch_codec_implementation_t write_impl
switch_frame_t * native_write_frame
void switch_core_media_bug_set_write_replace_frame(switch_media_bug_t *bug, switch_frame_t *frame)
void * packet
Definition: switch_frame.h:60
switch_stream_handle_write_function_t write_function
switch_memory_pool_t * pool
switch_image_t * img
Definition: switch_frame.h:88
switch_status_t
Common return values.
const cJSON *const target
uint32_t switch_core_media_bug_patch_video(switch_core_session_t *orig_session, switch_frame_t *frame)
#define SWITCH_SMIN
Definition: switch_utils.h:291
void switch_core_media_bug_flush(switch_media_bug_t *bug)
switch_vid_spy_fmt_t
uint32_t record_frame_size
void switch_img_fill(switch_image_t *img, int x, int y, int w, int h, switch_rgb_color_t *color)
Fill image with color.
Main Library Header.
#define switch_event_create(event, id)
Create a new event assuming it will not be custom event and therefore hiding the unused parameters...
Definition: switch_event.h:384
#define SWITCH_DECLARE(type)
uint32_t samples
Definition: switch_frame.h:72
void switch_core_media_bug_resume(switch_core_session_t *session)
Resume a media bug on the session.
#define switch_channel_set_flag(_c, _f)
#define SWITCH_IMG_FMT_I420
Definition: switch_vpx.h:77
void switch_core_media_bug_set_read_demux_frame(switch_media_bug_t *bug, switch_frame_t *frame)
uint32_t channels
Definition: switch_frame.h:76
switch_status_t switch_core_media_bug_remove_all_function(switch_core_session_t *session, const char *function)
int16_t tmp[SWITCH_RECOMMENDED_BUFFER_SIZE]
switch_codec_implementation_t read_impl
void * switch_core_media_bug_get_user_data(switch_media_bug_t *bug)
time_t switch_epoch_time_now(time_t *t)
Get the current epoch time.
Definition: switch_time.c:322
#define switch_core_session_alloc(_session, _memory)
Allocate memory from a session&#39;s pool.
Definition: switch_core.h:696
switch_status_t switch_queue_push(switch_queue_t *queue, void *data)
Definition: switch_apr.c:1253
uint32_t switch_core_media_bug_set_flag(switch_media_bug_t *bug, uint32_t flag)
switch_status_t switch_core_media_bug_flush_all(switch_core_session_t *session)
void(* switch_media_bug_exec_cb_t)(switch_media_bug_t *bug, void *user_data)
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:693
void switch_channel_clear_flag_recursive(switch_channel_t *channel, switch_channel_flag_t flag)
static switch_bool_t switch_core_codec_ready(switch_codec_t *codec)
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
switch_status_t switch_threadattr_create(switch_threadattr_t **new_attr, switch_memory_pool_t *pool)
Definition: switch_apr.c:665
switch_status_t switch_thread_create(switch_thread_t **new_thread, switch_threadattr_t *attr, switch_thread_start_t func, void *data, switch_memory_pool_t *cont)
Definition: switch_apr.c:698
A table of settings and callbacks that define a paticular implementation of a codec.
#define switch_normalize_to_16bit(n)
Definition: switch_utils.h:292
uint32_t switch_media_bug_flag_t
switch_frame_t * switch_core_media_bug_get_native_write_frame(switch_media_bug_t *bug)
struct fspr_pool_t switch_memory_pool_t
const char *const name
Definition: switch_cJSON.h:250
switch_status_t switch_queue_create(switch_queue_t **queue, unsigned int queue_capacity, switch_memory_pool_t *pool)
Definition: switch_apr.c:1233
#define switch_core_session_strdup(_session, _todup)
Copy a string using memory allocation from a session&#39;s pool.
Definition: switch_core.h:719
switch_thread_id_t switch_thread_self(void)
Definition: switch_apr.c:102
switch_status_t switch_core_media_bug_remove(switch_core_session_t *session, switch_media_bug_t **bug)
uint8_t data[SWITCH_RECOMMENDED_BUFFER_SIZE]
switch_vid_spy_fmt_t spy_fmt
unsigned int d_h
Definition: switch_image.h:100
switch_status_t switch_core_media_bug_exec_all(switch_core_session_t *orig_session, const char *function, switch_media_bug_exec_cb_t cb, void *user_data)
void switch_core_media_bug_set_read_replace_frame(switch_media_bug_t *bug, switch_frame_t *frame)
void switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Clear given flag(s) from a channel.
switch_buffer_t * raw_read_buffer
#define switch_assert(expr)
struct fspr_thread_t switch_thread_t
Definition: switch_apr.h:941
switch_frame_t * read_replace_frame_out
switch_status_t switch_core_media_bug_close(switch_media_bug_t **bug, switch_bool_t destroy)
switch_mutex_t * write_mutex
#define switch_channel_pre_answer(channel)
Indicate progress on a channel to attempt early media.
switch_frame_t * read_demux_frame
#define SWITCH_BUFFER_BLOCK_FRAMES
switch_size_t switch_buffer_inuse(_In_ switch_buffer_t *buffer)
Get the in use amount of a switch_buffer_t.
void switch_buffer_destroy(switch_buffer_t **buffer)
Destroy the buffer.
char * switch_channel_get_name(switch_channel_t *channel)
Retrieve the name of a given channel.
memset(buf, 0, buflen)
switch_memory_pool_t * switch_core_session_get_pool(_In_ switch_core_session_t *session)
Retrieve the memory pool from a session.
switch_frame_t * native_read_frame
uint32_t record_pre_buffer_max