mirror of
https://github.com/zotanmew/nginx-rtmp-module.git
synced 2024-05-16 00:31:09 +02:00
added parsing data frame & added stream meta info to stat xml
This commit is contained in:
parent
4d4af44bf2
commit
a4f48c5baa
1
config
1
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"
|
||||
|
||||
|
|
51
ngx_rtmp_codecs.c
Normal file
51
ngx_rtmp_codecs.c
Normal file
|
@ -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]
|
||||
: "");
|
||||
}
|
40
ngx_rtmp_codecs.h
Normal file
40
ngx_rtmp_codecs.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Roman Arutyunyan
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NGX_RTMP_CODECS_H_INCLUDED_
|
||||
#define _NGX_RTMP_CODECS_H_INCLUDED_
|
||||
|
||||
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
/* 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_ */
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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("</name>\r\n");
|
||||
|
||||
meta = &stream->meta;
|
||||
NGX_RTMP_STAT_L("<meta><width>");
|
||||
NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
|
||||
"%ui", meta->width) - buf);
|
||||
NGX_RTMP_STAT_L("</width><height>");
|
||||
NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
|
||||
"%ui", meta->height) - buf);
|
||||
NGX_RTMP_STAT_L("</height><framerate>");
|
||||
NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
|
||||
"%ui", meta->frame_rate) - buf);
|
||||
NGX_RTMP_STAT_L("</framerate><video>");
|
||||
codec = ngx_rtmp_get_video_codec_name(meta->video_codec_id);
|
||||
if (*codec) {
|
||||
NGX_RTMP_STAT_ECS(codec);
|
||||
}
|
||||
NGX_RTMP_STAT_L("</video><audio>");
|
||||
codec = ngx_rtmp_get_audio_codec_name(meta->audio_codec_id);
|
||||
if (*codec) {
|
||||
NGX_RTMP_STAT_ECS(codec);
|
||||
}
|
||||
NGX_RTMP_STAT_L("</audio></meta>\r\n");
|
||||
|
||||
ngx_rtmp_stat_bw(r, lll, &stream->bw_in, &stream->bw_out);
|
||||
|
||||
nclients = 0;
|
||||
|
|
33
stat.xsl
33
stat.xsl
|
@ -24,6 +24,10 @@
|
|||
<th>Out bytes</th>
|
||||
<th>In Kbps</th>
|
||||
<th>Out Kbps</th>
|
||||
<th>Size</th>
|
||||
<th>Frame Rate</th>
|
||||
<th>Video</th>
|
||||
<th>Audio</th>
|
||||
<th>State</th>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -32,7 +36,6 @@
|
|||
<td><xsl:value-of select="out"/></td>
|
||||
<td><xsl:value-of select="round(bwin div 1024)"/></td>
|
||||
<td><xsl:value-of select="round(bwout div 1024)"/></td>
|
||||
<td><xsl:apply-templates select="publishing"/></td>
|
||||
</tr>
|
||||
<xsl:apply-templates select="server"/>
|
||||
</table>
|
||||
|
@ -75,24 +78,16 @@
|
|||
<xsl:value-of select="name"/>
|
||||
</a>
|
||||
</td>
|
||||
<td align="middle">
|
||||
<xsl:value-of select="nclients"/>
|
||||
</td>
|
||||
<td>
|
||||
<xsl:value-of select="in"/>
|
||||
</td>
|
||||
<td>
|
||||
<xsl:value-of select="out"/>
|
||||
</td>
|
||||
<td>
|
||||
<xsl:value-of select="round(bwin div 1024)"/>
|
||||
</td>
|
||||
<td>
|
||||
<xsl:value-of select="round(bwout div 1024)"/>
|
||||
</td>
|
||||
<td>
|
||||
<xsl:apply-templates select="publishing"/>
|
||||
</td>
|
||||
<td align="middle"> <xsl:value-of select="nclients"/> </td>
|
||||
<td><xsl:value-of select="in"/></td>
|
||||
<td><xsl:value-of select="out"/></td>
|
||||
<td><xsl:value-of select="round(bwin div 1024)"/></td>
|
||||
<td><xsl:value-of select="round(bwout div 1024)"/></td>
|
||||
<td><xsl:value-of select="meta/width"/>x<xsl:value-of select="meta/height"/></td>
|
||||
<td align="middle"><xsl:value-of select="meta/framerate"/></td>
|
||||
<td><xsl:value-of select="meta/video"/></td>
|
||||
<td><xsl:value-of select="meta/audio"/></td>
|
||||
<td> <xsl:apply-templates select="publishing"/> </td>
|
||||
</tr>
|
||||
<tr style="display:none">
|
||||
<xsl:attribute name="id">
|
||||
|
|
Loading…
Reference in a new issue