From 630b5d75d970b97d1ddf7b687b2d8e4e704fd778 Mon Sep 17 00:00:00 2001 From: xia-chu <771730766@qq.com> Date: Sat, 9 Dec 2023 03:18:57 +0800 Subject: [PATCH] =?UTF-8?q?=E7=B2=BE=E7=AE=80=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/source/mk_h264_splitter.cpp | 7 ++- src/Codec/Transcode.cpp | 1 - src/Common/Device.cpp | 51 ++++-------------- src/Common/MediaSink.cpp | 11 ++-- src/Extension/AAC.cpp | 2 - src/Extension/AAC.h | 7 --- src/Extension/Factory.cpp | 35 +++++++++++++ src/Extension/Factory.h | 4 ++ src/Extension/Frame.cpp | 2 + src/Extension/Frame.h | 4 +- src/Player/PlayerProxy.cpp | 1 - src/Record/MP4Demuxer.cpp | 20 ++------ src/Rtp/Decoder.cpp | 91 ++++++++------------------------- 13 files changed, 89 insertions(+), 147 deletions(-) diff --git a/api/source/mk_h264_splitter.cpp b/api/source/mk_h264_splitter.cpp index 5f146dba..bed5576f 100644 --- a/api/source/mk_h264_splitter.cpp +++ b/api/source/mk_h264_splitter.cpp @@ -10,8 +10,7 @@ #include "mk_h264_splitter.h" #include "Http/HttpRequestSplitter.h" -#include "Extension/H264.h" -#include "Extension/H265.h" +#include "Extension/Factory.h" using namespace mediakit; @@ -71,9 +70,9 @@ const char *H264Splitter::onSearchPacketTail(const char *data, size_t len) { auto last_frame_len = next_frame - last_frame; Frame::Ptr frame; if (_h265) { - frame = std::make_shared((char *) last_frame, last_frame_len, 0, 0, prefixSize(last_frame, last_frame_len)); + frame = Factory::getFrameFromPtr(CodecH265, (char *)last_frame, last_frame_len, 0, 0); } else { - frame = std::make_shared((char *) last_frame, last_frame_len, 0, 0, prefixSize(last_frame, last_frame_len)); + frame = Factory::getFrameFromPtr(CodecH264, (char *)last_frame, last_frame_len, 0, 0); } if (frame->decodeAble()) { _search_pos = 0; diff --git a/src/Codec/Transcode.cpp b/src/Codec/Transcode.cpp index 25f9e77c..af5ed44a 100644 --- a/src/Codec/Transcode.cpp +++ b/src/Codec/Transcode.cpp @@ -15,7 +15,6 @@ #include "Util/File.h" #include "Util/uv_errno.h" #include "Transcode.h" -#include "Extension/AAC.h" #include "Common/config.h" #define MAX_DELAY_SECOND 3 diff --git a/src/Common/Device.cpp b/src/Common/Device.cpp index 53bd615c..f3d93544 100644 --- a/src/Common/Device.cpp +++ b/src/Common/Device.cpp @@ -11,11 +11,7 @@ #include "Device.h" #include "Util/logger.h" #include "Util/base64.h" -#include "Extension/AAC.h" -#include "Extension/Opus.h" -#include "Extension/G711.h" -#include "Extension/H264.h" -#include "Extension/H265.h" +#include "Extension/Factory.h" #ifdef ENABLE_FAAC #include "Codec/AACEncoder.h" #endif //ENABLE_FAAC @@ -85,15 +81,7 @@ bool DevChannel::inputH264(const char *data, int len, uint64_t dts, uint64_t pts pts = dts; } - //由于rtmp/hls/mp4需要缓存时间戳相同的帧, - //所以使用FrameNoCacheAble类型的帧反而会在转换成FrameCacheAble时多次内存拷贝 - //在此处只拷贝一次,性能开销更低 - auto frame = FrameImp::create(); - frame->_dts = dts; - frame->_pts = pts; - frame->_buffer.assign(data, len); - frame->_prefix_size = prefixSize(data,len); - return inputFrame(frame); + return inputFrame(Factory::getFrameFromPtr(CodecH264,data, len, dts, pts)); } bool DevChannel::inputH265(const char *data, int len, uint64_t dts, uint64_t pts) { @@ -104,17 +92,11 @@ bool DevChannel::inputH265(const char *data, int len, uint64_t dts, uint64_t pts pts = dts; } - //由于rtmp/hls/mp4需要缓存时间戳相同的帧, - //所以使用FrameNoCacheAble类型的帧反而会在转换成FrameCacheAble时多次内存拷贝 - //在此处只拷贝一次,性能开销更低 - auto frame = FrameImp::create(); - frame->_dts = dts; - frame->_pts = pts; - frame->_buffer.assign(data, len); - frame->_prefix_size = prefixSize(data,len); - return inputFrame(frame); + return inputFrame(Factory::getFrameFromPtr(CodecH265, data, len, dts, pts)); } +#define ADTS_HEADER_LEN 7 + bool DevChannel::inputAAC(const char *data_without_adts, int len, uint64_t dts, const char *adts_header){ if (dts == 0) { dts = _aTicker[1].elapsedTime(); @@ -122,47 +104,36 @@ bool DevChannel::inputAAC(const char *data_without_adts, int len, uint64_t dts, if (!adts_header) { //没有adts头 - return inputFrame(std::make_shared(_audio->codecId, (char *) data_without_adts, len, dts, 0, 0)); + return inputFrame(std::make_shared(CodecAAC, (char *) data_without_adts, len, dts, 0, 0)); } if (adts_header + ADTS_HEADER_LEN == data_without_adts) { //adts头和帧在一起 - return inputFrame(std::make_shared(_audio->codecId, (char *) data_without_adts - ADTS_HEADER_LEN, len + ADTS_HEADER_LEN, dts, 0, ADTS_HEADER_LEN)); + return inputFrame(std::make_shared(CodecAAC, (char *) data_without_adts - ADTS_HEADER_LEN, len + ADTS_HEADER_LEN, dts, 0, ADTS_HEADER_LEN)); } //adts头和帧不在一起 char *data_with_adts = new char[len + ADTS_HEADER_LEN]; memcpy(data_with_adts, adts_header, ADTS_HEADER_LEN); memcpy(data_with_adts + ADTS_HEADER_LEN, data_without_adts, len); - return inputFrame(std::make_shared(_audio->codecId, data_with_adts, len + ADTS_HEADER_LEN, dts, 0, ADTS_HEADER_LEN)); - + return inputFrame(std::make_shared(CodecAAC, data_with_adts, len + ADTS_HEADER_LEN, dts, 0, ADTS_HEADER_LEN)); } bool DevChannel::inputAudio(const char *data, int len, uint64_t dts){ if (dts == 0) { dts = _aTicker[1].elapsedTime(); } - return inputFrame(std::make_shared(_audio->codecId, (char *) data, len, dts, 0)); + return inputFrame(Factory::getFrameFromPtr(_audio->codecId, (char *) data, len, dts, dts)); } bool DevChannel::initVideo(const VideoInfo &info) { _video = std::make_shared(info); - switch (info.codecId){ - case CodecH265 : return addTrack(std::make_shared()); - case CodecH264 : return addTrack(std::make_shared()); - default: WarnL << "不支持该类型的视频编码类型:" << info.codecId; return false; - } + return addTrack(Factory::getTrackByCodecId(info.codecId)); } bool DevChannel::initAudio(const AudioInfo &info) { _audio = std::make_shared(info); - switch (info.codecId) { - case CodecAAC : return addTrack(std::make_shared()); - case CodecG711A : - case CodecG711U : return addTrack(std::make_shared(info.codecId, info.iSampleRate, info.iChannel, info.iSampleBit)); - case CodecOpus : return addTrack(std::make_shared()); - default: WarnL << "不支持该类型的音频编码类型:" << info.codecId; return false; - } + return addTrack(Factory::getTrackByCodecId(info.codecId, info.iSampleRate, info.iChannel, info.iSampleBit)); } bool DevChannel::inputFrame(const Frame::Ptr &frame) { diff --git a/src/Common/MediaSink.cpp b/src/Common/MediaSink.cpp index 4297e50e..f92e9cae 100644 --- a/src/Common/MediaSink.cpp +++ b/src/Common/MediaSink.cpp @@ -9,8 +9,8 @@ */ #include "MediaSink.h" -#include "Extension/AAC.h" #include "Common/config.h" +#include "Extension/Factory.h" using namespace std; @@ -226,16 +226,16 @@ static uint8_t s_mute_adts[] = {0xff, 0xf1, 0x6c, 0x40, 0x2d, 0x3f, 0xfc, 0x00, 0xc5, 0x97, 0x39, 0x6a, 0xb8, 0xa2, 0x55, 0xa8, 0xf8}; #define MUTE_ADTS_DATA s_mute_adts -#define MUTE_ADTS_DATA_LEN sizeof(s_mute_adts) #define MUTE_ADTS_DATA_MS 128 +static uint8_t ADTS_CONFIG[2] = { 0x15, 0x88 }; bool MuteAudioMaker::inputFrame(const Frame::Ptr &frame) { if (frame->getTrackType() == TrackVideo) { auto audio_idx = frame->dts() / MUTE_ADTS_DATA_MS; if (_audio_idx != audio_idx) { _audio_idx = audio_idx; - auto aacFrame = std::make_shared>(CodecAAC, (char *) MUTE_ADTS_DATA, MUTE_ADTS_DATA_LEN, - _audio_idx * MUTE_ADTS_DATA_MS, 0, ADTS_HEADER_LEN); + auto aacFrame = std::make_shared>(CodecAAC, (char *) MUTE_ADTS_DATA, sizeof(s_mute_adts), + _audio_idx * MUTE_ADTS_DATA_MS, 0, 7); return FrameDispatcher::inputFrame(aacFrame); } } @@ -249,7 +249,8 @@ bool MediaSink::addMuteAudioTrack() { if (_track_map.find(TrackAudio) != _track_map.end()) { return false; } - auto audio = std::make_shared(MUTE_ADTS_DATA, ADTS_HEADER_LEN); + auto audio = Factory::getTrackByCodecId(CodecAAC); + audio->setExtraData(ADTS_CONFIG, 2); _track_map[audio->getTrackType()] = std::make_pair(audio, true); audio->addDelegate([this](const Frame::Ptr &frame) { return onTrackFrame(frame); diff --git a/src/Extension/AAC.cpp b/src/Extension/AAC.cpp index 7df73916..38db7c36 100644 --- a/src/Extension/AAC.cpp +++ b/src/Extension/AAC.cpp @@ -244,8 +244,6 @@ AACTrack::AACTrack(const string &aac_cfg) { update(); } -AACTrack::AACTrack(const uint8_t *adts, size_t size) : AACTrack(makeAacConfig(adts, size)) {} - CodecId AACTrack::getCodecId() const { return CodecAAC; } diff --git a/src/Extension/AAC.h b/src/Extension/AAC.h index fdbc5c75..9df559be 100644 --- a/src/Extension/AAC.h +++ b/src/Extension/AAC.h @@ -17,8 +17,6 @@ namespace mediakit{ -int dumpAacConfig(const std::string &config, size_t length, uint8_t *out, size_t out_size); - /** * aac音频通道 */ @@ -33,11 +31,6 @@ public: */ AACTrack(const std::string &aac_cfg); - /** - * 通过aac adts头 构造对象 - */ - AACTrack(const uint8_t *adts, size_t size); - bool ready() const override; CodecId getCodecId() const override; int getAudioChannel() const override; diff --git a/src/Extension/Factory.cpp b/src/Extension/Factory.cpp index 3be898dd..8a1339eb 100644 --- a/src/Extension/Factory.cpp +++ b/src/Extension/Factory.cpp @@ -29,6 +29,7 @@ #include "Common/config.h" using namespace std; +using namespace toolkit; namespace mediakit{ @@ -293,5 +294,39 @@ AMFValue Factory::getAmfByCodecId(CodecId codecId) { } } +static size_t aacPrefixSize(const char *data, size_t bytes) { + uint8_t *ptr = (uint8_t *)data; + size_t prefix = 0; + if (!(bytes > ADTS_HEADER_LEN && ptr[0] == 0xFF && (ptr[1] & 0xF0) == 0xF0)) { + return 0; + } + return ADTS_HEADER_LEN; +} + +Frame::Ptr Factory::getFrameFromPtr(CodecId codec, const char *data, size_t bytes, uint64_t dts, uint64_t pts) { + switch (codec) { + case CodecH264: return std::make_shared((char *)data, bytes, dts, pts, prefixSize(data, bytes)); + case CodecH265: return std::make_shared((char *)data, bytes, dts, pts, prefixSize(data, bytes)); + case CodecAAC: return std::make_shared(codec, (char *)data, bytes, dts, pts, aacPrefixSize(data, bytes)); + case CodecOpus: + case CodecG711A: + case CodecG711U: return std::make_shared(codec, (char *)data, bytes, dts, pts); + default: return nullptr; + } +} + +Frame::Ptr Factory::getFrameFromBuffer(CodecId codec, const Buffer::Ptr &data, uint64_t dts, uint64_t pts) { + switch (codec) { + case CodecH264: return std::make_shared>(data, dts, pts, prefixSize(data->data(), data->size()), 0); + case CodecH265: return std::make_shared>(data, dts, pts, prefixSize(data->data(), data->size()), 0); + case CodecJPEG: return std::make_shared(data, dts); + case CodecAAC: return std::make_shared>(data, dts, pts, aacPrefixSize(data->data(), data->size()), 0, codec); + case CodecOpus: + case CodecG711A: + case CodecG711U: return std::make_shared>(data, dts, pts, 0, 0, codec); + default: return nullptr; + } +} + }//namespace mediakit diff --git a/src/Extension/Factory.h b/src/Extension/Factory.h index c6fcb16c..09cc14b7 100644 --- a/src/Extension/Factory.h +++ b/src/Extension/Factory.h @@ -14,6 +14,7 @@ #include #include "Rtmp/amf.h" #include "Extension/Track.h" +#include "Extension/Frame.h" #include "Rtsp/RtpCodec.h" #include "Rtmp/RtmpCodec.h" @@ -85,6 +86,9 @@ public: * 根据codecId获取rtmp的codec描述 */ static AMFValue getAmfByCodecId(CodecId codecId); + + static Frame::Ptr getFrameFromPtr(CodecId codec, const char *data, size_t size, uint64_t dts, uint64_t pts); + static Frame::Ptr getFrameFromBuffer(CodecId codec, const toolkit::Buffer::Ptr &data, uint64_t dts, uint64_t pts); }; }//namespace mediakit diff --git a/src/Extension/Frame.cpp b/src/Extension/Frame.cpp index e1d11110..d0a9bebd 100644 --- a/src/Extension/Frame.cpp +++ b/src/Extension/Frame.cpp @@ -97,6 +97,8 @@ CodecId getCodecByMpegId(int mpeg_id) { #define XX(name, type, value, str, mpeg_id, mp4_id) case mpeg_id : return name; CODEC_MAP(XX) #undef XX + // 海康的 PS 流中会有0xBD 的包 + case 0xBD: return CodecInvalid; default : WarnL << "Unsupported mpeg: " << mpeg_id; return CodecInvalid; } } diff --git a/src/Extension/Frame.h b/src/Extension/Frame.h index 590221b6..5dcd1005 100644 --- a/src/Extension/Frame.h +++ b/src/Extension/Frame.h @@ -251,9 +251,9 @@ template class FrameInternalBase : public Parent { public: using Ptr = std::shared_ptr; - FrameInternalBase(const Frame::Ptr &parent_frame, char *ptr, size_t size, size_t prefix_size, uint64_t dts, uint64_t pts) + FrameInternalBase(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; + _parent_frame = std::move(parent_frame); } bool cacheAble() const override { return _parent_frame->cacheAble(); } diff --git a/src/Player/PlayerProxy.cpp b/src/Player/PlayerProxy.cpp index 9ca1886a..ad463984 100644 --- a/src/Player/PlayerProxy.cpp +++ b/src/Player/PlayerProxy.cpp @@ -10,7 +10,6 @@ #include "PlayerProxy.h" #include "Common/config.h" -#include "Extension/AAC.h" #include "Rtmp/RtmpMediaSource.h" #include "Rtmp/RtmpPlayer.h" #include "Rtsp/RtspMediaSource.h" diff --git a/src/Record/MP4Demuxer.cpp b/src/Record/MP4Demuxer.cpp index 022a6c3d..398b2815 100644 --- a/src/Record/MP4Demuxer.cpp +++ b/src/Record/MP4Demuxer.cpp @@ -11,9 +11,6 @@ #ifdef ENABLE_MP4 #include "MP4Demuxer.h" #include "Util/logger.h" -#include "Extension/H265.h" -#include "Extension/H264.h" -#include "Extension/JPEG.h" #include "Extension/Factory.h" using namespace std; @@ -143,8 +140,8 @@ Frame::Ptr MP4Demuxer::makeFrame(uint32_t track_id, const Buffer::Ptr &buf, int6 Frame::Ptr ret; auto codec = it->second->getCodecId(); switch (codec) { - case CodecH264 : - case CodecH265 : { + case CodecH264: + case CodecH265: { auto bytes = buf->size(); auto data = buf->data(); auto offset = 0u; @@ -158,21 +155,12 @@ Frame::Ptr MP4Demuxer::makeFrame(uint32_t track_id, const Buffer::Ptr &buf, int6 memcpy(data + offset, "\x00\x00\x00\x01", 4); offset += (frame_len + 4); } - if (codec == CodecH264) { - ret = std::make_shared >(buf, (uint64_t)dts, (uint64_t)pts, 4, 0); - break; - } - ret = std::make_shared >(buf, (uint64_t)dts, (uint64_t)pts, 4, 0); - break; - } - - case CodecJPEG: { - ret = std::make_shared(buf, (uint64_t)dts, 0, 0); + ret = Factory::getFrameFromBuffer(codec, buf, dts, pts); break; } default: { - ret = std::make_shared>(buf, (uint64_t)dts, (uint64_t)pts, 0, 0, codec); + ret = Factory::getFrameFromBuffer(codec, buf, dts, pts); break; } } diff --git a/src/Rtp/Decoder.cpp b/src/Rtp/Decoder.cpp index 4bd52f86..d53bb36c 100644 --- a/src/Rtp/Decoder.cpp +++ b/src/Rtp/Decoder.cpp @@ -11,11 +11,6 @@ #include "Decoder.h" #include "PSDecoder.h" #include "TSDecoder.h" -#include "Extension/H264.h" -#include "Extension/H265.h" -#include "Extension/AAC.h" -#include "Extension/G711.h" -#include "Extension/Opus.h" #include "Extension/Factory.h" #if defined(ENABLE_RTPPROXY) || defined(ENABLE_HLS) @@ -101,72 +96,25 @@ void DecoderImp::onStream(int stream, int codecid, const void *extra, size_t byt } } -void DecoderImp::onDecode(int stream,int codecid,int flags,int64_t pts,int64_t dts,const void *data,size_t bytes) { +void DecoderImp::onDecode(int stream, int codecid, int flags, int64_t pts, int64_t dts, const void *data, size_t bytes) { pts /= 90; dts /= 90; - switch (codecid) { - case PSI_STREAM_H264: { - if (!_tracks[TrackVideo]) { - onTrack(std::make_shared()); - } - auto frame = std::make_shared((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 >(buffer, dts, pts, prefixSize(buffer->data(), buffer->size()), 0)); - }); - break; - } - - case PSI_STREAM_H265: { - if (!_tracks[TrackVideo]) { - onTrack(std::make_shared()); - } - auto frame = std::make_shared((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 >(buffer, dts, pts, prefixSize(buffer->data(), buffer->size()), 0)); - }); - break; - } - - case PSI_STREAM_MPEG4_AAC : - case PSI_STREAM_AAC: { - uint8_t *ptr = (uint8_t *)data; - if(!(bytes > 7 && ptr[0] == 0xFF && (ptr[1] & 0xF0) == 0xF0)){ - //这不是aac - break; - } - if (!_tracks[TrackAudio]) { - onTrack(std::make_shared()); - } - onFrame(std::make_shared(CodecAAC, (char *) data, bytes, (uint64_t)dts, 0, ADTS_HEADER_LEN)); - break; - } - - case PSI_STREAM_AUDIO_G711A: - case PSI_STREAM_AUDIO_G711U: { - auto codec = codecid == PSI_STREAM_AUDIO_G711A ? CodecG711A : CodecG711U; - if (!_tracks[TrackAudio]) { - //G711传统只支持 8000/1/16的规格,FFmpeg貌似做了扩展,但是这里不管它了 - onTrack(std::make_shared(codec, 8000, 1, 16)); - } - onFrame(std::make_shared(codec, (char *) data, bytes, (uint64_t)dts)); - break; - } - - case PSI_STREAM_AUDIO_OPUS: { - if (!_tracks[TrackAudio]) { - onTrack(std::make_shared()); - } - onFrame(std::make_shared(CodecOpus, (char *) data, bytes, (uint64_t)dts)); - break; - } - - default: - // 海康的 PS 流中会有 codecid 为 0xBD 的包 - if (codecid != 0 && codecid != 0xBD) { - WarnL << "Unsupported codec type:" << codecid; - } - break; + auto codec = getCodecByMpegId(codecid); + if (codec == CodecInvalid) { + return; + } + if (!_tracks[getTrackType(codec)]) { + onTrack(Factory::getTrackByCodecId(codec, 8000, 1, 16)); + } + // TODO 支持多track + auto frame = Factory::getFrameFromPtr(codec, (char *) data, bytes, dts, pts); + if (getTrackType(codec) == TrackVideo) { + _merger.inputFrame(frame, [&](uint64_t dts, uint64_t pts, const Buffer::Ptr &buffer, bool) { + onFrame(Factory::getFrameFromBuffer(codec, buffer, dts, pts)); + }); + } else { + onFrame(frame); } } #else @@ -175,6 +123,9 @@ void DecoderImp::onStream(int stream,int codecid,const void *extra,size_t bytes, #endif void DecoderImp::onTrack(const Track::Ptr &track) { + if (!track) { + return; + } if (!_tracks[track->getTrackType()]) { _tracks[track->getTrackType()] = track; _sink->addTrack(track); @@ -183,7 +134,9 @@ void DecoderImp::onTrack(const Track::Ptr &track) { } void DecoderImp::onFrame(const Frame::Ptr &frame) { - _sink->inputFrame(frame); + if (frame) { + _sink->inputFrame(frame); + } } }//namespace mediakit