@@ -45,8 +45,6 @@ typedef struct {
45
45
46
46
int64_t aframe_base ;
47
47
int64_t aframe_num ;
48
-
49
- int8_t nal_bytes ;
50
48
} ngx_rtmp_hls_ctx_t ;
51
49
52
50
@@ -314,7 +312,22 @@ ngx_rtmp_hls_copy(ngx_rtmp_session_t *s, void *dst, u_char **src, size_t n,
314
312
315
313
316
314
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 )
318
331
{
319
332
ngx_rtmp_codec_ctx_t * codec_ctx ;
320
333
u_char * p ;
@@ -352,22 +365,10 @@ ngx_rtmp_hls_append_avc_header(ngx_rtmp_session_t *s, ngx_buf_t *out)
352
365
* - level
353
366
*/
354
367
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 ) {
361
369
return NGX_ERROR ;
362
370
}
363
371
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
-
371
372
/* number of SPS NALs */
372
373
if (ngx_rtmp_hls_copy (s , & nnals , & p , 1 , & in ) != NGX_OK ) {
373
374
return NGX_ERROR ;
@@ -393,29 +394,29 @@ ngx_rtmp_hls_append_avc_header(ngx_rtmp_session_t *s, ngx_buf_t *out)
393
394
"h264: header NAL length: %uz" , (size_t ) len );
394
395
395
396
/* AnnexB prefix */
396
- if (out -> last - out -> pos < 4 ) {
397
+ if (out -> end - out -> last < 4 ) {
397
398
ngx_log_error (NGX_LOG_ERR , s -> connection -> log , 0 ,
398
399
"h264: too small buffer for header NAL size" );
399
400
return NGX_ERROR ;
400
401
}
401
402
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 ;
406
407
407
408
/* NAL body */
408
- if (out -> last - out -> pos < len ) {
409
+ if (out -> end - out -> last < len ) {
409
410
ngx_log_error (NGX_LOG_ERR , s -> connection -> log , 0 ,
410
411
"h264: too small buffer for header NAL" );
411
412
return NGX_ERROR ;
412
413
}
413
414
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 ) {
415
416
return NGX_ERROR ;
416
417
}
417
418
418
- out -> pos += len ;
419
+ out -> last += len ;
419
420
}
420
421
421
422
if (n == 1 ) {
@@ -871,6 +872,40 @@ ngx_rtmp_hls_audio(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
871
872
}
872
873
873
874
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
+
874
909
static ngx_int_t
875
910
ngx_rtmp_hls_video (ngx_rtmp_session_t * s , ngx_rtmp_header_t * h ,
876
911
ngx_chain_t * in )
@@ -884,6 +919,8 @@ ngx_rtmp_hls_video(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
884
919
ngx_buf_t out ;
885
920
int32_t cts ;
886
921
ngx_rtmp_mpegts_frame_t frame ;
922
+ ngx_uint_t nal_type , nal_bytes ;
923
+ ngx_int_t aud_sent , sps_pps_sent , rc ;
887
924
static u_char buffer [NGX_RTMP_HLS_BUFSIZE ];
888
925
889
926
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,
892
929
893
930
codec_ctx = ngx_rtmp_get_module_ctx (s , ngx_rtmp_codec_module );
894
931
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 )
897
934
{
898
935
return NGX_OK ;
899
936
}
@@ -937,89 +974,109 @@ ngx_rtmp_hls_video(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
937
974
938
975
ngx_memzero (& out , sizeof (out ));
939
976
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 ;
942
981
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 );
956
984
}
957
985
958
986
if (!ctx -> opened || codec_ctx -> avc_header == NULL ) {
959
987
return NGX_OK ;
960
988
}
961
989
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 " );
966
994
return NGX_OK ;
967
995
}
968
996
997
+ nal_bytes = rc ;
998
+ aud_sent = 0 ;
999
+ sps_pps_sent = 0 ;
1000
+
969
1001
while (in ) {
970
1002
971
- llen = ctx -> nal_bytes ;
1003
+ llen = nal_bytes ;
972
1004
if (ngx_rtmp_hls_copy (s , & rlen , & p , llen , & in ) != NGX_OK ) {
973
1005
return NGX_OK ;
974
1006
}
975
1007
976
1008
len = 0 ;
977
1009
ngx_rtmp_rmemcpy (& len , & rlen , llen );
978
1010
1011
+ nal_type = * p & 0x1f ;
1012
+
979
1013
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
+ }
983
1046
984
1047
/* AnnexB prefix */
985
1048
986
- if (out .last - out .pos < 4 ) {
1049
+ if (out .end - out .last < 4 ) {
987
1050
ngx_log_error (NGX_LOG_ERR , s -> connection -> log , 0 ,
988
1051
"hls: not enough buffer for AnnexB prefix" );
989
1052
return NGX_OK ;
990
1053
}
991
1054
992
- /*TODO: add AUD NAL*/
993
-
994
1055
/* first AnnexB prefix is long (4 bytes) */
995
1056
996
- if (out .pos == buffer ) {
997
- * out .pos ++ = 0 ;
1057
+ if (out .last == out . pos ) {
1058
+ * out .last ++ = 0 ;
998
1059
}
999
1060
1000
- * out .pos ++ = 0 ;
1001
- * out .pos ++ = 0 ;
1002
- * out .pos ++ = 1 ;
1061
+ * out .last ++ = 0 ;
1062
+ * out .last ++ = 0 ;
1063
+ * out .last ++ = 1 ;
1003
1064
1004
1065
/* NAL body */
1005
1066
1006
- if (out .last - out .pos < (ngx_int_t ) len ) {
1067
+ if (out .end - out .last < (ngx_int_t ) len ) {
1007
1068
ngx_log_error (NGX_LOG_ERR , s -> connection -> log , 0 ,
1008
1069
"hls: not enough buffer for NAL" );
1009
1070
return NGX_OK ;
1010
1071
}
1011
1072
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 ) {
1013
1074
return NGX_ERROR ;
1014
1075
}
1015
1076
1016
- out .pos += len ;
1077
+ out .last += len ;
1017
1078
}
1018
1079
1019
- /*TODO*/
1020
- out .last = out .pos ;
1021
- out .pos = buffer ;
1022
-
1023
1080
ngx_memzero (& frame , sizeof (frame ));
1024
1081
1025
1082
frame .cc = ctx -> video_cc ;
0 commit comments