static ngx_int_t ngx_rtmp_play_seek(ngx_rtmp_session_t *s, ngx_rtmp_seek_t *v) { ngx_rtmp_play_ctx_t *ctx; ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_play_module); if (ctx == NULL || ctx->file.fd == NGX_INVALID_FILE) { goto next; } ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "play: seek offset=%f", v->offset); ngx_rtmp_play_start(s, v->offset); next: return next_seek(s, v); }
static ngx_int_t ngx_rtmp_play_pause(ngx_rtmp_session_t *s, ngx_rtmp_pause_t *v) { ngx_rtmp_play_ctx_t *ctx; ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_play_module); if (ctx == NULL || ctx->file.fd == NGX_INVALID_FILE) { goto next; } ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "play: pause=%i timestamp=%i", (ngx_int_t) v->pause, (ngx_int_t) v->position); if (v->pause) { ngx_rtmp_play_stop(s); } else { ngx_rtmp_play_start(s, v->position); } next: return next_pause(s, v); }
static ngx_int_t ngx_rtmp_play_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v) { ngx_rtmp_play_main_conf_t *pmcf; ngx_rtmp_play_app_conf_t *pacf; ngx_rtmp_play_ctx_t *ctx; u_char *p; ngx_event_t *e; ngx_rtmp_play_fmt_t *fmt, **pfmt; ngx_str_t *pfx, *sfx; ngx_str_t name; ngx_uint_t n; static ngx_str_t nosfx; static u_char path[NGX_MAX_PATH]; pmcf = ngx_rtmp_get_module_main_conf(s, ngx_rtmp_play_module); pacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_play_module); if (pacf == NULL || pacf->root.len == 0) { goto next; } ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "play: play name='%s' timestamp=%i", v->name, (ngx_int_t) v->start); ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_play_module); if (ctx && ctx->file.fd != NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "play: already playing"); goto next; } /* check for double-dot in v->name; * we should not move out of play directory */ for (p = v->name; *p; ++p) { if (ngx_path_separator(p[0]) && p[1] == '.' && p[2] == '.' && ngx_path_separator(p[3])) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "play: bad name '%s'", v->name); return NGX_ERROR; } } if (ctx == NULL) { ctx = ngx_palloc(s->connection->pool, sizeof(ngx_rtmp_play_ctx_t)); ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_play_module); } ngx_memzero(ctx, sizeof(*ctx)); ctx->file.log = s->connection->log; name.len = ngx_strlen(v->name); name.data = v->name; pfmt = pmcf->fmts.elts; for (n = 0; n < pmcf->fmts.nelts; ++n, ++pfmt) { fmt = *pfmt; pfx = &fmt->pfx; sfx = &fmt->sfx; if (pfx->len == 0 && ctx->fmt == NULL) { ctx->fmt = fmt; } if (pfx->len && name.len >= pfx->len && ngx_strncasecmp(pfx->data, name.data, pfx->len) == 0) { name.data += pfx->len; name.len -= pfx->len; ctx->fmt = fmt; break; } if (name.len >= sfx->len && ngx_strncasecmp(sfx->data, name.data + name.len - sfx->len, sfx->len) == 0) { ctx->fmt = fmt; } } if (ctx->fmt == NULL) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "play: fmt not found"); goto next; } ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "play: fmt found: '%V'", &ctx->fmt->name); sfx = &ctx->fmt->sfx; if (name.len >= sfx->len && ngx_strncasecmp(sfx->data, name.data + name.len - sfx->len, sfx->len) == 0) { sfx = &nosfx; } p = ngx_snprintf(path, sizeof(path), "%V/%V%V", &pacf->root, &name, sfx); *p = 0; ctx->file.fd = ngx_open_file(path, NGX_FILE_RDONLY, NGX_FILE_OPEN, NGX_FILE_DEFAULT_ACCESS); if (ctx->file.fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "play: error opening file '%s'", path); return NGX_ERROR; } ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "play: opened file '%s'", path); e = &ctx->send_evt; e->data = s; e->handler = ngx_rtmp_play_send; e->log = s->connection->log; ngx_rtmp_send_user_recorded(s, 1); if (ngx_rtmp_play_init(s) != NGX_OK) { return NGX_ERROR; } if (ngx_rtmp_play_start(s, v->start) != NGX_OK) { return NGX_ERROR; } next: return next_play(s, v); }
static ngx_int_t ngx_rtmp_play_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v) { ngx_rtmp_play_app_conf_t *pacf; ngx_rtmp_play_ctx_t *ctx; u_char *p; ngx_event_t *e; size_t len, slen; static u_char path[NGX_MAX_PATH]; pacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_play_module); if (pacf == NULL || pacf->root.len == 0) { goto next; } ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "play: play name='%s' timestamp=%i", v->name, (ngx_int_t) v->start); ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_play_module); if (ctx && ctx->file.fd != NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "play: already playing"); goto next; } /* check for double-dot in v->name; * we should not move out of play directory */ p = v->name; while (*p) { if (*p == '.' && *(p + 1) == '.') { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "play: bad name '%s'", v->name); return NGX_ERROR; } ++p; } if (ctx == NULL) { ctx = ngx_palloc(s->connection->pool, sizeof(ngx_rtmp_play_ctx_t)); ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_play_module); } ngx_memzero(ctx, sizeof(*ctx)); ctx->file.log = s->connection->log; /* make file path */ len = ngx_strlen(v->name); slen = sizeof(".flv") - 1; p = ngx_snprintf(path, sizeof(path), "%V/%s%s", &pacf->root, v->name, len > slen && ngx_strncasecmp((u_char *) ".flv", v->name + len - slen, slen) == 0 ? "" : ".flv"); *p = 0; /* open file */ ctx->file.fd = ngx_open_file(path, NGX_FILE_RDONLY, NGX_FILE_OPEN, NGX_FILE_DEFAULT_ACCESS); if (ctx->file.fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "play: error opening file %s", path); goto next; } ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "play: opened file '%s'", path); e = &ctx->write_evt; e->data = s; e->handler = ngx_rtmp_play_send; e->log = s->connection->log; ngx_rtmp_send_user_recorded(s, 1); ngx_rtmp_play_start(s, v->start); next: return next_play(s, v); }