#include "AmConferenceChannel.h" #include "AmConfig.h" #include "AmUtils.h" #include #include #include AmConferenceChannel::AmConferenceChannel(AmConferenceStatus* status, int channel_id, string channel_tag, bool own_channel) : status(status), channel_id(channel_id), channel_tag(channel_tag), own_channel(own_channel), have_in_sr(false), have_out_sr(false), in_file(NULL), out_file(NULL) { assert(status); conf_id = status->getConfID(); if (AmConfig::DumpConferenceStreams) { in_file_name = AmConfig::DumpConferencePath + "/"+conf_id+"_"+int2str(channel_id)+"_"+long2str((long)this)+"_in.s16"; out_file_name = AmConfig::DumpConferencePath + "/"+conf_id+"_"+int2str(channel_id)+"_"+long2str((long)this)+"_out.s16"; DBG("conf channel opening in_file '%s'\n", in_file_name.c_str()); in_file = new ChannelWritingFile(in_file_name.c_str()); DBG("conf channel opening out_file '%s'\n", out_file_name.c_str()); out_file = new ChannelWritingFile(out_file_name.c_str()); } } AmConferenceChannel::~AmConferenceChannel() { if(own_channel) AmConferenceStatus::releaseChannel(conf_id,channel_id); if (in_file) in_file->close(); if (out_file) out_file->close(); } int AmConferenceChannel::put(unsigned long long system_ts, unsigned char* buffer, int input_sample_rate, unsigned int size) { memcpy((unsigned char*)samples,buffer,size); AmMultiPartyMixer* mixer = status->getMixer(); if (AmConfig::DumpConferenceStreams) { if (!have_in_sr) { DBG("writing sample rate of %u to %s\n", input_sample_rate, (in_file_name+".samplerate").c_str()); std::ofstream ofs((in_file_name+".samplerate").c_str()); if (ofs.good()) { ofs << int2str(input_sample_rate); ofs.close(); } have_in_sr = true; } if (in_file) { in_file->write(buffer, size); } } mixer->lock(); size = resampleInput(samples,size,input_sample_rate, mixer->GetCurrentSampleRate()); mixer->PutChannelPacket(channel_id,system_ts, (unsigned char*)samples,size); mixer->unlock(); return size; } int AmConferenceChannel::get(unsigned long long system_ts, unsigned char* buffer, int output_sample_rate, unsigned int nb_samples) { if (!nb_samples || !output_sample_rate) return 0; AmMultiPartyMixer* mixer = status->getMixer(); mixer->lock(); unsigned int size = PCM16_S2B(nb_samples * mixer->GetCurrentSampleRate() / output_sample_rate); unsigned int mixer_sample_rate = 0; mixer->GetChannelPacket(channel_id,system_ts,buffer,size,mixer_sample_rate); if (AmConfig::DumpConferenceStreams) { if (!have_out_sr) { DBG("writing mixer sample rate of %u to %s\n", mixer_sample_rate, (out_file_name+".samplerate").c_str()); std::ofstream ofs((out_file_name+".samplerate").c_str()); if (ofs.good()) { ofs << int2str(mixer_sample_rate); ofs.close(); } have_out_sr = true; } if (out_file) { out_file->write(buffer, size); } } size = resampleOutput(buffer,size,mixer_sample_rate,output_sample_rate); mixer->unlock(); return size; /* will be zero if `mixer_sample_rate` isn't set */ } ChannelWritingFile::ChannelWritingFile(const char* path) : async_file(256*1024) // 256k buffer { fp = fopen(path, "w"); if (!fp) { ERROR("opening file '%s' for writing: '%s'\n", path, strerror(errno)); } } ChannelWritingFile::~ChannelWritingFile() { if (fp) fclose(fp); } int ChannelWritingFile::write_to_file(const void* buf, unsigned int len) { if (!fp) return len; size_t res = fwrite(buf, 1, len, fp); return !ferror(fp) ? res : -1; } void ChannelWritingFile::on_flushed() { DBG("file on_flushed, deleting self\n"); delete this; // uh! }