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; }
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); }
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; }