implement ext timestamp fix to make flash client recognize 32-bit timestamps

This commit is contained in:
Roman Arutyunyan 2012-03-22 01:00:52 +04:00
parent 7b70e92413
commit e563c3146e
7 changed files with 94 additions and 21 deletions

4
TODO
View file

@ -3,11 +3,11 @@
- add HTTP callbacks for all calls
- support client chunk size change
- check compilation with IPv6 enabled
- remove macros hell from ngx_rtmp_send.c
- fix broken data_frame(?)
- fix time wrapping problem (% 0x00ffffff)

Binary file not shown.

View file

@ -245,6 +245,8 @@ typedef struct ngx_rtmp_core_srv_conf_s {
size_t max_buf;
size_t max_message;
ngx_flag_t wait_key_frame;
ngx_flag_t play_time_fix;
ngx_flag_t publish_time_fix;
ngx_rtmp_conf_ctx_t *ctx;
} ngx_rtmp_core_srv_conf_t;

View file

@ -33,6 +33,8 @@ static ngx_int_t ngx_rtmp_broadcast_set_data_frame(ngx_rtmp_session_t *s,
ngx_rtmp_header_t *h, ngx_chain_t *in);
static ngx_int_t ngx_rtmp_broadcast_ok(ngx_rtmp_session_t *s,
ngx_rtmp_header_t *h, ngx_chain_t *in);
static ngx_int_t ngx_rtmp_broadcast_stream_length(ngx_rtmp_session_t *s,
ngx_rtmp_header_t *h, ngx_chain_t *in);
static ngx_rtmp_amf0_handler_t ngx_rtmp_broadcast_map[] = {
@ -42,6 +44,7 @@ static ngx_rtmp_amf0_handler_t ngx_rtmp_broadcast_map[] = {
{ ngx_string("play"), ngx_rtmp_broadcast_play },
{ ngx_string("-@setDataFrame"), ngx_rtmp_broadcast_set_data_frame },
{ ngx_string("releaseStream"), ngx_rtmp_broadcast_ok },
{ ngx_string("getStreamLength"), ngx_rtmp_broadcast_stream_length },
{ ngx_string("FCPublish"), ngx_rtmp_broadcast_ok },
{ ngx_string("FCSubscribe"), ngx_rtmp_broadcast_ok },
};
@ -265,7 +268,7 @@ ngx_rtmp_broadcast_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_broadcast_module);
memset(&sh, 0, sizeof(sh));
sh.timestamp = h->timestamp + s->epoch;
sh.timestamp = (h->timestamp + s->epoch);/* & 0x00ffffff*/; /*FIXME*/
sh.msid = NGX_RTMP_BROADCAST_MSID;
sh.type = h->type;
@ -755,6 +758,43 @@ ngx_rtmp_broadcast_ok(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
}
static ngx_int_t
ngx_rtmp_broadcast_stream_length(ngx_rtmp_session_t *s,
ngx_rtmp_header_t *h, ngx_chain_t *in)
{
ngx_rtmp_header_t sh;
static double trans;
static double length;
static ngx_rtmp_amf0_elt_t in_elts[] = {
{ NGX_RTMP_AMF0_NUMBER, 0, &trans, sizeof(trans) },
};
static ngx_rtmp_amf0_elt_t out_elts[] = {
{ NGX_RTMP_AMF0_STRING, NULL, "_result", 0 },
{ NGX_RTMP_AMF0_NUMBER, NULL, &trans, 0 },
{ NGX_RTMP_AMF0_NUMBER, NULL, &length, 0 },
};
/* parse input */
if (ngx_rtmp_receive_amf0(s, in, in_elts,
sizeof(in_elts) / sizeof(in_elts[0])))
{
return NGX_ERROR;
}
memset(&sh, 0, sizeof(sh));
sh.csid = h->csid;
sh.type = NGX_RTMP_MSG_AMF0_CMD;
sh.msid = 0;
/* send simple _result */
return ngx_rtmp_send_amf0(s, &sh, out_elts,
sizeof(out_elts) / sizeof(out_elts[0]));
}
static ngx_int_t
ngx_rtmp_broadcast_postconfiguration(ngx_conf_t *cf)
{

View file

@ -98,6 +98,21 @@ static ngx_command_t ngx_rtmp_core_commands[] = {
offsetof(ngx_rtmp_core_srv_conf_t, wait_key_frame),
NULL },
/* time fixes are needed for flash clients */
{ ngx_string("play_time_fix"),
NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_CONF_TAKE1,
ngx_conf_set_flag_slot,
NGX_RTMP_SRV_CONF_OFFSET,
offsetof(ngx_rtmp_core_srv_conf_t, play_time_fix),
NULL },
{ ngx_string("publish_time_fix"),
NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_CONF_TAKE1,
ngx_conf_set_flag_slot,
NGX_RTMP_SRV_CONF_OFFSET,
offsetof(ngx_rtmp_core_srv_conf_t, publish_time_fix),
NULL },
ngx_null_command
};
@ -173,6 +188,8 @@ ngx_rtmp_core_create_srv_conf(ngx_conf_t *cf)
conf->max_buf = NGX_CONF_UNSET;
conf->max_message = NGX_CONF_UNSET;
conf->wait_key_frame = NGX_CONF_UNSET;
conf->play_time_fix = NGX_CONF_UNSET;
conf->publish_time_fix = NGX_CONF_UNSET;
return conf;
}
@ -193,6 +210,8 @@ ngx_rtmp_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_size_value(conf->max_buf, prev->max_buf, 128 * 1024);
ngx_conf_merge_size_value(conf->max_message, prev->max_message, 1024 * 1024);
ngx_conf_merge_value(conf->wait_key_frame, prev->wait_key_frame, 1);
ngx_conf_merge_value(conf->play_time_fix, prev->play_time_fix, 1);
ngx_conf_merge_value(conf->publish_time_fix, prev->publish_time_fix, 1);
if (prev->pool == NULL) {
prev->pool = ngx_create_pool(8192, cf->log);

View file

@ -281,7 +281,7 @@ ngx_rtmp_get_timestamp()
tod = ngx_timeofday();
/* FIXME: divisor */
return (uint32_t)(tod->sec * 1000 + tod->msec) % 0x00ffffff;
return (uint32_t)(tod->sec * 1000 + tod->msec) /*& 0x00ffffff*/;
}
@ -471,8 +471,6 @@ restart:
ngx_rtmp_handshake_recv(c->read);
}
ngx_chain_t * tmp;
void
ngx_rtmp_recv(ngx_event_t *rev)
@ -681,9 +679,16 @@ ngx_rtmp_recv(ngx_event_t *rev)
pp[3] = *p++;
}
}
}
/* extended header */
if (timestamp == 0x00ffffff) {
/* extended header */
if (timestamp >= 0x00ffffff) {
/* Messages with type=3 should
* never have ext timestamp field
* according to standard.
* However that's not always the case
* in real life */
if (fmt <= 2 || cscf->publish_time_fix) {
if (b->last - p < 4)
continue;
pp = (u_char*)&timestamp;
@ -692,11 +697,12 @@ ngx_rtmp_recv(ngx_event_t *rev)
pp[1] = *p++;
pp[0] = *p++;
}
if (fmt) {
h->timestamp += timestamp;
} else {
h->timestamp = timestamp;
}
}
if (fmt == 1 || fmt == 2) {
h->timestamp += timestamp;
} else {
h->timestamp = timestamp;
}
ngx_log_debug6(NGX_LOG_DEBUG_RTMP, c->log, 0,
@ -705,11 +711,6 @@ ngx_rtmp_recv(ngx_event_t *rev)
ngx_rtmp_message_type(h->type), (int)h->type,
h->timestamp, h->mlen, st->len, h->msid);
if (h->mlen==51441 && st->len==20864) {
/*asm("int $0x03");*/
tmp = in;
}
/* header done */
b->pos = p;
@ -876,7 +877,7 @@ ngx_rtmp_prepare_message(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_int_t hsize, thsize, nbufs;
uint32_t mlen, timestamp, ext_timestamp;
static uint8_t hdrsize[] = { 12, 8, 4, 1 };
u_char th[3];
u_char th[7];
ngx_rtmp_core_srv_conf_t *cscf;
uint8_t fmt;
ngx_connection_t *c;
@ -992,6 +993,15 @@ ngx_rtmp_prepare_message(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
*p++ = pp[2];
*p++ = pp[1];
*p++ = pp[0];
/* This CONTRADICTS the standard
* but that's the way flash client
* wants data to be encoded;
* ffmpeg complains */
if (cscf->play_time_fix) {
ngx_memcpy(&th[thsize], p - 4, 4);
thsize += 4;
}
}
/* append headers to successive fragments */

View file

@ -20,13 +20,15 @@ rtmp {
listen 1935;
# wait_key_frame on;
#wait_key_frame on;
chunk_size 128;
max_buf 1000000;
#allow play all;
#timestamp_fix on;
#allow play all;
allow publish 127.0.0.1;