Skip to content

Commit

Permalink
improved publishing & subscribing: now subscriber receives some data …
Browse files Browse the repository at this point in the history
…which looks like real video
  • Loading branch information
arut committed Mar 15, 2012
1 parent 17a3d36 commit 65cc92e
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 71 deletions.
2 changes: 2 additions & 0 deletions TODO
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
- implement chain-reuse for output

- get rid of greedy send_chain

- remove macros hell from ngx_rtmp_send.c

- packet dropping
Expand Down
8 changes: 7 additions & 1 deletion ngx_rtmp.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,9 @@ typedef struct ngx_rtmp_session_s {

ngx_str_t *addr_text;

ngx_buf_t hs_buf;
/* TODO: allocate this bufs from shared pool */
ngx_buf_t hs_in_buf;
ngx_buf_t hs_out_buf;
ngx_uint_t hs_stage;

/* connection timestamps */
Expand All @@ -190,6 +192,8 @@ typedef struct ngx_rtmp_session_s {
uint32_t in_csid;
ngx_uint_t in_chunk_size;
ngx_pool_t *in_pool;
uint32_t in_bytes;
uint32_t in_last_ack;

ngx_chain_t *out;
} ngx_rtmp_session_t;
Expand Down Expand Up @@ -217,6 +221,8 @@ typedef struct {
ngx_msec_t timeout;
ngx_flag_t so_keepalive;
ngx_int_t max_streams;

ngx_uint_t ack_window;

ngx_int_t out_chunk_size;
ngx_pool_t *out_pool;
Expand Down
52 changes: 43 additions & 9 deletions ngx_rtmp_broadcast_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ ngx_module_t ngx_rtmp_broadcast_module = {

#define NGX_RTMP_BROADCAST_PUBLISHER 0x01
#define NGX_RTMP_BROADCAST_SUBSCRIBER 0x02
#define NGX_RTMP_BROADCAST_WANT_KEYFRAME 0x04


typedef struct ngx_rtmp_broadcast_ctx_s {
Expand Down Expand Up @@ -223,6 +224,18 @@ ngx_rtmp_broadcast_leave(ngx_rtmp_session_t *s)
}


#define NGX_RTMP_VIDEO_KEY_FRAME 1
#define NGX_RTMP_VIDEO_INTER_FRAME 2
#define NGX_RTMP_VIDEO_DISPOSABLE_FRAME 3


static ngx_int_t
ngx_rtmp_get_video_frame_type(ngx_chain_t *in)
{
return (in->buf->pos[0] & 0xf0) >> 4;
}


static ngx_int_t
ngx_rtmp_broadcast_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_chain_t *in)
Expand All @@ -232,13 +245,16 @@ ngx_rtmp_broadcast_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_chain_t *out, *l, **ll;
u_char *p;
size_t nsubs, size;
ngx_int_t vftype;

c = s->connection;

ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_broadcast_module);

/*
h->timestamp -= s->peer_epoch;
h->timestamp += s->epoch;
*/

if (ctx == NULL
|| !(ctx->flags & NGX_RTMP_BROADCAST_PUBLISHER))
Expand All @@ -252,6 +268,11 @@ ngx_rtmp_broadcast_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
return NGX_OK;
}

vftype = 0;
if (h->type == NGX_RTMP_MSG_VIDEO) {
vftype = ngx_rtmp_get_video_frame_type(in);
}

/* copy data to output stream */
out = NULL;
ll = &out;
Expand Down Expand Up @@ -297,6 +318,14 @@ ngx_rtmp_broadcast_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
&& !ngx_strncmp(cctx->stream.data, ctx->stream.data,
ctx->stream.len))
{
if (h->type == NGX_RTMP_MSG_VIDEO
&& cctx->flags & NGX_RTMP_BROADCAST_WANT_KEYFRAME)
{
if (vftype && vftype != NGX_RTMP_VIDEO_KEY_FRAME) {
continue;
}
cctx->flags &= ~NGX_RTMP_BROADCAST_WANT_KEYFRAME;
}
if (ngx_rtmp_send_message(cctx->session, out) != NGX_OK) {
return NGX_ERROR;
}
Expand All @@ -319,11 +348,13 @@ static ngx_int_t
ngx_rtmp_broadcast_connect(ngx_rtmp_session_t *s, double in_trans,
ngx_chain_t *in)
{
static double trans;
static u_char app[1024];
static u_char url[1024];
static u_char acodecs[1024];
static ngx_str_t app_str;
ngx_rtmp_core_srv_conf_t *cscf;

static double trans;
static u_char app[1024];
static u_char url[1024];
static u_char acodecs[1024];
static ngx_str_t app_str;

static ngx_rtmp_amf0_elt_t in_cmd[] = {
{ NGX_RTMP_AMF0_STRING, "app", app, sizeof(app) },
Expand Down Expand Up @@ -354,6 +385,8 @@ ngx_rtmp_broadcast_connect(ngx_rtmp_session_t *s, double in_trans,
return NGX_ERROR;
}

cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module);

trans = in_trans;
ngx_str_set(&out_inf[0], "NetConnection.Connect.Success");
ngx_str_set(&out_inf[1], "status");
Expand All @@ -373,8 +406,8 @@ ngx_rtmp_broadcast_connect(ngx_rtmp_session_t *s, double in_trans,
*/
ngx_rtmp_broadcast_join(s, &app_str, 0);

return ngx_rtmp_send_ack_size(s, 2500000)
|| ngx_rtmp_send_bandwidth(s, 2500000, NGX_RTMP_LIMIT_DYNAMIC)
return ngx_rtmp_send_ack_size(s, cscf->ack_window)
|| ngx_rtmp_send_bandwidth(s, cscf->ack_window, NGX_RTMP_LIMIT_SOFT)
|| ngx_rtmp_send_user_stream_begin(s, 0)
|| ngx_rtmp_send_amf0(s, 3, 0, out_elts,
sizeof(out_elts) / sizeof(out_elts[0]))
Expand Down Expand Up @@ -498,10 +531,11 @@ ngx_rtmp_broadcast_play(ngx_rtmp_session_t *s, double in_trans,
}

ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"publish() called; pubName='%s' pubType='%s'",
"play() called; pubName='%s' pubType='%s'",
pub_name, pub_type);

ngx_rtmp_broadcast_set_flags(s, NGX_RTMP_BROADCAST_SUBSCRIBER);
ngx_rtmp_broadcast_set_flags(s, NGX_RTMP_BROADCAST_SUBSCRIBER
| NGX_RTMP_BROADCAST_WANT_KEYFRAME);

trans = in_trans;
ngx_str_set(&out_inf[0], "NetStream.Play.Start");
Expand Down
9 changes: 9 additions & 0 deletions ngx_rtmp_core_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ static ngx_command_t ngx_rtmp_core_commands[] = {
offsetof(ngx_rtmp_core_srv_conf_t, max_streams),
NULL },

{ ngx_string("ack_window"),
NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
NGX_RTMP_SRV_CONF_OFFSET,
offsetof(ngx_rtmp_core_srv_conf_t, ack_window),
NULL },

{ ngx_string("out_chunk_size"),
NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
Expand Down Expand Up @@ -141,6 +148,7 @@ ngx_rtmp_core_create_srv_conf(ngx_conf_t *cf)
conf->so_keepalive = NGX_CONF_UNSET;
conf->max_streams = NGX_CONF_UNSET;
conf->out_chunk_size = NGX_CONF_UNSET;
conf->ack_window = NGX_CONF_UNSET;

return conf;
}
Expand All @@ -157,6 +165,7 @@ ngx_rtmp_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_value(conf->so_keepalive, prev->so_keepalive, 0);
ngx_conf_merge_value(conf->max_streams, prev->max_streams, 16);
ngx_conf_merge_value(conf->out_chunk_size, prev->out_chunk_size, 128);
ngx_conf_merge_uint_value(conf->ack_window, prev->ack_window, 5000000);

if (prev->out_pool == NULL) {
prev->out_pool = ngx_create_pool(4096, cf->log);
Expand Down
Loading

0 comments on commit 65cc92e

Please sign in to comment.