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