解耦代码
This commit is contained in:
parent
fbe159db0e
commit
7d4a930162
|
|
@ -19,7 +19,7 @@
|
|||
using namespace mediakit;
|
||||
|
||||
extern "C" {
|
||||
#define XX(name, type, value, str, mpeg_id) API_EXPORT const int MK##name = value;
|
||||
#define XX(name, type, value, str, mpeg_id, mp4_id) API_EXPORT const int MK##name = value;
|
||||
CODEC_MAP(XX)
|
||||
#undef XX
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
#include "mk_player.h"
|
||||
#include "Util/logger.h"
|
||||
#include "Player/MediaPlayer.h"
|
||||
#include "Extension/H264.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace toolkit;
|
||||
|
|
|
|||
|
|
@ -115,20 +115,6 @@ bool DevChannel::inputH265(const char *data, int len, uint64_t dts, uint64_t pts
|
|||
return inputFrame(frame);
|
||||
}
|
||||
|
||||
class FrameAutoDelete : public FrameFromPtr{
|
||||
public:
|
||||
template <typename ... ARGS>
|
||||
FrameAutoDelete(ARGS && ...args) : FrameFromPtr(std::forward<ARGS>(args)...){}
|
||||
|
||||
~FrameAutoDelete() override {
|
||||
delete [] _ptr;
|
||||
};
|
||||
|
||||
bool cacheAble() const override {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
bool DevChannel::inputAAC(const char *data_without_adts, int len, uint64_t dts, const char *adts_header){
|
||||
if (dts == 0) {
|
||||
dts = _aTicker[1].elapsedTime();
|
||||
|
|
|
|||
|
|
@ -201,16 +201,6 @@ vector<Track::Ptr> MediaSink::getTracks(bool ready) const{
|
|||
return ret;
|
||||
}
|
||||
|
||||
class FrameFromStaticPtr : public FrameFromPtr {
|
||||
public:
|
||||
template<typename ... ARGS>
|
||||
FrameFromStaticPtr(ARGS &&...args) : FrameFromPtr(std::forward<ARGS>(args)...) {};
|
||||
|
||||
bool cacheAble() const override {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
static uint8_t s_mute_adts[] = {0xff, 0xf1, 0x6c, 0x40, 0x2d, 0x3f, 0xfc, 0x00, 0xe0, 0x34, 0x20, 0xad, 0xf2, 0x3f, 0xb5, 0xdd,
|
||||
0x73, 0xac, 0xbd, 0xca, 0xd7, 0x7d, 0x4a, 0x13, 0x2d, 0x2e, 0xa2, 0x62, 0x02, 0x70, 0x3c, 0x1c,
|
||||
0xc5, 0x63, 0x55, 0x69, 0x94, 0xb5, 0x8d, 0x70, 0xd7, 0x24, 0x6a, 0x9e, 0x2e, 0x86, 0x24, 0xea,
|
||||
|
|
@ -244,7 +234,7 @@ bool MuteAudioMaker::inputFrame(const Frame::Ptr &frame) {
|
|||
auto audio_idx = frame->dts() / MUTE_ADTS_DATA_MS;
|
||||
if (_audio_idx != audio_idx) {
|
||||
_audio_idx = audio_idx;
|
||||
auto aacFrame = std::make_shared<FrameFromStaticPtr>(CodecAAC, (char *) MUTE_ADTS_DATA, MUTE_ADTS_DATA_LEN,
|
||||
auto aacFrame = std::make_shared<FrameToCache<FrameFromPtr>>(CodecAAC, (char *) MUTE_ADTS_DATA, MUTE_ADTS_DATA_LEN,
|
||||
_audio_idx * MUTE_ADTS_DATA_MS, 0, ADTS_HEADER_LEN);
|
||||
return FrameDispatcher::inputFrame(aacFrame);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -300,7 +300,7 @@ bool AACTrack::inputFrame(const Frame::Ptr &frame) {
|
|||
if (frame_len == (int)frame->size()) {
|
||||
return inputFrame_l(frame);
|
||||
}
|
||||
auto sub_frame = std::make_shared<FrameTSInternal<FrameFromPtr>>(frame, (char *)ptr, frame_len, ADTS_HEADER_LEN, dts, pts);
|
||||
auto sub_frame = std::make_shared<FrameInternalBase<FrameFromPtr>>(frame, (char *)ptr, frame_len, ADTS_HEADER_LEN, dts, pts);
|
||||
ptr += frame_len;
|
||||
if (ptr > end) {
|
||||
WarnL << "invalid aac length in adts header: " << frame_len
|
||||
|
|
|
|||
|
|
@ -15,6 +15,14 @@
|
|||
#include "Common/Stamp.h"
|
||||
#include "Common/MediaSource.h"
|
||||
|
||||
#if defined(ENABLE_MP4)
|
||||
#include "mov-format.h"
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_HLS) || defined(ENABLE_RTPPROXY)
|
||||
#include "mpeg-proto.h"
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
using namespace toolkit;
|
||||
|
||||
|
|
@ -41,24 +49,71 @@ FrameStamp::FrameStamp(Frame::Ptr frame, Stamp &stamp, int modify_stamp)
|
|||
|
||||
TrackType getTrackType(CodecId codecId) {
|
||||
switch (codecId) {
|
||||
#define XX(name, type, value, str, mpeg_id) case name : return type;
|
||||
#define XX(name, type, value, str, mpeg_id, mp4_id) case name : return type;
|
||||
CODEC_MAP(XX)
|
||||
#undef XX
|
||||
default : return TrackInvalid;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(ENABLE_MP4)
|
||||
int getMovIdByCodec(CodecId codecId) {
|
||||
switch (codecId) {
|
||||
#define XX(name, type, value, str, mpeg_id, mp4_id) case name : return mp4_id;
|
||||
CODEC_MAP(XX)
|
||||
#undef XX
|
||||
default : return MOV_OBJECT_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
CodecId getCodecByMovId(int object_id) {
|
||||
if (object_id == MOV_OBJECT_NONE) {
|
||||
return CodecInvalid;
|
||||
}
|
||||
switch (object_id) {
|
||||
#define XX(name, type, value, str, mpeg_id, mp4_id) case mp4_id : return name;
|
||||
CODEC_MAP(XX)
|
||||
#undef XX
|
||||
default : WarnL << "Unsupported mov: " << object_id; return CodecInvalid;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_HLS) || defined(ENABLE_RTPPROXY)
|
||||
int getMpegIdByCodec(CodecId codec) {
|
||||
switch (codec) {
|
||||
#define XX(name, type, value, str, mpeg_id, mp4_id) case name : return mpeg_id;
|
||||
CODEC_MAP(XX)
|
||||
#undef XX
|
||||
default : return PSI_STREAM_RESERVED;
|
||||
}
|
||||
}
|
||||
|
||||
CodecId getCodecByMpegId(int mpeg_id) {
|
||||
if (mpeg_id == PSI_STREAM_RESERVED) {
|
||||
return CodecInvalid;
|
||||
}
|
||||
switch (mpeg_id) {
|
||||
#define XX(name, type, value, str, mpeg_id, mp4_id) case mpeg_id : return name;
|
||||
CODEC_MAP(XX)
|
||||
#undef XX
|
||||
default : WarnL << "Unsupported mpeg: " << mpeg_id; return CodecInvalid;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
const char *getCodecName(CodecId codec) {
|
||||
switch (codec) {
|
||||
#define XX(name, type, value, str, mpeg_id) case name : return str;
|
||||
#define XX(name, type, value, str, mpeg_id, mp4_id) case name : return str;
|
||||
CODEC_MAP(XX)
|
||||
#undef XX
|
||||
default : return "invalid";
|
||||
}
|
||||
}
|
||||
|
||||
#define XX(name, type, value, str, mpeg_id) {str, name},
|
||||
static map<string, CodecId, StrCaseCompare> codec_map = {CODEC_MAP(XX)};
|
||||
#define XX(name, type, value, str, mpeg_id, mp4_id) {str, name},
|
||||
static map<string, CodecId, StrCaseCompare> codec_map = { CODEC_MAP(XX) };
|
||||
#undef XX
|
||||
|
||||
CodecId getCodecId(const string &str){
|
||||
|
|
|
|||
|
|
@ -20,7 +20,9 @@
|
|||
#include "Network/Buffer.h"
|
||||
|
||||
namespace mediakit {
|
||||
|
||||
class Stamp;
|
||||
|
||||
typedef enum {
|
||||
TrackInvalid = -1,
|
||||
TrackVideo = 0,
|
||||
|
|
@ -31,21 +33,21 @@ typedef enum {
|
|||
} TrackType;
|
||||
|
||||
#define CODEC_MAP(XX) \
|
||||
XX(CodecH264, TrackVideo, 0, "H264", PSI_STREAM_H264) \
|
||||
XX(CodecH265, TrackVideo, 1, "H265", PSI_STREAM_H265) \
|
||||
XX(CodecAAC, TrackAudio, 2, "mpeg4-generic", PSI_STREAM_AAC) \
|
||||
XX(CodecG711A, TrackAudio, 3, "PCMA", PSI_STREAM_AUDIO_G711A) \
|
||||
XX(CodecG711U, TrackAudio, 4, "PCMU", PSI_STREAM_AUDIO_G711U) \
|
||||
XX(CodecOpus, TrackAudio, 5, "opus", PSI_STREAM_AUDIO_OPUS) \
|
||||
XX(CodecL16, TrackAudio, 6, "L16", PSI_STREAM_RESERVED) \
|
||||
XX(CodecVP8, TrackVideo, 7, "VP8", PSI_STREAM_VP8) \
|
||||
XX(CodecVP9, TrackVideo, 8, "VP9", PSI_STREAM_VP9) \
|
||||
XX(CodecAV1, TrackVideo, 9, "AV1", PSI_STREAM_AV1) \
|
||||
XX(CodecJPEG, TrackVideo, 10, "JPEG", PSI_STREAM_RESERVED)
|
||||
XX(CodecH264, TrackVideo, 0, "H264", PSI_STREAM_H264, MOV_OBJECT_H264) \
|
||||
XX(CodecH265, TrackVideo, 1, "H265", PSI_STREAM_H265, MOV_OBJECT_HEVC) \
|
||||
XX(CodecAAC, TrackAudio, 2, "mpeg4-generic", PSI_STREAM_AAC, MOV_OBJECT_AAC) \
|
||||
XX(CodecG711A, TrackAudio, 3, "PCMA", PSI_STREAM_AUDIO_G711A, MOV_OBJECT_G711a) \
|
||||
XX(CodecG711U, TrackAudio, 4, "PCMU", PSI_STREAM_AUDIO_G711U, MOV_OBJECT_G711u) \
|
||||
XX(CodecOpus, TrackAudio, 5, "opus", PSI_STREAM_AUDIO_OPUS, MOV_OBJECT_OPUS) \
|
||||
XX(CodecL16, TrackAudio, 6, "L16", PSI_STREAM_RESERVED, MOV_OBJECT_NONE) \
|
||||
XX(CodecVP8, TrackVideo, 7, "VP8", PSI_STREAM_VP8, MOV_OBJECT_VP8) \
|
||||
XX(CodecVP9, TrackVideo, 8, "VP9", PSI_STREAM_VP9, MOV_OBJECT_VP9) \
|
||||
XX(CodecAV1, TrackVideo, 9, "AV1", PSI_STREAM_AV1, MOV_OBJECT_AV1) \
|
||||
XX(CodecJPEG, TrackVideo, 10, "JPEG", PSI_STREAM_JPEG_2000, MOV_OBJECT_JPEG)
|
||||
|
||||
typedef enum {
|
||||
CodecInvalid = -1,
|
||||
#define XX(name, type, value, str, mpeg_id) name = value,
|
||||
#define XX(name, type, value, str, mpeg_id, mp4_id) name = value,
|
||||
CODEC_MAP(XX)
|
||||
#undef XX
|
||||
CodecMax
|
||||
|
|
@ -78,6 +80,26 @@ const char *getCodecName(CodecId codecId);
|
|||
*/
|
||||
TrackType getTrackType(CodecId codecId);
|
||||
|
||||
/**
|
||||
* 根据codecid获取mov object id
|
||||
*/
|
||||
int getMovIdByCodec(CodecId codecId);
|
||||
|
||||
/**
|
||||
* 根据mov object id获取CodecId
|
||||
*/
|
||||
CodecId getCodecByMovId(int object_id);
|
||||
|
||||
/**
|
||||
* 根据codecid获取mpeg id
|
||||
*/
|
||||
int getMpegIdByCodec(CodecId codec);
|
||||
|
||||
/**
|
||||
* 根据mpeg id获取CodecId
|
||||
*/
|
||||
CodecId getCodecByMpegId(int mpeg_id);
|
||||
|
||||
/**
|
||||
* 编码信息的抽象接口
|
||||
*/
|
||||
|
|
@ -220,17 +242,17 @@ protected:
|
|||
};
|
||||
|
||||
/**
|
||||
* 一个Frame类中可以有多个帧,他们通过 0x 00 00 01 分隔
|
||||
* 一个Frame类中可以有多个帧(AAC),时间戳会变化
|
||||
* ZLMediaKit会先把这种复合帧split成单个帧然后再处理
|
||||
* 一个复合帧可以通过无内存拷贝的方式切割成多个子Frame
|
||||
* 提供该类的目的是切割复合帧时防止内存拷贝,提高性能
|
||||
*/
|
||||
template <typename Parent>
|
||||
class FrameInternal : public Parent {
|
||||
class FrameInternalBase : public Parent {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<FrameInternal>;
|
||||
FrameInternal(const Frame::Ptr &parent_frame, char *ptr, size_t size, size_t prefix_size)
|
||||
: Parent(ptr, size, parent_frame->dts(), parent_frame->pts(), prefix_size) {
|
||||
using Ptr = std::shared_ptr<FrameInternalBase>;
|
||||
FrameInternalBase(const Frame::Ptr &parent_frame, char *ptr, size_t size, size_t prefix_size, uint64_t dts, uint64_t pts)
|
||||
: Parent(ptr, size, dts, pts, prefix_size) {
|
||||
_parent_frame = parent_frame;
|
||||
}
|
||||
bool cacheAble() const override { return _parent_frame->cacheAble(); }
|
||||
|
|
@ -240,24 +262,233 @@ private:
|
|||
};
|
||||
|
||||
/**
|
||||
* 一个Frame类中可以有多个帧(AAC),时间戳会变化
|
||||
* 一个Frame类中可以有多个帧,他们通过 0x 00 00 01 分隔
|
||||
* ZLMediaKit会先把这种复合帧split成单个帧然后再处理
|
||||
* 一个复合帧可以通过无内存拷贝的方式切割成多个子Frame
|
||||
* 提供该类的目的是切割复合帧时防止内存拷贝,提高性能
|
||||
*/
|
||||
template <typename Parent>
|
||||
class FrameTSInternal : public Parent {
|
||||
class FrameInternal : public FrameInternalBase<Parent> {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<FrameTSInternal>;
|
||||
FrameTSInternal(
|
||||
const Frame::Ptr &parent_frame, char *ptr, size_t size, size_t prefix_size, uint64_t dts, uint64_t pts)
|
||||
: Parent(ptr, size, dts, pts, prefix_size) {
|
||||
_parent_frame = parent_frame;
|
||||
using Ptr = std::shared_ptr<FrameInternal>;
|
||||
FrameInternal(const Frame::Ptr &parent_frame, char *ptr, size_t size, size_t prefix_size)
|
||||
: FrameInternalBase<Parent>(parent_frame, ptr, size, prefix_size, parent_frame->dts(), parent_frame->pts()) {}
|
||||
};
|
||||
|
||||
// 包装一个指针成不可缓存的frame
|
||||
class FrameFromPtr : public Frame {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<FrameFromPtr>;
|
||||
|
||||
FrameFromPtr(CodecId codec_id, char *ptr, size_t size, uint64_t dts, uint64_t pts = 0, size_t prefix_size = 0, bool is_key = false)
|
||||
: FrameFromPtr(ptr, size, dts, pts, prefix_size, is_key) {
|
||||
_codec_id = codec_id;
|
||||
}
|
||||
bool cacheAble() const override { return _parent_frame->cacheAble(); }
|
||||
|
||||
FrameFromPtr(char *ptr, size_t size, uint64_t dts, uint64_t pts = 0, size_t prefix_size = 0, bool is_key = false) {
|
||||
_ptr = ptr;
|
||||
_size = size;
|
||||
_dts = dts;
|
||||
_pts = pts;
|
||||
_prefix_size = prefix_size;
|
||||
_is_key = is_key;
|
||||
}
|
||||
|
||||
char *data() const override { return _ptr; }
|
||||
size_t size() const override { return _size; }
|
||||
uint64_t dts() const override { return _dts; }
|
||||
uint64_t pts() const override { return _pts ? _pts : dts(); }
|
||||
size_t prefixSize() const override { return _prefix_size; }
|
||||
bool cacheAble() const override { return false; }
|
||||
bool keyFrame() const override { return _is_key; }
|
||||
bool configFrame() const override { return false; }
|
||||
void setCodecId(CodecId codec_id) { _codec_id = codec_id; }
|
||||
|
||||
CodecId getCodecId() const override {
|
||||
if (_codec_id == CodecInvalid) {
|
||||
throw std::invalid_argument("Invalid codec type of FrameFromPtr");
|
||||
}
|
||||
return _codec_id;
|
||||
}
|
||||
|
||||
protected:
|
||||
FrameFromPtr() = default;
|
||||
|
||||
protected:
|
||||
bool _is_key;
|
||||
char *_ptr;
|
||||
uint64_t _dts;
|
||||
uint64_t _pts = 0;
|
||||
size_t _size;
|
||||
size_t _prefix_size;
|
||||
CodecId _codec_id = CodecInvalid;
|
||||
};
|
||||
|
||||
// 管理一个指针生命周期并生产一个frame
|
||||
class FrameAutoDelete : public FrameFromPtr {
|
||||
public:
|
||||
template <typename... ARGS>
|
||||
FrameAutoDelete(ARGS &&...args) : FrameFromPtr(std::forward<ARGS>(args)...) {}
|
||||
|
||||
~FrameAutoDelete() override { delete[] _ptr; };
|
||||
|
||||
bool cacheAble() const override { return true; }
|
||||
};
|
||||
|
||||
// 把一个不可缓存的frame声明为可缓存的
|
||||
template <typename Parent>
|
||||
class FrameToCache : public Parent {
|
||||
public:
|
||||
template<typename ... ARGS>
|
||||
FrameToCache(ARGS &&...args) : Parent(std::forward<ARGS>(args)...) {};
|
||||
|
||||
bool cacheAble() const override {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// 该对象的功能是把一个不可缓存的帧转换成可缓存的帧
|
||||
class FrameCacheAble : public FrameFromPtr {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<FrameCacheAble>;
|
||||
|
||||
FrameCacheAble(const Frame::Ptr &frame, bool force_key_frame = false) {
|
||||
if (frame->cacheAble()) {
|
||||
_frame = frame;
|
||||
_ptr = frame->data();
|
||||
} else {
|
||||
_buffer = FrameImp::create();
|
||||
_buffer->_buffer.assign(frame->data(), frame->size());
|
||||
_ptr = _buffer->data();
|
||||
}
|
||||
_size = frame->size();
|
||||
_dts = frame->dts();
|
||||
_pts = frame->pts();
|
||||
_prefix_size = frame->prefixSize();
|
||||
_codec_id = frame->getCodecId();
|
||||
_key = force_key_frame ? true : frame->keyFrame();
|
||||
_config = frame->configFrame();
|
||||
_drop_able = frame->dropAble();
|
||||
_decode_able = frame->decodeAble();
|
||||
}
|
||||
|
||||
/**
|
||||
* 可以被缓存
|
||||
*/
|
||||
bool cacheAble() const override { return true; }
|
||||
bool keyFrame() const override { return _key; }
|
||||
bool configFrame() const override { return _config; }
|
||||
bool dropAble() const override { return _drop_able; }
|
||||
bool decodeAble() const override { return _decode_able; }
|
||||
|
||||
private:
|
||||
Frame::Ptr _parent_frame;
|
||||
bool _key;
|
||||
bool _config;
|
||||
bool _drop_able;
|
||||
bool _decode_able;
|
||||
Frame::Ptr _frame;
|
||||
FrameImp::Ptr _buffer;
|
||||
};
|
||||
|
||||
//该类实现frame级别的时间戳覆盖
|
||||
class FrameStamp : public Frame {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<FrameStamp>;
|
||||
FrameStamp(Frame::Ptr frame, Stamp &stamp, int modify_stamp);
|
||||
~FrameStamp() override {}
|
||||
|
||||
uint64_t dts() const override { return (uint64_t)_dts; }
|
||||
uint64_t pts() const override { return (uint64_t)_pts; }
|
||||
size_t prefixSize() const override { return _frame->prefixSize(); }
|
||||
bool keyFrame() const override { return _frame->keyFrame(); }
|
||||
bool configFrame() const override { return _frame->configFrame(); }
|
||||
bool cacheAble() const override { return _frame->cacheAble(); }
|
||||
bool dropAble() const override { return _frame->dropAble(); }
|
||||
bool decodeAble() const override { return _frame->decodeAble(); }
|
||||
char *data() const override { return _frame->data(); }
|
||||
size_t size() const override { return _frame->size(); }
|
||||
CodecId getCodecId() const override { return _frame->getCodecId(); }
|
||||
|
||||
private:
|
||||
int64_t _dts;
|
||||
int64_t _pts;
|
||||
Frame::Ptr _frame;
|
||||
};
|
||||
|
||||
/**
|
||||
* 该对象可以把Buffer对象转换成可缓存的Frame对象
|
||||
*/
|
||||
template <typename Parent>
|
||||
class FrameFromBuffer : public Parent {
|
||||
public:
|
||||
/**
|
||||
* 构造frame
|
||||
* @param buf 数据缓存
|
||||
* @param dts 解码时间戳
|
||||
* @param pts 显示时间戳
|
||||
* @param prefix 帧前缀长度
|
||||
* @param offset buffer有效数据偏移量
|
||||
*/
|
||||
FrameFromBuffer(toolkit::Buffer::Ptr buf, uint64_t dts, uint64_t pts, size_t prefix, size_t offset)
|
||||
: Parent(buf->data() + offset, buf->size() - offset, dts, pts, prefix) {
|
||||
_buf = std::move(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造frame
|
||||
* @param buf 数据缓存
|
||||
* @param dts 解码时间戳
|
||||
* @param pts 显示时间戳
|
||||
* @param prefix 帧前缀长度
|
||||
* @param offset buffer有效数据偏移量
|
||||
* @param codec 帧类型
|
||||
*/
|
||||
FrameFromBuffer(toolkit::Buffer::Ptr buf, uint64_t dts, uint64_t pts, size_t prefix, size_t offset, CodecId codec)
|
||||
: Parent(codec, buf->data() + offset, buf->size() - offset, dts, pts, prefix) {
|
||||
_buf = std::move(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* 该帧可缓存
|
||||
*/
|
||||
bool cacheAble() const override { return true; }
|
||||
|
||||
private:
|
||||
toolkit::Buffer::Ptr _buf;
|
||||
};
|
||||
|
||||
/**
|
||||
* 合并一些时间戳相同的frame
|
||||
*/
|
||||
class FrameMerger {
|
||||
public:
|
||||
using onOutput = std::function<void(uint64_t dts, uint64_t pts, const toolkit::Buffer::Ptr &buffer, bool have_key_frame)>;
|
||||
using Ptr = std::shared_ptr<FrameMerger>;
|
||||
enum {
|
||||
none = 0,
|
||||
h264_prefix,
|
||||
mp4_nal_size,
|
||||
};
|
||||
|
||||
FrameMerger(int type);
|
||||
|
||||
/**
|
||||
* 刷新输出缓冲,注意此时会调用FrameMerger::inputFrame传入的onOutput回调
|
||||
* 请注意回调捕获参数此时是否有效
|
||||
*/
|
||||
void flush();
|
||||
void clear();
|
||||
bool inputFrame(const Frame::Ptr &frame, onOutput cb, toolkit::BufferLikeString *buffer = nullptr);
|
||||
|
||||
private:
|
||||
bool willFlush(const Frame::Ptr &frame) const;
|
||||
void doMerge(toolkit::BufferLikeString &buffer, const Frame::Ptr &frame) const;
|
||||
|
||||
private:
|
||||
int _type;
|
||||
bool _have_decode_able_frame = false;
|
||||
onOutput _cb;
|
||||
toolkit::List<Frame::Ptr> _frame_cache;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -393,202 +624,5 @@ private:
|
|||
std::map<void *, FrameWriterInterface::Ptr> _delegates;
|
||||
};
|
||||
|
||||
/**
|
||||
* 通过Frame接口包装指针,方便使用者把自己的数据快速接入ZLMediaKit
|
||||
*/
|
||||
class FrameFromPtr : public Frame {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<FrameFromPtr>;
|
||||
|
||||
FrameFromPtr(CodecId codec_id, char *ptr, size_t size, uint64_t dts, uint64_t pts = 0, size_t prefix_size = 0, bool is_key = false)
|
||||
: FrameFromPtr(ptr, size, dts, pts, prefix_size,is_key) {
|
||||
_codec_id = codec_id;
|
||||
}
|
||||
|
||||
FrameFromPtr(char *ptr, size_t size, uint64_t dts, uint64_t pts = 0, size_t prefix_size = 0, bool is_key = false) {
|
||||
_ptr = ptr;
|
||||
_size = size;
|
||||
_dts = dts;
|
||||
_pts = pts;
|
||||
_prefix_size = prefix_size;
|
||||
_is_key = is_key;
|
||||
}
|
||||
|
||||
char *data() const override { return _ptr; }
|
||||
size_t size() const override { return _size; }
|
||||
uint64_t dts() const override { return _dts; }
|
||||
uint64_t pts() const override { return _pts ? _pts : dts(); }
|
||||
size_t prefixSize() const override { return _prefix_size; }
|
||||
bool cacheAble() const override { return false; }
|
||||
bool keyFrame() const override { return _is_key; }
|
||||
bool configFrame() const override { return false; }
|
||||
void setCodecId(CodecId codec_id) { _codec_id = codec_id; }
|
||||
|
||||
CodecId getCodecId() const override {
|
||||
if (_codec_id == CodecInvalid) {
|
||||
throw std::invalid_argument("FrameFromPtr对象未设置codec类型");
|
||||
}
|
||||
return _codec_id;
|
||||
}
|
||||
|
||||
protected:
|
||||
FrameFromPtr() = default;
|
||||
|
||||
protected:
|
||||
bool _is_key;
|
||||
char *_ptr;
|
||||
uint64_t _dts;
|
||||
uint64_t _pts = 0;
|
||||
size_t _size;
|
||||
size_t _prefix_size;
|
||||
CodecId _codec_id = CodecInvalid;
|
||||
};
|
||||
|
||||
/**
|
||||
* 该对象的功能是把一个不可缓存的帧转换成可缓存的帧
|
||||
*/
|
||||
class FrameCacheAble : public FrameFromPtr {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<FrameCacheAble>;
|
||||
|
||||
FrameCacheAble(const Frame::Ptr &frame, bool force_key_frame = false) {
|
||||
if (frame->cacheAble()) {
|
||||
_frame = frame;
|
||||
_ptr = frame->data();
|
||||
} else {
|
||||
_buffer = FrameImp::create();
|
||||
_buffer->_buffer.assign(frame->data(), frame->size());
|
||||
_ptr = _buffer->data();
|
||||
}
|
||||
_size = frame->size();
|
||||
_dts = frame->dts();
|
||||
_pts = frame->pts();
|
||||
_prefix_size = frame->prefixSize();
|
||||
_codec_id = frame->getCodecId();
|
||||
_key = force_key_frame ? true : frame->keyFrame();
|
||||
_config = frame->configFrame();
|
||||
_drop_able = frame->dropAble();
|
||||
_decode_able = frame->decodeAble();
|
||||
}
|
||||
|
||||
/**
|
||||
* 可以被缓存
|
||||
*/
|
||||
bool cacheAble() const override { return true; }
|
||||
bool keyFrame() const override { return _key; }
|
||||
bool configFrame() const override { return _config; }
|
||||
bool dropAble() const override { return _drop_able; }
|
||||
bool decodeAble() const override { return _decode_able; }
|
||||
|
||||
private:
|
||||
bool _key;
|
||||
bool _config;
|
||||
bool _drop_able;
|
||||
bool _decode_able;
|
||||
Frame::Ptr _frame;
|
||||
FrameImp::Ptr _buffer;
|
||||
};
|
||||
|
||||
//该类实现frame级别的时间戳覆盖
|
||||
class FrameStamp : public Frame {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<FrameStamp>;
|
||||
FrameStamp(Frame::Ptr frame, Stamp &stamp, int modify_stamp);
|
||||
~FrameStamp() override {}
|
||||
|
||||
uint64_t dts() const override { return (uint64_t)_dts; }
|
||||
uint64_t pts() const override { return (uint64_t)_pts; }
|
||||
size_t prefixSize() const override { return _frame->prefixSize(); }
|
||||
bool keyFrame() const override { return _frame->keyFrame(); }
|
||||
bool configFrame() const override { return _frame->configFrame(); }
|
||||
bool cacheAble() const override { return _frame->cacheAble(); }
|
||||
bool dropAble() const override { return _frame->dropAble(); }
|
||||
bool decodeAble() const override { return _frame->decodeAble(); }
|
||||
char *data() const override { return _frame->data(); }
|
||||
size_t size() const override { return _frame->size(); }
|
||||
CodecId getCodecId() const override { return _frame->getCodecId(); }
|
||||
|
||||
private:
|
||||
int64_t _dts;
|
||||
int64_t _pts;
|
||||
Frame::Ptr _frame;
|
||||
};
|
||||
|
||||
/**
|
||||
* 该对象可以把Buffer对象转换成可缓存的Frame对象
|
||||
*/
|
||||
template <typename Parent>
|
||||
class FrameWrapper : public Parent {
|
||||
public:
|
||||
/**
|
||||
* 构造frame
|
||||
* @param buf 数据缓存
|
||||
* @param dts 解码时间戳
|
||||
* @param pts 显示时间戳
|
||||
* @param prefix 帧前缀长度
|
||||
* @param offset buffer有效数据偏移量
|
||||
*/
|
||||
FrameWrapper(toolkit::Buffer::Ptr buf, uint64_t dts, uint64_t pts, size_t prefix, size_t offset)
|
||||
: Parent(buf->data() + offset, buf->size() - offset, dts, pts, prefix) {
|
||||
_buf = std::move(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造frame
|
||||
* @param buf 数据缓存
|
||||
* @param dts 解码时间戳
|
||||
* @param pts 显示时间戳
|
||||
* @param prefix 帧前缀长度
|
||||
* @param offset buffer有效数据偏移量
|
||||
* @param codec 帧类型
|
||||
*/
|
||||
FrameWrapper(toolkit::Buffer::Ptr buf, uint64_t dts, uint64_t pts, size_t prefix, size_t offset, CodecId codec)
|
||||
: Parent(codec, buf->data() + offset, buf->size() - offset, dts, pts, prefix) {
|
||||
_buf = std::move(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* 该帧可缓存
|
||||
*/
|
||||
bool cacheAble() const override { return true; }
|
||||
|
||||
private:
|
||||
toolkit::Buffer::Ptr _buf;
|
||||
};
|
||||
|
||||
/**
|
||||
* 合并一些时间戳相同的frame
|
||||
*/
|
||||
class FrameMerger {
|
||||
public:
|
||||
using onOutput = std::function<void(uint64_t dts, uint64_t pts, const toolkit::Buffer::Ptr &buffer, bool have_key_frame)>;
|
||||
using Ptr = std::shared_ptr<FrameMerger>;
|
||||
enum {
|
||||
none = 0,
|
||||
h264_prefix,
|
||||
mp4_nal_size,
|
||||
};
|
||||
|
||||
FrameMerger(int type);
|
||||
|
||||
/**
|
||||
* 刷新输出缓冲,注意此时会调用FrameMerger::inputFrame传入的onOutput回调
|
||||
* 请注意回调捕获参数此时是否有效
|
||||
*/
|
||||
void flush();
|
||||
void clear();
|
||||
bool inputFrame(const Frame::Ptr &frame, onOutput cb, toolkit::BufferLikeString *buffer = nullptr);
|
||||
|
||||
private:
|
||||
bool willFlush(const Frame::Ptr &frame) const;
|
||||
void doMerge(toolkit::BufferLikeString &buffer, const Frame::Ptr &frame) const;
|
||||
|
||||
private:
|
||||
int _type;
|
||||
bool _have_decode_able_frame = false;
|
||||
onOutput _cb;
|
||||
toolkit::List<Frame::Ptr> _frame_cache;
|
||||
};
|
||||
|
||||
} // namespace mediakit
|
||||
#endif // ZLMEDIAKIT_FRAME_H
|
||||
|
|
@ -13,10 +13,8 @@
|
|||
#include "Util/logger.h"
|
||||
#include "Extension/H265.h"
|
||||
#include "Extension/H264.h"
|
||||
#include "Extension/AAC.h"
|
||||
#include "Extension/G711.h"
|
||||
#include "Extension/Opus.h"
|
||||
#include "Extension/JPEG.h"
|
||||
#include "Extension/Factory.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace toolkit;
|
||||
|
|
@ -61,85 +59,21 @@ int MP4Demuxer::getAllTracks() {
|
|||
return mov_reader_getinfo(_mov_reader.get(),&s_on_track,this);
|
||||
}
|
||||
|
||||
#define SWITCH_CASE(obj_id) case obj_id : return #obj_id
|
||||
static const char *getObjectName(int obj_id) {
|
||||
switch (obj_id) {
|
||||
SWITCH_CASE(MOV_OBJECT_TEXT);
|
||||
SWITCH_CASE(MOV_OBJECT_MP4V);
|
||||
SWITCH_CASE(MOV_OBJECT_H264);
|
||||
SWITCH_CASE(MOV_OBJECT_HEVC);
|
||||
SWITCH_CASE(MOV_OBJECT_AAC);
|
||||
SWITCH_CASE(MOV_OBJECT_MP2V);
|
||||
SWITCH_CASE(MOV_OBJECT_AAC_MAIN);
|
||||
SWITCH_CASE(MOV_OBJECT_AAC_LOW);
|
||||
SWITCH_CASE(MOV_OBJECT_AAC_SSR);
|
||||
SWITCH_CASE(MOV_OBJECT_MP3);
|
||||
SWITCH_CASE(MOV_OBJECT_MP1V);
|
||||
SWITCH_CASE(MOV_OBJECT_MP1A);
|
||||
SWITCH_CASE(MOV_OBJECT_JPEG);
|
||||
SWITCH_CASE(MOV_OBJECT_PNG);
|
||||
SWITCH_CASE(MOV_OBJECT_JPEG2000);
|
||||
SWITCH_CASE(MOV_OBJECT_G719);
|
||||
SWITCH_CASE(MOV_OBJECT_OPUS);
|
||||
SWITCH_CASE(MOV_OBJECT_G711a);
|
||||
SWITCH_CASE(MOV_OBJECT_G711u);
|
||||
SWITCH_CASE(MOV_OBJECT_AV1);
|
||||
default: return "unknown mp4 object";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MP4Demuxer::onVideoTrack(uint32_t track, uint8_t object, int width, int height, const void *extra, size_t bytes) {
|
||||
Track::Ptr video;
|
||||
switch (object) {
|
||||
case MOV_OBJECT_H264: {
|
||||
video = std::make_shared<H264Track>();
|
||||
_track_to_codec.emplace(track, video);
|
||||
break;
|
||||
}
|
||||
|
||||
case MOV_OBJECT_HEVC: {
|
||||
video = std::make_shared<H265Track>();
|
||||
_track_to_codec.emplace(track, video);
|
||||
break;
|
||||
}
|
||||
|
||||
case MOV_OBJECT_JPEG: {
|
||||
video = std::make_shared<JPEGTrack>();
|
||||
_track_to_codec.emplace(track, video);
|
||||
break;
|
||||
}
|
||||
|
||||
default: WarnL << "不支持该编码类型的MP4,已忽略:" << getObjectName(object); break;
|
||||
auto video = Factory::getTrackByCodecId(getCodecByMovId(object));
|
||||
if (!video) {
|
||||
return;
|
||||
}
|
||||
_track_to_codec.emplace(track, video);
|
||||
if (extra && bytes) {
|
||||
video->setExtraData((uint8_t *)extra, bytes);
|
||||
}
|
||||
}
|
||||
|
||||
void MP4Demuxer::onAudioTrack(uint32_t track_id, uint8_t object, int channel_count, int bit_per_sample, int sample_rate, const void *extra, size_t bytes) {
|
||||
Track::Ptr audio;
|
||||
switch(object){
|
||||
case MOV_OBJECT_AAC:{
|
||||
audio = std::make_shared<AACTrack>();
|
||||
_track_to_codec.emplace(track_id, audio);
|
||||
break;
|
||||
}
|
||||
|
||||
case MOV_OBJECT_G711a:
|
||||
case MOV_OBJECT_G711u:{
|
||||
audio = std::make_shared<G711Track>(object == MOV_OBJECT_G711a ? CodecG711A : CodecG711U, sample_rate, channel_count, bit_per_sample / channel_count );
|
||||
_track_to_codec.emplace(track_id, audio);
|
||||
break;
|
||||
}
|
||||
|
||||
case MOV_OBJECT_OPUS: {
|
||||
audio = std::make_shared<OpusTrack>();
|
||||
_track_to_codec.emplace(track_id, audio);
|
||||
break;
|
||||
}
|
||||
|
||||
default: WarnL << "不支持该编码类型的MP4,已忽略:" << getObjectName(object); break;
|
||||
auto audio = Factory::getTrackByCodecId(getCodecByMovId(object), sample_rate, channel_count, bit_per_sample / channel_count);
|
||||
if (!audio) {
|
||||
return;
|
||||
}
|
||||
if (extra && bytes) {
|
||||
audio->setExtraData((uint8_t *)extra, bytes);
|
||||
|
|
@ -225,10 +159,10 @@ Frame::Ptr MP4Demuxer::makeFrame(uint32_t track_id, const Buffer::Ptr &buf, int6
|
|||
offset += (frame_len + 4);
|
||||
}
|
||||
if (codec == CodecH264) {
|
||||
ret = std::make_shared<FrameWrapper<H264FrameNoCacheAble> >(buf, (uint64_t)dts, (uint64_t)pts, 4, 0);
|
||||
ret = std::make_shared<FrameFromBuffer<H264FrameNoCacheAble> >(buf, (uint64_t)dts, (uint64_t)pts, 4, 0);
|
||||
break;
|
||||
}
|
||||
ret = std::make_shared<FrameWrapper<H265FrameNoCacheAble> >(buf, (uint64_t)dts, (uint64_t)pts, 4, 0);
|
||||
ret = std::make_shared<FrameFromBuffer<H265FrameNoCacheAble> >(buf, (uint64_t)dts, (uint64_t)pts, 4, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -238,7 +172,7 @@ Frame::Ptr MP4Demuxer::makeFrame(uint32_t track_id, const Buffer::Ptr &buf, int6
|
|||
}
|
||||
|
||||
default: {
|
||||
ret = std::make_shared<FrameWrapper<FrameFromPtr>>(buf, (uint64_t)dts, (uint64_t)pts, 0, 0, codec);
|
||||
ret = std::make_shared<FrameFromBuffer<FrameFromPtr>>(buf, (uint64_t)dts, (uint64_t)pts, 0, 0, codec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -133,21 +133,6 @@ bool MP4MuxerInterface::inputFrame(const Frame::Ptr &frame) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static uint8_t getObject(CodecId codecId) {
|
||||
switch (codecId){
|
||||
case CodecG711A : return MOV_OBJECT_G711a;
|
||||
case CodecG711U : return MOV_OBJECT_G711u;
|
||||
case CodecOpus : return MOV_OBJECT_OPUS;
|
||||
case CodecAAC : return MOV_OBJECT_AAC;
|
||||
case CodecH264 : return MOV_OBJECT_H264;
|
||||
case CodecH265 : return MOV_OBJECT_HEVC;
|
||||
case CodecJPEG : return MOV_OBJECT_JPEG;
|
||||
case CodecVP9: return MOV_OBJECT_VP9;
|
||||
case CodecAV1: return MOV_OBJECT_AV1;
|
||||
default : return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void MP4MuxerInterface::stampSync() {
|
||||
if (_codec_to_trackid.size() < 2) {
|
||||
return;
|
||||
|
|
@ -172,14 +157,14 @@ bool MP4MuxerInterface::addTrack(const Track::Ptr &track) {
|
|||
if (!_mov_writter) {
|
||||
_mov_writter = createWriter();
|
||||
}
|
||||
auto mp4_object = getObject(track->getCodecId());
|
||||
if (!mp4_object) {
|
||||
WarnL << "MP4录制不支持该编码格式:" << track->getCodecName();
|
||||
auto mp4_object = getMovIdByCodec(track->getCodecId());
|
||||
if (mp4_object == MOV_OBJECT_NONE) {
|
||||
WarnL << "Unsupported codec: " << track->getCodecName();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!track->ready()) {
|
||||
WarnL << "Track[" << track->getCodecName() << "]未就绪";
|
||||
WarnL << "Track[" << track->getCodecName() << "] unready";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,26 +30,22 @@ MpegMuxer::~MpegMuxer() {
|
|||
releaseContext();
|
||||
}
|
||||
|
||||
#define XX(name, type, value, str, mpeg_id) \
|
||||
case name: { \
|
||||
if (mpeg_id == PSI_STREAM_RESERVED) { \
|
||||
break; \
|
||||
} \
|
||||
if (track->getTrackType() == TrackVideo) { \
|
||||
_have_video = true; \
|
||||
} \
|
||||
_codec_to_trackid[track->getCodecId()] = mpeg_muxer_add_stream((::mpeg_muxer_t *)_context, mpeg_id, nullptr, 0); \
|
||||
return true; \
|
||||
}
|
||||
bool MpegMuxer::addTrack(const Track::Ptr &track) {
|
||||
switch (track->getCodecId()) {
|
||||
CODEC_MAP(XX)
|
||||
default: break;
|
||||
auto mpeg_id = getMpegIdByCodec(track->getCodecId());
|
||||
if (mpeg_id == PSI_STREAM_RESERVED) {
|
||||
WarnL << "Unsupported codec: " << track->getCodecName();
|
||||
return false;
|
||||
}
|
||||
WarnL << "不支持该编码格式,已忽略:" << track->getCodecName();
|
||||
return false;
|
||||
|
||||
if (track->getTrackType() == TrackVideo) {
|
||||
_have_video = true;
|
||||
}
|
||||
auto extra_data = track->getExtraData();
|
||||
_codec_to_trackid[track->getCodecId()] = mpeg_muxer_add_stream((::mpeg_muxer_t *)_context, mpeg_id,
|
||||
extra_data ? extra_data->data() : nullptr,
|
||||
extra_data ? extra_data->size(): 0);
|
||||
return true;
|
||||
}
|
||||
#undef XX
|
||||
|
||||
bool MpegMuxer::inputFrame(const Frame::Ptr &frame) {
|
||||
auto it = _codec_to_trackid.find(frame->getCodecId());
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include "Extension/AAC.h"
|
||||
#include "Extension/G711.h"
|
||||
#include "Extension/Opus.h"
|
||||
#include "Extension/Factory.h"
|
||||
|
||||
#if defined(ENABLE_RTPPROXY) || defined(ENABLE_HLS)
|
||||
#include "mpeg-ts.h"
|
||||
|
|
@ -85,78 +86,18 @@ DecoderImp::DecoderImp(const Decoder::Ptr &decoder, MediaSinkInterface *sink){
|
|||
}
|
||||
|
||||
#if defined(ENABLE_RTPPROXY) || defined(ENABLE_HLS)
|
||||
#define SWITCH_CASE(codec_id) case codec_id : return #codec_id
|
||||
static const char *getCodecName(int codec_id) {
|
||||
switch (codec_id) {
|
||||
SWITCH_CASE(PSI_STREAM_MPEG1);
|
||||
SWITCH_CASE(PSI_STREAM_MPEG2);
|
||||
SWITCH_CASE(PSI_STREAM_AUDIO_MPEG1);
|
||||
SWITCH_CASE(PSI_STREAM_MP3);
|
||||
SWITCH_CASE(PSI_STREAM_AAC);
|
||||
SWITCH_CASE(PSI_STREAM_MPEG4);
|
||||
SWITCH_CASE(PSI_STREAM_MPEG4_AAC_LATM);
|
||||
SWITCH_CASE(PSI_STREAM_H264);
|
||||
SWITCH_CASE(PSI_STREAM_MPEG4_AAC);
|
||||
SWITCH_CASE(PSI_STREAM_H265);
|
||||
SWITCH_CASE(PSI_STREAM_AUDIO_AC3);
|
||||
SWITCH_CASE(PSI_STREAM_AUDIO_EAC3);
|
||||
SWITCH_CASE(PSI_STREAM_AUDIO_DTS);
|
||||
SWITCH_CASE(PSI_STREAM_VIDEO_DIRAC);
|
||||
SWITCH_CASE(PSI_STREAM_VIDEO_VC1);
|
||||
SWITCH_CASE(PSI_STREAM_VIDEO_SVAC);
|
||||
SWITCH_CASE(PSI_STREAM_AUDIO_SVAC);
|
||||
SWITCH_CASE(PSI_STREAM_AUDIO_G711A);
|
||||
SWITCH_CASE(PSI_STREAM_AUDIO_G711U);
|
||||
SWITCH_CASE(PSI_STREAM_AUDIO_G722);
|
||||
SWITCH_CASE(PSI_STREAM_AUDIO_G723);
|
||||
SWITCH_CASE(PSI_STREAM_AUDIO_G729);
|
||||
SWITCH_CASE(PSI_STREAM_AUDIO_OPUS);
|
||||
default : return "unknown codec";
|
||||
|
||||
void DecoderImp::onStream(int stream, int codecid, const void *extra, size_t bytes, int finish) {
|
||||
// G711传统只支持 8000/1/16的规格,FFmpeg貌似做了扩展,但是这里不管它了
|
||||
auto track = Factory::getTrackByCodecId(getCodecByMpegId(codecid), 8000, 1, 16);
|
||||
if (!track) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void DecoderImp::onStream(int stream, int codecid, const void *extra, size_t bytes, int finish){
|
||||
switch (codecid) {
|
||||
case PSI_STREAM_H264: {
|
||||
onTrack(std::make_shared<H264Track>());
|
||||
break;
|
||||
}
|
||||
|
||||
case PSI_STREAM_H265: {
|
||||
onTrack(std::make_shared<H265Track>());
|
||||
break;
|
||||
}
|
||||
|
||||
case PSI_STREAM_MPEG4_AAC :
|
||||
case PSI_STREAM_AAC: {
|
||||
onTrack(std::make_shared<AACTrack>());
|
||||
break;
|
||||
}
|
||||
|
||||
case PSI_STREAM_AUDIO_G711A:
|
||||
case PSI_STREAM_AUDIO_G711U: {
|
||||
auto codec = codecid == PSI_STREAM_AUDIO_G711A ? CodecG711A : CodecG711U;
|
||||
//G711传统只支持 8000/1/16的规格,FFmpeg貌似做了扩展,但是这里不管它了
|
||||
onTrack(std::make_shared<G711Track>(codec, 8000, 1, 16));
|
||||
break;
|
||||
}
|
||||
|
||||
case PSI_STREAM_AUDIO_OPUS: {
|
||||
onTrack(std::make_shared<OpusTrack>());
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
if(codecid != 0){
|
||||
WarnL<< "unsupported codec type:" << getCodecName(codecid) << " " << (int)codecid;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
//防止未获取视频track提前complete导致忽略后续视频的问题,用于兼容一些不太规范的ps流
|
||||
if (finish && _tracks[TrackVideo] ) {
|
||||
onTrack(std::move(track));
|
||||
// 防止未获取视频track提前complete导致忽略后续视频的问题,用于兼容一些不太规范的ps流
|
||||
if (finish && _tracks[TrackVideo]) {
|
||||
_sink->addTrackCompleted();
|
||||
InfoL << "add track finished";
|
||||
InfoL << "Add track finished";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -171,7 +112,7 @@ void DecoderImp::onDecode(int stream,int codecid,int flags,int64_t pts,int64_t d
|
|||
}
|
||||
auto frame = std::make_shared<H264FrameNoCacheAble>((char *) data, bytes, (uint64_t)dts, (uint64_t)pts, prefixSize((char *) data, bytes));
|
||||
_merger.inputFrame(frame,[this](uint64_t dts, uint64_t pts, const Buffer::Ptr &buffer, bool) {
|
||||
onFrame(std::make_shared<FrameWrapper<H264FrameNoCacheAble> >(buffer, dts, pts, prefixSize(buffer->data(), buffer->size()), 0));
|
||||
onFrame(std::make_shared<FrameFromBuffer<H264FrameNoCacheAble> >(buffer, dts, pts, prefixSize(buffer->data(), buffer->size()), 0));
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
|
@ -182,7 +123,7 @@ void DecoderImp::onDecode(int stream,int codecid,int flags,int64_t pts,int64_t d
|
|||
}
|
||||
auto frame = std::make_shared<H265FrameNoCacheAble>((char *) data, bytes, (uint64_t)dts, (uint64_t)pts, prefixSize((char *) data, bytes));
|
||||
_merger.inputFrame(frame,[this](uint64_t dts, uint64_t pts, const Buffer::Ptr &buffer, bool) {
|
||||
onFrame(std::make_shared<FrameWrapper<H265FrameNoCacheAble> >(buffer, dts, pts, prefixSize(buffer->data(), buffer->size()), 0));
|
||||
onFrame(std::make_shared<FrameFromBuffer<H265FrameNoCacheAble> >(buffer, dts, pts, prefixSize(buffer->data(), buffer->size()), 0));
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
|
@ -223,7 +164,7 @@ void DecoderImp::onDecode(int stream,int codecid,int flags,int64_t pts,int64_t d
|
|||
default:
|
||||
// 海康的 PS 流中会有 codecid 为 0xBD 的包
|
||||
if (codecid != 0 && codecid != 0xBD) {
|
||||
WarnL << "unsupported codec type:" << getCodecName(codecid) << " " << (int) codecid;
|
||||
WarnL << "Unsupported codec type:" << codecid;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,11 +12,6 @@
|
|||
#include "GB28181Process.h"
|
||||
#include "Extension/CommonRtp.h"
|
||||
#include "Extension/Factory.h"
|
||||
#include "Extension/G711.h"
|
||||
#include "Extension/H264.h"
|
||||
#include "Extension/H265.h"
|
||||
#include "Extension/Opus.h"
|
||||
#include "Extension/JPEG.h"
|
||||
#include "Http/HttpTSPlayer.h"
|
||||
#include "Util/File.h"
|
||||
#include "Common/config.h"
|
||||
|
|
@ -90,7 +85,8 @@ bool GB28181Process::inputRtp(bool, const char *data, size_t data_len) {
|
|||
case Rtsp::PT_PCMU: {
|
||||
// CodecG711U or CodecG711A
|
||||
ref = std::make_shared<RtpReceiverImp>(8000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); });
|
||||
auto track = std::make_shared<G711Track>(pt == Rtsp::PT_PCMU ? CodecG711U : CodecG711A, 8000, 1, 16);
|
||||
auto track = Factory::getTrackByCodecId(pt == Rtsp::PT_PCMU ? CodecG711U : CodecG711A, 8000, 1, 16);
|
||||
CHECK(track);
|
||||
_interface->addTrack(track);
|
||||
_rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track);
|
||||
break;
|
||||
|
|
@ -98,7 +94,8 @@ bool GB28181Process::inputRtp(bool, const char *data, size_t data_len) {
|
|||
case Rtsp::PT_JPEG: {
|
||||
// mjpeg
|
||||
ref = std::make_shared<RtpReceiverImp>(90000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); });
|
||||
auto track = std::make_shared<JPEGTrack>();
|
||||
auto track = Factory::getTrackByCodecId(CodecJPEG);
|
||||
CHECK(track);
|
||||
_interface->addTrack(track);
|
||||
_rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track);
|
||||
break;
|
||||
|
|
@ -107,19 +104,20 @@ bool GB28181Process::inputRtp(bool, const char *data, size_t data_len) {
|
|||
if (pt == opus_pt) {
|
||||
// opus负载
|
||||
ref = std::make_shared<RtpReceiverImp>(48000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); });
|
||||
auto track = std::make_shared<OpusTrack>();
|
||||
auto track = Factory::getTrackByCodecId(CodecOpus);
|
||||
CHECK(track);
|
||||
_interface->addTrack(track);
|
||||
_rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track);
|
||||
} else if (pt == h265_pt) {
|
||||
// H265负载
|
||||
ref = std::make_shared<RtpReceiverImp>(90000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); });
|
||||
auto track = std::make_shared<H265Track>();
|
||||
auto track = Factory::getTrackByCodecId(CodecH265);
|
||||
_interface->addTrack(track);
|
||||
_rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track);
|
||||
} else if (pt == h264_pt) {
|
||||
// H264负载
|
||||
ref = std::make_shared<RtpReceiverImp>(90000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); });
|
||||
auto track = std::make_shared<H264Track>();
|
||||
auto track = Factory::getTrackByCodecId(CodecH264);
|
||||
_interface->addTrack(track);
|
||||
_rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
#include "PSEncoder.h"
|
||||
#include "Common/config.h"
|
||||
#include "Extension/H264.h"
|
||||
#include "Extension/CommonRtp.h"
|
||||
#include "Rtsp/RtspMuxer.h"
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue