From 18fa7a5016773803069fc1041649f29b2666c8e9 Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Sat, 21 Dec 2013 00:47:00 +0400 Subject: [PATCH] implemented avc sps parser & improved dash & stats --- config | 2 + dash/ngx_rtmp_mp4.c | 18 +- hls/ngx_rtmp_hls_module.c | 55 +----- ngx_rtmp_bitop.c | 63 +++++++ ngx_rtmp_bitop.h | 46 +++++ ngx_rtmp_codec_module.c | 344 ++++++++++++++++++++++++++++++-------- ngx_rtmp_codec_module.h | 5 +- ngx_rtmp_stat_module.c | 83 +++++++-- stat.xsl | 17 +- 9 files changed, 485 insertions(+), 148 deletions(-) create mode 100644 ngx_rtmp_bitop.c create mode 100644 ngx_rtmp_bitop.h diff --git a/config b/config index a001002..044ad97 100644 --- a/config +++ b/config @@ -43,6 +43,7 @@ NGX_ADDON_DEPS="$NGX_ADDON_DEPS \ $ngx_addon_dir/ngx_rtmp_record_module.h \ $ngx_addon_dir/ngx_rtmp_relay_module.h \ $ngx_addon_dir/ngx_rtmp_streams.h \ + $ngx_addon_dir/ngx_rtmp_bitop.h \ $ngx_addon_dir/hls/ngx_rtmp_mpegts.h \ $ngx_addon_dir/dash/ngx_rtmp_mp4.h \ " @@ -77,6 +78,7 @@ NGX_ADDON_SRCS="$NGX_ADDON_SRCS \ $ngx_addon_dir/ngx_rtmp_notify_module.c \ $ngx_addon_dir/ngx_rtmp_log_module.c \ $ngx_addon_dir/ngx_rtmp_limit_module.c \ + $ngx_addon_dir/ngx_rtmp_bitop.c \ $ngx_addon_dir/hls/ngx_rtmp_hls_module.c \ $ngx_addon_dir/dash/ngx_rtmp_dash_module.c \ $ngx_addon_dir/hls/ngx_rtmp_mpegts.c \ diff --git a/dash/ngx_rtmp_mp4.c b/dash/ngx_rtmp_mp4.c index c02fd45..dd680c9 100644 --- a/dash/ngx_rtmp_mp4.c +++ b/dash/ngx_rtmp_mp4.c @@ -511,14 +511,18 @@ ngx_rtmp_mp4_write_avcc(ngx_rtmp_session_t *s, ngx_buf_t *b) /* assume config fits one chunk (highly probable) */ - /* check for start code */ - for (p = in->buf->pos; p <= in->buf->last; p++) { - if (*p == 0x01) { - break; - } - } + /* + * Skip: + * - flv fmt + * - H264 CONF/PICT (0x00) + * - 0 + * - 0 + * - 0 + */ - if (in->buf->last - p > 0) { + p = in->buf->pos + 5; + + if (p < in->buf->last) { ngx_rtmp_mp4_data(b, p, (size_t) (in->buf->last - p)); } else { ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, diff --git a/hls/ngx_rtmp_hls_module.c b/hls/ngx_rtmp_hls_module.c index 30a538e..6a4440a 100644 --- a/hls/ngx_rtmp_hls_module.c +++ b/hls/ngx_rtmp_hls_module.c @@ -657,7 +657,7 @@ ngx_rtmp_hls_append_sps_pps(ngx_rtmp_session_t *s, ngx_buf_t *out) nnals &= 0x1f; /* 5lsb */ ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, - "h264: SPS number: %uz", nnals); + "hls: SPS number: %uz", nnals); /* SPS */ for (n = 0; ; ++n) { @@ -671,12 +671,12 @@ ngx_rtmp_hls_append_sps_pps(ngx_rtmp_session_t *s, ngx_buf_t *out) ngx_rtmp_rmemcpy(&len, &rlen, 2); ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, - "h264: header NAL length: %uz", (size_t) len); + "hls: header NAL length: %uz", (size_t) len); /* AnnexB prefix */ if (out->end - out->last < 4) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, - "h264: too small buffer for header NAL size"); + "hls: too small buffer for header NAL size"); return NGX_ERROR; } @@ -688,7 +688,7 @@ ngx_rtmp_hls_append_sps_pps(ngx_rtmp_session_t *s, ngx_buf_t *out) /* NAL body */ if (out->end - out->last < len) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, - "h264: too small buffer for header NAL"); + "hls: too small buffer for header NAL"); return NGX_ERROR; } @@ -709,7 +709,7 @@ ngx_rtmp_hls_append_sps_pps(ngx_rtmp_session_t *s, ngx_buf_t *out) } ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, - "h264: PPS number: %uz", nnals); + "hls: PPS number: %uz", nnals); } return NGX_OK; @@ -1612,40 +1612,6 @@ ngx_rtmp_hls_audio(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, } -static ngx_int_t -ngx_rtmp_hls_get_nal_bytes(ngx_rtmp_session_t *s) -{ - ngx_rtmp_codec_ctx_t *codec_ctx; - ngx_chain_t *cl; - u_char *p; - uint8_t nal_bytes; - - codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - - cl = codec_ctx->avc_header; - - p = cl->buf->pos; - - if (ngx_rtmp_hls_copy(s, NULL, &p, 9, &cl) != NGX_OK) { - return NGX_ERROR; - } - - /* NAL size length (1,2,4) */ - if (ngx_rtmp_hls_copy(s, &nal_bytes, &p, 1, &cl) != NGX_OK) { - return NGX_ERROR; - } - - nal_bytes &= 0x03; /* 2 lsb */ - - ++nal_bytes; - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, - "hls: NAL bytes: %ui", (ngx_uint_t) nal_bytes); - - return nal_bytes; -} - - static ngx_int_t ngx_rtmp_hls_video(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, ngx_chain_t *in) @@ -1660,7 +1626,7 @@ ngx_rtmp_hls_video(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, uint32_t cts; ngx_rtmp_mpegts_frame_t frame; ngx_uint_t nal_bytes; - ngx_int_t aud_sent, sps_pps_sent, rc, boundary; + ngx_int_t aud_sent, sps_pps_sent, boundary; static u_char buffer[NGX_RTMP_HLS_BUFSIZE]; hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module); @@ -1719,14 +1685,7 @@ ngx_rtmp_hls_video(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, out.pos = out.start; out.last = out.pos; - rc = ngx_rtmp_hls_get_nal_bytes(s); - if (rc < 0) { - ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, - "hls: failed to parse NAL bytes"); - return NGX_OK; - } - - nal_bytes = rc; + nal_bytes = codec_ctx->avc_nal_bytes; aud_sent = 0; sps_pps_sent = 0; diff --git a/ngx_rtmp_bitop.c b/ngx_rtmp_bitop.c new file mode 100644 index 0000000..855d425 --- /dev/null +++ b/ngx_rtmp_bitop.c @@ -0,0 +1,63 @@ + +/* + * Copyright (C) Roman Arutyunyan + */ + + +#include +#include +#include "ngx_rtmp_bitop.h" + + +void +ngx_rtmp_bit_init_reader(ngx_rtmp_bit_reader_t *br, u_char *pos, u_char *last) +{ + ngx_memzero(br, sizeof(ngx_rtmp_bit_reader_t)); + + br->pos = pos; + br->last = last; +} + + +uint64_t +ngx_rtmp_bit_read(ngx_rtmp_bit_reader_t *br, ngx_uint_t n) +{ + uint64_t v; + ngx_uint_t d; + + v = 0; + + while (n) { + + if (br->pos >= br->last) { + br->err = 1; + return 0; + } + + d = (br->offs + n > 8 ? (ngx_uint_t) (8 - br->offs) : n); + + v <<= d; + v += (*br->pos >> (8 - br->offs - d)) & ((u_char) 0xff >> (8 - d)); + + br->offs += d; + n -= d; + + if (br->offs == 8) { + br->pos++; + br->offs = 0; + } + } + + return v; +} + + +uint64_t +ngx_rtmp_bit_read_golomb(ngx_rtmp_bit_reader_t *br) +{ + ngx_uint_t n; + + for (n = 0; ngx_rtmp_bit_read(br, 1) == 0 && !br->err; n++); + + return ((uint64_t) 1 << n) + ngx_rtmp_bit_read(br, n) - 1; +} diff --git a/ngx_rtmp_bitop.h b/ngx_rtmp_bitop.h new file mode 100644 index 0000000..c954a35 --- /dev/null +++ b/ngx_rtmp_bitop.h @@ -0,0 +1,46 @@ + +/* + * Copyright (C) Roman Arutyunyan + */ + + +#ifndef _NGX_RTMP_BITOP_H_INCLUDED_ +#define _NGX_RTMP_BITOP_H_INCLUDED_ + + +#include +#include + + +typedef struct { + u_char *pos; + u_char *last; + ngx_uint_t offs; + ngx_uint_t err; +} ngx_rtmp_bit_reader_t; + + +void ngx_rtmp_bit_init_reader(ngx_rtmp_bit_reader_t *br, u_char *pos, + u_char *last); +uint64_t ngx_rtmp_bit_read(ngx_rtmp_bit_reader_t *br, ngx_uint_t n); +uint64_t ngx_rtmp_bit_read_golomb(ngx_rtmp_bit_reader_t *br); + + +#define ngx_rtmp_bit_read_err(br) ((br)->err) + +#define ngx_rtmp_bit_read_eof(br) ((br)->pos == (br)->last) + +#define ngx_rtmp_bit_read_8(br) \ + ((uint8_t) ngx_rtmp_bit_read(br, 8)) + +#define ngx_rtmp_bit_read_16(br) \ + ((uint16_t) ngx_rtmp_bit_read(br, 16)) + +#define ngx_rtmp_bit_read_32(br) \ + ((uint32_t) ngx_rtmp_bit_read(br, 32)) + +#define ngx_rtmp_bit_read_64(br) \ + ((uint64_t) ngx_rtmp_read(br, 64)) + + +#endif /* _NGX_RTMP_BITOP_H_INCLUDED_ */ diff --git a/ngx_rtmp_codec_module.c b/ngx_rtmp_codec_module.c index b795fa9..8fd26d6 100644 --- a/ngx_rtmp_codec_module.c +++ b/ngx_rtmp_codec_module.c @@ -9,6 +9,7 @@ #include "ngx_rtmp_codec_module.h" #include "ngx_rtmp_live_module.h" #include "ngx_rtmp_cmd_module.h" +#include "ngx_rtmp_bitop.h" #define NGX_RTMP_CODEC_META_OFF 0 @@ -25,6 +26,14 @@ static ngx_int_t ngx_rtmp_codec_copy_meta(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, ngx_chain_t *in); static ngx_int_t ngx_rtmp_codec_prepare_meta(ngx_rtmp_session_t *s, uint32_t timestamp); +static void ngx_rtmp_codec_parse_aac_header(ngx_rtmp_session_t *s, + ngx_chain_t *in); +static void ngx_rtmp_codec_parse_avc_header(ngx_rtmp_session_t *s, + ngx_chain_t *in); +#if (NGX_DEBUG) +static void ngx_rtmp_codec_dump_header(ngx_rtmp_session_t *s, const char *type, + ngx_chain_t *in); +#endif typedef struct { @@ -189,17 +198,9 @@ ngx_rtmp_codec_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, ngx_rtmp_codec_ctx_t *ctx; ngx_chain_t **header; uint8_t fmt; - ngx_uint_t idx; - u_char *p; static ngx_uint_t sample_rates[] = { 5512, 11025, 22050, 44100 }; - static ngx_uint_t aac_sample_rates[] = - { 96000, 88200, 64000, 48000, - 44100, 32000, 24000, 22050, - 16000, 12000, 11025, 8000, - 7350, 0, 0, 0 }; - if (h->type != NGX_RTMP_MSG_AUDIO && h->type != NGX_RTMP_MSG_VIDEO) { return NGX_OK; } @@ -221,7 +222,7 @@ ngx_rtmp_codec_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, ctx->audio_channels = (fmt & 0x01) + 1; ctx->sample_size = (fmt & 0x02) ? 2 : 1; - if (ctx->aac_sample_rate == 0) { + if (ctx->sample_rate == 0) { ctx->sample_rate = sample_rates[(fmt & 0x0c) >> 2]; } } else { @@ -240,74 +241,16 @@ ngx_rtmp_codec_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module); header = NULL; + if (h->type == NGX_RTMP_MSG_AUDIO) { if (ctx->audio_codec_id == NGX_RTMP_AUDIO_AAC) { header = &ctx->aac_header; - - if (in->buf->last - in->buf->pos > 3) { - p = in->buf->pos + 2; - - /* MPEG-4 Audio Specific Config - - 5 bits: object type - if (object type == 31) - 6 bits + 32: object type - --->4 bits: frequency index - if (frequency index == 15) - 24 bits: frequency - 4 bits: channel configuration - var bits: AOT Specific Config - */ - - if ((p[0] >> 3) == 0x1f) { - idx = (p[1] >> 1) & 0x0f; - } else { - idx = ((p[0] << 1) & 0x0f) | (p[1] >> 7); - } - -#ifdef NGX_DEBUG - { - u_char buf[256], *p, *pp; - u_char hex[] = "01234567890abcdef"; - - for (pp = buf, p = in->buf->pos; - p < in->buf->last && pp < buf + sizeof(buf) - 1; - ++p) - { - *pp++ = hex[*p >> 4]; - *pp++ = hex[*p & 0x0f]; - } - - *pp = 0; - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, - "codec: AAC header: %s", buf); - } -#endif - - ctx->aac_sample_rate = aac_sample_rates[idx]; - ctx->sample_rate = ctx->aac_sample_rate; - } - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, - "codec: aac header arrived, sample_rate=%ui", - ctx->aac_sample_rate); + ngx_rtmp_codec_parse_aac_header(s, in); } } else { if (ctx->video_codec_id == NGX_RTMP_VIDEO_H264) { header = &ctx->avc_header; - - if (in->buf->last - in->buf->pos > 8) { - p = in->buf->pos; - ctx->avc_profile = p[6]; - ctx->avc_compat = p[7]; - ctx->avc_level = p[8]; - } - - ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, - "codec: avc header arrived, " - "profile=%ui, compat=%ui, level=%ui", - ctx->avc_profile, ctx->avc_compat, ctx->avc_level); + ngx_rtmp_codec_parse_avc_header(s, in); } } @@ -325,6 +268,267 @@ ngx_rtmp_codec_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, } +static void +ngx_rtmp_codec_parse_aac_header(ngx_rtmp_session_t *s, ngx_chain_t *in) +{ + ngx_uint_t idx; + ngx_rtmp_codec_ctx_t *ctx; + ngx_rtmp_bit_reader_t br; + + static ngx_uint_t aac_sample_rates[] = + { 96000, 88200, 64000, 48000, + 44100, 32000, 24000, 22050, + 16000, 12000, 11025, 8000, + 7350, 0, 0, 0 }; + +#if (NGX_DEBUG) + ngx_rtmp_codec_dump_header(s, "aac", in); +#endif + + ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); + + ngx_rtmp_bit_init_reader(&br, in->buf->pos, in->buf->last); + + ngx_rtmp_bit_read(&br, 16); + + ctx->aac_profile = (ngx_uint_t) ngx_rtmp_bit_read(&br, 5); + + if (ctx->aac_profile == 31) { + ctx->aac_profile = (ngx_uint_t) ngx_rtmp_bit_read(&br, 6) + 32; + } + + idx = (ngx_uint_t) ngx_rtmp_bit_read(&br, 4); + + if (idx == 15) { + ctx->sample_rate = (ngx_uint_t) ngx_rtmp_bit_read(&br, 24); + } else { + ctx->sample_rate = aac_sample_rates[idx]; + } + + ctx->aac_chan_conf = (ngx_uint_t) ngx_rtmp_bit_read(&br, 4); + + /* MPEG-4 Audio Specific Config + + 5 bits: object type + if (object type == 31) + 6 bits + 32: object type + --->4 bits: frequency index + if (frequency index == 15) + 24 bits: frequency + 4 bits: channel configuration + var bits: AOT Specific Config + */ + + ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + "codec: aac header profile=%ui, " + "sample_rate=%ui, chan_conf=%ui", + ctx->aac_profile, ctx->sample_rate, ctx->aac_chan_conf); +} + + +static void +ngx_rtmp_codec_parse_avc_header(ngx_rtmp_session_t *s, ngx_chain_t *in) +{ + ngx_uint_t profile_idc, width, height, crop_left, crop_right, + crop_top, crop_bottom, frame_mbs_only, n, cf_idc, + num_ref_frames; + ngx_rtmp_codec_ctx_t *ctx; + ngx_rtmp_bit_reader_t br; + +#if (NGX_DEBUG) + ngx_rtmp_codec_dump_header(s, "avc", in); +#endif + + ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); + + ngx_rtmp_bit_init_reader(&br, in->buf->pos, in->buf->last); + + ngx_rtmp_bit_read(&br, 48); + + ctx->avc_profile = (ngx_uint_t) ngx_rtmp_bit_read_8(&br); + ctx->avc_compat = (ngx_uint_t) ngx_rtmp_bit_read_8(&br); + ctx->avc_level = (ngx_uint_t) ngx_rtmp_bit_read_8(&br); + + /* nal bytes */ + ctx->avc_nal_bytes = (ngx_uint_t) ((ngx_rtmp_bit_read_8(&br) & 0x03) + 1); + + /* nnals */ + if ((ngx_rtmp_bit_read_8(&br) & 0x1f) == 0) { + return; + } + + /* nal size */ + ngx_rtmp_bit_read(&br, 16); + + /* nal type */ + if (ngx_rtmp_bit_read_8(&br) != 0x67) { + return; + } + + /* SPS */ + + /* profile idc */ + profile_idc = (ngx_uint_t) ngx_rtmp_bit_read(&br, 8); + + /* flags */ + ngx_rtmp_bit_read(&br, 8); + + /* level idc */ + ngx_rtmp_bit_read(&br, 8); + + /* SPS id */ + ngx_rtmp_bit_read_golomb(&br); + + if (profile_idc == 100 || profile_idc == 110 || + profile_idc == 122 || profile_idc == 244 || profile_idc == 44 || + profile_idc == 83 || profile_idc == 86 || profile_idc == 118) + { + /* chroma format idc */ + cf_idc = (ngx_uint_t) ngx_rtmp_bit_read_golomb(&br); + + if (cf_idc == 3) { + + /* separate color plane */ + ngx_rtmp_bit_read(&br, 1); + } + + /* bit depth luma - 8 */ + ngx_rtmp_bit_read_golomb(&br); + + /* bit depth chroma - 8 */ + ngx_rtmp_bit_read_golomb(&br); + + /* qpprime y zero transform bypass */ + ngx_rtmp_bit_read(&br, 1); + + /* seq scaling matrix present */ + if (ngx_rtmp_bit_read(&br, 1)) { + + for (n = 0; n < (cf_idc != 3 ? 8 : 12); n++) { + + /* seq scaling list present */ + if (ngx_rtmp_bit_read(&br, 1)) { + + /* TODO: scaling_list() + if (n < 6) { + } else { + } + */ + } + } + } + } + + /* log2 max frame num */ + ngx_rtmp_bit_read_golomb(&br); + + /* pic order cnt type */ + switch (ngx_rtmp_bit_read_golomb(&br)) { + case 0: + + /* max pic order cnt */ + ngx_rtmp_bit_read_golomb(&br); + break; + + case 1: + + /* delta pic order alwys zero */ + ngx_rtmp_bit_read(&br, 1); + + /* offset for non-ref pic */ + ngx_rtmp_bit_read_golomb(&br); + + /* offset for top to bottom field */ + ngx_rtmp_bit_read_golomb(&br); + + /* num ref frames in pic order */ + num_ref_frames = ngx_rtmp_bit_read_golomb(&br); + + for (n = 0; n < num_ref_frames; n++) { + + /* offset for ref frame */ + ngx_rtmp_bit_read_golomb(&br); + } + } + + /* num ref frames */ + ctx->avc_ref_frames = ngx_rtmp_bit_read_golomb(&br); + + /* gaps in frame num allowed */ + ngx_rtmp_bit_read(&br, 1); + + /* pic width in mbs - 1 */ + width = (ngx_uint_t) ngx_rtmp_bit_read_golomb(&br); + + /* pic height in map units - 1 */ + height = (ngx_uint_t) ngx_rtmp_bit_read_golomb(&br); + + /* frame mbs only flag */ + frame_mbs_only = (ngx_uint_t) ngx_rtmp_bit_read(&br, 1); + + if (!frame_mbs_only) { + + /* mbs adaprive frame field */ + ngx_rtmp_bit_read(&br, 1); + } + + /* direct 8x8 inference flag */ + ngx_rtmp_bit_read(&br, 1); + + /* frame cropping */ + if (ngx_rtmp_bit_read(&br, 1)) { + + crop_left = (ngx_uint_t) ngx_rtmp_bit_read_golomb(&br); + crop_right = (ngx_uint_t) ngx_rtmp_bit_read_golomb(&br); + crop_top = (ngx_uint_t) ngx_rtmp_bit_read_golomb(&br); + crop_bottom = (ngx_uint_t) ngx_rtmp_bit_read_golomb(&br); + + } else { + + crop_left = 0; + crop_right = 0; + crop_top = 0; + crop_bottom = 0; + } + + ctx->width = (width + 1) * 16 - (crop_left + crop_right) * 2; + ctx->height = (2 - frame_mbs_only) * (height + 1) * 16 - + (crop_top + crop_bottom) * 2; + + ngx_log_debug7(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + "codec: avc header " + "profile=%ui, compat=%ui, level=%ui, " + "nal_bytes=%ui, ref_frames=%ui, width=%ui, height=%ui", + ctx->avc_profile, ctx->avc_compat, ctx->avc_level, + ctx->avc_nal_bytes, ctx->avc_ref_frames, + ctx->width, ctx->height); +} + + +#if (NGX_DEBUG) +static void +ngx_rtmp_codec_dump_header(ngx_rtmp_session_t *s, const char *type, + ngx_chain_t *in) +{ + u_char buf[256], *p, *pp; + u_char hex[] = "0123456789abcdef"; + + for (pp = buf, p = in->buf->pos; + p < in->buf->last && pp < buf + sizeof(buf) - 1; + ++p) + { + *pp++ = hex[*p >> 4]; + *pp++ = hex[*p & 0x0f]; + } + + *pp = 0; + + ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + "codec: %s header %s", type, buf); +} +#endif + + static ngx_int_t ngx_rtmp_codec_reconstruct_meta(ngx_rtmp_session_t *s) { diff --git a/ngx_rtmp_codec_module.h b/ngx_rtmp_codec_module.h index bb3abd6..de417da 100644 --- a/ngx_rtmp_codec_module.h +++ b/ngx_rtmp_codec_module.h @@ -58,10 +58,13 @@ typedef struct { ngx_uint_t video_codec_id; ngx_uint_t audio_data_rate; ngx_uint_t audio_codec_id; - ngx_uint_t aac_sample_rate; + ngx_uint_t aac_profile; + ngx_uint_t aac_chan_conf; ngx_uint_t avc_profile; ngx_uint_t avc_compat; ngx_uint_t avc_level; + ngx_uint_t avc_nal_bytes; + ngx_uint_t avc_ref_frames; ngx_uint_t sample_rate; /* 5512, 11025, 22050, 44100 */ ngx_uint_t sample_size; /* 1=8bit, 2=16bit */ ngx_uint_t audio_channels; /* 1, 2 */ diff --git a/ngx_rtmp_stat_module.c b/ngx_rtmp_stat_module.c index 1543d24..85dce4e 100644 --- a/ngx_rtmp_stat_module.c +++ b/ngx_rtmp_stat_module.c @@ -362,6 +362,38 @@ ngx_rtmp_stat_client(ngx_http_request_t *r, ngx_chain_t ***lll, } +static char * +ngx_rtmp_stat_get_aac_profile(ngx_uint_t p) { + switch (p) { + case 1: + return "Main"; + case 2: + return "LC"; + case 3: + return "SSR"; + case 4: + return "LTP"; + default: + return ""; + } +} + + +static char * +ngx_rtmp_stat_get_avc_profile(ngx_uint_t p) { + switch (p) { + case 66: + return "Baseline"; + case 77: + return "Main"; + case 100: + return "High"; + default: + return ""; + } +} + + static void ngx_rtmp_stat_live(ngx_http_request_t *r, ngx_chain_t ***lll, ngx_rtmp_live_app_conf_t *lacf) @@ -456,28 +488,55 @@ ngx_rtmp_stat_live(ngx_http_request_t *r, ngx_chain_t ***lll, NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%ui", codec->frame_rate) - buf); NGX_RTMP_STAT_L(""); + + NGX_RTMP_STAT_L(""); + + NGX_RTMP_STAT_L(""); + NGX_RTMP_STAT_L("\r\n"); } diff --git a/stat.xsl b/stat.xsl index 1319f5f..678bd9a 100644 --- a/stat.xsl +++ b/stat.xsl @@ -170,11 +170,12 @@ - - - +    + + +   + - @@ -322,12 +323,8 @@ active - - / - - - - / + + x