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