예제 #1
0
int SrsHttpVhost::response_ts_file(SrsStSocket* skt, SrsHttpMessage* req, string fullpath)
{
    int ret = ERROR_SUCCESS;
    
    SrsFileReader fs;
    
    // TODO: FIXME: use more advance cache.
    if ((ret = fs.open(fullpath)) != ERROR_SUCCESS) {
        srs_warn("open file %s failed, ret=%d", fullpath.c_str(), ret);
        return ret;
    }

    int64_t length = fs.filesize();

    // write http header for ts.
    std::stringstream ss;

    res_status_line(ss)->res_content_type_mpegts(ss)
        ->res_content_length(ss, (int)length);
        
    if (req->requires_crossdomain()) {
        res_enable_crossdomain(ss);
    }
    
    res_header_eof(ss);
    
    // flush http header to peer
    if ((ret = res_flush(skt, ss)) != ERROR_SUCCESS) {
        return ret;
    }
    
    // write body.
    int64_t left = length;
    char* buf = req->http_ts_send_buffer();
    
    while (left > 0) {
        ssize_t nread = -1;
        if ((ret = fs.read(buf, __SRS_HTTP_TS_SEND_BUFFER_SIZE, &nread)) != ERROR_SUCCESS) {
            srs_warn("read file %s failed, ret=%d", fullpath.c_str(), ret);
            break;
        }
        
        left -= nread;
        if ((ret = skt->write(buf, nread, NULL)) != ERROR_SUCCESS) {
            break;
        }
    }
    
    return ret;
}
예제 #2
0
int SrsHttpVhost::response_regular_file(SrsStSocket* skt, SrsHttpMessage* req, string fullpath)
{
    int ret = ERROR_SUCCESS;

    SrsFileReader fs;
    
    if ((ret = fs.open(fullpath)) != ERROR_SUCCESS) {
        srs_warn("open file %s failed, ret=%d", fullpath.c_str(), ret);
        return ret;
    }

    int64_t length = fs.filesize();
    
    char* buf = new char[length];
    SrsAutoFree(char, buf);
    
    if ((ret = fs.read(buf, length, NULL)) != ERROR_SUCCESS) {
        srs_warn("read file %s failed, ret=%d", fullpath.c_str(), ret);
        return ret;
    }
    
    std::string str;
    str.append(buf, length);
    
    if (srs_string_ends_with(fullpath, ".ts")) {
        return res_mpegts(skt, req, str);
    } else if (srs_string_ends_with(fullpath, ".m3u8")) {
        return res_m3u8(skt, req, str);
    } else if (srs_string_ends_with(fullpath, ".xml")) {
        return res_xml(skt, req, str);
    } else if (srs_string_ends_with(fullpath, ".js")) {
        return res_javascript(skt, req, str);
    } else if (srs_string_ends_with(fullpath, ".json")) {
        return res_json(skt, req, str);
    } else if (srs_string_ends_with(fullpath, ".swf")) {
        return res_swf(skt, req, str);
    } else if (srs_string_ends_with(fullpath, ".css")) {
        return res_css(skt, req, str);
    } else if (srs_string_ends_with(fullpath, ".ico")) {
        return res_ico(skt, req, str);
    } else {
        return res_text(skt, req, str);
    }
    
    return ret;
}
예제 #3
0
int SrsVodStream::serve_mp4_stream(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, string fullpath, int start, int end)
{
    int ret = ERROR_SUCCESS;

    srs_assert(start >= 0);
    srs_assert(end == -1 || end >= 0);
    
    SrsFileReader fs;
    
    // open flv file
    if ((ret = fs.open(fullpath)) != ERROR_SUCCESS) {
        return ret;
    }

    // parse -1 to whole file.
    if (end == -1) {
        end = (int)fs.filesize();
    }
    
    if (end > fs.filesize() || start > end) {
        ret = ERROR_HTTP_REMUX_OFFSET_OVERFLOW;
        srs_warn("http mp4 streaming %s overflow. size=%"PRId64", offset=%d, ret=%d", 
            fullpath.c_str(), fs.filesize(), start, ret);
        return ret;
    }

    // seek to data offset, [start, end] for range.
    int64_t left = end - start + 1;

    // write http header for ts.
    w->header()->set_content_length(left);
    w->header()->set_content_type("video/mp4");

    // status code 206 to make dash.as happy.
    w->write_header(SRS_CONSTS_HTTP_PartialContent);

    // response the content range header.
    std::stringstream content_range;
    content_range << "bytes " << start << "-" << end << "/" << fs.filesize();
    w->header()->set("Content-Range", content_range.str());
    
    // write body.
    fs.lseek(start);
    
    // send data
    if ((ret = copy(w, &fs, r, (int)left)) != ERROR_SUCCESS) {
        srs_warn("read mp4=%s size=%d failed, ret=%d", fullpath.c_str(), left, ret);
        return ret;
    }
    
    return ret;
}
예제 #4
0
int SrsHttpVhost::response_flv_file2(SrsStSocket* skt, SrsHttpMessage* req, string fullpath, int offset)
{
    int ret = ERROR_SUCCESS;
    
    SrsFileReader fs;
    
    // open flv file
    if ((ret = fs.open(fullpath)) != ERROR_SUCCESS) {
        return ret;
    }
    
    if (offset > fs.filesize()) {
        ret = ERROR_HTTP_FLV_OFFSET_OVERFLOW;
        srs_warn("http flv streaming %s overflow. size=%"PRId64", offset=%d, ret=%d", 
            fullpath.c_str(), fs.filesize(), offset, ret);
        return ret;
    }
    
    SrsFlvVodStreamDecoder ffd;
    
    // open fast decoder
    if ((ret = ffd.initialize(&fs)) != ERROR_SUCCESS) {
        return ret;
    }
    
    // save header, send later.
    char flv_header[13];
    
    // send flv header
    if ((ret = ffd.read_header_ext(flv_header)) != ERROR_SUCCESS) {
        return ret;
    }
    
    // save sequence header, send later
    char* sh_data = NULL;
    int sh_size = 0;
    
    if (true) {
        // send sequence header
        int64_t start = 0;
        if ((ret = ffd.read_sequence_header_summary(&start, &sh_size)) != ERROR_SUCCESS) {
            return ret;
        }
        if (sh_size <= 0) {
            ret = ERROR_HTTP_FLV_SEQUENCE_HEADER;
            srs_warn("http flv streaming no sequence header. size=%d, ret=%d", sh_size, ret);
            return ret;
        }
    }
    sh_data = new char[sh_size];
    SrsAutoFree(char, sh_data);
    if ((ret = fs.read(sh_data, sh_size, NULL)) != ERROR_SUCCESS) {
        return ret;
    }

    // seek to data offset
    int64_t left = fs.filesize() - offset;

    // write http header for ts.
    std::stringstream ss;

    res_status_line(ss)->res_content_type_flv(ss)
        ->res_content_length(ss, (int)(sizeof(flv_header) + sh_size + left));
        
    if (req->requires_crossdomain()) {
        res_enable_crossdomain(ss);
    }
    
    res_header_eof(ss);
    
    // flush http header to peer
    if ((ret = res_flush(skt, ss)) != ERROR_SUCCESS) {
        return ret;
    }
    
    if ((ret = skt->write(flv_header, sizeof(flv_header), NULL)) != ERROR_SUCCESS) {
        return ret;
    }
    if (sh_size > 0 && (ret = skt->write(sh_data, sh_size, NULL)) != ERROR_SUCCESS) {
        return ret;
    }
    
    // write body.
    char* buf = req->http_ts_send_buffer();
    if ((ret = ffd.lseek(offset)) != ERROR_SUCCESS) {
        return ret;
    }
    
    // send data
    while (left > 0) {
        ssize_t nread = -1;
        if ((ret = fs.read(buf, __SRS_HTTP_TS_SEND_BUFFER_SIZE, &nread)) != ERROR_SUCCESS) {
            return ret;
        }
        
        left -= nread;
        if ((ret = skt->write(buf, nread, NULL)) != ERROR_SUCCESS) {
            return ret;
        }
    }
    
    return ret;
}
예제 #5
0
int SrsVodStream::serve_flv_stream(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, string fullpath, int offset)
{
    int ret = ERROR_SUCCESS;
    
    SrsFileReader fs;
    
    // open flv file
    if ((ret = fs.open(fullpath)) != ERROR_SUCCESS) {
        return ret;
    }
    
    if (offset > fs.filesize()) {
        ret = ERROR_HTTP_REMUX_OFFSET_OVERFLOW;
        srs_warn("http flv streaming %s overflow. size=%"PRId64", offset=%d, ret=%d", 
            fullpath.c_str(), fs.filesize(), offset, ret);
        return ret;
    }
    
    SrsFlvVodStreamDecoder ffd;
    
    // open fast decoder
    if ((ret = ffd.initialize(&fs)) != ERROR_SUCCESS) {
        return ret;
    }
    
    // save header, send later.
    char flv_header[13];
    
    // send flv header
    if ((ret = ffd.read_header_ext(flv_header)) != ERROR_SUCCESS) {
        return ret;
    }
    
    // save sequence header, send later
    char* sh_data = NULL;
    int sh_size = 0;
    
    if (true) {
        // send sequence header
        int64_t start = 0;
        if ((ret = ffd.read_sequence_header_summary(&start, &sh_size)) != ERROR_SUCCESS) {
            return ret;
        }
        if (sh_size <= 0) {
            ret = ERROR_HTTP_REMUX_SEQUENCE_HEADER;
            srs_warn("http flv streaming no sequence header. size=%d, ret=%d", sh_size, ret);
            return ret;
        }
    }
    sh_data = new char[sh_size];
    SrsAutoFreeA(char, sh_data);
    if ((ret = fs.read(sh_data, sh_size, NULL)) != ERROR_SUCCESS) {
        return ret;
    }

    // seek to data offset
    int64_t left = fs.filesize() - offset;

    // write http header for ts.
    w->header()->set_content_length((int)(sizeof(flv_header) + sh_size + left));
    w->header()->set_content_type("video/x-flv");
    
    // write flv header and sequence header.
    if ((ret = w->write(flv_header, sizeof(flv_header))) != ERROR_SUCCESS) {
        return ret;
    }
    if (sh_size > 0 && (ret = w->write(sh_data, sh_size)) != ERROR_SUCCESS) {
        return ret;
    }
    
    // write body.
    if ((ret = ffd.lseek(offset)) != ERROR_SUCCESS) {
        return ret;
    }
    
    // send data
    if ((ret = copy(w, &fs, r, (int)left)) != ERROR_SUCCESS) {
        srs_warn("read flv=%s size=%d failed, ret=%d", fullpath.c_str(), left, ret);
        return ret;
    }
    
    return ret;
}