mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-29 14:45:55 +08:00
完善mp4点播
This commit is contained in:
parent
278591d5ee
commit
47d8e37e3d
@ -158,7 +158,7 @@ struct Context{
|
|||||||
BufferRaw::Ptr buffer;
|
BufferRaw::Ptr buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
Frame::Ptr MP4Demuxer::readFrame(bool &keyFrame, bool &eof) {
|
Frame::Ptr MP4Demuxer::readFrame(bool &keyFrame) {
|
||||||
static mov_reader_onread mov_reader_onread = [](void *param, uint32_t track_id, const void *buffer, size_t bytes, int64_t pts, int64_t dts, int flags) {
|
static mov_reader_onread mov_reader_onread = [](void *param, uint32_t track_id, const void *buffer, size_t bytes, int64_t pts, int64_t dts, int flags) {
|
||||||
Context *ctx = (Context *) param;
|
Context *ctx = (Context *) param;
|
||||||
ctx->pts = pts;
|
ctx->pts = pts;
|
||||||
@ -178,24 +178,18 @@ Frame::Ptr MP4Demuxer::readFrame(bool &keyFrame, bool &eof) {
|
|||||||
Context ctx = {this, 0};
|
Context ctx = {this, 0};
|
||||||
auto ret = mov_reader_read2(_mov_reader.get(), mov_onalloc, mov_reader_onread, &ctx);
|
auto ret = mov_reader_read2(_mov_reader.get(), mov_onalloc, mov_reader_onread, &ctx);
|
||||||
switch (ret) {
|
switch (ret) {
|
||||||
case 0 : {
|
case 0 :
|
||||||
eof = true;
|
return nullptr;
|
||||||
WarnL << "读取mp4文件完毕";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1 : {
|
case 1 : {
|
||||||
keyFrame = ctx.flags & MOV_AV_FLAG_KEYFREAME;
|
keyFrame = ctx.flags & MOV_AV_FLAG_KEYFREAME;
|
||||||
return makeFrame(ctx.track_id,ctx.buffer, ctx.pts, ctx.dts);
|
return makeFrame(ctx.track_id, ctx.buffer, ctx.pts, ctx.dts);
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
eof = true;
|
|
||||||
WarnL << "读取mp4文件数据失败:" << ret;
|
WarnL << "读取mp4文件数据失败:" << ret;
|
||||||
break;
|
|
||||||
}
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Parent>
|
template <typename Parent>
|
||||||
|
@ -38,7 +38,7 @@ public:
|
|||||||
MP4Demuxer(const char *file);
|
MP4Demuxer(const char *file);
|
||||||
~MP4Demuxer() override;
|
~MP4Demuxer() override;
|
||||||
int64_t seekTo(int64_t stamp_ms);
|
int64_t seekTo(int64_t stamp_ms);
|
||||||
Frame::Ptr readFrame(bool &keyFrame, bool &eof);
|
Frame::Ptr readFrame(bool &keyFrame);
|
||||||
vector<Track::Ptr> getTracks(bool trackReady) const override ;
|
vector<Track::Ptr> getTracks(bool trackReady) const override ;
|
||||||
uint64_t getDurationMS() const;
|
uint64_t getDurationMS() const;
|
||||||
private:
|
private:
|
||||||
|
@ -62,32 +62,27 @@ MP4Reader::MP4Reader(const string &strVhost,const string &strApp, const string &
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool MP4Reader::readSample() {
|
bool MP4Reader::readSample() {
|
||||||
bool eof = false;
|
|
||||||
bool keyFrame = false;
|
bool keyFrame = false;
|
||||||
while (!eof) {
|
bool eof = false;
|
||||||
auto frame = _demuxer->readFrame(keyFrame, eof);
|
while (true) {
|
||||||
|
auto frame = _demuxer->readFrame(keyFrame);
|
||||||
if (!frame) {
|
if (!frame) {
|
||||||
|
eof = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
_mediaMuxer->inputFrame(frame);
|
_mediaMuxer->inputFrame(frame);
|
||||||
if (frame->dts() > nextStampForStop()) {
|
if (frame->dts() > getCurrentStamp()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!eof && _mediaMuxer->totalReaderCount() > 0){
|
GET_CONFIG(bool, fileRepeat, Record::kFileRepeat);
|
||||||
//文件未看完且观看者大于0个
|
if (eof && fileRepeat) {
|
||||||
_alive.resetTime();
|
//需要从头开始看
|
||||||
}
|
|
||||||
|
|
||||||
//重头开始循环读取
|
|
||||||
GET_CONFIG(bool,fileRepeat,Record::kFileRepeat);
|
|
||||||
if(eof && fileRepeat){
|
|
||||||
//文件看完了,且需要从头开始看
|
|
||||||
seekTo(0);
|
seekTo(0);
|
||||||
}
|
}
|
||||||
//读取mp4完毕后10秒才销毁对象
|
|
||||||
return _alive.elapsedTime() < 10 * 1000;
|
return !eof;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MP4Reader::startReadMP4() {
|
void MP4Reader::startReadMP4() {
|
||||||
@ -97,9 +92,8 @@ void MP4Reader::startReadMP4() {
|
|||||||
|
|
||||||
//先获取关键帧
|
//先获取关键帧
|
||||||
seekTo(0);
|
seekTo(0);
|
||||||
//设置下次读取停止事件
|
|
||||||
setNextStampForStop(_seek_to + sampleMS);
|
|
||||||
//读sampleMS毫秒的数据用于产生MediaSource
|
//读sampleMS毫秒的数据用于产生MediaSource
|
||||||
|
setCurrentStamp(getCurrentStamp() + sampleMS);
|
||||||
readSample();
|
readSample();
|
||||||
|
|
||||||
//启动定时器
|
//启动定时器
|
||||||
@ -109,14 +103,14 @@ void MP4Reader::startReadMP4() {
|
|||||||
}, _poller);
|
}, _poller);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t MP4Reader::nextStampForStop() {
|
uint32_t MP4Reader::getCurrentStamp() {
|
||||||
return _seek_to + _seek_ticker.elapsedTime();
|
return _seek_to + _seek_ticker.elapsedTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MP4Reader::setNextStampForStop(uint32_t ui32Stamp){
|
void MP4Reader::setCurrentStamp(uint32_t ui32Stamp){
|
||||||
_seek_to = ui32Stamp;
|
_seek_to = ui32Stamp;
|
||||||
_seek_ticker.resetTime();
|
_seek_ticker.resetTime();
|
||||||
_alive.resetTime();
|
_mediaMuxer->setTimeStamp(ui32Stamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MP4Reader::seekTo(MediaSource &sender,uint32_t ui32Stamp){
|
bool MP4Reader::seekTo(MediaSource &sender,uint32_t ui32Stamp){
|
||||||
@ -134,26 +128,27 @@ bool MP4Reader::seekTo(uint32_t ui32Stamp){
|
|||||||
//seek失败
|
//seek失败
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
InfoL << stamp;
|
|
||||||
//设置当前时间戳
|
|
||||||
setNextStampForStop(stamp);
|
|
||||||
|
|
||||||
if(!_have_video){
|
if(!_have_video){
|
||||||
//没有视频,不需要搜索关键帧
|
//没有视频,不需要搜索关键帧
|
||||||
|
//设置当前时间戳
|
||||||
|
setCurrentStamp(stamp);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//搜索到下一帧关键帧
|
//搜索到下一帧关键帧
|
||||||
bool eof = false;
|
bool eof = false;
|
||||||
bool keyFrame = false;
|
bool keyFrame = false;
|
||||||
while (!eof) {
|
while (!eof) {
|
||||||
auto frame = _demuxer->readFrame(keyFrame, eof);
|
auto frame = _demuxer->readFrame(keyFrame);
|
||||||
if(!frame){
|
if(!frame){
|
||||||
|
eof = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(keyFrame || frame->keyFrame() || frame->configFrame()){
|
if(keyFrame || frame->keyFrame() || frame->configFrame()){
|
||||||
//定位到key帧
|
//定位到key帧
|
||||||
_mediaMuxer->inputFrame(frame);
|
_mediaMuxer->inputFrame(frame);
|
||||||
setNextStampForStop(frame->dts());
|
//设置当前时间戳
|
||||||
|
setCurrentStamp(frame->dts());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,15 +58,14 @@ private:
|
|||||||
int totalReaderCount(MediaSource &sender) override;
|
int totalReaderCount(MediaSource &sender) override;
|
||||||
|
|
||||||
bool readSample();
|
bool readSample();
|
||||||
uint32_t nextStampForStop();
|
uint32_t getCurrentStamp();
|
||||||
void setNextStampForStop(uint32_t ui32Stamp);
|
void setCurrentStamp(uint32_t ui32Stamp);
|
||||||
bool seekTo(uint32_t ui32Stamp);
|
bool seekTo(uint32_t ui32Stamp);
|
||||||
private:
|
private:
|
||||||
recursive_mutex _mtx;
|
recursive_mutex _mtx;
|
||||||
MultiMediaSourceMuxer::Ptr _mediaMuxer;
|
MultiMediaSourceMuxer::Ptr _mediaMuxer;
|
||||||
uint32_t _seek_to;
|
uint32_t _seek_to;
|
||||||
Ticker _seek_ticker;
|
Ticker _seek_ticker;
|
||||||
Ticker _alive;
|
|
||||||
Timer::Ptr _timer;
|
Timer::Ptr _timer;
|
||||||
EventPoller::Ptr _poller;
|
EventPoller::Ptr _poller;
|
||||||
MP4Demuxer::Ptr _demuxer;
|
MP4Demuxer::Ptr _demuxer;
|
||||||
|
Loading…
Reference in New Issue
Block a user