diff --git a/ngx_rtmp_relay_module.c b/ngx_rtmp_relay_module.c index 155378c..09e4b23 100644 --- a/ngx_rtmp_relay_module.c +++ b/ngx_rtmp_relay_module.c @@ -1327,7 +1327,7 @@ ngx_rtmp_relay_send_set_data_frame(ngx_rtmp_session_t *s) }; ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_relay_module); - if (ctx == NULL) { + if (ctx == NULL || !s->relay) { ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "relay: couldn't get relay context"); return NGX_OK; @@ -1335,14 +1335,15 @@ ngx_rtmp_relay_send_set_data_frame(ngx_rtmp_session_t *s) /* we need to get the codec context from the incoming publisher in order to * send the metadata along */ - codec_ctx = ngx_rtmp_get_module_ctx(ctx->publish->session, ngx_rtmp_codec_module); + codec_ctx = ngx_rtmp_get_module_ctx(ctx->publish->session, + ngx_rtmp_codec_module); if (codec_ctx == NULL) { ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "relay: couldn't get codec context"); return NGX_OK; } - ngx_log_debug6(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, "relay: data frame from codec context: " "width=%ui height=%ui duration=%ui frame_rate=%ui " "video_codec_id=%ui audio_codec_id=%ui", @@ -1350,24 +1351,33 @@ ngx_rtmp_relay_send_set_data_frame(ngx_rtmp_session_t *s) codec_ctx->frame_rate, codec_ctx->video_codec_id, codec_ctx->audio_codec_id); - v.width = codec_ctx->width; - v.height = codec_ctx->height; - v.duration = codec_ctx->duration; - v.frame_rate = codec_ctx->frame_rate; - v.video_data_rate = codec_ctx->video_data_rate; - v.video_codec_id = codec_ctx->video_codec_id; - v.audio_data_rate = codec_ctx->audio_data_rate; - v.audio_codec_id = codec_ctx->audio_codec_id; - ngx_memcpy(v.profile, codec_ctx->profile, sizeof(codec_ctx->profile)); - ngx_memcpy(v.level, codec_ctx->level, sizeof(codec_ctx->level)); + /* we only want to send the metadata if the codec module has already + * parsed it -- is there a better way to check this? */ + if (codec_ctx->width > 0 && codec_ctx->height > 0) { + v.width = codec_ctx->width; + v.height = codec_ctx->height; + v.duration = codec_ctx->duration; + v.frame_rate = codec_ctx->frame_rate; + v.video_data_rate = codec_ctx->video_data_rate; + v.video_codec_id = codec_ctx->video_codec_id; + v.audio_data_rate = codec_ctx->audio_data_rate; + v.audio_codec_id = codec_ctx->audio_codec_id; + ngx_memcpy(v.profile, codec_ctx->profile, sizeof(codec_ctx->profile)); + ngx_memcpy(v.level, codec_ctx->level, sizeof(codec_ctx->level)); - ngx_memzero(&hdr, sizeof(hdr)); - hdr.csid = NGX_RTMP_RELAY_CSID_AMF_INI; - hdr.msid = NGX_RTMP_RELAY_MSID; - hdr.type = NGX_RTMP_MSG_AMF_META; + ngx_memzero(&hdr, sizeof(hdr)); + hdr.csid = NGX_RTMP_RELAY_CSID_AMF_INI; + hdr.msid = NGX_RTMP_RELAY_MSID; + hdr.type = NGX_RTMP_MSG_AMF_META; - return ngx_rtmp_send_amf(s, &hdr, out_elts, - sizeof(out_elts) / sizeof(out_elts[0])); + ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, + "relay: sending @setDataFrame"); + + return ngx_rtmp_send_amf(s, &hdr, out_elts, + sizeof(out_elts) / sizeof(out_elts[0])); + } + + return NGX_OK; } static ngx_int_t @@ -1445,8 +1455,12 @@ ngx_rtmp_relay_on_status(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, */ if (!ngx_strncasecmp(v.code, (u_char *)"NetStream.Publish.Start", ngx_strlen("NetStream.Publish.Start"))) { + + ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, + "relay: sending metadata from NetStream.Publish.Start from player"); + if (ngx_rtmp_relay_send_set_data_frame(s) != NGX_OK) { - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "relay: unable to send metadata via @setDataFrame"); } } @@ -1454,6 +1468,26 @@ ngx_rtmp_relay_on_status(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, return NGX_OK; } +static ngx_int_t +ngx_rtmp_relay_on_meta_data(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, + ngx_chain_t *in) +{ + /* when we receive onMetaData, the session (s) is our incoming publisher's + * session, so we need to send the @setDataFrame to our ctx->play->session */ + ngx_rtmp_relay_ctx_t *ctx; + + ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_relay_module); + if (ctx == NULL || !ctx->play->session->relay) { + ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, + "relay: not sending metadata from @setDataFrame event from publisher"); + return NGX_OK; + } + + ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, + "relay: sending metadata from @setDataFrame event from publisher"); + + return ngx_rtmp_relay_send_set_data_frame(ctx->play->session); +} static ngx_int_t ngx_rtmp_relay_handshake_done(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, @@ -1838,5 +1872,9 @@ ngx_rtmp_relay_postconfiguration(ngx_conf_t *cf) ngx_str_set(&ch->name, "onStatus"); ch->handler = ngx_rtmp_relay_on_status; + ch = ngx_array_push(&cmcf->amf); + ngx_str_set(&ch->name, "@setDataFrame"); + ch->handler = ngx_rtmp_relay_on_meta_data; + return NGX_OK; }