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

Generated on Thu Aug 7 16:18:58 2008 for elphel by  doxygen 1.5.1