summaryrefslogtreecommitdiffstats
path: root/libavfilter/asrc_flite.c
diff options
context:
space:
mode:
authorNicolas George <nicolas.george@normalesup.org>2012-07-28 11:53:18 +0200
committerNicolas George <nicolas.george@normalesup.org>2012-07-28 15:13:46 +0200
commit4ce87ecf2a8a8a9348f9bdbb420f3bee92e6513f (patch)
tree9f5eeb097060816e870e4cf394c96030bc6433ad /libavfilter/asrc_flite.c
parentfb0688b079c3751bcd4d64200280858a33e0b9cc (diff)
downloadffmpeg-streaming-4ce87ecf2a8a8a9348f9bdbb420f3bee92e6513f.zip
ffmpeg-streaming-4ce87ecf2a8a8a9348f9bdbb420f3bee92e6513f.tar.gz
asrc_flite: do not crash on multiple instances.
The voice register functions return the same voice structure upon multiple registration. It causes us two problems: If we delete a voice without deregistering it, it leaves a dangling pointer inside the library. If we delete or unregister a voice at uninit, it may still be in use by another instance of the filter. The second problem is solved by keeping an usage counter inside asrc_flite. This is not thread-safe, but neither is flite itself.
Diffstat (limited to 'libavfilter/asrc_flite.c')
-rw-r--r--libavfilter/asrc_flite.c39
1 files changed, 28 insertions, 11 deletions
diff --git a/libavfilter/asrc_flite.c b/libavfilter/asrc_flite.c
index 9226399..71271be 100644
--- a/libavfilter/asrc_flite.c
+++ b/libavfilter/asrc_flite.c
@@ -42,6 +42,7 @@ typedef struct {
int wave_nb_samples;
int list_voices;
cst_voice *voice;
+ struct voice_entry *voice_entry;
int64_t pts;
int frame_nb_samples; ///< number of samples per frame
} FliteContext;
@@ -64,7 +65,9 @@ AVFILTER_DEFINE_CLASS(flite);
static volatile int flite_inited = 0;
/* declare functions for all the supported voices */
-#define DECLARE_REGISTER_VOICE_FN(name) cst_voice *register_cmu_us_## name(const char *)
+#define DECLARE_REGISTER_VOICE_FN(name) \
+ cst_voice *register_cmu_us_## name(const char *); \
+ void unregister_cmu_us_## name(cst_voice *);
DECLARE_REGISTER_VOICE_FN(awb);
DECLARE_REGISTER_VOICE_FN(kal);
DECLARE_REGISTER_VOICE_FN(kal16);
@@ -74,14 +77,22 @@ DECLARE_REGISTER_VOICE_FN(slt);
struct voice_entry {
const char *name;
cst_voice * (*register_fn)(const char *);
+ void (*unregister_fn)(cst_voice *);
+ cst_voice *voice;
+ unsigned usage_count;
} voice_entry;
+#define MAKE_VOICE_STRUCTURE(voice_name) { \
+ .name = #voice_name, \
+ .register_fn = register_cmu_us_ ## voice_name, \
+ .unregister_fn = unregister_cmu_us_ ## voice_name, \
+}
static struct voice_entry voice_entries[] = {
- { "awb", register_cmu_us_awb },
- { "kal", register_cmu_us_kal },
- { "kal16", register_cmu_us_kal16 },
- { "rms", register_cmu_us_rms },
- { "slt", register_cmu_us_slt },
+ MAKE_VOICE_STRUCTURE(awb),
+ MAKE_VOICE_STRUCTURE(kal),
+ MAKE_VOICE_STRUCTURE(kal16),
+ MAKE_VOICE_STRUCTURE(rms),
+ MAKE_VOICE_STRUCTURE(slt),
};
static void list_voices(void *log_ctx, const char *sep)
@@ -92,19 +103,22 @@ static void list_voices(void *log_ctx, const char *sep)
voice_entries[i].name, i < (n-1) ? sep : "\n");
}
-static int select_voice(cst_voice **voice, const char *voice_name, void *log_ctx)
+static int select_voice(struct voice_entry **entry_ret, const char *voice_name, void *log_ctx)
{
int i;
for (i = 0; i < FF_ARRAY_ELEMS(voice_entries); i++) {
struct voice_entry *entry = &voice_entries[i];
if (!strcmp(entry->name, voice_name)) {
- *voice = entry->register_fn(NULL);
- if (!*voice) {
+ if (!entry->voice)
+ entry->voice = entry->register_fn(NULL);
+ if (!entry->voice) {
av_log(log_ctx, AV_LOG_ERROR,
"Could not register voice '%s'\n", voice_name);
return AVERROR_UNKNOWN;
}
+ entry->usage_count++;
+ *entry_ret = entry;
return 0;
}
}
@@ -142,8 +156,9 @@ static av_cold int init(AVFilterContext *ctx, const char *args)
flite_inited++;
}
- if ((ret = select_voice(&flite->voice, flite->voice_str, ctx)) < 0)
+ if ((ret = select_voice(&flite->voice_entry, flite->voice_str, ctx)) < 0)
return ret;
+ flite->voice = flite->voice_entry->voice;
if (flite->textfile && flite->text) {
av_log(ctx, AV_LOG_ERROR,
@@ -188,8 +203,10 @@ static av_cold void uninit(AVFilterContext *ctx)
av_opt_free(flite);
- delete_voice(flite->voice);
+ if (!--flite->voice_entry->usage_count)
+ flite->voice_entry->unregister_fn(flite->voice);
flite->voice = NULL;
+ flite->voice_entry = NULL;
delete_wave(flite->wave);
flite->wave = NULL;
}
OpenPOWER on IntegriCloud