commit de lancement : 2.0.1-1
[asterisk-app-conference.git] / member.c
1
2 // $Id: member.c 885 2007-06-27 15:41:18Z sbalea $
3
4 /*
5 * app_conference
6 *
7 * A channel independent conference application for Asterisk
8 *
9 * Copyright (C) 2002, 2003 Junghanns.NET GmbH
10 * Copyright (C) 2003, 2004 HorizonLive.com, Inc.
11 * Copyright (C) 2005, 2006 HorizonWimba, Inc.
12 * Copyright (C) 2007 Wimba, Inc.
13 *
14 * Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
15 *
16 * Video Conferencing support added by
17 * Neil Stratford <neils@vipadia.com>
18 * Copyright (C) 2005, 2005 Vipadia Limited
19 *
20 * VAD driven video conferencing, text message support
21 * and miscellaneous enhancements added by
22 * Mihai Balea <mihai at hates dot ms>
23 *
24 * This program may be modified and distributed under the
25 * terms of the GNU General Public License. You should have received
26 * a copy of the GNU General Public License along with this
27 * program; if not, write to the Free Software Foundation, Inc.
28 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 */
30
31 #include <stdio.h>
32 #include "asterisk/autoconfig.h"
33 #include "member.h"
34
35
36 // process an incoming frame. Returns 0 normally, 1 if hangup was received.
37 static int process_incoming(struct ast_conf_member *member, struct ast_conference *conf, struct ast_frame *f)
38 {
39 int silent_frame = 0;
40 struct ast_conf_member *src_member ;
41
42 // In Asterisk 1.4 AST_FRAME_DTMF is equivalent to AST_FRAME_DTMF_END
43 if (f->frametype == AST_FRAME_DTMF)
44 {
45 if (member->dtmf_switch)
46 {
47 ast_mutex_lock( &member->lock ) ;
48 switch (f->subclass) {
49 case '0' :member->req_id=0;
50 break;
51 case '1' :member->req_id=1;
52 break;
53 case '2' :member->req_id=2;
54 break;
55 case '3' :member->req_id=3;
56 break;
57 case '4' :member->req_id=4;
58 break;
59 case '5' :member->req_id=5;
60 break;
61 case '6' :member->req_id=6;
62 break;
63 case '7' :member->req_id=7;
64 break;
65 case '8' :member->req_id=8;
66 break;
67 case '9' :member->req_id=9;
68 break;
69 case '*' :
70 if (member->mute_video == 0 && member->mute_audio == 0)
71 {
72 member->mute_video = 1;
73 member->mute_audio = 1;
74 }
75 else if (member->mute_video == 1 && member->mute_audio == 1)
76 {
77 member->mute_video = 0;
78 member->mute_audio = 0;
79 }
80 break;
81 }
82 member->conference = 1; // switch me
83 ast_mutex_unlock( &member->lock ) ;
84 }
85 if (member->dtmf_relay)
86 {
87 // output to manager...
88 manager_event(
89 EVENT_FLAG_CALL,
90 "ConferenceDTMF",
91 "ConferenceName: %s\r\n"
92 "Channel: %s\r\n"
93 "CallerID: %s\r\n"
94 "CallerIDName: %s\r\n"
95 "Key: %c\r\n",
96 conf->name,
97 member->channel_name,
98 member->chan->cid.cid_num ? member->chan->cid.cid_num : "unknown",
99 member->chan->cid.cid_name ? member->chan->cid.cid_name : "unknown",
100 f->subclass
101 ) ;
102
103 }
104 if (!member->dtmf_switch && !member->dtmf_relay)
105 {
106 // relay this to the listening channels
107 queue_incoming_dtmf_frame( member, f );
108 }
109 } else if (f->frametype == AST_FRAME_DTMF_BEGIN)
110 {
111 if (!member->dtmf_switch && !member->dtmf_relay)
112 {
113 // relay this to the listening channels
114 queue_incoming_dtmf_frame( member, f );
115 }
116 }
117
118 ast_mutex_lock( &member->lock ) ;
119 // Handle a local or remote conference
120 if (member->conference)
121 {
122 int req_id = member->req_id;
123 ast_mutex_unlock( &member->lock );
124 // this will return NULL or a locked member
125 src_member = check_active_video(req_id,conf);
126 // Stream a picture to the recipient if no active video
127 if (!src_member)
128 {
129 // Mihai: we don't want to send video here, we cannot negotiate codec
130 // and we don't know what codec the conference is using
131 //if (member->norecv_video == 0)
132 //{
133 // if(!ast_streamfile(member->chan,"novideo",member->chan->language))
134 // {
135 // ast_waitstream(member->chan,"");
136 // }
137 //}
138 }
139 else
140 {
141 // Send a FIR to the new sender
142 ast_indicate(src_member->chan,AST_CONTROL_VIDUPDATE);
143 // we will have locked in check_active_video()
144 ast_mutex_unlock( &src_member->lock);
145 }
146 ast_mutex_lock( &member->lock );
147 member->conference = 0;
148 }
149 ast_mutex_unlock( &member->lock );
150
151
152 if ((f->frametype == AST_FRAME_VOICE && member->mute_audio == 1) || (f->frametype == AST_FRAME_VIDEO && member->mute_video == 1))
153 {
154 // this is a listen-only user, ignore the frame
155 //ast_log( AST_CONF_DEBUG, "Listen only user frame");
156 ast_frfree( f ) ;
157 f = NULL ;
158 }
159 else if ( f->frametype == AST_FRAME_VOICE )
160 { //ast_log( AST_CONF_DEBUG, "Got voice frame");
161 // reset silence detection flag
162 silent_frame = 0 ;
163
164 // accounting: count the incoming frame
165 member->frames_in++ ;
166
167 #if ( SILDET == 2 )
168 //
169 // make sure we have a valid dsp and frame type
170 //
171 if (
172 member->dsp != NULL
173 && f->subclass == AST_FORMAT_SLINEAR
174 && f->datalen == AST_CONF_FRAME_DATA_SIZE
175 )
176 {
177 // send the frame to the preprocessor
178 int spx_ret;
179 spx_ret = speex_preprocess( member->dsp, f->data, NULL );
180 #ifdef DEBUG_USE_TIMELOG
181 TIMELOG(spx_ret, 3, "speex_preprocess");
182 #endif
183 if ( spx_ret == 0 )
184 {
185 //
186 // we ignore the preprocessor's outcome if we've seen voice frames
187 // in within the last AST_CONF_SKIP_SPEEX_PREPROCESS frames
188 //
189 if ( member->ignore_speex_count > 0 )
190 {
191 // ast_log( AST_CONF_DEBUG, "ignore_speex_count => %d\n", ignore_speex_count ) ;
192
193 // skip speex_preprocess(), and decrement counter
194 --member->ignore_speex_count ;
195 }
196 else
197 {
198 // set silent_frame flag
199 silent_frame = 1 ;
200 }
201 }
202 else
203 {
204 // voice detected, reset skip count
205 member->ignore_speex_count = AST_CONF_SKIP_SPEEX_PREPROCESS ;
206 }
207 }
208 #endif
209 if ( !silent_frame )
210 queue_incoming_frame( member, f );
211
212 // free the original frame
213 ast_frfree( f ) ;
214 f = NULL ;
215
216 }
217 else if (f->frametype == AST_FRAME_VIDEO)
218 {
219 queue_incoming_video_frame( member, f );
220
221 // free the original frame
222 ast_frfree( f ) ;
223 f = NULL ;
224
225 }
226 else if (
227 f->frametype == AST_FRAME_CONTROL
228 && f->subclass == AST_CONTROL_HANGUP
229 )
230 {
231 // hangup received
232
233 // free the frame
234 ast_frfree( f ) ;
235 f = NULL ;
236
237 // break out of the while ( 42 == 42 )
238 return 1;
239 }
240 else if (
241 f->frametype == AST_FRAME_CONTROL
242 && f->subclass == AST_CONTROL_VIDUPDATE
243 )
244 {
245 // say we have switched to cause a FIR to
246 // be sent to the sender
247 ast_mutex_lock( &member->lock ) ;
248 member->conference = 1;
249 ast_mutex_unlock( &member->lock ) ;
250
251 // free the original frame
252 ast_frfree( f ) ;
253 f = NULL ;
254 }
255 else if ( f->frametype == AST_FRAME_TEXT && member->does_text )
256 {
257 if ( strncmp(f->data, AST_CONF_CONTROL_CAMERA_DISABLED, strlen(AST_CONF_CONTROL_CAMERA_DISABLED)) == 0 )
258 {
259 ast_mutex_lock(&member->lock);
260 manager_event(EVENT_FLAG_CALL,
261 "ConferenceCameraDisabled",
262 "ConferenceName: %s\r\nChannel: %s\r\n",
263 conf->name,
264 member->channel_name);
265 member->no_camera = 1;
266 ast_mutex_unlock(&member->lock);
267 } else if ( strncmp(f->data, AST_CONF_CONTROL_CAMERA_ENABLED, strlen(AST_CONF_CONTROL_CAMERA_ENABLED)) == 0 )
268 {
269 ast_mutex_lock(&member->lock);
270 manager_event(EVENT_FLAG_CALL,
271 "ConferenceCameraEnabled",
272 "ConferenceName: %s\r\nChannel: %s\r\n",
273 conf->name,
274 member->channel_name);
275 member->no_camera = 0;
276 ast_mutex_unlock(&member->lock);
277 } else if ( strncmp(f->data, AST_CONF_CONTROL_STOP_VIDEO_TRANSMIT, strlen(AST_CONF_CONTROL_STOP_VIDEO_TRANSMIT)) == 0 )
278 {
279 ast_mutex_lock(&member->lock);
280 manager_event(EVENT_FLAG_CALL,
281 "ConferenceStopVideoTransmit",
282 "ConferenceName: %s\r\nChannel: %s\r\n",
283 conf->name,
284 member->channel_name);
285 member->norecv_video = 1;
286 ast_mutex_unlock(&member->lock);
287 } else if ( strncmp(f->data, AST_CONF_CONTROL_START_VIDEO_TRANSMIT, strlen(AST_CONF_CONTROL_START_VIDEO_TRANSMIT)) == 0 )
288 {
289 ast_mutex_lock(&member->lock);
290 manager_event(EVENT_FLAG_CALL,
291 "ConferenceStartVideoTransmit",
292 "ConferenceName: %s\r\nChannel: %s\r\n",
293 conf->name,
294 member->channel_name);
295 member->norecv_video = 0;
296 ast_mutex_unlock(&member->lock);
297 }
298 ast_frfree(f);
299 f = NULL;
300 } else
301 {
302 // undesirables
303 ast_frfree( f ) ;
304 f = NULL ;
305 }
306
307 return 0;
308 }
309
310 // get the next frame from the soundq; must be called with member locked.
311 static struct ast_frame *get_next_soundframe(struct ast_conf_member *member, struct ast_frame
312 *exampleframe) {
313 struct ast_frame *f;
314
315 again:
316 f=ast_readframe(member->soundq->stream);
317
318 if(!f) { // we're done with this sound; remove it from the queue, and try again
319 struct ast_conf_soundq *toboot = member->soundq;
320
321 ast_closestream(toboot->stream);
322 member->soundq = toboot->next;
323
324 //ast_log( LOG_WARNING, "finished playing a sound, next = %x\n", member->soundq);
325 // notify applications via mgr interface that this sound has been played
326 manager_event(
327 EVENT_FLAG_CALL,
328 "ConferenceSoundComplete",
329 "Channel: %s\r\n"
330 "Sound: %s\r\n",
331 member->channel_name,
332 toboot->name
333 );
334
335 free(toboot);
336 if(member->soundq) goto again;
337
338 // if we get here, we've gotten to the end of the queue; reset write format
339 if ( ast_set_write_format( member->chan, member->write_format ) < 0 )
340 {
341 ast_log( LOG_ERROR, "unable to set write format to %d\n",
342 member->write_format ) ;
343 }
344 } else {
345 // copy delivery from exampleframe
346 f->delivery = exampleframe->delivery;
347 }
348
349 return f;
350 }
351
352
353 // process outgoing frames for the channel, playing either normal conference audio,
354 // or requested sounds
355 static int process_outgoing(struct ast_conf_member *member)
356 {
357 conf_frame* cf ; // frame read from the output queue
358 struct ast_frame *f;
359 struct ast_frame *realframe = NULL;
360
361 for(;;)
362 {
363 // acquire member mutex and grab a frame.
364 ast_mutex_lock( &member->lock ) ;
365 cf = get_outgoing_frame( member ) ;
366
367 // if there's no frames exit the loop.
368 if ( !cf )
369 {
370 ast_mutex_unlock( &member->lock ) ;
371 break;
372 }
373
374
375 f = cf->fr;
376
377 // if we're playing sounds, we can just replace the frame with the
378 // next sound frame, and send it instead
379 if ( member->soundq )
380 {
381 realframe = f;
382 f = get_next_soundframe(member, f);
383 if ( !f )
384 {
385 // if we didn't get anything, just revert to "normal"
386 f = realframe;
387 realframe = NULL;
388 } else
389 {
390 // We have a sound frame now, but we need to make sure it's the same
391 // format as our channel write format
392 int wf = member->chan->writeformat & AST_FORMAT_AUDIO_MASK;
393 if ( f->frametype == AST_FRAME_VOICE && !(wf & f->subclass) )
394 {
395 // We need to change our channel's write format
396 ast_set_write_format(member->chan, f->subclass);
397 }
398 }
399 }
400
401 ast_mutex_unlock(&member->lock);
402
403
404 #ifdef DEBUG_FRAME_TIMESTAMPS
405 // !!! TESTING !!!
406 int delivery_diff = usecdiff( &f->delivery, &member->lastsent_timeval ) ;
407 if ( delivery_diff != AST_CONF_FRAME_INTERVAL )
408 {
409 ast_log( AST_CONF_DEBUG, "unanticipated delivery time, delivery_diff => %d, delivery.tv_usec => %ld\n",
410 delivery_diff, f->delivery.tv_usec ) ;
411 }
412
413 // !!! TESTING !!!
414 if (
415 f->delivery.tv_sec < member->lastsent_timeval.tv_sec
416 || (
417 f->delivery.tv_sec == member->lastsent_timeval.tv_sec
418 && f->delivery.tv_usec <= member->lastsent_timeval.tv_usec
419 )
420 )
421 {
422 ast_log( LOG_WARNING, "queued frame timestamped in the past, %ld.%ld <= %ld.%ld\n",
423 f->delivery.tv_sec, f->delivery.tv_usec,
424 member->lastsent_timeval.tv_sec, member->lastsent_timeval.tv_usec ) ;
425 }
426 member->lastsent_timeval = f->delivery ;
427 #endif
428
429 #ifdef DEBUG_USE_TIMELOG
430 TIMELOG( ast_write( member->chan, f ), 10, "member: ast_write");
431 #else
432
433 // send the voice frame
434 if ( ast_write( member->chan, f ) == 0 )
435 {
436 struct timeval tv = ast_tvnow();
437 ast_log( AST_CONF_DEBUG, "SENT VOICE FRAME, channel => %s, frames_out => %ld, s => %ld, ms => %ld\n",
438 member->channel_name, member->frames_out, tv.tv_sec, tv.tv_usec ) ;
439 }
440 else
441 {
442 // log 'dropped' outgoing frame
443 ast_log( LOG_ERROR, "unable to write voice frame to channel, channel => %s\n", member->channel_name ) ;
444
445 // accounting: count dropped outgoing frames
446 member->frames_out_dropped++ ;
447 }
448 #endif
449 // clean up frame
450 delete_conf_frame( cf ) ;
451
452 }
453
454 // Do the same for video, suck it dry
455 for(;;)
456 {
457 // grab a frame.
458 cf = get_outgoing_video_frame( member ) ;
459
460 // if there's no frames exit the loop.
461 if(!cf){
462 break;
463 }
464
465 f = cf->fr;
466
467 // send the video frame
468 if ( ast_write_video( member->chan, f ) == 1 )
469 {
470 struct timeval tv = ast_tvnow();
471 ast_log( AST_CONF_DEBUG, "SENT VIDEO FRAME, channel => %s, frames_out => %ld, s => %ld, ms => %ld\n",
472 member->channel_name, member->frames_out, tv.tv_sec, tv.tv_usec ) ;
473 }
474 else
475 {
476 // log 'dropped' outgoing frame
477 ast_log( AST_CONF_DEBUG, "unable to write video frame to channel, channel => %s\n", member->channel_name ) ;
478
479 // accounting: count dropped outgoing frames
480 member->video_frames_out_dropped++ ;
481 }
482
483 // clean up frame
484 delete_conf_frame( cf ) ;
485
486 }
487
488 // Do the same for dtmf, suck it dry
489 for(;;)
490 {
491 // acquire member mutex and grab a frame.
492 cf = get_outgoing_dtmf_frame( member ) ;
493
494 // if there's no frames exit the loop.
495 if(!cf) break;
496
497 // send the dtmf frame
498 if ( ast_write( member->chan, cf->fr ) == 0 )
499 {
500 struct timeval tv = ast_tvnow();
501 ast_log( AST_CONF_DEBUG, "SENT DTMF FRAME, channel => %s, frames_out => %ld, s => %ld, ms => %ld\n",
502 member->channel_name, member->frames_out, tv.tv_sec, tv.tv_usec ) ;
503
504 }
505 else
506 {
507 // log 'dropped' outgoing frame
508 ast_log( AST_CONF_DEBUG, "unable to write dtmf frame to channel, channel => %s\n", member->channel_name ) ;
509
510 // accounting: count dropped outgoing frames
511 member->dtmf_frames_out_dropped++ ;
512 }
513
514 // clean up frame
515 delete_conf_frame( cf ) ;
516 }
517
518 // Do the same for text, hell, why not?
519 for(;;)
520 {
521 // acquire member mutex and grab a frame.
522 cf = get_outgoing_text_frame( member ) ;
523
524 // if there's no frames exit the loop.
525 if(!cf) break;
526
527 // send the text frame
528 if ( ast_write( member->chan, cf->fr ) == 0 )
529 {
530 struct timeval tv = ast_tvnow();
531 ast_log( AST_CONF_DEBUG, "SENT TEXT FRAME, channel => %s, frames_out => %ld, s => %ld, ms => %ld\n",
532 member->channel_name, member->frames_out, tv.tv_sec, tv.tv_usec ) ;
533
534 }
535 else
536 {
537 // log 'dropped' outgoing frame
538 ast_log( AST_CONF_DEBUG, "unable to write text frame to channel, channel => %s\n", member->channel_name ) ;
539
540 // accounting: count dropped outgoing frames
541 member->text_frames_out_dropped++ ;
542 }
543
544 // clean up frame
545 delete_conf_frame( cf ) ;
546 }
547
548
549 return 0;
550 }
551
552 static int member_checkkick( struct ast_conf_member *member )
553 {
554 int kick;
555 ast_mutex_lock( &member->lock ) ;
556 kick = member->kick_flag;
557 ast_mutex_unlock( &member->lock ) ;
558 return kick;
559 }
560
561 //
562 // main member thread function
563 //
564
565 int member_exec( struct ast_channel* chan, void* data )
566 {
567 // struct timeval start, end ;
568 // start = ast_tvnow();
569
570 struct ast_conference *conf ;
571 struct ast_conf_member *member ;
572 struct ast_conf_member *tmp_member ;
573
574 struct ast_frame *f ; // frame received from ast_read()
575
576 int left = 0 ;
577 int res;
578
579 ast_log( AST_CONF_DEBUG, "Begin processing member thread, channel => %s\n", chan->name ) ;
580
581 //
582 // If the call has not yet been answered, answer the call
583 // Note: asterisk apps seem to check _state, but it seems like it's safe
584 // to just call ast_answer. It will just do nothing if it is up.
585 // it will also return -1 if the channel is a zombie, or has hung up.
586 //
587
588 res = ast_answer( chan ) ;
589 if ( res )
590 {
591 ast_log( LOG_ERROR, "unable to answer call\n" ) ;
592 return -1 ;
593 }
594
595 //
596 // create a new member for the conference
597 //
598
599 // ast_log( AST_CONF_DEBUG, "creating new member, id => %s, flags => %s, p => %s\n",
600 // id, flags, priority ) ;
601
602 member = create_member( chan, (const char*)( data ) ) ; // flags, atoi( priority ) ) ;
603
604 // unable to create member, return an error
605 if ( member == NULL )
606 {
607 ast_log( LOG_ERROR, "unable to create member\n" ) ;
608 return -1 ;
609 }
610
611 //
612 // setup asterisk read/write formats
613 //
614 #if 0
615 ast_log( AST_CONF_DEBUG, "CHANNEL INFO, CHANNEL => %s, DNID => %s, CALLER_ID => %s, ANI => %s\n",
616 chan->name, chan->dnid, chan->callerid, chan->ani ) ;
617
618 ast_log( AST_CONF_DEBUG, "CHANNEL CODECS, CHANNEL => %s, NATIVE => %d, READ => %d, WRITE => %d\n",
619 chan->name, chan->nativeformats, member->read_format, member->write_format ) ;
620 #endif
621 if ( ast_set_read_format( chan, member->read_format ) < 0 )
622 {
623 ast_log( LOG_ERROR, "unable to set read format to signed linear\n" ) ;
624 delete_member( member ) ;
625 return -1 ;
626 }
627
628 if ( ast_set_write_format( chan, member->write_format ) < 0 ) // AST_FORMAT_SLINEAR, chan->nativeformats
629 {
630 ast_log( LOG_ERROR, "unable to set write format to signed linear\n" ) ;
631 delete_member( member ) ;
632 return -1 ;
633 }
634
635 //
636 // setup a conference for the new member
637 //
638
639 conf = start_conference( member ) ;
640
641 if ( conf == NULL )
642 {
643 ast_log( LOG_ERROR, "unable to setup member conference\n" ) ;
644 delete_member( member) ;
645 return -1 ;
646 }
647
648
649 manager_event(
650 EVENT_FLAG_CALL,
651 "ConferenceJoin",
652 "ConferenceName: %s\r\n"
653 "Member: %d\r\n"
654 "Channel: %s\r\n"
655 "CallerID: %s\r\n"
656 "CallerIDName: %s\r\n"
657 "Count: %d\r\n",
658 conf->name,
659 member->id,
660 member->channel_name,
661 member->chan->cid.cid_num ? member->chan->cid.cid_num : "unknown",
662 member->chan->cid.cid_name ? member->chan->cid.cid_name: "unknown",
663 conf->membercount
664 ) ;
665
666 // Store the CID information
667 if ( member->chan->cid.cid_num )
668 {
669 if ( (member->callerid = malloc(strlen(member->chan->cid.cid_num)+1)) )
670 memcpy(member->callerid,member->chan->cid.cid_num, strlen(member->chan->cid.cid_num)+1);
671 } else
672 member->callerid = NULL;
673
674 if ( member->chan->cid.cid_name )
675 {
676 if ( (member->callername = malloc(strlen(member->chan->cid.cid_name)+1)) )
677 memcpy(member->callername, member->chan->cid.cid_name, strlen(member->chan->cid.cid_name)+1);
678 } else
679 member->callername = NULL;
680
681
682 //
683 // process loop for new member ( this runs in it's own thread )
684 //
685
686 ast_log( AST_CONF_DEBUG, "begin member event loop, channel => %s\n", chan->name ) ;
687
688 // timer timestamps
689 struct timeval base, curr ;
690 base = ast_tvnow();
691
692 // tell conference_exec we're ready for frames
693 member->ready_for_outgoing = 1 ;
694
695 // beep when someone arrive
696 tmp_member = conf->memberlist ;
697 while (tmp_member != NULL)
698 {
699 if ( tmp_member != member )
700 play_sound_channel( __LOG_DEBUG, tmp_member->channel_name, "appconf-enter", 0);
701 else if (conf->membercount < 2)
702 play_sound_channel( __LOG_DEBUG, tmp_member->channel_name, "conf-onlyperson", 0);
703 tmp_member = tmp_member->next;
704 }
705
706 while ( 42 == 42 )
707 {
708 // make sure we have a channel to process
709 if ( chan == NULL )
710 {
711 ast_log( LOG_NOTICE, "member channel has closed\n" ) ;
712 break ;
713 }
714
715 //-----------------//
716 // INCOMING FRAMES //
717 //-----------------//
718
719 // wait for an event on this channel
720 left = ast_waitfor( chan, AST_CONF_WAITFOR_LATENCY ) ;
721
722 //ast_log( AST_CONF_DEBUG, "received event on channel, name => %s, left => %d\n", chan->name, left ) ;
723
724 if ( left < 0 )
725 {
726 // an error occured
727 ast_log(
728 LOG_NOTICE,
729 "an error occured waiting for a frame, channel => %s, error => %d\n",
730 chan->name, left
731 ) ;
732 break; // out of the 42==42
733 }
734 else if ( left == 0 )
735 {
736 // no frame has arrived yet
737 // ast_log( LOG_NOTICE, "no frame available from channel, channel => %s\n", chan->name ) ;
738 }
739 else if ( left > 0 )
740 {
741 // a frame has come in before the latency timeout
742 // was reached, so we process the frame
743
744 f = ast_read( chan ) ;
745
746 if ( f == NULL )
747 {
748 if (conf->debug_flag)
749 {
750 ast_log( LOG_NOTICE, "unable to read from channel, channel => %s\n", chan->name ) ;
751 // They probably want to hangup...
752 }
753 break ;
754 }
755
756 // actually process the frame: break if we got hangup.
757 if(process_incoming(member, conf, f)) break;
758
759 }
760
761 if (member_checkkick(member)) break;
762
763 //-----------------//
764 // OUTGOING FRAMES //
765 //-----------------//
766
767 // update the current timestamps
768 curr = ast_tvnow();
769
770 process_outgoing(member);
771 // back to process incoming frames
772 continue ;
773 }
774
775 ast_log( AST_CONF_DEBUG, "end member event loop, time_entered => %ld\n", member->time_entered.tv_sec ) ;
776
777 //
778 // clean up
779 //
780
781 #ifdef DEBUG_OUTPUT_PCM
782 // !!! TESTING !!!
783 if ( incoming_fh != NULL )
784 fclose( incoming_fh ) ;
785 #endif
786
787 // If we're driving another member, make sure its speaker count is correct
788 if ( member != NULL ) member->remove_flag = 1 ;
789
790 // end = ast_tvnow();
791 // int expected_frames = ( int )( floor( (double)( msecdiff( &end, &start ) / AST_CONF_FRAME_INTERVAL ) ) ) ;
792 // ast_log( AST_CONF_DEBUG, "expected_frames => %d\n", expected_frames ) ;
793
794 return 0 ;
795 }
796
797
798
799 struct ast_conf_member *check_active_video( int id, struct ast_conference *conf )
800 {
801 struct ast_conf_member *member;
802
803 // acquire the conference lock
804 ast_mutex_lock( &conf->lock ) ;
805
806 member = conf->memberlist;
807 while (member)
808 {
809 if (member->id == id)
810 {
811 // lock this member
812 ast_mutex_lock( &member->lock ) ;
813 ast_mutex_unlock( &conf->lock ) ;
814 return member;
815 }
816 member = member->next;
817 }
818 ast_mutex_unlock( &conf->lock ) ;
819 return NULL;
820 }
821
822 //
823 // manange member functions
824 //
825
826 struct ast_conf_member* create_member( struct ast_channel *chan, const char* data )
827 {
828 //
829 // check input
830 //
831
832 if ( chan == NULL )
833 {
834 ast_log( LOG_ERROR, "unable to create member with null channel\n" ) ;
835 return NULL ;
836 }
837
838 if ( chan->name == NULL )
839 {
840 ast_log( LOG_ERROR, "unable to create member with null channel name\n" ) ;
841 return NULL ;
842 }
843
844 //
845 // allocate memory for new conference member
846 //
847
848 struct ast_conf_member *member = calloc( 1, sizeof( struct ast_conf_member ) ) ;
849
850 if ( member == NULL )
851 {
852 ast_log( LOG_ERROR, "unable to malloc ast_conf_member\n" ) ;
853 return NULL ;
854 }
855
856 // initialize mutex
857 ast_mutex_init( &member->lock ) ;
858
859 //
860 // initialize member with passed data values
861 //
862
863 char argstr[80] ;
864 char *stringp, *token ;
865
866 // copy the passed data
867 strncpy( argstr, data, sizeof(argstr) - 1 ) ;
868
869 // point to the copied data
870 stringp = argstr ;
871
872 ast_log( AST_CONF_DEBUG, "attempting to parse passed params, stringp => %s\n", stringp ) ;
873
874 // parse the id
875 if ( ( token = strsep( &stringp, "/" ) ) != NULL )
876 {
877 member->conf_name = malloc( strlen( token ) + 1 ) ;
878 strcpy( member->conf_name, token ) ;
879 }
880 else
881 {
882 ast_log( LOG_ERROR, "unable to parse member id\n" ) ;
883 free( member ) ;
884 return NULL ;
885 }
886
887 // parse the flags
888 if ( ( token = strsep( &stringp, "/" ) ) != NULL )
889 {
890 member->flags = malloc( strlen( token ) + 1 ) ;
891 strcpy( member->flags, token ) ;
892 }
893 else
894 {
895 // make member->flags something
896 member->flags = malloc( sizeof( char ) ) ;
897 memset( member->flags, 0x0, sizeof( char ) ) ;
898 }
899
900 // parse the priority
901 member->priority = ( token = strsep( &stringp, "/" ) ) != NULL
902 ? atoi( token )
903 : 0
904 ;
905
906 // parse the vad_prob_start
907 member->vad_prob_start = ( token = strsep( &stringp, "/" ) ) != NULL
908 ? atof( token )
909 : AST_CONF_PROB_START
910 ;
911
912 // parse the vad_prob_continue
913 member->vad_prob_continue = ( token = strsep( &stringp, "/" ) ) != NULL
914 ? atof( token )
915 : AST_CONF_PROB_CONTINUE
916 ;
917
918 // debugging
919 ast_log(
920 AST_CONF_DEBUG,
921 "parsed data params, id => %s, flags => %s, priority => %d, vad_prob_start => %f, vad_prob_continue => %f\n",
922 member->conf_name, member->flags, member->priority, member->vad_prob_start, member->vad_prob_continue
923 ) ;
924
925 //
926 // initialize member with default values
927 //
928
929 // keep pointer to member's channel
930 member->chan = chan ;
931
932 // copy the channel name
933 member->channel_name = malloc( strlen( chan->name ) + 1 ) ;
934 strcpy( member->channel_name, chan->name ) ;
935
936 // ( default can be overridden by passed flags )
937 member->mute_audio = 0;
938 member->mute_video = 0;
939 member->norecv_audio = 0;
940 member->norecv_video = 0;
941 member->no_camera = 0;
942
943 // moderator?
944 member->ismoderator = 0;
945
946 // ready flag
947 member->ready_for_outgoing = 0 ;
948
949 // incoming frame queue
950 member->inFrames = NULL ;
951 member->inFramesTail = NULL ;
952 member->inFramesCount = 0 ;
953
954 member->inVideoFrames = NULL ;
955 member->inVideoFramesTail = NULL ;
956 member->inVideoFramesCount = 0 ;
957
958 member->inDTMFFrames = NULL ;
959 member->inDTMFFramesTail = NULL ;
960 member->inDTMFFramesCount = 0 ;
961
962 member->inTextFrames = NULL ;
963 member->inTextFramesTail = NULL ;
964 member->inTextFramesCount = 0 ;
965
966 member->conference = 1; // we have switched req_id
967 member->dtmf_switch = 0; // no dtmf switch by default
968 member->dtmf_relay = 0; // no dtmf relay by default
969
970 // start of day video ids
971 member->req_id = -1;
972 member->id = -1;
973
974 member->first_frame_received = 0; // cause a FIR after NAT delay
975
976 // last frame caching
977 member->inFramesRepeatLast = 0 ;
978 member->inFramesLast = NULL ;
979 member->okayToCacheLast = 0 ;
980
981 // outgoing frame queue
982 member->outFrames = NULL ;
983 member->outFramesTail = NULL ;
984 member->outFramesCount = 0 ;
985
986 member->outVideoFrames = NULL ;
987 member->outVideoFramesTail = NULL ;
988 member->outVideoFramesCount = 0 ;
989
990 member->outDTMFFrames = NULL ;
991 member->outDTMFFramesTail = NULL ;
992 member->outDTMFFramesCount = 0 ;
993
994 member->outTextFrames = NULL ;
995 member->outTextFramesTail = NULL ;
996 member->outTextFramesCount = 0 ;
997
998 // ( not currently used )
999 // member->samplesperframe = AST_CONF_BLOCK_SAMPLES ;
1000
1001 // used for determining need to mix frames
1002 // and for management interface notification
1003 // and for VAD based video switching
1004 member->speaking_state_notify = 0 ;
1005 member->speaking_state = 0 ;
1006 member->local_speaking_state = 0;
1007 member->speaker_count = 0;
1008 member->driven_member = NULL;
1009
1010 // linked-list pointer
1011 member->next = NULL ;
1012
1013 // account data
1014 member->frames_in = 0 ;
1015 member->frames_in_dropped = 0 ;
1016 member->frames_out = 0 ;
1017 member->frames_out_dropped = 0 ;
1018 member->video_frames_in = 0 ;
1019 member->video_frames_in_dropped = 0 ;
1020 member->video_frames_out = 0 ;
1021 member->video_frames_out_dropped = 0 ;
1022 member->dtmf_frames_in = 0 ;
1023 member->dtmf_frames_in_dropped = 0 ;
1024 member->dtmf_frames_out = 0 ;
1025 member->dtmf_frames_out_dropped = 0 ;
1026 member->text_frames_in = 0 ;
1027 member->text_frames_in_dropped = 0 ;
1028 member->text_frames_out = 0 ;
1029 member->text_frames_out_dropped = 0 ;
1030
1031 // for counting sequentially dropped frames
1032 member->sequential_drops = 0 ;
1033 member->since_dropped = 0 ;
1034
1035 // flags
1036 member->remove_flag = 0 ;
1037 member->kick_flag = 0;
1038
1039 // record start time
1040 // init dropped frame timestamps
1041 // init state change timestamp
1042 member->time_entered =
1043 member->last_in_dropped =
1044 member->last_out_dropped =
1045 member->last_state_change = ast_tvnow();
1046
1047 //
1048 // parse passed flags
1049 //
1050
1051 // silence detection flags w/ defaults
1052 member->vad_flag = 0 ;
1053 member->denoise_flag = 0 ;
1054 member->agc_flag = 0 ;
1055
1056 // is this member using the telephone?
1057 member->via_telephone = 0 ;
1058
1059 // temp pointer to flags string
1060 char* flags = member->flags ;
1061
1062 int i;
1063
1064 for ( i = 0 ; i < strlen( flags ) ; ++i )
1065 {
1066
1067 if (flags[i] >= (int)'0' && flags[i] <= (int)'9')
1068 {
1069 if (member->req_id < 0)
1070 {
1071 member->req_id = flags[i] - (int)'0';
1072 }
1073 else
1074 {
1075 int newid = flags[i] - (int)'0';
1076 // need to boot anyone with this id already
1077 // will happen in add_member
1078 member->id = newid;
1079 }
1080 }
1081 else
1082 {
1083 // allowed flags are C, c, L, l, V, D, A, C, X, R, T, t, M, S
1084 // mute/no_recv options
1085 switch ( flags[i] )
1086 {
1087 case 'C':
1088 member->mute_video = 1;
1089 break ;
1090 case 'c':
1091 member->norecv_video = 1;
1092 break ;
1093 case 'L':
1094 member->mute_audio = 1;
1095 break ;
1096 case 'l':
1097 member->norecv_audio = 1;
1098 break;
1099
1100 // speex preprocessing options
1101 case 'V':
1102 member->vad_flag = 1 ;
1103 break ;
1104 case 'D':
1105 member->denoise_flag = 1 ;
1106 break ;
1107 case 'A':
1108 member->agc_flag = 1 ;
1109 break ;
1110
1111 // dtmf/moderator/video switching options
1112 case 'X':
1113 member->dtmf_switch = 1;
1114 break;
1115 case 'R':
1116 member->dtmf_relay = 1;
1117 break;
1118 case 'S':
1119 member->vad_switch = 1;
1120 break;
1121 case 'M':
1122 member->ismoderator = 1;
1123 break;
1124 case 'N':
1125 member->no_camera = 1;
1126 break;
1127 case 't':
1128 member->does_text = 1;
1129 break;
1130
1131 //Telephone connection
1132 case 'T':
1133 member->via_telephone = 1;
1134 break;
1135
1136 default:
1137 ast_log( LOG_WARNING, "received invalid flag, chan => %s, flag => %c\n",
1138 chan->name, flags[i] );
1139 break ;
1140 }
1141 }
1142 }
1143
1144 // set the dsp to null so silence detection is disabled by default
1145 member->dsp = NULL ;
1146
1147 #if ( SILDET == 2 )
1148 //
1149 // configure silence detection and preprocessing
1150 // if the user is coming in via the telephone,
1151 // and is not listen-only
1152 //
1153 if (
1154 member->via_telephone == 1
1155 && member->type != 'L'
1156 )
1157 {
1158 // create a speex preprocessor
1159 member->dsp = speex_preprocess_state_init( AST_CONF_BLOCK_SAMPLES, AST_CONF_SAMPLE_RATE ) ;
1160
1161 if ( member->dsp == NULL )
1162 {
1163 ast_log( LOG_WARNING, "unable to initialize member dsp, channel => %s\n", chan->name ) ;
1164 }
1165 else
1166 {
1167 ast_log( LOG_NOTICE, "member dsp initialized, channel => %s, v => %d, d => %d, a => %d\n",
1168 chan->name, member->vad_flag, member->denoise_flag, member->agc_flag ) ;
1169
1170 // set speex preprocessor options
1171 speex_preprocess_ctl( member->dsp, SPEEX_PREPROCESS_SET_VAD, &(member->vad_flag) ) ;
1172 speex_preprocess_ctl( member->dsp, SPEEX_PREPROCESS_SET_DENOISE, &(member->denoise_flag) ) ;
1173 speex_preprocess_ctl( member->dsp, SPEEX_PREPROCESS_SET_AGC, &(member->agc_flag) ) ;
1174
1175 speex_preprocess_ctl( member->dsp, SPEEX_PREPROCESS_SET_PROB_START, &member->vad_prob_start ) ;
1176 speex_preprocess_ctl( member->dsp, SPEEX_PREPROCESS_SET_PROB_CONTINUE, &member->vad_prob_continue ) ;
1177
1178 ast_log( AST_CONF_DEBUG, "speech_prob_start => %f, speech_prob_continue => %f\n",
1179 member->dsp->speech_prob_start, member->dsp->speech_prob_continue ) ;
1180 }
1181 }
1182 #endif
1183
1184 //
1185 // set connection type
1186 //
1187
1188 if ( member->via_telephone == 1 )
1189 {
1190 member->connection_type = 'T' ;
1191 }
1192 else if ( strncmp( member->channel_name, "SIP", 3 ) == 0 )
1193 {
1194 member->connection_type = 'S' ;
1195 }
1196 else // default to iax
1197 {
1198 member->connection_type = 'X' ;
1199 }
1200
1201 //
1202 // read, write, and translation options
1203 //
1204
1205 // set member's audio formats, taking dsp preprocessing into account
1206 // ( chan->nativeformats, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FORMAT_GSM )
1207 member->read_format = ( member->dsp == NULL ) ? chan->nativeformats : AST_FORMAT_SLINEAR ;
1208
1209 member->write_format = chan->nativeformats;
1210
1211 // 1.2 or 1.3+
1212 #ifdef AST_FORMAT_AUDIO_MASK
1213
1214 member->read_format &= AST_FORMAT_AUDIO_MASK;
1215 member->write_format &= AST_FORMAT_AUDIO_MASK;
1216 #endif
1217
1218 // translation paths ( ast_translator_build_path() returns null if formats match )
1219 member->to_slinear = ast_translator_build_path( AST_FORMAT_SLINEAR, member->read_format ) ;
1220 member->from_slinear = ast_translator_build_path( member->write_format, AST_FORMAT_SLINEAR ) ;
1221
1222 ast_log( AST_CONF_DEBUG, "AST_FORMAT_SLINEAR => %d\n", AST_FORMAT_SLINEAR ) ;
1223
1224 // index for converted_frames array
1225 switch ( member->write_format )
1226 {
1227 case AST_FORMAT_SLINEAR:
1228 member->write_format_index = AC_SLINEAR_INDEX ;
1229 break ;
1230
1231 case AST_FORMAT_ULAW:
1232 member->write_format_index = AC_ULAW_INDEX ;
1233 break ;
1234
1235 case AST_FORMAT_ALAW:
1236 member->write_format_index = AC_ALAW_INDEX ;
1237 break ;
1238
1239 case AST_FORMAT_GSM:
1240 member->write_format_index = AC_GSM_INDEX ;
1241 break ;
1242
1243 case AST_FORMAT_SPEEX:
1244 member->write_format_index = AC_SPEEX_INDEX;
1245 break;
1246
1247 #ifdef AC_USE_G729A
1248 case AST_FORMAT_G729A:
1249 member->write_format_index = AC_G729A_INDEX;
1250 break;
1251 #endif
1252
1253 default:
1254 member->write_format_index = 0 ;
1255 }
1256
1257 // index for converted_frames array
1258 switch ( member->read_format )
1259 {
1260 case AST_FORMAT_SLINEAR:
1261 member->read_format_index = AC_SLINEAR_INDEX ;
1262 break ;
1263
1264 case AST_FORMAT_ULAW:
1265 member->read_format_index = AC_ULAW_INDEX ;
1266 break ;
1267
1268 case AST_FORMAT_ALAW:
1269 member->read_format_index = AC_ALAW_INDEX ;
1270 break ;
1271
1272 case AST_FORMAT_GSM:
1273 member->read_format_index = AC_GSM_INDEX ;
1274 break ;
1275
1276 case AST_FORMAT_SPEEX:
1277 member->read_format_index = AC_SPEEX_INDEX;
1278 break;
1279
1280 #ifdef AC_USE_G729A
1281 case AST_FORMAT_G729A:
1282 member->read_format_index = AC_G729A_INDEX;
1283 break;
1284 #endif
1285
1286 default:
1287 member->read_format_index = 0 ;
1288 }
1289
1290 // smoother defaults.
1291 member->smooth_multiple =1;
1292 member->smooth_size_in = -1;
1293 member->smooth_size_out = -1;
1294 member->inSmoother= NULL;
1295 member->outPacker= NULL;
1296
1297 switch (member->read_format){
1298 /* these assumptions may be incorrect */
1299 case AST_FORMAT_ULAW:
1300 case AST_FORMAT_ALAW:
1301 member->smooth_size_in = 160; //bytes
1302 member->smooth_size_out = 160; //samples
1303 break;
1304 case AST_FORMAT_GSM:
1305 /*
1306 member->smooth_size_in = 33; //bytes
1307 member->smooth_size_out = 160;//samples
1308 */
1309 break;
1310 case AST_FORMAT_SPEEX:
1311 case AST_FORMAT_G729A:
1312 /* this assumptions are wrong
1313 member->smooth_multiple = 2 ; // for testing, force to dual frame
1314 member->smooth_size_in = 39; // bytes
1315 member->smooth_size_out = 160; // samples
1316 */
1317 break;
1318 case AST_FORMAT_SLINEAR:
1319 member->smooth_size_in = 320; //bytes
1320 member->smooth_size_out = 160; //samples
1321 break;
1322 default:
1323 member->inSmoother = NULL; //don't use smoother for this type.
1324 //ast_log( AST_CONF_DEBUG, "smoother is NULL for member->read_format => %d\n", member->read_format);
1325 }
1326
1327 if (member->smooth_size_in > 0){
1328 member->inSmoother = ast_smoother_new(member->smooth_size_in);
1329 ast_log( AST_CONF_DEBUG, "created smoother(%d) for %d\n", member->smooth_size_in , member->read_format);
1330 }
1331
1332 //
1333 // finish up
1334 //
1335
1336 ast_log( AST_CONF_DEBUG, "created member, type => %c, priority => %d, readformat => %d\n",
1337 member->type, member->priority, chan->readformat ) ;
1338
1339 return member ;
1340 }
1341
1342 struct ast_conf_member* delete_member( struct ast_conf_member* member )
1343 {
1344 // !!! NO RETURN TEST !!!
1345 // do { sleep(1) ; } while (1) ;
1346
1347 // !!! CRASH TEST !!!
1348 // *((int *)0) = 0;
1349
1350 if ( member == NULL )
1351 {
1352 ast_log( LOG_WARNING, "unable to the delete null member\n" ) ;
1353 return NULL ;
1354 }
1355
1356 ast_mutex_lock(&member->lock);
1357
1358 // If member is driving another member, make sure its speaker count is correct
1359 if ( member->driven_member != NULL && member->speaking_state == 1 )
1360 decrement_speaker_count(member->driven_member, 1);
1361
1362 //
1363 // clean up member flags
1364 //
1365
1366 if ( member->flags != NULL )
1367 {
1368 // !!! DEBUGING !!!
1369 ast_log( AST_CONF_DEBUG, "freeing member flags, name => %s\n",
1370 member->channel_name ) ;
1371 free( member->flags ) ;
1372 }
1373
1374 //
1375 // delete the members frames
1376 //
1377
1378 conf_frame* cf ;
1379
1380 // !!! DEBUGING !!!
1381 ast_log( AST_CONF_DEBUG, "deleting member input frames, name => %s\n",
1382 member->channel_name ) ;
1383
1384 // incoming frames
1385 cf = member->inFrames ;
1386
1387 while ( cf != NULL )
1388 {
1389 cf = delete_conf_frame( cf ) ;
1390 }
1391
1392 if (member->inSmoother != NULL)
1393 ast_smoother_free(member->inSmoother);
1394
1395 cf = member->inVideoFrames ;
1396
1397 while ( cf != NULL )
1398 {
1399 cf = delete_conf_frame( cf ) ;
1400 }
1401
1402 // !!! DEBUGING !!!
1403 ast_log( AST_CONF_DEBUG, "deleting member output frames, name => %s\n",
1404 member->channel_name ) ;
1405
1406 // outgoing frames
1407 cf = member->outFrames ;
1408
1409 while ( cf != NULL )
1410 {
1411 cf = delete_conf_frame( cf ) ;
1412 }
1413
1414 cf = member->outVideoFrames ;
1415
1416 while ( cf != NULL )
1417 {
1418 cf = delete_conf_frame( cf ) ;
1419 }
1420
1421 #if ( SILDET == 2 )
1422 if ( member->dsp != NULL )
1423 {
1424 // !!! DEBUGING !!!
1425 ast_log( AST_CONF_DEBUG, "destroying member preprocessor, name => %s\n",
1426 member->channel_name ) ;
1427 speex_preprocess_state_destroy( member->dsp ) ;
1428 }
1429 #endif
1430
1431 // !!! DEBUGING !!!
1432 ast_log( AST_CONF_DEBUG, "freeing member translator paths, name => %s\n",
1433 member->channel_name ) ;
1434
1435 // free the mixing translators
1436 ast_translator_free_path( member->to_slinear ) ;
1437 ast_translator_free_path( member->from_slinear ) ;
1438
1439 // get a pointer to the next
1440 // member so we can return it
1441 struct ast_conf_member* nm = member->next ;
1442
1443 ast_mutex_unlock(&member->lock);
1444
1445 // !!! DEBUGING !!!
1446 ast_log( AST_CONF_DEBUG, "freeing member channel name, name => %s\n",
1447 member->channel_name ) ;
1448
1449 // free the member's copy for the channel name
1450 free( member->channel_name ) ;
1451
1452 // free the member's copy of the conference name
1453 free(member->conf_name);
1454
1455 // !!! DEBUGING !!!
1456 ast_log( AST_CONF_DEBUG, "freeing member\n" ) ;
1457
1458 // free the member's memory
1459 free(member->callerid);
1460 free(member->callername);
1461
1462 free( member ) ;
1463 member = NULL ;
1464
1465 return nm ;
1466 }
1467
1468 //
1469 // incoming frame functions
1470 //
1471
1472 conf_frame* get_incoming_video_frame( struct ast_conf_member *member )
1473 {
1474 if ( member == NULL )
1475 {
1476 ast_log( LOG_WARNING, "unable to get frame from null member\n" ) ;
1477 return NULL ;
1478 }
1479
1480 ast_mutex_lock(&member->lock);
1481
1482 if ( member->inVideoFramesCount == 0 )
1483 {
1484 ast_mutex_unlock(&member->lock);
1485 return NULL ;
1486 }
1487
1488 //
1489 // return the next frame in the queue
1490 //
1491
1492 conf_frame* cfr = NULL ;
1493
1494 // get first frame in line
1495 cfr = member->inVideoFramesTail ;
1496
1497 // if it's the only frame, reset the queue,
1498 // else, move the second frame to the front
1499 if ( member->inVideoFramesTail == member->inVideoFrames )
1500 {
1501 member->inVideoFramesTail = NULL ;
1502 member->inVideoFrames = NULL ;
1503 }
1504 else
1505 {
1506 // move the pointer to the next frame
1507 member->inVideoFramesTail = member->inVideoFramesTail->prev ;
1508
1509 // reset it's 'next' pointer
1510 if ( member->inVideoFramesTail != NULL )
1511 member->inVideoFramesTail->next = NULL ;
1512 }
1513
1514 // separate the conf frame from the list
1515 cfr->next = NULL ;
1516 cfr->prev = NULL ;
1517
1518 // decrement frame count
1519 member->inVideoFramesCount-- ;
1520
1521 ast_mutex_unlock(&member->lock);
1522 return cfr ;
1523
1524 }
1525 conf_frame* get_incoming_dtmf_frame( struct ast_conf_member *member )
1526 {
1527 if ( member == NULL )
1528 {
1529 ast_log( LOG_WARNING, "unable to get frame from null member\n" ) ;
1530 return NULL ;
1531 }
1532
1533 ast_mutex_lock(&member->lock);
1534
1535 if ( member->inDTMFFramesCount == 0 )
1536 {
1537 ast_mutex_unlock(&member->lock);
1538 return NULL ;
1539 }
1540
1541 //
1542 // return the next frame in the queue
1543 //
1544
1545 conf_frame* cfr = NULL ;
1546
1547 // get first frame in line
1548 cfr = member->inDTMFFramesTail ;
1549
1550 // if it's the only frame, reset the queue,
1551 // else, move the second frame to the front
1552 if ( member->inDTMFFramesTail == member->inDTMFFrames )
1553 {
1554 member->inDTMFFramesTail = NULL ;
1555 member->inDTMFFrames = NULL ;
1556 }
1557 else
1558 {
1559 // move the pointer to the next frame
1560 member->inDTMFFramesTail = member->inDTMFFramesTail->prev ;
1561
1562 // reset it's 'next' pointer
1563 if ( member->inDTMFFramesTail != NULL )
1564 member->inDTMFFramesTail->next = NULL ;
1565 }
1566
1567 // separate the conf frame from the list
1568 cfr->next = NULL ;
1569 cfr->prev = NULL ;
1570
1571 // decriment frame count
1572 member->inDTMFFramesCount-- ;
1573
1574 ast_mutex_unlock(&member->lock);
1575 return cfr ;
1576
1577 }
1578
1579
1580 conf_frame* get_incoming_frame( struct ast_conf_member *member )
1581 {
1582 conf_frame *cf_result;
1583 //
1584 // sanity checks
1585 //
1586
1587 if ( member == NULL )
1588 {
1589 ast_log( LOG_WARNING, "unable to get frame from null member\n" ) ;
1590 return NULL ;
1591 }
1592
1593 ast_mutex_lock(&member->lock);
1594
1595 //
1596 // repeat last frame a couple times to smooth transition
1597 //
1598
1599 #ifdef AST_CONF_CACHE_LAST_FRAME
1600 if ( member->inFramesCount == 0 )
1601 {
1602 // nothing to do if there's no cached frame
1603 if ( member->inFramesLast == NULL ) {
1604 ast_mutex_unlock(&member->lock);
1605 return NULL ;
1606 }
1607
1608 // turn off 'okay to cache' flag
1609 member->okayToCacheLast = 0 ;
1610
1611 if ( member->inFramesRepeatLast >= AST_CONF_CACHE_LAST_FRAME )
1612 {
1613 // already used this frame AST_CONF_CACHE_LAST_FRAME times
1614
1615 // reset repeat count
1616 member->inFramesRepeatLast = 0 ;
1617
1618 // clear the cached frame
1619 delete_conf_frame( member->inFramesLast ) ;
1620 member->inFramesLast = NULL ;
1621
1622 // return null
1623 ast_mutex_unlock(&member->lock);
1624 return NULL ;
1625 }
1626 else
1627 {
1628 ast_log( AST_CONF_DEBUG, "repeating cached frame, channel => %s, inFramesRepeatLast => %d\n",
1629 member->channel_name, member->inFramesRepeatLast ) ;
1630
1631 // increment counter
1632 member->inFramesRepeatLast++ ;
1633
1634 // return a copy of the cached frame
1635 cf_result = copy_conf_frame( member->inFramesLast ) ;
1636 ast_mutex_unlock(&member->lock);
1637 return cf_result;
1638 }
1639 }
1640 else if ( member->okayToCacheLast == 0 && member->inFramesCount >= 3 )
1641 {
1642 ast_log( AST_CONF_DEBUG, "enabling cached frame, channel => %s, incoming => %d, outgoing => %d\n",
1643 member->channel_name, member->inFramesCount, member->outFramesCount ) ;
1644
1645 // turn on 'okay to cache' flag
1646 member->okayToCacheLast = 1 ;
1647 }
1648 #else
1649 if ( member->inFramesCount == 0 ) {
1650 ast_mutex_unlock(&member->lock);
1651 return NULL ;
1652 }
1653 #endif // AST_CONF_CACHE_LAST_FRAME
1654
1655 //
1656 // return the next frame in the queue
1657 //
1658
1659 conf_frame* cfr = NULL ;
1660
1661 // get first frame in line
1662 cfr = member->inFramesTail ;
1663
1664 // if it's the only frame, reset the queue,
1665 // else, move the second frame to the front
1666 if ( member->inFramesTail == member->inFrames )
1667 {
1668 member->inFramesTail = NULL ;
1669 member->inFrames = NULL ;
1670 }
1671 else
1672 {
1673 // move the pointer to the next frame
1674 member->inFramesTail = member->inFramesTail->prev ;
1675
1676 // reset it's 'next' pointer
1677 if ( member->inFramesTail != NULL )
1678 member->inFramesTail->next = NULL ;
1679 }
1680
1681 // separate the conf frame from the list
1682 cfr->next = NULL ;
1683 cfr->prev = NULL ;
1684
1685 // decriment frame count
1686 member->inFramesCount-- ;
1687
1688 #ifdef AST_CONF_CACHE_LAST_FRAME
1689 // copy frame if queue is now empty
1690 if (
1691 member->inFramesCount == 0
1692 && member->okayToCacheLast == 1
1693 )
1694 {
1695 // reset repeat count
1696 member->inFramesRepeatLast = 0 ;
1697
1698 // clear cached frame
1699 if ( member->inFramesLast != NULL )
1700 {
1701 delete_conf_frame( member->inFramesLast ) ;
1702 member->inFramesLast = NULL ;
1703 }
1704
1705 // cache new frame
1706 member->inFramesLast = copy_conf_frame( cfr ) ;
1707 }
1708 #endif // AST_CONF_CACHE_LAST_FRAME
1709
1710 ast_mutex_unlock(&member->lock);
1711 return cfr ;
1712 }
1713
1714 int queue_incoming_video_frame( struct ast_conf_member* member, const struct ast_frame* fr )
1715 {
1716 // check on frame
1717 if ( fr == NULL )
1718 {
1719 ast_log( LOG_ERROR, "unable to queue null frame\n" ) ;
1720 return -1 ;
1721 }
1722
1723 // check on member
1724 if ( member == NULL )
1725 {
1726 ast_log( LOG_ERROR, "unable to queue frame for null member\n" ) ;
1727 return -1 ;
1728 }
1729
1730 // lock the member
1731 ast_mutex_lock(&member->lock);
1732
1733 if (!member->first_frame_received)
1734 {
1735 // nat=yes will be correct now
1736 member->first_frame_received = 1;
1737 member->conference = 1;
1738 }
1739
1740 // We have to drop if the queue is full!
1741 if ( member->inVideoFramesCount >= AST_CONF_MAX_VIDEO_QUEUE )
1742 {
1743 ast_log(
1744 AST_CONF_DEBUG,
1745 "unable to queue incoming VIDEO frame, channel => %s, incoming => %d, outgoing => %d\n",
1746 member->channel_name, member->inVideoFramesCount, member->outVideoFramesCount
1747 ) ;
1748 ast_mutex_unlock(&member->lock);
1749 return -1 ;
1750 }
1751
1752 //
1753 // create new conf frame from passed data frame
1754 //
1755
1756 // ( member->inFrames may be null at this point )
1757 conf_frame* cfr = create_conf_frame( member, member->inVideoFrames, fr ) ;
1758
1759 if ( cfr == NULL )
1760 {
1761 ast_log( LOG_ERROR, "unable to malloc conf_frame\n" ) ;
1762 ast_mutex_unlock(&member->lock);
1763 return -1 ;
1764 }
1765
1766 // copy frame data pointer to conf frame
1767 // cfr->fr = fr ;
1768
1769 //
1770 // add new frame to speaking members incoming frame queue
1771 // ( i.e. save this frame data, so we can distribute it in conference_exec later )
1772 //
1773
1774 if ( member->inVideoFrames == NULL )
1775 {
1776 // this is the first frame in the buffer
1777 member->inVideoFramesTail = cfr ;
1778 member->inVideoFrames = cfr ;
1779 }
1780 else
1781 {
1782 // put the new frame at the head of the list
1783 member->inVideoFrames = cfr ;
1784 }
1785
1786 // increment member frame count
1787 member->inVideoFramesCount++ ;
1788
1789 ast_mutex_unlock(&member->lock);
1790
1791 // Everything has gone okay!
1792 return 0;
1793 }
1794
1795 int queue_incoming_dtmf_frame( struct ast_conf_member* member, const struct ast_frame* fr )
1796 {
1797 //ast_log( AST_CONF_DEBUG, "queue incoming video frame\n");
1798
1799 // check on frame
1800 if ( fr == NULL )
1801 {
1802 ast_log( LOG_ERROR, "unable to queue null frame\n" ) ;
1803 return -1 ;
1804 }
1805
1806 // check on member
1807 if ( member == NULL )
1808 {
1809 ast_log( LOG_ERROR, "unable to queue frame for null member\n" ) ;
1810 return -1 ;
1811 }
1812
1813 ast_mutex_lock(&member->lock);
1814
1815 // We have to drop if the queue is full!
1816 if ( member->inDTMFFramesCount >= AST_CONF_MAX_DTMF_QUEUE )
1817 {
1818 ast_log(
1819 AST_CONF_DEBUG,
1820 "unable to queue incoming DTMF frame, channel => %s, incoming => %d, outgoing => %d\n",
1821 member->channel_name, member->inDTMFFramesCount, member->outDTMFFramesCount
1822 ) ;
1823 ast_mutex_unlock(&member->lock);
1824 return -1 ;
1825 }
1826
1827 //
1828 // create new conf frame from passed data frame
1829 //
1830
1831 // ( member->inFrames may be null at this point )
1832 conf_frame* cfr = create_conf_frame( member, member->inDTMFFrames, fr ) ;
1833
1834 if ( cfr == NULL )
1835 {
1836 ast_log( LOG_ERROR, "unable to malloc conf_frame\n" ) ;
1837 ast_mutex_unlock(&member->lock);
1838 return -1 ;
1839 }
1840
1841 // copy frame data pointer to conf frame
1842 // cfr->fr = fr ;
1843
1844 //
1845 // add new frame to speaking members incoming frame queue
1846 // ( i.e. save this frame data, so we can distribute it in conference_exec later )
1847 //
1848
1849 if ( member->inDTMFFrames == NULL )
1850 {
1851 // this is the first frame in the buffer
1852 member->inDTMFFramesTail = cfr ;
1853 member->inDTMFFrames = cfr ;
1854 }
1855 else
1856 {
1857 // put the new frame at the head of the list
1858 member->inDTMFFrames = cfr ;
1859 }
1860
1861 // increment member frame count
1862 member->inDTMFFramesCount++ ;
1863
1864 ast_mutex_unlock(&member->lock);
1865
1866 // Everything has gone okay!
1867 return 0;
1868 }
1869
1870 int queue_incoming_frame( struct ast_conf_member* member, struct ast_frame* fr )
1871 {
1872 //
1873 // sanity checks
1874 //
1875
1876 // check on frame
1877 if ( fr == NULL )
1878 {
1879 ast_log( LOG_ERROR, "unable to queue null frame\n" ) ;
1880 return -1 ;
1881 }
1882
1883 // check on member
1884 if ( member == NULL )
1885 {
1886 ast_log( LOG_ERROR, "unable to queue frame for null member\n" ) ;
1887 return -1 ;
1888 }
1889
1890 ast_mutex_lock(&member->lock);
1891
1892 if ( member->inFramesCount > member->inFramesNeeded )
1893 {
1894 if ( member->inFramesCount > AST_CONF_QUEUE_DROP_THRESHOLD )
1895 {
1896 struct timeval curr = ast_tvnow();
1897
1898 // time since last dropped frame
1899 long diff = ast_tvdiff_ms(curr, member->last_in_dropped);
1900
1901 // number of milliseconds which must pass between frame drops
1902 // ( 15 frames => -100ms, 10 frames => 400ms, 5 frames => 900ms, 0 frames => 1400ms, etc. )
1903 long time_limit = 1000 - ( ( member->inFramesCount - AST_CONF_QUEUE_DROP_THRESHOLD ) * 100 ) ;
1904
1905 if ( diff >= time_limit )
1906 {
1907 // count sequential drops
1908 member->sequential_drops++ ;
1909
1910 ast_log(
1911 AST_CONF_DEBUG,
1912 "dropping frame from input buffer, channel => %s, incoming => %d, outgoing => %d\n",
1913 member->channel_name, member->inFramesCount, member->outFramesCount
1914 ) ;
1915
1916 // accounting: count dropped incoming frames
1917 member->frames_in_dropped++ ;
1918
1919 // reset frames since dropped
1920 member->since_dropped = 0 ;
1921
1922 // delete the frame
1923 delete_conf_frame( get_incoming_frame( member ) ) ;
1924
1925 member->last_in_dropped = ast_tvnow();
1926 }
1927 else
1928 {
1929 /*
1930 ast_log(
1931 AST_CONF_DEBUG,
1932 "input buffer larger than drop threshold, channel => %s, incoming => %d, outgoing => %d\n",
1933 member->channel_name, member->inFramesCount, member->outFramesCount
1934 ) ;
1935 */
1936 }
1937 }
1938 }
1939
1940 //
1941 // if we have to drop frames, we'll drop new frames
1942 // because it's easier ( and doesn't matter much anyway ).
1943 //
1944
1945 if ( member->inFramesCount >= AST_CONF_MAX_QUEUE )
1946 {
1947 // count sequential drops
1948 member->sequential_drops++ ;
1949
1950 ast_log(
1951 AST_CONF_DEBUG,
1952 "unable to queue incoming frame, channel => %s, incoming => %d, outgoing => %d\n",
1953 member->channel_name, member->inFramesCount, member->outFramesCount
1954 ) ;
1955
1956 // accounting: count dropped incoming frames
1957 member->frames_in_dropped++ ;
1958
1959 // reset frames since dropped
1960 member->since_dropped = 0 ;
1961
1962 ast_mutex_unlock(&member->lock);
1963 return -1 ;
1964 }
1965
1966 // reset sequential drops
1967 member->sequential_drops = 0 ;
1968
1969 // increment frames since dropped
1970 member->since_dropped++ ;
1971
1972 //
1973 // create new conf frame from passed data frame
1974 //
1975
1976 // ( member->inFrames may be null at this point )
1977 if (member->inSmoother == NULL ){
1978 conf_frame* cfr = create_conf_frame( member, member->inFrames, fr ) ;
1979 if ( cfr == NULL )
1980 {
1981 ast_log( LOG_ERROR, "unable to malloc conf_frame\n" ) ;
1982 ast_mutex_unlock(&member->lock);
1983 return -1 ;
1984 }
1985
1986 //
1987 // add new frame to speaking members incoming frame queue
1988 // ( i.e. save this frame data, so we can distribute it in conference_exec later )
1989 //
1990
1991 if ( member->inFrames == NULL ) {
1992 member->inFramesTail = cfr ;
1993 }
1994 member->inFrames = cfr ;
1995 member->inFramesCount++ ;
1996 } else {
1997 //feed frame(fr) into the smoother
1998
1999 // smoother tmp frame
2000 struct ast_frame *sfr;
2001 int multiple = 1;
2002 int i=0;
2003
2004 #if 0
2005 if ( (member->smooth_size_in > 0 ) && (member->smooth_size_in * member->smooth_multiple != fr->datalen) )
2006 {
2007 ast_log( AST_CONF_DEBUG, "resetting smooth_size_in. old size=> %d, multiple =>%d, datalen=> %d\n", member->smooth_size_in, member->smooth_multiple, fr->datalen );
2008 if ( fr->datalen % member->smooth_multiple != 0) {
2009 // if datalen not divisible by smooth_multiple, assume we're just getting normal encoding.
2010 // ast_log(AST_CONF_DEBUG,"smooth_multiple does not divide datalen. changing smooth size from %d to %d, multiple => 1\n", member->smooth_size_in, fr->datalen);
2011 member->smooth_size_in = fr->datalen;
2012 member->smooth_multiple = 1;
2013 } else {
2014 // assume a fixed multiple, so divide into datalen.
2015 int newsmooth = fr->datalen / member->smooth_multiple ;
2016 // ast_log(AST_CONF_DEBUG,"datalen is divisible by smooth_multiple, changing smooth size from %d to %d\n", member->smooth_size_in, newsmooth);
2017 member->smooth_size_in = newsmooth;
2018 }
2019
2020 //free input smoother.
2021 if (member->inSmoother != NULL)
2022 ast_smoother_free(member->inSmoother);
2023
2024 //make new input smoother.
2025 member->inSmoother = ast_smoother_new(member->smooth_size_in);
2026 }
2027 #endif
2028
2029 ast_smoother_feed( member->inSmoother, fr );
2030 ast_log (AST_CONF_DEBUG, "SMOOTH:Feeding frame into inSmoother, timestamp => %ld.%ld\n", fr->delivery.tv_sec, fr->delivery.tv_usec);
2031
2032 if ( multiple > 1 )
2033 fr->samples /= multiple;
2034
2035 // read smoothed version of frames, add to queue
2036 while( ( sfr = ast_smoother_read( member->inSmoother ) ) ){
2037
2038 ++i;
2039 ast_log( AST_CONF_DEBUG , "\treading new frame [%d] from smoother, inFramesCount[%d], \n\tsfr->frametype -> %d , sfr->subclass -> %d , sfr->datalen => %d sfr->samples => %d\n", i , member->inFramesCount , sfr->frametype, sfr->subclass, sfr->datalen, sfr->samples);
2040 ast_log (AST_CONF_DEBUG, "SMOOTH:Reading frame from inSmoother, i=>%d, timestamp => %ld.%ld\n",i, sfr->delivery.tv_sec, sfr->delivery.tv_usec);
2041 conf_frame* cfr = create_conf_frame( member, member->inFrames, sfr ) ;
2042 if ( cfr == NULL )
2043 {
2044 ast_log( LOG_ERROR, "unable to malloc conf_frame\n" ) ;
2045 ast_mutex_unlock(&member->lock);
2046 return -1 ;
2047 }
2048
2049 //
2050 // add new frame to speaking members incoming frame queue
2051 // ( i.e. save this frame data, so we can distribute it in conference_exec later )
2052 //
2053
2054 if ( member->inFrames == NULL ) {
2055 member->inFramesTail = cfr ;
2056 }
2057 member->inFrames = cfr ;
2058 member->inFramesCount++ ;
2059 }
2060 }
2061 ast_mutex_unlock(&member->lock);
2062 return 0 ;
2063 }
2064
2065 //
2066 // outgoing frame functions
2067 //
2068
2069 conf_frame* get_outgoing_frame( struct ast_conf_member *member )
2070 {
2071 if ( member == NULL )
2072 {
2073 ast_log( LOG_WARNING, "unable to get frame from null member\n" ) ;
2074 return NULL ;
2075 }
2076
2077 conf_frame* cfr ;
2078
2079 // ast_log( AST_CONF_DEBUG, "getting member frames, count => %d\n", member->outFramesCount ) ;
2080
2081 ast_mutex_lock(&member->lock);
2082
2083 if ( member->outFramesCount > AST_CONF_MIN_QUEUE )
2084 {
2085 cfr = member->outFramesTail ;
2086
2087 // if it's the only frame, reset the queu,
2088 // else, move the second frame to the front
2089 if ( member->outFramesTail == member->outFrames )
2090 {
2091 member->outFrames = NULL ;
2092 member->outFramesTail = NULL ;
2093 }
2094 else
2095 {
2096 // move the pointer to the next frame
2097 member->outFramesTail = member->outFramesTail->prev ;
2098
2099 // reset it's 'next' pointer
2100 if ( member->outFramesTail != NULL )
2101 member->outFramesTail->next = NULL ;
2102 }
2103
2104 // separate the conf frame from the list
2105 cfr->next = NULL ;
2106 cfr->prev = NULL ;
2107
2108 // decriment frame count
2109 member->outFramesCount-- ;
2110 ast_mutex_unlock(&member->lock);
2111 return cfr ;
2112 }
2113 ast_mutex_unlock(&member->lock);
2114 return NULL ;
2115 }
2116
2117 int __queue_outgoing_frame( struct ast_conf_member* member, const struct ast_frame* fr, struct timeval delivery )
2118 {
2119 // accounting: count the number of outgoing frames for this member
2120 member->frames_out++ ;
2121
2122 //
2123 // we have to drop frames, so we'll drop new frames
2124 // because it's easier ( and doesn't matter much anyway ).
2125 //
2126 if ( member->outFramesCount >= AST_CONF_MAX_QUEUE )
2127 {
2128 ast_log(
2129 AST_CONF_DEBUG,
2130 "unable to queue outgoing frame, channel => %s, incoming => %d, outgoing => %d\n",
2131 member->channel_name, member->inFramesCount, member->outFramesCount
2132 ) ;
2133
2134 // accounting: count dropped outgoing frames
2135 member->frames_out_dropped++ ;
2136 return -1 ;
2137 }
2138
2139 //
2140 // create new conf frame from passed data frame
2141 //
2142
2143 conf_frame* cfr = create_conf_frame( member, member->outFrames, fr ) ;
2144
2145 if ( cfr == NULL )
2146 {
2147 ast_log( LOG_ERROR, "unable to create new conf frame\n" ) ;
2148
2149 // accounting: count dropped outgoing frames
2150 member->frames_out_dropped++ ;
2151 return -1 ;
2152 }
2153
2154 // set delivery timestamp
2155 cfr->fr->delivery = delivery ;
2156
2157 //
2158 // add new frame to speaking members incoming frame queue
2159 // ( i.e. save this frame data, so we can distribute it in conference_exec later )
2160 //
2161
2162 if ( member->outFrames == NULL ) {
2163 member->outFramesTail = cfr ;
2164 }
2165 member->outFrames = cfr ;
2166 member->outFramesCount++ ;
2167
2168 // return success
2169 return 0 ;
2170 }
2171
2172 int queue_outgoing_frame( struct ast_conf_member* member, const struct ast_frame* fr, struct timeval delivery )
2173 {
2174 // check on frame
2175 if ( fr == NULL )
2176 {
2177 ast_log( LOG_ERROR, "unable to queue null frame\n" ) ;
2178 return -1 ;
2179 }
2180
2181 // check on member
2182 if ( member == NULL )
2183 {
2184 ast_log( LOG_ERROR, "unable to queue frame for null member\n" ) ;
2185 return -1 ;
2186 }
2187
2188 if ( ( member->outPacker == NULL ) && ( member->smooth_multiple > 1 ) && ( member->smooth_size_out > 0 ) ){
2189 //ast_log (AST_CONF_DEBUG, "creating outPacker with size => %d \n\t( multiple => %d ) * ( size => %d )\n", member->smooth_multiple * member-> smooth_size_out, member->smooth_multiple , member->smooth_size_out);
2190 member->outPacker = ast_packer_new( member->smooth_multiple * member->smooth_size_out);
2191 }
2192
2193 if (member->outPacker == NULL ){
2194 return __queue_outgoing_frame( member, fr, delivery ) ;
2195 }
2196 else
2197 {
2198 struct ast_frame *sfr;
2199 int exitval = 0;
2200 //ast_log (AST_CONF_DEBUG, "sending fr into outPacker, datalen=>%d, samples=>%d\n",fr->datalen, fr->samples);
2201 ast_packer_feed( member->outPacker , fr );
2202 while( (sfr = ast_packer_read( member->outPacker ) ) )
2203 {
2204 //ast_log (AST_CONF_DEBUG, "read sfr from outPacker, datalen=>%d, samples=>%d\n",sfr->datalen, sfr->samples);
2205 if ( __queue_outgoing_frame( member, sfr, delivery ) == -1 ) {
2206 exitval = -1;
2207 }
2208 }
2209
2210 return exitval;
2211 }
2212 }
2213
2214 //
2215 // outgoing frame functions
2216 //
2217
2218 conf_frame* get_outgoing_video_frame( struct ast_conf_member *member )
2219 {
2220 if ( member == NULL )
2221 {
2222 ast_log( LOG_WARNING, "unable to get frame from null member\n" ) ;
2223 return NULL ;
2224 }
2225
2226 conf_frame* cfr ;
2227
2228 ast_mutex_lock(&member->lock);
2229
2230 // ast_log( AST_CONF_DEBUG, "getting member frames, count => %d\n", member->outFramesCount ) ;
2231
2232 if ( member->outVideoFramesCount > AST_CONF_MIN_QUEUE )
2233 {
2234 cfr = member->outVideoFramesTail ;
2235
2236 // if it's the only frame, reset the queu,
2237 // else, move the second frame to the front
2238 if ( member->outVideoFramesTail == member->outVideoFrames )
2239 {
2240 member->outVideoFrames = NULL ;
2241 member->outVideoFramesTail = NULL ;
2242 }
2243 else
2244 {
2245 // move the pointer to the next frame
2246 member->outVideoFramesTail = member->outVideoFramesTail->prev ;
2247
2248 // reset it's 'next' pointer
2249 if ( member->outVideoFramesTail != NULL )
2250 member->outVideoFramesTail->next = NULL ;
2251 }
2252
2253 // separate the conf frame from the list
2254 cfr->next = NULL ;
2255 cfr->prev = NULL ;
2256
2257 // decriment frame count
2258 member->outVideoFramesCount-- ;
2259 ast_mutex_unlock(&member->lock);
2260 return cfr ;
2261 }
2262
2263 ast_mutex_unlock(&member->lock);
2264 return NULL ;
2265 }
2266
2267
2268
2269 int queue_outgoing_video_frame( struct ast_conf_member* member, const struct ast_frame* fr, struct timeval delivery )
2270 {
2271 // check on frame
2272 if ( fr == NULL )
2273 {
2274 ast_log( LOG_ERROR, "unable to queue null frame\n" ) ;
2275 return -1 ;
2276 }
2277
2278 // check on member
2279 if ( member == NULL )
2280 {
2281 ast_log( LOG_ERROR, "unable to queue frame for null member\n" ) ;
2282 return -1 ;
2283 }
2284
2285 ast_mutex_lock(&member->lock);
2286
2287 // accounting: count the number of outgoing frames for this member
2288 member->video_frames_out++ ;
2289
2290 //
2291 // we have to drop frames, so we'll drop new frames
2292 // because it's easier ( and doesn't matter much anyway ).
2293 //
2294 if ( member->outVideoFramesCount >= AST_CONF_MAX_VIDEO_QUEUE)
2295 {
2296 ast_log(
2297 AST_CONF_DEBUG,
2298 "unable to queue outgoing VIDEO frame, channel => %s, incoming => %d, outgoing => %d\n",
2299 member->channel_name, member->inVideoFramesCount, member->outVideoFramesCount
2300 ) ;
2301
2302 // accounting: count dropped outgoing frames
2303 member->video_frames_out_dropped++ ;
2304 ast_mutex_unlock(&member->lock);
2305 return -1 ;
2306 }
2307
2308 //
2309 // create new conf frame from passed data frame
2310 //
2311
2312 conf_frame* cfr = create_conf_frame( member, member->outVideoFrames, fr ) ;
2313
2314 if ( cfr == NULL )
2315 {
2316 ast_log( LOG_ERROR, "unable to create new conf frame\n" ) ;
2317
2318 // accounting: count dropped outgoing frames
2319 member->video_frames_out_dropped++ ;
2320 ast_mutex_unlock(&member->lock);
2321 return -1 ;
2322 }
2323
2324 // set delivery timestamp
2325 #ifdef VIDEO_SETTIMESTAMP
2326 cfr->fr->delivery = delivery ;
2327 #else
2328 cfr->fr->delivery.tv_sec = 0;
2329 cfr->fr->delivery.tv_usec = 0;
2330 #endif
2331 //ast_log (LOG_WARNING,"%d\n",cfr->fr->seqno);
2332
2333 #ifdef RTP_SEQNO_ZERO
2334 cfr->fr->seqno = 0;
2335 #endif
2336
2337 if ( member->outVideoFrames == NULL )
2338 {
2339 // this is the first frame in the buffer
2340 member->outVideoFramesTail = cfr ;
2341 member->outVideoFrames = cfr ;
2342 }
2343 else
2344 {
2345 // put the new frame at the head of the list
2346 member->outVideoFrames = cfr ;
2347 }
2348
2349 // increment member frame count
2350 member->outVideoFramesCount++ ;
2351
2352 ast_mutex_unlock(&member->lock);
2353
2354 // return success
2355 return 0 ;
2356 }
2357
2358 conf_frame* get_outgoing_dtmf_frame( struct ast_conf_member *member )
2359 {
2360 if ( member == NULL )
2361 {
2362 ast_log( LOG_WARNING, "unable to get frame from null member\n" ) ;
2363 return NULL ;
2364 }
2365
2366 conf_frame* cfr ;
2367
2368 // ast_log( AST_CONF_DEBUG, "getting member frames, count => %d\n", member->outFramesCount ) ;
2369
2370 ast_mutex_lock(&member->lock);
2371
2372 if ( member->outDTMFFramesCount > AST_CONF_MIN_QUEUE )
2373 {
2374 cfr = member->outDTMFFramesTail ;
2375
2376 // if it's the only frame, reset the queu,
2377 // else, move the second frame to the front
2378 if ( member->outDTMFFramesTail == member->outDTMFFrames )
2379 {
2380 member->outDTMFFrames = NULL ;
2381 member->outDTMFFramesTail = NULL ;
2382 }
2383 else
2384 {
2385 // move the pointer to the next frame
2386 member->outDTMFFramesTail = member->outDTMFFramesTail->prev ;
2387
2388 // reset it's 'next' pointer
2389 if ( member->outDTMFFramesTail != NULL )
2390 member->outDTMFFramesTail->next = NULL ;
2391 }
2392
2393 // separate the conf frame from the list
2394 cfr->next = NULL ;
2395 cfr->prev = NULL ;
2396
2397 // decriment frame count
2398 member->outDTMFFramesCount-- ;
2399 ast_mutex_unlock(&member->lock);
2400 return cfr ;
2401 }
2402 ast_mutex_unlock(&member->lock);
2403 return NULL ;
2404 }
2405
2406 conf_frame* get_outgoing_text_frame( struct ast_conf_member *member )
2407 {
2408 if ( member == NULL )
2409 {
2410 ast_log( LOG_WARNING, "unable to get frame from null member\n" ) ;
2411 return NULL ;
2412 }
2413
2414 conf_frame* cfr ;
2415
2416 // ast_log( AST_CONF_DEBUG, "getting member frames, count => %d\n", member->outFramesCount ) ;
2417
2418 ast_mutex_lock(&member->lock);
2419
2420 if ( member->outTextFramesCount > AST_CONF_MIN_QUEUE )
2421 {
2422 cfr = member->outTextFramesTail ;
2423
2424 // if it's the only frame, reset the queu,
2425 // else, move the second frame to the front
2426 if ( member->outTextFramesTail == member->outTextFrames )
2427 {
2428 member->outTextFrames = NULL ;
2429 member->outTextFramesTail = NULL ;
2430 }
2431 else
2432 {
2433 // move the pointer to the next frame
2434 member->outTextFramesTail = member->outTextFramesTail->prev ;
2435
2436 // reset it's 'next' pointer
2437 if ( member->outTextFramesTail != NULL )
2438 member->outTextFramesTail->next = NULL ;
2439 }
2440
2441 // separate the conf frame from the list
2442 cfr->next = NULL ;
2443 cfr->prev = NULL ;
2444
2445 // decriment frame count
2446 member->outTextFramesCount-- ;
2447 ast_mutex_unlock(&member->lock);
2448 return cfr ;
2449 }
2450 ast_mutex_unlock(&member->lock);
2451 return NULL ;
2452 }
2453
2454
2455 int queue_outgoing_dtmf_frame( struct ast_conf_member* member, const struct ast_frame* fr )
2456 {
2457 // check on frame
2458 if ( fr == NULL )
2459 {
2460 ast_log( LOG_ERROR, "unable to queue null frame\n" ) ;
2461 return -1 ;
2462 }
2463
2464 // check on member
2465 if ( member == NULL )
2466 {
2467 ast_log( LOG_ERROR, "unable to queue frame for null member\n" ) ;
2468 return -1 ;
2469 }
2470
2471 ast_mutex_lock(&member->lock);
2472
2473 // accounting: count the number of outgoing frames for this member
2474 member->dtmf_frames_out++ ;
2475
2476 //
2477 // we have to drop frames, so we'll drop new frames
2478 // because it's easier ( and doesn't matter much anyway ).
2479 //
2480 if ( member->outDTMFFramesCount >= AST_CONF_MAX_DTMF_QUEUE)
2481 {
2482 ast_log(
2483 AST_CONF_DEBUG,
2484 "unable to queue outgoing DTMF frame, channel => %s, incoming => %d, outgoing => %d\n",
2485 member->channel_name, member->inDTMFFramesCount, member->outDTMFFramesCount
2486 ) ;
2487
2488 // accounting: count dropped outgoing frames
2489 member->dtmf_frames_out_dropped++ ;
2490 ast_mutex_unlock(&member->lock);
2491 return -1 ;
2492 }
2493
2494 //
2495 // create new conf frame from passed data frame
2496 //
2497
2498 conf_frame* cfr = create_conf_frame( member, member->outDTMFFrames, fr ) ;
2499
2500 if ( cfr == NULL )
2501 {
2502 ast_log( LOG_ERROR, "unable to create new conf frame\n" ) ;
2503
2504 // accounting: count dropped outgoing frames
2505 member->dtmf_frames_out_dropped++ ;
2506 ast_mutex_unlock(&member->lock);
2507 return -1 ;
2508 }
2509
2510 #ifdef RTP_SEQNO_ZERO
2511 cfr->fr->seqno = 0;
2512 #endif
2513
2514 if ( member->outDTMFFrames == NULL )
2515 {
2516 // this is the first frame in the buffer
2517 member->outDTMFFramesTail = cfr ;
2518 member->outDTMFFrames = cfr ;
2519 }
2520 else
2521 {
2522 // put the new frame at the head of the list
2523 member->outDTMFFrames = cfr ;
2524 }
2525
2526 // increment member frame count
2527 member->outDTMFFramesCount++ ;
2528
2529 ast_mutex_unlock(&member->lock);
2530 // return success
2531 return 0 ;
2532 }
2533
2534 int queue_outgoing_text_frame( struct ast_conf_member* member, const struct ast_frame* fr)
2535 {
2536 // check on frame
2537 if ( fr == NULL )
2538 {
2539 ast_log( LOG_ERROR, "unable to queue null frame\n" ) ;
2540 return -1 ;
2541 }
2542
2543 // check on member
2544 if ( member == NULL )
2545 {
2546 ast_log( LOG_ERROR, "unable to queue frame for null member\n" ) ;
2547 return -1 ;
2548 }
2549
2550 ast_mutex_lock(&member->lock);
2551
2552 // accounting: count the number of outgoing frames for this member
2553 member->text_frames_out++ ;
2554
2555 //
2556 // we have to drop frames, so we'll drop new frames
2557 // because it's easier ( and doesn't matter much anyway ).
2558 //
2559 if ( member->outTextFramesCount >= AST_CONF_MAX_TEXT_QUEUE)
2560 {
2561 ast_log(
2562 AST_CONF_DEBUG,
2563 "unable to queue outgoing text frame, channel => %s, incoming => %d, outgoing => %d\n",
2564 member->channel_name, member->inTextFramesCount, member->outTextFramesCount
2565 ) ;
2566
2567 // accounting: count dropped outgoing frames
2568 member->text_frames_out_dropped++ ;
2569 ast_mutex_unlock(&member->lock);
2570 return -1 ;
2571 }
2572
2573 //
2574 // create new conf frame from passed data frame
2575 //
2576
2577 conf_frame* cfr = create_conf_frame( member, member->outTextFrames, fr ) ;
2578
2579 if ( cfr == NULL )
2580 {
2581 ast_log( LOG_ERROR, "unable to create new conf frame\n" ) ;
2582
2583 // accounting: count dropped outgoing frames
2584 member->text_frames_out_dropped++ ;
2585 ast_mutex_unlock(&member->lock);
2586 return -1 ;
2587 }
2588
2589 #ifdef RTP_SEQNO_ZERO
2590 cfr->fr->seqno = 0;
2591 #endif
2592
2593 if ( member->outTextFrames == NULL )
2594 {
2595 // this is the first frame in the buffer
2596 member->outTextFramesTail = cfr ;
2597 member->outTextFrames = cfr ;
2598 }
2599 else
2600 {
2601 // put the new frame at the head of the list
2602 member->outTextFrames = cfr ;
2603 }
2604
2605 // increment member frame count
2606 member->outTextFramesCount++ ;
2607
2608 ast_mutex_unlock(&member->lock);
2609 // return success
2610 return 0 ;
2611 }
2612
2613
2614 //
2615 // manager functions
2616 //
2617
2618 void send_state_change_notifications( struct ast_conf_member* member )
2619 {
2620 // ast_log( AST_CONF_DEBUG, "sending state change notification\n" ) ;
2621
2622 // loop through list of members, sending state changes
2623 while ( member != NULL )
2624 {
2625 // has the state changed since last time through this loop?
2626 if ( member->speaking_state_notify )
2627 {
2628 manager_event(
2629 EVENT_FLAG_CALL,
2630 "ConferenceState",
2631 "Channel: %s\r\n"
2632 "State: %s\r\n",
2633 member->channel_name,
2634 ( ( member->speaking_state == 1 ) ? "speaking" : "silent" )
2635 ) ;
2636
2637 ast_log( AST_CONF_DEBUG, "member state changed, channel => %s, state => %d, incoming => %d, outgoing => %d\n",
2638 member->channel_name, member->speaking_state, member->inFramesCount, member->outFramesCount ) ;
2639
2640 member->speaking_state_notify = 0;
2641 }
2642
2643 // move the pointer to the next member
2644 member = member->next ;
2645 }
2646
2647 return ;
2648 }
2649
2650 //
2651 // ast_packer, adapted from ast_smoother
2652 // pack multiple frames together into one packet on the wire.
2653 //
2654
2655 #define PACKER_SIZE 8000
2656 #define PACKER_QUEUE 10 // store at most 10 complete packets in the queue
2657
2658 struct ast_packer {
2659 int framesize; // number of frames per packet on the wire.
2660 int size;
2661 int packet_index;
2662 int format;
2663 int readdata;
2664 int optimizablestream;
2665 int flags;
2666 float samplesperbyte;
2667 struct ast_frame f;
2668 struct timeval delivery;
2669 char data[PACKER_SIZE];
2670 char framedata[PACKER_SIZE + AST_FRIENDLY_OFFSET];
2671 int samples;
2672 int sample_queue[PACKER_QUEUE];
2673 int len_queue[PACKER_QUEUE];
2674 struct ast_frame *opt;
2675 int len;
2676 };
2677
2678 void ast_packer_reset(struct ast_packer *s, int framesize)
2679 {
2680 memset(s, 0, sizeof(struct ast_packer));
2681 s->framesize = framesize;
2682 s->packet_index=0;
2683 s->len=0;
2684 }
2685
2686 struct ast_packer *ast_packer_new(int framesize)
2687 {
2688 struct ast_packer *s;
2689 if (framesize < 1)
2690 return NULL;
2691 s = malloc(sizeof(struct ast_packer));
2692 if (s)
2693 ast_packer_reset(s, framesize);
2694 return s;
2695 }
2696
2697 int ast_packer_get_flags(struct ast_packer *s)
2698 {
2699 return s->flags;
2700 }
2701
2702 void ast_packer_set_flags(struct ast_packer *s, int flags)
2703 {
2704 s->flags = flags;
2705 }
2706
2707 int ast_packer_feed(struct ast_packer *s, const struct ast_frame *f)
2708 {
2709 if (f->frametype != AST_FRAME_VOICE) {
2710 ast_log(LOG_WARNING, "Huh? Can't pack a non-voice frame!\n");
2711 return -1;
2712 }
2713 if (!s->format) {
2714 s->format = f->subclass;
2715 s->samples=0;
2716 } else if (s->format != f->subclass) {
2717 ast_log(LOG_WARNING, "Packer was working on %d format frames, now trying to feed %d?\n", s->format, f->subclass);
2718 return -1;
2719 }
2720 if (s->len + f->datalen > PACKER_SIZE) {
2721 ast_log(LOG_WARNING, "Out of packer space\n");
2722 return -1;
2723 }
2724 if (s->packet_index >= PACKER_QUEUE ){
2725 ast_log(LOG_WARNING, "Out of packer queue space\n");
2726 return -1;
2727 }
2728
2729 memcpy(s->data + s->len, f->data, f->datalen);
2730 /* If either side is empty, reset the delivery time */
2731 if (!s->len || (!f->delivery.tv_sec && !f->delivery.tv_usec) ||
2732 (!s->delivery.tv_sec && !s->delivery.tv_usec))
2733 s->delivery = f->delivery;
2734 s->len += f->datalen;
2735 //packer stuff
2736 s->len_queue[s->packet_index] += f->datalen;
2737 s->sample_queue[s->packet_index] += f->samples;
2738 s->samples += f->samples;
2739
2740 if (s->samples > s->framesize )
2741 ++s->packet_index;
2742
2743 return 0;
2744 }
2745
2746 struct ast_frame *ast_packer_read(struct ast_packer *s)
2747 {
2748 struct ast_frame *opt;
2749 int len;
2750 /* IF we have an optimization frame, send it */
2751 if (s->opt) {
2752 opt = s->opt;
2753 s->opt = NULL;
2754 return opt;
2755 }
2756
2757 /* Make sure we have enough data */
2758 if (s->samples < s->framesize ){
2759 return NULL;
2760 }
2761 len = s->len_queue[0];
2762 if (len > s->len)
2763 len = s->len;
2764 /* Make frame */
2765 s->f.frametype = AST_FRAME_VOICE;
2766 s->f.subclass = s->format;
2767 s->f.data = s->framedata + AST_FRIENDLY_OFFSET;
2768 s->f.offset = AST_FRIENDLY_OFFSET;
2769 s->f.datalen = len;
2770 s->f.samples = s->sample_queue[0];
2771 s->f.delivery = s->delivery;
2772 /* Fill Data */
2773 memcpy(s->f.data, s->data, len);
2774 s->len -= len;
2775 /* Move remaining data to the front if applicable */
2776 if (s->len) {
2777 /* In principle this should all be fine because if we are sending
2778 G.729 VAD, the next timestamp will take over anyawy */
2779 memmove(s->data, s->data + len, s->len);
2780 if (s->delivery.tv_sec || s->delivery.tv_usec) {
2781 /* If we have delivery time, increment it, otherwise, leave it at 0 */
2782 s->delivery.tv_sec += s->sample_queue[0] / 8000.0;
2783 s->delivery.tv_usec += (((int)(s->sample_queue[0])) % 8000) * 125;
2784 if (s->delivery.tv_usec > 1000000) {
2785 s->delivery.tv_usec -= 1000000;
2786 s->delivery.tv_sec += 1;
2787 }
2788 }
2789 }
2790 int j;
2791 s->samples -= s->sample_queue[0];
2792 if( s->packet_index > 0 ){
2793 for (j=0; j<s->packet_index -1 ; j++){
2794 s->len_queue[j]=s->len_queue[j+1];
2795 s->sample_queue[j]=s->sample_queue[j+1];
2796 }
2797 s->len_queue[s->packet_index]=0;
2798 s->sample_queue[s->packet_index]=0;
2799 s->packet_index--;
2800 } else {
2801 s->len_queue[0]=0;
2802 s->sample_queue[0]=0;
2803 }
2804
2805
2806 /* Return frame */
2807 return &s->f;
2808 }
2809
2810 void ast_packer_free(struct ast_packer *s)
2811 {
2812 free(s);
2813 }
2814
2815 int queue_frame_for_listener(
2816 struct ast_conference* conf,
2817 struct ast_conf_member* member,
2818 conf_frame* frame
2819 )
2820 {
2821 //
2822 // check inputs
2823 //
2824
2825 if ( conf == NULL )
2826 {
2827 ast_log( LOG_WARNING, "unable to queue listener frame with null conference\n" ) ;
2828 return -1 ;
2829 }
2830
2831 if ( member == NULL )
2832 {
2833 ast_log( LOG_WARNING, "unable to queue listener frame with null member\n" ) ;
2834 return -1 ;
2835 }
2836
2837 //
2838 // loop over spoken frames looking for member's appropriate match
2839 //
2840
2841 short found_flag = 0 ;
2842 struct ast_frame* qf ;
2843
2844 for ( ; frame != NULL ; frame = frame->next )
2845 {
2846 // we're looking for a null or matching member
2847 if ( frame->member != NULL && frame->member != member )
2848 continue ;
2849
2850 if ( frame->fr == NULL )
2851 {
2852 ast_log( LOG_WARNING, "unknown error queueing frame for listener, frame->fr == NULL\n" ) ;
2853 continue ;
2854 }
2855
2856 // first, try for a pre-converted frame
2857 qf = frame->converted[ member->write_format_index ] ;
2858
2859 // convert ( and store ) the frame
2860 if ( qf == NULL )
2861 {
2862 // make a copy of the slinear version of the frame
2863 qf = ast_frdup( frame->fr ) ;
2864
2865 if ( qf == NULL )
2866 {
2867 ast_log( LOG_WARNING, "unable to duplicate frame\n" ) ;
2868 continue ;
2869 }
2870
2871 // convert using the conference's translation path
2872 qf = convert_frame_from_slinear( conf->from_slinear_paths[ member->write_format_index ], qf ) ;
2873
2874 // store the converted frame
2875 // ( the frame will be free'd next time through the loop )
2876 frame->converted[ member->write_format_index ] = qf ;
2877 }
2878
2879 if ( qf != NULL )
2880 {
2881 // duplicate the frame before queue'ing it
2882 // ( since this member doesn't own this _shared_ frame )
2883 // qf = ast_frdup( qf ) ;
2884
2885
2886
2887 if ( queue_outgoing_frame( member, qf, conf->delivery_time ) != 0 )
2888 {
2889 // free the new frame if it couldn't be queue'd
2890 // XXX NEILS - WOULD BE FREED IN CLEANUPast_frfree( qf ) ;
2891 //qf = NULL ;
2892 }
2893 }
2894 else
2895 {
2896 ast_log( LOG_WARNING, "unable to translate outgoing listener frame, channel => %s\n", member->channel_name ) ;
2897 }
2898
2899 // set found flag
2900 found_flag = 1 ;
2901
2902 // break from for loop
2903 break ;
2904 }
2905
2906 // queue a silent frame
2907 if ( found_flag == 0 )
2908 queue_silent_frame( conf, member ) ;
2909
2910 return 0 ;
2911 }
2912
2913
2914 int queue_frame_for_speaker(
2915 struct ast_conference* conf,
2916 struct ast_conf_member* member,
2917 conf_frame* frame
2918 )
2919 {
2920 //
2921 // check inputs
2922 //
2923
2924 if ( conf == NULL )
2925 {
2926 ast_log( LOG_WARNING, "unable to queue speaker frame with null conference\n" ) ;
2927 return -1 ;
2928 }
2929
2930 if ( member == NULL )
2931 {
2932 ast_log( LOG_WARNING, "unable to queue speaker frame with null member\n" ) ;
2933 return -1 ;
2934 }
2935
2936 //
2937 // loop over spoken frames looking for member's appropriate match
2938 //
2939
2940 short found_flag = 0 ;
2941 struct ast_frame* qf ;
2942
2943 for ( ; frame != NULL ; frame = frame->next )
2944 {
2945 if ( frame->member != member )
2946 {
2947 continue ;
2948 }
2949
2950 if ( frame->fr == NULL )
2951 {
2952 ast_log( LOG_WARNING, "unable to queue speaker frame with null data\n" ) ;
2953 continue ;
2954 }
2955
2956 //
2957 // convert and queue frame
2958 //
2959
2960 // short-cut pointer to the ast_frame
2961 qf = frame->fr ;
2962
2963 if ( qf->subclass == member->write_format )
2964 {
2965 // frame is already in correct format, so just queue it
2966
2967 queue_outgoing_frame( member, qf, conf->delivery_time ) ;
2968 }
2969 else
2970 {
2971 //
2972 // convert frame to member's write format
2973 // ( calling ast_frdup() to make sure the translator's copy sticks around )
2974 //
2975 qf = convert_frame_from_slinear( member->from_slinear, ast_frdup( qf ) ) ;
2976
2977 if ( qf != NULL )
2978 {
2979 // queue frame
2980 queue_outgoing_frame( member, qf, conf->delivery_time ) ;
2981
2982 // free frame ( the translator's copy )
2983 ast_frfree( qf ) ;
2984 }
2985 else
2986 {
2987 ast_log( LOG_WARNING, "unable to translate outgoing speaker frame, channel => %s\n", member->channel_name ) ;
2988 }
2989 }
2990
2991 // set found flag
2992 found_flag = 1 ;
2993
2994 // we found the frame, skip to the next member
2995 break ;
2996 }
2997
2998 // queue a silent frame
2999 if ( found_flag == 0 )
3000 queue_silent_frame( conf, member ) ;
3001
3002 return 0 ;
3003 }
3004
3005
3006 int queue_silent_frame(
3007 struct ast_conference* conf,
3008 struct ast_conf_member* member
3009 )
3010 {
3011 int c;
3012 #ifdef APP_CONFERENCE_DEBUG
3013 //
3014 // check inputs
3015 //
3016
3017 if ( conf == NULL )
3018 {
3019 ast_log( AST_CONF_DEBUG, "unable to queue silent frame for null conference\n" ) ;
3020 return -1 ;
3021 }
3022
3023 if ( member == NULL )
3024 {
3025 ast_log( AST_CONF_DEBUG, "unable to queue silent frame for null member\n" ) ;
3026 return -1 ;
3027 }
3028 #endif // APP_CONFERENCE_DEBUG
3029
3030 //
3031 // initialize static variables
3032 //
3033
3034 static conf_frame* silent_frame = NULL ;
3035 static struct ast_frame* qf = NULL ;
3036
3037 if ( silent_frame == NULL )
3038 {
3039 if ( ( silent_frame = get_silent_frame() ) == NULL )
3040 {
3041 ast_log( LOG_WARNING, "unable to initialize static silent frame\n" ) ;
3042 return -1 ;
3043 }
3044 }
3045
3046
3047 // get the appropriate silent frame
3048 qf = silent_frame->converted[ member->write_format_index ] ;
3049
3050 if ( qf == NULL )
3051 {
3052 //
3053 // we need to do this to avoid echo on the speaker's line.
3054 // translators seem to be single-purpose, i.e. they
3055 // can't be used simultaneously for multiple audio streams
3056 //
3057
3058 struct ast_trans_pvt* trans = ast_translator_build_path( member->write_format, AST_FORMAT_SLINEAR ) ;
3059
3060 if ( trans != NULL )
3061 {
3062 // attempt ( five times ) to get a silent frame
3063 // to make sure we provice the translator with enough data
3064 for ( c = 0 ; c < 5 ; ++c )
3065 {
3066 // translate the frame
3067 qf = ast_translate( trans, silent_frame->fr, 0 ) ;
3068
3069 // break if we get a frame
3070 if ( qf != NULL ) break ;
3071 }
3072
3073 if ( qf != NULL )
3074 {
3075 // isolate the frame so we can keep it around after trans is free'd
3076 qf = ast_frisolate( qf ) ;
3077
3078 // cache the new, isolated frame
3079 silent_frame->converted[ member->write_format_index ] = qf ;
3080 }
3081
3082 ast_translator_free_path( trans ) ;
3083 }
3084 }
3085
3086 //
3087 // queue the frame, if it's not null,
3088 // otherwise there was an error
3089 //
3090 if ( qf != NULL )
3091 {
3092 queue_outgoing_frame( member, qf, conf->delivery_time ) ;
3093 }
3094 else
3095 {
3096 ast_log( LOG_ERROR, "unable to translate outgoing silent frame, channel => %s\n", member->channel_name ) ;
3097 }
3098
3099 return 0 ;
3100 }
3101
3102
3103
3104 void member_process_outgoing_frames(struct ast_conference* conf,
3105 struct ast_conf_member *member,
3106 struct conf_frame *send_frames)
3107 {
3108 ast_mutex_lock(&member->lock);
3109
3110 // skip members that are not ready
3111 if ( member->ready_for_outgoing == 0 )
3112 {
3113 ast_mutex_unlock(&member->lock);
3114 return ;
3115 }
3116
3117 // skip no receive audio clients
3118 if ( member->norecv_audio )
3119 {
3120 ast_mutex_unlock(&member->lock);
3121 return;
3122 }
3123
3124 if ( member->local_speaking_state == 0 )
3125 {
3126 // queue listener frame
3127 queue_frame_for_listener( conf, member, send_frames ) ;
3128 }
3129 else
3130 {
3131 // queue speaker frame
3132 queue_frame_for_speaker( conf, member, send_frames ) ;
3133 }
3134 ast_mutex_unlock(&member->lock);
3135 }
3136
3137 // Functions that will increase and decrease speaker_count in a secure way, locking the member mutex if required
3138 // Will also set speaking_state flag.
3139 // Returns the previous speaking state
3140 int increment_speaker_count(struct ast_conf_member *member, int lock)
3141 {
3142 int old_state;
3143
3144 if ( lock )
3145 ast_mutex_lock(&member->lock);
3146
3147 old_state = member->speaking_state;
3148 member->speaker_count++;
3149 member->speaking_state = 1;
3150
3151 ast_log(AST_CONF_DEBUG, "Increment speaker count: id=%d, count=%d\n", member->id, member->speaker_count);
3152
3153 // If this is a state change, update the timestamp
3154 if ( old_state == 0 )
3155 {
3156 member->speaking_state_notify = 1;
3157 member->last_state_change = ast_tvnow();
3158 }
3159
3160 if ( lock )
3161 ast_mutex_unlock(&member->lock);
3162
3163 return old_state;
3164 }
3165
3166 int decrement_speaker_count(struct ast_conf_member *member, int lock)
3167 {
3168 int old_state;
3169
3170 if ( lock )
3171 ast_mutex_lock(&member->lock);
3172
3173 old_state = member->speaking_state;
3174 if ( member->speaker_count > 0 )
3175 member->speaker_count--;
3176 if ( member->speaker_count == 0 )
3177 member->speaking_state = 0;
3178
3179 ast_log(AST_CONF_DEBUG, "Decrement speaker count: id=%d, count=%d\n", member->id, member->speaker_count);
3180
3181 // If this is a state change, update the timestamp
3182 if ( old_state == 1 && member->speaking_state == 0 )
3183 {
3184 member->speaking_state_notify = 1;
3185 member->last_state_change = ast_tvnow();
3186 }
3187
3188 if ( lock )
3189 ast_mutex_unlock(&member->lock);
3190
3191 return old_state;
3192 }
3193
3194 void member_process_spoken_frames(struct ast_conference* conf,
3195 struct ast_conf_member *member,
3196 struct conf_frame **spoken_frames,
3197 long time_diff,
3198 int *listener_count,
3199 int *speaker_count
3200 )
3201 {
3202 struct conf_frame *cfr;
3203
3204 // acquire member mutex
3205 TIMELOG(ast_mutex_lock( &member->lock ),1,"conf thread member lock") ;
3206
3207 // check for dead members
3208 if ( member->remove_flag == 1 )
3209 {
3210 // If this member is the default video source for the conference, then change the default to -1
3211 if ( member->id == conf->default_video_source_id )
3212 conf->default_video_source_id = -1;
3213
3214 if (conf->debug_flag)
3215 {
3216 ast_log( LOG_NOTICE, "found member slated for removal, channel => %s\n", member->channel_name ) ;
3217 }
3218 remove_member( member, conf ) ;
3219 // leave a message for all remaining members
3220 member = conf->memberlist ;
3221 while (member != NULL)
3222 {
3223 play_sound_channel( __LOG_DEBUG, member->channel_name, (conf->membercount < 2) ? "conf-onlypersonleft" : "appconf-leave" , 0);
3224 member = member->next;
3225 }
3226 return;
3227 }
3228
3229 // tell member the number of frames we're going to need ( used to help dropping algorithm )
3230 member->inFramesNeeded = ( time_diff / AST_CONF_FRAME_INTERVAL ) - 1 ;
3231
3232 // !!! TESTING !!!
3233 if (
3234 conf->debug_flag == 1
3235 && member->inFramesNeeded > 0
3236 )
3237 {
3238 ast_log( AST_CONF_DEBUG, "channel => %s, inFramesNeeded => %d, inFramesCount => %d\n",
3239 member->channel_name, member->inFramesNeeded, member->inFramesCount ) ;
3240 }
3241
3242 // non-listener member should have frames,
3243 // unless silence detection dropped them
3244 cfr = get_incoming_frame( member ) ;
3245
3246 // handle retrieved frames
3247 if ( cfr == NULL || cfr->fr == NULL )
3248 {
3249 // Decrement speaker count for us and for driven members
3250 // This happens only for the first missed frame, since we want to
3251 // decrement only on state transitions
3252 if ( member->local_speaking_state == 1 )
3253 {
3254 decrement_speaker_count(member, 0);
3255 member->local_speaking_state = 0;
3256 // If we're driving another member, decrement its speaker count as well
3257 if ( member->driven_member != NULL )
3258 decrement_speaker_count(member->driven_member, 1);
3259 }
3260
3261 // count the listeners
3262 (*listener_count)++ ;
3263 }
3264 else
3265 {
3266 // append the frame to the list of spoken frames
3267 if ( *spoken_frames != NULL )
3268 {
3269 // add new frame to end of list
3270 cfr->next = *spoken_frames ;
3271 (*spoken_frames)->prev = cfr ;
3272 }
3273
3274 // point the list at the new frame
3275 *spoken_frames = cfr ;
3276
3277 // Increment speaker count for us and for driven members
3278 // This happens only on the first received frame, since we want to
3279 // increment only on state transitions
3280 if ( member->local_speaking_state == 0 )
3281 {
3282 increment_speaker_count(member, 0);
3283 member->local_speaking_state = 1;
3284
3285 // If we're driving another member, increment its speaker count as well
3286 if ( member->driven_member != NULL )
3287 increment_speaker_count(member->driven_member, 1);
3288 }
3289
3290 // count the speakers
3291 (*speaker_count)++ ;
3292 }
3293
3294 // release member mutex
3295 ast_mutex_unlock( &member->lock ) ;
3296
3297 return;
3298 }