2017-03-25 09:21:39 +00:00
|
|
|
/**
|
|
|
|
* The MIT License (MIT)
|
|
|
|
*
|
2019-12-30 02:10:35 +00:00
|
|
|
* Copyright (c) 2013-2020 Winlin
|
2017-03-25 09:21:39 +00:00
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
|
|
* this software and associated documentation files (the "Software"), to deal in
|
|
|
|
* the Software without restriction, including without limitation the rights to
|
|
|
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
|
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
|
|
|
* subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice shall be included in all
|
|
|
|
* copies or substantial portions of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
|
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
|
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
|
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
|
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
*/
|
2014-04-07 01:34:36 +00:00
|
|
|
|
|
|
|
#include <srs_app_ffmpeg.hpp>
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <sys/wait.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
2015-11-11 02:45:45 +00:00
|
|
|
// for srs-librtmp, @see https://github.com/ossrs/srs/issues/213
|
2015-08-24 14:19:57 +00:00
|
|
|
#ifndef _WIN32
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
|
2015-08-24 13:51:05 +00:00
|
|
|
#include <vector>
|
2014-04-07 02:15:44 +00:00
|
|
|
using namespace std;
|
2014-04-07 01:34:36 +00:00
|
|
|
|
|
|
|
#include <srs_kernel_error.hpp>
|
|
|
|
#include <srs_kernel_log.hpp>
|
|
|
|
#include <srs_app_config.hpp>
|
2015-05-30 01:32:03 +00:00
|
|
|
#include <srs_app_utility.hpp>
|
2015-08-24 13:51:05 +00:00
|
|
|
#include <srs_app_process.hpp>
|
|
|
|
#include <srs_core_autofree.hpp>
|
2015-09-24 09:54:58 +00:00
|
|
|
#include <srs_kernel_utility.hpp>
|
2014-04-07 01:34:36 +00:00
|
|
|
|
2014-10-09 02:41:24 +00:00
|
|
|
#ifdef SRS_AUTO_FFMPEG_STUB
|
2014-04-07 01:34:36 +00:00
|
|
|
|
2015-10-20 06:52:34 +00:00
|
|
|
#define SRS_RTMP_ENCODER_COPY "copy"
|
|
|
|
#define SRS_RTMP_ENCODER_NO_VIDEO "vn"
|
|
|
|
#define SRS_RTMP_ENCODER_NO_AUDIO "an"
|
2014-04-07 01:34:36 +00:00
|
|
|
// only support libx264 encoder.
|
2015-10-20 06:52:34 +00:00
|
|
|
#define SRS_RTMP_ENCODER_VCODEC_LIBX264 "libx264"
|
|
|
|
#define SRS_RTMP_ENCODER_VCODEC_PNG "png"
|
2014-04-07 01:34:36 +00:00
|
|
|
// any aac encoder is ok which contains the aac,
|
|
|
|
// for example, libaacplus, aac, fdkaac
|
2015-10-20 06:52:34 +00:00
|
|
|
#define SRS_RTMP_ENCODER_ACODEC "aac"
|
|
|
|
#define SRS_RTMP_ENCODER_LIBAACPLUS "libaacplus"
|
|
|
|
#define SRS_RTMP_ENCODER_LIBFDKAAC "libfdk_aac"
|
2014-04-07 01:34:36 +00:00
|
|
|
|
|
|
|
SrsFFMPEG::SrsFFMPEG(std::string ffmpeg_bin)
|
|
|
|
{
|
2017-01-16 07:47:26 +00:00
|
|
|
ffmpeg = ffmpeg_bin;
|
2014-04-07 01:34:36 +00:00
|
|
|
|
2017-01-16 07:47:26 +00:00
|
|
|
vbitrate = 0;
|
|
|
|
vfps = 0;
|
|
|
|
vwidth = 0;
|
|
|
|
vheight = 0;
|
|
|
|
vthreads = 0;
|
|
|
|
abitrate = 0;
|
|
|
|
asample_rate = 0;
|
|
|
|
achannels = 0;
|
2015-08-24 13:51:05 +00:00
|
|
|
|
|
|
|
process = new SrsProcess();
|
2014-04-07 01:34:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SrsFFMPEG::~SrsFFMPEG()
|
|
|
|
{
|
|
|
|
stop();
|
2015-08-24 13:51:05 +00:00
|
|
|
|
|
|
|
srs_freep(process);
|
2014-04-07 01:34:36 +00:00
|
|
|
}
|
|
|
|
|
2020-02-05 04:32:15 +00:00
|
|
|
void SrsFFMPEG::append_iparam(string iparam)
|
2014-04-07 06:20:03 +00:00
|
|
|
{
|
2020-02-05 04:32:15 +00:00
|
|
|
iparams.push_back(iparam);
|
2014-04-07 06:20:03 +00:00
|
|
|
}
|
|
|
|
|
2014-07-19 07:20:16 +00:00
|
|
|
void SrsFFMPEG::set_oformat(string format)
|
|
|
|
{
|
|
|
|
oformat = format;
|
|
|
|
}
|
|
|
|
|
2014-04-07 02:15:44 +00:00
|
|
|
string SrsFFMPEG::output()
|
|
|
|
{
|
|
|
|
return _output;
|
|
|
|
}
|
|
|
|
|
2018-01-01 11:39:57 +00:00
|
|
|
srs_error_t SrsFFMPEG::initialize(string in, string out, string log)
|
2014-04-07 05:13:57 +00:00
|
|
|
{
|
2018-01-01 11:39:57 +00:00
|
|
|
srs_error_t err = srs_success;
|
2014-04-07 05:13:57 +00:00
|
|
|
|
|
|
|
input = in;
|
|
|
|
_output = out;
|
|
|
|
log_file = log;
|
|
|
|
|
2018-01-01 11:39:57 +00:00
|
|
|
return err;
|
2014-04-07 05:13:57 +00:00
|
|
|
}
|
|
|
|
|
2018-01-01 11:39:57 +00:00
|
|
|
srs_error_t SrsFFMPEG::initialize_transcode(SrsConfDirective* engine)
|
2014-04-07 01:34:36 +00:00
|
|
|
{
|
2018-01-01 11:39:57 +00:00
|
|
|
srs_error_t err = srs_success;
|
2014-04-07 01:34:36 +00:00
|
|
|
|
2017-01-16 07:47:26 +00:00
|
|
|
perfile = _srs_config->get_engine_perfile(engine);
|
|
|
|
iformat = _srs_config->get_engine_iformat(engine);
|
|
|
|
vfilter = _srs_config->get_engine_vfilter(engine);
|
|
|
|
vcodec = _srs_config->get_engine_vcodec(engine);
|
|
|
|
vbitrate = _srs_config->get_engine_vbitrate(engine);
|
|
|
|
vfps = _srs_config->get_engine_vfps(engine);
|
|
|
|
vwidth = _srs_config->get_engine_vwidth(engine);
|
|
|
|
vheight = _srs_config->get_engine_vheight(engine);
|
|
|
|
vthreads = _srs_config->get_engine_vthreads(engine);
|
|
|
|
vprofile = _srs_config->get_engine_vprofile(engine);
|
|
|
|
vpreset = _srs_config->get_engine_vpreset(engine);
|
|
|
|
vparams = _srs_config->get_engine_vparams(engine);
|
|
|
|
acodec = _srs_config->get_engine_acodec(engine);
|
|
|
|
abitrate = _srs_config->get_engine_abitrate(engine);
|
|
|
|
asample_rate = _srs_config->get_engine_asample_rate(engine);
|
|
|
|
achannels = _srs_config->get_engine_achannels(engine);
|
|
|
|
aparams = _srs_config->get_engine_aparams(engine);
|
|
|
|
oformat = _srs_config->get_engine_oformat(engine);
|
2014-04-07 01:34:36 +00:00
|
|
|
|
|
|
|
// ensure the size is even.
|
|
|
|
vwidth -= vwidth % 2;
|
|
|
|
vheight -= vheight % 2;
|
|
|
|
|
2014-04-14 01:10:36 +00:00
|
|
|
if (vcodec == SRS_RTMP_ENCODER_NO_VIDEO && acodec == SRS_RTMP_ENCODER_NO_AUDIO) {
|
2018-01-01 11:39:57 +00:00
|
|
|
return srs_error_new(ERROR_ENCODER_VCODEC, "video and audio disabled");
|
2014-04-07 01:34:36 +00:00
|
|
|
}
|
|
|
|
|
2015-10-20 06:52:34 +00:00
|
|
|
if (vcodec != SRS_RTMP_ENCODER_COPY && vcodec != SRS_RTMP_ENCODER_NO_VIDEO && vcodec != SRS_RTMP_ENCODER_VCODEC_PNG) {
|
|
|
|
if (vcodec != SRS_RTMP_ENCODER_VCODEC_LIBX264) {
|
2018-01-01 11:39:57 +00:00
|
|
|
return srs_error_new(ERROR_ENCODER_VCODEC, "invalid vcodec, must be %s, actual %s", SRS_RTMP_ENCODER_VCODEC_LIBX264, vcodec.c_str());
|
2014-04-07 01:34:36 +00:00
|
|
|
}
|
2015-07-21 04:07:26 +00:00
|
|
|
if (vbitrate < 0) {
|
2018-01-01 11:39:57 +00:00
|
|
|
return srs_error_new(ERROR_ENCODER_VBITRATE, "invalid vbitrate: %d", vbitrate);
|
2014-04-07 01:34:36 +00:00
|
|
|
}
|
2015-07-21 04:07:26 +00:00
|
|
|
if (vfps < 0) {
|
2018-01-01 11:39:57 +00:00
|
|
|
return srs_error_new(ERROR_ENCODER_VFPS, "invalid vfps: %.2f", vfps);
|
2014-04-07 01:34:36 +00:00
|
|
|
}
|
2015-07-21 04:07:26 +00:00
|
|
|
if (vwidth < 0) {
|
2018-01-01 11:39:57 +00:00
|
|
|
return srs_error_new(ERROR_ENCODER_VWIDTH, "invalid vwidth: %d", vwidth);
|
2014-04-07 01:34:36 +00:00
|
|
|
}
|
2015-07-21 04:07:26 +00:00
|
|
|
if (vheight < 0) {
|
2018-01-01 11:39:57 +00:00
|
|
|
return srs_error_new(ERROR_ENCODER_VHEIGHT, "invalid vheight: %d", vheight);
|
2014-04-07 01:34:36 +00:00
|
|
|
}
|
|
|
|
if (vthreads < 0) {
|
2018-01-01 11:39:57 +00:00
|
|
|
return srs_error_new(ERROR_ENCODER_VTHREADS, "invalid vthreads: %d", vthreads);
|
2014-04-07 01:34:36 +00:00
|
|
|
}
|
|
|
|
if (vprofile.empty()) {
|
2018-01-01 11:39:57 +00:00
|
|
|
return srs_error_new(ERROR_ENCODER_VPROFILE, "invalid vprofile: %s", vprofile.c_str());
|
2014-04-07 01:34:36 +00:00
|
|
|
}
|
|
|
|
if (vpreset.empty()) {
|
2018-01-01 11:39:57 +00:00
|
|
|
return srs_error_new(ERROR_ENCODER_VPRESET, "invalid vpreset: %s", vpreset.c_str());
|
2014-04-07 01:34:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-11 02:37:50 +00:00
|
|
|
// @see, https://github.com/ossrs/srs/issues/145
|
2015-06-08 07:02:19 +00:00
|
|
|
if (acodec == SRS_RTMP_ENCODER_LIBAACPLUS && acodec != SRS_RTMP_ENCODER_LIBFDKAAC) {
|
2015-07-21 04:07:26 +00:00
|
|
|
if (abitrate != 0 && (abitrate < 16 || abitrate > 72)) {
|
2018-01-01 11:39:57 +00:00
|
|
|
return srs_error_new(ERROR_ENCODER_ABITRATE, "invalid abitrate for aac: %d, must in [16, 72]", abitrate);
|
2014-08-03 05:06:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-14 01:10:36 +00:00
|
|
|
if (acodec != SRS_RTMP_ENCODER_COPY && acodec != SRS_RTMP_ENCODER_NO_AUDIO) {
|
2015-07-21 04:07:26 +00:00
|
|
|
if (abitrate < 0) {
|
2018-01-01 11:39:57 +00:00
|
|
|
return srs_error_new(ERROR_ENCODER_ABITRATE, "invalid abitrate: %d", abitrate);
|
2014-04-07 01:34:36 +00:00
|
|
|
}
|
2015-07-21 04:07:26 +00:00
|
|
|
if (asample_rate < 0) {
|
2018-01-01 11:39:57 +00:00
|
|
|
return srs_error_new(ERROR_ENCODER_ASAMPLE_RATE, "invalid sample rate: %d", asample_rate);
|
2014-04-07 01:34:36 +00:00
|
|
|
}
|
2015-07-21 04:07:26 +00:00
|
|
|
if (achannels != 0 && achannels != 1 && achannels != 2) {
|
2018-01-01 11:39:57 +00:00
|
|
|
return srs_error_new(ERROR_ENCODER_ACHANNELS, "invalid achannels, must be 1 or 2, actual %d", achannels);
|
2014-04-07 01:34:36 +00:00
|
|
|
}
|
|
|
|
}
|
2014-04-07 02:15:44 +00:00
|
|
|
if (_output.empty()) {
|
2018-01-01 11:39:57 +00:00
|
|
|
return srs_error_new(ERROR_ENCODER_OUTPUT, "invalid empty output");
|
2014-04-07 01:34:36 +00:00
|
|
|
}
|
|
|
|
|
2015-01-17 05:04:52 +00:00
|
|
|
// for not rtmp input, donot append the iformat,
|
|
|
|
// for example, "-f flv" before "-i udp://192.168.1.252:2222"
|
2015-11-11 02:37:50 +00:00
|
|
|
// @see https://github.com/ossrs/srs/issues/290
|
2015-10-13 08:54:51 +00:00
|
|
|
if (!srs_string_starts_with(input, "rtmp://")) {
|
2015-01-17 05:04:52 +00:00
|
|
|
iformat = "";
|
|
|
|
}
|
|
|
|
|
2018-01-01 11:39:57 +00:00
|
|
|
return err;
|
2014-04-07 01:34:36 +00:00
|
|
|
}
|
|
|
|
|
2018-01-01 11:39:57 +00:00
|
|
|
srs_error_t SrsFFMPEG::initialize_copy()
|
2014-04-07 05:13:57 +00:00
|
|
|
{
|
2018-01-01 11:39:57 +00:00
|
|
|
srs_error_t err = srs_success;
|
2014-04-07 05:13:57 +00:00
|
|
|
|
2014-04-14 01:10:36 +00:00
|
|
|
vcodec = SRS_RTMP_ENCODER_COPY;
|
|
|
|
acodec = SRS_RTMP_ENCODER_COPY;
|
2017-03-25 09:21:39 +00:00
|
|
|
|
2014-04-07 05:13:57 +00:00
|
|
|
if (_output.empty()) {
|
2018-01-01 11:39:57 +00:00
|
|
|
return srs_error_new(ERROR_ENCODER_OUTPUT, "invalid empty output");
|
2014-04-07 05:13:57 +00:00
|
|
|
}
|
|
|
|
|
2018-01-01 11:39:57 +00:00
|
|
|
return err;
|
2014-04-07 05:13:57 +00:00
|
|
|
}
|
|
|
|
|
2018-01-01 11:39:57 +00:00
|
|
|
srs_error_t SrsFFMPEG::start()
|
2014-04-07 01:34:36 +00:00
|
|
|
{
|
2018-01-01 11:39:57 +00:00
|
|
|
srs_error_t err = srs_success;
|
2014-04-07 01:34:36 +00:00
|
|
|
|
2015-08-24 13:51:05 +00:00
|
|
|
if (process->started()) {
|
2018-01-01 11:39:57 +00:00
|
|
|
return err;
|
2014-04-07 01:34:36 +00:00
|
|
|
}
|
|
|
|
|
2015-08-24 13:51:05 +00:00
|
|
|
// the argv for process.
|
|
|
|
params.clear();
|
2014-04-07 01:34:36 +00:00
|
|
|
|
|
|
|
// argv[0], set to ffmpeg bin.
|
|
|
|
// The execv() and execvp() functions ....
|
2015-08-24 13:51:05 +00:00
|
|
|
// The first argument, by convention, should point to
|
2014-04-07 01:34:36 +00:00
|
|
|
// the filename associated with the file being executed.
|
|
|
|
params.push_back(ffmpeg);
|
|
|
|
|
2014-04-07 06:20:03 +00:00
|
|
|
// input params
|
2020-02-18 11:59:47 +00:00
|
|
|
for (int i = 0; i < (int)iparams.size(); i++) {
|
2020-02-05 04:32:15 +00:00
|
|
|
string iparam = iparams.at(i);
|
|
|
|
if (!iparam.empty()) {
|
|
|
|
params.push_back(iparam);
|
|
|
|
}
|
2014-04-07 06:20:03 +00:00
|
|
|
}
|
|
|
|
|
2017-01-06 02:39:37 +00:00
|
|
|
// build the perfile
|
|
|
|
if (!perfile.empty()) {
|
|
|
|
std::vector<std::string>::iterator it;
|
|
|
|
for (it = perfile.begin(); it != perfile.end(); ++it) {
|
|
|
|
std::string p = *it;
|
|
|
|
if (!p.empty()) {
|
|
|
|
params.push_back(p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-07 01:34:36 +00:00
|
|
|
// input.
|
2014-07-19 07:20:16 +00:00
|
|
|
if (iformat != "off" && !iformat.empty()) {
|
2014-07-19 02:54:38 +00:00
|
|
|
params.push_back("-f");
|
|
|
|
params.push_back(iformat);
|
|
|
|
}
|
2014-04-07 01:34:36 +00:00
|
|
|
|
|
|
|
params.push_back("-i");
|
|
|
|
params.push_back(input);
|
|
|
|
|
|
|
|
// build the filter
|
|
|
|
if (!vfilter.empty()) {
|
|
|
|
std::vector<std::string>::iterator it;
|
|
|
|
for (it = vfilter.begin(); it != vfilter.end(); ++it) {
|
|
|
|
std::string p = *it;
|
|
|
|
if (!p.empty()) {
|
|
|
|
params.push_back(p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// video specified.
|
2014-04-14 01:10:36 +00:00
|
|
|
if (vcodec != SRS_RTMP_ENCODER_NO_VIDEO) {
|
2014-04-07 01:34:36 +00:00
|
|
|
params.push_back("-vcodec");
|
|
|
|
params.push_back(vcodec);
|
|
|
|
} else {
|
|
|
|
params.push_back("-vn");
|
|
|
|
}
|
|
|
|
|
|
|
|
// the codec params is disabled when copy
|
2014-04-14 01:10:36 +00:00
|
|
|
if (vcodec != SRS_RTMP_ENCODER_COPY && vcodec != SRS_RTMP_ENCODER_NO_VIDEO) {
|
2015-07-21 04:07:26 +00:00
|
|
|
if (vbitrate > 0) {
|
|
|
|
params.push_back("-b:v");
|
2015-09-24 09:54:58 +00:00
|
|
|
params.push_back(srs_int2str(vbitrate * 1000));
|
2015-07-21 04:07:26 +00:00
|
|
|
}
|
2014-04-07 01:34:36 +00:00
|
|
|
|
2015-07-21 04:07:26 +00:00
|
|
|
if (vfps > 0) {
|
|
|
|
params.push_back("-r");
|
2015-09-24 09:54:58 +00:00
|
|
|
params.push_back(srs_float2str(vfps));
|
2015-07-21 04:07:26 +00:00
|
|
|
}
|
2014-04-07 01:34:36 +00:00
|
|
|
|
2015-07-21 04:07:26 +00:00
|
|
|
if (vwidth > 0 && vheight > 0) {
|
|
|
|
params.push_back("-s");
|
2015-09-24 09:54:58 +00:00
|
|
|
params.push_back(srs_int2str(vwidth) + "x" + srs_int2str(vheight));
|
2015-07-21 04:07:26 +00:00
|
|
|
}
|
2014-04-07 01:34:36 +00:00
|
|
|
|
|
|
|
// TODO: add aspect if needed.
|
2015-07-21 04:07:26 +00:00
|
|
|
if (vwidth > 0 && vheight > 0) {
|
|
|
|
params.push_back("-aspect");
|
2015-09-24 09:54:58 +00:00
|
|
|
params.push_back(srs_int2str(vwidth) + ":" + srs_int2str(vheight));
|
2015-07-21 04:07:26 +00:00
|
|
|
}
|
2014-04-07 01:34:36 +00:00
|
|
|
|
2015-07-21 04:07:26 +00:00
|
|
|
if (vthreads > 0) {
|
|
|
|
params.push_back("-threads");
|
2015-09-24 09:54:58 +00:00
|
|
|
params.push_back(srs_int2str(vthreads));
|
2015-07-21 04:07:26 +00:00
|
|
|
}
|
2014-04-07 01:34:36 +00:00
|
|
|
|
2015-10-20 06:52:34 +00:00
|
|
|
if (!vprofile.empty()) {
|
|
|
|
params.push_back("-profile:v");
|
|
|
|
params.push_back(vprofile);
|
|
|
|
}
|
2014-04-07 01:34:36 +00:00
|
|
|
|
2015-10-20 06:52:34 +00:00
|
|
|
if (!vpreset.empty()) {
|
|
|
|
params.push_back("-preset");
|
|
|
|
params.push_back(vpreset);
|
|
|
|
}
|
2014-04-07 01:34:36 +00:00
|
|
|
|
|
|
|
// vparams
|
|
|
|
if (!vparams.empty()) {
|
|
|
|
std::vector<std::string>::iterator it;
|
|
|
|
for (it = vparams.begin(); it != vparams.end(); ++it) {
|
|
|
|
std::string p = *it;
|
|
|
|
if (!p.empty()) {
|
|
|
|
params.push_back(p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// audio specified.
|
2014-04-14 01:10:36 +00:00
|
|
|
if (acodec != SRS_RTMP_ENCODER_NO_AUDIO) {
|
2014-04-07 01:34:36 +00:00
|
|
|
params.push_back("-acodec");
|
|
|
|
params.push_back(acodec);
|
|
|
|
} else {
|
|
|
|
params.push_back("-an");
|
|
|
|
}
|
|
|
|
|
|
|
|
// the codec params is disabled when copy
|
2015-04-20 03:24:12 +00:00
|
|
|
if (acodec != SRS_RTMP_ENCODER_NO_AUDIO) {
|
|
|
|
if (acodec != SRS_RTMP_ENCODER_COPY) {
|
2015-07-21 04:07:26 +00:00
|
|
|
if (abitrate > 0) {
|
|
|
|
params.push_back("-b:a");
|
2015-09-24 09:54:58 +00:00
|
|
|
params.push_back(srs_int2str(abitrate * 1000));
|
2015-07-21 04:07:26 +00:00
|
|
|
}
|
2015-04-20 03:24:12 +00:00
|
|
|
|
2015-07-21 04:07:26 +00:00
|
|
|
if (asample_rate > 0) {
|
|
|
|
params.push_back("-ar");
|
2015-09-24 09:54:58 +00:00
|
|
|
params.push_back(srs_int2str(asample_rate));
|
2015-07-21 04:07:26 +00:00
|
|
|
}
|
2015-04-20 03:24:12 +00:00
|
|
|
|
2015-07-21 04:07:26 +00:00
|
|
|
if (achannels > 0) {
|
|
|
|
params.push_back("-ac");
|
2015-09-24 09:54:58 +00:00
|
|
|
params.push_back(srs_int2str(achannels));
|
2015-07-21 04:07:26 +00:00
|
|
|
}
|
2015-04-20 03:24:12 +00:00
|
|
|
|
|
|
|
// aparams
|
2014-04-07 01:34:36 +00:00
|
|
|
std::vector<std::string>::iterator it;
|
|
|
|
for (it = aparams.begin(); it != aparams.end(); ++it) {
|
|
|
|
std::string p = *it;
|
|
|
|
if (!p.empty()) {
|
|
|
|
params.push_back(p);
|
|
|
|
}
|
|
|
|
}
|
2015-04-20 03:24:12 +00:00
|
|
|
} else {
|
|
|
|
// for audio copy.
|
|
|
|
for (int i = 0; i < (int)aparams.size();) {
|
|
|
|
std::string pn = aparams[i++];
|
|
|
|
|
|
|
|
// aparams, the adts to asc filter "-bsf:a aac_adtstoasc"
|
|
|
|
if (pn == "-bsf:a" && i < (int)aparams.size()) {
|
|
|
|
std::string pv = aparams[i++];
|
|
|
|
if (pv == "aac_adtstoasc") {
|
|
|
|
params.push_back(pn);
|
|
|
|
params.push_back(pv);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-04-07 01:34:36 +00:00
|
|
|
}
|
|
|
|
}
|
2015-08-24 13:51:05 +00:00
|
|
|
|
2014-04-07 01:34:36 +00:00
|
|
|
// output
|
2014-07-19 07:20:16 +00:00
|
|
|
if (oformat != "off" && !oformat.empty()) {
|
2014-07-19 02:54:38 +00:00
|
|
|
params.push_back("-f");
|
|
|
|
params.push_back(oformat);
|
|
|
|
}
|
2014-04-07 01:34:36 +00:00
|
|
|
|
|
|
|
params.push_back("-y");
|
2014-04-07 02:15:44 +00:00
|
|
|
params.push_back(_output);
|
2014-08-03 05:06:37 +00:00
|
|
|
|
2015-08-24 13:51:05 +00:00
|
|
|
// when specified the log file.
|
2015-08-24 14:19:57 +00:00
|
|
|
if (!log_file.empty()) {
|
2015-08-24 13:51:05 +00:00
|
|
|
// 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);
|
2014-04-07 01:34:36 +00:00
|
|
|
}
|
|
|
|
|
2015-08-24 13:51:05 +00:00
|
|
|
// initialize the process.
|
2018-01-01 11:39:57 +00:00
|
|
|
if ((err = process->initialize(ffmpeg, params)) != srs_success) {
|
|
|
|
return srs_error_wrap(err, "init process");
|
2014-04-07 01:34:36 +00:00
|
|
|
}
|
|
|
|
|
2015-08-24 13:51:05 +00:00
|
|
|
return process->start();
|
2014-04-07 01:34:36 +00:00
|
|
|
}
|
|
|
|
|
2018-01-01 11:39:57 +00:00
|
|
|
srs_error_t SrsFFMPEG::cycle()
|
2014-04-07 01:34:36 +00:00
|
|
|
{
|
2015-08-24 13:51:05 +00:00
|
|
|
return process->cycle();
|
2014-04-07 01:34:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SrsFFMPEG::stop()
|
|
|
|
{
|
2015-08-24 13:51:05 +00:00
|
|
|
process->stop();
|
2014-04-07 01:34:36 +00:00
|
|
|
}
|
|
|
|
|
2015-05-30 03:25:33 +00:00
|
|
|
void SrsFFMPEG::fast_stop()
|
|
|
|
{
|
2015-08-24 13:51:05 +00:00
|
|
|
process->fast_stop();
|
2015-05-30 03:25:33 +00:00
|
|
|
}
|
|
|
|
|
2020-01-29 12:22:28 +00:00
|
|
|
void SrsFFMPEG::fast_kill()
|
|
|
|
{
|
|
|
|
process->fast_kill();
|
|
|
|
}
|
|
|
|
|
2014-04-07 01:34:36 +00:00
|
|
|
#endif
|
|
|
|
|
2014-08-02 14:18:39 +00:00
|
|
|
|