Пример #1
0
int process(const char* in_flv_file, const char* out_flv_file, srs_flv_t* pic, srs_flv_t* poc)
{
    int ret = 0;
    
    srs_flv_t ic;
    srs_flv_t oc;
    
    // to adjust metadata.
    // the ic metadata end offset, the next tag start offset.
    // all oc metadata must adjust according to:
    //      adjust = new_metadata_end_offset - metadata_end_offset
    int64_t metadata_end_offset = 0;
    
    // metadata
    srs_amf0_t amf0_name = NULL;
    srs_amf0_t amf0_data = NULL;
    srs_amf0_t filepositions = NULL;
    
    if ((ic = srs_flv_open_read(in_flv_file)) == NULL) {
        ret = 2;
        srs_human_trace("open input flv file failed. ret=%d", ret);
        return ret;
    }
    *pic = ic;
    
    if ((oc = srs_flv_open_write(out_flv_file)) == NULL) {
        ret = 2;
        srs_human_trace("open output flv file failed. ret=%d", ret);
        return ret;
    }
    *poc = oc;
    
    /**
    * we use two roundtrip to avoid the paddings of metadata,
    * to support large keyframes videos without padding fields.
    */
    // build keyframes offset to metadata.
    if ((ret = build_keyframes(ic, &amf0_name, &amf0_data, &filepositions, &metadata_end_offset)) != 0) {
        return ret;
    }
    
    // inject the metadata to oc.
    if ((ret = do_inject_flv(ic, oc, amf0_name, amf0_data, filepositions, metadata_end_offset)) != 0) {
        return ret;
    }
    
    // TODO: FIXME: mem leak when error.
    srs_amf0_free(amf0_name);
    srs_amf0_free(amf0_data);
    
    return ret;
}
Пример #2
0
PushEngine::PushEngine(JobQueue<OneStreamSharePtr> &jobQueue, JobQueue<StreamEventSharePtr> &streamEventQueue)
    : m_jobQueue(jobQueue)
    , m_streamEventQueue(streamEventQueue)
    , m_thread("PushEngine")
    , m_timeTick(0)
    , m_logger(Poco::Logger::get("PushEngine")){       
    int ret = 0;    

    if ((m_flv = srs_flv_open_read("nba.flv")) == NULL) {
        m_logger.error("open flv file failed.");
        m_flv = NULL;
    }
    
    char header[13];
    if ((ret = srs_flv_read_header(m_flv, header)) != 0) {
        m_logger.error("read header error.");
    }
    
    for (;;) {
        // tag header
        Frame f;
        if ((ret = srs_flv_read_tag_header(m_flv, &f.type, &f.size, &f.timestamp)) != 0) {
            if (srs_flv_is_eof(ret)) {
                m_logger.information("parse completed.");
                break;
            }
            m_logger.error("flv get packet failed. ret=%d");
            break;
        }
        if (f.size <= 0) {
            m_logger.error("invalid size.");
            break;
        }
        
        f.data = (char*)malloc(f.size);
        if ((ret = srs_flv_read_tag_data(m_flv, f.data, f.size)) != 0) {
            m_logger.error("read data error.");
            break;
        }
        m_flvFrame.push_back(f);
    }
    m_logger.information("frame size = %d", (int)m_flvFrame.size());
    
    m_thread.start(*this);
}
Пример #3
0
int main(int argc, char **argv) {
    int ret = 0;

    // main function
    tools_main_entrance_startup_time = srs_utils_time_ms();

    // user option parse index.
    int opt = 0;
    // user options.
    char *in_flv_file = NULL;
    char *out_rtmp_url = NULL;
    // rtmp handler
    srs_rtmp_t ortmp;
    // flv handler
    srs_flv_t flv;

    printf("ingest flv file and publish to RTMP server like FFMPEG.\n");
    printf("srs(simple-rtmp-server) client librtmp library.\n");
    printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision());

    if (argc <= 2) {
        printf("ingest flv file and publish to RTMP server\n"
                       "Usage: %s <-i in_flv_file> <-y out_rtmp_url>\n"
                       "   in_flv_file     input flv file, ingest from this file.\n"
                       "   out_rtmp_url    output rtmp url, publish to this url.\n"
                       "For example:\n"
                       "   %s -i doc/source.200kbps.768x320.flv -y rtmp://127.0.0.1/live/livestream\n"
                       "   %s -i ../../doc/source.200kbps.768x320.flv -y rtmp://127.0.0.1/live/livestream\n",
               argv[0], argv[0], argv[0]);
        exit(-1);
    }

    for (opt = 0; opt < argc; opt++) {
        srs_human_trace("argv[%d]=%s", opt, argv[opt]);
    }

    // fill the options for mac
    for (opt = 0; opt < argc - 1; opt++) {
        // ignore all options except -i and -y.
        char *p = argv[opt];

        // only accept -x
        if (p[0] != '-' || p[1] == 0 || p[2] != 0) {
            continue;
        }

        // parse according the option name.
        switch (p[1]) {
            case 'i':
                in_flv_file = argv[opt + 1];
                break;
            case 'y':
                out_rtmp_url = argv[opt + 1];
                break;
            default:
                break;
        }
    }

    if (!in_flv_file) {
        srs_human_trace("input invalid, use -i <input>");
        return -1;
    }
    if (!out_rtmp_url) {
        srs_human_trace("output invalid, use -y <output>");
        return -1;
    }

    srs_human_trace("input:  %s", in_flv_file);
    srs_human_trace("output: %s", out_rtmp_url);

    if ((flv = srs_flv_open_read(in_flv_file)) == NULL) {
        ret = 2;
        srs_human_trace("open flv file failed. ret=%d", ret);
        return ret;
    }

    ortmp = srs_rtmp_create(out_rtmp_url);

    ret = proxy(flv, ortmp);
    srs_human_trace("ingest flv to RTMP completed");

    srs_rtmp_destroy(ortmp);
    srs_flv_close(flv);

    return ret;
}