Browse Source

TT#31403 handle passthrough payloads in a transcoding context

Change-Id: I45001272a735847973a6261b899e5acd0687ccef
changes/16/18916/5
Richard Fuchs 8 years ago
parent
commit
2a4acf5e29
2 changed files with 57 additions and 4 deletions
  1. +42
    -3
      daemon/codec.c
  2. +15
    -1
      daemon/rtcp.c

+ 42
- 3
daemon/codec.c View File

@ -33,6 +33,7 @@ struct transcode_packet {
static codec_handler_func handler_func_passthrough; static codec_handler_func handler_func_passthrough;
static codec_handler_func handler_func_passthrough_ssrc;
static codec_handler_func handler_func_transcode; static codec_handler_func handler_func_transcode;
static struct ssrc_entry *__ssrc_handler_new(void *p); static struct ssrc_entry *__ssrc_handler_new(void *p);
@ -49,6 +50,10 @@ static struct codec_handler codec_handler_stub = {
.source_pt.payload_type = -1, .source_pt.payload_type = -1,
.func = handler_func_passthrough, .func = handler_func_passthrough,
}; };
static struct codec_handler codec_handler_stub_ssrc = {
.source_pt.payload_type = -1,
.func = handler_func_passthrough_ssrc,
};
@ -73,6 +78,11 @@ static void __make_passthrough(struct codec_handler *handler) {
handler->func = handler_func_passthrough; handler->func = handler_func_passthrough;
} }
static void __make_passthrough_ssrc(struct codec_handler *handler) {
__handler_shutdown(handler);
handler->func = handler_func_passthrough_ssrc;
}
static void __make_transcoder(struct codec_handler *handler, struct rtp_payload_type *source, static void __make_transcoder(struct codec_handler *handler, struct rtp_payload_type *source,
struct rtp_payload_type *dest) struct rtp_payload_type *dest)
{ {
@ -140,6 +150,7 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink)
MEDIA_CLEAR(receiver, TRANSCODE); MEDIA_CLEAR(receiver, TRANSCODE);
receiver->rtcp_handler = NULL; receiver->rtcp_handler = NULL;
GSList *passthrough_handlers = NULL;
// we go through the list of codecs that the receiver supports and compare it // we go through the list of codecs that the receiver supports and compare it
// with the list of codecs supported by the sink. if the receiver supports // with the list of codecs supported by the sink. if the receiver supports
@ -250,6 +261,7 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink)
if (!pt->codec_def || pt->codec_def->avcodec_id == -1) { if (!pt->codec_def || pt->codec_def->avcodec_id == -1) {
// not supported, or not a real audio codec // not supported, or not a real audio codec
__make_passthrough(handler); __make_passthrough(handler);
passthrough_handlers = g_slist_prepend(passthrough_handlers, handler);
goto next; goto next;
} }
@ -267,6 +279,7 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink)
ilog(LOG_DEBUG, "No known/supported sink codec for " STR_FORMAT, ilog(LOG_DEBUG, "No known/supported sink codec for " STR_FORMAT,
STR_FMT(&pt->encoding_with_params)); STR_FMT(&pt->encoding_with_params));
__make_passthrough(handler); __make_passthrough(handler);
passthrough_handlers = g_slist_prepend(passthrough_handlers, handler);
goto next; goto next;
} }
@ -303,6 +316,7 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink)
// XXX check format parameters as well // XXX check format parameters as well
ilog(LOG_DEBUG, "Sink supports codec " STR_FORMAT, STR_FMT(&pt->encoding_with_params)); ilog(LOG_DEBUG, "Sink supports codec " STR_FORMAT, STR_FMT(&pt->encoding_with_params));
__make_passthrough(handler); __make_passthrough(handler);
passthrough_handlers = g_slist_prepend(passthrough_handlers, handler);
goto next; goto next;
} }
@ -322,8 +336,6 @@ next:
// the list, as we must expect to potentially receive media in that codec, which we // the list, as we must expect to potentially receive media in that codec, which we
// then could not transcode. // then could not transcode.
if (MEDIA_ISSET(receiver, TRANSCODE)) { if (MEDIA_ISSET(receiver, TRANSCODE)) {
// XXX we also must switch all "passthrough" handlers to a special passthrough
// that substitutes out the SSRC
for (GList *l = receiver->codecs_prefs_recv.head; l; ) { for (GList *l = receiver->codecs_prefs_recv.head; l; ) {
struct rtp_payload_type *pt = l->data; struct rtp_payload_type *pt = l->data;
@ -338,7 +350,18 @@ next:
l = __delete_receiver_codec(receiver, l); l = __delete_receiver_codec(receiver, l);
} }
// we have to translate RTCP packets
receiver->rtcp_handler = rtcp_transcode_handler; receiver->rtcp_handler = rtcp_transcode_handler;
// at least some payload types will be transcoded, which will result in SSRC
// change. for payload types which we don't actually transcode, we still
// must substitute the SSRC
while (passthrough_handlers) {
struct codec_handler *handler = passthrough_handlers->data;
__make_passthrough_ssrc(handler);
passthrough_handlers = g_slist_delete_link(passthrough_handlers, passthrough_handlers);
}
} }
} }
@ -362,6 +385,8 @@ struct codec_handler *codec_handler_get(struct call_media *m, int payload_type)
return h; return h;
out: out:
if (MEDIA_ISSET(m, TRANSCODE))
return &codec_handler_stub_ssrc;
return &codec_handler_stub; return &codec_handler_stub;
} }
@ -384,6 +409,20 @@ static int handler_func_passthrough(struct codec_handler *h, struct call_media *
codec_add_raw_packet(mp); codec_add_raw_packet(mp);
return 0; return 0;
} }
static int handler_func_passthrough_ssrc(struct codec_handler *h, struct call_media *media,
struct media_packet *mp)
{
if (G_UNLIKELY(!mp->rtp))
return handler_func_passthrough(h, media, mp);
// substitute out SSRC
mp->rtp->ssrc = htonl(mp->ssrc_in->ssrc_map_out);
// keep track of other stats here?
codec_add_raw_packet(mp);
return 0;
}
static void __transcode_packet_free(struct transcode_packet *p) { static void __transcode_packet_free(struct transcode_packet *p) {
@ -545,7 +584,7 @@ static int __packet_decoded(decoder_t *decoder, AVFrame *frame, void *u1, void *
static int handler_func_transcode(struct codec_handler *h, struct call_media *media, static int handler_func_transcode(struct codec_handler *h, struct call_media *media,
struct media_packet *mp) struct media_packet *mp)
{ {
if (G_UNLIKELY(!mp->rtp || mp->rtcp))
if (G_UNLIKELY(!mp->rtp))
return handler_func_passthrough(h, media, mp); return handler_func_passthrough(h, media, mp);
assert((mp->rtp->m_pt & 0x7f) == h->source_pt.payload_type); assert((mp->rtp->m_pt & 0x7f) == h->source_pt.payload_type);


+ 15
- 1
daemon/rtcp.c View File

@ -1234,6 +1234,7 @@ static void transcode_rr(struct rtcp_process_ctx *ctx, struct report_block *rr)
struct ssrc_ctx *map_ctx = get_ssrc_ctx(ctx->scratch.rr.ssrc, ctx->mp->call->ssrc_hash, struct ssrc_ctx *map_ctx = get_ssrc_ctx(ctx->scratch.rr.ssrc, ctx->mp->call->ssrc_hash,
SSRC_DIR_OUTPUT); SSRC_DIR_OUTPUT);
rr->ssrc = htonl(map_ctx->ssrc_map_out); rr->ssrc = htonl(map_ctx->ssrc_map_out);
// for reception stats // for reception stats
struct ssrc_ctx *input_ctx = get_ssrc_ctx(map_ctx->ssrc_map_out, ctx->mp->call->ssrc_hash, struct ssrc_ctx *input_ctx = get_ssrc_ctx(map_ctx->ssrc_map_out, ctx->mp->call->ssrc_hash,
SSRC_DIR_INPUT); SSRC_DIR_INPUT);
@ -1241,6 +1242,12 @@ static void transcode_rr(struct rtcp_process_ctx *ctx, struct report_block *rr)
// substitute our own values // substitute our own values
unsigned int packets = atomic64_get(&input_ctx->packets); unsigned int packets = atomic64_get(&input_ctx->packets);
// we might not be keeping track of stats for this SSRC (handler_func_passthrough_ssrc).
// just leave the values in place.
if (!packets)
return;
unsigned int lost = atomic64_get(&input_ctx->packets_lost); unsigned int lost = atomic64_get(&input_ctx->packets_lost);
unsigned int dupes = atomic64_get(&input_ctx->duplicates); unsigned int dupes = atomic64_get(&input_ctx->duplicates);
unsigned int tot_lost = lost - dupes; // can be negative/rollover unsigned int tot_lost = lost - dupes; // can be negative/rollover
@ -1270,9 +1277,16 @@ static void transcode_rr(struct rtcp_process_ctx *ctx, struct report_block *rr)
static void transcode_sr(struct rtcp_process_ctx *ctx, struct sender_report_packet *sr) { static void transcode_sr(struct rtcp_process_ctx *ctx, struct sender_report_packet *sr) {
assert(ctx->scratch.sr.ssrc == ctx->mp->ssrc_in->parent->h.ssrc); assert(ctx->scratch.sr.ssrc == ctx->mp->ssrc_in->parent->h.ssrc);
unsigned int packets = atomic64_get(&ctx->mp->ssrc_out->packets);
// we might not be keeping track of stats for this SSRC (handler_func_passthrough_ssrc).
// just leave the values in place.
if (!packets)
return;
// substitute our own values // substitute our own values
sr->octet_count = htonl(atomic64_get(&ctx->mp->ssrc_out->octets)); sr->octet_count = htonl(atomic64_get(&ctx->mp->ssrc_out->octets));
sr->packet_count = htonl(atomic64_get(&ctx->mp->ssrc_out->packets));
sr->packet_count = htonl(packets);
sr->timestamp = htonl(atomic64_get(&ctx->mp->ssrc_out->last_ts)); sr->timestamp = htonl(atomic64_get(&ctx->mp->ssrc_out->last_ts));
// XXX NTP timestamp // XXX NTP timestamp
} }


Loading…
Cancel
Save