static ngx_int_t
ngx_rtmp_play_close_stream(ngx_rtmp_session_t *s, ngx_rtmp_close_stream_t *v)
{
    ngx_rtmp_play_ctx_t        *ctx;

    ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_play_module);
    if (ctx == NULL) {
        goto next;
    }

    ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
                   "play: close_stream");

    ngx_rtmp_play_do_stop(s);

    ngx_rtmp_play_do_done(s);

    if (ctx->file.fd != NGX_INVALID_FILE) {
        ngx_close_file(ctx->file.fd);
        ctx->file.fd = NGX_INVALID_FILE;

        ngx_rtmp_send_stream_eof(s, NGX_RTMP_MSID);

        ngx_rtmp_send_status(s, "NetStream.Play.Stop", "status",
                             "Stop video on demand");
    }

    if (ctx->file_id) {
        ngx_rtmp_play_cleanup_local_file(s);
    }

next:
    return next_close_stream(s, v);
}
static void
ngx_rtmp_play_copy_local_file(ngx_rtmp_session_t *s, u_char *name)
{
    ngx_rtmp_play_app_conf_t   *pacf;
    ngx_rtmp_play_ctx_t        *ctx;
    u_char                     *path, *p;
    static u_char               dpath[NGX_MAX_PATH + 1];

    pacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_play_module);
    if (pacf == NULL) {
        return;
    }

    ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_play_module);
    if (ctx == NULL || ctx->file_id == 0) {
        return;
    }

    path = ngx_rtmp_play_get_local_file_path(s);

    p = ngx_snprintf(dpath, NGX_MAX_PATH, "%V/%s%V", &pacf->local_path,
                     name + ctx->pfx_size, &ctx->sfx);
    *p = 0;

    ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
                   "play: copy local file '%s' to '%s'", path, dpath);

    if (ngx_rename_file(path, dpath) == 0) {
        ctx->file_id = 0;
        return;
    }

    ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
                  "play: error copying local file '%s' to '%s'",
                  path, dpath);

    ngx_rtmp_play_cleanup_local_file(s);
}
static ngx_int_t
ngx_rtmp_play_next_entry(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v)
{
    ngx_rtmp_play_app_conf_t   *pacf;
    ngx_rtmp_core_srv_conf_t   *cscf;
    ngx_rtmp_play_ctx_t        *ctx;
    ngx_rtmp_play_entry_t      *pe;
    u_char                     *p;
    static u_char               path[NGX_MAX_PATH + 1];

    pacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_play_module);
    cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module);

    ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_play_module);

    for ( ;; ) {

        if (ctx->file.fd != NGX_INVALID_FILE) {
            ngx_close_file(ctx->file.fd);
            ctx->file.fd = NGX_INVALID_FILE;
        }

        if (ctx->file_id) {
            ngx_rtmp_play_cleanup_local_file(s);
        }

        ctx->nentry = (ctx->nentry == NGX_CONF_UNSET_UINT ?
                       0 : ctx->nentry + 1);

        if (ctx->nentry >= pacf->entries.nelts) {
            ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
                           "play: all entries failed");

            ngx_rtmp_send_status(s, "NetStream.Play.StreamNotFound", "error",
                                 "Video on demand stream not found");
            break;
        }

        pe = ngx_rtmp_play_get_current_entry(s);

        ngx_log_debug4(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
                       "play: trying %s entry %ui/%uz '%V'",
                       pe->url ? "remote" : "local",
                       ctx->nentry + 1, pacf->entries.nelts,
                       pe->url ? &pe->url->url : pe->root);

        /* open remote */

        if (pe->url) {
            return ngx_rtmp_play_open_remote(s, v);
        }

        /* open local */

        p = ngx_snprintf(path, NGX_MAX_PATH, "%V/%s%V",
                         pe->root, v->name + ctx->pfx_size, &ctx->sfx);
        *p = 0;

        ctx->file.fd = ngx_open_file(path, NGX_FILE_RDONLY, NGX_FILE_OPEN,
                                     cscf->file_access);

        if (ctx->file.fd == NGX_INVALID_FILE) {
            ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, ngx_errno,
                           "play: error opening file '%s'", path);
            continue;
        }

        ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
                       "play: open local file '%s'", path);

        if (ngx_rtmp_play_open(s, v->start) != NGX_OK) {
            return NGX_ERROR;
        }

        break;
    }

    return next_play(s, v);
}