aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--epan/Makefile.common2
-rw-r--r--epan/codecs.c91
-rw-r--r--epan/codecs.h43
-rw-r--r--epan/libwireshark.def5
-rw-r--r--epan/plugins.c39
-rw-r--r--epan/plugins.h2
-rw-r--r--gtk/plugins_dlg.c6
-rw-r--r--gtk/rtp_player.c68
8 files changed, 244 insertions, 12 deletions
diff --git a/epan/Makefile.common b/epan/Makefile.common
index ebfaac6e18..3cbeff93cc 100644
--- a/epan/Makefile.common
+++ b/epan/Makefile.common
@@ -35,6 +35,7 @@ LIBWIRESHARK_SRC = \
camel-persistentdata.c \
charsets.c \
circuit.c \
+ codecs.c \
column.c \
column-utils.c \
conversation.c \
@@ -145,6 +146,7 @@ LIBWIRESHARK_INCLUDES = \
charsets.h \
chdlctypes.h \
circuit.h \
+ codecs.h \
column.h \
column_info.h \
column-utils.h \
diff --git a/epan/codecs.c b/epan/codecs.c
new file mode 100644
index 0000000000..28c53d7b62
--- /dev/null
+++ b/epan/codecs.c
@@ -0,0 +1,91 @@
+/* codecs.c
+ * codecs interface 2007 Tomas Kukosa
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <epan/codecs.h>
+
+struct codec_handle {
+ const char *name;
+ codec_init_fn init_fn;
+ codec_release_fn release_fn;
+ codec_decode_fn decode_fn;
+};
+
+/*
+ * List of registered codecs.
+ */
+static GHashTable *registered_codecs = NULL;
+
+
+/* Find a registered codec by name. */
+codec_handle_t
+find_codec(const char *name)
+{
+ return (registered_codecs) ? g_hash_table_lookup(registered_codecs, name) : NULL;
+}
+
+/* Register a codec by name. */
+void
+register_codec(const char *name, codec_init_fn init_fn, codec_release_fn release_fn, codec_decode_fn decode_fn)
+{
+ struct codec_handle *handle;
+
+ /* Create our hash table if it doesn't already exist */
+ if (registered_codecs == NULL) {
+ registered_codecs = g_hash_table_new(g_str_hash, g_str_equal);
+ g_assert(registered_codecs != NULL);
+ }
+
+ /* Make sure the registration is unique */
+ g_assert(g_hash_table_lookup(registered_codecs, name) == NULL);
+
+ handle = g_malloc(sizeof (struct codec_handle));
+ handle->name = name;
+ handle->init_fn = init_fn;
+ handle->release_fn = release_fn;
+ handle->decode_fn = decode_fn;
+
+ g_hash_table_insert(registered_codecs, (gpointer)name, (gpointer) handle);
+}
+
+void *codec_init(codec_handle_t codec)
+{
+ if (!codec) return NULL;
+ return (codec->init_fn)();
+}
+
+void codec_release(codec_handle_t codec, void *context)
+{
+ if (!codec) return;
+ (codec->release_fn)(context);
+}
+
+int codec_decode(codec_handle_t codec, void *context, const void *input, int inputSizeBytes, void *output, int *outputSizeBytes)
+{
+ if (!codec) return 0;
+ return (codec->decode_fn)(context, input, inputSizeBytes, output, outputSizeBytes);
+}
diff --git a/epan/codecs.h b/epan/codecs.h
new file mode 100644
index 0000000000..de5d02c1be
--- /dev/null
+++ b/epan/codecs.h
@@ -0,0 +1,43 @@
+/* codecs.h
+ * codecs interface 2007 Tomas Kukosa
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _CODECS_H_
+#define _CODECS_H_
+
+#include "epan/epan.h"
+
+struct codec_handle;
+typedef struct codec_handle *codec_handle_t;
+
+typedef void *(*codec_init_fn)(void);
+typedef void (*codec_release_fn)(void *context);
+typedef int (*codec_decode_fn)(void *context, const void *input, int inputSizeBytes, void *output, int *outputSizeBytes);
+
+extern void register_codec(const char *name, codec_init_fn init_fn, codec_release_fn release_fn, codec_decode_fn decode_fn);
+extern codec_handle_t find_codec(const char *name);
+extern void *codec_init(codec_handle_t codec);
+extern void codec_release(codec_handle_t codec, void *context);
+extern int codec_decode(codec_handle_t codec, void *context, const void *input, int inputSizeBytes, void *output, int *outputSizeBytes);
+
+#endif
diff --git a/epan/libwireshark.def b/epan/libwireshark.def
index e304183ef9..22047e49f4 100644
--- a/epan/libwireshark.def
+++ b/epan/libwireshark.def
@@ -66,6 +66,9 @@ circuit_add_proto_data
circuit_get_proto_data
circuit_new
cleanup_dissection
+codec_init
+codec_decode
+codec_release
col_add_fstr
col_add_str
col_append_fstr
@@ -318,6 +321,7 @@ file_write_error_message
files_identical
filesystem_opt
find_circuit
+find_codec
find_conversation
find_dissector
find_dissector_table
@@ -693,6 +697,7 @@ register_all_protocol_handoffs
register_all_wiretap_modules
register_ber_oid_syntax
register_ber_syntax_dissector
+register_codec
register_count
register_dissector
register_dissector_filter
diff --git a/epan/plugins.c b/epan/plugins.c
index 6594afd3b9..68031b5be2 100644
--- a/epan/plugins.c
+++ b/epan/plugins.c
@@ -69,7 +69,8 @@ static int
add_plugin(void *handle, gchar *name, gchar *version,
void (*register_protoinfo)(void), void (*reg_handoff)(void),
void (*register_tap_listener)(void),
- void (*register_wtap_module)(void))
+ void (*register_wtap_module)(void),
+ void (*register_codec_module)(void))
{
plugin *new_plug, *pt_plug;
@@ -108,6 +109,7 @@ add_plugin(void *handle, gchar *name, gchar *version,
new_plug->reg_handoff = reg_handoff;
new_plug->register_tap_listener = register_tap_listener;
new_plug->register_wtap_module = register_wtap_module;
+ new_plug->register_codec_module = register_codec_module;
new_plug->next = NULL;
return 0;
@@ -145,6 +147,7 @@ plugins_scan_dir(const char *dirname)
void (*reg_handoff)(void);
void (*register_tap_listener)(void);
void (*register_wtap_module)(void);
+ void (*register_codec_module)(void);
gchar *dot;
int cr;
@@ -310,18 +313,29 @@ plugins_scan_dir(const char *dirname)
register_wtap_module = NULL;
}
+ /*
+ * Do we have a register_codec_module routine?
+ */
+ if (g_module_symbol(handle, "register_codec_module", &gp))
+ {
+ register_codec_module = gp;
+ } else {
+ register_codec_module = NULL;
+ }
+
/*
* Does this dissector do anything useful?
*/
if (register_protoinfo == NULL &&
register_tap_listener == NULL &&
- register_wtap_module == NULL )
+ register_wtap_module == NULL &&
+ register_codec_module == NULL )
{
/*
* No.
*/
report_failure("The plugin '%s' has neither a register routine, "
- "a register_tap_listener or a register_wtap_module routine",
+ "a register_tap_listener or a register_wtap_module or a register_codec_module routine",
name);
g_module_close(handle);
continue;
@@ -332,7 +346,7 @@ plugins_scan_dir(const char *dirname)
*/
if ((cr = add_plugin(handle, g_strdup(name), version,
register_protoinfo, reg_handoff,
- register_tap_listener,register_wtap_module)))
+ register_tap_listener,register_wtap_module,register_codec_module)))
{
if (cr == EEXIST)
fprintf(stderr, "The plugin %s, version %s\n"
@@ -432,6 +446,7 @@ init_plugins(void)
}
}
register_all_wiretap_modules();
+ register_all_codecs();
}
void
@@ -507,4 +522,20 @@ register_all_wiretap_modules(void)
(pt_plug->register_wtap_module)();
}
}
+
+void
+register_all_codecs(void)
+{
+ plugin *pt_plug;
+
+ /*
+ * For all plugins with register_wtap_module routines, call the
+ * routines.
+ */
+ for (pt_plug = plugin_list; pt_plug != NULL; pt_plug = pt_plug->next)
+ {
+ if (pt_plug->register_codec_module)
+ (pt_plug->register_codec_module)();
+ }
+}
#endif
diff --git a/epan/plugins.h b/epan/plugins.h
index c6a43ab2c9..961cb1c024 100644
--- a/epan/plugins.h
+++ b/epan/plugins.h
@@ -38,6 +38,7 @@ typedef struct _plugin {
void (*reg_handoff)(void); /* routine to call to register dissector handoff */
void (*register_tap_listener)(void); /* routine to call to register tap listener */
void (*register_wtap_module)(void); /* routine to call to register a wiretap module */
+ void (*register_codec_module)(void); /* routine to call to register a codec */
struct _plugin *next; /* forward link */
} plugin;
@@ -48,6 +49,7 @@ extern void register_all_plugin_registrations(void);
extern void register_all_plugin_handoffs(void);
extern void register_all_plugin_tap_listeners(void);
extern void register_all_wiretap_modules(void);
+extern void register_all_codecs(void);
/* get the personal plugin dir */
/* Return value is g_malloced so the caller should g_free() it. */
diff --git a/gtk/plugins_dlg.c b/gtk/plugins_dlg.c
index 7bb76af491..23dfad4028 100644
--- a/gtk/plugins_dlg.c
+++ b/gtk/plugins_dlg.c
@@ -66,6 +66,12 @@ plugins_scan(GtkWidget *list)
{
type = g_string_append(type, sep);
type = g_string_append(type, "file_format");
+ sep = ", ";
+ }
+ if (pt_plug->register_codec_module)
+ {
+ type = g_string_append(type, sep);
+ type = g_string_append(type, "codec");
}
simple_list_append(list, 0, pt_plug->name, 1, pt_plug->version,
2, type->str, -1);
diff --git a/gtk/rtp_player.c b/gtk/rtp_player.c
index a2a3b7cf32..c1ee8cbe24 100644
--- a/gtk/rtp_player.c
+++ b/gtk/rtp_player.c
@@ -79,6 +79,7 @@
#include <epan/dissectors/packet-rtp.h>
#include <epan/rtp_pt.h>
+#include <epan/codecs.h>
#include "rtp_player.h"
#include "codecs/G711a/G711adecode.h"
@@ -238,6 +239,11 @@ typedef struct _rtp_play_channles {
/* The two RTP channles to play */
static rtp_play_channles_t *rtp_channels = NULL;
+typedef struct _rtp_decoder_t {
+ codec_handle_t handle;
+ void *context;
+} rtp_decoder_t;
+
/****************************************************************************/
static void
@@ -283,6 +289,17 @@ rtp_stream_value_destroy(gpointer rsi_arg)
}
/****************************************************************************/
+static void
+rtp_decoder_value_destroy(gpointer dec_arg)
+{
+ rtp_decoder_t *dec = dec_arg;
+
+ if (dec->handle)
+ codec_release(dec->handle, dec->context);
+ g_free(dec_arg);
+}
+
+/****************************************************************************/
static void
set_sensitive_check_bt(gchar *key _U_ , rtp_channel_info_t *rci, guint *stop _U_ )
{
@@ -440,10 +457,13 @@ mark_rtp_stream_to_play(gchar *key _U_ , rtp_stream_info_t *rsi, gpointer ptr _U
* Return the number of decoded bytes
*/
static int
-decode_rtp_packet(rtp_packet_t *rp, SAMPLE **out_buff)
+decode_rtp_packet(rtp_packet_t *rp, SAMPLE **out_buff, GHashTable *decoders_hash)
{
unsigned int payload_type;
+ const gchar *p;
+ rtp_decoder_t *decoder;
SAMPLE *tmp_buff = NULL;
+ int tmp_buff_len;
int decoded_bytes = 0;
if ((rp->payload_data == NULL) || (rp->info->info_payload_len == 0) ) {
@@ -451,32 +471,57 @@ decode_rtp_packet(rtp_packet_t *rp, SAMPLE **out_buff)
}
payload_type = rp->info->info_payload_type;
+
+ /* Look for registered codecs */
+ decoder = g_hash_table_lookup(decoders_hash, (gpointer)payload_type);
+ if (!decoder) { /* Put either valid or empty decoder into the hash table */
+ decoder = g_malloc(sizeof(rtp_decoder_t));
+ decoder->handle = NULL;
+ decoder->context = NULL;
+ p = match_strval(payload_type, rtp_payload_type_short_vals);
+ if (p) {
+ decoder->handle = find_codec(p);
+ if (decoder->handle)
+ decoder->context = codec_init(decoder->handle);
+ }
+ g_hash_table_insert(decoders_hash, (gpointer)payload_type, decoder);
+ }
+ if (decoder->handle) { /* Decode with registered codec */
+ tmp_buff_len = codec_decode(decoder->handle, decoder->context, rp->payload_data, rp->info->info_payload_len, NULL, NULL);
+ tmp_buff = g_malloc(tmp_buff_len);
+ decoded_bytes = codec_decode(decoder->handle, decoder->context, rp->payload_data, rp->info->info_payload_len, tmp_buff, &tmp_buff_len);
+ *out_buff = tmp_buff;
+ return decoded_bytes;
+ }
+
+ /* Try to decode with built-in codec */
+
switch (payload_type) {
case PT_PCMU: /* G.711 u-law */
- tmp_buff = malloc(sizeof(SAMPLE) * rp->info->info_payload_len * 1);
+ tmp_buff = g_malloc(sizeof(SAMPLE) * rp->info->info_payload_len * 1);
decodeG711u(rp->payload_data, rp->info->info_payload_len,
tmp_buff, &decoded_bytes);
break;
case PT_PCMA: /* G.711 A-law */
- tmp_buff = malloc(sizeof(SAMPLE) * rp->info->info_payload_len * 1);
+ tmp_buff = g_malloc(sizeof(SAMPLE) * rp->info->info_payload_len * 1);
decodeG711a(rp->payload_data, rp->info->info_payload_len,
tmp_buff, &decoded_bytes);
break;
#ifdef HAVE_G729_G723
case PT_G729: /* G.729 */
- tmp_buff = malloc(sizeof(SAMPLE) * rp->info->info_payload_len * 8); /* G729 8kbps => 64kbps/8kbps = 8 */
+ tmp_buff = g_malloc(sizeof(SAMPLE) * rp->info->info_payload_len * 8); /* G729 8kbps => 64kbps/8kbps = 8 */
decodeG729(rp->payload_data, rp->info->info_payload_len,
tmp_buff, &decoded_bytes);
break;
case PT_G723: /* G.723 */
if (rp->info->info_payload_len%24 == 0) /* G723 High 6.4kbps */
- tmp_buff = malloc(sizeof(SAMPLE) * rp->info->info_payload_len * 10); /* G723 High 64kbps/6.4kbps = 10 */
+ tmp_buff = g_malloc(sizeof(SAMPLE) * rp->info->info_payload_len * 10); /* G723 High 64kbps/6.4kbps = 10 */
else if (rp->info->info_payload_len%20 == 0) /* G723 Low 5.3kbps */
- tmp_buff = malloc(sizeof(SAMPLE) * rp->info->info_payload_len * 13); /* G723 High 64kbps/5.3kbps = 13 */
+ tmp_buff = g_malloc(sizeof(SAMPLE) * rp->info->info_payload_len * 13); /* G723 High 64kbps/5.3kbps = 13 */
else {
return 0;
}
@@ -546,6 +591,7 @@ decode_rtp_stream(rtp_stream_info_t *rsi, gpointer ptr _U_)
sample_t sample;
guint8 status;
guint32 start_timestamp;
+ GHashTable *decoders_hash = NULL;
guint32 progbar_nextstep;
int progbar_quantum;
@@ -580,7 +626,7 @@ decode_rtp_stream(rtp_stream_info_t *rsi, gpointer ptr _U_)
/* ..if it is not in the hash, create an entry */
if (rci == NULL) {
- rci = malloc(sizeof(rtp_channel_info_t));
+ rci = g_malloc(sizeof(rtp_channel_info_t));
rci->call_num = rsi->call_num;
rci->start_time = rsi->start_time;
rci->end_time = rsi->start_time;
@@ -628,6 +674,7 @@ decode_rtp_stream(rtp_stream_info_t *rsi, gpointer ptr _U_)
mean_delay = 0;
variation = 0;
start_timestamp = 0;
+ decoders_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, rtp_decoder_value_destroy);
/* we update the progress bar 100 times */
@@ -663,7 +710,7 @@ decode_rtp_stream(rtp_stream_info_t *rsi, gpointer ptr _U_)
seq = rp->info->info_seq_num - 1;
}
- decoded_bytes = decode_rtp_packet(rp, &out_buff);
+ decoded_bytes = decode_rtp_packet(rp, &out_buff, decoders_hash);
if (decoded_bytes == 0) {
seq = rp->info->info_seq_num;
}
@@ -744,6 +791,10 @@ decode_rtp_stream(rtp_stream_info_t *rsi, gpointer ptr _U_)
}
+ if (out_buff) {
+ g_free(out_buff);
+ out_buff = NULL;
+ }
rtp_packets_list = g_list_next (rtp_packets_list);
progbar_count++;
}
@@ -751,6 +802,7 @@ decode_rtp_stream(rtp_stream_info_t *rsi, gpointer ptr _U_)
rci->end_time = rci->start_time + ((double)rci->samples->len/SAMPLE_RATE)*1000;
g_string_free(key_str, TRUE);
+ g_hash_table_destroy(decoders_hash);
}
/****************************************************************************/