diff --git a/3rdpart/media-server b/3rdpart/media-server index 82a48c57..5d8f1536 160000 --- a/3rdpart/media-server +++ b/3rdpart/media-server @@ -1 +1 @@ -Subproject commit 82a48c57ae5269aaa70a8c3df8a67dc06b05d0cd +Subproject commit 5d8f1536bd4c70be8f2d7ff30fde3c36877477c8 diff --git a/src/Record/MP4.cpp b/src/Record/MP4.cpp index 0dd1756a..a6a141ed 100644 --- a/src/Record/MP4.cpp +++ b/src/Record/MP4.cpp @@ -13,34 +13,119 @@ #include "Util/File.h" #include "Util/logger.h" #include "Common/config.h" +#include "fmp4-writer.h" + using namespace toolkit; namespace mediakit { +struct mp4_writer_t { + int is_fmp4; + union { + fmp4_writer_t *fmp4; + mov_writer_t *mov; + } u; +}; + +mp4_writer_t* mp4_writer_create(int is_fmp4, const struct mov_buffer_t *buffer, void* param, int flags){ + mp4_writer_t *mp4 = (mp4_writer_t *) malloc(sizeof(mp4_writer_t)); + mp4->is_fmp4 = is_fmp4; + if (is_fmp4) { + mp4->u.fmp4 = fmp4_writer_create(buffer, param, flags); + } else { + mp4->u.mov = mov_writer_create(buffer, param, flags); + } + return mp4; +} + +void mp4_writer_destroy(mp4_writer_t* mp4){ + if (mp4->is_fmp4) { + fmp4_writer_destroy(mp4->u.fmp4); + } else { + mov_writer_destroy(mp4->u.mov); + } + free(mp4); +} + +int mp4_writer_add_audio(mp4_writer_t* mp4, uint8_t object, int channel_count, int bits_per_sample, int sample_rate, const void* extra_data, size_t extra_data_size){ + if (mp4->is_fmp4) { + return fmp4_writer_add_audio(mp4->u.fmp4, object, channel_count, bits_per_sample, sample_rate, extra_data, extra_data_size); + } else { + return mov_writer_add_audio(mp4->u.mov, object, channel_count, bits_per_sample, sample_rate, extra_data, extra_data_size); + } +} + +int mp4_writer_add_video(mp4_writer_t* mp4, uint8_t object, int width, int height, const void* extra_data, size_t extra_data_size){ + if (mp4->is_fmp4) { + return fmp4_writer_add_video(mp4->u.fmp4, object, width, height, extra_data, extra_data_size); + } else { + return mov_writer_add_video(mp4->u.mov, object, width, height, extra_data, extra_data_size); + } +} + +int mp4_writer_add_subtitle(mp4_writer_t* mp4, uint8_t object, const void* extra_data, size_t extra_data_size){ + if (mp4->is_fmp4) { + return fmp4_writer_add_subtitle(mp4->u.fmp4, object, extra_data, extra_data_size); + } else { + return mov_writer_add_subtitle(mp4->u.mov, object, extra_data, extra_data_size); + } +} + +int mp4_writer_write(mp4_writer_t* mp4, int track, const void* data, size_t bytes, int64_t pts, int64_t dts, int flags){ + if (mp4->is_fmp4) { + return fmp4_writer_write(mp4->u.fmp4, track, data, bytes, pts, dts, flags); + } else { + return mov_writer_write(mp4->u.mov, track, data, bytes, pts, dts, flags); + } +} + +int mp4_writer_write_l(mp4_writer_t* mp4, int track, const void* data, size_t bytes, int64_t pts, int64_t dts, int flags, int add_nalu_size){ + if (mp4->is_fmp4) { + return fmp4_writer_write_l(mp4->u.fmp4, track, data, bytes, pts, dts, flags, add_nalu_size); + } else { + return mov_writer_write_l(mp4->u.mov, track, data, bytes, pts, dts, flags, add_nalu_size); + } +} + +int mp4_writer_save_segment(mp4_writer_t* mp4){ + if (mp4->is_fmp4) { + return fmp4_writer_save_segment(mp4->u.fmp4); + } else { + return -1; + } +} + +int mp4_writer_init_segment(mp4_writer_t* mp4){ + if (mp4->is_fmp4) { + return fmp4_writer_init_segment(mp4->u.fmp4); + } else { + return -1; + } +} + static struct mov_buffer_t s_io = { - [](void* ctx, void* data, uint64_t bytes) { - MP4File *thiz = (MP4File *)ctx; - return thiz->onRead(data,bytes); + [](void *ctx, void *data, uint64_t bytes) { + MP4File *thiz = (MP4File *) ctx; + return thiz->onRead(data, bytes); }, - [](void* ctx, const void* data, uint64_t bytes){ - MP4File *thiz = (MP4File *)ctx; - return thiz->onWrite(data,bytes); + [](void *ctx, const void *data, uint64_t bytes) { + MP4File *thiz = (MP4File *) ctx; + return thiz->onWrite(data, bytes); }, - [](void* ctx, uint64_t offset) { - MP4File *thiz = (MP4File *)ctx; + [](void *ctx, uint64_t offset) { + MP4File *thiz = (MP4File *) ctx; return thiz->onSeek(offset); }, - [](void* ctx){ - MP4File *thiz = (MP4File *)ctx; + [](void *ctx) { + MP4File *thiz = (MP4File *) ctx; return thiz->onTell(); } }; -MP4File::Writer MP4File::createWriter(){ - GET_CONFIG(bool, mp4FastStart, Record::kFastStart); +MP4File::Writer MP4File::createWriter(int flags, bool is_fmp4){ Writer writer; - writer.reset(mov_writer_create(&s_io,this,mp4FastStart ? MOV_FLAG_FASTSTART : 0),[](mov_writer_t *ptr){ + writer.reset(mp4_writer_create(is_fmp4, &s_io,this, flags),[](mp4_writer_t *ptr){ if(ptr){ - mov_writer_destroy(ptr); + mp4_writer_destroy(ptr); } }); if(!writer){ diff --git a/src/Record/MP4.h b/src/Record/MP4.h index b76362a9..e9d49b83 100644 --- a/src/Record/MP4.h +++ b/src/Record/MP4.h @@ -23,15 +23,26 @@ using namespace std; namespace mediakit { +typedef struct mp4_writer_t mp4_writer_t; +mp4_writer_t* mp4_writer_create(int is_fmp4, const struct mov_buffer_t *buffer, void* param, int flags); +void mp4_writer_destroy(mp4_writer_t* mp4); +int mp4_writer_add_audio(mp4_writer_t* mp4, uint8_t object, int channel_count, int bits_per_sample, int sample_rate, const void* extra_data, size_t extra_data_size); +int mp4_writer_add_video(mp4_writer_t* mp4, uint8_t object, int width, int height, const void* extra_data, size_t extra_data_size); +int mp4_writer_add_subtitle(mp4_writer_t* mp4, uint8_t object, const void* extra_data, size_t extra_data_size); +int mp4_writer_write(mp4_writer_t* mp4, int track, const void* data, size_t bytes, int64_t pts, int64_t dts, int flags); +int mp4_writer_write_l(mp4_writer_t* mp4, int track, const void* data, size_t bytes, int64_t pts, int64_t dts, int flags, int add_nalu_size); +int mp4_writer_save_segment(mp4_writer_t* mp4); +int mp4_writer_init_segment(mp4_writer_t* mp4); + class MP4File { public: friend struct mov_buffer_t; - typedef std::shared_ptr Writer; + typedef std::shared_ptr Writer; typedef std::shared_ptr Reader; MP4File() = default; virtual ~MP4File() = default; - Writer createWriter(); + Writer createWriter(int flags, bool is_fmp4 = false); Reader createReader(); void openFile(const char *file,const char *mode); void closeFile(); diff --git a/src/Record/MP4Muxer.cpp b/src/Record/MP4Muxer.cpp index 72fbbc9d..e8f5f153 100644 --- a/src/Record/MP4Muxer.cpp +++ b/src/Record/MP4Muxer.cpp @@ -26,7 +26,8 @@ MP4Muxer::~MP4Muxer() { void MP4Muxer::openMP4(){ closeMP4(); openFile(_file_name.data(), "wb+"); - _mov_writter = createWriter(); + GET_CONFIG(bool, mp4FastStart, Record::kFastStart); + _mov_writter = createWriter(mp4FastStart ? MOV_FLAG_FASTSTART : 0, false); } void MP4Muxer::closeMP4(){ _mov_writter = nullptr; @@ -84,24 +85,23 @@ void MP4Muxer::inputFrame(const Frame::Ptr &frame) { merged.append((char *) &nalu_size, 4); merged.append(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize()); }); - mov_writer_write_l(_mov_writter.get(), + mp4_writer_write(_mov_writter.get(), track_info.track_id, merged.data(), merged.size(), pts_out, dts_out, - back->keyFrame() ? MOV_AV_FLAG_KEYFREAME : 0, - 1/*我们合并时已经生成了4个字节的MP4格式start code*/); + back->keyFrame() ? MOV_AV_FLAG_KEYFREAME : 0); } else { //缓存中只有一帧视频 - mov_writer_write_l(_mov_writter.get(), + mp4_writer_write_l(_mov_writter.get(), track_info.track_id, back->data() + back->prefixSize(), back->size() - back->prefixSize(), pts_out, dts_out, back->keyFrame() ? MOV_AV_FLAG_KEYFREAME : 0, - 0/*需要生成头4个字节的MP4格式start code*/); + 1/*需要生成头4个字节的MP4格式start code*/); } _frameCached.clear(); } @@ -111,14 +111,13 @@ void MP4Muxer::inputFrame(const Frame::Ptr &frame) { break; default: { track_info.stamp.revise(frame->dts(), frame->pts(), dts_out, pts_out); - mov_writer_write_l(_mov_writter.get(), - track_info.track_id, - frame->data() + frame->prefixSize(), - frame->size() - frame->prefixSize(), - pts_out, - dts_out, - frame->keyFrame() ? MOV_AV_FLAG_KEYFREAME : 0, - 1/*aac或其他类型frame不用添加4个nalu_size的字节*/); + mp4_writer_write(_mov_writter.get(), + track_info.track_id, + frame->data() + frame->prefixSize(), + frame->size() - frame->prefixSize(), + pts_out, + dts_out, + frame->keyFrame() ? MOV_AV_FLAG_KEYFREAME : 0); } break; } @@ -178,7 +177,7 @@ void MP4Muxer::addTrack(const Track::Ptr &track) { return; } - auto track_id = mov_writer_add_audio(_mov_writter.get(), + auto track_id = mp4_writer_add_audio(_mov_writter.get(), mp4_object, audio_track->getAudioChannel(), audio_track->getAudioSampleBit() * audio_track->getAudioChannel(), @@ -199,7 +198,7 @@ void MP4Muxer::addTrack(const Track::Ptr &track) { return; } - auto track_id = mov_writer_add_audio(_mov_writter.get(), + auto track_id = mp4_writer_add_audio(_mov_writter.get(), mp4_object, audio_track->getAudioChannel(), audio_track->getAudioSampleBit() * audio_track->getAudioChannel(), @@ -232,7 +231,7 @@ void MP4Muxer::addTrack(const Track::Ptr &track) { return; } - auto track_id = mov_writer_add_video(_mov_writter.get(), + auto track_id = mp4_writer_add_video(_mov_writter.get(), mp4_object, h264_track->getVideoWidth(), h264_track->getVideoHeight(), @@ -267,7 +266,7 @@ void MP4Muxer::addTrack(const Track::Ptr &track) { return; } - auto track_id = mov_writer_add_video(_mov_writter.get(), + auto track_id = mp4_writer_add_video(_mov_writter.get(), mp4_object, h265_track->getVideoWidth(), h265_track->getVideoHeight(),