mirror of
https://github.com/arut/nginx-rtmp-module.git
synced 2025-08-06 15:00:18 +08:00
fixed choppy audio in HLS: added hls_muxdelay directive
This commit is contained in:
@ -58,6 +58,7 @@ typedef struct {
|
|||||||
unsigned opened:1;
|
unsigned opened:1;
|
||||||
unsigned audio:1;
|
unsigned audio:1;
|
||||||
unsigned video:1;
|
unsigned video:1;
|
||||||
|
unsigned header_sent:1;
|
||||||
|
|
||||||
ngx_str_t playlist;
|
ngx_str_t playlist;
|
||||||
ngx_str_t playlist_bak;
|
ngx_str_t playlist_bak;
|
||||||
@ -78,6 +79,7 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
ngx_flag_t hls;
|
ngx_flag_t hls;
|
||||||
ngx_msec_t fraglen;
|
ngx_msec_t fraglen;
|
||||||
|
ngx_msec_t muxdelay;
|
||||||
ngx_msec_t playlen;
|
ngx_msec_t playlen;
|
||||||
size_t nfrags;
|
size_t nfrags;
|
||||||
ngx_rtmp_hls_ctx_t **ctx;
|
ngx_rtmp_hls_ctx_t **ctx;
|
||||||
@ -116,6 +118,14 @@ static ngx_command_t ngx_rtmp_hls_commands[] = {
|
|||||||
offsetof(ngx_rtmp_hls_app_conf_t, playlen),
|
offsetof(ngx_rtmp_hls_app_conf_t, playlen),
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
|
{ ngx_string("hls_muxdelay"),
|
||||||
|
NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
|
||||||
|
ngx_conf_set_msec_slot,
|
||||||
|
NGX_RTMP_APP_CONF_OFFSET,
|
||||||
|
offsetof(ngx_rtmp_hls_app_conf_t, muxdelay),
|
||||||
|
NULL },
|
||||||
|
|
||||||
|
|
||||||
ngx_null_command
|
ngx_null_command
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -262,7 +272,7 @@ ngx_rtmp_hls_init_video(ngx_rtmp_session_t *s)
|
|||||||
stream->codec->codec_id = CODEC_ID_H264;
|
stream->codec->codec_id = CODEC_ID_H264;
|
||||||
stream->codec->codec_type = AVMEDIA_TYPE_VIDEO;
|
stream->codec->codec_type = AVMEDIA_TYPE_VIDEO;
|
||||||
stream->codec->pix_fmt = PIX_FMT_YUV420P;
|
stream->codec->pix_fmt = PIX_FMT_YUV420P;
|
||||||
stream->codec->time_base.den = 1;
|
stream->codec->time_base.den = 25;
|
||||||
stream->codec->time_base.num = 1;
|
stream->codec->time_base.num = 1;
|
||||||
stream->codec->width = 100;
|
stream->codec->width = 100;
|
||||||
stream->codec->height = 100;
|
stream->codec->height = 100;
|
||||||
@ -316,7 +326,7 @@ ngx_rtmp_hls_init_audio(ngx_rtmp_session_t *s)
|
|||||||
stream->codec->sample_fmt = (codec_ctx->sample_size == 1 ?
|
stream->codec->sample_fmt = (codec_ctx->sample_size == 1 ?
|
||||||
AV_SAMPLE_FMT_U8 : AV_SAMPLE_FMT_S16);
|
AV_SAMPLE_FMT_U8 : AV_SAMPLE_FMT_S16);
|
||||||
stream->codec->sample_rate = 48000;/*codec_ctx->sample_rate;*/
|
stream->codec->sample_rate = 48000;/*codec_ctx->sample_rate;*/
|
||||||
stream->codec->bit_rate = 128000;
|
stream->codec->bit_rate = 2000000;
|
||||||
stream->codec->channels = codec_ctx->audio_channels;
|
stream->codec->channels = codec_ctx->audio_channels;
|
||||||
|
|
||||||
ctx->out_astream = stream->index;
|
ctx->out_astream = stream->index;
|
||||||
@ -406,8 +416,10 @@ static ngx_int_t
|
|||||||
ngx_rtmp_hls_initialize(ngx_rtmp_session_t *s)
|
ngx_rtmp_hls_initialize(ngx_rtmp_session_t *s)
|
||||||
{
|
{
|
||||||
ngx_rtmp_hls_ctx_t *ctx;
|
ngx_rtmp_hls_ctx_t *ctx;
|
||||||
|
ngx_rtmp_hls_app_conf_t *hacf;
|
||||||
AVOutputFormat *format;
|
AVOutputFormat *format;
|
||||||
|
|
||||||
|
hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module);
|
||||||
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module);
|
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module);
|
||||||
if (ctx == NULL || ctx->out_format || ctx->publishing == 0) {
|
if (ctx == NULL || ctx->out_format || ctx->publishing == 0) {
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
@ -430,6 +442,7 @@ ngx_rtmp_hls_initialize(ngx_rtmp_session_t *s)
|
|||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
ctx->out_format->oformat = format;
|
ctx->out_format->oformat = format;
|
||||||
|
ctx->out_format->max_delay = (int64_t)hacf->muxdelay * AV_TIME_BASE / 1000;
|
||||||
|
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
@ -449,6 +462,10 @@ ngx_rtmp_hls_open_file(ngx_rtmp_session_t *s, u_char *fpath)
|
|||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!ctx->video || !ctx->audio) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||||
"hls: open stream file '%s'", fpath);
|
"hls: open stream file '%s'", fpath);
|
||||||
|
|
||||||
@ -475,11 +492,14 @@ ngx_rtmp_hls_open_file(ngx_rtmp_session_t *s, u_char *fpath)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* write header */
|
/* write header */
|
||||||
if (avformat_write_header(ctx->out_format, NULL) < 0) {
|
if (!ctx->header_sent &&
|
||||||
|
avformat_write_header(ctx->out_format, NULL) < 0)
|
||||||
|
{
|
||||||
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
|
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
|
||||||
"hls: avformat_write_header failed");
|
"hls: avformat_write_header failed");
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
ctx->header_sent = 1;
|
||||||
|
|
||||||
if (astream) {
|
if (astream) {
|
||||||
astream->codec->extradata = NULL;
|
astream->codec->extradata = NULL;
|
||||||
@ -651,10 +671,11 @@ ngx_rtmp_hls_close_file(ngx_rtmp_session_t *s)
|
|||||||
|
|
||||||
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module);
|
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module);
|
||||||
|
|
||||||
|
/*
|
||||||
if (av_write_trailer(ctx->out_format) < 0) {
|
if (av_write_trailer(ctx->out_format) < 0) {
|
||||||
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
|
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
|
||||||
"hls: av_write_trailer failed");
|
"hls: av_write_trailer failed");
|
||||||
}
|
}*/
|
||||||
|
|
||||||
avio_flush(ctx->out_format->pb);
|
avio_flush(ctx->out_format->pb);
|
||||||
|
|
||||||
@ -1028,10 +1049,11 @@ ngx_rtmp_hls_video(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
|
|||||||
packet.dts = h->timestamp * 90L;
|
packet.dts = h->timestamp * 90L;
|
||||||
packet.pts = packet.dts + cts * 90;
|
packet.pts = packet.dts + cts * 90;
|
||||||
packet.stream_index = ctx->out_vstream;
|
packet.stream_index = ctx->out_vstream;
|
||||||
/*
|
|
||||||
if (ftype == 1) {
|
if (ftype == 1) {
|
||||||
packet.flags |= AV_PKT_FLAG_KEY;
|
packet.flags |= AV_PKT_FLAG_KEY;
|
||||||
}*/
|
}
|
||||||
|
|
||||||
packet.data = buffer;
|
packet.data = buffer;
|
||||||
packet.size = out.pos - buffer;
|
packet.size = out.pos - buffer;
|
||||||
|
|
||||||
@ -1056,6 +1078,7 @@ ngx_rtmp_hls_create_app_conf(ngx_conf_t *cf)
|
|||||||
|
|
||||||
conf->hls = NGX_CONF_UNSET;
|
conf->hls = NGX_CONF_UNSET;
|
||||||
conf->fraglen = NGX_CONF_UNSET;
|
conf->fraglen = NGX_CONF_UNSET;
|
||||||
|
conf->muxdelay = NGX_CONF_UNSET;
|
||||||
conf->playlen = NGX_CONF_UNSET;
|
conf->playlen = NGX_CONF_UNSET;
|
||||||
conf->nbuckets = 1024;
|
conf->nbuckets = 1024;
|
||||||
|
|
||||||
@ -1071,6 +1094,7 @@ ngx_rtmp_hls_merge_app_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
|
|
||||||
ngx_conf_merge_value(conf->hls, prev->hls, 0);
|
ngx_conf_merge_value(conf->hls, prev->hls, 0);
|
||||||
ngx_conf_merge_msec_value(conf->fraglen, prev->fraglen, 5000);
|
ngx_conf_merge_msec_value(conf->fraglen, prev->fraglen, 5000);
|
||||||
|
ngx_conf_merge_msec_value(conf->muxdelay, prev->muxdelay, 700);
|
||||||
ngx_conf_merge_msec_value(conf->playlen, prev->playlen, 30000);
|
ngx_conf_merge_msec_value(conf->playlen, prev->playlen, 30000);
|
||||||
ngx_conf_merge_str_value(conf->path, prev->path, "");
|
ngx_conf_merge_str_value(conf->path, prev->path, "");
|
||||||
conf->ctx = ngx_pcalloc(cf->pool,
|
conf->ctx = ngx_pcalloc(cf->pool,
|
||||||
|
Reference in New Issue
Block a user