From 1609fe67d735f4e520ae2d0de7b5862a771bba52 Mon Sep 17 00:00:00 2001 From: fruit Juice <2317232721@qq.com> Date: Tue, 7 Nov 2023 23:36:41 +0800 Subject: [PATCH] =?UTF-8?q?Track=E6=96=B0=E5=A2=9Eupdate=E6=96=B9=E6=B3=95?= =?UTF-8?q?=EF=BC=8C=E6=94=AF=E6=8C=81=E6=9B=B4=E6=96=B0=E5=AE=BD=E9=AB=98?= =?UTF-8?q?=E9=87=87=E6=A0=B7=E7=8E=87=E7=AD=89=E4=BF=A1=E6=81=AF=20(#2960?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 当变分辨率时候,实时更新MP4封装层的参数信息,避免出现封装层与编码(SPS)层视频宽高不一样,造成解码参数错误花屏;同时也支持更新音频采样率等信息。 --------- Co-authored-by: xia-chu <771730766@qq.com> --- src/Common/MultiMediaSourceMuxer.cpp | 1 + src/Extension/AAC.cpp | 98 +++++++++++++++------------- src/Extension/AAC.h | 1 + src/Extension/H264.cpp | 4 ++ src/Extension/H264.h | 1 + src/Extension/H265.cpp | 4 ++ src/Extension/H265.h | 1 + src/Extension/Track.h | 5 ++ src/Player/PlayerProxy.cpp | 1 + src/Record/MP4Muxer.cpp | 1 + src/Rtmp/Rtmp.cpp | 2 + 11 files changed, 75 insertions(+), 44 deletions(-) diff --git a/src/Common/MultiMediaSourceMuxer.cpp b/src/Common/MultiMediaSourceMuxer.cpp index bbb9b357..e3151093 100644 --- a/src/Common/MultiMediaSourceMuxer.cpp +++ b/src/Common/MultiMediaSourceMuxer.cpp @@ -45,6 +45,7 @@ static string getTrackInfoStr(const TrackSource *track_src){ _StrPrinter codec_info; auto tracks = track_src->getTracks(true); for (auto &track : tracks) { + track->update(); auto codec_type = track->getTrackType(); codec_info << track->getCodecName(); switch (codec_type) { diff --git a/src/Extension/AAC.cpp b/src/Extension/AAC.cpp index 1047a8b3..27f18359 100644 --- a/src/Extension/AAC.cpp +++ b/src/Extension/AAC.cpp @@ -21,53 +21,56 @@ namespace mediakit{ #ifndef ENABLE_MP4 unsigned const samplingFrequencyTable[16] = { 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350, 0, 0, 0 }; -class AdtsHeader{ +class AdtsHeader { public: - unsigned int syncword = 0; //12 bslbf 同步字The bit string ‘1111 1111 1111’,说明一个ADTS帧的开始 - unsigned int id; //1 bslbf MPEG 标示符, 设置为1 - unsigned int layer; //2 uimsbf Indicates which layer is used. Set to ‘00’ - unsigned int protection_absent; //1 bslbf 表示是否误码校验 - unsigned int profile; //2 uimsbf 表示使用哪个级别的AAC,如01 Low Complexity(LC)--- AACLC - unsigned int sf_index; //4 uimsbf 表示使用的采样率下标 - unsigned int private_bit; //1 bslbf - unsigned int channel_configuration; //3 uimsbf 表示声道数 - unsigned int original; //1 bslbf - unsigned int home; //1 bslbf - //下面的为改变的参数即每一帧都不同 - unsigned int copyright_identification_bit; //1 bslbf - unsigned int copyright_identification_start; //1 bslbf + unsigned int syncword = 0; // 12 bslbf 同步字The bit string ‘1111 1111 1111’,说明一个ADTS帧的开始 + unsigned int id; // 1 bslbf MPEG 标示符, 设置为1 + unsigned int layer; // 2 uimsbf Indicates which layer is used. Set to ‘00’ + unsigned int protection_absent; // 1 bslbf 表示是否误码校验 + unsigned int profile; // 2 uimsbf 表示使用哪个级别的AAC,如01 Low Complexity(LC)--- AACLC + unsigned int sf_index; // 4 uimsbf 表示使用的采样率下标 + unsigned int private_bit; // 1 bslbf + unsigned int channel_configuration; // 3 uimsbf 表示声道数 + unsigned int original; // 1 bslbf + unsigned int home; // 1 bslbf + // 下面的为改变的参数即每一帧都不同 + unsigned int copyright_identification_bit; // 1 bslbf + unsigned int copyright_identification_start; // 1 bslbf unsigned int aac_frame_length; // 13 bslbf 一个ADTS帧的长度包括ADTS头和raw data block - unsigned int adts_buffer_fullness; //11 bslbf 0x7FF 说明是码率可变的码流 - //no_raw_data_blocks_in_frame 表示ADTS帧中有number_of_raw_data_blocks_in_frame + 1个AAC原始帧. - //所以说number_of_raw_data_blocks_in_frame == 0 - //表示说ADTS帧中有一个AAC数据块并不是说没有。(一个AAC原始帧包含一段时间内1024个采样及相关数据) - unsigned int no_raw_data_blocks_in_frame; //2 uimsfb + unsigned int adts_buffer_fullness; // 11 bslbf 0x7FF 说明是码率可变的码流 + // no_raw_data_blocks_in_frame 表示ADTS帧中有number_of_raw_data_blocks_in_frame + 1个AAC原始帧. + // 所以说number_of_raw_data_blocks_in_frame == 0 + // 表示说ADTS帧中有一个AAC数据块并不是说没有。(一个AAC原始帧包含一段时间内1024个采样及相关数据) + unsigned int no_raw_data_blocks_in_frame; // 2 uimsfb }; static void dumpAdtsHeader(const AdtsHeader &hed, uint8_t *out) { - out[0] = (hed.syncword >> 4 & 0xFF); //8bit - out[1] = (hed.syncword << 4 & 0xF0); //4 bit - out[1] |= (hed.id << 3 & 0x08); //1 bit - out[1] |= (hed.layer << 1 & 0x06); //2bit - out[1] |= (hed.protection_absent & 0x01); //1 bit + out[0] = (hed.syncword >> 4 & 0xFF); // 8bit + out[1] = (hed.syncword << 4 & 0xF0); // 4 bit + out[1] |= (hed.id << 3 & 0x08); // 1 bit + out[1] |= (hed.layer << 1 & 0x06); // 2bit + out[1] |= (hed.protection_absent & 0x01); // 1 bit out[2] = (hed.profile << 6 & 0xC0); // 2 bit - out[2] |= (hed.sf_index << 2 & 0x3C); //4bit - out[2] |= (hed.private_bit << 1 & 0x02); //1 bit - out[2] |= (hed.channel_configuration >> 2 & 0x03); //1 bit - out[3] = (hed.channel_configuration << 6 & 0xC0); // 2 bit - out[3] |= (hed.original << 5 & 0x20); //1 bit - out[3] |= (hed.home << 4 & 0x10); //1 bit - out[3] |= (hed.copyright_identification_bit << 3 & 0x08); //1 bit - out[3] |= (hed.copyright_identification_start << 2 & 0x04); //1 bit - out[3] |= (hed.aac_frame_length >> 11 & 0x03); //2 bit - out[4] = (hed.aac_frame_length >> 3 & 0xFF); //8 bit - out[5] = (hed.aac_frame_length << 5 & 0xE0); //3 bit - out[5] |= (hed.adts_buffer_fullness >> 6 & 0x1F); //5 bit - out[6] = (hed.adts_buffer_fullness << 2 & 0xFC); //6 bit - out[6] |= (hed.no_raw_data_blocks_in_frame & 0x03); //2 bit + out[2] |= (hed.sf_index << 2 & 0x3C); // 4bit + out[2] |= (hed.private_bit << 1 & 0x02); // 1 bit + out[2] |= (hed.channel_configuration >> 2 & 0x03); // 1 bit + out[3] = (hed.channel_configuration << 6 & 0xC0); // 2 bit + out[3] |= (hed.original << 5 & 0x20); // 1 bit + out[3] |= (hed.home << 4 & 0x10); // 1 bit + out[3] |= (hed.copyright_identification_bit << 3 & 0x08); // 1 bit + out[3] |= (hed.copyright_identification_start << 2 & 0x04); // 1 bit + out[3] |= (hed.aac_frame_length >> 11 & 0x03); // 2 bit + out[4] = (hed.aac_frame_length >> 3 & 0xFF); // 8 bit + out[5] = (hed.aac_frame_length << 5 & 0xE0); // 3 bit + out[5] |= (hed.adts_buffer_fullness >> 6 & 0x1F); // 5 bit + out[6] = (hed.adts_buffer_fullness << 2 & 0xFC); // 6 bit + out[6] |= (hed.no_raw_data_blocks_in_frame & 0x03); // 2 bit } -static void parseAacConfig(const string &config, AdtsHeader &adts) { +static bool parseAacConfig(const string &config, AdtsHeader &adts) { + if (config.size() < 2) { + return false; + } uint8_t cfg1 = config[0]; uint8_t cfg2 = config[1]; @@ -94,6 +97,7 @@ static void parseAacConfig(const string &config, AdtsHeader &adts) { adts.aac_frame_length = 7; adts.adts_buffer_fullness = 2047; adts.no_raw_data_blocks_in_frame = 0; + return true; } #endif// ENABLE_MP4 @@ -168,10 +172,12 @@ int dumpAacConfig(const string &config, size_t length, uint8_t *out, size_t out_ #endif } -bool parseAacConfig(const string &config, int &samplerate, int &channels){ +bool parseAacConfig(const string &config, int &samplerate, int &channels) { #ifndef ENABLE_MP4 AdtsHeader header; - parseAacConfig(config, header); + if (!parseAacConfig(config, header)) { + return false; + } samplerate = samplingFrequencyTable[header.sf_index]; channels = header.channel_configuration; return true; @@ -326,11 +332,14 @@ bool AACTrack::inputFrame_l(const Frame::Ptr &frame) { return false; } +bool AACTrack::update() { + return parseAacConfig(_cfg, _sampleRate, _channel); +} + void AACTrack::onReady() { - if (_cfg.size() < 2) { - return; + if (!parseAacConfig(_cfg, _sampleRate, _channel)) { + _cfg.clear(); } - parseAacConfig(_cfg, _sampleRate, _channel); } Track::Ptr AACTrack::clone() { @@ -342,6 +351,7 @@ Sdp::Ptr AACTrack::getSdp() { WarnL << getCodecName() << " Track未准备好"; return nullptr; } + update(); return std::make_shared(getConfig(), getAudioSampleRate(), getAudioChannel(), getBitRate() / 1024); } diff --git a/src/Extension/AAC.h b/src/Extension/AAC.h index b95fc6f2..32cf934b 100644 --- a/src/Extension/AAC.h +++ b/src/Extension/AAC.h @@ -52,6 +52,7 @@ public: int getAudioSampleRate() const override; int getAudioSampleBit() const override; bool inputFrame(const Frame::Ptr &frame) override; + bool update() override; private: void onReady(); diff --git a/src/Extension/H264.cpp b/src/Extension/H264.cpp index eeccd600..eda6b188 100644 --- a/src/Extension/H264.cpp +++ b/src/Extension/H264.cpp @@ -168,6 +168,10 @@ bool H264Track::inputFrame(const Frame::Ptr &frame) { return ret; } +bool H264Track::update() { + return getAVCInfo(_sps, _width, _height, _fps); +} + void H264Track::onReady() { if (!getAVCInfo(_sps, _width, _height, _fps)) { _sps.clear(); diff --git a/src/Extension/H264.h b/src/Extension/H264.h index 30a8f747..0afe593d 100644 --- a/src/Extension/H264.h +++ b/src/Extension/H264.h @@ -128,6 +128,7 @@ public: int getVideoWidth() const override; float getVideoFps() const override; bool inputFrame(const Frame::Ptr &frame) override; + bool update() override; private: void onReady(); diff --git a/src/Extension/H265.cpp b/src/Extension/H265.cpp index 9985a9cb..926ab2a4 100644 --- a/src/Extension/H265.cpp +++ b/src/Extension/H265.cpp @@ -144,6 +144,10 @@ bool H265Track::inputFrame_l(const Frame::Ptr &frame) { return ret; } +bool H265Track::update() { + return getHEVCInfo(_vps, _sps, _width, _height, _fps); +} + void H265Track::onReady() { if (!getHEVCInfo(_vps, _sps, _width, _height, _fps)) { _vps.clear(); diff --git a/src/Extension/H265.h b/src/Extension/H265.h index 521663f4..912f1f46 100644 --- a/src/Extension/H265.h +++ b/src/Extension/H265.h @@ -150,6 +150,7 @@ public: int getVideoHeight() const override; float getVideoFps() const override; bool inputFrame(const Frame::Ptr &frame) override; + bool update() override; private: void onReady(); diff --git a/src/Extension/Track.h b/src/Extension/Track.h index e7aa2b7c..3a1b8519 100644 --- a/src/Extension/Track.h +++ b/src/Extension/Track.h @@ -39,6 +39,11 @@ public: */ virtual Track::Ptr clone() = 0; + /** + * 更新track信息,比如触发sps/pps解析 + */ + virtual bool update() { return false; } + /** * 生成sdp * @return sdp对象 diff --git a/src/Player/PlayerProxy.cpp b/src/Player/PlayerProxy.cpp index 2a319ff8..73e46b71 100644 --- a/src/Player/PlayerProxy.cpp +++ b/src/Player/PlayerProxy.cpp @@ -70,6 +70,7 @@ void PlayerProxy::setTranslationInfo() _transtalion_info.stream_info.clear(); auto tracks = _muxer->getTracks(); for (auto &track : tracks) { + track->update(); _transtalion_info.stream_info.emplace_back(); auto &back = _transtalion_info.stream_info.back(); back.bitrate = track->getBitRate(); diff --git a/src/Record/MP4Muxer.cpp b/src/Record/MP4Muxer.cpp index c79cc132..5458a31d 100644 --- a/src/Record/MP4Muxer.cpp +++ b/src/Record/MP4Muxer.cpp @@ -198,6 +198,7 @@ bool MP4MuxerInterface::addTrack(const Track::Ptr &track) { return false; } + track->update(); switch (track->getCodecId()) { case CodecG711A: case CodecG711U: diff --git a/src/Rtmp/Rtmp.cpp b/src/Rtmp/Rtmp.cpp index 140afeed..33c46f11 100644 --- a/src/Rtmp/Rtmp.cpp +++ b/src/Rtmp/Rtmp.cpp @@ -57,6 +57,7 @@ AudioMeta::AudioMeta(const AudioTrack::Ptr &audio) { } uint8_t getAudioRtmpFlags(const Track::Ptr &track) { + track->update(); switch (track->getTrackType()) { case TrackAudio: { auto audioTrack = std::dynamic_pointer_cast(track); @@ -115,6 +116,7 @@ uint8_t getAudioRtmpFlags(const Track::Ptr &track) { void Metadata::addTrack(AMFValue &metadata, const Track::Ptr &track) { Metadata::Ptr new_metadata; + track->update(); switch (track->getTrackType()) { case TrackVideo: { new_metadata = std::make_shared(std::dynamic_pointer_cast(track));