From a4f48c5baa427c9d9093c0ceee339820c2167624 Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Sat, 12 May 2012 17:47:39 +0400 Subject: [PATCH] added parsing data frame & added stream meta info to stat xml --- config | 1 + ngx_rtmp_codecs.c | 51 +++++++++++++++++ ngx_rtmp_codecs.h | 40 +++++++++++++ ngx_rtmp_live_module.c | 126 ++++++++++++++++++++++++++++++++++++++++- ngx_rtmp_live_module.h | 13 +++++ ngx_rtmp_stat_module.c | 25 ++++++++ stat.xsl | 33 +++++------ 7 files changed, 269 insertions(+), 20 deletions(-) create mode 100644 ngx_rtmp_codecs.c create mode 100644 ngx_rtmp_codecs.h diff --git a/config b/config index 0e29bd6..34d0af7 100644 --- a/config +++ b/config @@ -35,6 +35,7 @@ NGX_ADDON_SRCS="$NGX_ADDON_SRCS \ $ngx_addon_dir/ngx_rtmp_notify_module.c \ $ngx_addon_dir/ngx_rtmp_stat_module.c \ $ngx_addon_dir/ngx_rtmp_bandwidth.c \ + $ngx_addon_dir/ngx_rtmp_codecs.c \ " CFLAGS="$CFLAGS -I$ngx_addon_dir" diff --git a/ngx_rtmp_codecs.c b/ngx_rtmp_codecs.c new file mode 100644 index 0000000..4ccc8e7 --- /dev/null +++ b/ngx_rtmp_codecs.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2012 Roman Arutyunyan + */ + + +#include "ngx_rtmp_codecs.h" + + +const char * audio_codecs[] = { + "Uncompressed", + "ADPCM", + "MP3", + "", + "", + "Nellymoser8", + "Nellymoser", + "", + "", + "", + "HE-ACC", + "Speex" +}; + + +const char * video_codecs[] = { + "", + "", + "Sorenson-H263", + "ScreenVideo", + "On2-VP6", + "On2-VP6-Alpha", + "H264", +}; + + +u_char * +ngx_rtmp_get_audio_codec_name(ngx_uint_t id) +{ + return (u_char *)(id < sizeof(audio_codecs) / sizeof(audio_codecs[0]) + ? audio_codecs[id] + : ""); +} + + +u_char * +ngx_rtmp_get_video_codec_name(ngx_uint_t id) +{ + return (u_char *)(id < sizeof(video_codecs) / sizeof(video_codecs[0]) + ? video_codecs[id] + : ""); +} diff --git a/ngx_rtmp_codecs.h b/ngx_rtmp_codecs.h new file mode 100644 index 0000000..aecef12 --- /dev/null +++ b/ngx_rtmp_codecs.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2012 Roman Arutyunyan + */ + + +#ifndef _NGX_RTMP_CODECS_H_INCLUDED_ +#define _NGX_RTMP_CODECS_H_INCLUDED_ + + +#include + + +/* Audio codecs */ +enum { + NGX_RTMP_AUDIO_UNCOMPRESSED = 0, + NGX_RTMP_AUDIO_ADPCM = 1, + NGX_RTMP_AUDIO_MP3 = 2, + NGX_RTMP_AUDIO_NELLY8 = 5, + NGX_RTMP_AUDIO_NELLY = 6, + NGX_RTMP_AUDIO_HE_ACC = 10, + NGX_RTMP_AUDIO_SPEEX = 11 +}; + + +/* Video codecs */ +enum { + NGX_RTMP_VIDEO_SORENSON_H263 = 2, + NGX_RTMP_VIDEO_SCREEN = 3, + NGX_RTMP_VIDEO_ON2_VP6 = 4, + NGX_RTMP_VIDEO_ON2_VP6_ALPHA = 5, + NGX_RTMP_VIDEO_H264 = 7 +}; + + +u_char * ngx_rtmp_get_audio_codec_name(ngx_uint_t id); +u_char * ngx_rtmp_get_video_codec_name(ngx_uint_t id); + + +#endif /* _NGX_RTMP_CODECS_H_INCLUDED_ */ + diff --git a/ngx_rtmp_live_module.c b/ngx_rtmp_live_module.c index 0f66593..c584a74 100644 --- a/ngx_rtmp_live_module.c +++ b/ngx_rtmp_live_module.c @@ -5,6 +5,7 @@ #include "ngx_rtmp_live_module.h" #include "ngx_rtmp_cmd_module.h" +#include "ngx_rtmp_codecs.h" static ngx_rtmp_publish_pt next_publish; @@ -443,15 +444,138 @@ next: } +static ngx_int_t +ngx_rtmp_live_data_frame(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, + ngx_chain_t *in) +{ + ngx_rtmp_live_app_conf_t *lacf; + ngx_rtmp_live_ctx_t *ctx; + ngx_rtmp_live_meta_t *meta; + + static struct { + double width; + double height; + double duration; + double frame_rate; + double video_data_rate; + double video_codec_id; + double audio_data_rate; + double audio_codec_id; + } v; + + static ngx_rtmp_amf_elt_t in_inf[] = { + + { NGX_RTMP_AMF_NUMBER, + ngx_string("width"), + &v.width, 0 }, + + { NGX_RTMP_AMF_NUMBER, + ngx_string("height"), + &v.height, 0 }, + + { NGX_RTMP_AMF_NUMBER, + ngx_string("duration"), + &v.duration, 0 }, + + { NGX_RTMP_AMF_NUMBER, + ngx_string("framerate"), + &v.frame_rate, 0 }, + + { NGX_RTMP_AMF_NUMBER, + ngx_string("videodatarate"), + &v.video_data_rate, 0 }, + + { NGX_RTMP_AMF_NUMBER, + ngx_string("videocodecid"), + &v.video_codec_id, 0 }, + + { NGX_RTMP_AMF_NUMBER, + ngx_string("audiodatarate"), + &v.audio_data_rate, 0 }, + + { NGX_RTMP_AMF_NUMBER, + ngx_string("audiocodecid"), + &v.audio_codec_id, 0 }, + }; + + static ngx_rtmp_amf_elt_t in_elts[] = { + + { NGX_RTMP_AMF_STRING, + ngx_null_string, + NULL, 0 }, + + { NGX_RTMP_AMF_OBJECT, + ngx_null_string, + in_inf, sizeof(in_inf) }, + }; + + lacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_live_module); + if (lacf == NULL || !lacf->live) { + return NGX_OK; + } + + ngx_memzero(&v, sizeof(v)); + if (ngx_rtmp_receive_amf(s, in, in_elts, + sizeof(in_elts) / sizeof(in_elts[0]))) + { + ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, + "live: error parsing data frame"); + return NGX_OK; + } + + ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_live_module); + if (ctx == NULL) { + return NGX_OK; + } + + if ((ctx->flags & NGX_RTMP_LIVE_PUBLISHING) == 0) { + ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, + "live: received data stream from non-publisher"); + return NGX_OK; + } + + meta = &ctx->stream->meta; + meta->width = v.width; + meta->height = v.height; + meta->duration = v.duration; + meta->frame_rate = v.frame_rate; + meta->video_data_rate = v.video_data_rate; + meta->video_codec_id = v.video_codec_id; + meta->audio_data_rate = v.audio_data_rate; + meta->audio_codec_id = v.audio_codec_id; + + ngx_log_debug8(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + "live: data frame: " + "width=%ui height=%ui duration=%ui frame_rate=%ui " + "video=%s (%ui) audio=%s (%ui)", + meta->width, meta->height, meta->duration, meta->frame_rate, + ngx_rtmp_get_video_codec_name(meta->video_codec_id), + meta->video_codec_id, + ngx_rtmp_get_audio_codec_name(meta->audio_codec_id), + meta->audio_codec_id); + + return NGX_OK; +} + + static ngx_int_t ngx_rtmp_live_postconfiguration(ngx_conf_t *cf) { ngx_rtmp_core_main_conf_t *cmcf; ngx_rtmp_handler_pt *h; + ngx_rtmp_amf_handler_t *ch; - /* register raw event handlers */ cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module); + /* register data frame handler */ + ch = ngx_array_push(&cmcf->amf); + if (ch == NULL) { + return NGX_ERROR; + } + ngx_str_set(&ch->name, "@setDataFrame"); + ch->handler = ngx_rtmp_live_data_frame; + + /* register raw event handlers */ h = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_AUDIO]); *h = ngx_rtmp_live_av; diff --git a/ngx_rtmp_live_module.h b/ngx_rtmp_live_module.h index 4077c85..1caf4da 100644 --- a/ngx_rtmp_live_module.h +++ b/ngx_rtmp_live_module.h @@ -15,6 +15,18 @@ #define NGX_RTMP_LIVE_PUBLISHING 0x01 +typedef struct { + ngx_uint_t width; + ngx_uint_t height; + ngx_uint_t duration; + ngx_uint_t frame_rate; + ngx_uint_t video_data_rate; + ngx_uint_t video_codec_id; + ngx_uint_t audio_data_rate; + ngx_uint_t audio_codec_id; +} ngx_rtmp_live_meta_t; + + typedef struct ngx_rtmp_live_ctx_s ngx_rtmp_live_ctx_t; typedef struct ngx_rtmp_live_stream_s ngx_rtmp_live_stream_t; @@ -40,6 +52,7 @@ struct ngx_rtmp_live_stream_s { ngx_uint_t flags; ngx_rtmp_bandwidth_t bw_in; ngx_rtmp_bandwidth_t bw_out; + ngx_rtmp_live_meta_t meta; }; diff --git a/ngx_rtmp_stat_module.c b/ngx_rtmp_stat_module.c index 2b5a93b..4db736f 100644 --- a/ngx_rtmp_stat_module.c +++ b/ngx_rtmp_stat_module.c @@ -7,6 +7,7 @@ #include "ngx_rtmp.h" #include "ngx_rtmp_live_module.h" +#include "ngx_rtmp_codecs.h" static ngx_int_t ngx_rtmp_stat_postconfiguration(ngx_conf_t *cf); @@ -202,6 +203,7 @@ ngx_rtmp_stat_live(ngx_http_request_t *r, ngx_chain_t ***lll, ngx_rtmp_live_app_conf_t *lacf) { ngx_rtmp_live_stream_t *stream; + ngx_rtmp_live_meta_t *meta; ngx_rtmp_live_ctx_t *ctx; ngx_rtmp_session_t *s; ngx_int_t n; @@ -209,6 +211,7 @@ ngx_rtmp_stat_live(ngx_http_request_t *r, ngx_chain_t ***lll, ngx_int_t publishing; u_char buf[NGX_OFF_T_LEN + 1]; ngx_rtmp_stat_loc_conf_t *slcf; + u_char *codec; slcf = ngx_http_get_module_loc_conf(r, ngx_rtmp_stat_module); @@ -224,6 +227,28 @@ ngx_rtmp_stat_live(ngx_http_request_t *r, ngx_chain_t ***lll, NGX_RTMP_STAT_ECS(stream->name); NGX_RTMP_STAT_L("\r\n"); + meta = &stream->meta; + NGX_RTMP_STAT_L(""); + NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), + "%ui", meta->width) - buf); + NGX_RTMP_STAT_L(""); + NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), + "%ui", meta->height) - buf); + NGX_RTMP_STAT_L(""); + NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), + "%ui", meta->frame_rate) - buf); + NGX_RTMP_STAT_L("\r\n"); + ngx_rtmp_stat_bw(r, lll, &stream->bw_in, &stream->bw_out); nclients = 0; diff --git a/stat.xsl b/stat.xsl index 95f38da..b171ec1 100644 --- a/stat.xsl +++ b/stat.xsl @@ -24,6 +24,10 @@ Out bytes In Kbps Out Kbps + Size + Frame Rate + Video + Audio State @@ -32,7 +36,6 @@ - @@ -75,24 +78,16 @@ - - - - - - - - - - - - - - - - - - + + + + + + x + + + +