FreeSWITCH API Documentation  1.7.0
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 
42  if (bug->raw_read_buffer) {
44  }
45 
46  if (bug->raw_write_buffer) {
48  }
49 
51  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Media-Bug-Function", "%s", bug->function);
52  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Media-Bug-Target", "%s", bug->target);
53  if (bug->session) switch_channel_event_set_data(bug->session->channel, event);
54  switch_event_fire(&event);
55  }
56 }
57 
59 {
60  switch_channel_set_flag(session->channel, CF_PAUSE_BUGS);
61 }
62 
64 {
65  switch_channel_clear_flag(session->channel, CF_PAUSE_BUGS);
66 }
67 
69 {
70  return switch_test_flag(bug, flag);
71 }
72 
74 {
75  if ((flag & SMBF_PRUNE)) {
77  }
78  return switch_set_flag(bug, flag);
79 }
80 
82 {
83  return switch_clear_flag(bug, flag);
84 }
85 
87 {
88  return bug->session;
89 }
90 
92 {
93  return bug->video_ping_frame;
94 }
95 
97 {
98  return bug->write_replace_frame_in;
99 }
100 
102 {
103  bug->write_replace_frame_out = frame;
104 }
105 
107 {
108  return bug->read_replace_frame_in;
109 }
110 
112 {
113  return bug->native_read_frame;
114 }
115 
117 {
118  return bug->native_write_frame;
119 }
120 
122 {
123  bug->read_replace_frame_out = frame;
124 }
125 
127 {
128  bug->read_demux_frame = frame;
129 }
130 
132 {
133  return bug->user_data;
134 }
135 
137 {
138 
139  bug->record_pre_buffer_count = 0;
140 
141  if (bug->raw_read_buffer) {
142  switch_mutex_lock(bug->read_mutex);
143  switch_buffer_zero(bug->raw_read_buffer);
144  switch_mutex_unlock(bug->read_mutex);
145  }
146 
147  if (bug->raw_write_buffer) {
148  switch_mutex_lock(bug->write_mutex);
149  switch_buffer_zero(bug->raw_write_buffer);
150  switch_mutex_unlock(bug->write_mutex);
151  }
152 
153  bug->record_frame_size = 0;
154  bug->record_pre_buffer_count = 0;
155 }
156 
158 {
160  switch_mutex_lock(bug->read_mutex);
161  *readp = bug->raw_read_buffer ? switch_buffer_inuse(bug->raw_read_buffer) : 0;
162  switch_mutex_unlock(bug->read_mutex);
163  } else {
164  *readp = 0;
165  }
166 
168  switch_mutex_lock(bug->write_mutex);
169  *writep = bug->raw_write_buffer ? switch_buffer_inuse(bug->raw_write_buffer) : 0;
170  switch_mutex_unlock(bug->write_mutex);
171  } else {
172  *writep = 0;
173  }
174 }
175 
177 {
178  bug->record_pre_buffer_max = framecount;
179 
180  return SWITCH_STATUS_SUCCESS;
181 }
182 
184 {
185  switch_size_t bytes = 0, datalen = 0;
186  int16_t *dp, *fp;
187  uint32_t x;
188  size_t rlen = 0;
189  size_t wlen = 0;
190  uint32_t blen;
191  switch_codec_implementation_t read_impl = { 0 };
192  int16_t *tp;
193  switch_size_t do_read = 0, do_write = 0, has_read = 0, has_write = 0, fill_read = 0, fill_write = 0;
194 
195  switch_core_session_get_read_impl(bug->session, &read_impl);
196 
197  bytes = read_impl.decoded_bytes_per_packet;
198 
199  if (frame->buflen < bytes) {
201  switch_channel_get_name(bug->session->channel));
202  return SWITCH_STATUS_FALSE;
203  }
204 
205  if ((!bug->raw_read_buffer && (!bug->raw_write_buffer || !switch_test_flag(bug, SMBF_WRITE_STREAM)))) {
207  "%s Buffer Error (raw_read_buffer=%p, raw_write_buffer=%p, read=%s, write=%s)\n",
208  switch_channel_get_name(bug->session->channel),
209  (void *)bug->raw_read_buffer, (void *)bug->raw_write_buffer,
210  switch_test_flag(bug, SMBF_READ_STREAM) ? "yes" : "no",
211  switch_test_flag(bug, SMBF_WRITE_STREAM) ? "yes" : "no");
212  return SWITCH_STATUS_FALSE;
213  }
214 
215  frame->flags = 0;
216  frame->datalen = 0;
217 
219  has_read = 1;
220  switch_mutex_lock(bug->read_mutex);
221  do_read = switch_buffer_inuse(bug->raw_read_buffer);
222  switch_mutex_unlock(bug->read_mutex);
223  }
224 
226  has_write = 1;
227  switch_mutex_lock(bug->write_mutex);
228  do_write = switch_buffer_inuse(bug->raw_write_buffer);
229  switch_mutex_unlock(bug->write_mutex);
230  }
231 
232 
233  if (bug->record_frame_size && bug->record_pre_buffer_max && (do_read || do_write) && bug->record_pre_buffer_count < bug->record_pre_buffer_max) {
234  bug->record_pre_buffer_count++;
235  return SWITCH_STATUS_FALSE;
236  } else {
237  uint32_t frame_size;
238  switch_codec_implementation_t read_impl = { 0 };
239 
240  switch_core_session_get_read_impl(bug->session, &read_impl);
241  frame_size = read_impl.decoded_bytes_per_packet;
242  bug->record_frame_size = frame_size;
243  }
244 
245  if (bug->record_frame_size && do_write > do_read && do_write > (bug->record_frame_size * 2)) {
246  switch_mutex_lock(bug->write_mutex);
247  switch_buffer_toss(bug->raw_write_buffer, bug->record_frame_size);
248  do_write = switch_buffer_inuse(bug->raw_write_buffer);
249  switch_mutex_unlock(bug->write_mutex);
250  }
251 
252 
253 
254  if ((has_read && !do_read)) {
255  fill_read = 1;
256  }
257 
258  if ((has_write && !do_write)) {
259  fill_write = 1;
260  }
261 
262 
263  if (bug->record_frame_size) {
264  if ((do_read && do_read < bug->record_frame_size) || (do_write && do_write < bug->record_frame_size)) {
265  return SWITCH_STATUS_FALSE;
266  }
267 
268  if (do_read && do_read > bug->record_frame_size) {
269  do_read = bug->record_frame_size;
270  }
271 
272  if (do_write && do_write > bug->record_frame_size) {
273  do_write = bug->record_frame_size;
274  }
275  }
276 
277  if ((fill_read && fill_write) || (fill && (fill_read || fill_write))) {
278  return SWITCH_STATUS_FALSE;
279  }
280 
281  if (do_read && do_read > SWITCH_RECOMMENDED_BUFFER_SIZE) {
282  do_read = 1280;
283  }
284 
285  if (do_write && do_write > SWITCH_RECOMMENDED_BUFFER_SIZE) {
286  do_write = 1280;
287  }
288 
289  if (do_read) {
290  switch_mutex_lock(bug->read_mutex);
291  frame->datalen = (uint32_t) switch_buffer_read(bug->raw_read_buffer, frame->data, do_read);
292  if (frame->datalen != do_read) {
295  switch_mutex_unlock(bug->read_mutex);
296  return SWITCH_STATUS_FALSE;
297  }
298  switch_mutex_unlock(bug->read_mutex);
299  } else if (fill_read) {
300  frame->datalen = (uint32_t)bytes;
301  memset(frame->data, 255, frame->datalen);
302  }
303 
304  if (do_write) {
305  switch_assert(bug->raw_write_buffer);
306  switch_mutex_lock(bug->write_mutex);
307  datalen = (uint32_t) switch_buffer_read(bug->raw_write_buffer, bug->data, do_write);
308  if (datalen != do_write) {
311  switch_mutex_unlock(bug->write_mutex);
312  return SWITCH_STATUS_FALSE;
313  }
314  switch_mutex_unlock(bug->write_mutex);
315  } else if (fill_write) {
316  datalen = bytes;
317  memset(bug->data, 255, datalen);
318  }
319 
320  tp = bug->tmp;
321  dp = (int16_t *) bug->data;
322  fp = (int16_t *) frame->data;
323  rlen = frame->datalen / 2;
324  wlen = datalen / 2;
325  blen = (uint32_t)(bytes / 2);
326 
327  if (switch_test_flag(bug, SMBF_STEREO)) {
328  int16_t *left, *right;
329  size_t left_len, right_len;
331  left = dp; /* write stream */
332  left_len = wlen;
333  right = fp; /* read stream */
334  right_len = rlen;
335  } else {
336  left = fp; /* read stream */
337  left_len = rlen;
338  right = dp; /* write stream */
339  right_len = wlen;
340  }
341  for (x = 0; x < blen; x++) {
342  if (x < left_len) {
343  *(tp++) = *(left + x);
344  } else {
345  *(tp++) = 0;
346  }
347  if (x < right_len) {
348  *(tp++) = *(right + x);
349  } else {
350  *(tp++) = 0;
351  }
352  }
353  memcpy(frame->data, bug->tmp, bytes * 2);
354  } else {
355  for (x = 0; x < blen; x++) {
356  int32_t w = 0, r = 0, z = 0;
357 
358  if (x < rlen) {
359  r = (int32_t) * (fp + x);
360  }
361 
362  if (x < wlen) {
363  w = (int32_t) * (dp + x);
364  }
365 
366  z = w + r;
367 
368  if (z > SWITCH_SMAX || z < SWITCH_SMIN) {
369  if (r) z += (r/2);
370  if (w) z += (w/2);
371  }
372 
374 
375  *(fp + x) = (int16_t) z;
376  }
377  }
378 
379  frame->datalen = (uint32_t)bytes;
380  frame->samples = (uint32_t)(bytes / sizeof(int16_t) / read_impl.number_of_channels);
381  frame->rate = read_impl.actual_samples_per_second;
382  frame->codec = NULL;
383 
384  if (switch_test_flag(bug, SMBF_STEREO)) {
385  frame->datalen *= 2;
386  frame->channels = 2;
387  } else {
388  frame->channels = read_impl.number_of_channels;
389  }
390 
391  return SWITCH_STATUS_SUCCESS;
392 }
393 
395 {
396  if (zstr(name)) goto end;
397 
398  if (!strcasecmp(name, "dual-crop")) {
399  return SPY_DUAL_CROP;
400  }
401 
402  if (!strcasecmp(name, "lower-right-large")) {
403  return SPY_LOWER_RIGHT_LARGE;
404  }
405 
406  end:
407 
408  return SPY_LOWER_RIGHT_SMALL;
409 }
410 
412 {
413  bug->spy_fmt = spy_fmt;
414 }
415 
417 {
418  switch_queue_t *spy_q = NULL;
419  int w = 0, h = 0;
420  switch_status_t status;
421  void *pop;
422  int i;
423 
424  for (i = 0; i < 2; i++) {
425  if (!bug->spy_video_queue[i]) {
426  switch_queue_create(&bug->spy_video_queue[i], SWITCH_CORE_QUEUE_LEN, switch_core_session_get_pool(bug->session));
427  }
428  }
429 
430  spy_q = bug->spy_video_queue[rw];
431 
432  while(switch_queue_size(spy_q) > 0) {
433  if ((status = switch_queue_trypop(spy_q, &pop)) == SWITCH_STATUS_SUCCESS) {
434  switch_img_free(&bug->spy_img[rw]);
435  if (!(bug->spy_img[rw] = (switch_image_t *) pop)) {
436  break;
437  }
438  }
439  }
440 
441  w = img->d_w;
442  h = img->d_h;
443 
444  if (bug->spy_img[rw]) {
445 
446  switch (bug->spy_fmt) {
447  case SPY_DUAL_CROP:
448  {
449  switch_image_t *spy_tmp = NULL;
450  switch_image_t *img_tmp = NULL;
451  switch_image_t *img_dup = NULL;
452  int x = 0, y = 0;
453  float aspect169 = (float)1920 / 1080;
454  switch_rgb_color_t bgcolor = { 0 };
455 
456  if ((float)w/h == aspect169) {
457  if ((float)bug->spy_img[rw]->d_w / bug->spy_img[rw]->d_h == aspect169) {
458  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);
459 
460  } else {
461  switch_img_copy(bug->spy_img[rw], &spy_tmp);
462  }
463  } else {
464  if ((float)bug->spy_img[rw]->d_w / bug->spy_img[rw]->d_h == aspect169) {
465  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);
466  } else {
467  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);
468  }
469  }
470 
471  switch_img_copy(img, &img_dup);
472  img_tmp = switch_img_copy_rect(img_dup, w / 4, 0, w / 2, h);
473 
474  switch_img_fit(&spy_tmp, w / 2, h, SWITCH_FIT_SIZE);
475  switch_img_fit(&img_tmp, w / 2, h, SWITCH_FIT_SIZE);
476 
477  switch_color_set_rgb(&bgcolor, "#000000");
478  switch_img_fill(img, 0, 0, img->d_w, img->d_h, &bgcolor);
479 
480  switch_img_find_position(POS_CENTER_MID, w / 2, h, img_tmp->d_w, img_tmp->d_h, &x, &y);
481  switch_img_patch(img, img_tmp, x, y);
482 
483  switch_img_find_position(POS_CENTER_MID, w / 2, h, spy_tmp->d_w, spy_tmp->d_h, &x, &y);
484  switch_img_patch(img, spy_tmp, x + w / 2, y);
485 
486 
487  switch_img_free(&img_tmp);
488  switch_img_free(&img_dup);
489  switch_img_free(&spy_tmp);
490  }
491  break;
494  default:
495  {
496  float scaler = 0.125f;
497  int spyw, spyh;
498 
499  if (bug->spy_fmt == SPY_LOWER_RIGHT_LARGE) {
500  scaler = 0.25f;
501  }
502 
503  spyw = (int) (float)w * scaler;
504  spyh = (int) (float)h * scaler;
505 
506  if (bug->spy_img[rw]->d_w != spyw || bug->spy_img[rw]->d_h != spyh) {
507  switch_image_t *tmp_img = NULL;
508 
509  switch_img_scale(bug->spy_img[rw], &tmp_img, spyw, spyh);
510  switch_img_free(&bug->spy_img[rw]);
511  bug->spy_img[rw] = tmp_img;
512  }
513 
514  switch_img_patch(img, bug->spy_img[rw], w - spyw, h - spyh);
515  }
516  break;
517  }
518 
519  return SWITCH_STATUS_SUCCESS;
520  }
521 
522  return SWITCH_STATUS_FALSE;
523 }
524 
526 {
527  switch_media_bug_t *bug = (switch_media_bug_t *) obj;
528  switch_queue_t *main_q = NULL, *other_q = NULL;
529  switch_image_t *IMG = NULL, *img = NULL, *other_img = NULL;
530  void *pop;
531  uint8_t *buf;
533  switch_frame_t frame = { 0 };
534 
535  buf = switch_core_session_alloc(bug->session, buflen);
536  frame.packet = buf;
537  frame.data = buf + 12;
538  frame.packetlen = buflen;
539  frame.buflen = buflen - 12;
540  frame.flags = SFF_RAW_RTP;
541 
543  main_q = bug->read_video_queue;
544 
546  other_q = bug->write_video_queue;
547  }
548  } else if (switch_test_flag(bug, SMBF_WRITE_VIDEO_STREAM)) {
549  main_q = bug->write_video_queue;
550  } else {
551  return NULL;
552  }
553 
554  while (bug->ready) {
555  switch_status_t status;
556  int w = 0, h = 0, ok = 1;
557 
558 
559  if ((status = switch_queue_pop(main_q, &pop)) == SWITCH_STATUS_SUCCESS) {
560  switch_img_free(&img);
561 
562  if (!pop) {
563  goto end;
564  }
565 
566  img = (switch_image_t *) pop;
567 
568  w = img->d_w;
569  h = img->d_h;
570 
571  if (other_q) {
572  while(switch_queue_size(other_q) > 0) {
573  if ((status = switch_queue_trypop(other_q, &pop)) == SWITCH_STATUS_SUCCESS) {
574  switch_img_free(&other_img);
575  if (!(other_img = (switch_image_t *) pop)) {
576  goto end;
577  }
578  }
579  }
580 
581  if (other_img) {
582  if (other_img->d_w != w || other_img->d_h != h) {
583  switch_image_t *tmp_img = NULL;
584 
585  switch_img_scale(other_img, &tmp_img, w, h);
586  switch_img_free(&other_img);
587  other_img = tmp_img;
588  }
589  }
590 
591  w *= 2;
592 
593  if (!IMG || IMG->d_h != h || IMG->d_w != w) {
594  switch_img_free(&IMG);
595  IMG = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, w, h, 1);
596  }
597 
598  switch_img_patch(IMG, img, 0, 0);
599 
600  if (other_img) {
601  switch_img_patch(IMG, other_img, w / 2, 0);
602  }
603  }
604 
606  frame.img = other_q ? IMG : img;
607  bug->video_ping_frame = &frame;
608  if (bug->callback) {
610  || (bug->stop_time && bug->stop_time <= switch_epoch_time_now(NULL))) {
611  ok = SWITCH_FALSE;
612  }
613  }
614  bug->video_ping_frame = NULL;
616 
617  if (!ok) {
619  goto end;
620  }
621  }
622  }
623 
624  end:
625 
626  switch_img_free(&IMG);
627  switch_img_free(&img);
628  switch_img_free(&other_img);
629 
630  while (switch_queue_trypop(main_q, &pop) == SWITCH_STATUS_SUCCESS && pop) {
631  img = (switch_image_t *) pop;
632  switch_img_free(&img);
633  }
634 
635  if (other_q) {
636  while (switch_queue_trypop(other_q, &pop) == SWITCH_STATUS_SUCCESS && pop) {
637  img = (switch_image_t *) pop;
638  switch_img_free(&img);
639  }
640  }
641 
642  return NULL;
643 }
644 
646 {
647 
648  switch_assert(bug);
649  switch_assert(frame);
650 
651  if (bug->spy_video_queue[rw] && frame->img) {
652  switch_image_t *img = NULL;
653 
654  switch_img_copy(frame->img, &img);
655 
656  if (img) {
657  switch_queue_push(bug->spy_video_queue[rw], img);
658  return SWITCH_STATUS_SUCCESS;
659  }
660  }
661 
662  return SWITCH_STATUS_FALSE;
663 }
664 
665 #define MAX_BUG_BUFFER 1024 * 512
667  const char *function,
668  const char *target,
670  void *user_data, time_t stop_time,
672  switch_media_bug_t **new_bug)
673 {
674  switch_media_bug_t *bug, *bp;
675  switch_size_t bytes;
676  switch_event_t *event;
677  int tap_only = 1, punt = 0;
678 
679  const char *p;
680 
681  if (!zstr(function)) {
682  if ((flags & SMBF_ONE_ONLY)) {
683  switch_thread_rwlock_wrlock(session->bug_rwlock);
684  for (bp = session->bugs; bp; bp = bp->next) {
685  if (!zstr(bp->function) && !strcasecmp(function, bp->function)) {
686  punt = 1;
687  break;
688  }
689  }
690  switch_thread_rwlock_unlock(session->bug_rwlock);
691  }
692  }
693 
694  if (punt) {
695  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Only one bug of this type allowed!\n");
696  return SWITCH_STATUS_GENERR;
697  }
698 
699 
700  if (!switch_channel_media_ready(session->channel)) {
701  if (switch_channel_pre_answer(session->channel) != SWITCH_STATUS_SUCCESS) {
702  return SWITCH_STATUS_FALSE;
703  }
704  }
705 
706 
707 
708  *new_bug = NULL;
709 
710 
711  if ((p = switch_channel_get_variable(session->channel, "media_bug_answer_req")) && switch_true(p)) {
712  flags |= SMBF_ANSWER_REQ;
713  }
714 #if 0
715  if (flags & SMBF_WRITE_REPLACE) {
716  switch_thread_rwlock_wrlock(session->bug_rwlock);
717  for (bp = session->bugs; bp; bp = bp->next) {
718  if (switch_test_flag(bp, SMBF_WRITE_REPLACE)) {
719  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Only one bug of this type allowed!\n");
720  switch_thread_rwlock_unlock(session->bug_rwlock);
721  return SWITCH_STATUS_GENERR;
722  }
723  }
724  switch_thread_rwlock_unlock(session->bug_rwlock);
725  }
726 
727  if (flags & SMBF_READ_REPLACE) {
728  switch_thread_rwlock_wrlock(session->bug_rwlock);
729  for (bp = session->bugs; bp; bp = bp->next) {
730  if (switch_test_flag(bp, SMBF_READ_REPLACE)) {
731  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Only one bug of this type allowed!\n");
732  switch_thread_rwlock_unlock(session->bug_rwlock);
733  return SWITCH_STATUS_GENERR;
734  }
735  }
736  switch_thread_rwlock_unlock(session->bug_rwlock);
737  }
738 #endif
739 
740  if (!(bug = switch_core_session_alloc(session, sizeof(*bug)))) {
741  return SWITCH_STATUS_MEMERR;
742  }
743 
744  bug->callback = callback;
745  bug->user_data = user_data;
746  bug->session = session;
747  bug->flags = flags;
748  bug->function = "N/A";
749  bug->target = "N/A";
750 
753 
754  if (function) {
755  bug->function = switch_core_session_strdup(session, function);
756  }
757 
758  if (target) {
759  bug->target = switch_core_session_strdup(session, target);
760  }
761 
762  bug->stop_time = stop_time;
763  bytes = bug->read_impl.decoded_bytes_per_packet;
764 
765  if (!bug->flags) {
767  }
768 
771  switch_mutex_init(&bug->read_mutex, SWITCH_MUTEX_NESTED, session->pool);
772  }
773 
775 
778  switch_mutex_init(&bug->write_mutex, SWITCH_MUTEX_NESTED, session->pool);
779  }
780 
781  if ((bug->flags & SMBF_THREAD_LOCK)) {
782  bug->thread_id = switch_thread_self();
783  }
784 
787  }
788 
792  }
793 
796 
799  }
800 
803  }
804  }
805 
806 
807  if (bug->callback) {
808  switch_bool_t result = bug->callback(bug, bug->user_data, SWITCH_ABC_TYPE_INIT);
809  if (result == SWITCH_FALSE) {
811  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error attaching BUG to %s\n",
812  switch_channel_get_name(session->channel));
813  return SWITCH_STATUS_GENERR;
814  }
815  }
816 
817  bug->ready = 1;
818 
820  switch_threadattr_t *thd_attr = NULL;
822  switch_threadattr_create(&thd_attr, pool);
824  switch_thread_create(&bug->video_bug_thread, thd_attr, video_bug_thread, bug, pool);
825 
826  }
827 
828  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Attaching BUG to %s\n", switch_channel_get_name(session->channel));
829  switch_thread_rwlock_wrlock(session->bug_rwlock);
830  bug->next = session->bugs;
831  session->bugs = bug;
832 
833  for(bp = session->bugs; bp; bp = bp->next) {
835  tap_only = 0;
836  }
837  }
838 
839  switch_thread_rwlock_unlock(session->bug_rwlock);
840  *new_bug = bug;
841 
842  if (tap_only) {
844  } else {
846  }
847 
849  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Media-Bug-Function", "%s", bug->function);
850  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Media-Bug-Target", "%s", bug->target);
851  switch_channel_event_set_data(session->channel, event);
852  switch_event_fire(&event);
853  }
854 
856 
857  return SWITCH_STATUS_SUCCESS;
858 }
859 
860 
862 {
863  switch_media_bug_t *bp;
864 
865  if (session->bugs) {
866  switch_thread_rwlock_wrlock(session->bug_rwlock);
867  for (bp = session->bugs; bp; bp = bp->next) {
869  }
870  switch_thread_rwlock_unlock(session->bug_rwlock);
871  return SWITCH_STATUS_SUCCESS;
872  }
873 
874  return SWITCH_STATUS_FALSE;
875 }
876 
878 {
879  switch_media_bug_t *bp;
880  char *list[100] = { 0 };
881  int stop_times[100] = { 0 };
882  int i = 0, x = 0;
883 
884  if (orig_session->bugs) {
885  switch_channel_t *new_channel = switch_core_session_get_channel(new_session);
886  switch_channel_t *orig_channel = switch_core_session_get_channel(orig_session);
887  const char *save_append = switch_channel_get_variable(new_channel, "record_append");
888  const char *save_stereo = switch_channel_get_variable(new_channel, "record_stereo");
889  const char *orig_stereo = switch_channel_get_variable(orig_channel, "record_stereo");
890  const char *new_stereo = orig_stereo;
891 
892  switch_thread_rwlock_wrlock(orig_session->bug_rwlock);
893  switch_channel_set_variable(new_channel, "RECORD_MIN_SEC", "0");
894  switch_channel_set_variable(new_channel, "record_append", "true");
895  switch_channel_set_variable(new_channel, "record_stereo", new_stereo);
896 
897  for (bp = orig_session->bugs; bp; bp = bp->next) {
898  if (!strcmp(bp->function, "session_record")) {
899  list[x] = switch_core_session_strdup(new_session, bp->target);
900  if (bp->stop_time > 0) {
901  stop_times[x] = (int)(bp->stop_time - switch_epoch_time_now(NULL));
902  }
903  x++;
904  }
905  }
906 
907  switch_thread_rwlock_unlock(orig_session->bug_rwlock);
908 
909  for(i = 0; i < x; i++) {
910  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(orig_session), SWITCH_LOG_DEBUG, "Transfering %s from %s to %s\n", list[i],
911  switch_core_session_get_name(orig_session), switch_core_session_get_name(new_session));
912  switch_ivr_stop_record_session(orig_session, list[i]);
913  switch_ivr_record_session(new_session, list[i], stop_times[i], NULL);
914  }
915 
916  switch_channel_set_variable(new_channel, "record_append", save_append);
917  switch_channel_set_variable(new_channel, "record_stereo", save_stereo);
918 
919  }
920 
922 }
923 
924 
926  switch_media_bug_callback_t callback, void * (*user_data_dup_func) (switch_core_session_t *, void *))
927 {
928  switch_media_bug_t *new_bug = NULL, *cur = NULL, *bp = NULL, *last = NULL;
929  int total = 0;
930 
931  switch_thread_rwlock_wrlock(orig_session->bug_rwlock);
932  bp = orig_session->bugs;
933  while (bp) {
934  cur = bp;
935  bp = bp->next;
936 
937  if (cur->callback == callback) {
938  if (last) {
939  last->next = cur->next;
940  } else {
941  orig_session->bugs = cur->next;
942  }
943 
944  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(orig_session), SWITCH_LOG_DEBUG, "Transfering %s from %s to %s\n", cur->target,
945  switch_core_session_get_name(orig_session), switch_core_session_get_name(new_session));
946 
947  switch_core_media_bug_add(new_session, cur->function, cur->target, cur->callback,
948  user_data_dup_func(new_session, cur->user_data),
949  cur->stop_time, cur->flags, &new_bug);
951  total++;
952  } else {
953  last = cur;
954  }
955  }
956 
957  if (!orig_session->bugs && switch_core_codec_ready(&orig_session->bug_codec)) {
958  switch_core_codec_destroy(&orig_session->bug_codec);
959  }
960 
961  switch_thread_rwlock_unlock(orig_session->bug_rwlock);
962 
963 
965 }
966 
967 
969 {
970  switch_media_bug_t *bp;
971 
972  if (orig_session->bugs) {
973  switch_thread_rwlock_wrlock(orig_session->bug_rwlock);
974  for (bp = orig_session->bugs; bp; bp = bp->next) {
975  if (!strcmp(bp->function, function)) {
977  break;
978  }
979  }
980  switch_thread_rwlock_unlock(orig_session->bug_rwlock);
981 
982  if (bp) {
983  *pop = bp;
984  return SWITCH_STATUS_SUCCESS;
985  } else {
986  *pop = NULL;
987  }
988  }
989 
990  return SWITCH_STATUS_FALSE;
991 }
992 
993 
994 SWITCH_DECLARE(uint32_t) switch_core_media_bug_count(switch_core_session_t *orig_session, const char *function)
995 {
996  switch_media_bug_t *bp;
997  uint32_t x = 0;
998 
999  if (orig_session->bugs) {
1000  switch_thread_rwlock_rdlock(orig_session->bug_rwlock);
1001  for (bp = orig_session->bugs; bp; bp = bp->next) {
1002  if (!switch_test_flag(bp, SMBF_PRUNE) && !switch_test_flag(bp, SMBF_LOCK) && !strcmp(bp->function, function)) {
1003  x++;
1004  }
1005  }
1006  switch_thread_rwlock_unlock(orig_session->bug_rwlock);
1007  }
1008 
1009  return x;
1010 }
1011 
1013 {
1014  switch_media_bug_t *bp;
1015  uint32_t x = 0, ok = SWITCH_TRUE, prune = 0;
1016 
1017  if (orig_session->bugs) {
1018  switch_thread_rwlock_rdlock(orig_session->bug_rwlock);
1019  for (bp = orig_session->bugs; bp; bp = bp->next) {
1020  if (!switch_test_flag(bp, SMBF_PRUNE) && !switch_test_flag(bp, SMBF_LOCK) && !strcmp(bp->function, "patch:video")) {
1021  if (bp->ready && frame->img && switch_test_flag(bp, SMBF_VIDEO_PATCH)) {
1022  bp->video_ping_frame = frame;
1023  if (bp->callback) {
1025  || (bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL))) {
1026  ok = SWITCH_FALSE;
1027  }
1028  }
1029  bp->video_ping_frame = NULL;
1030  }
1031 
1032  if (ok == SWITCH_FALSE) {
1034  prune++;
1035  } else x++;
1036  }
1037  }
1038  switch_thread_rwlock_unlock(orig_session->bug_rwlock);
1039  if (prune) {
1040  switch_core_media_bug_prune(orig_session);
1041  }
1042  }
1043 
1044  return x;
1045 }
1046 
1048  const char *function, switch_media_bug_exec_cb_t cb, void *user_data)
1049 {
1050  switch_media_bug_t *bp;
1051  int x = 0;
1052 
1053  switch_assert(cb);
1054 
1055  if (orig_session->bugs) {
1056  switch_thread_rwlock_wrlock(orig_session->bug_rwlock);
1057  for (bp = orig_session->bugs; bp; bp = bp->next) {
1058  if (!switch_test_flag(bp, SMBF_PRUNE) && !switch_test_flag(bp, SMBF_LOCK) && !strcmp(bp->function, function)) {
1059  cb(bp, user_data);
1060  x++;
1061  }
1062  }
1063  switch_thread_rwlock_unlock(orig_session->bug_rwlock);
1064  }
1065 
1067 }
1068 
1070 {
1071  switch_media_bug_t *bp;
1072 
1073  stream->write_function(stream, "<media-bugs>\n");
1074 
1075  if (session->bugs) {
1076  switch_thread_rwlock_rdlock(session->bug_rwlock);
1077  for (bp = session->bugs; bp; bp = bp->next) {
1078  int thread_locked = (bp->thread_id && bp->thread_id == switch_thread_self());
1079  stream->write_function(stream,
1080  " <media-bug>\n"
1081  " <function>%s</function>\n"
1082  " <target>%s</target>\n"
1083  " <thread-locked>%d</thread-locked>\n"
1084  " </media-bug>\n",
1085  bp->function, bp->target, thread_locked);
1086 
1087  }
1088  switch_thread_rwlock_unlock(session->bug_rwlock);
1089  }
1090 
1091  stream->write_function(stream, "</media-bugs>\n");
1092 
1093  return SWITCH_STATUS_SUCCESS;
1094 }
1095 
1097 {
1098  switch_media_bug_t *bp, *last = NULL;
1100 
1101  if (session->bugs) {
1102  switch_thread_rwlock_wrlock(session->bug_rwlock);
1103  for (bp = session->bugs; bp; bp = bp->next) {
1104  if (!switch_test_flag(session, SSF_DESTROYABLE) &&
1105  ((bp->thread_id && bp->thread_id != switch_thread_self()) || switch_test_flag(bp, SMBF_LOCK))) {
1106  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "BUG is thread locked skipping.\n");
1107  last = bp;
1108  continue;
1109  }
1110 
1111  if (!zstr(function) && strcmp(bp->function, function)) {
1112  last = bp;
1113  continue;
1114  }
1115 
1116  if (bp->callback) {
1118  }
1120  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Removing BUG from %s\n", switch_channel_get_name(session->channel));
1121 
1122  if (last) {
1123  last->next = bp->next;
1124  } else {
1125  session->bugs = bp->next;
1126  }
1127  }
1128  switch_thread_rwlock_unlock(session->bug_rwlock);
1129  status = SWITCH_STATUS_SUCCESS;
1130  }
1131 
1132  if (switch_core_codec_ready(&session->bug_codec)) {
1133  switch_core_codec_destroy(&session->bug_codec);
1134  }
1135 
1136  return status;
1137 }
1138 
1140 {
1141  switch_media_bug_t *bp = *bug;
1142 
1143  if (bp) {
1144  if ((bp->thread_id && bp->thread_id != switch_thread_self()) || switch_test_flag(bp, SMBF_LOCK)) {
1146  return SWITCH_STATUS_FALSE;
1147  }
1148 
1149  if (bp->callback) {
1151  }
1152 
1155  }
1156 
1157  bp->ready = 0;
1158 
1159  switch_img_free(&bp->spy_img[0]);
1160  switch_img_free(&bp->spy_img[1]);
1161 
1162  if (bp->video_bug_thread) {
1163  switch_status_t st;
1164  int i;
1165 
1166  for (i = 0; i < 2; i++) {
1167  void *pop;
1168  switch_image_t *img;
1169 
1170  if (bp->spy_video_queue[i]) {
1171  while (switch_queue_trypop(bp->spy_video_queue[i], &pop) == SWITCH_STATUS_SUCCESS && pop) {
1172  img = (switch_image_t *) pop;
1173  switch_img_free(&img);
1174  }
1175  }
1176  }
1177 
1178  if (bp->read_video_queue) {
1180  }
1181 
1182  if (bp->write_video_queue) {
1184  }
1185 
1187  }
1188 
1192  *bug = NULL;
1193  return SWITCH_STATUS_SUCCESS;
1194  }
1195 
1196  return SWITCH_STATUS_FALSE;
1197 }
1198 
1200 {
1201  switch_media_bug_t *bp = NULL, *bp2 = NULL, *last = NULL;
1203  int tap_only = 0;
1204 
1206  return status;
1207  }
1208 
1209  switch_thread_rwlock_wrlock(session->bug_rwlock);
1210  if (session->bugs) {
1211  for (bp = session->bugs; bp; bp = bp->next) {
1212  if ((!bp->thread_id || bp->thread_id == switch_thread_self()) && bp->ready && bp == *bug) {
1213  if (last) {
1214  last->next = bp->next;
1215  } else {
1216  session->bugs = bp->next;
1217  }
1218  break;
1219  }
1220 
1221  last = bp;
1222  }
1223  }
1224 
1225  if (!session->bugs && switch_core_codec_ready(&session->bug_codec)) {
1226  switch_core_codec_destroy(&session->bug_codec);
1227  }
1228 
1229  if (session->bugs) {
1230  for(bp2 = session->bugs; bp2; bp2 = bp2->next) {
1231  if (bp2->ready && !switch_test_flag(bp2, SMBF_TAP_NATIVE_READ) && !switch_test_flag(bp2, SMBF_TAP_NATIVE_WRITE)) {
1232  tap_only = 0;
1233  }
1234  }
1235  }
1236 
1237  if (tap_only) {
1239  } else {
1241  }
1242 
1243  switch_thread_rwlock_unlock(session->bug_rwlock);
1244 
1245  if (bp) {
1246  status = switch_core_media_bug_close(&bp);
1247  }
1248 
1249  return status;
1250 }
1251 
1252 
1254 {
1255  switch_media_bug_t *bp = NULL, *last = NULL;
1256  int ttl = 0;
1257 
1258 
1259  top:
1260 
1261  switch_thread_rwlock_wrlock(session->bug_rwlock);
1262  if (session->bugs) {
1263  for (bp = session->bugs; bp; bp = bp->next) {
1265  if (last) {
1266  last->next = bp->next;
1267  } else {
1268  session->bugs = bp->next;
1269  }
1270  break;
1271  }
1272 
1273  last = bp;
1274  }
1275  }
1276 
1277  if (!session->bugs && switch_core_codec_ready(&session->bug_codec)) {
1278  switch_core_codec_destroy(&session->bug_codec);
1279  }
1280 
1281  switch_thread_rwlock_unlock(session->bug_rwlock);
1282 
1283  if (bp) {
1285  bp->thread_id = 0;
1287  ttl++;
1288  goto top;
1289  }
1290 
1291  return ttl;
1292 }
1293 
1294 
1296 {
1297  switch_media_bug_t *cur = NULL, *bp = NULL, *last = NULL;
1298  int total = 0;
1299 
1300  switch_thread_rwlock_wrlock(session->bug_rwlock);
1301  if (session->bugs) {
1302  bp = session->bugs;
1303  while (bp) {
1304  cur = bp;
1305  bp = bp->next;
1306 
1307  if ((!cur->thread_id || cur->thread_id == switch_thread_self()) && cur->ready && cur->callback == callback) {
1308  if (last) {
1309  last->next = cur->next;
1310  } else {
1311  session->bugs = cur->next;
1312  }
1314  total++;
1315  }
1316  } else {
1317  last = cur;
1318  }
1319  }
1320  }
1321 
1322  if (!session->bugs && switch_core_codec_ready(&session->bug_codec)) {
1323  switch_core_codec_destroy(&session->bug_codec);
1324  }
1325 
1326  switch_thread_rwlock_unlock(session->bug_rwlock);
1327 
1328 
1329  return total ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
1330 }
1331 
1332 /* For Emacs:
1333  * Local Variables:
1334  * mode:c
1335  * indent-tabs-mode:t
1336  * tab-width:4
1337  * c-basic-offset:4
1338  * End:
1339  * For VIM:
1340  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
1341  */
struct apr_queue_t switch_queue_t
Definition: switch_apr.h:590
switch_frame_t * switch_core_media_bug_get_video_ping_frame(switch_media_bug_t *bug)
static void switch_core_media_bug_destroy(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:412
unsigned int switch_queue_size(switch_queue_t *queue)
Definition: switch_apr.c:1114
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:263
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
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:631
#define SWITCH_THREAD_FUNC
switch_thread_id_t thread_id
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...
void(* switch_media_bug_exec_cb_t)(switch_media_bug_t *bug, void *user_data)
void switch_img_free(switch_image_t **img)
Close an image descriptor.
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_status_t switch_ivr_stop_record_session(switch_core_session_t *session, const char *file)
Stop Recording a session.
switch_frame_t * switch_core_media_bug_get_native_read_frame(switch_media_bug_t *bug)
#define SWITCH_RECOMMENDED_BUFFER_SIZE
Definition: switch_types.h:557
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:405
switch_status_t switch_threadattr_stacksize_set(switch_threadattr_t *attr, switch_size_t stacksize)
Definition: switch_apr.c:660
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:44
switch_status_t switch_queue_trypop(switch_queue_t *queue, void **data)
Definition: switch_apr.c:1140
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_status_t switch_core_codec_destroy(switch_codec_t *codec)
Destroy an initalized codec handle.
#define switch_core_session_get_name(_s)
Definition: switch_core.h:271
switch_status_t switch_queue_pop(switch_queue_t *queue, void **data)
Definition: switch_apr.c:1119
switch_bool_t(* switch_media_bug_callback_t)(switch_media_bug_t *, void *, switch_abc_type_t)
switch_status_t switch_core_media_bug_transfer_recordings(switch_core_session_t *orig_session, switch_core_session_t *new_session)
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
static switch_thread_t * thread
Definition: switch_log.c:279
switch_status_t switch_core_media_bug_enumerate(switch_core_session_t *session, switch_stream_handle_t *stream)
static int switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:450
void switch_img_find_position(switch_img_position_t pos, int sw, int sh, int iw, int ih, int *xP, int *yP)
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:281
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:290
switch_status_t switch_thread_rwlock_rdlock(switch_thread_rwlock_t *rwlock)
Definition: switch_apr.c:227
switch_status_t switch_thread_join(switch_status_t *retval, switch_thread_t *thd)
Definition: switch_apr.c:1255
switch_status_t switch_core_session_get_read_impl(switch_core_session_t *session, switch_codec_implementation_t *impp)
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
#define switch_clear_flag(obj, flag)
Clear a flag on an arbitrary object while locked.
Definition: switch_utils.h:655
#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:237
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:565
uint32_t buflen
Definition: switch_frame.h:59
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
#define SWITCH_CORE_QUEUE_LEN
Definition: switch_types.h:560
uint32_t packetlen
Definition: switch_frame.h:51
switch_status_t switch_core_media_bug_close(switch_media_bug_t **bug)
switch_frame_flag_t flags
Definition: switch_frame.h:74
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:285
switch_status_t switch_core_media_bug_push_spy_frame(switch_media_bug_t *bug, switch_frame_t *frame, switch_rw_t rw)
#define switch_channel_get_variable(_c, _v)
#define SWITCH_THREAD_STACKSIZE
Definition: switch_types.h:551
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]
void switch_img_copy(switch_image_t *img, switch_image_t **new_img)
Copy image to a new image.
switch_status_t switch_img_fit(switch_image_t **srcP, int width, int height, switch_img_fit_t fit)
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:270
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:43
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.
uint32_t switch_core_media_bug_test_flag(switch_media_bug_t *bug, uint32_t flag)
#define SWITCH_SMAX
Definition: switch_utils.h:259
switch_codec_implementation_t write_impl
void switch_core_media_bug_set_write_replace_frame(switch_media_bug_t *bug, switch_frame_t *frame)
void * packet
Definition: switch_frame.h:49
switch_image_t * img
Definition: switch_frame.h:77
switch_status_t
Common return values.
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:260
void switch_core_media_bug_flush(switch_media_bug_t *bug)
switch_vid_spy_fmt_t
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.
switch_status_t switch_ivr_record_session(switch_core_session_t *session, char *file, uint32_t limit, switch_file_handle_t *fh)
Record a session to disk.
struct apr_thread_t switch_thread_t
Definition: switch_apr.h:941
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:383
#define SWITCH_DECLARE(type)
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)
switch_status_t switch_core_media_bug_remove_all_function(switch_core_session_t *session, const char *function)
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:321
#define switch_core_session_alloc(_session, _memory)
Allocate memory from a session's pool.
Definition: switch_core.h:694
switch_status_t switch_queue_push(switch_queue_t *queue, void *data)
Definition: switch_apr.c:1129
uint32_t switch_core_media_bug_set_flag(switch_media_bug_t *bug, uint32_t flag)
struct apr_pool_t switch_memory_pool_t
switch_status_t switch_core_media_bug_flush_all(switch_core_session_t *session)
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:624
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:642
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:675
A table of settings and callbacks that define a paticular implementation of a codec.
#define switch_normalize_to_16bit(n)
Definition: switch_utils.h:261
uint32_t switch_media_bug_flag_t
switch_frame_t * switch_core_media_bug_get_native_write_frame(switch_media_bug_t *bug)
switch_status_t switch_queue_create(switch_queue_t **queue, unsigned int queue_capacity, switch_memory_pool_t *pool)
Definition: switch_apr.c:1109
#define switch_core_session_strdup(_session, _todup)
Copy a string using memory allocation from a session's pool.
Definition: switch_core.h:717
switch_thread_id_t switch_thread_self(void)
Definition: switch_apr.c:79
switch_status_t switch_core_media_bug_remove(switch_core_session_t *session, switch_media_bug_t **bug)
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)
#define switch_channel_set_variable(_channel, _var, _val)
switch_mutex_t * write_mutex
#define switch_channel_pre_answer(channel)
Indicate progress on a channel to attempt early media.
#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.