Skip to content

Commit 8def5f3

Browse files
committed
Merge branch 'out-metadata'
2 parents fa3630d + 9788b1a commit 8def5f3

File tree

5 files changed

+202
-10
lines changed

5 files changed

+202
-10
lines changed

ngx_rtmp_codec_module.c

Lines changed: 154 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,6 @@
1111
static ngx_int_t ngx_rtmp_codec_postconfiguration(ngx_conf_t *cf);
1212

1313

14-
/* Global header version is used to identify
15-
* incoming AAC/AVC header */
16-
static ngx_uint_t header_version;
17-
18-
1914
static ngx_rtmp_module_t ngx_rtmp_codec_module_ctx = {
2015
NULL, /* preconfiguration */
2116
ngx_rtmp_codec_postconfiguration, /* postconfiguration */
@@ -97,6 +92,20 @@ ngx_rtmp_get_video_codec_name(ngx_uint_t id)
9792
}
9893

9994

95+
static ngx_uint_t
96+
ngx_rtmp_codec_get_next_version()
97+
{
98+
ngx_uint_t v;
99+
static ngx_uint_t version;
100+
101+
do {
102+
v = ++version;
103+
} while (v == 0);
104+
105+
return v;
106+
}
107+
108+
100109
static ngx_int_t
101110
ngx_rtmp_codec_disconnect(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
102111
ngx_chain_t *in)
@@ -131,6 +140,11 @@ ngx_rtmp_codec_disconnect(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
131140
ctx->aac_pheader = NULL;
132141
}
133142

143+
if (ctx->meta) {
144+
ngx_rtmp_free_shared_chain(cscf, ctx->meta);
145+
ctx->meta = NULL;
146+
}
147+
134148
return NGX_OK;
135149
}
136150

@@ -229,9 +243,139 @@ ngx_rtmp_codec_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
229243
ngx_rtmp_prepare_message(s, &ch, &lh, *pheader);
230244

231245
/* don't want zero as version value */
232-
do {
233-
*version = ++header_version;
234-
} while (*version == 0);
246+
*version = ngx_rtmp_codec_get_next_version();
247+
248+
return NGX_OK;
249+
}
250+
251+
252+
static ngx_int_t
253+
ngx_rtmp_codec_update_meta(ngx_rtmp_session_t *s)
254+
{
255+
ngx_rtmp_codec_ctx_t *ctx;
256+
ngx_rtmp_core_srv_conf_t *cscf;
257+
ngx_int_t rc;
258+
ngx_rtmp_header_t h;
259+
260+
static struct {
261+
double width;
262+
double height;
263+
double duration;
264+
double frame_rate;
265+
double video_data_rate;
266+
double video_codec_id;
267+
double audio_data_rate;
268+
double audio_codec_id;
269+
u_char profile[32];
270+
u_char level[32];
271+
} v;
272+
273+
static ngx_rtmp_amf_elt_t out_inf[] = {
274+
275+
{ NGX_RTMP_AMF_STRING,
276+
ngx_string("Server"),
277+
"NGINX RTMP (github.com/arut/nginx-rtmp-module)", 0 },
278+
279+
{ NGX_RTMP_AMF_NUMBER,
280+
ngx_string("width"),
281+
&v.width, 0 },
282+
283+
{ NGX_RTMP_AMF_NUMBER,
284+
ngx_string("height"),
285+
&v.height, 0 },
286+
287+
{ NGX_RTMP_AMF_NUMBER,
288+
ngx_string("displayWidth"),
289+
&v.width, 0 },
290+
291+
{ NGX_RTMP_AMF_NUMBER,
292+
ngx_string("displayHeight"),
293+
&v.height, 0 },
294+
295+
{ NGX_RTMP_AMF_NUMBER,
296+
ngx_string("duration"),
297+
&v.duration, 0 },
298+
299+
{ NGX_RTMP_AMF_NUMBER,
300+
ngx_string("framerate"),
301+
&v.frame_rate, 0 },
302+
303+
{ NGX_RTMP_AMF_NUMBER,
304+
ngx_string("fps"),
305+
&v.frame_rate, 0 },
306+
307+
{ NGX_RTMP_AMF_NUMBER,
308+
ngx_string("videodatarate"),
309+
&v.video_data_rate, 0 },
310+
311+
{ NGX_RTMP_AMF_NUMBER,
312+
ngx_string("videocodecid"),
313+
&v.video_codec_id, 0 },
314+
315+
{ NGX_RTMP_AMF_NUMBER,
316+
ngx_string("audiodatarate"),
317+
&v.audio_data_rate, 0 },
318+
319+
{ NGX_RTMP_AMF_NUMBER,
320+
ngx_string("audiocodecid"),
321+
&v.audio_codec_id, 0 },
322+
323+
{ NGX_RTMP_AMF_STRING,
324+
ngx_string("profile"),
325+
&v.profile, sizeof(v.profile) },
326+
327+
{ NGX_RTMP_AMF_STRING,
328+
ngx_string("level"),
329+
&v.level, sizeof(v.level) },
330+
};
331+
332+
static ngx_rtmp_amf_elt_t out_elts[] = {
333+
334+
{ NGX_RTMP_AMF_STRING,
335+
ngx_null_string,
336+
"onMetaData", 0 },
337+
338+
{ NGX_RTMP_AMF_OBJECT,
339+
ngx_null_string,
340+
out_inf, sizeof(out_inf) },
341+
};
342+
343+
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);
344+
if (ctx == NULL) {
345+
return NGX_OK;
346+
}
347+
348+
cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module);
349+
350+
if (ctx->meta) {
351+
ngx_rtmp_free_shared_chain(cscf, ctx->meta);
352+
ctx->meta = NULL;
353+
}
354+
355+
v.width = ctx->width;
356+
v.height = ctx->height;
357+
v.duration = ctx->duration;
358+
v.frame_rate = ctx->frame_rate;
359+
v.video_data_rate = ctx->video_data_rate;
360+
v.video_codec_id = ctx->video_codec_id;
361+
v.audio_data_rate = ctx->audio_data_rate;
362+
v.audio_codec_id = ctx->audio_codec_id;
363+
ngx_memcpy(v.profile, ctx->profile, sizeof(ctx->profile));
364+
ngx_memcpy(v.level, ctx->level, sizeof(ctx->level));
365+
366+
rc = ngx_rtmp_append_amf(s, &ctx->meta, NULL, out_elts,
367+
sizeof(out_elts) / sizeof(out_elts[0]));
368+
if (rc != NGX_OK || ctx->meta == NULL) {
369+
return NGX_ERROR;
370+
}
371+
372+
ngx_memzero(&h, sizeof(h));
373+
h.csid = 5;
374+
h.msid = NGX_RTMP_LIVE_MSID;
375+
h.type = NGX_RTMP_MSG_AMF_META;
376+
ngx_rtmp_prepare_message(s, &h, NULL, ctx->meta);
377+
378+
ctx->meta_version = ngx_rtmp_codec_get_next_version();
235379

236380
return NGX_OK;
237381
}
@@ -385,6 +529,8 @@ ngx_rtmp_codec_meta_data(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
385529
ngx_rtmp_get_audio_codec_name(ctx->audio_codec_id),
386530
ctx->audio_codec_id);
387531

532+
ngx_rtmp_codec_update_meta(s);
533+
388534
return NGX_OK;
389535
}
390536

ngx_rtmp_codec_module.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ typedef struct {
7070
/* prepared headers (for live streaming) */
7171
ngx_chain_t *avc_pheader;
7272
ngx_chain_t *aac_pheader;
73+
74+
ngx_chain_t *meta;
75+
ngx_uint_t meta_version;
7376
} ngx_rtmp_codec_ctx_t;
7477

7578

ngx_rtmp_live_module.c

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ static ngx_command_t ngx_rtmp_live_commands[] = {
3232
offsetof(ngx_rtmp_live_app_conf_t, live),
3333
NULL },
3434

35+
{ ngx_string("meta"),
36+
NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
37+
ngx_conf_set_flag_slot,
38+
NGX_RTMP_APP_CONF_OFFSET,
39+
offsetof(ngx_rtmp_live_app_conf_t, meta),
40+
NULL },
41+
3542
{ ngx_string("stream_buckets"),
3643
NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
3744
ngx_conf_set_str_slot,
@@ -89,6 +96,7 @@ ngx_rtmp_live_create_app_conf(ngx_conf_t *cf)
8996
}
9097

9198
lacf->live = NGX_CONF_UNSET;
99+
lacf->meta = NGX_CONF_UNSET;
92100
lacf->nbuckets = NGX_CONF_UNSET;
93101
lacf->buflen = NGX_CONF_UNSET;
94102

@@ -103,6 +111,7 @@ ngx_rtmp_live_merge_app_conf(ngx_conf_t *cf, void *parent, void *child)
103111
ngx_rtmp_live_app_conf_t *conf = child;
104112

105113
ngx_conf_merge_value(conf->live, prev->live, 0);
114+
ngx_conf_merge_value(conf->meta, prev->meta, 1);
106115
ngx_conf_merge_value(conf->nbuckets, prev->nbuckets, 1024);
107116
ngx_conf_merge_msec_value(conf->buflen, prev->buflen, 0);
108117

@@ -283,15 +292,16 @@ ngx_rtmp_live_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
283292
{
284293
ngx_rtmp_live_ctx_t *ctx, *pctx;
285294
ngx_rtmp_codec_ctx_t *codec_ctx;
286-
ngx_chain_t *out, *peer_out, *header_out, *pheader_out;
295+
ngx_chain_t *out, *peer_out, *header_out,
296+
*pheader_out, *meta;
287297
ngx_rtmp_core_srv_conf_t *cscf;
288298
ngx_rtmp_live_app_conf_t *lacf;
289299
ngx_rtmp_session_t *ss;
290300
ngx_rtmp_header_t ch, lh;
291301
ngx_uint_t prio, peer_prio;
292302
ngx_uint_t peers, dropped_peers;
293303
size_t header_offset;
294-
ngx_uint_t header_version;
304+
ngx_uint_t header_version, meta_version;
295305

296306
lacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_live_module);
297307
if (lacf == NULL) {
@@ -355,6 +365,8 @@ ngx_rtmp_live_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
355365
pheader_out = NULL;
356366
header_offset = 0;
357367
header_version = 0;
368+
meta = NULL;
369+
meta_version = 0;
358370
if (codec_ctx) {
359371
if (h->type == NGX_RTMP_MSG_AUDIO) {
360372
if (codec_ctx->aac_pheader) {
@@ -371,6 +383,10 @@ ngx_rtmp_live_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
371383
header_version = codec_ctx->avc_version;
372384
}
373385
}
386+
if (lacf->meta && codec_ctx->meta) {
387+
meta = codec_ctx->meta;
388+
meta_version = codec_ctx->meta_version;
389+
}
374390
}
375391

376392
/* broadcast to all subscribers */
@@ -415,6 +431,15 @@ ngx_rtmp_live_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
415431
}
416432
}
417433

434+
/* send metadata if newer exists */
435+
if (meta && meta_version != pctx->meta_version) {
436+
ngx_log_debug0(NGX_LOG_DEBUG_RTMP, ss->connection->log, 0,
437+
"live: sending metadata");
438+
if (ngx_rtmp_send_message(ss, meta, prio) == NGX_OK) {
439+
pctx->meta_version = meta_version;
440+
}
441+
}
442+
418443
/* push buffered data */
419444
peer_prio = prio;
420445
if (ngx_rtmp_send_message(ss, out, peer_prio) != NGX_OK) {

ngx_rtmp_live_module.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ struct ngx_rtmp_live_ctx_s {
3939
uint32_t last_video;
4040
ngx_uint_t aac_version;
4141
ngx_uint_t avc_version;
42+
ngx_uint_t meta_version;
4243
};
4344

4445

@@ -57,6 +58,7 @@ typedef struct {
5758
ngx_int_t nbuckets;
5859
ngx_rtmp_live_stream_t **streams;
5960
ngx_flag_t live;
61+
ngx_flag_t meta;
6062
ngx_msec_t buflen;
6163
ngx_pool_t *pool;
6264
ngx_rtmp_live_stream_t *free_streams;

ngx_rtmp_record_module.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,21 @@ ngx_rtmp_record_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
637637
if (codec_ctx) {
638638
ch = *h;
639639

640+
#if 0
641+
/* metadata */
642+
if (codec_ctx->meta) {
643+
ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
644+
"record: writing metadata");
645+
ch.type = NGX_RTMP_MSG_AMF_META;
646+
ch.mlen = ngx_rtmp_record_get_chain_mlen(codec_ctx->meta);
647+
if (ngx_rtmp_record_write_frame(s, &ch, codec_ctx->meta)
648+
!= NGX_OK)
649+
{
650+
return NGX_OK;
651+
}
652+
}
653+
#endif
654+
/* AAC header */
640655
if (codec_ctx->aac_header && (racf->flags & NGX_RTMP_RECORD_AUDIO))
641656
{
642657
ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
@@ -650,6 +665,7 @@ ngx_rtmp_record_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
650665
}
651666
}
652667

668+
/* AVC header */
653669
if (codec_ctx->avc_header && (racf->flags
654670
& (NGX_RTMP_RECORD_VIDEO|NGX_RTMP_RECORD_KEYFRAMES)))
655671
{

0 commit comments

Comments
 (0)