FS-10503: [mod_av] mod_av split audio to two channels #resolve

This commit is contained in:
Anthony Minessale 2017-07-14 18:35:23 -05:00
parent fd3b25d282
commit 4e5219cd27
7 changed files with 513 additions and 617 deletions

View File

@ -378,6 +378,8 @@ struct switch_file_handle {
int64_t duration; int64_t duration;
/*! current video position, or current page in pdf */ /*! current video position, or current page in pdf */
int64_t vpos; int64_t vpos;
void *muxbuf;
switch_size_t muxlen;
}; };
/*! \brief Abstract interface to an asr module */ /*! \brief Abstract interface to an asr module */

View File

@ -32,6 +32,7 @@
*/ */
#include <switch.h> #include <switch.h>
#include "mod_av.h"
#include <libavcodec/avcodec.h> #include <libavcodec/avcodec.h>
#include <libavformat/avformat.h> #include <libavformat/avformat.h>
#include <libavutil/opt.h> #include <libavutil/opt.h>
@ -1534,18 +1535,9 @@ void show_codecs(switch_stream_handle_t *stream)
av_free(codecs); av_free(codecs);
} }
SWITCH_STANDARD_API(av_codec_api_function)
{
show_codecs(stream);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_MODULE_LOAD_FUNCTION(mod_avcodec_load) SWITCH_MODULE_LOAD_FUNCTION(mod_avcodec_load)
{ {
switch_codec_interface_t *codec_interface; switch_codec_interface_t *codec_interface;
switch_api_interface_t *api_interface;
SWITCH_ADD_CODEC(codec_interface, "H264 Video"); SWITCH_ADD_CODEC(codec_interface, "H264 Video");
switch_core_codec_add_video_implementation(pool, codec_interface, 99, "H264", NULL, switch_core_codec_add_video_implementation(pool, codec_interface, 99, "H264", NULL,
@ -1559,8 +1551,6 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_avcodec_load)
switch_core_codec_add_video_implementation(pool, codec_interface, 115, "H263-1998", NULL, switch_core_codec_add_video_implementation(pool, codec_interface, 115, "H263-1998", NULL,
switch_h264_init, switch_h264_encode, switch_h264_decode, switch_h264_control, switch_h264_destroy); switch_h264_init, switch_h264_encode, switch_h264_decode, switch_h264_control, switch_h264_destroy);
SWITCH_ADD_API(api_interface, "av_codec", "av_codec information", av_codec_api_function, "");
/* indicate that the module should continue to be loaded */ /* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }

File diff suppressed because it is too large Load Diff

View File

@ -31,6 +31,7 @@
*/ */
#include <switch.h> #include <switch.h>
#include "mod_av.h"
#include <libavcodec/avcodec.h> #include <libavcodec/avcodec.h>
#include <libavformat/avformat.h> #include <libavformat/avformat.h>
@ -40,9 +41,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_av_load);
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_av_shutdown); SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_av_shutdown);
SWITCH_MODULE_DEFINITION(mod_av, mod_av_load, mod_av_shutdown, NULL); SWITCH_MODULE_DEFINITION(mod_av, mod_av_load, mod_av_shutdown, NULL);
static struct { struct mod_av_globals mod_av_globals;
int debug;
} globals;
typedef struct av_mutex_helper_s { typedef struct av_mutex_helper_s {
switch_mutex_t *mutex; switch_mutex_t *mutex;
@ -99,7 +98,7 @@ static void log_callback(void *ptr, int level, const char *fmt, va_list vl)
switch_log_level_t switch_level = SWITCH_LOG_DEBUG; switch_log_level_t switch_level = SWITCH_LOG_DEBUG;
/* naggy messages */ /* naggy messages */
if ((level == AV_LOG_DEBUG || level == AV_LOG_WARNING) && !globals.debug) return; if ((level == AV_LOG_DEBUG || level == AV_LOG_WARNING) && !mod_av_globals.debug) return;
switch(level) { switch(level) {
case AV_LOG_QUIET: switch_level = SWITCH_LOG_CONSOLE; break; case AV_LOG_QUIET: switch_level = SWITCH_LOG_CONSOLE; break;
@ -126,6 +125,8 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_av_shutdown)
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
#define AV_USAGE "debug [on|off] | show <formats | codecs>"
SWITCH_STANDARD_API(av_function) SWITCH_STANDARD_API(av_function)
{ {
char *argv[2] = { 0 }; char *argv[2] = { 0 };
@ -134,25 +135,43 @@ SWITCH_STANDARD_API(av_function)
int ok = 0; int ok = 0;
if (cmd) { if (cmd) {
if (!strcmp(cmd, "show formats")) {
show_formats(stream);
ok = 1;
goto end;
} else if (!strcmp(cmd, "show codecs")) {
show_codecs(stream);
ok = 1;
goto end;
}
mycmd = strdup(cmd); mycmd = strdup(cmd);
argc = switch_split(mycmd, ' ', argv); argc = switch_split(mycmd, ' ', argv);
if (argc > 0) { if (argc > 0) {
if (!strcasecmp(argv[0], "debug")) { if (!strcasecmp(argv[0], "debug")) {
if (argc > 1) { if (argc > 1) {
int tmp = atoi(argv[1]); if (switch_is_number(argv[1])) {
if (tmp > -1) { int tmp = atoi(argv[1]);
globals.debug = tmp; if (tmp > -1) {
mod_av_globals.debug = tmp;
}
} else {
mod_av_globals.debug = switch_true(argv[1]);
} }
} }
stream->write_function(stream, "Debug Level: %d\n", globals.debug); stream->write_function(stream, "Debug Level: %d\n", mod_av_globals.debug);
ok++; ok++;
} }
} }
} }
end:
if (!ok) { if (!ok) {
stream->write_function(stream, "No input received\n"); stream->write_function(stream, "Usage %s\n", AV_USAGE);
} }
switch_safe_free(mycmd); switch_safe_free(mycmd);
@ -175,11 +194,19 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_av_load)
/* connect my internal structure to the blank pointer passed to me */ /* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname); *module_interface = switch_loadable_module_create_module_interface(pool, modname);
SWITCH_ADD_API(api_interface, "av", "AV general commands", av_function, "debug [on|off]"); SWITCH_ADD_API(api_interface, "av", "AV general commands", av_function, AV_USAGE);
mod_avformat_load(module_interface, pool); mod_avformat_load(module_interface, pool);
mod_avcodec_load(module_interface, pool); mod_avcodec_load(module_interface, pool);
switch_console_set_complete("add av debug on");
switch_console_set_complete("add av debug off");
switch_console_set_complete("add av debug 0");
switch_console_set_complete("add av debug 1");
switch_console_set_complete("add av debug 2");
switch_console_set_complete("add av show formats");
switch_console_set_complete("add av show codecs");
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }

View File

@ -0,0 +1,63 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
*
* 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 <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthm@freeswitch.org>
* Ken Rice <krice@freeswitch.org>
* Paul D. Tinsley <pdt at jackhammer.org>
* Bret McDanel <trixter AT 0xdecafbad.com>
* Marcel Barbulescu <marcelbarbulescu@gmail.com>
* Raymond Chandler <intralanman@gmail.com>
* Emmanuel Schmidbauer <e.schmidbauer@gmail.com>
*
*
* mod_av.h -- LibAV mod
*
*/
#ifndef MOD_AV_H
#define MOD_AV_H
struct mod_av_globals {
int debug;
};
extern struct mod_av_globals mod_av_globals;
void show_codecs(switch_stream_handle_t *stream);
void show_formats(switch_stream_handle_t *stream);
#endif
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

View File

@ -49,6 +49,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_file_open(const char *file,
int is_stream = 0; int is_stream = 0;
char *fp = NULL; char *fp = NULL;
int to = 0; int to = 0;
int force_channels = 0;
if (switch_test_flag(fh, SWITCH_FILE_OPEN)) { if (switch_test_flag(fh, SWITCH_FILE_OPEN)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Handle already open\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Handle already open\n");
@ -128,10 +129,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_file_open(const char *file,
} }
} }
if ((val = switch_event_get_header(fh->params, "channels"))) { if ((val = switch_event_get_header(fh->params, "force_channels"))) {
tmp = atoi(val); tmp = atoi(val);
if (tmp == 1 || tmp == 2) { if (tmp >= 0 && tmp < 3) {
fh->mm.channels = tmp; force_channels = tmp;
} }
} }
@ -298,10 +299,23 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_file_open(const char *file,
fh->handler = NULL; fh->handler = NULL;
} }
if (channels) { if (force_channels == channels) {
fh->channels = channels; force_channels = 0;
}
if (force_channels && force_channels > 0 && force_channels < 3) {
fh->real_channels = channels ? channels : fh->channels;
fh->channels = force_channels;
fh->mm.channels = fh->channels;
} else { } else {
fh->channels = 1;
if (channels) {
fh->channels = channels;
} else {
fh->channels = 1;
}
fh->mm.channels = fh->channels;
} }
file_path = fh->spool_path ? fh->spool_path : fh->file_path; file_path = fh->spool_path ? fh->spool_path : fh->file_path;
@ -314,10 +328,12 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_file_open(const char *file,
goto fail; goto fail;
} }
fh->real_channels = fh->channels; if (!force_channels && !fh->real_channels) {
fh->real_channels = fh->channels;
if (channels) { if (channels) {
fh->channels = channels; fh->channels = channels;
}
} }
if ((flags & SWITCH_FILE_FLAG_WRITE) && !is_stream && (status = switch_file_exists(file_path, fh->memory_pool)) != SWITCH_STATUS_SUCCESS) { if ((flags & SWITCH_FILE_FLAG_WRITE) && !is_stream && (status = switch_file_exists(file_path, fh->memory_pool)) != SWITCH_STATUS_SUCCESS) {
@ -537,6 +553,23 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_write(switch_file_handle_t *fh,
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
if (fh->real_channels != fh->channels && !switch_test_flag(fh, SWITCH_FILE_NOMUX)) {
int need = *len * 2 * fh->real_channels;
if (need > fh->muxlen) {
fh->muxbuf = realloc(fh->muxbuf, need);
switch_assert(fh->muxbuf);
fh->muxlen = need;
memcpy(fh->muxbuf, data, fh->muxlen);
data = fh->muxbuf;
}
switch_mux_channels((int16_t *) data, *len, fh->real_channels, fh->channels);
}
if (!switch_test_flag(fh, SWITCH_FILE_NATIVE) && fh->native_rate != fh->samplerate) { if (!switch_test_flag(fh, SWITCH_FILE_NATIVE) && fh->native_rate != fh->samplerate) {
if (!fh->resampler) { if (!fh->resampler) {
if (switch_resample_create(&fh->resampler, if (switch_resample_create(&fh->resampler,
@ -572,6 +605,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_write(switch_file_handle_t *fh,
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
if (fh->pre_buffer) { if (fh->pre_buffer) {
switch_size_t rlen, blen; switch_size_t rlen, blen;
switch_status_t status = SWITCH_STATUS_SUCCESS; switch_status_t status = SWITCH_STATUS_SUCCESS;
@ -847,6 +881,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_close(switch_file_handle_t *fh)
fh->memory_pool = NULL; fh->memory_pool = NULL;
switch_safe_free(fh->dbuf); switch_safe_free(fh->dbuf);
switch_safe_free(fh->muxbuf);
if (fh->spool_path) { if (fh->spool_path) {
char *command; char *command;

View File

@ -2642,6 +2642,19 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_session(switch_core_session_t
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
} }
if (fh->params) {
if ((p = switch_event_get_header(fh->params,"record_write_only")) && switch_true(p)) {
flags &= ~SMBF_READ_STREAM;
flags |= SMBF_WRITE_STREAM;
}
if ((p = switch_event_get_header(fh->params, "record_read_only")) && switch_true(p)) {
flags &= ~SMBF_WRITE_STREAM;
flags |= SMBF_READ_STREAM;
}
}
if (switch_core_file_has_video(fh, SWITCH_TRUE)) { if (switch_core_file_has_video(fh, SWITCH_TRUE)) {
//switch_core_media_set_video_file(session, fh, SWITCH_RW_READ); //switch_core_media_set_video_file(session, fh, SWITCH_RW_READ);
//switch_channel_set_flag_recursive(session->channel, CF_VIDEO_DECODED_READ); //switch_channel_set_flag_recursive(session->channel, CF_VIDEO_DECODED_READ);