fixed pausing vod stream

This commit is contained in:
Roman Arutyunyan 2012-07-05 12:19:24 +04:00
parent 58bc83de8a
commit 26d932eb1c
2 changed files with 148 additions and 35 deletions

View file

@ -820,6 +820,11 @@ ngx_rtmp_cmd_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v)
h.csid = NGX_RTMP_CMD_CSID_AMF;
h.msid = NGX_RTMP_CMD_MSID;
/*
if (ngx_rtmp_send_user_recorded(s, NGX_RTMP_CMD_MSID) != NGX_OK) {
return NGX_ERROR;
}*/
if (ngx_rtmp_send_user_stream_begin(s, NGX_RTMP_CMD_MSID) != NGX_OK) {
return NGX_ERROR;
}
@ -985,7 +990,7 @@ ngx_rtmp_cmd_pause_init(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
}
ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"pause: pause=%i position=%i",
"cmd: pause pause=%i position=%i",
(ngx_int_t)v.pause, (ngx_int_t)v.position);
return ngx_rtmp_pause
@ -1001,7 +1006,7 @@ ngx_rtmp_cmd_pause(ngx_rtmp_session_t *s, ngx_rtmp_pause_t *v)
static double trans;
static ngx_rtmp_amf_elt_t out_inf[] = {
static ngx_rtmp_amf_elt_t out_inf[] = {
{ NGX_RTMP_AMF_STRING,
ngx_string("code"),
@ -1016,7 +1021,7 @@ ngx_rtmp_cmd_pause(ngx_rtmp_session_t *s, ngx_rtmp_pause_t *v)
"Paused.", 0 },
};
static ngx_rtmp_amf_elt_t out_elts[] = {
static ngx_rtmp_amf_elt_t out_elts[] = {
{ NGX_RTMP_AMF_STRING,
ngx_null_string,
@ -1036,13 +1041,14 @@ ngx_rtmp_cmd_pause(ngx_rtmp_session_t *s, ngx_rtmp_pause_t *v)
};
/* send onStatus reply */
memset(&h, 0, sizeof(h));
ngx_memzero(&h, sizeof(h));
h.type = NGX_RTMP_MSG_AMF_CMD;
h.csid = NGX_RTMP_CMD_CSID_AMF;
h.msid = NGX_RTMP_CMD_MSID;
if (v->pause) {
out_inf[0].data = "NetStream.Pause.Notify";
out_inf[2].data = "Paused.";
return ngx_rtmp_send_user_stream_eof(s, NGX_RTMP_CMD_MSID) != NGX_OK
|| ngx_rtmp_send_amf(s, &h, out_elts,
sizeof(out_elts) / sizeof(out_elts[0])) != NGX_OK
@ -1051,6 +1057,7 @@ ngx_rtmp_cmd_pause(ngx_rtmp_session_t *s, ngx_rtmp_pause_t *v)
}
out_inf[0].data = "NetStream.Unpause.Notify";
out_inf[2].data = "Unpaused.";
return ngx_rtmp_send_user_stream_begin(s, NGX_RTMP_CMD_MSID) != NGX_OK
|| ngx_rtmp_send_amf(s, &h, out_elts,
sizeof(out_elts) / sizeof(out_elts[0])) != NGX_OK
@ -1059,7 +1066,6 @@ ngx_rtmp_cmd_pause(ngx_rtmp_session_t *s, ngx_rtmp_pause_t *v)
}
static ngx_int_t
ngx_rtmp_cmd_disconnect(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_chain_t *in)
@ -1110,10 +1116,56 @@ ngx_rtmp_cmd_seek_init(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
static ngx_int_t
ngx_rtmp_cmd_seek(ngx_rtmp_session_t *s, ngx_rtmp_seek_t *v)
{
ngx_rtmp_send_user_stream_eof(s, NGX_RTMP_CMD_MSID);
ngx_rtmp_send_user_stream_begin(s, NGX_RTMP_CMD_MSID);
ngx_rtmp_header_t h;
return NGX_OK;
static double trans;
static ngx_rtmp_amf_elt_t out_inf[] = {
{ NGX_RTMP_AMF_STRING,
ngx_string("code"),
"NetStream.Play.Reset", 0 },
{ NGX_RTMP_AMF_STRING,
ngx_string("level"),
"status", 0 },
{ NGX_RTMP_AMF_STRING,
ngx_string("description"),
"Paused.", 0 },
};
static ngx_rtmp_amf_elt_t out_elts[] = {
{ NGX_RTMP_AMF_STRING,
ngx_null_string,
"onStatus", 0 },
{ NGX_RTMP_AMF_NUMBER,
ngx_null_string,
&trans, 0 },
{ NGX_RTMP_AMF_NULL,
ngx_null_string,
NULL, 0 },
{ NGX_RTMP_AMF_OBJECT,
ngx_null_string,
out_inf, sizeof(out_inf) },
};
/* send onStatus reply */
ngx_memzero(&h, sizeof(h));
h.type = NGX_RTMP_MSG_AMF_CMD;
h.csid = NGX_RTMP_CMD_CSID_AMF;
h.msid = NGX_RTMP_CMD_MSID;
return (ngx_rtmp_send_user_stream_eof(s, NGX_RTMP_CMD_MSID) != NGX_OK
|| ngx_rtmp_send_user_stream_begin(s, NGX_RTMP_CMD_MSID) != NGX_OK
|| ngx_rtmp_send_amf(s, &h, out_elts,
sizeof(out_elts) / sizeof(out_elts[0])) != NGX_OK)
? NGX_ERROR
: NGX_OK;
}
@ -1134,6 +1186,7 @@ static ngx_rtmp_amf_handler_t ngx_rtmp_cmd_map[] = {
{ ngx_string("seek"), ngx_rtmp_cmd_seek_init },
{ ngx_string("pause"), ngx_rtmp_cmd_pause_init },
{ ngx_string("pauseraw"), ngx_rtmp_cmd_pause_init },
};

View file

@ -10,6 +10,7 @@
static ngx_rtmp_play_pt next_play;
static ngx_rtmp_close_stream_pt next_close_stream;
static ngx_rtmp_seek_pt next_seek;
static ngx_rtmp_pause_pt next_pause;
static ngx_int_t ngx_rtmp_play_postconfiguration(ngx_conf_t *cf);
@ -17,6 +18,8 @@ static void * ngx_rtmp_play_create_app_conf(ngx_conf_t *cf);
static char * ngx_rtmp_play_merge_app_conf(ngx_conf_t *cf,
void *parent, void *child);
static void ngx_rtmp_play_send(ngx_event_t *e);
static ngx_int_t ngx_rtmp_play_restart(ngx_rtmp_session_t *s, uint32_t);
static ngx_int_t ngx_rtmp_play_stop(ngx_rtmp_session_t *s);
typedef struct {
@ -125,18 +128,12 @@ ngx_rtmp_play_close_stream(ngx_rtmp_session_t *s, ngx_rtmp_close_stream_t *v)
goto next;
}
ngx_rtmp_play_stop(s);
if (ctx->file.fd != NGX_INVALID_FILE) {
ngx_close_file(ctx->file.fd);
}
if (ctx->write_evt.timer_set) {
ngx_del_timer(&ctx->write_evt);
}
if (ctx->write_evt.prev) {
ngx_delete_posted_event((&ctx->write_evt));
}
next:
return next_close_stream(s, v);
}
@ -146,13 +143,39 @@ static ngx_int_t
ngx_rtmp_play_restart(ngx_rtmp_session_t *s, uint32_t offset)
{
ngx_rtmp_play_ctx_t *ctx;
ngx_rtmp_play_app_conf_t *pacf;
pacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_play_module);
if (pacf == NULL) {
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_play_module);
if (ctx == NULL) {
return NGX_OK;
}
ngx_rtmp_play_stop(s);
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"play: restart offset=%D", offset);
/*TODO: lookup metadata keyframe map
* for start_timestamp/ctx->offset */
ctx->offset = 13; /* header + zero tag size */
ctx->epoch = ngx_current_msec;
ctx->start_timestamp = offset;
ctx->msg_mask = 0;
if (offset) {
ctx->key_seeking = 1;
}
ngx_post_event((&ctx->write_evt), &ngx_posted_events)
return NGX_OK;
}
static ngx_int_t
ngx_rtmp_play_stop(ngx_rtmp_session_t *s)
{
ngx_rtmp_play_ctx_t *ctx;
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_play_module);
if (ctx == NULL) {
return NGX_OK;
@ -166,21 +189,8 @@ ngx_rtmp_play_restart(ngx_rtmp_session_t *s, uint32_t offset)
ngx_delete_posted_event((&ctx->write_evt));
}
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"play: starting at offset=%D", offset);
/*TODO: lookup metadata keyframe map
* for start_timestamp/ctx->offset */
ctx->offset = 13; /* header + zero tag size */
ctx->epoch = ngx_current_msec;
ctx->start_timestamp = offset;
ctx->msg_mask = 0;
if (offset) {
ctx->key_seeking = 1;
}
ngx_post_event((&ctx->write_evt), &ngx_posted_events)
ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"play: stop");
return NGX_OK;
}
@ -202,6 +212,9 @@ ngx_rtmp_play_seek(ngx_rtmp_session_t *s, ngx_rtmp_seek_t *v)
goto next;
}
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"play: seek offset=%i", (ngx_int_t) v->offset);
ngx_rtmp_play_restart(s, v->offset);
next:
@ -209,6 +222,41 @@ next:
}
static ngx_int_t
ngx_rtmp_play_pause(ngx_rtmp_session_t *s, ngx_rtmp_pause_t *v)
{
ngx_rtmp_play_ctx_t *ctx;
ngx_rtmp_play_app_conf_t *pacf;
pacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_play_module);
if (pacf == NULL) {
goto next;
}
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_play_module);
if (ctx == NULL) {
goto next;
}
if (ctx->file.fd == NGX_INVALID_FILE) {
goto next;
}
ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"play: pause pause=%i position=%i",
(ngx_int_t) v->pause, (ngx_int_t) v->position);
if (v->pause) {
ngx_rtmp_play_stop(s);
} else {
ngx_rtmp_play_restart(s, v->position);
}
next:
return next_pause(s, v);
}
static void
ngx_rtmp_play_send(ngx_event_t *e)
{
@ -241,6 +289,7 @@ ngx_rtmp_play_send(ngx_event_t *e)
if (n != sizeof(header)) {
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
"play: could not read flv tag header");
ngx_rtmp_send_user_stream_eof(s, 1);
if (ctx->msg_mask == 0) {
ngx_rtmp_play_restart(s, 0);
}
@ -358,6 +407,12 @@ next:
end_timestamp = (ngx_current_msec - ctx->epoch) +
ctx->start_timestamp + buflen;
ngx_log_debug5(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"play: %s wait=%D timestamp=%D end_timestamp=%D bufen=%i",
h.timestamp > end_timestamp ? "schedule" : "advance",
h.timestamp > end_timestamp ? h.timestamp - end_timestamp : 0,
h.timestamp, end_timestamp, (ngx_int_t) buflen);
/* too much data sent; schedule timeout */
if (h.timestamp > end_timestamp) {
ctx->offset += (size + 4);
@ -435,7 +490,9 @@ ngx_rtmp_play_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v)
ctx->meta_seeking = 1;
ngx_rtmp_play_restart(s, v->start);
ngx_rtmp_send_user_recorded(s, 1);
ngx_rtmp_play_restart(s, v->start < 0 ? 0 : v->start);
next:
return next_play(s, v);
@ -454,5 +511,8 @@ ngx_rtmp_play_postconfiguration(ngx_conf_t *cf)
next_seek = ngx_rtmp_seek;
ngx_rtmp_seek = ngx_rtmp_play_seek;
next_pause = ngx_rtmp_pause;
ngx_rtmp_pause = ngx_rtmp_play_pause;
return NGX_OK;
}