1 #include "AmConferenceChannel.h"
2 #include "AmConfig.h"
3 #include "AmUtils.h"
4 #include <assert.h>
5 #include <fstream>
6 #include <string.h>
7 
AmConferenceChannel(AmConferenceStatus * status,int channel_id,string channel_tag,bool own_channel)8 AmConferenceChannel::AmConferenceChannel(AmConferenceStatus* status, int channel_id, string channel_tag, bool own_channel)
9   : own_channel(own_channel), channel_id(channel_id), channel_tag(channel_tag), status(status),
10     have_in_sr(false), have_out_sr(false), in_file(NULL), out_file(NULL)
11 {
12   assert(status);
13   conf_id = status->getConfID();
14 
15   if (AmConfig::DumpConferenceStreams) {
16     in_file_name = AmConfig::DumpConferencePath + "/"+conf_id+"_"+int2str(channel_id)+"_"+long2str((long)this)+"_in.s16";
17     out_file_name = AmConfig::DumpConferencePath + "/"+conf_id+"_"+int2str(channel_id)+"_"+long2str((long)this)+"_out.s16";
18 
19     DBG("conf channel opening in_file '%s'\n", in_file_name.c_str());
20     in_file = new ChannelWritingFile(in_file_name.c_str());
21     DBG("conf channel opening out_file '%s'\n", out_file_name.c_str());
22     out_file = new ChannelWritingFile(out_file_name.c_str());
23   }
24 }
25 
~AmConferenceChannel()26 AmConferenceChannel::~AmConferenceChannel()
27 {
28   if(own_channel)
29     AmConferenceStatus::releaseChannel(conf_id,channel_id);
30 
31   if (in_file)
32     in_file->close();
33   if (out_file)
34     out_file->close();
35 
36 }
37 
put(unsigned long long system_ts,unsigned char * buffer,int input_sample_rate,unsigned int size)38 int AmConferenceChannel::put(unsigned long long system_ts, unsigned char* buffer,
39 			     int input_sample_rate, unsigned int size)
40 {
41   memcpy((unsigned char*)samples,buffer,size);
42   AmMultiPartyMixer* mixer = status->getMixer();
43 
44   if (AmConfig::DumpConferenceStreams) {
45     if (!have_in_sr) {
46       DBG("writing sample rate of %u to %s\n", input_sample_rate, (in_file_name+".samplerate").c_str());
47       std::ofstream ofs((in_file_name+".samplerate").c_str());
48       if (ofs.good()) {
49 	ofs << int2str(input_sample_rate);
50 	ofs.close();
51       }
52       have_in_sr = true;
53     }
54     if (in_file) {
55       in_file->write(buffer, size);
56     }
57   }
58 
59   mixer->lock();
60   size = resampleInput(samples,size,input_sample_rate,
61 		       mixer->GetCurrentSampleRate());
62   mixer->PutChannelPacket(channel_id,system_ts,
63 			  (unsigned char*)samples,size);
64   mixer->unlock();
65   return size;
66 }
67 
get(unsigned long long system_ts,unsigned char * buffer,int output_sample_rate,unsigned int nb_samples)68 int AmConferenceChannel::get(unsigned long long system_ts, unsigned char* buffer,
69 			     int output_sample_rate, unsigned int nb_samples)
70 {
71   if (!nb_samples || !output_sample_rate)
72     return 0;
73 
74   AmMultiPartyMixer* mixer = status->getMixer();
75   mixer->lock();
76   unsigned int size = output_sample_rate ?
77     PCM16_S2B(nb_samples * mixer->GetCurrentSampleRate() / output_sample_rate) : 0;
78   unsigned int mixer_sample_rate = 0;
79   mixer->GetChannelPacket(channel_id,system_ts,buffer,size,mixer_sample_rate);
80 
81 
82   if (AmConfig::DumpConferenceStreams) {
83     if (!have_out_sr) {
84       DBG("writing mixer sample rate of %u to %s\n", mixer_sample_rate, (out_file_name+".samplerate").c_str());
85       std::ofstream ofs((out_file_name+".samplerate").c_str());
86       if (ofs.good()) {
87 	ofs << int2str(mixer_sample_rate);
88 	ofs.close();
89       }
90       have_out_sr = true;
91     }
92     if (out_file) {
93       out_file->write(buffer, size);
94     }
95   }
96 
97   size = resampleOutput(buffer,size,mixer_sample_rate,output_sample_rate);
98   mixer->unlock();
99   return size;
100 }
101 
ChannelWritingFile(const char * path)102 ChannelWritingFile::ChannelWritingFile(const char* path)
103   : async_file(256*1024) // 256k buffer
104 {
105   fp = fopen(path, "w");
106   if (!fp) {
107     ERROR("opening file '%s' for writing: '%s'\n", path, strerror(errno));
108   }
109 }
110 
~ChannelWritingFile()111 ChannelWritingFile::~ChannelWritingFile() {
112   if (fp)
113     fclose(fp);
114 }
115 
write_to_file(const void * buf,unsigned int len)116 int ChannelWritingFile::write_to_file(const void* buf, unsigned int len) {
117   if (!fp)
118     return len;
119   size_t res = fwrite(buf, 1, len, fp);
120     return !ferror(fp) ? res : -1;
121 }
122 
on_flushed()123 void ChannelWritingFile::on_flushed() {
124   DBG("file on_flushed, deleting self\n");
125   delete this; // uh!
126 }
127