From 266e206afcda93cf2880e660fb796eb99fb6df6c Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Wed, 13 Jun 2012 17:35:48 +0400 Subject: [PATCH] added support for multiple aac/avc codecs per stream --- ngx_rtmp_codec_module.c | 13 +++++++++ ngx_rtmp_codec_module.h | 3 +++ ngx_rtmp_live_module.c | 59 +++++++++++++++++++++++++---------------- ngx_rtmp_live_module.h | 2 ++ 4 files changed, 54 insertions(+), 23 deletions(-) diff --git a/ngx_rtmp_codec_module.c b/ngx_rtmp_codec_module.c index 5334fc7..202d89b 100644 --- a/ngx_rtmp_codec_module.c +++ b/ngx_rtmp_codec_module.c @@ -11,6 +11,11 @@ static ngx_int_t ngx_rtmp_codec_postconfiguration(ngx_conf_t *cf); +/* Global header version is used to identify + * incoming AAC/AVC header */ +static ngx_uint_t header_version; + + static ngx_rtmp_module_t ngx_rtmp_codec_module_ctx = { NULL, /* preconfiguration */ ngx_rtmp_codec_postconfiguration, /* postconfiguration */ @@ -139,6 +144,7 @@ ngx_rtmp_codec_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, ngx_chain_t **header, **pheader; uint8_t fmt; ngx_rtmp_header_t ch, lh; + ngx_uint_t *version; /* save AVC/AAC header */ if ((h->type != NGX_RTMP_MSG_AUDIO @@ -166,6 +172,7 @@ ngx_rtmp_codec_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, if (((fmt & 0xf0) >> 4) == NGX_RTMP_AUDIO_AAC) { header = &ctx->aac_header; pheader = &ctx->aac_pheader; + version = &ctx->aac_version; ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "codec: AAC header arrived"); } @@ -173,6 +180,7 @@ ngx_rtmp_codec_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, if ((fmt & 0x0f) == NGX_RTMP_VIDEO_H264) { header = &ctx->avc_header; pheader = &ctx->avc_pheader; + version = &ctx->avc_version; ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "codec: AVC/H264 header arrived"); } @@ -204,6 +212,11 @@ ngx_rtmp_codec_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, *pheader = ngx_rtmp_append_shared_bufs(cscf, NULL, in); ngx_rtmp_prepare_message(s, &ch, &lh, *pheader); + /* don't want zero as version value */ + do { + *version = ++header_version; + } while (*version == 0); + return NGX_OK; } diff --git a/ngx_rtmp_codec_module.h b/ngx_rtmp_codec_module.h index 95e1db0..1d2d308 100644 --- a/ngx_rtmp_codec_module.h +++ b/ngx_rtmp_codec_module.h @@ -47,6 +47,9 @@ u_char * ngx_rtmp_get_video_codec_name(ngx_uint_t id); typedef struct { + ngx_uint_t avc_version; + ngx_uint_t aac_version; + ngx_chain_t *avc_header; ngx_chain_t *aac_header; diff --git a/ngx_rtmp_live_module.c b/ngx_rtmp_live_module.c index ca86c19..d03309c 100644 --- a/ngx_rtmp_live_module.c +++ b/ngx_rtmp_live_module.c @@ -283,7 +283,7 @@ ngx_rtmp_live_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, { ngx_rtmp_live_ctx_t *ctx, *pctx; ngx_rtmp_codec_ctx_t *codec_ctx; - ngx_chain_t *out, *peer_out; + ngx_chain_t *out, *peer_out, *header_out; ngx_rtmp_core_srv_conf_t *cscf; ngx_rtmp_live_app_conf_t *lacf; ngx_rtmp_session_t *ss; @@ -291,6 +291,8 @@ ngx_rtmp_live_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, ngx_uint_t prio, peer_prio; ngx_uint_t peers, dropped_peers; uint8_t flv_fmt; + size_t header_offset; + ngx_uint_t header_version; lacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_live_module); if (lacf == NULL) { @@ -358,6 +360,27 @@ ngx_rtmp_live_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, } } + codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); + header_out = NULL; + header_offset = 0; + header_version = 0; + if (codec_ctx) { + peer_out = NULL; + if (h->type == NGX_RTMP_MSG_AUDIO) { + if (codec_ctx->aac_pheader) { + header_out = codec_ctx->aac_pheader; + header_offset = offsetof(ngx_rtmp_live_ctx_t, aac_version); + header_version = codec_ctx->aac_version; + } + } else { + if (codec_ctx->avc_pheader) { + header_out = codec_ctx->avc_pheader; + header_offset = offsetof(ngx_rtmp_live_ctx_t, avc_version); + header_version = codec_ctx->avc_version; + } + } + } + /* broadcast to all subscribers */ for (pctx = ctx->stream->ctx; pctx; pctx = pctx->next) { if (pctx == ctx) { @@ -378,31 +401,21 @@ ngx_rtmp_live_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, pctx->msg_mask |= (1 << h->type); ngx_rtmp_send_message(ss, peer_out, prio); ngx_rtmp_free_shared_chain(cscf, peer_out); - - /* send AVC/H264 header */ - codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - if (codec_ctx) { - peer_out = NULL; - if (h->type == NGX_RTMP_MSG_AUDIO) { - if (codec_ctx->aac_pheader) { - peer_out = codec_ctx->aac_pheader; - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, ss->connection->log, - 0, "live: sending AAC header"); - } - } else { - if (codec_ctx->avc_pheader) { - peer_out = codec_ctx->avc_pheader; - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, ss->connection->log, - 0, "live: sending AVC/H264 header"); - } - } - if (peer_out) { - ngx_rtmp_send_message(ss, peer_out, prio); - } - } continue; } + /* send AVC/H264 header */ + if (header_out && *(ngx_uint_t *)((u_char *)pctx + header_offset) + != header_version) + { + ngx_log_debug0(NGX_LOG_DEBUG_RTMP, ss->connection->log, 0, + "live: sending codec header"); + if (ngx_rtmp_send_message(ss, header_out, prio) == NGX_OK) { + *(ngx_uint_t *)((u_char *)pctx + header_offset) + = header_version; + } + } + /* push buffered data */ peer_prio = prio; if (ngx_rtmp_send_message(ss, out, peer_prio) != NGX_OK) { diff --git a/ngx_rtmp_live_module.h b/ngx_rtmp_live_module.h index 6d3e30c..ac5e7ac 100644 --- a/ngx_rtmp_live_module.h +++ b/ngx_rtmp_live_module.h @@ -49,6 +49,8 @@ struct ngx_rtmp_live_ctx_s { uint32_t next_push; uint32_t last_audio; uint32_t last_video; + ngx_uint_t aac_version; + ngx_uint_t avc_version; };