TT#76711 generalise media_player mechanism

Change-Id: I940bd8c156691418ee0fe7743e9fade59ba8635a
changes/47/38447/9
Richard Fuchs 5 years ago
parent 9ab6c27b4f
commit 20607bbabc

@ -145,7 +145,7 @@ void codec_handler_free(struct codec_handler *handler) {
__codec_handler_free(handler);
}
static struct codec_handler *__handler_new(struct rtp_payload_type *pt) {
static struct codec_handler *__handler_new(const struct rtp_payload_type *pt) {
struct codec_handler *handler = g_slice_alloc0(sizeof(*handler));
handler->source_pt = *pt;
handler->output_handler = handler; // default
@ -245,8 +245,8 @@ check_output:;
}
}
struct codec_handler *codec_handler_make_playback(struct rtp_payload_type *src_pt,
struct rtp_payload_type *dst_pt, unsigned long last_ts)
struct codec_handler *codec_handler_make_playback(const struct rtp_payload_type *src_pt,
const struct rtp_payload_type *dst_pt, unsigned long last_ts)
{
struct codec_handler *handler = __handler_new(src_pt);
handler->dest_pt = *dst_pt;

@ -33,6 +33,8 @@ static struct timerthread send_timer_thread;
static void send_timer_send_nolock(struct send_timer *st, struct codec_packet *cp);
static void send_timer_send_lock(struct send_timer *st, struct codec_packet *cp);
static void media_player_read_packet(struct media_player *mp);
#ifdef WITH_TRANSCODING
@ -112,6 +114,7 @@ struct media_player *media_player_new(struct call_monologue *ml) {
mp->tt_obj.tt = &media_player_thread;
mutex_init(&mp->lock);
mp->run_func = media_player_read_packet; // default
mp->call = obj_get(ml->call);
mp->ml = ml;
mp->seq = random();
@ -214,29 +217,9 @@ void send_timer_push(struct send_timer *st, struct codec_packet *cp) {
#ifdef WITH_TRANSCODING
#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 26, 0)
#define CODECPAR codecpar
#else
#define CODECPAR codec
#endif
static int __ensure_codec_handler(struct media_player *mp, AVStream *avs) {
if (mp->handler)
return 0;
// synthesise rtp payload type
struct rtp_payload_type src_pt = { .payload_type = -1 };
// src_pt.codec_def = codec_find_by_av(avs->codec->codec_id); `codec` is deprecated
src_pt.codec_def = codec_find_by_av(avs->CODECPAR->codec_id);
if (!src_pt.codec_def) {
ilog(LOG_ERR, "Attempting to play media from an unsupported file format/codec");
return -1;
}
src_pt.encoding = src_pt.codec_def->rtpname_str;
src_pt.channels = avs->CODECPAR->channels;
src_pt.clock_rate = avs->CODECPAR->sample_rate;
codec_init_payload_type(&src_pt, mp->media);
int media_player_setup(struct media_player *mp, const struct rtp_payload_type *src_pt) {
// find suitable output payload type
struct rtp_payload_type *dst_pt;
for (GList *l = mp->media->codecs_prefs_send.head; l; l = l->next) {
@ -260,16 +243,93 @@ found:
mp->sync_ts += ts_diff_us * dst_pt->clock_rate / 1000000 / dst_pt->codec_def->clockrate_mult;
}
mp->handler = codec_handler_make_playback(&src_pt, dst_pt, mp->sync_ts);
mp->handler = codec_handler_make_playback(src_pt, dst_pt, mp->sync_ts);
if (!mp->handler)
return -1;
return 0;
}
#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 26, 0)
#define CODECPAR codecpar
#else
#define CODECPAR codec
#endif
static int __ensure_codec_handler(struct media_player *mp, AVStream *avs) {
if (mp->handler)
return 0;
// synthesise rtp payload type
struct rtp_payload_type src_pt = { .payload_type = -1 };
// src_pt.codec_def = codec_find_by_av(avs->codec->codec_id); `codec` is deprecated
src_pt.codec_def = codec_find_by_av(avs->CODECPAR->codec_id);
if (!src_pt.codec_def) {
ilog(LOG_ERR, "Attempting to play media from an unsupported file format/codec");
return -1;
}
src_pt.encoding = src_pt.codec_def->rtpname_str;
src_pt.channels = avs->CODECPAR->channels;
src_pt.clock_rate = avs->CODECPAR->sample_rate;
codec_init_payload_type(&src_pt, mp->media);
if (media_player_setup(mp, &src_pt))
return -1;
mp->duration = avs->duration * 1000 * avs->time_base.num / avs->time_base.den;
return 0;
}
// appropriate lock must be held
void media_player_add_packet(struct media_player *mp, char *buf, size_t len,
long long us_dur, unsigned long long pts)
{
// synthesise fake RTP header and media_packet context
struct rtp_header rtp = {
.timestamp = pts, // taken verbatim by handler_func_playback w/o byte swap
.seq_num = htons(mp->seq),
};
struct media_packet packet = {
.tv = rtpe_now,
.call = mp->call,
.media = mp->media,
.rtp = &rtp,
.ssrc_out = mp->ssrc_out,
};
str_init_len(&packet.raw, buf, len);
packet.payload = packet.raw;
mp->handler->func(mp->handler, &packet);
// as this is timing sensitive and we may have spent some time decoding,
// update our global "now" timestamp
gettimeofday(&rtpe_now, NULL);
// keep track of RTP timestamps and real clock. look at the last packet we received
// and update our sync TS.
if (packet.packets_out.head) {
struct codec_packet *p = packet.packets_out.head->data;
if (p->rtp) {
mp->sync_ts = ntohl(p->rtp->timestamp);
mp->sync_ts_tv = p->ttq_entry.when;
}
}
media_packet_encrypt(mp->crypt_handler->out->rtp_crypt, mp->sink, &packet);
mutex_lock(&mp->sink->out_lock);
if (media_socket_dequeue(&packet, mp->sink))
ilog(LOG_ERR, "Error sending playback media to RTP sink");
mutex_unlock(&mp->sink->out_lock);
timeval_add_usec(&mp->next_run, us_dur);
timerthread_obj_schedule_abs(&mp->tt_obj, &mp->next_run);
}
// appropriate lock must be held
static void media_player_read_packet(struct media_player *mp) {
if (!mp->fmtctx)
@ -317,50 +377,20 @@ static void media_player_read_packet(struct media_player *mp) {
avs->CODECPAR->sample_rate,
avs->time_base.num, avs->time_base.den);
// synthesise fake RTP header and media_packet context
media_player_add_packet(mp, (char *) mp->pkt.data, mp->pkt.size, us_dur, pts_scaled);
struct rtp_header rtp = {
.timestamp = pts_scaled, // taken verbatim by handler_func_playback w/o byte swap
.seq_num = htons(mp->seq),
};
struct media_packet packet = {
.tv = rtpe_now,
.call = mp->call,
.media = mp->media,
.rtp = &rtp,
.ssrc_out = mp->ssrc_out,
};
str_init_len(&packet.raw, (char *) mp->pkt.data, mp->pkt.size);
packet.payload = packet.raw;
mp->handler->func(mp->handler, &packet);
out:
av_packet_unref(&mp->pkt);
}
// as this is timing sensitive and we may have spent some time decoding,
// update our global "now" timestamp
gettimeofday(&rtpe_now, NULL);
// keep track of RTP timestamps and real clock. look at the last packet we received
// and update our sync TS.
if (packet.packets_out.head) {
struct codec_packet *p = packet.packets_out.head->data;
if (p->rtp) {
mp->sync_ts = ntohl(p->rtp->timestamp);
mp->sync_ts_tv = p->ttq_entry.when;
}
// call->master_lock held in W
void media_player_set_media(struct media_player *mp, struct call_media *media) {
mp->media = media;
if (media->streams.head) {
mp->sink = media->streams.head->data;
mp->crypt_handler = determine_handler(&transport_protocols[PROTO_RTP_AVP], media, 1);
}
media_packet_encrypt(mp->crypt_handler->out->rtp_crypt, mp->sink, &packet);
mutex_lock(&mp->sink->out_lock);
if (media_socket_dequeue(&packet, mp->sink))
ilog(LOG_ERR, "Error sending playback media to RTP sink");
mutex_unlock(&mp->sink->out_lock);
timeval_add_usec(&mp->next_run, us_dur);
timerthread_obj_schedule_abs(&mp->tt_obj, &mp->next_run);
out:
av_packet_unref(&mp->pkt);
}
@ -386,9 +416,7 @@ found:
ilog(LOG_ERR, "No suitable SDP section for media playback");
return -1;
}
mp->media = media;
mp->sink = media->streams.head->data;
mp->crypt_handler = determine_handler(&transport_protocols[PROTO_RTP_AVP], media, 1);
media_player_set_media(mp, media);
return 0;
}
@ -629,7 +657,7 @@ static void media_player_run(void *ptr) {
rwlock_lock_r(&call->master_lock);
mutex_lock(&mp->lock);
media_player_read_packet(mp);
mp->run_func(mp);
mutex_unlock(&mp->lock);
rwlock_unlock_r(&call->master_lock);

@ -52,8 +52,8 @@ struct codec_packet {
struct codec_handler *codec_handler_get(struct call_media *, int payload_type);
void codec_handlers_free(struct call_media *);
struct codec_handler *codec_handler_make_playback(struct rtp_payload_type *src_pt,
struct rtp_payload_type *dst_pt, unsigned long ts);
struct codec_handler *codec_handler_make_playback(const struct rtp_payload_type *src_pt,
const struct rtp_payload_type *dst_pt, unsigned long ts);
void codec_handler_free(struct codec_handler *handler);
void ensure_codec_def(struct rtp_payload_type *pt, struct call_media *media);

@ -9,12 +9,14 @@
struct call;
struct call_media;
struct call_monologue;
struct codec_handler;
struct ssrc_ctx;
struct packet_stream;
struct codec_packet;
struct media_player;
struct rtp_payload_type;
#ifdef WITH_TRANSCODING
@ -22,9 +24,14 @@ struct media_player;
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
typedef void (*media_player_run_func)(struct media_player *);
struct media_player {
struct timerthread_obj tt_obj;
mutex_t lock;
media_player_run_func run_func;
struct call *call;
struct call_monologue *ml;
struct call_media *media;
@ -74,6 +81,11 @@ 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 *);
int media_player_setup(struct media_player *mp, const struct rtp_payload_type *src_pt);
void media_player_set_media(struct media_player *mp, struct call_media *media);
void media_player_add_packet(struct media_player *mp, char *buf, size_t len,
long long us_dur, unsigned long long pts);
void media_player_init(void);
void media_player_loop(void *);

Loading…
Cancel
Save