|
|
|
|
@ -25,6 +25,12 @@
|
|
|
|
|
|
|
|
|
|
#define DEFAULT_AVIO_BUFSIZE 4096
|
|
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
|
MPC_OK = 0,
|
|
|
|
|
MPC_ERR = -1,
|
|
|
|
|
MPC_CACHED = 1,
|
|
|
|
|
} mp_cached_code;
|
|
|
|
|
|
|
|
|
|
#ifdef WITH_TRANSCODING
|
|
|
|
|
static struct timerthread media_player_thread;
|
|
|
|
|
static __thread MYSQL *mysql_conn;
|
|
|
|
|
@ -512,6 +518,8 @@ static bool media_player_cache_get_entry(struct media_player *mp,
|
|
|
|
|
return false;
|
|
|
|
|
if (mp->cache_index.type <= 0)
|
|
|
|
|
return false;
|
|
|
|
|
if (!dst_pt)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
struct media_player_cache_index lookup;
|
|
|
|
|
lookup.index = mp->cache_index;
|
|
|
|
|
@ -954,17 +962,15 @@ static void media_player_play_start(struct media_player *mp, const rtp_payload_t
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// call->master_lock held in W
|
|
|
|
|
bool media_player_play_file(struct media_player *mp, const str *file, long long repeat, long long start_pos) {
|
|
|
|
|
static mp_cached_code __media_player_init_file(struct media_player *mp, const str *file, long long repeat,
|
|
|
|
|
long long start_pos, const rtp_payload_type *dst_pt)
|
|
|
|
|
{
|
|
|
|
|
#ifdef WITH_TRANSCODING
|
|
|
|
|
const rtp_payload_type *dst_pt = media_player_play_init(mp);
|
|
|
|
|
if (!dst_pt)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
mp->cache_index.type = MP_FILE;
|
|
|
|
|
str_init_dup_str(&mp->cache_index.file, file);
|
|
|
|
|
|
|
|
|
|
if (media_player_cache_get_entry(mp, dst_pt, repeat))
|
|
|
|
|
return true;
|
|
|
|
|
return MPC_CACHED;
|
|
|
|
|
|
|
|
|
|
char file_s[PATH_MAX];
|
|
|
|
|
snprintf(file_s, sizeof(file_s), STR_FORMAT, STR_FMT(file));
|
|
|
|
|
@ -972,9 +978,28 @@ bool media_player_play_file(struct media_player *mp, const str *file, long long
|
|
|
|
|
int ret = avformat_open_input(&mp->coder.fmtctx, file_s, NULL, NULL);
|
|
|
|
|
if (ret < 0) {
|
|
|
|
|
ilog(LOG_ERR, "Failed to open media file for playback: %s", av_error(ret));
|
|
|
|
|
return false;
|
|
|
|
|
return MPC_ERR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return MPC_OK;
|
|
|
|
|
#else
|
|
|
|
|
return MPC_ERR;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// call->master_lock held in W
|
|
|
|
|
bool media_player_play_file(struct media_player *mp, const str *file, long long repeat, long long start_pos) {
|
|
|
|
|
#ifdef WITH_TRANSCODING
|
|
|
|
|
const rtp_payload_type *dst_pt = media_player_play_init(mp);
|
|
|
|
|
if (!dst_pt)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
mp_cached_code ret = __media_player_init_file(mp, file, repeat, start_pos, dst_pt);
|
|
|
|
|
if (ret == MPC_CACHED)
|
|
|
|
|
return true;
|
|
|
|
|
if (ret == MPC_ERR)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
media_player_play_start(mp, dst_pt, repeat, start_pos);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
@ -1032,29 +1057,25 @@ static int64_t __mp_avio_seek(void *opaque, int64_t offset, int whence) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// call->master_lock held in W
|
|
|
|
|
static bool media_player_play_blob_id(struct media_player *mp, const str *blob, long long repeat,
|
|
|
|
|
long long start_pos, long long db_id)
|
|
|
|
|
static mp_cached_code __media_player_init_blob_id(struct media_player *mp, const str *blob, long long repeat,
|
|
|
|
|
long long start_pos, long long db_id, const rtp_payload_type *dst_pt)
|
|
|
|
|
{
|
|
|
|
|
const char *err;
|
|
|
|
|
int av_ret = 0;
|
|
|
|
|
|
|
|
|
|
const rtp_payload_type *dst_pt = media_player_play_init(mp);
|
|
|
|
|
if (!dst_pt)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (db_id >= 0) {
|
|
|
|
|
mp->cache_index.type = MP_DB;
|
|
|
|
|
mp->cache_index.db_id = db_id;
|
|
|
|
|
|
|
|
|
|
if (media_player_cache_get_entry(mp, dst_pt, repeat))
|
|
|
|
|
return true;
|
|
|
|
|
return MPC_CACHED;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
mp->cache_index.type = MP_BLOB;
|
|
|
|
|
str_init_dup_str(&mp->cache_index.file, blob);
|
|
|
|
|
|
|
|
|
|
if (media_player_cache_get_entry(mp, dst_pt, repeat))
|
|
|
|
|
return true;
|
|
|
|
|
return MPC_CACHED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mp->coder.blob = str_dup(blob);
|
|
|
|
|
@ -1087,15 +1108,13 @@ static bool media_player_play_blob_id(struct media_player *mp, const str *blob,
|
|
|
|
|
if (av_ret < 0)
|
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
|
|
media_player_play_start(mp, dst_pt, repeat, start_pos);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
return MPC_OK;
|
|
|
|
|
|
|
|
|
|
err:
|
|
|
|
|
ilog(LOG_ERR, "Failed to start media playback from memory: %s", err);
|
|
|
|
|
if (av_ret)
|
|
|
|
|
ilog(LOG_ERR, "Error returned from libav: %s", av_error(av_ret));
|
|
|
|
|
return false;
|
|
|
|
|
return MPC_ERR;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
@ -1103,7 +1122,19 @@ err:
|
|
|
|
|
// call->master_lock held in W
|
|
|
|
|
bool media_player_play_blob(struct media_player *mp, const str *blob, long long repeat, long long start_pos) {
|
|
|
|
|
#ifdef WITH_TRANSCODING
|
|
|
|
|
return media_player_play_blob_id(mp, blob, repeat, start_pos, -1);
|
|
|
|
|
const rtp_payload_type *dst_pt = media_player_play_init(mp);
|
|
|
|
|
if (!dst_pt)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
mp_cached_code ret = __media_player_init_blob_id(mp, blob, repeat, start_pos, -1, dst_pt);
|
|
|
|
|
if (ret == MPC_CACHED)
|
|
|
|
|
return true;
|
|
|
|
|
if (ret == MPC_ERR)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
media_player_play_start(mp, dst_pt, repeat, start_pos);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
#else
|
|
|
|
|
return false;
|
|
|
|
|
#endif
|
|
|
|
|
@ -1134,7 +1165,10 @@ err:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// call->master_lock held in W
|
|
|
|
|
bool media_player_play_db(struct media_player *mp, long long id, long long repeat, long long start_pos) {
|
|
|
|
|
static mp_cached_code __media_player_init_db(struct media_player *mp, long long id, long long repeat,
|
|
|
|
|
long long start_pos,
|
|
|
|
|
const rtp_payload_type *dst_pt)
|
|
|
|
|
{
|
|
|
|
|
const char *err;
|
|
|
|
|
g_autoptr(char) query = NULL;
|
|
|
|
|
|
|
|
|
|
@ -1180,7 +1214,7 @@ success:;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
str blob = STR_INIT_LEN(row[0], lengths[0]);
|
|
|
|
|
bool ret = media_player_play_blob_id(mp, &blob, repeat, start_pos, id);
|
|
|
|
|
mp_cached_code ret = __media_player_init_blob_id(mp, &blob, repeat, start_pos, id, dst_pt);
|
|
|
|
|
|
|
|
|
|
mysql_free_result(res);
|
|
|
|
|
|
|
|
|
|
@ -1191,7 +1225,24 @@ err:
|
|
|
|
|
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 false;
|
|
|
|
|
return MPC_ERR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// call->master_lock held in W
|
|
|
|
|
bool media_player_play_db(struct media_player *mp, long long id, long long repeat, long long start_pos) {
|
|
|
|
|
const rtp_payload_type *dst_pt = media_player_play_init(mp);
|
|
|
|
|
if (!dst_pt)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
mp_cached_code ret = __media_player_init_db(mp, id, repeat, start_pos, dst_pt);
|
|
|
|
|
if (ret == MPC_CACHED)
|
|
|
|
|
return true;
|
|
|
|
|
if (ret == MPC_ERR)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
media_player_play_start(mp, dst_pt, repeat, start_pos);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|