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