Browse Source

TT#50652 support playing back media files from database

Change-Id: Ib21b6605553f67d6892ec8e2c75a7b0fca40936e
changes/22/27722/5
Richard Fuchs 7 years ago
parent
commit
5b0a0105ef
9 changed files with 143 additions and 10 deletions
  1. +1
    -0
      daemon/.ycm_extra_conf.py
  2. +6
    -4
      daemon/Makefile
  3. +11
    -5
      daemon/call_interfaces.c
  4. +21
    -0
      daemon/main.c
  5. +94
    -0
      daemon/media_player.c
  6. +5
    -0
      include/main.h
  7. +1
    -0
      include/media_player.h
  8. +2
    -0
      t/Makefile
  9. +2
    -1
      utils/rtpengine-ng-client

+ 1
- 0
daemon/.ycm_extra_conf.py View File

@ -29,6 +29,7 @@ flags = [
'-I/usr/include/glib-2.0',
'-I/usr/lib/x86_64-linux-gnu/glib-2.0/include',
'-I/usr/include/json-glib-1.0',
'-I/usr/include/mysql',
'-pthread',
'-I../kernel-module/',
'-I../lib/',


+ 6
- 4
daemon/Makefile View File

@ -76,13 +76,14 @@ CFLAGS+= $(shell pkg-config --cflags libavutil)
CFLAGS+= $(shell pkg-config --cflags libswresample)
CFLAGS+= $(shell pkg-config --cflags libavfilter)
CFLAGS+= -DWITH_TRANSCODING
else
CFLAGS+= -DWITHOUT_CODECLIB
endif
ifeq ($(have_bcg729),yes)
CFLAGS+= -DHAVE_BCG729
CFLAGS+= $(bcg729_inc)
endif
CFLAGS+= $(shell mysql_config --cflags)
else
CFLAGS+= -DWITHOUT_CODECLIB
endif
CFLAGS+= -DRE_PLUGIN_DIR="\"/usr/lib/rtpengine\""
@ -114,10 +115,11 @@ LDLIBS+= $(shell pkg-config --libs libavformat)
LDLIBS+= $(shell pkg-config --libs libavutil)
LDLIBS+= $(shell pkg-config --libs libswresample)
LDLIBS+= $(shell pkg-config --libs libavfilter)
endif
ifeq ($(have_bcg729),yes)
LDLIBS+= $(bcg729_lib)
endif
LDLIBS+= $(shell mysql_config --libs)
endif
SRCS= main.c kernel.c poller.c aux.c control_tcp.c call.c control_udp.c redis.c \
bencode.c cookie_cache.c udp_listener.c control_ng.strhash.c sdp.strhash.c stun.c rtcp.c \


+ 11
- 5
daemon/call_interfaces.c View File

@ -1734,10 +1734,11 @@ out:
const char *call_play_media_ng(bencode_item_t *input, bencode_item_t *output) {
#ifdef WITH_TRANSCODING
str callid, fromtag, file;
str callid, fromtag, str;
struct call *call;
struct call_monologue *monologue;
const char *err = NULL;
long long db_id;
if (!bencode_dictionary_get_str(input, "call-id", &callid))
return "No call-id in message";
@ -1759,14 +1760,19 @@ const char *call_play_media_ng(bencode_item_t *input, bencode_item_t *output) {
monologue->player = media_player_new(monologue);
err = "No media file specified";
if (bencode_dictionary_get_str(input, "file", &file)) {
if (bencode_dictionary_get_str(input, "file", &str)) {
err = "Failed to start media playback from file";
if (media_player_play_file(monologue->player, &file))
if (media_player_play_file(monologue->player, &str))
goto out;
}
else if (bencode_dictionary_get_str(input, "blob", &file)) {
else if (bencode_dictionary_get_str(input, "blob", &str)) {
err = "Failed to start media playback from blob";
if (media_player_play_blob(monologue->player, &file))
if (media_player_play_blob(monologue->player, &str))
goto out;
}
else if ((db_id = bencode_dictionary_get_int_str(input, "db-id", 0)) > 0) {
err = "Failed to start media playback from database";
if (media_player_play_db(monologue->player, db_id))
goto out;
}
else


+ 21
- 0
daemon/main.c View File

@ -366,6 +366,11 @@ static void options(int *argc, char ***argv) {
{ "idle-scheduling",0, 0,G_OPTION_ARG_STRING, &rtpe_config.idle_scheduling,"Idle thread scheduling policy", "default|none|fifo|rr|other|batch|idle" },
{ "idle-priority",0, 0, G_OPTION_ARG_INT, &rtpe_config.idle_priority,"Idle thread scheduling priority", "INT" },
{ "log-srtp-keys",'F', 0, G_OPTION_ARG_NONE, &rtpe_config.log_keys, "Log SRTP keys to error log", NULL },
{ "mysql-host", 0, 0, G_OPTION_ARG_STRING, &rtpe_config.mysql_host,"MySQL host for stored media files","HOST|IP" },
{ "mysql-port", 0, 0, G_OPTION_ARG_INT, &rtpe_config.mysql_port,"MySQL port" ,"INT" },
{ "mysql-user", 0, 0, G_OPTION_ARG_STRING, &rtpe_config.mysql_user,"MySQL connection credentials", "USERNAME" },
{ "mysql-pass", 0, 0, G_OPTION_ARG_STRING, &rtpe_config.mysql_pass,"MySQL connection credentials", "PASSWORD" },
{ "mysql-query",0, 0, G_OPTION_ARG_STRING, &rtpe_config.mysql_query,"MySQL select query", "STRING" },
{ NULL, }
};
@ -518,6 +523,22 @@ static void options(int *argc, char ***argv) {
rtpe_config.cpu_limit = max_cpu * 100;
rtpe_config.load_limit = max_load * 100;
if (rtpe_config.mysql_query) {
// require exactly one %llu placeholder and allow no other % placeholders
if (!strstr(rtpe_config.mysql_query, "%llu"))
die("No '%%llu' present in --mysql-query='%s'", rtpe_config.mysql_query);
const char *front = rtpe_config.mysql_query;
unsigned int count = 0;
const char *match;
while ((match = strchr(front, '%'))) {
front = match + 1;
count++;
}
if (count != 1)
die("Too many '%%' placeholders (%u) present in --mysql-query='%s'",
count, rtpe_config.mysql_query);
}
}
void fill_initial_rtpe_cfg(struct rtpengine_config* ini_rtpe_cfg) {


+ 94
- 0
daemon/media_player.c View File

@ -1,5 +1,9 @@
#include "media_player.h"
#include <glib.h>
#ifdef WITH_TRANSCODING
#include <mysql.h>
#include <mysql/errmsg.h>
#endif
#include "obj.h"
#include "log.h"
#include "timerthread.h"
@ -10,6 +14,7 @@
#include "media_socket.h"
#include "ssrc.h"
#include "log_funcs.h"
#include "main.h"
@ -19,6 +24,7 @@
#ifdef WITH_TRANSCODING
static struct timerthread media_player_thread;
static MYSQL __thread *mysql_conn;
#endif
static struct timerthread send_timer_thread;
@ -404,6 +410,7 @@ static int64_t __mp_avio_seek(void *opaque, int64_t offset, int whence) {
#endif
// call->master_lock held in W
int media_player_play_blob(struct media_player *mp, const str *blob) {
#ifdef WITH_TRANSCODING
@ -453,6 +460,93 @@ err:
#ifdef WITH_TRANSCODING
static int __connect_db(void) {
if (mysql_conn) {
mysql_close(mysql_conn);
mysql_conn = NULL;
}
mysql_conn = mysql_init(NULL);
if (!mysql_conn)
return -1;
if (!mysql_real_connect(mysql_conn, rtpe_config.mysql_host, rtpe_config.mysql_user, rtpe_config.mysql_pass, NULL, rtpe_config.mysql_port,
NULL, CLIENT_IGNORE_SIGPIPE))
goto err;
return 0;
err:
ilog(LOG_ERR, "Couldn't connect to database: %s", mysql_error(mysql_conn));
mysql_close(mysql_conn);
mysql_conn = NULL;
return -1;
}
// call->master_lock held in W
int media_player_play_db(struct media_player *mp, long long id) {
const char *err;
AUTO_CLEANUP_BUF(query);
err = "missing configuration";
if (!rtpe_config.mysql_host || !rtpe_config.mysql_query)
goto err;
int len = asprintf(&query, rtpe_config.mysql_query, (unsigned long long) id);
err = "query print error";
if (len <= 0)
goto err;
for (int retries = 0; retries < 5; retries++) {
if (!mysql_conn || retries != 0) {
err = "failed to connect to database";
if (__connect_db())
goto err;
}
int ret = mysql_real_query(mysql_conn, query, len);
if (ret == 0)
goto success;
ret = mysql_errno(mysql_conn);
if (ret == CR_SERVER_GONE_ERROR || ret == CR_SERVER_LOST)
continue;
ilog(LOG_ERR, "Failed to query from database: %s", mysql_error(mysql_conn));
}
err = "exceeded max number of database retries";
goto err;
success:;
MYSQL_RES *res = mysql_store_result(mysql_conn);
err = "failed to get result from database";
if (!res)
goto err;
MYSQL_ROW row = mysql_fetch_row(res);
unsigned long *lengths = mysql_fetch_lengths(res);
err = "empty result from database";
if (!row || !lengths || !row[0] || !lengths[0]) {
mysql_free_result(res);
goto err;
}
str blob;
str_init_len(&blob, row[0], lengths[0]);
int ret = media_player_play_blob(mp, &blob);
mysql_free_result(res);
return ret;
err:
if (query)
ilog(LOG_ERR, "Failed to start media playback from database (used query '%s'): %s", query, err);
else
ilog(LOG_ERR, "Failed to start media playback from database: %s", err);
return -1;
}
static void media_player_run(void *ptr) {
struct media_player *mp = ptr;
struct call *call = mp->call;


+ 5
- 0
include/main.h View File

@ -78,6 +78,11 @@ struct rtpengine_config {
char *idle_scheduling;
int idle_priority;
int log_keys;
char *mysql_host;
int mysql_port;
char *mysql_user;
char *mysql_pass;
char *mysql_query;
};


+ 1
- 0
include/media_player.h View File

@ -69,6 +69,7 @@ struct send_timer {
struct media_player *media_player_new(struct call_monologue *);
int media_player_play_file(struct media_player *, const str *);
int media_player_play_blob(struct media_player *, const str *);
int media_player_play_db(struct media_player *, long long);
void media_player_stop(struct media_player *);
void media_player_init(void);


+ 2
- 0
t/Makefile View File

@ -26,6 +26,7 @@ CFLAGS+= $(shell pkg-config xmlrpc_util --cflags 2> /dev/null)
ifeq ($(with_amr_tests),yes)
CFLAGS+= -DWITH_AMR_TESTS
endif
CFLAGS+= $(shell mysql_config --cflags)
else
CFLAGS+= -DWITHOUT_CODECLIB
endif
@ -50,6 +51,7 @@ LDLIBS+= $(shell pkg-config xmlrpc_client --libs 2> /dev/null || xmlrpc-c-config
LDLIBS+= $(shell pkg-config xmlrpc --libs 2> /dev/null)
LDLIBS+= $(shell pkg-config xmlrpc_util --libs 2> /dev/null)
LDLIBS+= -lhiredis
LDLIBS+= $(shell mysql_config --libs)
endif
SRCS= bitstr-test.c aes-crypt.c payload-tracker-test.c const_str_hash-test.strhash.c


+ 2
- 1
utils/rtpengine-ng-client View File

@ -69,13 +69,14 @@ GetOptions(
'file=s' => \$options{'file'},
'blob=s' => \$options{'blob'},
'blob-file=s' => \$options{'blob-file'},
'db-id=i' => \$options{'db-id'},
) or die;
my $cmd = shift(@ARGV) or die;
my %packet = (command => $cmd);
for my $x (split(/,/, 'from-tag,to-tag,call-id,transport protocol,media address,ICE,address family,DTLS,via-branch,media address,ptime,xmlrpc-callback,metadata,address,file')) {
for my $x (split(/,/, 'from-tag,to-tag,call-id,transport protocol,media address,ICE,address family,DTLS,via-branch,media address,ptime,xmlrpc-callback,metadata,address,file,db-id')) {
defined($options{$x}) and $packet{$x} = \$options{$x};
}
for my $x (split(/,/, 'TOS,delete-delay')) {


Loading…
Cancel
Save