RTP Stream Analysis: Process more streams than two, audio save removed

This commit is contained in:
j.novak@netsystem.cz 2021-04-07 05:40:09 +00:00 committed by Wireshark GitLab Utility
parent fe7bf413fc
commit 2b072b8e76
11 changed files with 746 additions and 1475 deletions

View File

@ -77,6 +77,7 @@
#include <ui/qt/models/pref_models.h>
#include "rtp_stream_dialog.h"
#include "voip_calls_dialog.h"
#include "rtp_analysis_dialog.h"
class AccordionFrame;
class ByteViewTab;
@ -250,6 +251,7 @@ private:
QPointer<VoipCallsDialog> voip_calls_dialog_; // Singleton pattern used
QPointer<VoipCallsDialog> sip_calls_dialog_; // Singleton pattern used
QPointer<RtpPlayerDialog> rtp_player_dialog_; // Singleton pattern used
QPointer<RtpAnalysisDialog> rtp_analysis_dialog_; // Singleton pattern used
void freeze();
void thaw();
@ -312,9 +314,6 @@ signals:
void framesSelected(QList<int>);
void captureActive(int);
void replaceRtpStreams(QVector<rtpstream_info_t *> stream_infos);
void addRtpStreams(QVector<rtpstream_info_t *> stream_infos);
void removeRtpStreams(QVector<rtpstream_info_t *> stream_infos);
void selectRtpStream(rtpstream_id_t *id);
void deselectRtpStream(rtpstream_id_t *id);
@ -367,6 +366,9 @@ public slots:
void rtpPlayerDialogReplaceRtpStreams(QVector<rtpstream_info_t *> stream_infos);
void rtpPlayerDialogAddRtpStreams(QVector<rtpstream_info_t *> stream_infos);
void rtpPlayerDialogRemoveRtpStreams(QVector<rtpstream_info_t *> stream_infos);
void rtpAnalysisDialogReplaceRtpStreams(QVector<rtpstream_info_t *> stream_infos);
void rtpAnalysisDialogAddRtpStreams(QVector<rtpstream_info_t *> stream_infos);
void rtpAnalysisDialogRemoveRtpStreams(QVector<rtpstream_info_t *> stream_infos);
void rtpStreamsDialogSelectRtpStream(rtpstream_id_t *id);
void rtpStreamsDialogDeselectRtpStream(rtpstream_id_t *id);
@ -686,6 +688,7 @@ private slots:
void openTelephonyRtpStreamsDialog();
void openTelephonyRtpPlayerDialog();
void openTelephonyVoipCallsDialog(bool all_flows);
void openTelephonyRtpAnalysisDialog();
void on_actionTelephonyVoipCalls_triggered();
void on_actionTelephonyGsmMapSummary_triggered();
void statCommandLteMacStatistics(const char *arg, void *);

View File

@ -3311,12 +3311,6 @@ void MainWindow::openTelephonyRtpPlayerDialog()
connect(rtp_player_dialog_, SIGNAL(goToPacket(int)),
packet_list_, SLOT(goToPacket(int)));
connect(this, SIGNAL(replaceRtpStreams(QVector<rtpstream_info_t *>)),
rtp_player_dialog_, SLOT(replaceRtpStreams(QVector<rtpstream_info_t *>)));
connect(this, SIGNAL(addRtpStreams(QVector<rtpstream_info_t *>)),
rtp_player_dialog_, SLOT(addRtpStreams(QVector<rtpstream_info_t *>)));
connect(this, SIGNAL(removeRtpStreams(QVector<rtpstream_info_t *>)),
rtp_player_dialog_, SLOT(removeRtpStreams(QVector<rtpstream_info_t *>)));
}
rtp_player_dialog_->show();
}
@ -3356,6 +3350,23 @@ void MainWindow::openTelephonyVoipCallsDialog(bool all_flows)
dlg->show();
}
void MainWindow::openTelephonyRtpAnalysisDialog()
{
if (!rtp_analysis_dialog_) {
rtp_analysis_dialog_ = new RtpAnalysisDialog(*this, capture_file_);
connect(rtp_analysis_dialog_, SIGNAL(goToPacket(int)),
packet_list_, SLOT(goToPacket(int)));
connect(rtp_analysis_dialog_, SIGNAL(rtpPlayerDialogReplaceRtpStreams(QVector<rtpstream_info_t *>)),
this, SLOT(rtpPlayerDialogReplaceRtpStreams(QVector<rtpstream_info_t *>)));
connect(rtp_analysis_dialog_, SIGNAL(rtpPlayerDialogAddRtpStreams(QVector<rtpstream_info_t *>)),
this, SLOT(rtpPlayerDialogAddRtpStreams(QVector<rtpstream_info_t *>)));
connect(rtp_analysis_dialog_, SIGNAL(rtpPlayerDialogRemoveRtpStreams(QVector<rtpstream_info_t *>)),
this, SLOT(rtpPlayerDialogRemoveRtpStreams(QVector<rtpstream_info_t *>)));
}
rtp_analysis_dialog_->show();
}
void MainWindow::on_actionTelephonyVoipCalls_triggered()
{
openTelephonyVoipCallsDialog(false);
@ -3447,7 +3458,6 @@ void MainWindow::openTelephonyRtpStreamsDialog()
{
if (!rtp_stream_dialog_) {
rtp_stream_dialog_ = new RtpStreamDialog(*this, capture_file_);
connect(rtp_stream_dialog_, SIGNAL(packetsMarked()),
packet_list_, SLOT(redrawVisiblePackets()));
connect(rtp_stream_dialog_, SIGNAL(goToPacket(int)),
@ -3462,8 +3472,12 @@ void MainWindow::openTelephonyRtpStreamsDialog()
this, SLOT(rtpPlayerDialogAddRtpStreams(QVector<rtpstream_info_t *>)));
connect(rtp_stream_dialog_, SIGNAL(rtpPlayerDialogRemoveRtpStreams(QVector<rtpstream_info_t *>)),
this, SLOT(rtpPlayerDialogRemoveRtpStreams(QVector<rtpstream_info_t *>)));
connect(this, SIGNAL(selectRtpStream(rtpstream_id_t *)), rtp_stream_dialog_, SLOT(selectRtpStream(rtpstream_id_t *)));
connect(this, SIGNAL(deselectRtpStream(rtpstream_id_t *)), rtp_stream_dialog_, SLOT(deselectRtpStream(rtpstream_id_t *)));
connect(rtp_stream_dialog_, SIGNAL(rtpAnalysisDialogReplaceRtpStreams(QVector<rtpstream_info_t *>)),
this, SLOT(rtpAnalysisDialogReplaceRtpStreams(QVector<rtpstream_info_t *>)));
connect(rtp_stream_dialog_, SIGNAL(rtpAnalysisDialogAddRtpStreams(QVector<rtpstream_info_t *>)),
this, SLOT(rtpAnalysisDialogAddRtpStreams(QVector<rtpstream_info_t *>)));
connect(rtp_stream_dialog_, SIGNAL(rtpAnalysisDialogRemoveRtpStreams(QVector<rtpstream_info_t *>)),
this, SLOT(rtpAnalysisDialogRemoveRtpStreams(QVector<rtpstream_info_t *>)));
}
rtp_stream_dialog_->show();
}
@ -3475,16 +3489,8 @@ void MainWindow::on_actionTelephonyRtpStreams_triggered()
void MainWindow::on_actionTelephonyRtpStreamAnalysis_triggered()
{
RtpAnalysisDialog *rtp_analysis_dialog = new RtpAnalysisDialog(*this, capture_file_);
connect(rtp_analysis_dialog, SIGNAL(goToPacket(int)),
packet_list_, SLOT(goToPacket(int)));
connect(rtp_analysis_dialog, SIGNAL(rtpPlayerDialogReplaceRtpStreams(QVector<rtpstream_info_t *>)),
this, SLOT(rtpPlayerDialogReplaceRtpStreams(QVector<rtpstream_info_t *>)));
connect(rtp_analysis_dialog, SIGNAL(rtpPlayerDialogAddRtpStreams(QVector<rtpstream_info_t *>)),
this, SLOT(rtpPlayerDialogAddRtpStreams(QVector<rtpstream_info_t *>)));
connect(rtp_analysis_dialog, SIGNAL(rtpPlayerDialogRemoveRtpStreams(QVector<rtpstream_info_t *>)),
this, SLOT(rtpPlayerDialogRemoveRtpStreams(QVector<rtpstream_info_t *>)));
rtp_analysis_dialog->show();
openTelephonyRtpAnalysisDialog();
rtp_analysis_dialog_->findRtpStreams();
}
void MainWindow::on_actionTelephonyRTSPPacketCounter_triggered()
@ -4061,31 +4067,49 @@ void MainWindow::activatePluginIFToolbar(bool)
void MainWindow::rtpPlayerDialogReplaceRtpStreams(QVector<rtpstream_info_t *> stream_infos)
{
openTelephonyRtpPlayerDialog();
emit replaceRtpStreams(stream_infos);
rtp_player_dialog_->replaceRtpStreams(stream_infos);
}
void MainWindow::rtpPlayerDialogAddRtpStreams(QVector<rtpstream_info_t *> stream_infos)
{
openTelephonyRtpPlayerDialog();
emit addRtpStreams(stream_infos);
rtp_player_dialog_->addRtpStreams(stream_infos);
}
void MainWindow::rtpPlayerDialogRemoveRtpStreams(QVector<rtpstream_info_t *> stream_infos)
{
openTelephonyRtpPlayerDialog();
emit removeRtpStreams(stream_infos);
rtp_player_dialog_->removeRtpStreams(stream_infos);
}
void MainWindow::rtpAnalysisDialogReplaceRtpStreams(QVector<rtpstream_info_t *> stream_infos)
{
openTelephonyRtpAnalysisDialog();
rtp_analysis_dialog_->replaceRtpStreams(stream_infos);
}
void MainWindow::rtpAnalysisDialogAddRtpStreams(QVector<rtpstream_info_t *> stream_infos)
{
openTelephonyRtpAnalysisDialog();
rtp_analysis_dialog_->addRtpStreams(stream_infos);
}
void MainWindow::rtpAnalysisDialogRemoveRtpStreams(QVector<rtpstream_info_t *> stream_infos)
{
openTelephonyRtpAnalysisDialog();
rtp_analysis_dialog_->removeRtpStreams(stream_infos);
}
void MainWindow::rtpStreamsDialogSelectRtpStream(rtpstream_id_t *id)
{
openTelephonyRtpStreamsDialog();
emit selectRtpStream(id);
rtp_stream_dialog_->selectRtpStream(id);
}
void MainWindow::rtpStreamsDialogDeselectRtpStream(rtpstream_id_t *id)
{
openTelephonyRtpStreamsDialog();
emit deselectRtpStream(id);
rtp_stream_dialog_->deselectRtpStream(id);
}
#ifdef _MSC_VER

File diff suppressed because it is too large Load Diff

View File

@ -20,9 +20,12 @@
#include "ui/tap-rtp-common.h"
#include "ui/tap-rtp-analysis.h"
#include <QAbstractButton>
#include <QMenu>
#include <QTreeWidget>
#include <QLabel>
#include <QFile>
#include <QCheckBox>
#include <QHBoxLayout>
#include "wireshark_dialog.h"
@ -32,6 +35,26 @@ class RtpAnalysisDialog;
class QCPGraph;
class QTemporaryFile;
class QDialogButtonBox;
typedef struct {
rtpstream_info_t stream;
QVector<double> *time_vals;
QVector<double> *jitter_vals;
QVector<double> *diff_vals;
QVector<double> *delta_vals;
QTreeWidget *tree_widget;
QLabel *statistics_label;
QString *tab_name;
QCPGraph *jitter_graph;
QCPGraph *diff_graph;
QCPGraph *delta_graph;
QHBoxLayout *graphHorizontalLayout;
QCheckBox *stream_checkbox;
QCheckBox *jitter_checkbox;
QCheckBox *diff_checkbox;
QCheckBox *delta_checkbox;
} tab_info_t;
class RtpAnalysisDialog : public WiresharkDialog
{
@ -40,6 +63,24 @@ class RtpAnalysisDialog : public WiresharkDialog
public:
explicit RtpAnalysisDialog(QWidget &parent, CaptureFile &cf, rtpstream_info_t *stream_fwd = 0, rtpstream_info_t *stream_rev = 0);
~RtpAnalysisDialog();
/**
* @brief Common routine to add a "Analyze" button to a QDialogButtonBox.
* @param button_box Caller's QDialogButtonBox.
* @return The new "Analyze" button.
*/
static QPushButton *addAnalyzeButton(QDialogButtonBox *button_box, QDialog *dialog);
/** Replace/Add/Remove an RTP streams to analyse.
* Requires array of rtpstream_info_t.
* Each item must have filled items: src_addr, src_port, dest_addr,
* dest_port, ssrc, packet_count, setup_frame_number, and start_rel_time.
*
* @param rtpstream struct with rtpstream info
*/
void replaceRtpStreams(QVector<rtpstream_info_t *> stream_infos);
void addRtpStreams(QVector<rtpstream_info_t *> stream_infos);
void removeRtpStreams(QVector<rtpstream_info_t *> stream_infos);
void findRtpStreams();
signals:
void goToPacket(int packet_num);
@ -58,102 +99,54 @@ protected slots:
private slots:
void on_actionGoToPacket_triggered();
void on_actionNextProblem_triggered();
void on_fJitterCheckBox_toggled(bool checked);
void on_fDiffCheckBox_toggled(bool checked);
void on_fDeltaCheckBox_toggled(bool checked);
void on_rJitterCheckBox_toggled(bool checked);
void on_rDiffCheckBox_toggled(bool checked);
void on_rDeltaCheckBox_toggled(bool checked);
void on_actionSaveAudioUnsync_triggered();
void on_actionSaveForwardAudioUnsync_triggered();
void on_actionSaveReverseAudioUnsync_triggered();
void on_actionSaveAudioSyncStream_triggered();
void on_actionSaveForwardAudioSyncStream_triggered();
void on_actionSaveReverseAudioSyncStream_triggered();
void on_actionSaveAudioSyncFile_triggered();
void on_actionSaveForwardAudioSyncFile_triggered();
void on_actionSaveReverseAudioSyncFile_triggered();
void on_actionSaveCsv_triggered();
void on_actionSaveForwardCsv_triggered();
void on_actionSaveReverseCsv_triggered();
void on_actionSaveOneCsv_triggered();
void on_actionSaveAllCsv_triggered();
void on_actionSaveGraph_triggered();
void on_buttonBox_helpRequested();
void showStreamMenu(QPoint pos);
void graphClicked(QMouseEvent *event);
void closeTab(int index);
void rowCheckboxChanged(int checked);
void singleCheckboxChanged(int checked);
private:
Ui::RtpAnalysisDialog *ui;
enum StreamDirection { dir_both_, dir_forward_, dir_reverse_ };
enum SyncType { sync_unsync_, sync_sync_stream_, sync_sync_file_ };
enum StreamDirection { dir_all_, dir_one_ };
int tab_seq;
/* Save Audio Errors */
bool sae_stopped_;
bool sae_file_error_;
bool sae_unsupported_codec_;
bool sae_unsupported_rate_;
bool sae_other_error_;
int num_streams_;
rtpstream_info_t fwd_statinfo_;
rtpstream_info_t rev_statinfo_;
QVector<tab_info_t *> tabs_;
QPushButton *player_button_;
QTemporaryFile *fwd_tempfile_;
QTemporaryFile *rev_tempfile_;
// Graph data for QCustomPlot
QList<QCPGraph *>graphs_;
QVector<double> fwd_time_vals_;
QVector<double> fwd_jitter_vals_;
QVector<double> fwd_diff_vals_;
QVector<double> fwd_delta_vals_;
QVector<double> rev_time_vals_;
QVector<double> rev_jitter_vals_;
QVector<double> rev_diff_vals_;
QVector<double> rev_delta_vals_;
rtpstream_tapinfo_t tapinfo_;
QString err_str_;
tap_rtp_error_type_t save_payload_error_;
QMenu stream_ctx_menu_;
QMenu graph_ctx_menu_;
void findStreams();
// Tap callbacks
static void tapReset(void *tapinfo_ptr);
static tap_packet_status tapPacket(void *tapinfo_ptr, packet_info *pinfo, epan_dissect_t *, const void *rtpinfo_ptr);
static void tapDraw(void *tapinfo_ptr);
void resetStatistics();
void addPacket(bool forward, packet_info *pinfo, const struct _rtp_info *rtpinfo);
void savePayload(QTemporaryFile *tmpfile, tap_rtp_stat_t *statinfo, packet_info *pinfo, const struct _rtp_info *rtpinfo);
void addPacket(tab_info_t *tab, packet_info *pinfo, const struct _rtp_info *rtpinfo);
void updateStatistics();
void updateGraph();
void showPlayer();
size_t convert_payload_to_samples(unsigned int payload_type, const gchar *payload_type_names[256], QTemporaryFile *tempfile, uint8_t *pd_out, size_t expected_nchars, struct _GHashTable *decoders_hash);
bool saveAudioAUSilence(size_t total_len, QFile *save_file, gboolean *stop_flag);
bool saveAudioAUUnidir(tap_rtp_stat_t &statinfo, const gchar *payload_type_names[256], QTemporaryFile *tempfile, QFile *save_file, int64_t header_end, gboolean *stop_flag, gboolean interleave, size_t prefix_silence);
bool saveAudioAUBidir(tap_rtp_stat_t &fwd_statinfo, tap_rtp_stat_t &rev_statinfo, const gchar *fwd_payload_type_names[256], const gchar *rev_payload_type_names[256], QTemporaryFile *fwd_tempfile, QTemporaryFile *rev_tempfile, QFile *save_file, int64_t header_end, gboolean *stop_flag, size_t prefix_silence_fwd, size_t prefix_silence_rev);
bool saveAudioAU(StreamDirection direction, QFile *save_file, gboolean *stop_flag, RtpAnalysisDialog::SyncType sync);
bool saveAudioRAW(StreamDirection direction, QFile *save_file, gboolean *stop_flag);
void saveAudio(StreamDirection direction, RtpAnalysisDialog::SyncType sync);
void saveCsvData(QFile *save_file, QTreeWidget *tree);
void saveCsv(StreamDirection direction);
uint32_t processNode(proto_node *ptree_node, header_field_info *hfinformation, const gchar* proto_field, bool *ok);
uint32_t getIntFromProtoTree(proto_tree *protocol_tree, const gchar *proto_name, const gchar *proto_field, bool *ok);
bool eventFilter(QObject*, QEvent* event);
void clearSAEErrors();
bool isSAEOK();
QVector<rtpstream_info_t *>getSelectedRtpStreams();
int addTabUI(tab_info_t *new_tab);
tab_info_t *getTabInfoForCurrentTab();
void deleteTabInfo(tab_info_t *tab_info);
void clearLayout(QLayout *layout);
};
#endif // RTP_ANALYSIS_DIALOG_H

View File

@ -16,123 +16,11 @@
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="statisticsLabel">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:medium; font-weight:600;&quot;&gt;Forward&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-size:medium; font-weight:600;&quot;&gt;Reverse&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QTreeWidget" name="forwardTreeWidget">
<property name="rootIsDecorated">
<bool>false</bool>
</property>
<property name="uniformRowHeights">
<bool>true</bool>
</property>
<property name="itemsExpandable">
<bool>false</bool>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<property name="expandsOnDoubleClick">
<bool>false</bool>
</property>
<attribute name="title">
<string>Forward</string>
</attribute>
<column>
<property name="text">
<string>Packet</string>
</property>
</column>
<column>
<property name="text">
<string>Sequence</string>
</property>
</column>
<column>
<property name="text">
<string>Delta (ms)</string>
</property>
</column>
<column>
<property name="text">
<string>Jitter (ms)</string>
</property>
</column>
<column>
<property name="text">
<string>Skew</string>
</property>
</column>
<column>
<property name="text">
<string>Bandwidth</string>
</property>
</column>
<column>
<property name="text">
<string>Marker</string>
</property>
</column>
<column>
<property name="text">
<string>Status</string>
</property>
</column>
</widget>
<widget class="QTreeWidget" name="reverseTreeWidget">
<property name="rootIsDecorated">
<bool>false</bool>
</property>
<property name="uniformRowHeights">
<bool>true</bool>
</property>
<property name="itemsExpandable">
<bool>false</bool>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<attribute name="title">
<string>Reverse</string>
</attribute>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
<widget class="QWidget" name="graphTab">
<attribute name="title">
<string>Graph</string>
@ -141,152 +29,6 @@
<item>
<widget class="QCustomPlot" name="streamGraph" native="true"/>
</item>
<item>
<layout class="QHBoxLayout" name="forwardHorizontalLayout" stretch="0,0,0,0,0,1">
<item>
<widget class="QCheckBox" name="fJitterCheckBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Show or hide forward jitter values.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Forward Jitter</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>5</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="fDiffCheckBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Show or hide forward difference values.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Forward Difference</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>5</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="fDeltaCheckBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Show or hide forward delta values.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Forward Delta</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>5</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="reverseHorizontalLayout" stretch="0,0,0,0,0,1">
<item>
<widget class="QCheckBox" name="rJitterCheckBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Show or hide reverse jitter values.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Reverse Jitter</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>5</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="rDiffCheckBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Show or hide reverse difference values.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Reverse Difference</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>5</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="rDeltaCheckBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Show or hide reverse delta values.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Reverse Delta</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>5</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
@ -336,52 +78,28 @@
<string>Open export menu</string>
</property>
</action>
<action name="actionSaveAudioUnsync">
<property name="text">
<string>Unsynchronized Forward and Reverse Audio</string>
</property>
<property name="toolTip">
<string>Save the unsynchronized audio data for both channels.</string>
</property>
</action>
<action name="actionSaveForwardAudioUnsync">
<property name="text">
<string>Unsynchronized Forward Stream Audio</string>
</property>
<property name="toolTip">
<string>Save the unsynchronized forward stream audio data.</string>
</property>
</action>
<action name="actionSaveReverseAudioUnsync">
<property name="text">
<string>Unsynchronized Reverse Stream Audio</string>
</property>
<property name="toolTip">
<string>Save the unsynchronized reverse stream audio data.</string>
</property>
</action>
<action name="actionSaveCsv">
<property name="text">
<string>CSV</string>
</property>
<property name="toolTip">
<string>Save both tables as CSV.</string>
<string>Save tables as CSV.</string>
</property>
</action>
<action name="actionSaveForwardCsv">
<action name="actionSaveOneCsv">
<property name="text">
<string>Forward Stream CSV</string>
<string>Current Tab Stream CSV</string>
</property>
<property name="toolTip">
<string>Save the forward table as CSV.</string>
<string>Save the table on the current tab as CSV.</string>
</property>
</action>
<action name="actionSaveReverseCsv">
<action name="actionSaveAllCsv">
<property name="text">
<string>Reverse Stream CSV</string>
<string>All Tab Streams CSV</string>
</property>
<property name="toolTip">
<string>Save the reverse table as CSV.</string>
<string>Save the table from all tabs as CSV.</string>
</property>
</action>
<action name="actionSaveGraph">
@ -414,54 +132,6 @@
<string>N</string>
</property>
</action>
<action name="actionSaveAudioSyncStream">
<property name="text">
<string>Stream Synchronized Forward and Reverse Audio</string>
</property>
<property name="toolTip">
<string>Save the audio data for both channels synchronized to start of earlier stream.</string>
</property>
</action>
<action name="actionSaveForwardAudioSyncStream">
<property name="text">
<string>Stream Synchronized Forward Stream Audio</string>
</property>
<property name="toolTip">
<string>Save the forward stream audio data synchronized to start of earlier stream.</string>
</property>
</action>
<action name="actionSaveReverseAudioSyncStream">
<property name="text">
<string>Stream Synchronized Reverse Stream Audio</string>
</property>
<property name="toolTip">
<string>Save the reverse stream audio data synchronized to start of earlier stream.</string>
</property>
</action>
<action name="actionSaveAudioSyncFile">
<property name="text">
<string>File Synchronized Forward and Reverse Audio</string>
</property>
<property name="toolTip">
<string>Save the audio data for both channels synchronized to start of file.</string>
</property>
</action>
<action name="actionSaveForwardAudioSyncFile">
<property name="text">
<string>File Synchronized Forward Stream Audio</string>
</property>
<property name="toolTip">
<string>Save the forward stream audio data synchronized to start of file.</string>
</property>
</action>
<action name="actionSaveReverseAudioSyncFile">
<property name="text">
<string>File Synchronized Reverse Stream Audio</string>
</property>
<property name="toolTip">
<string>Save the reverse stream audio data synchronized to start of file.</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>

View File

@ -14,6 +14,7 @@
#ifdef QT_MULTIMEDIA_LIB
#include <epan/dissectors/packet-rtp.h>
#include <epan/to_str.h>
#include <wsutil/report_message.h>
#include <wsutil/utf8_entities.h>

View File

@ -62,7 +62,6 @@ public:
* @param button_box Caller's QDialogButtonBox.
* @return The new "Play call" button.
*/
// XXX We might want to move this to qt_ui_utils.
static QPushButton *addPlayerButton(QDialogButtonBox *button_box, QDialog *dialog);
#ifdef QT_MULTIMEDIA_LIB
@ -73,7 +72,6 @@ public:
void setMarkers();
public slots:
/** Replace/Add/Remove an RTP streams to play.
* Requires array of rtpstream_info_t.
* Each item must have filled items: src_addr, src_port, dest_addr,

View File

@ -273,8 +273,7 @@ RtpStreamDialog::RtpStreamDialog(QWidget &parent, CaptureFile &cf) :
// this? Perhaps you should volunteer to maintain this code!
find_reverse_button_ = ui->buttonBox->addButton(ui->actionFindReverse->text(), QDialogButtonBox::ActionRole);
find_reverse_button_->setToolTip(ui->actionFindReverse->toolTip());
analyze_button_ = ui->buttonBox->addButton(ui->actionAnalyze->text(), QDialogButtonBox::ActionRole);
analyze_button_->setToolTip(ui->actionAnalyze->toolTip());
analyze_button_ = RtpAnalysisDialog::addAnalyzeButton(ui->buttonBox, this);
prepare_button_ = ui->buttonBox->addButton(ui->actionPrepareFilter->text(), QDialogButtonBox::ActionRole);
prepare_button_->setToolTip(ui->actionPrepareFilter->toolTip());
player_button_ = RtpPlayerDialog::addPlayerButton(ui->buttonBox, this);
@ -619,26 +618,6 @@ void RtpStreamDialog::showStreamMenu(QPoint pos)
ctx_menu_.popup(ui->streamTreeWidget->viewport()->mapToGlobal(pos));
}
void RtpStreamDialog::on_actionAnalyze_triggered()
{
rtpstream_info_t *stream_a, *stream_b = NULL;
QTreeWidgetItem *ti = ui->streamTreeWidget->selectedItems()[0];
RtpStreamTreeWidgetItem *rsti = static_cast<RtpStreamTreeWidgetItem*>(ti);
stream_a = rsti->streamInfo();
if (ui->streamTreeWidget->selectedItems().count() > 1) {
ti = ui->streamTreeWidget->selectedItems()[1];
rsti = static_cast<RtpStreamTreeWidgetItem*>(ti);
stream_b = rsti->streamInfo();
}
if (stream_a == NULL && stream_b == NULL) return;
RtpAnalysisDialog *rtp_analysis_dialog = new RtpAnalysisDialog(*this, cap_file_, stream_a, stream_b);
connect(rtp_analysis_dialog, SIGNAL(goToPacket(int)), this, SIGNAL(goToPacket(int)));
rtp_analysis_dialog->show();
}
void RtpStreamDialog::on_actionCopyAsCsv_triggered()
{
QString csv;
@ -807,8 +786,6 @@ void RtpStreamDialog::on_buttonBox_clicked(QAbstractButton *button)
on_actionPrepareFilter_triggered();
} else if (button == export_button_) {
on_actionExportAsRtpDump_triggered();
} else if (button == analyze_button_) {
on_actionAnalyze_triggered();
}
}
@ -891,6 +868,27 @@ void RtpStreamDialog::rtpPlayerRemove()
emit rtpPlayerDialogRemoveRtpStreams(getSelectedRtpStreams());
}
void RtpStreamDialog::rtpAnalysisReplace()
{
if (ui->streamTreeWidget->selectedItems().count() < 1) return;
emit rtpAnalysisDialogReplaceRtpStreams(getSelectedRtpStreams());
}
void RtpStreamDialog::rtpAnalysisAdd()
{
if (ui->streamTreeWidget->selectedItems().count() < 1) return;
emit rtpAnalysisDialogAddRtpStreams(getSelectedRtpStreams());
}
void RtpStreamDialog::rtpAnalysisRemove()
{
if (ui->streamTreeWidget->selectedItems().count() < 1) return;
emit rtpAnalysisDialogRemoveRtpStreams(getSelectedRtpStreams());
}
void RtpStreamDialog::displayFilterSuccess(bool success)
{
if (success && ui->displayFilterCheckBox->isChecked()) {

View File

@ -29,6 +29,8 @@ class RtpStreamDialog : public WiresharkDialog
public:
explicit RtpStreamDialog(QWidget &parent, CaptureFile &cf);
~RtpStreamDialog();
void selectRtpStream(rtpstream_id_t *id);
void deselectRtpStream(rtpstream_id_t *id);
signals:
// Tells the packet list to redraw. An alternative might be to add a
@ -40,14 +42,18 @@ signals:
void rtpPlayerDialogReplaceRtpStreams(QVector<rtpstream_info_t *> stream_infos);
void rtpPlayerDialogAddRtpStreams(QVector<rtpstream_info_t *> stream_infos);
void rtpPlayerDialogRemoveRtpStreams(QVector<rtpstream_info_t *> stream_infos);
void rtpAnalysisDialogReplaceRtpStreams(QVector<rtpstream_info_t *> stream_infos);
void rtpAnalysisDialogAddRtpStreams(QVector<rtpstream_info_t *> stream_infos);
void rtpAnalysisDialogRemoveRtpStreams(QVector<rtpstream_info_t *> stream_infos);
public slots:
void selectRtpStream(rtpstream_id_t *id);
void deselectRtpStream(rtpstream_id_t *id);
void displayFilterSuccess(bool success);
void rtpPlayerReplace();
void rtpPlayerAdd();
void rtpPlayerRemove();
void rtpAnalysisReplace();
void rtpAnalysisAdd();
void rtpAnalysisRemove();
protected:
bool eventFilter(QObject *obj, QEvent *event);
@ -94,7 +100,6 @@ private slots:
void on_buttonBox_helpRequested();
void on_buttonBox_clicked(QAbstractButton *button);
void on_actionExportAsRtpDump_triggered();
void on_actionAnalyze_triggered();
void captureEvent(CaptureEvent e);
void on_displayFilterCheckBox_toggled(bool checked);
void on_todCheckBox_toggled(bool checked);

View File

@ -46,6 +46,7 @@
#include <QFontMetrics>
#include <QMap>
#include <QPainter>
#include <QPainterPath>
#include <QStyle>
#include <QStyleOption>
@ -170,6 +171,78 @@ QIcon StockIcon::colorIcon(const QRgb bg_color, const QRgb fg_color, const QStri
return color_icon;
}
// Create a triangle icon filled with the specified color.
QIcon StockIcon::colorIconTriangle(const QRgb bg_color, const QRgb fg_color)
{
QList<int> sizes = QList<int>() << 12 << 16 << 24 << 32 << 48;
QIcon color_icon;
foreach (int size, sizes) {
QPixmap pm(size, size);
QPainter painter(&pm);
QPainterPath triangle;
pm.fill();
painter.fillRect(0, 0, size-1, size-1, Qt::transparent);
painter.setPen(fg_color);
painter.setBrush(QColor(bg_color));
triangle.moveTo(0, size-1);
triangle.lineTo(size-1, size-1);
triangle.lineTo((size-1)/2, 0);
triangle.closeSubpath();
painter.fillPath(triangle, QColor(bg_color));
color_icon.addPixmap(pm);
}
return color_icon;
}
// Create a cross icon filled with the specified color.
QIcon StockIcon::colorIconCross(const QRgb bg_color, const QRgb fg_color)
{
QList<int> sizes = QList<int>() << 12 << 16 << 24 << 32 << 48;
QIcon color_icon;
foreach (int size, sizes) {
QPixmap pm(size, size);
QPainter painter(&pm);
QPainterPath cross;
pm.fill();
painter.fillRect(0, 0, size-1, size-1, Qt::transparent);
painter.setPen(QPen(QBrush(bg_color), 3));
painter.setBrush(QColor(fg_color));
cross.moveTo(0, 0);
cross.lineTo(size-1, size-1);
cross.moveTo(0, size-1);
cross.lineTo(size-1, 0);
painter.drawPath(cross);
color_icon.addPixmap(pm);
}
return color_icon;
}
// Create a circle icon filled with the specified color.
QIcon StockIcon::colorIconCircle(const QRgb bg_color, const QRgb fg_color)
{
QList<int> sizes = QList<int>() << 12 << 16 << 24 << 32 << 48;
QIcon color_icon;
foreach (int size, sizes) {
QPixmap pm(size, size);
QPainter painter(&pm);
QRect border(2, 2, size - 3, size - 3);
pm.fill();
painter.fillRect(0, 0, size-1, size-1, Qt::transparent);
painter.setPen(QPen(QBrush(bg_color), 3));
painter.setBrush(QColor(fg_color));
painter.setBrush(QColor(bg_color));
painter.drawEllipse(border);
color_icon.addPixmap(pm);
}
return color_icon;
}
void StockIcon::fillIconNameMap()
{
// Note that some of Qt's standard pixmaps are awful. We shouldn't add an

View File

@ -29,6 +29,9 @@ public:
explicit StockIcon(const QString icon_name);
static QIcon colorIcon(const QRgb bg_color, const QRgb fg_color, const QString glyph = QString());
static QIcon colorIconTriangle(const QRgb bg_color, const QRgb fg_color);
static QIcon colorIconCross(const QRgb bg_color, const QRgb fg_color);
static QIcon colorIconCircle(const QRgb bg_color, const QRgb fg_color);
private:
void fillIconNameMap();