diff --git a/api/include/mk_media.h b/api/include/mk_media.h index e2eeba8c..4f56a4f8 100755 --- a/api/include/mk_media.h +++ b/api/include/mk_media.h @@ -129,6 +129,31 @@ API_EXPORT void API_CALL mk_media_input_aac(mk_media ctx, void *data, int len, u */ API_EXPORT void API_CALL mk_media_input_aac1(mk_media ctx, void *data, int len, uint32_t dts, void *adts); +/** + * 在调用对应的MediaSource.close()时会触发该回调 + * 你可以在该事件中做清理工作(比如说关闭摄像头,同时调用mk_media_release函数销毁该对象) + * @param user_data 用户数据指针,通过mk_media_set_on_close函数设置 + * @return 返回0告知事件触发者关闭媒体失败,非0代表成功 + */ +typedef int(API_CALL *on_mk_media_close)(void *user_data); + +/** + * 监听MediaSource.close()事件 + * 在选择关闭一个MediaSource时,将会最终触发到该回调 + * 你可以通过该事件选择删除对象,当然你在该事件中也可以什么都不做 + * @param ctx 对象指针 + * @param cb 回调指针 + * @param user_data 用户数据指针 + */ +API_EXPORT void API_CALL mk_media_set_on_close(mk_media ctx, on_mk_media_close cb, void *user_data); + +/** + * 获取总的观看人数 + * @param ctx 对象指针 + * @return 观看人数 + */ +API_EXPORT int API_CALL mk_media_total_reader_count(mk_media ctx); + #ifdef __cplusplus } #endif diff --git a/api/source/mk_media.cpp b/api/source/mk_media.cpp index a09525fd..e1ffea59 100755 --- a/api/source/mk_media.cpp +++ b/api/source/mk_media.cpp @@ -32,77 +32,151 @@ using namespace std; using namespace toolkit; using namespace mediakit; +class MediaHelper : public MediaSourceEvent , public std::enable_shared_from_this { +public: + typedef std::shared_ptr Ptr; + template + MediaHelper(ArgsType &&...args){ + _channel = std::make_shared(std::forward(args)...); + } + ~MediaHelper(){} + + void attachEvent(){ + _channel->setListener(shared_from_this()); + } + + DevChannel::Ptr &getChannel(){ + return _channel; + } + + void setCallBack(on_mk_media_close cb, void *user_data){ + _cb = cb; + _user_data = user_data; + } +protected: + // 通知其停止推流 + bool close(MediaSource &sender,bool force) override{ + if(!force && _channel->totalReaderCount()){ + //非强制关闭且正有人在观看该视频 + return false; + } + if(!_cb){ + //未设置回调,没法关闭 + return false; + } + if(!_cb(_user_data)){ + //回调选择返回不关闭该视频 + return false; + } + + //回调中已经关闭该视频 + string err = StrPrinter << "close media:" << sender.getSchema() << "/" << sender.getVhost() << "/" << sender.getApp() << "/" << sender.getId() << " " << force; + return true; + } + + // 通知无人观看 + void onNoneReader(MediaSource &sender) override{ + if(_channel->totalReaderCount()){ + //统计有误,还有人在看 + return; + } + MediaSourceEvent::onNoneReader(sender); + } + + // 观看总人数 + int totalReaderCount(MediaSource &sender) override{ + return _channel->totalReaderCount(); + } +private: + DevChannel::Ptr _channel; + on_mk_media_close _cb; + void *_user_data; +}; + +API_EXPORT void API_CALL mk_media_set_on_close(mk_media ctx, on_mk_media_close cb, void *user_data){ + assert(ctx); + MediaHelper::Ptr *obj = (MediaHelper::Ptr *) ctx; + (*obj)->setCallBack(cb,user_data); +} + +API_EXPORT int API_CALL mk_media_total_reader_count(mk_media ctx){ + assert(ctx); + MediaHelper::Ptr *obj = (MediaHelper::Ptr *) ctx; + return (*obj)->getChannel()->totalReaderCount(); +} + API_EXPORT mk_media API_CALL mk_media_create(const char *vhost, const char *app, const char *stream, float duration, int hls_enabled, int mp4_enabled) { assert(vhost && app && stream); - DevChannel::Ptr *obj(new DevChannel::Ptr(new DevChannel(vhost, app, stream, duration, true, true, hls_enabled, mp4_enabled))); + MediaHelper::Ptr *obj(new MediaHelper::Ptr(new MediaHelper(vhost, app, stream, duration, true, true, hls_enabled, mp4_enabled))); + (*obj)->attachEvent(); return (mk_media) obj; } API_EXPORT void API_CALL mk_media_release(mk_media ctx) { assert(ctx); - DevChannel::Ptr *obj = (DevChannel::Ptr *) ctx; + MediaHelper::Ptr *obj = (MediaHelper::Ptr *) ctx; delete obj; } API_EXPORT void API_CALL mk_media_init_h264(mk_media ctx, int width, int height, int frameRate) { assert(ctx); - DevChannel::Ptr *obj = (DevChannel::Ptr *) ctx; + MediaHelper::Ptr *obj = (MediaHelper::Ptr *) ctx; VideoInfo info; info.iFrameRate = frameRate; info.iWidth = width; info.iHeight = height; - (*obj)->initVideo(info); + (*obj)->getChannel()->initVideo(info); } API_EXPORT void API_CALL mk_media_init_h265(mk_media ctx, int width, int height, int frameRate) { assert(ctx); - DevChannel::Ptr *obj = (DevChannel::Ptr *) ctx; + MediaHelper::Ptr *obj = (MediaHelper::Ptr *) ctx; VideoInfo info; info.iFrameRate = frameRate; info.iWidth = width; info.iHeight = height; - (*obj)->initH265Video(info); + (*obj)->getChannel()->initH265Video(info); } API_EXPORT void API_CALL mk_media_init_aac(mk_media ctx, int channel, int sample_bit, int sample_rate, int profile) { assert(ctx); - DevChannel::Ptr *obj = (DevChannel::Ptr *) ctx; + MediaHelper::Ptr *obj = (MediaHelper::Ptr *) ctx; AudioInfo info; info.iSampleRate = sample_rate; info.iChannel = channel; info.iSampleBit = sample_bit; info.iProfile = profile; - (*obj)->initAudio(info); + (*obj)->getChannel()->initAudio(info); } API_EXPORT void API_CALL mk_media_init_complete(mk_media ctx){ assert(ctx); - DevChannel::Ptr *obj = (DevChannel::Ptr *) ctx; - (*obj)->addTrackCompleted(); + MediaHelper::Ptr *obj = (MediaHelper::Ptr *) ctx; + (*obj)->getChannel()->addTrackCompleted(); } API_EXPORT void API_CALL mk_media_input_h264(mk_media ctx, void *data, int len, uint32_t dts, uint32_t pts) { assert(ctx && data && len > 0); - DevChannel::Ptr *obj = (DevChannel::Ptr *) ctx; - (*obj)->inputH264((char *) data, len, dts, pts); + MediaHelper::Ptr *obj = (MediaHelper::Ptr *) ctx; + (*obj)->getChannel()->inputH264((char *) data, len, dts, pts); } API_EXPORT void API_CALL mk_media_input_h265(mk_media ctx, void *data, int len, uint32_t dts, uint32_t pts) { assert(ctx && data && len > 0); - DevChannel::Ptr *obj = (DevChannel::Ptr *) ctx; - (*obj)->inputH265((char *) data, len, dts, pts); + MediaHelper::Ptr *obj = (MediaHelper::Ptr *) ctx; + (*obj)->getChannel()->inputH265((char *) data, len, dts, pts); } API_EXPORT void API_CALL mk_media_input_aac(mk_media ctx, void *data, int len, uint32_t dts, int with_adts_header) { assert(ctx && data && len > 0); - DevChannel::Ptr *obj = (DevChannel::Ptr *) ctx; - (*obj)->inputAAC((char *) data, len, dts, with_adts_header); + MediaHelper::Ptr *obj = (MediaHelper::Ptr *) ctx; + (*obj)->getChannel()->inputAAC((char *) data, len, dts, with_adts_header); } API_EXPORT void API_CALL mk_media_input_aac1(mk_media ctx, void *data, int len, uint32_t dts, void *adts) { assert(ctx && data && len > 0 && adts); - DevChannel::Ptr *obj = (DevChannel::Ptr *) ctx; - (*obj)->inputAAC((char *) data, len, dts, (char *) adts); + MediaHelper::Ptr *obj = (MediaHelper::Ptr *) ctx; + (*obj)->getChannel()->inputAAC((char *) data, len, dts, (char *) adts); }