From 0ec6ec10ae06e026d2b2450a63c797bf24936b54 Mon Sep 17 00:00:00 2001 From: Dragos Oancea Date: Sat, 25 Jan 2020 16:42:07 +0000 Subject: [PATCH] [mod_opusfile] fix play sample rate (don't use original rate, always use 48k), fix EOF, add unit-test. --- src/mod/formats/mod_opusfile/Makefile.am | 21 ++- src/mod/formats/mod_opusfile/mod_opusfile.c | 19 ++- .../formats/mod_opusfile/test/freeswitch.xml | 21 +++ .../formats/mod_opusfile/test/sounds/hi.opus | Bin 0 -> 8753 bytes .../formats/mod_opusfile/test/test_opusfile.c | 123 ++++++++++++++++++ 5 files changed, 176 insertions(+), 8 deletions(-) create mode 100644 src/mod/formats/mod_opusfile/test/freeswitch.xml create mode 100644 src/mod/formats/mod_opusfile/test/sounds/hi.opus create mode 100644 src/mod/formats/mod_opusfile/test/test_opusfile.c diff --git a/src/mod/formats/mod_opusfile/Makefile.am b/src/mod/formats/mod_opusfile/Makefile.am index abf251e700..f02f8212d7 100644 --- a/src/mod/formats/mod_opusfile/Makefile.am +++ b/src/mod/formats/mod_opusfile/Makefile.am @@ -1,15 +1,30 @@ include $(top_srcdir)/build/modmake.rulesam MODNAME=mod_opusfile +noinst_LTLIBRARIES = libopusfilemod.la + +libopusfilemod_la_SOURCES = mod_opusfile.c +libopusfilemod_la_CFLAGS = $(AM_CFLAGS) $(freeswitch_LDFLAGS) $(OPUSFILE_DECODE_CFLAGS) + mod_LTLIBRARIES = mod_opusfile.la -mod_opusfile_la_SOURCES = mod_opusfile.c -mod_opusfile_la_CFLAGS = $(AM_CFLAGS) -mod_opusfile_la_LIBADD = $(switch_builddir)/libfreeswitch.la +mod_opusfile_la_SOURCES = +mod_opusfile_la_CFLAGS = $(AM_CFLAGS) $(freeswitch_LDFLAGS) $(OPUSFILE_DECODE_CFLAGS) +mod_opusfile_la_LIBADD = libopusfilemod.la $(switch_builddir)/libfreeswitch.la mod_opusfile_la_LDFLAGS = -avoid-version -module -no-undefined -shared if HAVE_OPUSFILE_DECODE mod_opusfile_la_CFLAGS += $(OPUSFILE_DECODE_CFLAGS) mod_opusfile_la_LIBADD += $(OPUSFILE_DECODE_LIBS) + +noinst_PROGRAMS = test/test_opusfile + +test_test_opusfile_SOURCES = test/test_opusfile.c +test_test_opusfile_CFLAGS = $(AM_CFLAGS) -I./ -I../ -DSWITCH_TEST_BASE_DIR_FOR_CONF=\"${abs_builddir}/test\" -DSWITCH_TEST_BASE_DIR_OVERRIDE=\"${abs_builddir}/test\" $(OPUSFILE_DECODE_CFLAGS) +test_test_opusfile_LDFLAGS = $(AM_LDFLAGS) -avoid-version -no-undefined $(freeswitch_LDFLAGS) $(switch_builddir)/libfreeswitch.la $(CORE_LIBS) $(APR_LIBS) $(OPUSFILE_DECODE_LIBS) +test_test_opusfile_LDADD = libopusfilemod.la $(switch_builddir)/libfreeswitch.la + +TESTS = $(noinst_PROGRAMS) + endif if HAVE_OPUSFILE_ENCODE diff --git a/src/mod/formats/mod_opusfile/mod_opusfile.c b/src/mod/formats/mod_opusfile/mod_opusfile.c index 418628b8e4..51bcb720bb 100644 --- a/src/mod/formats/mod_opusfile/mod_opusfile.c +++ b/src/mod/formats/mod_opusfile/mod_opusfile.c @@ -148,7 +148,7 @@ static switch_status_t switch_opusfile_decode(opus_file_context *context, void * if (globals.debug) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[OGG/OPUS Decoder]: EOF reached [%d]\n", ret); } - context->eof = TRUE; + context->eof = SWITCH_TRUE; break; } else /* (ret > 0)*/ { /*The number of samples read per channel on success*/ @@ -161,7 +161,6 @@ static switch_status_t switch_opusfile_decode(opus_file_context *context, void * } } switch_mutex_unlock(context->audio_mutex); - context->eof = FALSE; // for next page return SWITCH_STATUS_SUCCESS; } @@ -266,6 +265,8 @@ static switch_status_t switch_opusfile_open(switch_file_handle_t *handle, const if(context->pcm_offset!=0){ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[OGG/OPUS File] Non-zero starting PCM offset: [%li]\n", (long)context->pcm_offset); } + + context->eof = SWITCH_FALSE; context->pcm_print_offset = context->pcm_offset - DEFAULT_RATE; context->bitrate = 0; context->buffer_seconds = 1; @@ -282,7 +283,6 @@ static switch_status_t switch_opusfile_open(switch_file_handle_t *handle, const switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "[OGG/OPUS File] Channels: %i\n", head->channel_count); if (head->input_sample_rate) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "[OGG/OPUS File] Original sampling rate: %lu Hz\n", (unsigned long)head->input_sample_rate); - handle->samplerate = context->samplerate = head->input_sample_rate; } } if (op_seekable(context->of)) { @@ -365,20 +365,29 @@ static switch_status_t switch_opusfile_read(switch_file_handle_t *handle, void * if (!handle->handler) { if (switch_opusfile_decode(context, data, bytes, handle->real_channels) == SWITCH_STATUS_FALSE) { - context->eof = 1; + context->eof = SWITCH_TRUE; } } switch_mutex_lock(context->audio_mutex); rb = switch_buffer_read(context->audio_buffer, data, bytes); switch_mutex_unlock(context->audio_mutex); + if (globals.debug) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[OGG/OPUS File] rb: [%lu] bytes: [%lu]\n", rb, bytes); + } + if (!rb && (context->eof)) { + if (globals.debug) { + // should be same as returned by op_pcm_total() + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[OGG/OPUS File] EOF. sample count: [%lu]\n", handle->sample_count); + } + *len = 0; return SWITCH_STATUS_FALSE; } if (rb) { *len = rb / sizeof(int16_t) / handle->real_channels; if (globals.debug) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[OGG/OPUS File] rb: [%d] *len: [%d]\n", (int)rb, (int)*len); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[OGG/OPUS File] rb: [%lu] *len: [%lu]\n", rb, *len); } } else { newbytes = (2 * handle->samplerate * handle->real_channels) * context->buffer_seconds; diff --git a/src/mod/formats/mod_opusfile/test/freeswitch.xml b/src/mod/formats/mod_opusfile/test/freeswitch.xml new file mode 100644 index 0000000000..80591e86ac --- /dev/null +++ b/src/mod/formats/mod_opusfile/test/freeswitch.xml @@ -0,0 +1,21 @@ + + +
+ + + + + + +
+ +
+ + + + + + + +
+
diff --git a/src/mod/formats/mod_opusfile/test/sounds/hi.opus b/src/mod/formats/mod_opusfile/test/sounds/hi.opus new file mode 100644 index 0000000000000000000000000000000000000000..ae13c23cca7f5cb56f79a02ae6d3262d546a92e4 GIT binary patch literal 8753 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 + * + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * + * The Initial Developer of the Original Code is + * Anthony Minessale II + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Dragos Oancea + * + * + * test_opusfile.c -- tests mod_opusfile + * + */ +#include +#include + +#include + + +FST_CORE_BEGIN(".") +{ + FST_SUITE_BEGIN(test_opusfile) + { + FST_SETUP_BEGIN() + { + fst_requires_module("mod_loopback"); + fst_requires_module("mod_opusfile"); + } + FST_SETUP_END() + + FST_TEARDOWN_BEGIN() + { + } + FST_TEARDOWN_END() + + FST_TEST_BEGIN(opusfile_read) + { + switch_core_session_t *session = NULL; + switch_channel_t *channel = NULL; + switch_status_t status; + switch_call_cause_t cause; + /* + $ mediainfo hi.opus + General + Complete name : hi.opus + Format : OGG + File size : 8.55 KiB + Duration : 2s 157ms + Overall bit rate : 32.5 Kbps + Writing application : opusenc from opus-tools 0.1.10 + + Audio + ID : 277454932 (0x1089A054) + Format : Opus + Duration : 2s 157ms + Channel(s) : 1 channel + Channel positions : Front: C + Sampling rate : 16.0 KHz + Compression mode : Lossy + Writing library : libopus 1.2~alpha2 + */ + static char filename[] = "sounds/hi.opus"; // duration in samples: 103200 + char path[4096]; + switch_file_handle_t fh = { 0 }; + int16_t *audiobuf; + switch_size_t len; + + sprintf(path, "%s%s%s", SWITCH_GLOBAL_dirs.conf_dir, SWITCH_PATH_SEPARATOR, filename); + + status = switch_ivr_originate(NULL, &session, &cause, "null/+15553334444", 2, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL, NULL); + fst_requires(session); + fst_check(status == SWITCH_STATUS_SUCCESS); + + status = switch_core_file_open(&fh, path, 1, 48000, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL); + fst_check(status == SWITCH_STATUS_SUCCESS); + + len = 128 * 1024 * sizeof(*audiobuf); + switch_zmalloc(audiobuf, len); + + status = switch_core_file_read(&fh, audiobuf, &len); + fst_check(status == SWITCH_STATUS_SUCCESS); + + /* [INFO] mod_opusfile.c:292 [OGG/OPUS File] Duration (samples): 103200 */ + /* compare the read sample count with the one in the OGG/OPUS header. */ + fst_check(len == 103200); + + status = switch_core_file_close(&fh); + fst_check(status == SWITCH_STATUS_SUCCESS); + + switch_safe_free(audiobuf); + channel = switch_core_session_get_channel(session); + fst_requires(channel); + + switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); + fst_check(!switch_channel_ready(channel)); + + switch_core_session_rwunlock(session); + + switch_sleep(1000000); + } + + FST_TEST_END() + } + FST_SUITE_END() +} +FST_CORE_END()