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:11:12 
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