mirror of
https://github.com/zotanmew/nginx-rtmp-module.git
synced 2024-05-17 00:51:09 +02:00
Backport support MP3 for HLS from abandoned pull request
This commit is contained in:
parent
f62a083806
commit
8341644121
|
@ -848,6 +848,7 @@ ngx_rtmp_hls_open_fragment(ngx_rtmp_session_t *s, uint64_t ts,
|
|||
ngx_fd_t fd;
|
||||
ngx_uint_t g;
|
||||
ngx_rtmp_hls_ctx_t *ctx;
|
||||
ngx_rtmp_codec_ctx_t *codec_ctx;
|
||||
ngx_rtmp_hls_frag_t *f;
|
||||
ngx_rtmp_hls_app_conf_t *hacf;
|
||||
|
||||
|
@ -943,8 +944,10 @@ ngx_rtmp_hls_open_fragment(ngx_rtmp_session_t *s, uint64_t ts,
|
|||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);
|
||||
|
||||
if (ngx_rtmp_mpegts_open_file(&ctx->file, ctx->stream.data,
|
||||
s->connection->log)
|
||||
s->connection->log, &codec_ctx->audio_codec_id)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
|
@ -1687,7 +1690,7 @@ ngx_rtmp_hls_audio(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
|
|||
size_t bsize;
|
||||
ngx_buf_t *b;
|
||||
u_char *p;
|
||||
ngx_uint_t objtype, srindex, chconf, size;
|
||||
ngx_uint_t objtype, srindex, chconf, size, samples_per_frame;
|
||||
|
||||
hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module);
|
||||
|
||||
|
@ -1701,8 +1704,14 @@ ngx_rtmp_hls_audio(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
|
|||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (codec_ctx->audio_codec_id != NGX_RTMP_AUDIO_AAC ||
|
||||
codec_ctx->aac_header == NULL || ngx_rtmp_is_codec_header(in))
|
||||
if (codec_ctx->audio_codec_id != NGX_RTMP_AUDIO_AAC &&
|
||||
codec_ctx->audio_codec_id != NGX_RTMP_AUDIO_MP3)
|
||||
{
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if ((codec_ctx->audio_codec_id == NGX_RTMP_AUDIO_AAC &&
|
||||
codec_ctx->aac_header == NULL) || ngx_rtmp_is_codec_header(in))
|
||||
{
|
||||
return NGX_OK;
|
||||
}
|
||||
|
@ -1727,7 +1736,7 @@ ngx_rtmp_hls_audio(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
|
|||
b->pos = b->last = b->start;
|
||||
}
|
||||
|
||||
size = h->mlen - 2 + 7;
|
||||
size = codec_ctx->audio_codec_id == NGX_RTMP_AUDIO_MP3 ? h->mlen - 1 : h->mlen - 2 + 7;
|
||||
pts = (uint64_t) h->timestamp * 90;
|
||||
|
||||
if (b->start + size > b->end) {
|
||||
|
@ -1751,14 +1760,22 @@ ngx_rtmp_hls_audio(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
|
|||
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||
"hls: audio pts=%uL", pts);
|
||||
|
||||
if (b->last + 7 > b->end) {
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||
"hls: not enough buffer for audio header");
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
p = b->last;
|
||||
b->last += 5;
|
||||
if (codec_ctx->audio_codec_id == NGX_RTMP_AUDIO_AAC) {
|
||||
if (b->last + 7 > b->end) {
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||
"hls: not enough buffer for audio header");
|
||||
return NGX_OK;
|
||||
}
|
||||
b->last += 5;
|
||||
}
|
||||
else {
|
||||
/* For some reason the pointer is already incremented past the rest
|
||||
of the RTMP frame header. I'm not sure where in the code this is
|
||||
being done. Regardless, there's an extra byte that needs to be skipped
|
||||
for MP3. */
|
||||
in->buf->pos += 1;
|
||||
}
|
||||
|
||||
/* copy payload */
|
||||
|
||||
|
@ -1774,28 +1791,30 @@ ngx_rtmp_hls_audio(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
|
|||
|
||||
/* make up ADTS header */
|
||||
|
||||
if (ngx_rtmp_hls_parse_aac_header(s, &objtype, &srindex, &chconf)
|
||||
!= NGX_OK)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
|
||||
"hls: aac header error");
|
||||
return NGX_OK;
|
||||
}
|
||||
if (codec_ctx->audio_codec_id == NGX_RTMP_AUDIO_AAC) {
|
||||
if (ngx_rtmp_hls_parse_aac_header(s, &objtype, &srindex, &chconf)
|
||||
!= NGX_OK)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
|
||||
"hls: aac header error");
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
/* we have 5 free bytes + 2 bytes of RTMP frame header */
|
||||
/* we have 5 free bytes + 2 bytes of RTMP frame header */
|
||||
|
||||
p[0] = 0xff;
|
||||
p[1] = 0xf1;
|
||||
p[2] = (u_char) (((objtype - 1) << 6) | (srindex << 2) |
|
||||
((chconf & 0x04) >> 2));
|
||||
p[3] = (u_char) (((chconf & 0x03) << 6) | ((size >> 11) & 0x03));
|
||||
p[4] = (u_char) (size >> 3);
|
||||
p[5] = (u_char) ((size << 5) | 0x1f);
|
||||
p[6] = 0xfc;
|
||||
p[0] = 0xff;
|
||||
p[1] = 0xf1;
|
||||
p[2] = (u_char) (((objtype - 1) << 6) | (srindex << 2) |
|
||||
((chconf & 0x04) >> 2));
|
||||
p[3] = (u_char) (((chconf & 0x03) << 6) | ((size >> 11) & 0x03));
|
||||
p[4] = (u_char) (size >> 3);
|
||||
p[5] = (u_char) ((size << 5) | 0x1f);
|
||||
p[6] = 0xfc;
|
||||
|
||||
if (p != b->start) {
|
||||
ctx->aframe_num++;
|
||||
return NGX_OK;
|
||||
if (p != b->start) {
|
||||
ctx->aframe_num++;
|
||||
return NGX_OK;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->aframe_pts = pts;
|
||||
|
@ -1809,7 +1828,9 @@ ngx_rtmp_hls_audio(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
|
|||
/* TODO: We assume here AAC frame size is 1024
|
||||
* Need to handle AAC frames with frame size of 960 */
|
||||
|
||||
est_pts = ctx->aframe_base + ctx->aframe_num * 90000 * 1024 /
|
||||
samples_per_frame = codec_ctx->audio_codec_id == NGX_RTMP_AUDIO_AAC ? 1024 : 1152;
|
||||
|
||||
est_pts = ctx->aframe_base + ctx->aframe_num * 90000 * samples_per_frame /
|
||||
codec_ctx->sample_rate;
|
||||
dpts = (int64_t) (est_pts - pts);
|
||||
|
||||
|
@ -1822,6 +1843,10 @@ ngx_rtmp_hls_audio(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
|
|||
{
|
||||
ctx->aframe_num++;
|
||||
ctx->aframe_pts = est_pts;
|
||||
|
||||
if (codec_ctx->audio_codec_id == NGX_RTMP_AUDIO_MP3) {
|
||||
ngx_rtmp_hls_flush_audio(s);
|
||||
}
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <ngx_core.h>
|
||||
#include "ngx_rtmp_mpegts.h"
|
||||
|
||||
#include "ngx_rtmp_codec_module.h"
|
||||
|
||||
static u_char ngx_rtmp_mpegts_header[] = {
|
||||
|
||||
|
@ -46,11 +47,9 @@ static u_char ngx_rtmp_mpegts_header[] = {
|
|||
0xe1, 0x00,
|
||||
0xf0, 0x00,
|
||||
0x1b, 0xe1, 0x00, 0xf0, 0x00, /* h264 */
|
||||
0x0f, 0xe1, 0x01, 0xf0, 0x00, /* aac */
|
||||
/*0x03, 0xe1, 0x01, 0xf0, 0x00,*/ /* mp3 */
|
||||
/* CRC */
|
||||
0x2f, 0x44, 0xb9, 0x9b, /* crc for aac */
|
||||
/*0x4e, 0x59, 0x3d, 0x1e,*/ /* crc for mp3 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, /* audio placeholder */
|
||||
0x00, 0x00, 0x00, 0x00, /* audio crc placeholder */
|
||||
|
||||
/* stuffing 157 bytes */
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
|
@ -70,6 +69,17 @@ static u_char ngx_rtmp_mpegts_header[] = {
|
|||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
};
|
||||
|
||||
static u_char ngx_rtmp_mpegts_header_mp3[] = {
|
||||
0x03, 0xe1, 0x01, 0xf0, 0x00, /* mp3 */
|
||||
/* CRC */
|
||||
0xd7, 0x86, 0x44, 0x5c, /* crc for mp3 */
|
||||
};
|
||||
|
||||
static u_char ngx_rtmp_mpegts_header_aac[] = {
|
||||
0x0f, 0xe1, 0x01, 0xf0, 0x00, /* aac */
|
||||
/* CRC */
|
||||
0x2f, 0x44, 0xb9, 0x9b, /* crc for aac */
|
||||
};
|
||||
|
||||
/* 700 ms PCR delay */
|
||||
#define NGX_RTMP_HLS_DELAY 63000
|
||||
|
@ -155,8 +165,19 @@ ngx_rtmp_mpegts_write_file(ngx_rtmp_mpegts_file_t *file, u_char *in,
|
|||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_rtmp_mpegts_write_header(ngx_rtmp_mpegts_file_t *file)
|
||||
ngx_rtmp_mpegts_write_header(ngx_rtmp_mpegts_file_t *file, ngx_uint_t *audio_codec_id)
|
||||
{
|
||||
|
||||
if (*audio_codec_id == NGX_RTMP_AUDIO_AAC) {
|
||||
ngx_memcpy(ngx_rtmp_mpegts_header+210, ngx_rtmp_mpegts_header_aac,
|
||||
sizeof(ngx_rtmp_mpegts_header_aac));
|
||||
}
|
||||
//if (*audio_codec_id == NGX_RTMP_AUDIO_MP3) {
|
||||
else {
|
||||
ngx_memcpy(ngx_rtmp_mpegts_header+210, ngx_rtmp_mpegts_header_mp3,
|
||||
sizeof(ngx_rtmp_mpegts_header_mp3));
|
||||
}
|
||||
|
||||
return ngx_rtmp_mpegts_write_file(file, ngx_rtmp_mpegts_header,
|
||||
sizeof(ngx_rtmp_mpegts_header));
|
||||
}
|
||||
|
@ -350,7 +371,7 @@ ngx_rtmp_mpegts_init_encryption(ngx_rtmp_mpegts_file_t *file,
|
|||
|
||||
ngx_int_t
|
||||
ngx_rtmp_mpegts_open_file(ngx_rtmp_mpegts_file_t *file, u_char *path,
|
||||
ngx_log_t *log)
|
||||
ngx_log_t *log, ngx_uint_t *audio_codec_id)
|
||||
{
|
||||
file->log = log;
|
||||
|
||||
|
@ -365,7 +386,7 @@ ngx_rtmp_mpegts_open_file(ngx_rtmp_mpegts_file_t *file, u_char *path,
|
|||
|
||||
file->size = 0;
|
||||
|
||||
if (ngx_rtmp_mpegts_write_header(file) != NGX_OK) {
|
||||
if (ngx_rtmp_mpegts_write_header(file, audio_codec_id) != NGX_OK) {
|
||||
ngx_log_error(NGX_LOG_ERR, log, ngx_errno,
|
||||
"hls: error writing fragment header");
|
||||
ngx_close_file(file->fd);
|
||||
|
|
|
@ -37,7 +37,7 @@ typedef struct {
|
|||
ngx_int_t ngx_rtmp_mpegts_init_encryption(ngx_rtmp_mpegts_file_t *file,
|
||||
u_char *key, size_t key_len, uint64_t iv);
|
||||
ngx_int_t ngx_rtmp_mpegts_open_file(ngx_rtmp_mpegts_file_t *file, u_char *path,
|
||||
ngx_log_t *log);
|
||||
ngx_log_t *log, ngx_uint_t *audio_codec_id);
|
||||
ngx_int_t ngx_rtmp_mpegts_close_file(ngx_rtmp_mpegts_file_t *file);
|
||||
ngx_int_t ngx_rtmp_mpegts_write_frame(ngx_rtmp_mpegts_file_t *file,
|
||||
ngx_rtmp_mpegts_frame_t *f, ngx_buf_t *b);
|
||||
|
|
Loading…
Reference in a new issue