1+ /*
2+ * @Author: likai
3+ * @Date: 2023-08-11 19:00:30
4+ * @Last Modified by: likai
5+ * @Last Modified time: 2023-08-11 20:10:13
6+ * @Description: "this module for handle h264 nal data"
7+ */
8+
9+ #include "ngx_rtmp_cmd_module.h"
10+ #include "ngx_rtmp_codec_module.h"
11+ #include <nginx.h>
12+ #include <ngx_config.h>
13+ #include <ngx_core.h>
14+
15+ static void * ngx_rtmp_nal_create_app_conf (ngx_conf_t * cf );
16+ static char * ngx_rtmp_nal_merge_app_conf (ngx_conf_t * cf , void * parent ,
17+ void * child );
18+ static ngx_int_t ngx_rtmp_nal_postconfiguration (ngx_conf_t * cf );
19+
20+ typedef struct {
21+ ngx_flag_t skip_filler_data ;
22+ } ngx_rtmp_nal_app_conf_t ;
23+
24+ static ngx_command_t ngx_rtmp_nal_commands [] = {
25+
26+ { ngx_string ("skip_filler_data" ),
27+ NGX_RTMP_MAIN_CONF | NGX_RTMP_SRV_CONF | NGX_RTMP_APP_CONF | NGX_CONF_TAKE1 ,
28+ ngx_conf_set_flag_slot , NGX_RTMP_APP_CONF_OFFSET ,
29+ offsetof(ngx_rtmp_nal_app_conf_t , skip_filler_data ), NULL },
30+
31+ ngx_null_command
32+
33+ };
34+
35+ static ngx_rtmp_module_t ngx_rtmp_nal_module_ctx = {
36+ NULL , /* preconfiguration */
37+ ngx_rtmp_nal_postconfiguration , /* postconfiguration */
38+ NULL , /* create main configuration */
39+ NULL , /* init main configuration */
40+ NULL , /* create server configuration */
41+ NULL , /* merge server configuration */
42+ ngx_rtmp_nal_create_app_conf , /* create app configuration */
43+ ngx_rtmp_nal_merge_app_conf /* merge app configuration */
44+ };
45+
46+ ngx_module_t ngx_rtmp_nal_module = {
47+ NGX_MODULE_V1 ,
48+ & ngx_rtmp_nal_module_ctx , /* module context */
49+ ngx_rtmp_nal_commands , /* module directives */
50+ NGX_RTMP_MODULE , /* module type */
51+ NULL , /* init master */
52+ NULL , /* init module */
53+ NULL , /* init process */
54+ NULL , /* init thread */
55+ NULL , /* exit thread */
56+ NULL , /* exit process */
57+ NULL , /* exit master */
58+ NGX_MODULE_V1_PADDING
59+ };
60+
61+ static ngx_int_t ngx_rtmp_handle_video (ngx_rtmp_session_t * s ,
62+ ngx_rtmp_header_t * h , ngx_chain_t * in ) {
63+ ngx_rtmp_codec_ctx_t * codec_ctx ;
64+ ngx_rtmp_nal_app_conf_t * nacf ;
65+
66+ ngx_int_t nal_type , nsize , nal_size , i , least_size ;
67+ ngx_int_t remain , nal_size_remain , remove_size ;
68+ ngx_int_t parse_header ;
69+ ngx_chain_t * inp ;
70+ u_char av_type , * p ;
71+
72+ nal_size = 0 ;
73+ nsize = 0 ;
74+ nal_type = 0 ;
75+ av_type = 0 ;
76+ nal_size_remain = 0 ;
77+ remove_size = 0 ;
78+ remain = 0 ;
79+ parse_header = 1 ;
80+
81+ nacf = ngx_rtmp_get_module_app_conf (s , ngx_rtmp_nal_module );
82+ if (nacf == NULL ) {
83+ return NGX_ERROR ;
84+ }
85+
86+ if (!nacf -> skip_filler_data ) {
87+ return NGX_OK ;
88+ }
89+
90+ codec_ctx = ngx_rtmp_get_module_ctx (s , ngx_rtmp_codec_module );
91+ if (codec_ctx == NULL ) {
92+ return NGX_ERROR ;
93+ }
94+
95+ if (codec_ctx -> video_codec_id != NGX_RTMP_VIDEO_H264 ) {
96+ ngx_log_error (NGX_LOG_WARN , s -> connection -> log , 0 ,
97+ "skip filler data"
98+ "only support h264" );
99+ return NGX_OK ;
100+ }
101+
102+ if (in -> buf -> last - in -> buf -> pos < 5 ) {
103+ ngx_log_error (NGX_LOG_WARN , s -> connection -> log , 0 ,
104+ "input buffer too short: %d" , in -> buf -> last - in -> buf -> pos );
105+ return NGX_OK ;
106+ }
107+
108+ inp = in ;
109+ p = inp -> buf -> pos ;
110+ p ++ ;
111+ av_type = * p ;
112+ p += 4 ;
113+ least_size = codec_ctx -> avc_nal_bytes + 1 ;
114+
115+ while (av_type != 0 ) {
116+ if (parse_header == 1 ) {
117+ for (i = 0 ; i < ((ngx_int_t )codec_ctx -> avc_nal_bytes - nal_size_remain );
118+ i ++ ) {
119+ nal_size = (nal_size << 8 ) | (* p ++ );
120+ }
121+ if (nal_size_remain != 0 ) {
122+ p += (codec_ctx -> avc_nal_bytes - nal_size_remain );
123+ }
124+
125+ if (codec_ctx -> video_codec_id == NGX_RTMP_VIDEO_H264 ) {
126+ nal_type = * p & 0x1f ;
127+ } else {
128+ nal_type = (* p & 0x7e ) >> 1 ;
129+ }
130+
131+ if ((h -> mlen - 5 ) == nal_size + codec_ctx -> avc_nal_bytes ) {
132+ break ;
133+ }
134+ if ((h -> mlen - 5 ) < nal_size + codec_ctx -> avc_nal_bytes ) {
135+ ngx_log_error (NGX_LOG_WARN , s -> connection -> log , 0 ,
136+ "nal size:%d > rtmp message length" , nal_size );
137+ break ;
138+ }
139+ parse_header = 0 ;
140+ p -= (codec_ctx -> avc_nal_bytes - nal_size_remain );
141+ }
142+
143+ nsize += (inp -> buf -> last - p );
144+ remain = nsize - (nal_size + codec_ctx -> avc_nal_bytes );
145+
146+ if (remain > 0 && nal_type == 12 &&
147+ codec_ctx -> video_codec_id == NGX_RTMP_VIDEO_H264 ) {
148+ remove_size = (inp -> buf -> last - p - remain );
149+ inp -> buf -> last = ngx_movemem (p , inp -> buf -> last - remain , remain );
150+
151+ } else if (remain <= 0 && nal_type == 12 &&
152+ codec_ctx -> video_codec_id == NGX_RTMP_VIDEO_H264 ) {
153+ remove_size += (inp -> buf -> last - p );
154+ inp -> buf -> last = p ;
155+ }
156+
157+ if (remain >= least_size ) {
158+ p = inp -> buf -> last - remain ;
159+ nal_size_remain = 0 ;
160+ nal_size = 0 ;
161+ nsize = 0 ;
162+ nal_type = 0 ;
163+ parse_header = 1 ;
164+ continue ;
165+ } else if (remain > 0 && remain < least_size ) {
166+ nal_size_remain = remain ;
167+ nal_size = 0 ;
168+ nsize = 0 ;
169+ nal_type = 0 ;
170+ p = inp -> buf -> last - remain ;
171+ for (i = 0 ; i < nal_size_remain ; i ++ ) {
172+ nal_size = (nal_size << 8 ) | (* p ++ );
173+ }
174+ parse_header = 1 ;
175+ }
176+
177+ if (inp -> next ) {
178+ inp = inp -> next ;
179+ p = inp -> buf -> pos ;
180+ } else {
181+ break ;
182+ }
183+ }
184+
185+ #if (NGX_DEBUG )
186+ if (remove_size > 0 ) {
187+ ngx_log_error (NGX_LOG_DEBUG , s -> connection -> log , 0 ,
188+ "remove filler data size:%d" , remove_size );
189+ }
190+ #endif
191+
192+ return NGX_OK ;
193+ }
194+
195+ static void * ngx_rtmp_nal_create_app_conf (ngx_conf_t * cf ) {
196+ ngx_rtmp_nal_app_conf_t * nacf ;
197+
198+ nacf = ngx_pcalloc (cf -> pool , sizeof (ngx_rtmp_nal_app_conf_t ));
199+ if (nacf == NULL ) {
200+ return NULL ;
201+ }
202+
203+ nacf -> skip_filler_data = NGX_CONF_UNSET ;
204+ return nacf ;
205+ }
206+
207+ static char * ngx_rtmp_nal_merge_app_conf (ngx_conf_t * cf , void * parent ,
208+ void * child ) {
209+ ngx_rtmp_nal_app_conf_t * prev = parent ;
210+ ngx_rtmp_nal_app_conf_t * conf = child ;
211+
212+ ngx_conf_merge_value (conf -> skip_filler_data , prev -> skip_filler_data , 0 );
213+ return NGX_CONF_OK ;
214+ }
215+
216+ static ngx_int_t ngx_rtmp_nal_postconfiguration (ngx_conf_t * cf ) {
217+ ngx_rtmp_core_main_conf_t * cmcf ;
218+ ngx_rtmp_handler_pt * h ;
219+
220+ cmcf = ngx_rtmp_conf_get_module_main_conf (cf , ngx_rtmp_core_module );
221+
222+ h = ngx_array_push (& cmcf -> events [NGX_RTMP_MSG_VIDEO ]);
223+ * h = ngx_rtmp_handle_video ;
224+
225+ return NGX_OK ;
226+ }
0 commit comments