aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomas Kukosa <tomas.kukosa@siemens.com>2007-10-25 09:38:15 +0000
committerTomas Kukosa <tomas.kukosa@siemens.com>2007-10-25 09:38:15 +0000
commit136de3920c4f703e9d7aeb5f6d3b6484a2bc6479 (patch)
treeb55286be4fe6da2b8556a21a18dea5b3563ed374
parent821106256bf98c026652181dbdf9480abf080f6a (diff)
new codec table for registering codecs by name
new codec plugin type search registered codecs in rtp player fix memory leak in rtp player svn path=/trunk/; revision=23270
-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);
}
/****************************************************************************/