Skip to content

Commit 9bfd605

Browse files
committed
[feat] support h264 skip filler data
1 parent a13c92c commit 9bfd605

File tree

3 files changed

+229
-1
lines changed

3 files changed

+229
-1
lines changed

Diff for: config

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ RTMP_CORE_MODULES=" \
1313
ngx_rtmp_play_module \
1414
ngx_rtmp_flv_module \
1515
ngx_rtmp_mp4_module \
16+
ngx_rtmp_nal_module \
1617
ngx_rtmp_netcall_module \
1718
ngx_rtmp_relay_module \
1819
ngx_rtmp_exec_module \
@@ -78,6 +79,7 @@ RTMP_CORE_SRCS=" \
7879
$ngx_addon_dir/ngx_rtmp_play_module.c \
7980
$ngx_addon_dir/ngx_rtmp_flv_module.c \
8081
$ngx_addon_dir/ngx_rtmp_mp4_module.c \
82+
$ngx_addon_dir/ngx_rtmp_nal_module.c \
8183
$ngx_addon_dir/ngx_rtmp_netcall_module.c \
8284
$ngx_addon_dir/ngx_rtmp_relay_module.c \
8385
$ngx_addon_dir/ngx_rtmp_bandwidth.c \

Diff for: ngx_rtmp_nal_module.c

+226
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
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+
}

Diff for: test/nginx.conf

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ rtmp {
1212

1313
application myapp {
1414
live on;
15-
15+
# skip_filler_data on;
1616
#record keyframes;
1717
#record_path /tmp;
1818
#record_max_size 128K;

0 commit comments

Comments
 (0)