mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-26 04:31:37 +08:00
合并fmp4和mov接口
This commit is contained in:
parent
d3cb0e3d39
commit
2dd1046131
@ -1 +1 @@
|
|||||||
Subproject commit 82a48c57ae5269aaa70a8c3df8a67dc06b05d0cd
|
Subproject commit 5d8f1536bd4c70be8f2d7ff30fde3c36877477c8
|
@ -13,34 +13,119 @@
|
|||||||
#include "Util/File.h"
|
#include "Util/File.h"
|
||||||
#include "Util/logger.h"
|
#include "Util/logger.h"
|
||||||
#include "Common/config.h"
|
#include "Common/config.h"
|
||||||
|
#include "fmp4-writer.h"
|
||||||
|
|
||||||
using namespace toolkit;
|
using namespace toolkit;
|
||||||
namespace mediakit {
|
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 = {
|
static struct mov_buffer_t s_io = {
|
||||||
[](void* ctx, void* data, uint64_t bytes) {
|
[](void *ctx, void *data, uint64_t bytes) {
|
||||||
MP4File *thiz = (MP4File *)ctx;
|
MP4File *thiz = (MP4File *) ctx;
|
||||||
return thiz->onRead(data,bytes);
|
return thiz->onRead(data, bytes);
|
||||||
},
|
},
|
||||||
[](void* ctx, const void* data, uint64_t bytes){
|
[](void *ctx, const void *data, uint64_t bytes) {
|
||||||
MP4File *thiz = (MP4File *)ctx;
|
MP4File *thiz = (MP4File *) ctx;
|
||||||
return thiz->onWrite(data,bytes);
|
return thiz->onWrite(data, bytes);
|
||||||
},
|
},
|
||||||
[](void* ctx, uint64_t offset) {
|
[](void *ctx, uint64_t offset) {
|
||||||
MP4File *thiz = (MP4File *)ctx;
|
MP4File *thiz = (MP4File *) ctx;
|
||||||
return thiz->onSeek(offset);
|
return thiz->onSeek(offset);
|
||||||
},
|
},
|
||||||
[](void* ctx){
|
[](void *ctx) {
|
||||||
MP4File *thiz = (MP4File *)ctx;
|
MP4File *thiz = (MP4File *) ctx;
|
||||||
return thiz->onTell();
|
return thiz->onTell();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
MP4File::Writer MP4File::createWriter(){
|
MP4File::Writer MP4File::createWriter(int flags, bool is_fmp4){
|
||||||
GET_CONFIG(bool, mp4FastStart, Record::kFastStart);
|
|
||||||
Writer writer;
|
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){
|
if(ptr){
|
||||||
mov_writer_destroy(ptr);
|
mp4_writer_destroy(ptr);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if(!writer){
|
if(!writer){
|
||||||
|
@ -23,15 +23,26 @@
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
namespace mediakit {
|
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 {
|
class MP4File {
|
||||||
public:
|
public:
|
||||||
friend struct mov_buffer_t;
|
friend struct mov_buffer_t;
|
||||||
typedef std::shared_ptr<mov_writer_t> Writer;
|
typedef std::shared_ptr<mp4_writer_t> Writer;
|
||||||
typedef std::shared_ptr<mov_reader_t> Reader;
|
typedef std::shared_ptr<mov_reader_t> Reader;
|
||||||
MP4File() = default;
|
MP4File() = default;
|
||||||
virtual ~MP4File() = default;
|
virtual ~MP4File() = default;
|
||||||
|
|
||||||
Writer createWriter();
|
Writer createWriter(int flags, bool is_fmp4 = false);
|
||||||
Reader createReader();
|
Reader createReader();
|
||||||
void openFile(const char *file,const char *mode);
|
void openFile(const char *file,const char *mode);
|
||||||
void closeFile();
|
void closeFile();
|
||||||
|
@ -26,7 +26,8 @@ MP4Muxer::~MP4Muxer() {
|
|||||||
void MP4Muxer::openMP4(){
|
void MP4Muxer::openMP4(){
|
||||||
closeMP4();
|
closeMP4();
|
||||||
openFile(_file_name.data(), "wb+");
|
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(){
|
void MP4Muxer::closeMP4(){
|
||||||
_mov_writter = nullptr;
|
_mov_writter = nullptr;
|
||||||
@ -84,24 +85,23 @@ void MP4Muxer::inputFrame(const Frame::Ptr &frame) {
|
|||||||
merged.append((char *) &nalu_size, 4);
|
merged.append((char *) &nalu_size, 4);
|
||||||
merged.append(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize());
|
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,
|
track_info.track_id,
|
||||||
merged.data(),
|
merged.data(),
|
||||||
merged.size(),
|
merged.size(),
|
||||||
pts_out,
|
pts_out,
|
||||||
dts_out,
|
dts_out,
|
||||||
back->keyFrame() ? MOV_AV_FLAG_KEYFREAME : 0,
|
back->keyFrame() ? MOV_AV_FLAG_KEYFREAME : 0);
|
||||||
1/*我们合并时已经生成了4个字节的MP4格式start code*/);
|
|
||||||
} else {
|
} else {
|
||||||
//缓存中只有一帧视频
|
//缓存中只有一帧视频
|
||||||
mov_writer_write_l(_mov_writter.get(),
|
mp4_writer_write_l(_mov_writter.get(),
|
||||||
track_info.track_id,
|
track_info.track_id,
|
||||||
back->data() + back->prefixSize(),
|
back->data() + back->prefixSize(),
|
||||||
back->size() - back->prefixSize(),
|
back->size() - back->prefixSize(),
|
||||||
pts_out,
|
pts_out,
|
||||||
dts_out,
|
dts_out,
|
||||||
back->keyFrame() ? MOV_AV_FLAG_KEYFREAME : 0,
|
back->keyFrame() ? MOV_AV_FLAG_KEYFREAME : 0,
|
||||||
0/*需要生成头4个字节的MP4格式start code*/);
|
1/*需要生成头4个字节的MP4格式start code*/);
|
||||||
}
|
}
|
||||||
_frameCached.clear();
|
_frameCached.clear();
|
||||||
}
|
}
|
||||||
@ -111,14 +111,13 @@ void MP4Muxer::inputFrame(const Frame::Ptr &frame) {
|
|||||||
break;
|
break;
|
||||||
default: {
|
default: {
|
||||||
track_info.stamp.revise(frame->dts(), frame->pts(), dts_out, pts_out);
|
track_info.stamp.revise(frame->dts(), frame->pts(), dts_out, pts_out);
|
||||||
mov_writer_write_l(_mov_writter.get(),
|
mp4_writer_write(_mov_writter.get(),
|
||||||
track_info.track_id,
|
track_info.track_id,
|
||||||
frame->data() + frame->prefixSize(),
|
frame->data() + frame->prefixSize(),
|
||||||
frame->size() - frame->prefixSize(),
|
frame->size() - frame->prefixSize(),
|
||||||
pts_out,
|
pts_out,
|
||||||
dts_out,
|
dts_out,
|
||||||
frame->keyFrame() ? MOV_AV_FLAG_KEYFREAME : 0,
|
frame->keyFrame() ? MOV_AV_FLAG_KEYFREAME : 0);
|
||||||
1/*aac或其他类型frame不用添加4个nalu_size的字节*/);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -178,7 +177,7 @@ void MP4Muxer::addTrack(const Track::Ptr &track) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto track_id = mov_writer_add_audio(_mov_writter.get(),
|
auto track_id = mp4_writer_add_audio(_mov_writter.get(),
|
||||||
mp4_object,
|
mp4_object,
|
||||||
audio_track->getAudioChannel(),
|
audio_track->getAudioChannel(),
|
||||||
audio_track->getAudioSampleBit() * audio_track->getAudioChannel(),
|
audio_track->getAudioSampleBit() * audio_track->getAudioChannel(),
|
||||||
@ -199,7 +198,7 @@ void MP4Muxer::addTrack(const Track::Ptr &track) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto track_id = mov_writer_add_audio(_mov_writter.get(),
|
auto track_id = mp4_writer_add_audio(_mov_writter.get(),
|
||||||
mp4_object,
|
mp4_object,
|
||||||
audio_track->getAudioChannel(),
|
audio_track->getAudioChannel(),
|
||||||
audio_track->getAudioSampleBit() * audio_track->getAudioChannel(),
|
audio_track->getAudioSampleBit() * audio_track->getAudioChannel(),
|
||||||
@ -232,7 +231,7 @@ void MP4Muxer::addTrack(const Track::Ptr &track) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto track_id = mov_writer_add_video(_mov_writter.get(),
|
auto track_id = mp4_writer_add_video(_mov_writter.get(),
|
||||||
mp4_object,
|
mp4_object,
|
||||||
h264_track->getVideoWidth(),
|
h264_track->getVideoWidth(),
|
||||||
h264_track->getVideoHeight(),
|
h264_track->getVideoHeight(),
|
||||||
@ -267,7 +266,7 @@ void MP4Muxer::addTrack(const Track::Ptr &track) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto track_id = mov_writer_add_video(_mov_writter.get(),
|
auto track_id = mp4_writer_add_video(_mov_writter.get(),
|
||||||
mp4_object,
|
mp4_object,
|
||||||
h265_track->getVideoWidth(),
|
h265_track->getVideoWidth(),
|
||||||
h265_track->getVideoHeight(),
|
h265_track->getVideoHeight(),
|
||||||
|
Loading…
Reference in New Issue
Block a user