Skip to content

Commit

Permalink
for #367: extract the process from ffmpeg to exec programs.
Browse files Browse the repository at this point in the history
  • Loading branch information
winlinvip committed Aug 24, 2015
1 parent 3a8c03a commit 0e1861b
Show file tree
Hide file tree
Showing 8 changed files with 376 additions and 195 deletions.
2 changes: 1 addition & 1 deletion trunk/configure
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ if [ $SRS_EXPORT_LIBRTMP_PROJECT = NO ]; then
"srs_app_heartbeat" "srs_app_empty" "srs_app_http_client" "srs_app_http_static"
"srs_app_recv_thread" "srs_app_security" "srs_app_statistic" "srs_app_hds"
"srs_app_mpegts_udp" "srs_app_rtsp" "srs_app_listener" "srs_app_async_call"
"srs_app_caster_flv")
"srs_app_caster_flv" "srs_app_process")
DEFINES=""
# add each modules for app
for SRS_MODULE in ${SRS_MODULES[*]}; do
Expand Down
2 changes: 2 additions & 0 deletions trunk/ide/srs_upp/srs_upp.upp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ file
../../src/app/srs_app_log.cpp,
../../src/app/srs_app_mpegts_udp.hpp,
../../src/app/srs_app_mpegts_udp.cpp,
../../src/app/srs_app_process.hpp,
../../src/app/srs_app_process.cpp,
../../src/app/srs_app_recv_thread.hpp,
../../src/app/srs_app_recv_thread.cpp,
../../src/app/srs_app_refer.hpp,
Expand Down
6 changes: 6 additions & 0 deletions trunk/ide/srs_xcode/srs_xcode.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
3C36DB5B1ABD1CB90066CCAF /* srs_lib_bandwidth.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C36DB551ABD1CB90066CCAF /* srs_lib_bandwidth.cpp */; };
3C36DB5C1ABD1CB90066CCAF /* srs_lib_simple_socket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C36DB571ABD1CB90066CCAF /* srs_lib_simple_socket.cpp */; };
3C36DB5D1ABD1CB90066CCAF /* srs_librtmp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C36DB591ABD1CB90066CCAF /* srs_librtmp.cpp */; };
3C4F97121B8B466D00FF0E46 /* srs_app_process.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C4F97101B8B466D00FF0E46 /* srs_app_process.cpp */; };
3C5265B41B241BF0009CA186 /* srs_core_mem_watch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C5265B21B241BF0009CA186 /* srs_core_mem_watch.cpp */; };
3C663F0F1AB0155100286D8B /* srs_aac_raw_publish.c in Sources */ = {isa = PBXBuildFile; fileRef = 3C663F021AB0155100286D8B /* srs_aac_raw_publish.c */; };
3C663F101AB0155100286D8B /* srs_audio_raw_publish.c in Sources */ = {isa = PBXBuildFile; fileRef = 3C663F031AB0155100286D8B /* srs_audio_raw_publish.c */; };
Expand Down Expand Up @@ -328,6 +329,8 @@
3C36DB581ABD1CB90066CCAF /* srs_lib_simple_socket.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_lib_simple_socket.hpp; path = ../../../src/libs/srs_lib_simple_socket.hpp; sourceTree = "<group>"; };
3C36DB591ABD1CB90066CCAF /* srs_librtmp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_librtmp.cpp; path = ../../../src/libs/srs_librtmp.cpp; sourceTree = "<group>"; };
3C36DB5A1ABD1CB90066CCAF /* srs_librtmp.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_librtmp.hpp; path = ../../../src/libs/srs_librtmp.hpp; sourceTree = "<group>"; };
3C4F97101B8B466D00FF0E46 /* srs_app_process.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_process.cpp; path = ../../../src/app/srs_app_process.cpp; sourceTree = "<group>"; };
3C4F97111B8B466D00FF0E46 /* srs_app_process.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_process.hpp; path = ../../../src/app/srs_app_process.hpp; sourceTree = "<group>"; };
3C5265B21B241BF0009CA186 /* srs_core_mem_watch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_core_mem_watch.cpp; path = ../../../src/core/srs_core_mem_watch.cpp; sourceTree = "<group>"; };
3C5265B31B241BF0009CA186 /* srs_core_mem_watch.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_core_mem_watch.hpp; path = ../../../src/core/srs_core_mem_watch.hpp; sourceTree = "<group>"; };
3C663F021AB0155100286D8B /* srs_aac_raw_publish.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = srs_aac_raw_publish.c; path = ../../../research/librtmp/srs_aac_raw_publish.c; sourceTree = "<group>"; };
Expand Down Expand Up @@ -573,6 +576,8 @@
3C1232771AAE81D900CE8F6C /* srs_app_mpegts_udp.hpp */,
3C1232781AAE81D900CE8F6C /* srs_app_pithy_print.cpp */,
3C1232791AAE81D900CE8F6C /* srs_app_pithy_print.hpp */,
3C4F97101B8B466D00FF0E46 /* srs_app_process.cpp */,
3C4F97111B8B466D00FF0E46 /* srs_app_process.hpp */,
3C12327A1AAE81D900CE8F6C /* srs_app_recv_thread.cpp */,
3C12327B1AAE81D900CE8F6C /* srs_app_recv_thread.hpp */,
3C12327C1AAE81D900CE8F6C /* srs_app_refer.cpp */,
Expand Down Expand Up @@ -911,6 +916,7 @@
3C1232B21AAE81D900CE8F6C /* srs_app_source.cpp in Sources */,
3C1231F71AAE652D00CE8F6C /* srs_core_performance.cpp in Sources */,
3CC52DD81ACE4023006FEB01 /* srs_utest_amf0.cpp in Sources */,
3C4F97121B8B466D00FF0E46 /* srs_app_process.cpp in Sources */,
3C1232981AAE81D900CE8F6C /* srs_app_edge.cpp in Sources */,
3CC52DDB1ACE4023006FEB01 /* srs_utest_kernel.cpp in Sources */,
3C689F9E1AB6AAC800C9CEEE /* md.S in Sources */,
Expand Down
209 changes: 41 additions & 168 deletions trunk/src/app/srs_app_ffmpeg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <signal.h>
#include <sys/types.h>

#include <vector>
using namespace std;

#include <srs_kernel_error.hpp>
#include <srs_kernel_log.hpp>
#include <srs_app_config.hpp>
#include <srs_app_utility.hpp>
#include <srs_app_process.hpp>
#include <srs_core_autofree.hpp>

#ifdef SRS_AUTO_FFMPEG_STUB

Expand All @@ -52,9 +55,6 @@ using namespace std;

SrsFFMPEG::SrsFFMPEG(std::string ffmpeg_bin)
{
started = false;
fast_stopped = false;
pid = -1;
ffmpeg = ffmpeg_bin;

vbitrate = 0;
Expand All @@ -65,11 +65,15 @@ SrsFFMPEG::SrsFFMPEG(std::string ffmpeg_bin)
abitrate = 0;
asample_rate = 0;
achannels = 0;

process = new SrsProcess();
}

SrsFFMPEG::~SrsFFMPEG()
{
stop();

srs_freep(process);
}

void SrsFFMPEG::set_iparams(string iparams)
Expand Down Expand Up @@ -236,17 +240,22 @@ int SrsFFMPEG::start()
{
int ret = ERROR_SUCCESS;

if (started) {
if (process->started()) {
return ret;
}

// prepare exec params
char tmp[256];
std::vector<std::string> params;
// @remark we should never use stack variable, use heap to alloc to make lldb happy.
#define SRS_TMP_SIZE 512
char* tmp = new char[SRS_TMP_SIZE];
SrsAutoFree(char, tmp);

// the argv for process.
params.clear();

// argv[0], set to ffmpeg bin.
// The execv() and execvp() functions ....
// The first argument, by convention, should point to
// The first argument, by convention, should point to
// the filename associated with the file being executed.
params.push_back(ffmpeg);

Expand Down Expand Up @@ -287,32 +296,32 @@ int SrsFFMPEG::start()
if (vcodec != SRS_RTMP_ENCODER_COPY && vcodec != SRS_RTMP_ENCODER_NO_VIDEO) {
if (vbitrate > 0) {
params.push_back("-b:v");
snprintf(tmp, sizeof(tmp), "%d", vbitrate * 1000);
snprintf(tmp, SRS_TMP_SIZE, "%d", vbitrate * 1000);
params.push_back(tmp);
}

if (vfps > 0) {
params.push_back("-r");
snprintf(tmp, sizeof(tmp), "%.2f", vfps);
snprintf(tmp, SRS_TMP_SIZE, "%.2f", vfps);
params.push_back(tmp);
}

if (vwidth > 0 && vheight > 0) {
params.push_back("-s");
snprintf(tmp, sizeof(tmp), "%dx%d", vwidth, vheight);
snprintf(tmp, SRS_TMP_SIZE, "%dx%d", vwidth, vheight);
params.push_back(tmp);
}

// TODO: add aspect if needed.
if (vwidth > 0 && vheight > 0) {
params.push_back("-aspect");
snprintf(tmp, sizeof(tmp), "%d:%d", vwidth, vheight);
snprintf(tmp, SRS_TMP_SIZE, "%d:%d", vwidth, vheight);
params.push_back(tmp);
}

if (vthreads > 0) {
params.push_back("-threads");
snprintf(tmp, sizeof(tmp), "%d", vthreads);
snprintf(tmp, SRS_TMP_SIZE, "%d", vthreads);
params.push_back(tmp);
}

Expand Down Expand Up @@ -347,19 +356,19 @@ int SrsFFMPEG::start()
if (acodec != SRS_RTMP_ENCODER_COPY) {
if (abitrate > 0) {
params.push_back("-b:a");
snprintf(tmp, sizeof(tmp), "%d", abitrate * 1000);
snprintf(tmp, SRS_TMP_SIZE, "%d", abitrate * 1000);
params.push_back(tmp);
}

if (asample_rate > 0) {
params.push_back("-ar");
snprintf(tmp, sizeof(tmp), "%d", asample_rate);
snprintf(tmp, SRS_TMP_SIZE, "%d", asample_rate);
params.push_back(tmp);
}

if (achannels > 0) {
params.push_back("-ac");
snprintf(tmp, sizeof(tmp), "%d", achannels);
snprintf(tmp, SRS_TMP_SIZE, "%d", achannels);
params.push_back(tmp);
}

Expand Down Expand Up @@ -387,7 +396,7 @@ int SrsFFMPEG::start()
}
}
}

// output
if (oformat != "off" && !oformat.empty()) {
params.push_back("-f");
Expand All @@ -396,176 +405,40 @@ int SrsFFMPEG::start()

params.push_back("-y");
params.push_back(_output);

std::string cli;
if (true) {
for (int i = 0; i < (int)params.size(); i++) {
std::string ffp = params[i];
cli += ffp;
if (i < (int)params.size() - 1) {
cli += " ";
}
}
srs_trace("start ffmpeg, log: %s, params: %s", log_file.c_str(), cli.c_str());
}

// for log
int cid = _srs_context->get_id();

// TODO: fork or vfork?
if ((pid = fork()) < 0) {
ret = ERROR_ENCODER_FORK;
srs_error("vfork process failed. ret=%d", ret);
return ret;
// when specified the log file.
if (false && !log_file.empty()) {
// stdout
params.push_back("1");
params.push_back(">");
params.push_back(log_file);
// stderr
params.push_back("2");
params.push_back(">");
params.push_back(log_file);
}

// child process: ffmpeg encoder engine.
if (pid == 0) {
// ignore the SIGINT and SIGTERM
signal(SIGINT, SIG_IGN);
signal(SIGTERM, SIG_IGN);

// redirect logs to file.
int log_fd = -1;
int flags = O_CREAT|O_WRONLY|O_APPEND;
mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH;
if ((log_fd = ::open(log_file.c_str(), flags, mode)) < 0) {
ret = ERROR_ENCODER_OPEN;
srs_error("open encoder file %s failed. ret=%d", log_file.c_str(), ret);
return ret;
}

// log basic info
if (true) {
char buf[4096];
int pos = 0;
pos += snprintf(buf + pos, sizeof(buf) - pos, "\n");
pos += snprintf(buf + pos, sizeof(buf) - pos, "ffmpeg cid=%d\n", cid);
pos += snprintf(buf + pos, sizeof(buf) - pos, "log=%s\n", log_file.c_str());
pos += snprintf(buf + pos, sizeof(buf) - pos, "params: %s\n", cli.c_str());
::write(log_fd, buf, pos);
}

// dup to stdout and stderr.
if (dup2(log_fd, STDOUT_FILENO) < 0) {
ret = ERROR_ENCODER_DUP2;
srs_error("dup2 encoder file failed. ret=%d", ret);
return ret;
}
if (dup2(log_fd, STDERR_FILENO) < 0) {
ret = ERROR_ENCODER_DUP2;
srs_error("dup2 encoder file failed. ret=%d", ret);
return ret;
}

// close log fd
::close(log_fd);
// close other fds
// TODO: do in right way.
for (int i = 3; i < 1024; i++) {
::close(i);
}

// memory leak in child process, it's ok.
char** charpv_params = new char*[params.size() + 1];
for (int i = 0; i < (int)params.size(); i++) {
std::string& p = params[i];
charpv_params[i] = (char*)p.data();
}
// EOF: NULL
charpv_params[params.size()] = NULL;

// TODO: execv or execvp
ret = execv(ffmpeg.c_str(), charpv_params);
if (ret < 0) {
fprintf(stderr, "fork ffmpeg failed, errno=%d(%s)",
errno, strerror(errno));
}
exit(ret);
}

// parent.
if (pid > 0) {
started = true;
srs_trace("vfored ffmpeg encoder engine, pid=%d", pid);
// initialize the process.
if ((ret = process->initialize(ffmpeg, params)) != ERROR_SUCCESS) {
return ret;
}

return ret;
return process->start();
}

int SrsFFMPEG::cycle()
{
int ret = ERROR_SUCCESS;

if (!started) {
return ret;
}

// ffmpeg is prepare to stop, donot cycle.
if (fast_stopped) {
return ret;
}

int status = 0;
pid_t p = waitpid(pid, &status, WNOHANG);

if (p < 0) {
ret = ERROR_SYSTEM_WAITPID;
srs_error("transcode waitpid failed, pid=%d, ret=%d", pid, ret);
return ret;
}

if (p == 0) {
srs_info("transcode process pid=%d is running.", pid);
return ret;
}

srs_trace("transcode process pid=%d terminate, restart it.", pid);
started = false;

return ret;
return process->cycle();
}

void SrsFFMPEG::stop()
{
if (!started) {
return;
}

// kill the ffmpeg,
// when rewind, upstream will stop publish(unpublish),
// unpublish event will stop all ffmpeg encoders,
// then publish will start all ffmpeg encoders.
int ret = srs_kill_forced(pid);
if (ret != ERROR_SUCCESS) {
srs_warn("ignore kill the encoder failed, pid=%d. ret=%d", pid, ret);
return;
}

// terminated, set started to false to stop the cycle.
started = false;
process->stop();
}

void SrsFFMPEG::fast_stop()
{
int ret = ERROR_SUCCESS;

if (!started) {
return;
}

if (pid <= 0) {
return;
}

if (kill(pid, SIGTERM) < 0) {
ret = ERROR_SYSTEM_KILL;
srs_warn("ignore fast stop ffmpeg failed, pid=%d. ret=%d", pid, ret);
return;
}

return;
process->fast_stop();
}

#endif
Expand Down
Loading

0 comments on commit 0e1861b

Please sign in to comment.