mirror of
https://github.com/arut/nginx-rtmp-module.git
synced 2025-08-06 15:00:18 +08:00
added AAC support to HLS
This commit is contained in:
7
README
7
README
@ -15,7 +15,7 @@ NGINX-based RTMP server
|
||||
(experimental; Linux only)
|
||||
|
||||
* HLS (HTTP Live Streaming) support
|
||||
(experimental; H264/MP3 only)
|
||||
(experimental; H264/AAC/MP3)
|
||||
|
||||
* HTTP callbacks on publish/play/record
|
||||
|
||||
@ -107,7 +107,7 @@ rtmp {
|
||||
|
||||
application small {
|
||||
live on;
|
||||
# Video with rediced resolution comes here from ffmpeg
|
||||
# Video with reduced resolution comes here from ffmpeg
|
||||
}
|
||||
|
||||
application mypush {
|
||||
@ -180,9 +180,8 @@ rtmp {
|
||||
# for the fragments. The directory contents is served via HTTP (see
|
||||
# http{} section in config)
|
||||
#
|
||||
# Incoming stream must be in H264/MP3. For iPhones use baseline H264
|
||||
# Incoming stream must be in H264/AAC/MP3. For iPhones use baseline H264
|
||||
# profile (see ffmpeg example).
|
||||
#
|
||||
# This example creates RTMP stream from movie ready for HLS:
|
||||
#
|
||||
# ffmpeg -loglevel verbose -re -i movie.avi -vcodec libx264
|
||||
|
@ -206,6 +206,30 @@ ngx_rtmp_hls_get_audio_codec(ngx_int_t cid)
|
||||
}
|
||||
|
||||
|
||||
static size_t
|
||||
ngx_rtmp_hls_chain2buffer(u_char *buffer, size_t size, ngx_chain_t *in,
|
||||
size_t skip)
|
||||
{
|
||||
ngx_buf_t out;
|
||||
|
||||
out.pos = buffer;
|
||||
out.last = buffer + size - FF_INPUT_BUFFER_PADDING_SIZE;
|
||||
|
||||
for (; in; in = in->next) {
|
||||
size = in->buf->last - in->buf->pos;
|
||||
if (size < skip) {
|
||||
skip -= size;
|
||||
continue;
|
||||
}
|
||||
out.pos = ngx_cpymem(out.pos, in->buf->pos + skip, ngx_min(
|
||||
size - skip, (size_t)(out.last - out.pos)));
|
||||
skip = 0;
|
||||
}
|
||||
|
||||
return out.pos - buffer;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_rtmp_hls_init_video(ngx_rtmp_session_t *s)
|
||||
{
|
||||
@ -295,7 +319,7 @@ ngx_rtmp_hls_init_audio(ngx_rtmp_session_t *s)
|
||||
stream->codec->codec_type = AVMEDIA_TYPE_AUDIO;
|
||||
stream->codec->sample_fmt = (codec_ctx->sample_size == 1 ?
|
||||
AV_SAMPLE_FMT_U8 : AV_SAMPLE_FMT_S16);
|
||||
stream->codec->sample_rate = codec_ctx->sample_rate;
|
||||
stream->codec->sample_rate = 48000;/*codec_ctx->sample_rate;*/
|
||||
stream->codec->bit_rate = 128000;
|
||||
stream->codec->channels = codec_ctx->audio_channels;
|
||||
|
||||
@ -419,8 +443,12 @@ static ngx_int_t
|
||||
ngx_rtmp_hls_open_file(ngx_rtmp_session_t *s, u_char *fpath)
|
||||
{
|
||||
ngx_rtmp_hls_ctx_t *ctx;
|
||||
ngx_rtmp_codec_ctx_t *codec_ctx;
|
||||
AVStream *astream;
|
||||
static u_char buffer[NGX_RTMP_HLS_BUFSIZE];
|
||||
|
||||
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module);
|
||||
codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);
|
||||
if (ctx == NULL || ctx->out_format == NULL) {
|
||||
return NGX_OK;
|
||||
}
|
||||
@ -435,6 +463,21 @@ ngx_rtmp_hls_open_file(ngx_rtmp_session_t *s, u_char *fpath)
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
astream = NULL;
|
||||
if (codec_ctx && codec_ctx->audio_codec_id == NGX_RTMP_AUDIO_AAC
|
||||
&& codec_ctx->aac_header && codec_ctx->aac_header->buf->last -
|
||||
codec_ctx->aac_header->buf->pos > 2
|
||||
&& ctx->audio)
|
||||
{
|
||||
astream = ctx->out_format->streams[ctx->out_astream];
|
||||
astream->codec->extradata = buffer;
|
||||
astream->codec->extradata_size = ngx_rtmp_hls_chain2buffer(buffer,
|
||||
sizeof(buffer), codec_ctx->aac_header, 2);
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||
"hls: setting AAC extradata %i bytes",
|
||||
(ngx_int_t)astream->codec->extradata_size);
|
||||
}
|
||||
|
||||
/* write header */
|
||||
if (avformat_write_header(ctx->out_format, NULL) < 0) {
|
||||
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
|
||||
@ -442,6 +485,11 @@ ngx_rtmp_hls_open_file(ngx_rtmp_session_t *s, u_char *fpath)
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (astream) {
|
||||
astream->codec->extradata = NULL;
|
||||
astream->codec->extradata_size = 0;
|
||||
}
|
||||
|
||||
ctx->opened = 1;
|
||||
ctx->nal_bytes = -1;
|
||||
|
||||
@ -802,13 +850,16 @@ ngx_rtmp_hls_audio(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
|
||||
{
|
||||
ngx_rtmp_hls_app_conf_t *hacf;
|
||||
ngx_rtmp_hls_ctx_t *ctx;
|
||||
ngx_rtmp_codec_ctx_t *codec_ctx;
|
||||
AVPacket packet;
|
||||
ngx_buf_t out;
|
||||
static u_char buffer[NGX_RTMP_HLS_BUFSIZE];
|
||||
|
||||
hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module);
|
||||
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module);
|
||||
if (hacf == NULL || !hacf->hls || ctx == NULL || h->mlen < 1) {
|
||||
codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);
|
||||
if (hacf == NULL || !hacf->hls || ctx == NULL || codec_ctx == NULL ||
|
||||
h->mlen < 1)
|
||||
{
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
@ -824,22 +875,26 @@ ngx_rtmp_hls_audio(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
/* copy audio data */
|
||||
out.pos = buffer;
|
||||
out.last = buffer + sizeof(buffer) - FF_INPUT_BUFFER_PADDING_SIZE;
|
||||
|
||||
for (; in; in = in->next) {
|
||||
out.pos = ngx_cpymem(out.pos, in->buf->pos, ngx_min(
|
||||
in->buf->last - in->buf->pos, out.last - out.pos));
|
||||
}
|
||||
|
||||
/* write to file */
|
||||
av_init_packet(&packet);
|
||||
packet.dts = h->timestamp * 90;
|
||||
packet.pts = packet.dts;
|
||||
packet.stream_index = ctx->out_astream;
|
||||
packet.data = buffer + 1;
|
||||
packet.size = out.pos - buffer - 1;
|
||||
packet.data = buffer;
|
||||
packet.size = ngx_rtmp_hls_chain2buffer(buffer, sizeof(buffer), in, 1);
|
||||
|
||||
if (codec_ctx->audio_codec_id == NGX_RTMP_AUDIO_AAC) {
|
||||
if (packet.size == 0) {
|
||||
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
|
||||
"hls: malformed AAC packet");
|
||||
return NGX_OK;
|
||||
}
|
||||
++packet.data;
|
||||
--packet.size;
|
||||
}
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||
"hls: audio buffer %uD", *(uint32_t*)packet.data);
|
||||
|
||||
if (av_interleaved_write_frame(ctx->out_format, &packet) < 0) {
|
||||
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
|
||||
@ -1012,10 +1067,10 @@ ngx_rtmp_hls_create_app_conf(ngx_conf_t *cf)
|
||||
static char *
|
||||
ngx_rtmp_hls_merge_app_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
{
|
||||
ngx_rtmp_hls_app_conf_t *prev = parent;
|
||||
ngx_rtmp_hls_app_conf_t *conf = child;
|
||||
ngx_rtmp_hls_app_conf_t *prev = parent;
|
||||
ngx_rtmp_hls_app_conf_t *conf = 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->playlen, prev->playlen, 30000);
|
||||
ngx_conf_merge_str_value(conf->path, prev->path, "");
|
||||
@ -1028,7 +1083,7 @@ ngx_rtmp_hls_merge_app_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
conf->nfrags = conf->playlen / conf->fraglen;
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -1059,6 +1114,6 @@ ngx_rtmp_hls_postconfiguration(ngx_conf_t *cf)
|
||||
ngx_rtmp_hls_log = &cf->cycle->new_log;
|
||||
av_log_set_callback(ngx_rtmp_hls_av_log_callback);
|
||||
|
||||
return NGX_OK;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user