Add jitter logic to RtpAudioStream.

Copy the jitter logic from rtp_player.c to rtp_audio_stream.cpp. This
still isn't correct but the RTP player should now be complete enough to
start looking at the bug list at the top of rtp_player_dialog.cpp.

Disable timing and jitter controls while we're playing while we're here.
Fixes bug 11635.

Bug: 11635
Change-Id: Ie583ade522702cbe1bbcea4475a535caa1d74fa2
Reviewed-on: https://code.wireshark.org/review/11295
Petri-Dish: Gerald Combs <gerald@wireshark.org>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Gerald Combs <gerald@wireshark.org>
This commit is contained in:
Gerald Combs 2015-10-26 08:34:58 -07:00
parent 25de4422c6
commit 2ccb9d2d95
6 changed files with 357 additions and 48 deletions

View File

@ -47,7 +47,6 @@ static const spx_int16_t visual_sample_rate_ = 1000;
RtpAudioStream::RtpAudioStream(QObject *parent, _rtp_stream_info *rtp_stream) :
QObject(parent),
last_sequence_(0),
decoders_hash_(rtp_decoder_hash_table_new()),
global_start_rel_time_(0.0),
start_abs_offset_(0.0),
@ -57,7 +56,9 @@ RtpAudioStream::RtpAudioStream(QObject *parent, _rtp_stream_info *rtp_stream) :
audio_resampler_(0),
audio_output_(0),
max_sample_val_(1),
color_(0)
color_(0),
jitter_buffer_size_(50),
timing_mode_(RtpAudioStream::JitterBuffer)
{
copy_address(&src_addr_, &rtp_stream->src_addr);
src_port_ = rtp_stream->src_port;
@ -148,7 +149,6 @@ void RtpAudioStream::addRtpPacket(const struct _packet_info *pinfo, const struct
void RtpAudioStream::reset(double start_rel_time)
{
last_sequence_ = 0;
global_start_rel_time_ = start_rel_time;
stop_rel_time_ = start_rel_time_;
audio_out_rate_ = 0;
@ -156,6 +156,7 @@ void RtpAudioStream::reset(double start_rel_time)
packet_timestamps_.clear();
visual_samples_.clear();
out_of_seq_timestamps_.clear();
jitter_drop_timestamps_.clear();
if (audio_resampler_) {
ws_codec_resampler_reset_mem(audio_resampler_);
@ -167,22 +168,39 @@ void RtpAudioStream::reset(double start_rel_time)
}
static const int sample_bytes_ = sizeof(SAMPLE) / sizeof(char);
/* Fix for bug 4119/5902: don't insert too many silence frames.
* XXX - is there a better thing to do here?
*/
static const int max_silence_samples_ = 240000;
void RtpAudioStream::decode()
{
if (rtp_packets_.size() < 1) return;
// gtk/rtp_player.c:decode_rtp_stream
// XXX This is more messy than it should be.
SAMPLE *decode_buff = NULL;
gsize resample_buff_len = 0x1000;
SAMPLE *resample_buff = (SAMPLE *) g_malloc(resample_buff_len);
spx_uint32_t cur_in_rate, visual_out_rate;
char *write_buff;
qint64 write_bytes;
unsigned channels;
unsigned sample_rate;
spx_uint32_t cur_in_rate = 0, visual_out_rate = 0;
char *write_buff = NULL;
qint64 write_bytes = 0;
unsigned channels = 0;
unsigned sample_rate = 0;
int last_sequence = 0;
for (int i = 0; i < rtp_packets_.size(); i++) {
rtp_packet_t *rtp_packet = rtp_packets_[i];
double rtp_time_prev = 0.0;
double arrive_time_prev = 0.0;
double pack_period = 0.0;
double start_time = 0.0;
double start_rtp_time = 0.0;
guint32 start_timestamp = 0;
size_t decoded_bytes_prev = 0;
for (int cur_packet = 0; cur_packet < rtp_packets_.size(); cur_packet++) {
SAMPLE *decode_buff = NULL;
// XXX The GTK+ UI updates a progress bar here.
rtp_packet_t *rtp_packet = rtp_packets_[cur_packet];
stop_rel_time_ = start_rel_time_ + rtp_packet->arrive_offset;
ws_codec_resampler_get_rate(visual_resampler_, &cur_in_rate, &visual_out_rate);
@ -197,33 +215,118 @@ void RtpAudioStream::decode()
payload_names_ << payload_name;
}
if (cur_packet < 1) { // First packet
start_timestamp = rtp_packet->info->info_timestamp;
start_rtp_time = 0;
rtp_time_prev = 0;
last_sequence = rtp_packet->info->info_seq_num - 1;
}
size_t decoded_bytes = decode_rtp_packet(rtp_packet, &decode_buff, decoders_hash_, &channels, &sample_rate);
if (decoded_bytes == 0)
continue; /* Didn't decode anything */
if (decoded_bytes == 0 || sample_rate == 0) {
// We didn't decode anything. Clean up and prep for the next packet.
last_sequence = rtp_packet->info->info_seq_num;
continue;
}
if (audio_out_rate_ == 0) { // First non-zero wins
audio_out_rate_ = sample_rate;
RTP_STREAM_DEBUG("Audio sample rate is %u", audio_out_rate_);
// Prepend silence to match our sibling streams.
tempfile_->seek(0);
int prepend_samples = (start_rel_time_ - global_start_rel_time_) * audio_out_rate_;
if (prepend_samples > 0) {
writeSilence(prepend_samples);
}
}
if (rtp_packet->info->info_seq_num != last_sequence+1) {
out_of_seq_timestamps_.append(stop_rel_time_);
}
last_sequence = rtp_packet->info->info_seq_num;
double rtp_time = (double)(rtp_packet->info->info_timestamp-start_timestamp)/sample_rate - start_rtp_time;
double arrive_time;
if (timing_mode_ == Uninterrupted) {
arrive_time = rtp_time;
} else {
arrive_time = (double)rtp_packet->arrive_offset/1000 - start_time;
}
double diff = qAbs(arrive_time - rtp_time);
if (diff*1000 > jitter_buffer_size_ && timing_mode_ == Uninterrupted) {
// rtp_player.c:628
jitter_drop_timestamps_.append(stop_rel_time_);
RTP_STREAM_DEBUG("Packet drop by jitter buffer exceeded %f > %d", diff*1000, jitter_buffer_size_);
/* if there was a silence period (more than two packetization period) resync the source */
if ( (rtp_time - rtp_time_prev) > pack_period*2 ){
int silence_samples;
RTP_STREAM_DEBUG("Resync...");
silence_samples = (int)((arrive_time - arrive_time_prev)*sample_rate - decoded_bytes_prev / sample_bytes_);
/* Fix for bug 4119/5902: don't insert too many silence frames.
* XXX - is there a better thing to do here?
*/
silence_samples = qMin(silence_samples, max_silence_samples_);
writeSilence(silence_samples);
silence_timestamps_.append(stop_rel_time_);
decoded_bytes_prev = 0;
/* defined start_timestmp to avoid overflow in timestamp. TODO: handle the timestamp correctly */
/* XXX: if timestamps (RTP) are missing/ignored try use packet arrive time only (see also "rtp_time") */
start_timestamp = rtp_packet->info->info_timestamp;
start_rtp_time = 0;
start_time = (double)rtp_packet->arrive_offset/1000;
rtp_time_prev = 0;
}
} else {
// rtp_player.c:664
/* Add silence if it is necessary */
int silence_samples;
if (timing_mode_ == Uninterrupted) {
silence_samples = 0;
} else {
silence_samples = (int)((rtp_time - rtp_time_prev)*sample_rate - decoded_bytes_prev / sample_bytes_);
}
if (silence_samples != 0) {
wrong_timestamp_timestamps_.append(stop_rel_time_);
}
if (silence_samples > 0) {
/* Fix for bug 4119/5902: don't insert too many silence frames.
* XXX - is there a better thing to do here?
*/
silence_samples = qMin(silence_samples, max_silence_samples_);
writeSilence(silence_samples);
silence_timestamps_.append(stop_rel_time_);
}
// XXX rtp_player.c:696 adds audio here.
rtp_time_prev = rtp_time;
pack_period = (double) decoded_bytes / sample_bytes_ / sample_rate;
decoded_bytes_prev = decoded_bytes;
arrive_time_prev = arrive_time;
}
// Write samples to our file.
write_buff = (char *) decode_buff;
write_bytes = rtp_packet->info->info_payload_len * sample_bytes_;
if (tempfile_->pos() == 0) {
// First packet. Let it determine our sample rate.
audio_out_rate_ = sample_rate;
last_sequence_ = rtp_packet->info->info_seq_num - 1;
// Prepend silence to match our sibling streams.
int prepend_samples = (start_rel_time_ - global_start_rel_time_) * audio_out_rate_;
if (prepend_samples > 0) {
int prepend_bytes = prepend_samples * sample_bytes_;
char *prepend_buff = (char *) g_malloc(prepend_bytes);
SAMPLE silence = 0;
memccpy(prepend_buff, &silence, prepend_samples, sample_bytes_);
tempfile_->write(prepend_buff, prepend_bytes);
}
} else if (audio_out_rate_ != sample_rate) {
if (audio_out_rate_ != sample_rate) {
// Resample the audio to match our previous output rate.
if (!audio_resampler_) {
audio_resampler_ = ws_codec_resampler_init(1, sample_rate, audio_out_rate_, 10, NULL);
ws_codec_resampler_skip_zeros(audio_resampler_);
// RTP_STREAM_DEBUG("Started resampling from %u to (out) %u Hz.", sample_rate, audio_out_rate_);
RTP_STREAM_DEBUG("Started resampling from %u to (out) %u Hz.", sample_rate, audio_out_rate_);
} else {
spx_uint32_t audio_out_rate;
ws_codec_resampler_get_rate(audio_resampler_, &cur_in_rate, &audio_out_rate);
@ -232,7 +335,7 @@ void RtpAudioStream::decode()
if (sample_rate != cur_in_rate) {
ws_codec_resampler_set_rate(audio_resampler_, sample_rate, audio_out_rate);
ws_codec_resampler_set_rate(visual_resampler_, sample_rate, visual_out_rate);
// RTP_STREAM_DEBUG("Changed input rate from %u to %u Hz. Out is %u.", cur_in_rate, sample_rate, audio_out_rate_);
RTP_STREAM_DEBUG("Changed input rate from %u to %u Hz. Out is %u.", cur_in_rate, sample_rate, audio_out_rate_);
}
}
spx_uint32_t in_len = (spx_uint32_t)rtp_packet->info->info_payload_len;
@ -248,12 +351,6 @@ void RtpAudioStream::decode()
write_bytes = out_len * sample_bytes_;
}
if (rtp_packet->info->info_seq_num != last_sequence_+1) {
out_of_seq_timestamps_.append(stop_rel_time_);
// XXX Add silence to tempfile_ and visual_samples_
}
last_sequence_ = rtp_packet->info->info_seq_num;
// Write the decoded, possibly-resampled audio to our temp file.
tempfile_->write(write_buff, write_bytes);
@ -328,13 +425,76 @@ const QVector<double> RtpAudioStream::outOfSequenceTimestamps(bool relative)
const QVector<double> RtpAudioStream::outOfSequenceSamples(int y_offset)
{
QVector<double> adj_samples;
double scaled_offset = y_offset * stack_offset_;
double scaled_offset = y_offset * stack_offset_; // XXX Should be different for seq, jitter, wrong & silence
for (int i = 0; i < out_of_seq_timestamps_.size(); i++) {
adj_samples.append(scaled_offset);
}
return adj_samples;
}
const QVector<double> RtpAudioStream::jitterDroppedTimestamps(bool relative)
{
if (relative) return jitter_drop_timestamps_;
QVector<double> adj_timestamps;
for (int i = 0; i < jitter_drop_timestamps_.size(); i++) {
adj_timestamps.append(jitter_drop_timestamps_[i] + start_abs_offset_);
}
return adj_timestamps;
}
const QVector<double> RtpAudioStream::jitterDroppedSamples(int y_offset)
{
QVector<double> adj_samples;
double scaled_offset = y_offset * stack_offset_; // XXX Should be different for seq, jitter, wrong & silence
for (int i = 0; i < jitter_drop_timestamps_.size(); i++) {
adj_samples.append(scaled_offset);
}
return adj_samples;
}
const QVector<double> RtpAudioStream::wrongTimestampTimestamps(bool relative)
{
if (relative) return wrong_timestamp_timestamps_;
QVector<double> adj_timestamps;
for (int i = 0; i < wrong_timestamp_timestamps_.size(); i++) {
adj_timestamps.append(wrong_timestamp_timestamps_[i] + start_abs_offset_);
}
return adj_timestamps;
}
const QVector<double> RtpAudioStream::wrongTimestampSamples(int y_offset)
{
QVector<double> adj_samples;
double scaled_offset = y_offset * stack_offset_; // XXX Should be different for seq, jitter, wrong & silence
for (int i = 0; i < wrong_timestamp_timestamps_.size(); i++) {
adj_samples.append(scaled_offset);
}
return adj_samples;
}
const QVector<double> RtpAudioStream::insertedSilenceTimestamps(bool relative)
{
if (relative) return silence_timestamps_;
QVector<double> adj_timestamps;
for (int i = 0; i < silence_timestamps_.size(); i++) {
adj_timestamps.append(silence_timestamps_[i] + start_abs_offset_);
}
return adj_timestamps;
}
const QVector<double> RtpAudioStream::insertedSilenceSamples(int y_offset)
{
QVector<double> adj_samples;
double scaled_offset = y_offset * stack_offset_; // XXX Should be different for seq, jitter, wrong & silence
for (int i = 0; i < silence_timestamps_.size(); i++) {
adj_samples.append(scaled_offset);
}
return adj_samples;
}
quint32 RtpAudioStream::nearestPacket(double timestamp, bool is_relative)
{
if (packet_timestamps_.keys().count() < 1) return 0;
@ -385,6 +545,23 @@ void RtpAudioStream::stopPlaying()
emit finishedPlaying();
}
void RtpAudioStream::writeSilence(int samples)
{
if (samples < 1 || audio_out_rate_ == 0) return;
unsigned silence_bytes = samples * sample_bytes_;
char *silence_buff = (char *) g_malloc(silence_bytes);
SAMPLE silence = 0;
RTP_STREAM_DEBUG("Writing %u silence samples", samples);
memccpy(silence_buff, &silence, samples, sample_bytes_);
tempfile_->write(silence_buff, silence_bytes);
g_free(silence_buff);
QVector<qint16> visual_fill(samples * visual_sample_rate_ / audio_out_rate_, 0);
visual_samples_ += visual_fill;
}
void RtpAudioStream::outputStateChanged()
{
if (!audio_output_) return;

View File

@ -48,6 +48,8 @@ class RtpAudioStream : public QObject
{
Q_OBJECT
public:
enum TimingMode { JitterBuffer, RtpTimestamp, Uninterrupted };
explicit RtpAudioStream(QObject *parent, struct _rtp_stream_info *rtp_stream);
~RtpAudioStream();
bool isMatch(const struct _rtp_stream_info *rtp_stream) const;
@ -88,6 +90,45 @@ public:
*/
const QVector<double> outOfSequenceSamples(int y_offset = 0);
/**
* @brief Return a list of jitter dropped timestamps.
* @return A set of timestamps suitable for passing to QCPGraph::setData.
*/
const QVector<double> jitterDroppedTimestamps(bool relative = true);
int jitterDropped() { return jitter_drop_timestamps_.size(); }
/**
* @brief Return a list of jitter dropped samples. Y value is constant.
* @param y_offset Y axis offset to be used for stacking graphs.
* @return A set of values suitable for passing to QCPGraph::setData.
*/
const QVector<double> jitterDroppedSamples(int y_offset = 0);
/**
* @brief Return a list of wrong timestamps.
* @return A set of timestamps suitable for passing to QCPGraph::setData.
*/
const QVector<double> wrongTimestampTimestamps(bool relative = true);
int wrongTimestamps() { return wrong_timestamp_timestamps_.size(); }
/**
* @brief Return a list of wrong timestamp samples. Y value is constant.
* @param y_offset Y axis offset to be used for stacking graphs.
* @return A set of values suitable for passing to QCPGraph::setData.
*/
const QVector<double> wrongTimestampSamples(int y_offset = 0);
/**
* @brief Return a list of inserted silence timestamps.
* @return A set of timestamps suitable for passing to QCPGraph::setData.
*/
const QVector<double> insertedSilenceTimestamps(bool relative = true);
int insertedSilences() { return silence_timestamps_.size(); }
/**
* @brief Return a list of wrong timestamp samples. Y value is constant.
* @param y_offset Y axis offset to be used for stacking graphs.
* @return A set of values suitable for passing to QCPGraph::setData.
*/
const QVector<double> insertedSilenceSamples(int y_offset = 0);
quint32 nearestPacket(double timestamp, bool is_relative = true);
QRgb color() { return color_; }
@ -95,6 +136,9 @@ public:
QAudio::State outputState() const;
void setJitterBufferSize(int jitter_buffer_size) { jitter_buffer_size_ = jitter_buffer_size; }
void setTimingMode(TimingMode timing_mode) { timing_mode_ = timing_mode; }
signals:
void startedPlaying();
void processedSecs(double secs);
@ -114,7 +158,6 @@ private:
quint32 ssrc_;
QVector<struct _rtp_packet *>rtp_packets_;
int last_sequence_;
QTemporaryFile *tempfile_;
struct _GHashTable *decoders_hash_;
QList<const struct _rtp_stream_info *>rtp_streams_;
@ -130,9 +173,17 @@ private:
QMap<double, quint32> packet_timestamps_;
QVector<qint16> visual_samples_;
QVector<double> out_of_seq_timestamps_;
QVector<double> jitter_drop_timestamps_;
QVector<double> wrong_timestamp_timestamps_;
QVector<double> silence_timestamps_;
qint16 max_sample_val_;
QRgb color_;
int jitter_buffer_size_;
TimingMode timing_mode_;
void writeSilence(int samples);
private slots:
void outputStateChanged();
void outputNotify();

View File

@ -183,7 +183,7 @@ void RtpPlayerDialog::retapPackets()
cap_file_.retapPackets();
remove_tap_listener(this);
rescanPackets();
rescanPackets(true);
}
void RtpPlayerDialog::rescanPackets(bool rescale_axes)
@ -209,6 +209,21 @@ void RtpPlayerDialog::rescanPackets(bool rescale_axes)
RtpAudioStream *audio_stream = ti->data(stream_data_col_, Qt::UserRole).value<RtpAudioStream*>();
int y_offset = row_count - row - 1;
audio_stream->setJitterBufferSize((int) ui->jitterSpinBox->value());
RtpAudioStream::TimingMode timing_mode = RtpAudioStream::JitterBuffer;
switch (ui->timingComboBox->currentIndex()) {
case RtpAudioStream::RtpTimestamp:
timing_mode = RtpAudioStream::RtpTimestamp;
break;
case RtpAudioStream::Uninterrupted:
timing_mode = RtpAudioStream::Uninterrupted;
break;
default:
break;
}
audio_stream->setTimingMode(timing_mode);
audio_stream->decode();
// Waveform
@ -246,6 +261,51 @@ void RtpPlayerDialog::rescanPackets(bool rescale_axes)
seq_graph->removeFromLegend();
}
}
if (audio_stream->jitterDropped() > 0) {
// Jitter drops
QCPGraph *seq_graph = ui->audioPlot->addGraph();
seq_graph->setLineStyle(QCPGraph::lsNone);
seq_graph->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, tango_scarlet_red_5, Qt::white, 4)); // Arbitrary
seq_graph->setSelectable(false);
seq_graph->setData(audio_stream->jitterDroppedTimestamps(relative_timestamps), audio_stream->jitterDroppedSamples(y_offset));
if (row < 1) {
seq_graph->setName(tr("Jitter Drops"));
show_legend = true;
} else {
seq_graph->removeFromLegend();
}
}
if (audio_stream->wrongTimestamps() > 0) {
// Wrong timestamps
QCPGraph *seq_graph = ui->audioPlot->addGraph();
seq_graph->setLineStyle(QCPGraph::lsNone);
seq_graph->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssDiamond, tango_sky_blue_5, Qt::white, 4)); // Arbitrary
seq_graph->setSelectable(false);
seq_graph->setData(audio_stream->wrongTimestampTimestamps(relative_timestamps), audio_stream->wrongTimestampSamples(y_offset));
if (row < 1) {
seq_graph->setName(tr("Wrong Timestamps"));
show_legend = true;
} else {
seq_graph->removeFromLegend();
}
}
if (audio_stream->insertedSilences() > 0) {
// Inserted silence
QCPGraph *seq_graph = ui->audioPlot->addGraph();
seq_graph->setLineStyle(QCPGraph::lsNone);
seq_graph->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssTriangle, tango_butter_5, Qt::white, 4)); // Arbitrary
seq_graph->setSelectable(false);
seq_graph->setData(audio_stream->insertedSilenceTimestamps(relative_timestamps), audio_stream->insertedSilenceSamples(y_offset));
if (row < 1) {
seq_graph->setName(tr("Inserted Silence"));
show_legend = true;
} else {
seq_graph->removeFromLegend();
}
}
}
ui->audioPlot->legend->setVisible(show_legend);
@ -381,6 +441,7 @@ void RtpPlayerDialog::updateWidgets()
{
bool enable_play = true;
bool enable_stop = false;
bool enable_timing = true;
for (int row = 0; row < ui->streamTreeWidget->topLevelItemCount(); row++) {
QTreeWidgetItem *ti = ui->streamTreeWidget->topLevelItem(row);
@ -389,12 +450,18 @@ void RtpPlayerDialog::updateWidgets()
if (audio_stream->outputState() != QAudio::IdleState) {
enable_play = false;
enable_stop = true;
enable_timing = false;
}
}
ui->playButton->setEnabled(enable_play);
ui->stopButton->setEnabled(enable_stop);
cur_play_pos_->setVisible(enable_stop);
ui->jitterSpinBox->setEnabled(enable_timing);
ui->timingComboBox->setEnabled(enable_timing);
ui->todCheckBox->setEnabled(enable_timing);
ui->audioPlot->replot();
}
@ -442,7 +509,7 @@ void RtpPlayerDialog::resetXAxis()
void RtpPlayerDialog::setPlayPosition(double secs)
{
secs+= ui->audioPlot->xAxis->range().lower;
secs+= start_rel_time_;
double cur_secs = cur_play_pos_->point1->key();
if (secs > cur_secs) {
cur_play_pos_->point1->setCoords(secs, 0.0);
@ -514,7 +581,7 @@ void RtpPlayerDialog::panXAxis(int x_pixels)
void RtpPlayerDialog::on_playButton_clicked()
{
double left = ui->audioPlot->xAxis->range().lower;
double left = start_rel_time_;
cur_play_pos_->point1->setCoords(left, 0.0);
cur_play_pos_->point2->setCoords(left, 1.0);
cur_play_pos_->setVisible(true);
@ -624,12 +691,22 @@ int RtpPlayerDialog::getHoveredPacket()
return audio_stream->nearestPacket(ts, !ui->todCheckBox->isChecked());
}
void RtpPlayerDialog::on_jitterSpinBox_valueChanged(double)
{
rescanPackets();
}
void RtpPlayerDialog::on_timingComboBox_currentIndexChanged(int)
{
rescanPackets();
}
void RtpPlayerDialog::on_todCheckBox_toggled(bool)
{
QCPAxis *x_axis = ui->audioPlot->xAxis;
double old_lowest = getLowestTimestamp();
rescanPackets(false);
rescanPackets();
x_axis->moveRange(getLowestTimestamp() - old_lowest);
ui->audioPlot->replot();
}

View File

@ -86,7 +86,7 @@ private slots:
void retapPackets();
/** Clear, decode, and redraw each stream.
*/
void rescanPackets(bool rescale_axes = true);
void rescanPackets(bool rescale_axes = false);
void updateWidgets();
void graphClicked(QMouseEvent *event);
void mouseMoved(QMouseEvent *);
@ -104,6 +104,8 @@ private slots:
void on_actionMoveRight1_triggered();
void on_actionGoToPacket_triggered();
void on_streamTreeWidget_itemSelectionChanged();
void on_jitterSpinBox_valueChanged(double);
void on_timingComboBox_currentIndexChanged(int);
void on_todCheckBox_toggled(bool checked);
void on_buttonBox_helpRequested();
@ -129,7 +131,6 @@ private:
int getHoveredPacket();
#else // QT_MULTIMEDIA_LIB
private:
Ui::RtpPlayerDialog *ui;
#endif // QT_MULTIMEDIA_LIB

View File

@ -164,10 +164,13 @@
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="doubleSpinBox">
<widget class="QDoubleSpinBox" name="jitterSpinBox">
<property name="toolTip">
<string>The simulated jitter buffer in milliseconds.</string>
</property>
<property name="decimals">
<number>0</number>
</property>
<property name="maximum">
<double>500.000000000000000</double>
</property>
@ -200,7 +203,7 @@
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBox">
<widget class="QComboBox" name="timingComboBox">
<property name="toolTip">
<string>&lt;strong&gt;Jitter Buffer&lt;/strong&gt;: Use jitter buffer to simulate the RTP stream as heard by the end user.
&lt;br/&gt;

View File

@ -110,7 +110,7 @@ struct _rtpstream_tapinfo {
gboolean is_registered; /**< if the tap listener is currently registered or not */
};
#if 0
#if 1
#define RTP_STREAM_DEBUG(...) { \
char *RTP_STREAM_DEBUG_MSG = g_strdup_printf(__VA_ARGS__); \
g_warning("rtp_stream: %s:%d %s", G_STRFUNC, __LINE__, RTP_STREAM_DEBUG_MSG); \