mirror of
https://github.com/zotanmew/nginx-rtmp-module.git
synced 2024-05-09 14:11:07 +02:00
implement ext timestamp fix to make flash client recognize 32-bit timestamps
This commit is contained in:
parent
7b70e92413
commit
e563c3146e
4
TODO
4
TODO
|
@ -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)
|
||||
|
||||
|
|
BIN
doc/video_file_format_spec_v10.pdf
Normal file
BIN
doc/video_file_format_spec_v10.pdf
Normal file
Binary file not shown.
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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*)×tamp;
|
||||
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue