Commit 07e65a43 authored by Mikhail Karpenko's avatar Mikhail Karpenko

Use delta between FPGA time and ALSA time for SR timestamps

ALSA reports monotonic timestamps regardles of the time stamps type set
by snd_pcm_params_set_tstamp_type(). Calculate delta between FPGA time
and ALSA time when audio stream starts and use this delta to correct
time stamps in SR packets.
parent 58b954f2
This diff is collapsed.
...@@ -52,10 +52,10 @@ public: ...@@ -52,10 +52,10 @@ public:
void Stop(void); void Stop(void);
protected: protected:
// int fd; // int fd;
snd_pcm_t *capture_handle; // PCM handle, returned from snd_pcm_open snd_pcm_t *capture_handle; //< PCM handle, returned from snd_pcm_open
short *sbuffer; short *sbuffer; //< buffer for sound data
long sbuffer_len; long sbuffer_len;
bool _present; // flag indicating that audio interface has been initialized bool _present; //< flag indicating that audio interface has been initialized
long _sample_rate; long _sample_rate;
long _channels; long _channels;
long _volume; long _volume;
...@@ -66,9 +66,13 @@ protected: ...@@ -66,9 +66,13 @@ protected:
void set_capture_volume(int volume); void set_capture_volume(int volume);
uint64_t timestamp_rtcp; uint64_t timestamp_rtcp;
long delta_fpga_sys; // A/V clocks delta for RTCP long delta_fpga_sys; //< A/V clocks delta for RTCP
// bool is_first; // bool is_first;
// bool is_first2; // bool is_first2;
long long delta_fpga_alsa; //< time delta between FPGA time and time reported by ALSA, in microseconds
unsigned char *packet_buffer; //< buffer for RTP packet data (header plus PCM samples)
private:
long long get_delta_fpga_alsa(void); //< return time delta between FPGA time and time stamps reported by ALSA, in microseconds
}; };
#endif // _AUDIO__H_ #endif // _AUDIO__H_
/** /**
* @file FILENAME * @file helper.h
* @brief BRIEF DESCRIPTION * @brief Various time helper functions to work with \e timeval structures
* @copyright Copyright (C) YEAR Elphel Inc. * @copyright Copyright (C) 2017 Elphel Inc.
* @author AUTHOR <EMAIL> * @author AUTHOR <EMAIL>
* *
* @par License: * @par License:
...@@ -54,4 +54,19 @@ inline struct timeval time_minus(struct timeval tv_1, const struct timeval &tv_2 ...@@ -54,4 +54,19 @@ inline struct timeval time_minus(struct timeval tv_1, const struct timeval &tv_2
return tv_1; return tv_1;
} }
#endif /**
* @brief Add microseconds to a value represented by \e timeval structure
* @param tv time to which microseconds should be added
* @param us the value of microseconds
* @return The sum of two values
*/
inline struct timeval time_plus_us(struct timeval &tv, unsigned long us)
{
tv.tv_usec += us;
tv.tv_sec += tv.tv_usec / 1000000;
tv.tv_usec = tv.tv_usec % 1000000;
return tv;
}
#endif /* __H_HELPER__ */
...@@ -119,3 +119,19 @@ bool Parameters::daemon_enabled(void) { ...@@ -119,3 +119,19 @@ bool Parameters::daemon_enabled(void) {
void Parameters::setPValue(unsigned long *val_array, int count) { void Parameters::setPValue(unsigned long *val_array, int count) {
this->write(val_array, sizeof(unsigned long) * count); this->write(val_array, sizeof(unsigned long) * count);
} }
/**
* @brief Get current FPGA time
* @return Time value in \e timeval structure
*/
struct timeval Parameters::get_fpga_time(void)
{
struct timeval tv;
unsigned long write_data[] = {FRAMEPARS_GETFPGATIME, 0};
write(write_data, sizeof(unsigned long) * 2);
tv.tv_sec = getGPValue(G_SECONDS);
tv.tv_usec = getGPValue(G_MICROSECONDS);
return tv;
}
...@@ -48,6 +48,7 @@ public: ...@@ -48,6 +48,7 @@ public:
bool daemon_enabled(void); bool daemon_enabled(void);
void setPValue(unsigned long *val_array, int count); void setPValue(unsigned long *val_array, int count);
inline int get_port_num() const {return sensor_port;} inline int get_port_num() const {return sensor_port;}
struct timeval get_fpga_time(void);
protected: protected:
// static Parameters *_parameters; // static Parameters *_parameters;
......
...@@ -50,21 +50,19 @@ protected: ...@@ -50,21 +50,19 @@ protected:
static void *pthread_f(void *_this); static void *pthread_f(void *_this);
void *thread(void); void *thread(void);
pthread_mutex_t pthm_flow; pthread_mutex_t pthm_flow;
// virtual bool process(void) = 0;
virtual long process(void) = 0; virtual long process(void) = 0;
int _ptype; int _ptype;
bool _play; bool _play;
/// semaphore to wait 'play' event sem_t sem_play; //< semaphore to wait 'play' event
sem_t sem_play;
Socket *rtp_socket; Socket *rtp_socket;
Socket *rtcp_socket; Socket *rtcp_socket;
unsigned short packet_num; unsigned short packet_num; //< sequence number in RTP packet header
unsigned long SSRC; unsigned long SSRC;
struct timeval f_tv; struct timeval f_tv;
struct timeval rtcp_tv; // time of last SR struct timeval rtcp_tv; //< time of last SR
long rtcp_delay; long rtcp_delay;
unsigned long timestamp; unsigned long timestamp;
......
...@@ -278,7 +278,8 @@ int Streamer::update_settings(bool apply) { ...@@ -278,7 +278,8 @@ int Streamer::update_settings(bool apply) {
f_audio_channels = true; f_audio_channels = true;
if ((audio_proc || session->process_audio) && (f_audio_rate || f_audio_channels)) if ((audio_proc || session->process_audio) && (f_audio_rate || f_audio_channels))
audio_was_changed = true; audio_was_changed = true;
D(sensor_port, cerr << "audio_proc = " << audio_proc << ", process_audio = " << session->process_audio << ", f_audio_rate = " << f_audio_rate << "f_audio_channels = " << f_audio_channels << endl); D(sensor_port, cerr << "audio_proc = " << audio_proc << ", process_audio = " << session->process_audio << ", f_audio_rate = " << f_audio_rate
<< ", f_audio_channels = " << f_audio_channels << endl);
if (apply) { if (apply) {
bool audio_restarted = false; bool audio_restarted = false;
if (audio_was_changed) { if (audio_was_changed) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment