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"
36 #include "private/switch_core_pvt.h"
37
switch_core_media_bug_destroy(switch_media_bug_t ** bug)38 static void switch_core_media_bug_destroy(switch_media_bug_t **bug)
39 {
40 switch_event_t *event = NULL;
41 switch_media_bug_t *bp = *bug;
42
43 *bug = NULL;
44
45 if (bp->text_buffer) {
46 switch_buffer_destroy(&bp->text_buffer);
47 switch_safe_free(bp->text_framedata);
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
69 switch_thread_join(&st, bp->video_bug_thread);
70 }
71
72 if (bp->session && switch_test_flag(bp, SMBF_READ_VIDEO_PATCH) && bp->session->video_read_codec) {
73 switch_clear_flag(bp->session->video_read_codec, SWITCH_CODEC_FLAG_VIDEO_PATCHING);
74 }
75
76 if (bp->raw_read_buffer) {
77 switch_buffer_destroy(&bp->raw_read_buffer);
78 }
79
80 if (bp->raw_write_buffer) {
81 switch_buffer_destroy(&bp->raw_write_buffer);
82 }
83
84 if (switch_event_create(&event, SWITCH_EVENT_MEDIA_BUG_STOP) == SWITCH_STATUS_SUCCESS) {
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);
87 if (bp->session) switch_channel_event_set_data(bp->session->channel, event);
88 switch_event_fire(&event);
89 }
90 }
91
switch_core_media_bug_pause(switch_core_session_t * session)92 SWITCH_DECLARE(void) switch_core_media_bug_pause(switch_core_session_t *session)
93 {
94 switch_channel_set_flag(session->channel, CF_PAUSE_BUGS);
95 }
96
switch_core_media_bug_resume(switch_core_session_t * session)97 SWITCH_DECLARE(void) switch_core_media_bug_resume(switch_core_session_t *session)
98 {
99 switch_channel_clear_flag(session->channel, CF_PAUSE_BUGS);
100 }
101
switch_core_media_bug_test_flag(switch_media_bug_t * bug,uint32_t flag)102 SWITCH_DECLARE(uint32_t) switch_core_media_bug_test_flag(switch_media_bug_t *bug, uint32_t flag)
103 {
104 return switch_test_flag(bug, flag);
105 }
106
switch_core_media_bug_set_flag(switch_media_bug_t * bug,uint32_t flag)107 SWITCH_DECLARE(uint32_t) switch_core_media_bug_set_flag(switch_media_bug_t *bug, uint32_t flag)
108 {
109 if ((flag & SMBF_PRUNE)) {
110 switch_clear_flag(bug, SMBF_LOCK);
111 }
112 return switch_set_flag(bug, flag);
113 }
114
switch_core_media_bug_clear_flag(switch_media_bug_t * bug,uint32_t flag)115 SWITCH_DECLARE(uint32_t) switch_core_media_bug_clear_flag(switch_media_bug_t *bug, uint32_t flag)
116 {
117 return switch_clear_flag(bug, flag);
118 }
119
switch_core_media_bug_set_media_params(switch_media_bug_t * bug,switch_mm_t * mm)120 SWITCH_DECLARE(void) switch_core_media_bug_set_media_params(switch_media_bug_t *bug, switch_mm_t *mm)
121 {
122 bug->mm = *mm;
123 }
124
switch_core_media_bug_get_media_params(switch_media_bug_t * bug,switch_mm_t * mm)125 SWITCH_DECLARE(void) switch_core_media_bug_get_media_params(switch_media_bug_t *bug, switch_mm_t *mm)
126 {
127 *mm = bug->mm;
128 }
129
switch_core_media_bug_get_session(switch_media_bug_t * bug)130 SWITCH_DECLARE(switch_core_session_t *) switch_core_media_bug_get_session(switch_media_bug_t *bug)
131 {
132 return bug->session;
133 }
134
switch_core_media_bug_get_text(switch_media_bug_t * bug)135 SWITCH_DECLARE(const char *) switch_core_media_bug_get_text(switch_media_bug_t *bug)
136 {
137 return bug->text_framedata;
138 }
139
switch_core_media_bug_get_video_ping_frame(switch_media_bug_t * bug)140 SWITCH_DECLARE(switch_frame_t *) switch_core_media_bug_get_video_ping_frame(switch_media_bug_t *bug)
141 {
142 return bug->video_ping_frame;
143 }
144
switch_core_media_bug_get_write_replace_frame(switch_media_bug_t * bug)145 SWITCH_DECLARE(switch_frame_t *) switch_core_media_bug_get_write_replace_frame(switch_media_bug_t *bug)
146 {
147 return bug->write_replace_frame_in;
148 }
149
switch_core_media_bug_set_write_replace_frame(switch_media_bug_t * bug,switch_frame_t * frame)150 SWITCH_DECLARE(void) switch_core_media_bug_set_write_replace_frame(switch_media_bug_t *bug, switch_frame_t *frame)
151 {
152 bug->write_replace_frame_out = frame;
153 }
154
switch_core_media_bug_get_read_replace_frame(switch_media_bug_t * bug)155 SWITCH_DECLARE(switch_frame_t *) switch_core_media_bug_get_read_replace_frame(switch_media_bug_t *bug)
156 {
157 return bug->read_replace_frame_in;
158 }
159
switch_core_media_bug_get_native_read_frame(switch_media_bug_t * bug)160 SWITCH_DECLARE(switch_frame_t *) switch_core_media_bug_get_native_read_frame(switch_media_bug_t *bug)
161 {
162 return bug->native_read_frame;
163 }
164
switch_core_media_bug_get_native_write_frame(switch_media_bug_t * bug)165 SWITCH_DECLARE(switch_frame_t *) switch_core_media_bug_get_native_write_frame(switch_media_bug_t *bug)
166 {
167 return bug->native_write_frame;
168 }
169
switch_core_media_bug_set_read_replace_frame(switch_media_bug_t * bug,switch_frame_t * frame)170 SWITCH_DECLARE(void) switch_core_media_bug_set_read_replace_frame(switch_media_bug_t *bug, switch_frame_t *frame)
171 {
172 bug->read_replace_frame_out = frame;
173 }
174
switch_core_media_bug_set_read_demux_frame(switch_media_bug_t * bug,switch_frame_t * frame)175 SWITCH_DECLARE(void) switch_core_media_bug_set_read_demux_frame(switch_media_bug_t *bug, switch_frame_t *frame)
176 {
177 bug->read_demux_frame = frame;
178 }
179
switch_core_media_bug_get_user_data(switch_media_bug_t * bug)180 SWITCH_DECLARE(void *) switch_core_media_bug_get_user_data(switch_media_bug_t *bug)
181 {
182 return bug->user_data;
183 }
184
switch_core_media_bug_flush(switch_media_bug_t * bug)185 SWITCH_DECLARE(void) switch_core_media_bug_flush(switch_media_bug_t *bug)
186 {
187
188 bug->record_pre_buffer_count = 0;
189
190 if (bug->raw_read_buffer) {
191 switch_mutex_lock(bug->read_mutex);
192 switch_buffer_zero(bug->raw_read_buffer);
193 switch_mutex_unlock(bug->read_mutex);
194 }
195
196 if (bug->raw_write_buffer) {
197 switch_mutex_lock(bug->write_mutex);
198 switch_buffer_zero(bug->raw_write_buffer);
199 switch_mutex_unlock(bug->write_mutex);
200 }
201
202 bug->record_frame_size = 0;
203 bug->record_pre_buffer_count = 0;
204 }
205
switch_core_media_bug_inuse(switch_media_bug_t * bug,switch_size_t * readp,switch_size_t * writep)206 SWITCH_DECLARE(void) switch_core_media_bug_inuse(switch_media_bug_t *bug, switch_size_t *readp, switch_size_t *writep)
207 {
208 if (switch_test_flag(bug, SMBF_READ_STREAM)) {
209 switch_mutex_lock(bug->read_mutex);
210 *readp = bug->raw_read_buffer ? switch_buffer_inuse(bug->raw_read_buffer) : 0;
211 switch_mutex_unlock(bug->read_mutex);
212 } else {
213 *readp = 0;
214 }
215
216 if (switch_test_flag(bug, SMBF_WRITE_STREAM)) {
217 switch_mutex_lock(bug->write_mutex);
218 *writep = bug->raw_write_buffer ? switch_buffer_inuse(bug->raw_write_buffer) : 0;
219 switch_mutex_unlock(bug->write_mutex);
220 } else {
221 *writep = 0;
222 }
223 }
224
switch_core_media_bug_set_pre_buffer_framecount(switch_media_bug_t * bug,uint32_t framecount)225 SWITCH_DECLARE(switch_status_t) switch_core_media_bug_set_pre_buffer_framecount(switch_media_bug_t *bug, uint32_t framecount)
226 {
227 bug->record_pre_buffer_max = framecount;
228
229 return SWITCH_STATUS_SUCCESS;
230 }
231
switch_core_media_bug_read(switch_media_bug_t * bug,switch_frame_t * frame,switch_bool_t fill)232 SWITCH_DECLARE(switch_status_t) switch_core_media_bug_read(switch_media_bug_t *bug, switch_frame_t *frame, switch_bool_t fill)
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;
240 switch_codec_implementation_t read_impl = { 0 };
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) {
249 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)), SWITCH_LOG_ERROR, "%s frame buffer too small!\n",
250 switch_channel_get_name(bug->session->channel));
251 return SWITCH_STATUS_FALSE;
252 }
253
254 if ((!bug->raw_read_buffer && (!bug->raw_write_buffer || !switch_test_flag(bug, SMBF_WRITE_STREAM)))) {
255 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)), SWITCH_LOG_ERROR,
256 "%s Buffer Error (raw_read_buffer=%p, raw_write_buffer=%p, read=%s, write=%s)\n",
257 switch_channel_get_name(bug->session->channel),
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
267 if (switch_test_flag(bug, SMBF_READ_STREAM)) {
268 has_read = 1;
269 switch_mutex_lock(bug->read_mutex);
270 do_read = switch_buffer_inuse(bug->raw_read_buffer);
271 switch_mutex_unlock(bug->read_mutex);
272 }
273
274 if (switch_test_flag(bug, SMBF_WRITE_STREAM)) {
275 has_write = 1;
276 switch_mutex_lock(bug->write_mutex);
277 do_write = switch_buffer_inuse(bug->raw_write_buffer);
278 switch_mutex_unlock(bug->write_mutex);
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) {
283 bug->record_pre_buffer_count++;
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)) {
295 switch_mutex_lock(bug->write_mutex);
296 switch_buffer_toss(bug->raw_write_buffer, bug->record_frame_size);
297 do_write = switch_buffer_inuse(bug->raw_write_buffer);
298 switch_mutex_unlock(bug->write_mutex);
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) {
339 switch_mutex_lock(bug->read_mutex);
340 frame->datalen = (uint32_t) switch_buffer_read(bug->raw_read_buffer, frame->data, do_read);
341 if (frame->datalen != do_read) {
342 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)), SWITCH_LOG_ERROR, "Framing Error Reading!\n");
343 switch_core_media_bug_flush(bug);
344 switch_mutex_unlock(bug->read_mutex);
345 return SWITCH_STATUS_FALSE;
346 }
347 switch_mutex_unlock(bug->read_mutex);
348 } else if (fill_read) {
349 frame->datalen = (uint32_t)bytes;
350 memset(frame->data, 255, frame->datalen);
351 }
352
353 if (do_write) {
354 switch_assert(bug->raw_write_buffer);
355 switch_mutex_lock(bug->write_mutex);
356 datalen = (uint32_t) switch_buffer_read(bug->raw_write_buffer, bug->data, do_write);
357 if (datalen != do_write) {
358 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)), SWITCH_LOG_ERROR, "Framing Error Writing!\n");
359 switch_core_media_bug_flush(bug);
360 switch_mutex_unlock(bug->write_mutex);
361 return SWITCH_STATUS_FALSE;
362 }
363 switch_mutex_unlock(bug->write_mutex);
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;
379 if (switch_test_flag(bug, SMBF_STEREO_SWAP)) {
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
422 switch_normalize_to_16bit(z);
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
switch_media_bug_parse_spy_fmt(const char * name)443 SWITCH_DECLARE(switch_vid_spy_fmt_t) switch_media_bug_parse_spy_fmt(const char *name)
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
switch_media_bug_set_spy_fmt(switch_media_bug_t * bug,switch_vid_spy_fmt_t spy_fmt)460 SWITCH_DECLARE(void) switch_media_bug_set_spy_fmt(switch_media_bug_t *bug, switch_vid_spy_fmt_t spy_fmt)
461 {
462 bug->spy_fmt = spy_fmt;
463 }
464
switch_core_media_bug_patch_spy_frame(switch_media_bug_t * bug,switch_image_t * img,switch_rw_t rw)465 SWITCH_DECLARE(switch_status_t) switch_core_media_bug_patch_spy_frame(switch_media_bug_t *bug, switch_image_t *img, switch_rw_t rw)
466 {
467 switch_queue_t *spy_q = NULL;
468 int w = 0, h = 0;
469 switch_status_t status;
470 void *pop;
471 int i;
472
473 for (i = 0; i < 2; i++) {
474 if (!bug->spy_video_queue[i]) {
475 switch_queue_create(&bug->spy_video_queue[i], SWITCH_CORE_QUEUE_LEN, switch_core_session_get_pool(bug->session));
476 }
477 }
478
479 spy_q = bug->spy_video_queue[rw];
480
481 while(switch_queue_size(spy_q) > 0) {
482 if ((status = switch_queue_trypop(spy_q, &pop)) == SWITCH_STATUS_SUCCESS) {
483 switch_img_free(&bug->spy_img[rw]);
484 if (!(bug->spy_img[rw] = (switch_image_t *) pop)) {
485 break;
486 }
487 }
488 }
489
490 w = img->d_w;
491 h = img->d_h;
492
493 if (bug->spy_img[rw]) {
494
495 switch (bug->spy_fmt) {
496 case SPY_DUAL_CROP:
497 {
498 switch_image_t *spy_tmp = NULL;
499 switch_image_t *img_tmp = NULL;
500 switch_image_t *img_dup = NULL;
501 int x = 0, y = 0;
502 float aspect169 = (float)1920 / 1080;
503 switch_rgb_color_t bgcolor = { 0 };
504
505 if ((float)w/h == aspect169) {
506 if ((float)bug->spy_img[rw]->d_w / bug->spy_img[rw]->d_h == aspect169) {
507 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);
508
509 } else {
510 switch_img_copy(bug->spy_img[rw], &spy_tmp);
511 }
512 } else {
513 if ((float)bug->spy_img[rw]->d_w / bug->spy_img[rw]->d_h == aspect169) {
514 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);
515 } else {
516 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);
517 }
518 }
519
520 switch_img_copy(img, &img_dup);
521 img_tmp = switch_img_copy_rect(img_dup, w / 4, 0, w / 2, h);
522
523 switch_img_fit(&spy_tmp, w / 2, h, SWITCH_FIT_SIZE);
524 switch_img_fit(&img_tmp, w / 2, h, SWITCH_FIT_SIZE);
525
526 switch_color_set_rgb(&bgcolor, "#000000");
527 switch_img_fill(img, 0, 0, img->d_w, img->d_h, &bgcolor);
528
529 switch_img_find_position(POS_CENTER_MID, w / 2, h, img_tmp->d_w, img_tmp->d_h, &x, &y);
530 switch_img_patch(img, img_tmp, x, y);
531
532 switch_img_find_position(POS_CENTER_MID, w / 2, h, spy_tmp->d_w, spy_tmp->d_h, &x, &y);
533 switch_img_patch(img, spy_tmp, x + w / 2, y);
534
535
536 switch_img_free(&img_tmp);
537 switch_img_free(&img_dup);
538 switch_img_free(&spy_tmp);
539 }
540 break;
541 case SPY_LOWER_RIGHT_SMALL:
542 case SPY_LOWER_RIGHT_LARGE:
543 default:
544 {
545 float scaler = 0.125f;
546 int spyw, spyh;
547
548 if (bug->spy_fmt == SPY_LOWER_RIGHT_LARGE) {
549 scaler = 0.25f;
550 }
551
552 spyw = (int) (float)w * scaler;
553 spyh = (int) (float)h * scaler;
554
555 if (bug->spy_img[rw]->d_w != spyw || bug->spy_img[rw]->d_h != spyh) {
556 switch_image_t *tmp_img = NULL;
557
558 switch_img_scale(bug->spy_img[rw], &tmp_img, spyw, spyh);
559 switch_img_free(&bug->spy_img[rw]);
560 bug->spy_img[rw] = tmp_img;
561 }
562
563 switch_img_patch(img, bug->spy_img[rw], w - spyw, h - spyh);
564 }
565 break;
566 }
567
568 return SWITCH_STATUS_SUCCESS;
569 }
570
571 return SWITCH_STATUS_FALSE;
572 }
573
flush_video_queue(switch_queue_t * q,int min)574 static int flush_video_queue(switch_queue_t *q, int min)
575 {
576 void *pop;
577
578 if (switch_queue_size(q) > min) {
579 while (switch_queue_trypop(q, &pop) == SWITCH_STATUS_SUCCESS) {
580 switch_image_t *img = (switch_image_t *) pop;
581 switch_img_free(&img);
582 if (min && switch_queue_size(q) <= min) {
583 break;
584 }
585 }
586 }
587
588 return switch_queue_size(q);
589 }
590
video_bug_thread(switch_thread_t * thread,void * obj)591 static void *SWITCH_THREAD_FUNC video_bug_thread(switch_thread_t *thread, void *obj)
592 {
593 switch_media_bug_t *bug = (switch_media_bug_t *) obj;
594 switch_queue_t *main_q = NULL, *other_q = NULL;
595 switch_image_t *IMG = NULL, *img = NULL, *other_img = NULL;
596 void *pop, *other_pop;
597 uint8_t *buf;
598 switch_size_t buflen = SWITCH_RTP_MAX_BUF_LEN;
599 switch_frame_t frame = { 0 };
600 switch_timer_t timer = { 0 };
601 switch_mm_t mm = { 0 };
602 int vw = 1280;
603 int vh = 720;
604 int last_w = 0, last_h = 0, other_last_w = 0, other_last_h = 0;
605 switch_fps_t fps_data = { 0 };
606 float fps;
607 switch_rgb_color_t color = { 0 };
608 switch_color_set_rgb(&color, "#000000");
609
610 buf = switch_core_session_alloc(bug->session, buflen);
611 frame.packet = buf;
612 frame.data = buf + 12;
613 frame.packetlen = buflen;
614 frame.buflen = buflen - 12;
615 frame.flags = SFF_RAW_RTP;
616
617 if (switch_test_flag(bug, SMBF_READ_VIDEO_STREAM)) {
618 main_q = bug->read_video_queue;
619
620 if (switch_test_flag(bug, SMBF_WRITE_VIDEO_STREAM)) {
621 other_q = bug->write_video_queue;
622 }
623 } else if (switch_test_flag(bug, SMBF_WRITE_VIDEO_STREAM)) {
624 main_q = bug->write_video_queue;
625 } else {
626 return NULL;
627 }
628
629 switch_core_media_bug_get_media_params(bug, &mm);
630
631 if (mm.vw) vw = mm.vw;
632 if (mm.vh) vh = mm.vh;
633
634 if (mm.fps) {
635 fps = mm.fps;
636 } else {
637 fps = 15;
638 }
639 switch_calc_video_fps(&fps_data, fps);
640
641 switch_core_timer_init(&timer, "soft", fps_data.ms, fps_data.samples, NULL);
642
643 while (bug->ready) {
644 switch_status_t status;
645 int w = 0, h = 0, ok = 1, new_main = 0, new_other = 0, new_canvas = 0;
646
647 switch_core_timer_next(&timer);
648
649 if (!switch_channel_test_flag(bug->session->channel, CF_ANSWERED) && switch_core_media_bug_test_flag(bug, SMBF_ANSWER_REQ)) {
650 flush_video_queue(main_q, 0);
651 if (other_q) flush_video_queue(other_q, 0);
652 continue;
653 }
654
655 flush_video_queue(main_q, 1);
656
657 w = vw / 2;
658 h = vh;
659
660 if ((status = switch_queue_trypop(main_q, &pop)) == SWITCH_STATUS_SUCCESS) {
661 switch_img_free(&img);
662
663 if (!pop) {
664 goto end;
665 }
666
667 img = (switch_image_t *) pop;
668 new_main = 1;
669
670 if (IMG && !(last_w == img->d_w && last_h == img->d_h)) {
671 switch_img_fill(IMG, 0, 0, w, h, &color);
672 }
673
674 last_w = img->d_w;
675 last_h = img->d_h;
676 }
677
678 if (other_q) {
679 flush_video_queue(other_q, 1);
680
681 if ((status = switch_queue_trypop(other_q, &other_pop)) == SWITCH_STATUS_SUCCESS) {
682 switch_img_free(&other_img);
683 other_img = (switch_image_t *) other_pop;
684
685 if (IMG && !(other_last_w == other_img->d_w && other_last_h == other_img->d_h)) {
686 switch_img_fill(IMG, w, 0, w, h, &color);
687 }
688
689 other_last_w = other_img->d_w;
690 other_last_h = other_img->d_h;
691 new_other = 1;
692 }
693
694
695 if (img && new_main) {
696 switch_img_fit(&img, w, h, SWITCH_FIT_SIZE);
697 }
698
699 if (other_img && new_other) {
700 switch_img_fit(&other_img, w, h, SWITCH_FIT_SIZE);
701 }
702
703 if (!IMG) {
704 IMG = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, vw, vh, 1);
705 new_canvas = 1;
706 switch_img_fill(IMG, 0, 0, IMG->d_w, IMG->d_h, &color);
707 }
708 }
709
710
711 if (IMG) {
712
713
714 if (img && (new_canvas || new_main)) {
715 int x = 0, y = 0;
716 switch_img_find_position(POS_CENTER_MID, w, h, img->d_w, img->d_h, &x, &y);
717
718 switch_img_patch(IMG, img, x, y);
719 }
720
721 if (other_img && (new_canvas || new_other)) {
722 int x = 0, y = 0;
723 switch_img_find_position(POS_CENTER_MID, w, h, other_img->d_w, other_img->d_h, &x, &y);
724
725 switch_img_patch(IMG, other_img, w + x, y);
726 }
727 }
728
729 if (IMG || img) {
730 switch_thread_rwlock_rdlock(bug->session->bug_rwlock);
731 frame.img = other_q ? IMG : img;
732
733 bug->video_ping_frame = &frame;
734
735 if (bug->callback) {
736 if (bug->callback(bug, bug->user_data, SWITCH_ABC_TYPE_STREAM_VIDEO_PING) == SWITCH_FALSE
737 || (bug->stop_time && bug->stop_time <= switch_epoch_time_now(NULL))) {
738 ok = SWITCH_FALSE;
739 }
740 }
741
742 bug->video_ping_frame = NULL;
743 switch_thread_rwlock_unlock(bug->session->bug_rwlock);
744
745 if (!ok) {
746 switch_set_flag(bug, SMBF_PRUNE);
747 goto end;
748 }
749 }
750 }
751
752 end:
753
754 switch_core_timer_destroy(&timer);
755
756 switch_img_free(&IMG);
757 switch_img_free(&img);
758 switch_img_free(&other_img);
759
760 while (switch_queue_trypop(main_q, &pop) == SWITCH_STATUS_SUCCESS && pop) {
761 img = (switch_image_t *) pop;
762 switch_img_free(&img);
763 }
764
765 if (other_q) {
766 while (switch_queue_trypop(other_q, &pop) == SWITCH_STATUS_SUCCESS && pop) {
767 img = (switch_image_t *) pop;
768 switch_img_free(&img);
769 }
770 }
771
772 return NULL;
773 }
774
switch_core_media_bug_push_spy_frame(switch_media_bug_t * bug,switch_frame_t * frame,switch_rw_t rw)775 SWITCH_DECLARE(switch_status_t) switch_core_media_bug_push_spy_frame(switch_media_bug_t *bug, switch_frame_t *frame, switch_rw_t rw)
776 {
777
778 switch_assert(bug);
779 switch_assert(frame);
780
781 if (bug->spy_video_queue[rw] && frame->img) {
782 switch_image_t *img = NULL;
783
784 switch_img_copy(frame->img, &img);
785
786 if (img) {
787 switch_queue_push(bug->spy_video_queue[rw], img);
788 return SWITCH_STATUS_SUCCESS;
789 }
790 }
791
792 return SWITCH_STATUS_FALSE;
793 }
794
795 #define MAX_BUG_BUFFER 1024 * 512
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)796 SWITCH_DECLARE(switch_status_t) switch_core_media_bug_add(switch_core_session_t *session,
797 const char *function,
798 const char *target,
799 switch_media_bug_callback_t callback,
800 void *user_data, time_t stop_time,
801 switch_media_bug_flag_t flags,
802 switch_media_bug_t **new_bug)
803 {
804 switch_media_bug_t *bug, *bp;
805 switch_size_t bytes;
806 switch_event_t *event;
807 int tap_only = 1, punt = 0, added = 0;
808
809 const char *p;
810
811 if (!zstr(function)) {
812 if ((flags & SMBF_ONE_ONLY)) {
813 switch_thread_rwlock_wrlock(session->bug_rwlock);
814 for (bp = session->bugs; bp; bp = bp->next) {
815 if (!zstr(bp->function) && !strcasecmp(function, bp->function)) {
816 punt = 1;
817 break;
818 }
819 }
820 switch_thread_rwlock_unlock(session->bug_rwlock);
821 }
822 }
823
824 if (punt) {
825 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Only one bug of this type allowed!\n");
826 return SWITCH_STATUS_GENERR;
827 }
828
829
830 if (!switch_channel_media_ready(session->channel)) {
831 if (switch_channel_pre_answer(session->channel) != SWITCH_STATUS_SUCCESS) {
832 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot establish media. Media bug add failed.\n");
833 return SWITCH_STATUS_FALSE;
834 }
835 }
836
837
838
839 *new_bug = NULL;
840
841
842 if ((p = switch_channel_get_variable(session->channel, "media_bug_answer_req")) && switch_true(p)) {
843 flags |= SMBF_ANSWER_REQ;
844 }
845 #if 0
846 if (flags & SMBF_WRITE_REPLACE) {
847 switch_thread_rwlock_wrlock(session->bug_rwlock);
848 for (bp = session->bugs; bp; bp = bp->next) {
849 if (switch_test_flag(bp, SMBF_WRITE_REPLACE)) {
850 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Only one bug of this type allowed!\n");
851 switch_thread_rwlock_unlock(session->bug_rwlock);
852 return SWITCH_STATUS_GENERR;
853 }
854 }
855 switch_thread_rwlock_unlock(session->bug_rwlock);
856 }
857
858 if (flags & SMBF_READ_REPLACE) {
859 switch_thread_rwlock_wrlock(session->bug_rwlock);
860 for (bp = session->bugs; bp; bp = bp->next) {
861 if (switch_test_flag(bp, SMBF_READ_REPLACE)) {
862 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Only one bug of this type allowed!\n");
863 switch_thread_rwlock_unlock(session->bug_rwlock);
864 return SWITCH_STATUS_GENERR;
865 }
866 }
867 switch_thread_rwlock_unlock(session->bug_rwlock);
868 }
869 #endif
870
871 if (!(bug = switch_core_session_alloc(session, sizeof(*bug)))) {
872 return SWITCH_STATUS_MEMERR;
873 }
874
875 bug->callback = callback;
876 bug->user_data = user_data;
877 bug->session = session;
878 bug->flags = flags;
879 bug->function = "N/A";
880 bug->target = "N/A";
881
882 switch_core_session_get_read_impl(session, &bug->read_impl);
883 switch_core_session_get_write_impl(session, &bug->write_impl);
884
885 if (function) {
886 bug->function = switch_core_session_strdup(session, function);
887 }
888
889 if (target) {
890 bug->target = switch_core_session_strdup(session, target);
891 }
892
893 bug->stop_time = stop_time;
894
895 if (!(bytes = bug->read_impl.decoded_bytes_per_packet)) {
896 bytes = 320;
897 }
898
899 if (!bug->flags) {
900 bug->flags = (SMBF_READ_STREAM | SMBF_WRITE_STREAM);
901 }
902
903 if (switch_test_flag(bug, SMBF_READ_STREAM) || switch_test_flag(bug, SMBF_READ_PING)) {
904 switch_buffer_create_dynamic(&bug->raw_read_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, MAX_BUG_BUFFER);
905 switch_mutex_init(&bug->read_mutex, SWITCH_MUTEX_NESTED, session->pool);
906 }
907
908 bytes = bug->write_impl.decoded_bytes_per_packet;
909
910 if (switch_test_flag(bug, SMBF_WRITE_STREAM)) {
911 switch_buffer_create_dynamic(&bug->raw_write_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, MAX_BUG_BUFFER);
912 switch_mutex_init(&bug->write_mutex, SWITCH_MUTEX_NESTED, session->pool);
913 }
914
915 if ((bug->flags & SMBF_THREAD_LOCK)) {
916 bug->thread_id = switch_thread_self();
917 }
918
919 if (switch_test_flag(bug, SMBF_READ_VIDEO_STREAM) || switch_test_flag(bug, SMBF_WRITE_VIDEO_STREAM) || switch_test_flag(bug, SMBF_READ_VIDEO_PING) || switch_test_flag(bug, SMBF_WRITE_VIDEO_PING)) {
920 switch_channel_set_flag_recursive(session->channel, CF_VIDEO_DECODED_READ);
921 }
922
923 if (switch_test_flag(bug, SMBF_SPY_VIDEO_STREAM) || switch_core_media_bug_test_flag(bug, SMBF_SPY_VIDEO_STREAM_BLEG)) {
924 switch_queue_create(&bug->spy_video_queue[0], SWITCH_CORE_QUEUE_LEN, switch_core_session_get_pool(session));
925 switch_queue_create(&bug->spy_video_queue[1], SWITCH_CORE_QUEUE_LEN, switch_core_session_get_pool(session));
926 }
927
928 if ((switch_test_flag(bug, SMBF_READ_TEXT_STREAM))) {
929
930 switch_buffer_create_dynamic(&bug->text_buffer, 512, 1024, 0);
931 switch_zmalloc(bug->text_framedata, 1024);
932 bug->text_framesize = 1024;
933
934 }
935
936 if ((switch_test_flag(bug, SMBF_READ_VIDEO_STREAM) || switch_test_flag(bug, SMBF_WRITE_VIDEO_STREAM))) {
937 switch_memory_pool_t *pool = switch_core_session_get_pool(session);
938
939 if (switch_test_flag(bug, SMBF_READ_VIDEO_STREAM)) {
940 switch_queue_create(&bug->read_video_queue, SWITCH_CORE_QUEUE_LEN, pool);
941 }
942
943 if (switch_test_flag(bug, SMBF_WRITE_VIDEO_STREAM)) {
944 switch_queue_create(&bug->write_video_queue, SWITCH_CORE_QUEUE_LEN, pool);
945 }
946 }
947
948
949 if (bug->callback) {
950 switch_bool_t result = bug->callback(bug, bug->user_data, SWITCH_ABC_TYPE_INIT);
951 if (result == SWITCH_FALSE) {
952 switch_core_media_bug_destroy(&bug);
953 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error attaching BUG to %s\n",
954 switch_channel_get_name(session->channel));
955 return SWITCH_STATUS_GENERR;
956 }
957 }
958
959 bug->ready = 1;
960
961 if ((switch_test_flag(bug, SMBF_READ_VIDEO_STREAM) || switch_test_flag(bug, SMBF_WRITE_VIDEO_STREAM))) {
962 switch_threadattr_t *thd_attr = NULL;
963 switch_memory_pool_t *pool = switch_core_session_get_pool(session);
964 switch_threadattr_create(&thd_attr, pool);
965 switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
966 switch_thread_create(&bug->video_bug_thread, thd_attr, video_bug_thread, bug, pool);
967
968 }
969
970 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Attaching BUG to %s\n", switch_channel_get_name(session->channel));
971 switch_thread_rwlock_wrlock(session->bug_rwlock);
972
973 if (!session->bugs) {
974 session->bugs = bug;
975 added = 1;
976 }
977
978 if (!added && switch_test_flag(bug, SMBF_FIRST)) {
979 bug->next = session->bugs;
980 session->bugs = bug;
981 added = 1;
982 }
983
984 for(bp = session->bugs; bp; bp = bp->next) {
985 if (bp->ready && !switch_test_flag(bp, SMBF_TAP_NATIVE_READ) && !switch_test_flag(bp, SMBF_TAP_NATIVE_WRITE)) {
986 tap_only = 0;
987 }
988
989 if (!added && !bp->next) {
990 bp->next = bug;
991 break;
992 }
993 }
994
995 switch_thread_rwlock_unlock(session->bug_rwlock);
996 *new_bug = bug;
997
998 if (tap_only) {
999 switch_set_flag(session, SSF_MEDIA_BUG_TAP_ONLY);
1000 } else {
1001 switch_clear_flag(session, SSF_MEDIA_BUG_TAP_ONLY);
1002 }
1003
1004 if (switch_test_flag(bug, SMBF_READ_VIDEO_PATCH) && session->video_read_codec) {
1005 switch_set_flag(session->video_read_codec, SWITCH_CODEC_FLAG_VIDEO_PATCHING);
1006 }
1007
1008 if (switch_event_create(&event, SWITCH_EVENT_MEDIA_BUG_START) == SWITCH_STATUS_SUCCESS) {
1009 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Media-Bug-Function", "%s", bug->function);
1010 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Media-Bug-Target", "%s", bug->target);
1011 switch_channel_event_set_data(session->channel, event);
1012 switch_event_fire(&event);
1013 }
1014
1015 switch_core_media_hard_mute(session, SWITCH_FALSE);
1016
1017 return SWITCH_STATUS_SUCCESS;
1018 }
1019
1020
switch_core_media_bug_flush_all(switch_core_session_t * session)1021 SWITCH_DECLARE(switch_status_t) switch_core_media_bug_flush_all(switch_core_session_t *session)
1022 {
1023 switch_media_bug_t *bp;
1024
1025 if (session->bugs) {
1026 switch_thread_rwlock_wrlock(session->bug_rwlock);
1027 for (bp = session->bugs; bp; bp = bp->next) {
1028 switch_core_media_bug_flush(bp);
1029 }
1030 switch_thread_rwlock_unlock(session->bug_rwlock);
1031 return SWITCH_STATUS_SUCCESS;
1032 }
1033
1034 return SWITCH_STATUS_FALSE;
1035 }
1036
1037
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 *))1038 SWITCH_DECLARE(switch_status_t) switch_core_media_bug_transfer_callback(switch_core_session_t *orig_session, switch_core_session_t *new_session,
1039 switch_media_bug_callback_t callback, void * (*user_data_dup_func) (switch_core_session_t *, void *))
1040 {
1041 switch_media_bug_t *new_bug = NULL, *cur = NULL, *bp = NULL, *last = NULL;
1042 int total = 0;
1043
1044 if (!switch_channel_media_ready(new_session->channel)) {
1045 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(orig_session), SWITCH_LOG_WARNING, "Cannot transfer media bugs to a channel with no media.\n");
1046 return SWITCH_STATUS_FALSE;
1047 }
1048
1049 switch_thread_rwlock_wrlock(orig_session->bug_rwlock);
1050 bp = orig_session->bugs;
1051 while (bp) {
1052 cur = bp;
1053 bp = bp->next;
1054
1055 if (cur->callback == callback) {
1056 if (last) {
1057 last->next = cur->next;
1058 } else {
1059 orig_session->bugs = cur->next;
1060 }
1061
1062 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(orig_session), SWITCH_LOG_DEBUG, "Transfering %s from %s to %s\n", cur->target,
1063 switch_core_session_get_name(orig_session), switch_core_session_get_name(new_session));
1064
1065 switch_core_media_bug_add(new_session, cur->function, cur->target, cur->callback,
1066 user_data_dup_func(new_session, cur->user_data),
1067 cur->stop_time, cur->flags, &new_bug);
1068 switch_core_media_bug_destroy(&cur);
1069 total++;
1070 } else {
1071 last = cur;
1072 }
1073 }
1074
1075 if (!orig_session->bugs && switch_core_codec_ready(&orig_session->bug_codec)) {
1076 switch_core_codec_destroy(&orig_session->bug_codec);
1077 }
1078
1079 switch_thread_rwlock_unlock(orig_session->bug_rwlock);
1080
1081
1082 return total ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
1083 }
1084
1085
switch_core_media_bug_pop(switch_core_session_t * orig_session,const char * function,switch_media_bug_t ** pop)1086 SWITCH_DECLARE(switch_status_t) switch_core_media_bug_pop(switch_core_session_t *orig_session, const char *function, switch_media_bug_t **pop)
1087 {
1088 switch_media_bug_t *bp;
1089
1090 if (orig_session->bugs) {
1091 switch_thread_rwlock_wrlock(orig_session->bug_rwlock);
1092 for (bp = orig_session->bugs; bp; bp = bp->next) {
1093 if (!strcmp(bp->function, function)) {
1094 switch_set_flag(bp, SMBF_LOCK);
1095 break;
1096 }
1097 }
1098 switch_thread_rwlock_unlock(orig_session->bug_rwlock);
1099
1100 if (bp) {
1101 *pop = bp;
1102 return SWITCH_STATUS_SUCCESS;
1103 } else {
1104 *pop = NULL;
1105 }
1106 }
1107
1108 return SWITCH_STATUS_FALSE;
1109 }
1110
1111
switch_core_media_bug_count(switch_core_session_t * orig_session,const char * function)1112 SWITCH_DECLARE(uint32_t) switch_core_media_bug_count(switch_core_session_t *orig_session, const char *function)
1113 {
1114 switch_media_bug_t *bp;
1115 uint32_t x = 0;
1116
1117 if (orig_session->bugs) {
1118 switch_thread_rwlock_rdlock(orig_session->bug_rwlock);
1119 for (bp = orig_session->bugs; bp; bp = bp->next) {
1120 if (!switch_test_flag(bp, SMBF_PRUNE) && !switch_test_flag(bp, SMBF_LOCK) && !strcmp(bp->function, function)) {
1121 x++;
1122 }
1123 }
1124 switch_thread_rwlock_unlock(orig_session->bug_rwlock);
1125 }
1126
1127 return x;
1128 }
1129
switch_core_media_bug_patch_video(switch_core_session_t * orig_session,switch_frame_t * frame)1130 SWITCH_DECLARE(uint32_t) switch_core_media_bug_patch_video(switch_core_session_t *orig_session, switch_frame_t *frame)
1131 {
1132 switch_media_bug_t *bp;
1133 uint32_t x = 0, ok = SWITCH_TRUE, prune = 0;
1134
1135 if (orig_session->bugs) {
1136 switch_thread_rwlock_rdlock(orig_session->bug_rwlock);
1137 for (bp = orig_session->bugs; bp; bp = bp->next) {
1138 if (!switch_test_flag(bp, SMBF_PRUNE) && !switch_test_flag(bp, SMBF_LOCK) && !strcmp(bp->function, "patch:video")) {
1139 if (bp->ready && frame->img && switch_test_flag(bp, SMBF_VIDEO_PATCH)) {
1140 bp->video_ping_frame = frame;
1141 if (bp->callback) {
1142 if (bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_VIDEO_PATCH) == SWITCH_FALSE
1143 || (bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL))) {
1144 ok = SWITCH_FALSE;
1145 }
1146 }
1147 bp->video_ping_frame = NULL;
1148 }
1149
1150 if (ok == SWITCH_FALSE) {
1151 switch_set_flag(bp, SMBF_PRUNE);
1152 prune++;
1153 } else x++;
1154 }
1155 }
1156 switch_thread_rwlock_unlock(orig_session->bug_rwlock);
1157 if (prune) {
1158 switch_core_media_bug_prune(orig_session);
1159 }
1160 }
1161
1162 return x;
1163 }
1164
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)1165 SWITCH_DECLARE(switch_status_t) switch_core_media_bug_exec_all(switch_core_session_t *orig_session,
1166 const char *function, switch_media_bug_exec_cb_t cb, void *user_data)
1167 {
1168 switch_media_bug_t *bp;
1169 int x = 0;
1170
1171 switch_assert(cb);
1172
1173 if (orig_session->bugs) {
1174 switch_thread_rwlock_wrlock(orig_session->bug_rwlock);
1175 for (bp = orig_session->bugs; bp; bp = bp->next) {
1176 if (!switch_test_flag(bp, SMBF_PRUNE) && !switch_test_flag(bp, SMBF_LOCK) && !strcmp(bp->function, function)) {
1177 cb(bp, user_data);
1178 x++;
1179 }
1180 }
1181 switch_thread_rwlock_unlock(orig_session->bug_rwlock);
1182 }
1183
1184 return x ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
1185 }
1186
switch_core_media_bug_enumerate(switch_core_session_t * session,switch_stream_handle_t * stream)1187 SWITCH_DECLARE(switch_status_t) switch_core_media_bug_enumerate(switch_core_session_t *session, switch_stream_handle_t *stream)
1188 {
1189 switch_media_bug_t *bp;
1190
1191 stream->write_function(stream, "<media-bugs>\n");
1192
1193 if (session->bugs) {
1194 switch_thread_rwlock_rdlock(session->bug_rwlock);
1195 for (bp = session->bugs; bp; bp = bp->next) {
1196 int thread_locked = (bp->thread_id && bp->thread_id == switch_thread_self());
1197 stream->write_function(stream,
1198 " <media-bug>\n"
1199 " <function>%s</function>\n"
1200 " <target>%s</target>\n"
1201 " <thread-locked>%d</thread-locked>\n"
1202 " </media-bug>\n",
1203 bp->function, bp->target, thread_locked);
1204
1205 }
1206 switch_thread_rwlock_unlock(session->bug_rwlock);
1207 }
1208
1209 stream->write_function(stream, "</media-bugs>\n");
1210
1211 return SWITCH_STATUS_SUCCESS;
1212 }
1213
switch_core_media_bug_remove_all_function(switch_core_session_t * session,const char * function)1214 SWITCH_DECLARE(switch_status_t) switch_core_media_bug_remove_all_function(switch_core_session_t *session, const char *function)
1215 {
1216 switch_media_bug_t *bp, *last = NULL, *next = NULL;
1217 switch_status_t status = SWITCH_STATUS_FALSE;
1218 switch_media_bug_t *closed = NULL;
1219
1220 switch_thread_rwlock_wrlock(session->bug_rwlock);
1221 if (session->bugs) {
1222 for (bp = session->bugs; bp; bp = next) {
1223 next = bp->next;
1224
1225 if (!switch_test_flag(session, SSF_DESTROYABLE) &&
1226 ((bp->thread_id && bp->thread_id != switch_thread_self()) || switch_test_flag(bp, SMBF_LOCK))) {
1227 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "BUG is thread locked skipping.\n");
1228 last = bp;
1229 continue;
1230 }
1231
1232 if (!zstr(function) && strcmp(bp->function, function)) {
1233 last = bp;
1234 continue;
1235 }
1236
1237 if (last) {
1238 last->next = bp->next;
1239 } else {
1240 session->bugs = bp->next;
1241 }
1242
1243 bp->next = closed;
1244 closed = bp;
1245
1246 switch_core_media_bug_close(&bp, SWITCH_FALSE);
1247 }
1248 status = SWITCH_STATUS_SUCCESS;
1249 }
1250 switch_thread_rwlock_unlock(session->bug_rwlock);
1251
1252
1253 if (closed) {
1254 for (bp = closed; bp; bp = next) {
1255 next = bp->next;
1256 switch_core_media_bug_destroy(&bp);
1257 }
1258 }
1259
1260 if (switch_core_codec_ready(&session->bug_codec)) {
1261 switch_core_codec_destroy(&session->bug_codec);
1262 }
1263
1264 return status;
1265 }
1266
switch_core_media_bug_close(switch_media_bug_t ** bug,switch_bool_t destroy)1267 SWITCH_DECLARE(switch_status_t) switch_core_media_bug_close(switch_media_bug_t **bug, switch_bool_t destroy)
1268 {
1269 switch_media_bug_t *bp = *bug;
1270
1271 if (bp) {
1272 if ((bp->thread_id && bp->thread_id != switch_thread_self()) || switch_test_flag(bp, SMBF_LOCK)) {
1273 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(*bug)), SWITCH_LOG_DEBUG, "BUG is thread locked skipping.\n");
1274 return SWITCH_STATUS_FALSE;
1275 }
1276
1277 if (bp->callback) {
1278 bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_CLOSE);
1279 }
1280
1281 if (switch_test_flag(bp, SMBF_READ_VIDEO_STREAM) || switch_test_flag(bp, SMBF_WRITE_VIDEO_STREAM) || switch_test_flag(bp, SMBF_READ_VIDEO_PING) || switch_test_flag(bp, SMBF_WRITE_VIDEO_PING)) {
1282 switch_channel_clear_flag_recursive(bp->session->channel, CF_VIDEO_DECODED_READ);
1283 }
1284
1285 bp->ready = 0;
1286
1287 if (bp->read_video_queue) {
1288 switch_queue_push(bp->read_video_queue, NULL);
1289 }
1290
1291 if (bp->write_video_queue) {
1292 switch_queue_push(bp->write_video_queue, NULL);
1293 }
1294
1295 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(*bug)), SWITCH_LOG_DEBUG, "Removing BUG from %s\n",
1296 switch_channel_get_name(bp->session->channel));
1297
1298 if (destroy) {
1299 switch_core_media_bug_destroy(bug);
1300 }
1301
1302 return SWITCH_STATUS_SUCCESS;
1303 }
1304
1305 return SWITCH_STATUS_FALSE;
1306 }
1307
switch_core_media_bug_remove(switch_core_session_t * session,switch_media_bug_t ** bug)1308 SWITCH_DECLARE(switch_status_t) switch_core_media_bug_remove(switch_core_session_t *session, switch_media_bug_t **bug)
1309 {
1310 switch_media_bug_t *bp = NULL, *bp2 = NULL, *last = NULL;
1311 switch_status_t status = SWITCH_STATUS_FALSE;
1312 int tap_only = 0;
1313
1314 if (switch_core_media_bug_test_flag(*bug, SMBF_LOCK)) {
1315 return status;
1316 }
1317
1318 switch_thread_rwlock_wrlock(session->bug_rwlock);
1319 if (session->bugs) {
1320 for (bp = session->bugs; bp; bp = bp->next) {
1321 if ((!bp->thread_id || bp->thread_id == switch_thread_self()) && bp->ready && bp == *bug) {
1322 if (last) {
1323 last->next = bp->next;
1324 } else {
1325 session->bugs = bp->next;
1326 }
1327 break;
1328 }
1329
1330 last = bp;
1331 }
1332 }
1333
1334 if (!session->bugs && switch_core_codec_ready(&session->bug_codec)) {
1335 switch_core_codec_destroy(&session->bug_codec);
1336 }
1337
1338 if (session->bugs) {
1339 for(bp2 = session->bugs; bp2; bp2 = bp2->next) {
1340 if (bp2->ready && !switch_test_flag(bp2, SMBF_TAP_NATIVE_READ) && !switch_test_flag(bp2, SMBF_TAP_NATIVE_WRITE)) {
1341 tap_only = 0;
1342 }
1343 }
1344 }
1345
1346 if (tap_only) {
1347 switch_set_flag(session, SSF_MEDIA_BUG_TAP_ONLY);
1348 } else {
1349 switch_clear_flag(session, SSF_MEDIA_BUG_TAP_ONLY);
1350 }
1351
1352 switch_thread_rwlock_unlock(session->bug_rwlock);
1353
1354 if (bp) {
1355 status = switch_core_media_bug_close(&bp, SWITCH_TRUE);
1356 }
1357
1358 return status;
1359 }
1360
1361
switch_core_media_bug_prune(switch_core_session_t * session)1362 SWITCH_DECLARE(uint32_t) switch_core_media_bug_prune(switch_core_session_t *session)
1363 {
1364 switch_media_bug_t *bp = NULL, *last = NULL;
1365 int ttl = 0;
1366
1367
1368 top:
1369
1370 switch_thread_rwlock_wrlock(session->bug_rwlock);
1371 if (session->bugs) {
1372 for (bp = session->bugs; bp; bp = bp->next) {
1373 if (switch_core_media_bug_test_flag(bp, SMBF_PRUNE)) {
1374 if (last) {
1375 last->next = bp->next;
1376 } else {
1377 session->bugs = bp->next;
1378 }
1379 break;
1380 }
1381
1382 last = bp;
1383 }
1384 }
1385
1386 if (!session->bugs && switch_core_codec_ready(&session->bug_codec)) {
1387 switch_core_codec_destroy(&session->bug_codec);
1388 }
1389
1390 switch_thread_rwlock_unlock(session->bug_rwlock);
1391
1392 if (bp) {
1393 switch_clear_flag(bp, SMBF_LOCK);
1394 bp->thread_id = 0;
1395 switch_core_media_bug_close(&bp, SWITCH_TRUE);
1396 ttl++;
1397 goto top;
1398 }
1399
1400 return ttl;
1401 }
1402
1403
switch_core_media_bug_remove_callback(switch_core_session_t * session,switch_media_bug_callback_t callback)1404 SWITCH_DECLARE(switch_status_t) switch_core_media_bug_remove_callback(switch_core_session_t *session, switch_media_bug_callback_t callback)
1405 {
1406 switch_media_bug_t *cur = NULL, *bp = NULL, *last = NULL, *closed = NULL, *next = NULL;
1407 int total = 0;
1408
1409 switch_thread_rwlock_wrlock(session->bug_rwlock);
1410 if (session->bugs) {
1411 bp = session->bugs;
1412 while (bp) {
1413 cur = bp;
1414 bp = bp->next;
1415
1416 if ((!cur->thread_id || cur->thread_id == switch_thread_self()) && cur->ready && cur->callback == callback) {
1417 if (last) {
1418 last->next = cur->next;
1419 } else {
1420 session->bugs = cur->next;
1421 }
1422 if (switch_core_media_bug_close(&cur, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
1423 total++;
1424 }
1425
1426 cur->next = closed;
1427 closed = cur;
1428
1429 } else {
1430 last = cur;
1431 }
1432 }
1433 }
1434 switch_thread_rwlock_unlock(session->bug_rwlock);
1435
1436 if (closed) {
1437 for (bp = closed; bp; bp = next) {
1438 next = bp->next;
1439 switch_core_media_bug_destroy(&bp);
1440 }
1441 }
1442
1443 if (!session->bugs && switch_core_codec_ready(&session->bug_codec)) {
1444 switch_core_codec_destroy(&session->bug_codec);
1445 }
1446
1447 return total ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
1448 }
1449
1450 /* For Emacs:
1451 * Local Variables:
1452 * mode:c
1453 * indent-tabs-mode:t
1454 * tab-width:4
1455 * c-basic-offset:4
1456 * End:
1457 * For VIM:
1458 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
1459 */
1460