Skip to content

Commit 53e68df

Browse files
committed
added AUD NALs & fixed SPS/PPS
1 parent e916ca9 commit 53e68df

File tree

1 file changed

+121
-64
lines changed

1 file changed

+121
-64
lines changed

hls/ngx_rtmp_hls_module.c

Lines changed: 121 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,6 @@ typedef struct {
4545

4646
int64_t aframe_base;
4747
int64_t aframe_num;
48-
49-
int8_t nal_bytes;
5048
} ngx_rtmp_hls_ctx_t;
5149

5250

@@ -314,7 +312,22 @@ ngx_rtmp_hls_copy(ngx_rtmp_session_t *s, void *dst, u_char **src, size_t n,
314312

315313

316314
static ngx_int_t
317-
ngx_rtmp_hls_append_avc_header(ngx_rtmp_session_t *s, ngx_buf_t *out)
315+
ngx_rtmp_hls_append_aud(ngx_rtmp_session_t *s, ngx_buf_t *out)
316+
{
317+
static u_char aud_nal[] = { 0x00, 0x00, 0x00, 0x01, 0x09, 0xf0 };
318+
319+
if (out->last + sizeof(aud_nal) > out->end) {
320+
return NGX_ERROR;
321+
}
322+
323+
out->last = ngx_cpymem(out->last, aud_nal, sizeof(aud_nal));
324+
325+
return NGX_OK;
326+
}
327+
328+
329+
static ngx_int_t
330+
ngx_rtmp_hls_append_sps_pps(ngx_rtmp_session_t *s, ngx_buf_t *out)
318331
{
319332
ngx_rtmp_codec_ctx_t *codec_ctx;
320333
u_char *p;
@@ -352,22 +365,10 @@ ngx_rtmp_hls_append_avc_header(ngx_rtmp_session_t *s, ngx_buf_t *out)
352365
* - level
353366
*/
354367

355-
if (ngx_rtmp_hls_copy(s, NULL, &p, 9, &in) != NGX_OK) {
356-
return NGX_ERROR;
357-
}
358-
359-
/* NAL size length (1,2,4) */
360-
if (ngx_rtmp_hls_copy(s, &ctx->nal_bytes, &p, 1, &in) != NGX_OK) {
368+
if (ngx_rtmp_hls_copy(s, NULL, &p, 10, &in) != NGX_OK) {
361369
return NGX_ERROR;
362370
}
363371

364-
ctx->nal_bytes &= 0x03; /* 2 lsb */
365-
366-
++ctx->nal_bytes;
367-
368-
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
369-
"h264: NAL size bytes: %uz", ctx->nal_bytes);
370-
371372
/* number of SPS NALs */
372373
if (ngx_rtmp_hls_copy(s, &nnals, &p, 1, &in) != NGX_OK) {
373374
return NGX_ERROR;
@@ -393,29 +394,29 @@ ngx_rtmp_hls_append_avc_header(ngx_rtmp_session_t *s, ngx_buf_t *out)
393394
"h264: header NAL length: %uz", (size_t) len);
394395

395396
/* AnnexB prefix */
396-
if (out->last - out->pos < 4) {
397+
if (out->end - out->last < 4) {
397398
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
398399
"h264: too small buffer for header NAL size");
399400
return NGX_ERROR;
400401
}
401402

402-
*out->pos++ = 0;
403-
*out->pos++ = 0;
404-
*out->pos++ = 0;
405-
*out->pos++ = 1;
403+
*out->last++ = 0;
404+
*out->last++ = 0;
405+
*out->last++ = 0;
406+
*out->last++ = 1;
406407

407408
/* NAL body */
408-
if (out->last - out->pos < len) {
409+
if (out->end - out->last < len) {
409410
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
410411
"h264: too small buffer for header NAL");
411412
return NGX_ERROR;
412413
}
413414

414-
if (ngx_rtmp_hls_copy(s, out->pos, &p, len, &in) != NGX_OK) {
415+
if (ngx_rtmp_hls_copy(s, out->last, &p, len, &in) != NGX_OK) {
415416
return NGX_ERROR;
416417
}
417418

418-
out->pos += len;
419+
out->last += len;
419420
}
420421

421422
if (n == 1) {
@@ -871,6 +872,40 @@ ngx_rtmp_hls_audio(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
871872
}
872873

873874

875+
static ngx_int_t
876+
ngx_rtmp_hls_get_nal_bytes(ngx_rtmp_session_t *s)
877+
{
878+
ngx_rtmp_codec_ctx_t *codec_ctx;
879+
ngx_chain_t *cl;
880+
u_char *p;
881+
uint8_t nal_bytes;
882+
883+
codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);
884+
885+
cl = codec_ctx->avc_header;
886+
887+
p = cl->buf->pos;
888+
889+
if (ngx_rtmp_hls_copy(s, NULL, &p, 9, &cl) != NGX_OK) {
890+
return NGX_ERROR;
891+
}
892+
893+
/* NAL size length (1,2,4) */
894+
if (ngx_rtmp_hls_copy(s, &nal_bytes, &p, 1, &cl) != NGX_OK) {
895+
return NGX_ERROR;
896+
}
897+
898+
nal_bytes &= 0x03; /* 2 lsb */
899+
900+
++nal_bytes;
901+
902+
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
903+
"hls: NAL bytes: %ui", (ngx_uint_t) nal_bytes);
904+
905+
return nal_bytes;
906+
}
907+
908+
874909
static ngx_int_t
875910
ngx_rtmp_hls_video(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
876911
ngx_chain_t *in)
@@ -884,6 +919,8 @@ ngx_rtmp_hls_video(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
884919
ngx_buf_t out;
885920
int32_t cts;
886921
ngx_rtmp_mpegts_frame_t frame;
922+
ngx_uint_t nal_type, nal_bytes;
923+
ngx_int_t aud_sent, sps_pps_sent, rc;
887924
static u_char buffer[NGX_RTMP_HLS_BUFSIZE];
888925

889926
hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module);
@@ -892,8 +929,8 @@ ngx_rtmp_hls_video(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
892929

893930
codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);
894931

895-
if (hacf == NULL || !hacf->hls || ctx == NULL ||
896-
codec_ctx == NULL || h->mlen < 1)
932+
if (hacf == NULL || !hacf->hls || ctx == NULL || codec_ctx == NULL ||
933+
h->mlen < 1)
897934
{
898935
return NGX_OK;
899936
}
@@ -937,89 +974,109 @@ ngx_rtmp_hls_video(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
937974

938975
ngx_memzero(&out, sizeof(out));
939976

940-
out.pos = buffer;
941-
out.last = buffer + sizeof(buffer);
977+
out.start = buffer;
978+
out.end = buffer + sizeof(buffer);
979+
out.pos = out.start;
980+
out.last = out.pos;
942981

943-
/* keyframe? */
944-
945-
if (ftype == 1) {
946-
if (ngx_current_msec - ctx->frag_start > hacf->fraglen) {
947-
ngx_rtmp_hls_restart(s);
948-
}
949-
950-
/* Prepend IDR frame with H264 header for random seeks */
951-
952-
if (ngx_rtmp_hls_append_avc_header(s, &out) != NGX_OK) {
953-
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
954-
"hls: error appenging H264 header");
955-
}
982+
if (ftype == 1 && ngx_current_msec - ctx->frag_start > hacf->fraglen) {
983+
ngx_rtmp_hls_restart(s);
956984
}
957985

958986
if (!ctx->opened || codec_ctx->avc_header == NULL) {
959987
return NGX_OK;
960988
}
961989

962-
if (ctx->nal_bytes == 0) {
963-
ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
964-
"hls: nal length size is unknown, "
965-
"waiting for IDR to parse header");
990+
rc = ngx_rtmp_hls_get_nal_bytes(s);
991+
if (rc < 0) {
992+
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
993+
"hls: failed to parse NAL bytes");
966994
return NGX_OK;
967995
}
968996

997+
nal_bytes = rc;
998+
aud_sent = 0;
999+
sps_pps_sent = 0;
1000+
9691001
while (in) {
9701002

971-
llen = ctx->nal_bytes;
1003+
llen = nal_bytes;
9721004
if (ngx_rtmp_hls_copy(s, &rlen, &p, llen, &in) != NGX_OK) {
9731005
return NGX_OK;
9741006
}
9751007

9761008
len = 0;
9771009
ngx_rtmp_rmemcpy(&len, &rlen, llen);
9781010

1011+
nal_type = *p & 0x1f;
1012+
9791013
ngx_log_debug4(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
980-
"hls: h264 NAL type=%i llen=%i len=%uD unit_type=%i",
981-
(ngx_int_t) ftype, (ngx_int_t) llen, len,
982-
(ngx_int_t) (*p & 0x1f));
1014+
"hls: h264 NAL type=%i llen=%i len=%uD unit_type=%ui",
1015+
(ngx_int_t) ftype, (ngx_int_t) llen, len, nal_type);
1016+
1017+
if (!aud_sent) {
1018+
switch (nal_type) {
1019+
case 1:
1020+
case 5:
1021+
if (ngx_rtmp_hls_append_aud(s, &out) != NGX_OK) {
1022+
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
1023+
"hls: error appending AUD NAL");
1024+
}
1025+
case 9:
1026+
aud_sent = 1;
1027+
break;
1028+
}
1029+
}
1030+
1031+
switch (nal_type) {
1032+
case 1:
1033+
sps_pps_sent = 0;
1034+
break;
1035+
case 5:
1036+
if (sps_pps_sent) {
1037+
break;
1038+
}
1039+
if (ngx_rtmp_hls_append_sps_pps(s, &out) != NGX_OK) {
1040+
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
1041+
"hls: error appenging SPS/PPS NALs");
1042+
}
1043+
sps_pps_sent = 1;
1044+
break;
1045+
}
9831046

9841047
/* AnnexB prefix */
9851048

986-
if (out.last - out.pos < 4) {
1049+
if (out.end - out.last < 4) {
9871050
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
9881051
"hls: not enough buffer for AnnexB prefix");
9891052
return NGX_OK;
9901053
}
9911054

992-
/*TODO: add AUD NAL*/
993-
9941055
/* first AnnexB prefix is long (4 bytes) */
9951056

996-
if (out.pos == buffer) {
997-
*out.pos++ = 0;
1057+
if (out.last == out.pos) {
1058+
*out.last++ = 0;
9981059
}
9991060

1000-
*out.pos++ = 0;
1001-
*out.pos++ = 0;
1002-
*out.pos++ = 1;
1061+
*out.last++ = 0;
1062+
*out.last++ = 0;
1063+
*out.last++ = 1;
10031064

10041065
/* NAL body */
10051066

1006-
if (out.last - out.pos < (ngx_int_t) len) {
1067+
if (out.end - out.last < (ngx_int_t) len) {
10071068
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
10081069
"hls: not enough buffer for NAL");
10091070
return NGX_OK;
10101071
}
10111072

1012-
if (ngx_rtmp_hls_copy(s, out.pos, &p, len, &in) != NGX_OK) {
1073+
if (ngx_rtmp_hls_copy(s, out.last, &p, len, &in) != NGX_OK) {
10131074
return NGX_ERROR;
10141075
}
10151076

1016-
out.pos += len;
1077+
out.last += len;
10171078
}
10181079

1019-
/*TODO*/
1020-
out.last = out.pos;
1021-
out.pos = buffer;
1022-
10231080
ngx_memzero(&frame, sizeof(frame));
10241081

10251082
frame.cc = ctx->video_cc;

0 commit comments

Comments
 (0)