Backport support MP3 for HLS from abandoned pull request

This commit is contained in:
Sergey Dryabzhinsky 2015-07-03 01:03:39 +03:00
parent f62a083806
commit 8341644121
3 changed files with 87 additions and 41 deletions

View file

@ -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;
}

View file

@ -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);

View file

@ -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);