apps/astreamer/audio.cpp

Go to the documentation of this file.
00001 #include "audio.h"
00002 #include "helper.h"
00003 
00004 #include <iostream>
00005 
00006 #include <sys/ioctl.h>
00007 #include <arpa/inet.h>
00008 #include <asm/elphel/hist.h>
00009 
00010 #include <asm/elphel/c313a.h>
00011 #include <asm/elphel/hist.h>
00012 #include <asm/elphel/ext353.h>
00013 #undef AUDIO_DEBUG
00014 //#define AUDIO_DEBUG
00015 
00016 #ifdef AUDIO_DEBUG
00017         #define D(a) a
00018 #else
00019         #define D(a)
00020 #endif
00021 
00022 using namespace std;
00023 
00024 //Audio *audio = NULL;
00025 
00026 Audio::Audio(bool enable, int sample_rate, int channels) {
00027         snd_pcm_hw_params_t *hw_params;
00028         _present = false;
00029         rtc_fd = 0;
00030         stream_name = "audio";
00031 
00032         // normalize audio settings
00033         if(sample_rate == 0)
00034                 sample_rate = SAMPLE_RATE;
00035         if(sample_rate > 48000)
00036                 sample_rate = 48000;
00037         if(sample_rate < 11025)
00038                 sample_rate = 11025;
00039         if(channels == 0)
00040                 channels = SAMPLE_CHANNELS;
00041         if(channels < 1)
00042                 channels = 1;
00043         if(channels > 2)
00044                 channels = 2;
00045         
00046         SSRC = 10;
00047         _sample_rate = sample_rate;
00048         _channels = channels;
00049 //      _sample_rate = SAMPLE_RATE;
00050 //      _channels = SAMPLE_CHANNELS;
00051 //      long sample_time = 100;
00052         long sample_time = 20;
00053         sbuffer_len = _sample_rate * 2 * _channels * sample_time;
00054         sbuffer_len /= 1000;
00055         sbuffer_len -= sbuffer_len % 2;
00056 D(cerr << "sbuffer_len == " << sbuffer_len << endl;)
00057         _ptype = 97;
00058 
00059         if(enable) {
00060             // open ALSA for capturing
00061                 int err;
00062                 sbuffer = (short *)malloc(sbuffer_len * sizeof(short) * 8);
00063                 if((err = snd_pcm_open(&capture_handle, "default", SND_PCM_STREAM_CAPTURE, 0)) < 0)
00064                         return;
00065                 if((err = snd_pcm_hw_params_malloc(&hw_params)) < 0)
00066                         return;
00067                 if((err = snd_pcm_hw_params_any(capture_handle, hw_params)) < 0)
00068                         return;
00069                 if((err = snd_pcm_hw_params_set_access(capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
00070                         return;
00071                 if((err = snd_pcm_hw_params_set_format(capture_handle, hw_params, SND_PCM_FORMAT_S16_BE)) < 0)
00072                         return;
00073                 unsigned int t = _sample_rate;
00074                 if((err = snd_pcm_hw_params_set_rate_near(capture_handle, hw_params, &t, 0)) < 0)
00075                         return;
00076                 _sample_rate = t;
00077                 if((err = snd_pcm_hw_params_set_channels(capture_handle, hw_params, _channels)) < 0)
00078                         return;
00079                 if((err = snd_pcm_hw_params(capture_handle, hw_params)) < 0)
00080                         return;
00081                 snd_pcm_hw_params_free (hw_params);
00082                 if((err = snd_pcm_prepare(capture_handle)) < 0)
00083                         return;
00084 
00085 D(              cerr << endl << "Audio init: ok; with sample rate: " << _sample_rate << "; and channels: " << _channels << endl;)
00086                 _present = true;
00087 
00088                 _play = false;
00089                 // create thread...
00090                 init_pthread((void *)this);
00091         }
00092 }
00093 
00094 Audio::~Audio(void) {
00095         if(_present)
00096                 snd_pcm_close(capture_handle);
00097         if(rtc_fd)
00098                 close(rtc_fd);
00099 }
00100 
00101 void Audio::Start(string ip, long port) {
00102         if(!_present)
00103                 return;
00104 D(cerr << "Audio ---> Start !!!" << endl;)
00105         // create udp socket
00106 /*
00107         f_tv.tv_sec = 0;
00108         f_tv.tv_usec = 0;
00109 */
00110         unsigned long rtc[4];
00111         ioctl(fd_stream, _IO(IOC_STREAM_GET_TIME, 0x00), (void *)&rtc[0]);
00112         f_tv.tv_sec = rtc[2];
00113         f_tv.tv_usec = rtc[3];
00114         RTP_Stream::Start(ip, port);
00115 }
00116 
00117 void Audio::Stop(void) {
00118         if(!_present)
00119                 return;
00120 D(cerr << "Audio ---> Stop !!!" << endl;)
00121         RTP_Stream::Stop();
00122         f_tv.tv_sec = 0;
00123         f_tv.tv_usec = 0;
00124         // destroy udp socket
00125 }
00126 
00127 long Audio::capture(void) {
00128 //D(cerr << "audio: capture()" << endl;)
00129         long slen = sbuffer_len;
00130 //      void *sb = (void *)sbuffer;
00131         if((slen = snd_pcm_readi(capture_handle, sbuffer, sbuffer_len)) <= 0)
00132 //      if((slen = snd_pcm_readn(capture_handle, &sb, sbuffer_len)) <= 0)
00133                 snd_pcm_prepare(capture_handle);
00134         else {// update timestamp, and 
00135                 if(f_tv.tv_sec == 0) {
00137 //                      rtc[0] = 0;
00138 //                      rtc[1] = 0;
00139 //                      struct timeval tv;
00140 //                      gettimeofday(&tv, NULL);
00141 //                      rtc[0] = tv.tv_sec;
00142 //                      rtc[1] = tv.tv_usec;
00143 //                      rtc[0] = 1;
00144 //                      rtc[1] = 1;
00145 //D(cerr << "rtc_fd == " << rtc_fd << endl;)
00146 //                      ioctl(_fd, _IO(IOC_HIST_RTC_GET, 0x00), &rtc);
00147 /*                      
00148 char buf[32];
00149 sprintf(buf, "audio: %d:%06d\n", rtc[0], rtc[1]);
00150 D(cerr << buf << endl;)
00151 */
00152 //                      f_tv = time_sys();
00153 /*
00154                         f_tv.tv_sec = rtc[0];
00155                         f_tv.tv_usec = rtc[1];
00156                         struct timeval m;
00157                         m.tv_sec = 0;
00158                         m.tv_usec = (1000000 * slen) / _sample_rate;
00159                         f_tv = time_minus(f_tv, m);
00160 */
00161 /*
00162                         ioctl(fd_stream, _IO(IOC_STREAM_GET_TIME, 0x00), (void *)&rtc[0]);
00163                         f_tv.tv_sec = rtc[2];
00164                         f_tv.tv_usec = rtc[3];
00165 */
00166                 }
00167         }
00168 //D(cerr << "audio: capture() - end" << endl;)
00169         return slen;
00170 }
00171 
00172 //bool Audio::process(void) {
00173 long Audio::process(void) {
00174 //D(cerr << "audio: process()" << endl;)
00175         long sample_len;
00176         if((sample_len = capture()) <= 0) {
00177 D(              cerr << "nothing to send" << endl;)
00178 //              return false;
00179                 return sample_len;
00180         }
00181         
00182 //D(cerr << "audio: process()...1" << endl;)
00183         static unsigned short packet_num = 0;
00184         unsigned short pnum;
00185 //      unsigned long SSRC;
00186 //      unsigned long timestamp;
00187 //      static unsigned long old_ts = 0;
00188 
00189 //      m.t_usec = (1000000 * slen) / sample_rate;
00190         struct timeval t;
00191         t.tv_sec = 0;
00192         long long usec = sample_len;
00193         usec *= 1000000;
00194         usec /= _sample_rate;
00195 //usec *= 4;
00196 //usec /= 4;
00197         t.tv_usec = usec;
00198         f_tv = time_plus(f_tv, t);
00199 //D(cerr << "usec == " << usec;)
00200 //D(cerr << "sample_len... " << sample_len;)
00201 //D(fprintf(stderr, "0x%08X\n", t.tv_usec);)
00202 //D(cerr << "audio time: " << f_tv.tv_sec << ":" << f_tv.tv_usec << endl;)
00203 //D(cerr << "audio: process()...2" << endl;)
00204         unsigned long ts;
00205         float f = f_tv.tv_usec;
00206         f /= 1000000;
00207         f += f_tv.tv_sec;
00208         f *= _sample_rate;
00209         timestamp = (unsigned long)f;
00210 //D(cerr << "....>>>> audio ts == " << timestamp << endl;)
00211         ts = htonl(timestamp);
00212 /*
00213         timestamp = sample_len;
00214         timestamp += old_ts;
00215         old_ts = timestamp;
00216         timestamp = htonl(timestamp);
00217 */
00218         void *m = (void *)sbuffer;
00219 //D(cerr << "audio: process()...3" << endl;)
00220 
00221         int i;
00222         long offset = 0;
00223         #define LEN 1200
00224         unsigned char d[LEN + 20];
00225         int chunk = LEN;
00226         int to_send = sample_len * 2 * _channels;
00227         int size = to_send;
00228         long count = 0;
00229         for(;;) {
00230                 if(to_send == 0)
00231                         break;
00232                 if(to_send > chunk) {
00233                         i = chunk;
00234                         to_send -= i;
00235                 } else {
00236                         i = to_send;
00237                         to_send = 0;
00238                 }
00239                 packet_num++;
00240                 pnum = htons(packet_num);
00241                 count += i;
00242                 // fill RTP header
00243                 d[0] = 0x80;
00244                 if(count >= size)
00245                         d[1] = _ptype + 0x80;
00246                 else
00247                         d[1] = _ptype;
00248                 memcpy((void *)&d[2], (void *)&pnum, 2);
00249                 memcpy((void *)&d[4], (void *)&ts, 4);
00250                 memcpy((void *)&d[8], (void *)&SSRC, 4);
00251         // fill data
00252                 memcpy((void *)&d[12], (void *)((char *)m + offset), i);
00253                 offset += i;
00254                 // send packet
00255                 rtp_packets++;
00256                 rtp_octets += i; // data + MJPEG header
00257                 rtp_socket->send((void *)d, i + 12);
00258     }
00259 //D(cerr << "audio: process()...4" << endl;)
00260         return true;
00261 }

Generated on Fri Nov 28 00:06:21 2008 for elphel by  doxygen 1.5.1