bool CConferenceInfo::mix_member_frame(CConferenceMember::pointer member, const CLockMap<CConferenceMember*, CMemberData::pointer> & audios, int & outTimestamp) { BOOST_ASSERT (member.get() != 0); if (member->getClosed()) return false; bool result = false; bool first = true; boost::mutex::scoped_lock lock(const_cast<boost::mutex&>(audios.mutex())); CLockMap<CConferenceMember*, CMemberData::pointer>::const_iterator iter; for (iter=audios.begin(); iter!= audios.end(); iter++) { if (iter->second->getRtpParam() == member.get()) continue; if (iter->second->isSilence()) continue; result = true; member->audioBuffer()->remalloc(iter->second->getRtpData()->size()); if (first) { first = false; member->audioBuffer()->set(iter->second->getRtpData()->data(), iter->second->getRtpData()->size()); }else { mix_slinear_frames((char*)const_cast<void*>(member->audioBuffer()->buffer()), (const char*)iter->second->getRtpData()->data(), iter->second->getRtpData()->size()/2); } if (iter->second->getRtpData()->timestamp() > (unsigned int)outTimestamp) outTimestamp = iter->second->getRtpData()->timestamp(); } return result; }
struct ast_frame* get_outgoing_frame( struct ast_conference *conf, struct ast_conf_member* member, int samples ) { // // sanity checks // // check on conf if ( conf == NULL ) { ast_log( LOG_ERROR, "unable to queue null conference\n" ) ; return NULL ; } if ( conf->memberlist == NULL ) { ast_log( LOG_ERROR, "unable to queue for a null memberlist\n" ) ; return NULL ; } // check on member if ( member == NULL ) { ast_log( LOG_ERROR, "unable to queue frame for null member\n" ) ; return NULL ; } //*********************************** // Mixing procedure //*********************************** int members =0; struct ast_frame *f = NULL; struct ast_conf_member *mixmember; short *dst = member->framedata; short *src = NULL; memset(member->framedata,0,sizeof(member->framedata)); mixmember=conf->memberlist; while ( mixmember ) { if ( mixmember!=member && mixmember->is_speaking && ( mixmember->type != MEMBERTYPE_CONSULTANT || ( mixmember->type == MEMBERTYPE_CONSULTANT && member->type == MEMBERTYPE_MASTER ) ) ) { members++; src = mixmember->cbuf->buffer8k; #if ( APP_NCONFERENCE_DEBUG == 1 ) if(vdebug) ast_log(AST_CONF_DEBUG, "Mixing memb %s Chan %s Ind %d Samples %d " " bufpos: %p with offset %p FOR MEMBER %s\n", mixmember->id, mixmember->chan->name, mixmember->cbuf->index8k, samples, member->framedata, member->framedata + AST_FRIENDLY_OFFSET/sizeof(short), member->chan->name ); #endif mix_slinear_frames( dst, src, samples, mixmember->cbuf->index8k, sizeof(mixmember->cbuf->buffer8k)/sizeof(short) ); } mixmember=mixmember->next; } //Building the frame f = calloc(1, sizeof(struct ast_frame)); if (f != NULL) { ast_fr_init_ex(f, AST_FRAME_VOICE, AST_FORMAT_SLINEAR, "Nconf"); f->data = member->framedata; f->datalen = samples*sizeof(short); f->samples = samples; f->offset = 0; } else return NULL; #if ( APP_NCONFERENCE_DEBUG == 1 ) if (vdebug && members) { int count=0; short *msrc; msrc = f->data + AST_FRIENDLY_OFFSET; if (vdebug) ast_log(AST_CONF_DEBUG, "Offset %d OFO: %d Data at %p SRC at %p memberdata at %p \n", f->offset, AST_FRIENDLY_OFFSET, f->data, &msrc, member->framedata ); for( count=0; count<f->samples; count++ ) { ast_log(AST_CONF_DEBUG, "DUMP POS %04d VALUE %08d at %p \n", count, msrc[count], &msrc[count] ); } } #endif return f ; }