Commit bc125e65 by xiongziliang

addFFmpegSource接口支持enable_hls、enable_mp4参数

parent 3cdc8938
...@@ -428,7 +428,7 @@ ...@@ -428,7 +428,7 @@
"method": "GET", "method": "GET",
"header": [], "header": [],
"url": { "url": {
"raw": "{{ZLMediaKit_URL}}/index/api/addStreamProxy?secret={{ZLMediaKit_secret}}&vhost={{defaultVhost}}&app=live&stream=test&url=rtmp://live.hkstv.hk.lxdns.com/live/hks2&enable_rtsp=1&enable_rtmp=1", "raw": "{{ZLMediaKit_URL}}/index/api/addStreamProxy?secret={{ZLMediaKit_secret}}&vhost={{defaultVhost}}&app=live&stream=test&url=rtmp://live.hkstv.hk.lxdns.com/live/hks2",
"host": [ "host": [
"{{ZLMediaKit_URL}}" "{{ZLMediaKit_URL}}"
], ],
...@@ -523,7 +523,7 @@ ...@@ -523,7 +523,7 @@
"method": "GET", "method": "GET",
"header": [], "header": [],
"url": { "url": {
"raw": "{{ZLMediaKit_URL}}/index/api/addFFmpegSource?secret={{ZLMediaKit_secret}}&src_url=http://live.hkstv.hk.lxdns.com/live/hks2/playlist.m3u8&dst_url=rtmp://10.8.9.115:8554/live/hks2&timeout_ms=10000", "raw": "{{ZLMediaKit_URL}}/index/api/addFFmpegSource?secret={{ZLMediaKit_secret}}&src_url=http://hefeng.live.tempsource.cjyun.org/videotmp/s10100-hftv.m3u8&dst_url=rtmp://127.0.0.1/live/hks2&timeout_ms=10000&enable_hls=0&enable_mp4=0",
"host": [ "host": [
"{{ZLMediaKit_URL}}" "{{ZLMediaKit_URL}}"
], ],
...@@ -540,7 +540,7 @@ ...@@ -540,7 +540,7 @@
}, },
{ {
"key": "src_url", "key": "src_url",
"value": "http://live.hkstv.hk.lxdns.com/live/hks2/playlist.m3u8", "value": "http://hefeng.live.tempsource.cjyun.org/videotmp/s10100-hftv.m3u8",
"description": "FFmpeg拉流地址,支持任意协议或格式(只要FFmpeg支持即可)" "description": "FFmpeg拉流地址,支持任意协议或格式(只要FFmpeg支持即可)"
}, },
{ {
...@@ -552,6 +552,16 @@ ...@@ -552,6 +552,16 @@
"key": "timeout_ms", "key": "timeout_ms",
"value": "10000", "value": "10000",
"description": "FFmpeg推流成功超时时间,单位毫秒" "description": "FFmpeg推流成功超时时间,单位毫秒"
},
{
"key": "enable_hls",
"value": "0",
"description": "是否开启hls录制"
},
{
"key": "enable_mp4",
"value": "0",
"description": "是否开启mp4录制"
} }
] ]
} }
......
...@@ -59,6 +59,11 @@ static bool is_local_ip(const string &ip){ ...@@ -59,6 +59,11 @@ static bool is_local_ip(const string &ip){
return false; return false;
} }
void FFmpegSource::setupRecord(bool enable_hls, bool enable_mp4){
_enable_hls = enable_hls;
_enable_mp4 = enable_mp4;
}
void FFmpegSource::play(const string &src_url,const string &dst_url,int timeout_ms,const onPlay &cb) { void FFmpegSource::play(const string &src_url,const string &dst_url,int timeout_ms,const onPlay &cb) {
GET_CONFIG(string,ffmpeg_bin,FFmpeg::kBin); GET_CONFIG(string,ffmpeg_bin,FFmpeg::kBin);
GET_CONFIG(string,ffmpeg_cmd,FFmpeg::kCmd); GET_CONFIG(string,ffmpeg_cmd,FFmpeg::kCmd);
...@@ -263,6 +268,12 @@ void FFmpegSource::onGetMediaSource(const MediaSource::Ptr &src) { ...@@ -263,6 +268,12 @@ void FFmpegSource::onGetMediaSource(const MediaSource::Ptr &src) {
//防止多次进入onGetMediaSource函数导致无限递归调用的bug //防止多次进入onGetMediaSource函数导致无限递归调用的bug
setDelegate(listener); setDelegate(listener);
src->setListener(shared_from_this()); src->setListener(shared_from_this());
if (_enable_hls) {
src->setupRecord(Recorder::type_hls, true, "");
}
if (_enable_mp4) {
src->setupRecord(Recorder::type_mp4, true, "");
}
} }
} }
......
...@@ -46,13 +46,29 @@ public: ...@@ -46,13 +46,29 @@ public:
typedef function<void(const SockException &ex)> onPlay; typedef function<void(const SockException &ex)> onPlay;
FFmpegSource(); FFmpegSource();
virtual ~FFmpegSource(); ~FFmpegSource();
/** /**
* 设置主动关闭回调 * 设置主动关闭回调
* @param cb
*/ */
void setOnClose(const function<void()> &cb); void setOnClose(const function<void()> &cb);
void play(const string &src_url,const string &dst_url,int timeout_ms,const onPlay &cb);
/**
* 开始播放url
* @param src_url FFmpeg拉流地址
* @param dst_url FFmpeg推流地址
* @param timeout_ms 等待结果超时时间,单位毫秒
* @param cb 成功与否回调
*/
void play(const string &src_url, const string &dst_url, int timeout_ms, const onPlay &cb);
/**
* 设置录制
* @param enable_hls 是否开启hls直播或录制
* @param enable_mp4 是否录制mp4
*/
void setupRecord(bool enable_hls, bool enable_mp4);
private: private:
void findAsync(int maxWaitMS ,const function<void(const MediaSource::Ptr &src)> &cb); void findAsync(int maxWaitMS ,const function<void(const MediaSource::Ptr &src)> &cb);
void startTimer(int timeout_ms); void startTimer(int timeout_ms);
...@@ -69,6 +85,8 @@ private: ...@@ -69,6 +85,8 @@ private:
std::shared_ptr<SockInfo> getOriginSock(MediaSource &sender) const override; std::shared_ptr<SockInfo> getOriginSock(MediaSource &sender) const override;
private: private:
bool _enable_hls = false;
bool _enable_mp4 = false;
Process _process; Process _process;
Timer::Ptr _timer; Timer::Ptr _timer;
EventPoller::Ptr _poller; EventPoller::Ptr _poller;
......
...@@ -694,28 +694,31 @@ void installWebApi() { ...@@ -694,28 +694,31 @@ void installWebApi() {
static auto addFFmpegSource = [](const string &src_url, static auto addFFmpegSource = [](const string &src_url,
const string &dst_url, const string &dst_url,
int timeout_ms, int timeout_ms,
const function<void(const SockException &ex,const string &key)> &cb){ bool enable_hls,
bool enable_mp4,
const function<void(const SockException &ex, const string &key)> &cb) {
auto key = MD5(dst_url).hexdigest(); auto key = MD5(dst_url).hexdigest();
lock_guard<decltype(s_ffmpegMapMtx)> lck(s_ffmpegMapMtx); lock_guard<decltype(s_ffmpegMapMtx)> lck(s_ffmpegMapMtx);
if(s_ffmpegMap.find(key) != s_ffmpegMap.end()){ if (s_ffmpegMap.find(key) != s_ffmpegMap.end()) {
//已经在拉流了 //已经在拉流了
cb(SockException(Err_success),key); cb(SockException(Err_success), key);
return; return;
} }
FFmpegSource::Ptr ffmpeg = std::make_shared<FFmpegSource>(); FFmpegSource::Ptr ffmpeg = std::make_shared<FFmpegSource>();
s_ffmpegMap[key] = ffmpeg; s_ffmpegMap[key] = ffmpeg;
ffmpeg->setOnClose([key](){ ffmpeg->setOnClose([key]() {
lock_guard<decltype(s_ffmpegMapMtx)> lck(s_ffmpegMapMtx); lock_guard<decltype(s_ffmpegMapMtx)> lck(s_ffmpegMapMtx);
s_ffmpegMap.erase(key); s_ffmpegMap.erase(key);
}); });
ffmpeg->play(src_url, dst_url,timeout_ms,[cb , key](const SockException &ex){ ffmpeg->setupRecord(enable_hls, enable_mp4);
if(ex){ ffmpeg->play(src_url, dst_url, timeout_ms, [cb, key](const SockException &ex) {
if (ex) {
lock_guard<decltype(s_ffmpegMapMtx)> lck(s_ffmpegMapMtx); lock_guard<decltype(s_ffmpegMapMtx)> lck(s_ffmpegMapMtx);
s_ffmpegMap.erase(key); s_ffmpegMap.erase(key);
} }
cb(ex,key); cb(ex, key);
}); });
}; };
...@@ -727,12 +730,15 @@ void installWebApi() { ...@@ -727,12 +730,15 @@ void installWebApi() {
auto src_url = allArgs["src_url"]; auto src_url = allArgs["src_url"];
auto dst_url = allArgs["dst_url"]; auto dst_url = allArgs["dst_url"];
int timeout_ms = allArgs["timeout_ms"]; int timeout_ms = allArgs["timeout_ms"];
auto enable_hls = allArgs["enable_hls"].as<int>();
auto enable_mp4 = allArgs["enable_mp4"].as<int>();
addFFmpegSource(src_url,dst_url,timeout_ms,[invoker,val,headerOut](const SockException &ex,const string &key){ addFFmpegSource(src_url, dst_url, timeout_ms, enable_hls, enable_mp4,
if(ex){ [invoker, val, headerOut](const SockException &ex, const string &key) {
if (ex) {
const_cast<Value &>(val)["code"] = API::OtherFailed; const_cast<Value &>(val)["code"] = API::OtherFailed;
const_cast<Value &>(val)["msg"] = ex.what(); const_cast<Value &>(val)["msg"] = ex.what();
}else{ } else {
const_cast<Value &>(val)["data"]["key"] = key; const_cast<Value &>(val)["data"]["key"] = key;
} }
invoker("200 OK", headerOut, val.toStyledString()); invoker("200 OK", headerOut, val.toStyledString());
...@@ -1084,6 +1090,8 @@ void installWebApi() { ...@@ -1084,6 +1090,8 @@ void installWebApi() {
addFFmpegSource("http://hls-ott-zhibo.wasu.tv/live/272/index.m3u8",/** ffmpeg拉流支持任意编码格式任意协议 **/ addFFmpegSource("http://hls-ott-zhibo.wasu.tv/live/272/index.m3u8",/** ffmpeg拉流支持任意编码格式任意协议 **/
dst_url, dst_url,
(1000 * timeout_sec) - 500, (1000 * timeout_sec) - 500,
false,
false,
[invoker,val,headerOut](const SockException &ex,const string &key){ [invoker,val,headerOut](const SockException &ex,const string &key){
if(ex){ if(ex){
const_cast<Value &>(val)["code"] = API::OtherFailed; const_cast<Value &>(val)["code"] = API::OtherFailed;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论