From 7c6b612a4d0a0b966c4bdb7f4475b2d037408f53 Mon Sep 17 00:00:00 2001 From: xiangshengjye <46069012+xiangshengjye@users.noreply.github.com> Date: Thu, 6 Jul 2023 14:11:21 +0800 Subject: [PATCH] =?UTF-8?q?c=20sdk=E6=96=B0=E5=A2=9Empeg-ps/ts=E6=89=93?= =?UTF-8?q?=E5=8C=85=E6=8E=A5=E5=8F=A3=20(#2620)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/include/mk_frame.h | 53 +++++++++++++++++++++++++++++++++ api/source/mk_frame.cpp | 65 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) diff --git a/api/include/mk_frame.h b/api/include/mk_frame.h index 5df8a617..62498096 100644 --- a/api/include/mk_frame.h +++ b/api/include/mk_frame.h @@ -166,6 +166,59 @@ API_EXPORT void API_CALL mk_frame_merger_input(mk_frame_merger ctx, mk_frame fra */ API_EXPORT void API_CALL mk_frame_merger_flush(mk_frame_merger ctx); +////////////////////////////////////////////////////////////////////// + +typedef struct mk_mpeg_muxer_t *mk_mpeg_muxer; + +/** + * mpeg-ps/ts 打包器输出回调函数 + * @param user_data 设置回调时的用户数据指针 + * @param muxer 对象 + * @param frame 帧数据 + * @param size 帧数据长度 + * @param timestamp 时间戳 + * @param key_pos 是否关键帧 + */ +typedef void(API_CALL *on_mk_mpeg_muxer_frame)(void *user_data, mk_mpeg_muxer muxer, const char *frame, size_t size, uint64_t timestamp, int key_pos); + +/** + * mpeg-ps/ts 打包器 + * @param cb 打包回调函数 + * @param user_data 回调用户数据指针 + * @param is_ps 是否是ps + * @return 打包器对象 + */ +API_EXPORT mk_mpeg_muxer API_CALL mk_mpeg_muxer_create(on_mk_mpeg_muxer_frame cb, void *user_data, int is_ps); + +/** + * 删除mpeg-ps/ts 打包器 + * @param ctx 打包器 + */ +API_EXPORT void API_CALL mk_mpeg_muxer_release(mk_mpeg_muxer ctx); + +/** + * 添加音视频track + * @param ctx mk_mpeg_muxer对象 + * @param track mk_track对象,音视频轨道 + */ +API_EXPORT void API_CALL mk_mpeg_muxer_init_track(mk_mpeg_muxer ctx, void* track); + +/** + * 初始化track完毕后调用此函数, + * 在单track(只有音频或视频)时,因为ZLMediaKit不知道后续是否还要添加track,所以会多等待3秒钟 + * 如果产生的流是单Track类型,请调用此函数以便加快流生成速度,当然不调用该函数,影响也不大(会多等待3秒) + * @param ctx 对象指针 + */ +API_EXPORT void API_CALL mk_mpeg_muxer_init_complete(mk_mpeg_muxer ctx); + +/** + * 输入frame对象 + * @param ctx mk_mpeg_muxer对象 + * @param frame 帧对象 + * @return 1代表成功,0失败 + */ +API_EXPORT int API_CALL mk_mpeg_muxer_input_frame(mk_mpeg_muxer ctx, mk_frame frame); + #ifdef __cplusplus } #endif diff --git a/api/source/mk_frame.cpp b/api/source/mk_frame.cpp index c136d76f..7a7cdb85 100644 --- a/api/source/mk_frame.cpp +++ b/api/source/mk_frame.cpp @@ -9,10 +9,12 @@ */ #include "mk_frame.h" +#include "mk_track.h" #include "Extension/Frame.h" #include "Extension/H264.h" #include "Extension/H265.h" #include "Extension/AAC.h" +#include "Record/MPEG.h" using namespace mediakit; @@ -204,3 +206,66 @@ API_EXPORT void API_CALL mk_frame_merger_input(mk_frame_merger ctx, mk_frame fra cb(user_data, dts, pts, (mk_buffer)(&buffer), have_key_frame); }); } + +////////////////////////////////////////////////////////////////////// + +class MpegMuxerForC : public MpegMuxer { +public: + using onMuxer = std::function; + MpegMuxerForC(bool is_ps) : MpegMuxer(is_ps) { + _cb = nullptr; + } + ~MpegMuxerForC() { MpegMuxer::flush(); }; + + void setOnMuxer(onMuxer cb) { + _cb = std::move(cb); + } + +private: + void onWrite(std::shared_ptr buffer, uint64_t timestamp, bool key_pos) override { + if (_cb) { + if (!buffer) { + _cb(nullptr, 0, timestamp, key_pos); + } else { + _cb(buffer->data(), buffer->size(), timestamp, key_pos); + } + } + } + +private: + onMuxer _cb; +}; + +API_EXPORT mk_mpeg_muxer API_CALL mk_mpeg_muxer_create(on_mk_mpeg_muxer_frame cb, void *user_data, int is_ps){ + assert(cb); + auto ret = new MpegMuxerForC(is_ps); + std::shared_ptr ptr(user_data, [](void *) {}); + ret->setOnMuxer([cb, ptr, ret](const char *frame, size_t size, uint64_t timestamp, int key_pos) { + cb(ptr.get(), reinterpret_cast(ret), frame, size, timestamp, key_pos); + }); + return reinterpret_cast(ret); +} + +API_EXPORT void API_CALL mk_mpeg_muxer_release(mk_mpeg_muxer ctx){ + assert(ctx); + auto ptr = reinterpret_cast(ctx); + delete ptr; +} + +API_EXPORT void API_CALL mk_mpeg_muxer_init_track(mk_mpeg_muxer ctx, void* track) { + assert(ctx && track); + auto ptr = reinterpret_cast(ctx); + ptr->addTrack(*((Track::Ptr *) track)); +} + +API_EXPORT void API_CALL mk_mpeg_muxer_init_complete(mk_mpeg_muxer ctx) { + assert(ctx); + auto ptr = reinterpret_cast(ctx); + ptr->addTrackCompleted(); +} + +API_EXPORT int API_CALL mk_mpeg_muxer_input_frame(mk_mpeg_muxer ctx, mk_frame frame){ + assert(ctx && frame); + auto ptr = reinterpret_cast(ctx); + return ptr->inputFrame(*((Frame::Ptr *) frame)); +} \ No newline at end of file