mirror of
https://github.com/zotanmew/nginx-rtmp-module.git
synced 2024-05-09 22:11:08 +02:00
It's possible that we'll receive NetStream.Publish.Start _before_ the codec
module has parsed the meta data. To handle that case, we'll also try to call @setDataFrame when we receive the @setDataFrame from the publisher.
This commit is contained in:
parent
2a54c8e089
commit
1d21d68c3c
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue