mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-22 19:00:01 +08:00
Track新增update方法,支持更新宽高采样率等信息 (#2960)
当变分辨率时候,实时更新MP4封装层的参数信息,避免出现封装层与编码(SPS)层视频宽高不一样,造成解码参数错误花屏;同时也支持更新音频采样率等信息。 --------- Co-authored-by: xia-chu <771730766@qq.com>
This commit is contained in:
parent
77b3c4312e
commit
1609fe67d7
@ -45,6 +45,7 @@ static string getTrackInfoStr(const TrackSource *track_src){
|
|||||||
_StrPrinter codec_info;
|
_StrPrinter codec_info;
|
||||||
auto tracks = track_src->getTracks(true);
|
auto tracks = track_src->getTracks(true);
|
||||||
for (auto &track : tracks) {
|
for (auto &track : tracks) {
|
||||||
|
track->update();
|
||||||
auto codec_type = track->getTrackType();
|
auto codec_type = track->getTrackType();
|
||||||
codec_info << track->getCodecName();
|
codec_info << track->getCodecName();
|
||||||
switch (codec_type) {
|
switch (codec_type) {
|
||||||
|
@ -21,53 +21,56 @@ namespace mediakit{
|
|||||||
#ifndef ENABLE_MP4
|
#ifndef ENABLE_MP4
|
||||||
unsigned const samplingFrequencyTable[16] = { 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350, 0, 0, 0 };
|
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:
|
public:
|
||||||
unsigned int syncword = 0; //12 bslbf 同步字The bit string ‘1111 1111 1111’,说明一个ADTS帧的开始
|
unsigned int syncword = 0; // 12 bslbf 同步字The bit string ‘1111 1111 1111’,说明一个ADTS帧的开始
|
||||||
unsigned int id; //1 bslbf MPEG 标示符, 设置为1
|
unsigned int id; // 1 bslbf MPEG 标示符, 设置为1
|
||||||
unsigned int layer; //2 uimsbf Indicates which layer is used. Set to ‘00’
|
unsigned int layer; // 2 uimsbf Indicates which layer is used. Set to ‘00’
|
||||||
unsigned int protection_absent; //1 bslbf 表示是否误码校验
|
unsigned int protection_absent; // 1 bslbf 表示是否误码校验
|
||||||
unsigned int profile; //2 uimsbf 表示使用哪个级别的AAC,如01 Low Complexity(LC)--- AACLC
|
unsigned int profile; // 2 uimsbf 表示使用哪个级别的AAC,如01 Low Complexity(LC)--- AACLC
|
||||||
unsigned int sf_index; //4 uimsbf 表示使用的采样率下标
|
unsigned int sf_index; // 4 uimsbf 表示使用的采样率下标
|
||||||
unsigned int private_bit; //1 bslbf
|
unsigned int private_bit; // 1 bslbf
|
||||||
unsigned int channel_configuration; //3 uimsbf 表示声道数
|
unsigned int channel_configuration; // 3 uimsbf 表示声道数
|
||||||
unsigned int original; //1 bslbf
|
unsigned int original; // 1 bslbf
|
||||||
unsigned int home; //1 bslbf
|
unsigned int home; // 1 bslbf
|
||||||
//下面的为改变的参数即每一帧都不同
|
// 下面的为改变的参数即每一帧都不同
|
||||||
unsigned int copyright_identification_bit; //1 bslbf
|
unsigned int copyright_identification_bit; // 1 bslbf
|
||||||
unsigned int copyright_identification_start; //1 bslbf
|
unsigned int copyright_identification_start; // 1 bslbf
|
||||||
unsigned int aac_frame_length; // 13 bslbf 一个ADTS帧的长度包括ADTS头和raw data block
|
unsigned int aac_frame_length; // 13 bslbf 一个ADTS帧的长度包括ADTS头和raw data block
|
||||||
unsigned int adts_buffer_fullness; //11 bslbf 0x7FF 说明是码率可变的码流
|
unsigned int adts_buffer_fullness; // 11 bslbf 0x7FF 说明是码率可变的码流
|
||||||
//no_raw_data_blocks_in_frame 表示ADTS帧中有number_of_raw_data_blocks_in_frame + 1个AAC原始帧.
|
// no_raw_data_blocks_in_frame 表示ADTS帧中有number_of_raw_data_blocks_in_frame + 1个AAC原始帧.
|
||||||
//所以说number_of_raw_data_blocks_in_frame == 0
|
// 所以说number_of_raw_data_blocks_in_frame == 0
|
||||||
//表示说ADTS帧中有一个AAC数据块并不是说没有。(一个AAC原始帧包含一段时间内1024个采样及相关数据)
|
// 表示说ADTS帧中有一个AAC数据块并不是说没有。(一个AAC原始帧包含一段时间内1024个采样及相关数据)
|
||||||
unsigned int no_raw_data_blocks_in_frame; //2 uimsfb
|
unsigned int no_raw_data_blocks_in_frame; // 2 uimsfb
|
||||||
};
|
};
|
||||||
|
|
||||||
static void dumpAdtsHeader(const AdtsHeader &hed, uint8_t *out) {
|
static void dumpAdtsHeader(const AdtsHeader &hed, uint8_t *out) {
|
||||||
out[0] = (hed.syncword >> 4 & 0xFF); //8bit
|
out[0] = (hed.syncword >> 4 & 0xFF); // 8bit
|
||||||
out[1] = (hed.syncword << 4 & 0xF0); //4 bit
|
out[1] = (hed.syncword << 4 & 0xF0); // 4 bit
|
||||||
out[1] |= (hed.id << 3 & 0x08); //1 bit
|
out[1] |= (hed.id << 3 & 0x08); // 1 bit
|
||||||
out[1] |= (hed.layer << 1 & 0x06); //2bit
|
out[1] |= (hed.layer << 1 & 0x06); // 2bit
|
||||||
out[1] |= (hed.protection_absent & 0x01); //1 bit
|
out[1] |= (hed.protection_absent & 0x01); // 1 bit
|
||||||
out[2] = (hed.profile << 6 & 0xC0); // 2 bit
|
out[2] = (hed.profile << 6 & 0xC0); // 2 bit
|
||||||
out[2] |= (hed.sf_index << 2 & 0x3C); //4bit
|
out[2] |= (hed.sf_index << 2 & 0x3C); // 4bit
|
||||||
out[2] |= (hed.private_bit << 1 & 0x02); //1 bit
|
out[2] |= (hed.private_bit << 1 & 0x02); // 1 bit
|
||||||
out[2] |= (hed.channel_configuration >> 2 & 0x03); //1 bit
|
out[2] |= (hed.channel_configuration >> 2 & 0x03); // 1 bit
|
||||||
out[3] = (hed.channel_configuration << 6 & 0xC0); // 2 bit
|
out[3] = (hed.channel_configuration << 6 & 0xC0); // 2 bit
|
||||||
out[3] |= (hed.original << 5 & 0x20); //1 bit
|
out[3] |= (hed.original << 5 & 0x20); // 1 bit
|
||||||
out[3] |= (hed.home << 4 & 0x10); //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_bit << 3 & 0x08); // 1 bit
|
||||||
out[3] |= (hed.copyright_identification_start << 2 & 0x04); //1 bit
|
out[3] |= (hed.copyright_identification_start << 2 & 0x04); // 1 bit
|
||||||
out[3] |= (hed.aac_frame_length >> 11 & 0x03); //2 bit
|
out[3] |= (hed.aac_frame_length >> 11 & 0x03); // 2 bit
|
||||||
out[4] = (hed.aac_frame_length >> 3 & 0xFF); //8 bit
|
out[4] = (hed.aac_frame_length >> 3 & 0xFF); // 8 bit
|
||||||
out[5] = (hed.aac_frame_length << 5 & 0xE0); //3 bit
|
out[5] = (hed.aac_frame_length << 5 & 0xE0); // 3 bit
|
||||||
out[5] |= (hed.adts_buffer_fullness >> 6 & 0x1F); //5 bit
|
out[5] |= (hed.adts_buffer_fullness >> 6 & 0x1F); // 5 bit
|
||||||
out[6] = (hed.adts_buffer_fullness << 2 & 0xFC); //6 bit
|
out[6] = (hed.adts_buffer_fullness << 2 & 0xFC); // 6 bit
|
||||||
out[6] |= (hed.no_raw_data_blocks_in_frame & 0x03); //2 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 cfg1 = config[0];
|
||||||
uint8_t cfg2 = config[1];
|
uint8_t cfg2 = config[1];
|
||||||
|
|
||||||
@ -94,6 +97,7 @@ static void parseAacConfig(const string &config, AdtsHeader &adts) {
|
|||||||
adts.aac_frame_length = 7;
|
adts.aac_frame_length = 7;
|
||||||
adts.adts_buffer_fullness = 2047;
|
adts.adts_buffer_fullness = 2047;
|
||||||
adts.no_raw_data_blocks_in_frame = 0;
|
adts.no_raw_data_blocks_in_frame = 0;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
#endif// ENABLE_MP4
|
#endif// ENABLE_MP4
|
||||||
|
|
||||||
@ -168,10 +172,12 @@ int dumpAacConfig(const string &config, size_t length, uint8_t *out, size_t out_
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parseAacConfig(const string &config, int &samplerate, int &channels){
|
bool parseAacConfig(const string &config, int &samplerate, int &channels) {
|
||||||
#ifndef ENABLE_MP4
|
#ifndef ENABLE_MP4
|
||||||
AdtsHeader header;
|
AdtsHeader header;
|
||||||
parseAacConfig(config, header);
|
if (!parseAacConfig(config, header)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
samplerate = samplingFrequencyTable[header.sf_index];
|
samplerate = samplingFrequencyTable[header.sf_index];
|
||||||
channels = header.channel_configuration;
|
channels = header.channel_configuration;
|
||||||
return true;
|
return true;
|
||||||
@ -326,11 +332,14 @@ bool AACTrack::inputFrame_l(const Frame::Ptr &frame) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AACTrack::update() {
|
||||||
|
return parseAacConfig(_cfg, _sampleRate, _channel);
|
||||||
|
}
|
||||||
|
|
||||||
void AACTrack::onReady() {
|
void AACTrack::onReady() {
|
||||||
if (_cfg.size() < 2) {
|
if (!parseAacConfig(_cfg, _sampleRate, _channel)) {
|
||||||
return;
|
_cfg.clear();
|
||||||
}
|
}
|
||||||
parseAacConfig(_cfg, _sampleRate, _channel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Track::Ptr AACTrack::clone() {
|
Track::Ptr AACTrack::clone() {
|
||||||
@ -342,6 +351,7 @@ Sdp::Ptr AACTrack::getSdp() {
|
|||||||
WarnL << getCodecName() << " Track未准备好";
|
WarnL << getCodecName() << " Track未准备好";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
update();
|
||||||
return std::make_shared<AACSdp>(getConfig(), getAudioSampleRate(), getAudioChannel(), getBitRate() / 1024);
|
return std::make_shared<AACSdp>(getConfig(), getAudioSampleRate(), getAudioChannel(), getBitRate() / 1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,6 +52,7 @@ public:
|
|||||||
int getAudioSampleRate() const override;
|
int getAudioSampleRate() const override;
|
||||||
int getAudioSampleBit() const override;
|
int getAudioSampleBit() const override;
|
||||||
bool inputFrame(const Frame::Ptr &frame) override;
|
bool inputFrame(const Frame::Ptr &frame) override;
|
||||||
|
bool update() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void onReady();
|
void onReady();
|
||||||
|
@ -168,6 +168,10 @@ bool H264Track::inputFrame(const Frame::Ptr &frame) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool H264Track::update() {
|
||||||
|
return getAVCInfo(_sps, _width, _height, _fps);
|
||||||
|
}
|
||||||
|
|
||||||
void H264Track::onReady() {
|
void H264Track::onReady() {
|
||||||
if (!getAVCInfo(_sps, _width, _height, _fps)) {
|
if (!getAVCInfo(_sps, _width, _height, _fps)) {
|
||||||
_sps.clear();
|
_sps.clear();
|
||||||
|
@ -128,6 +128,7 @@ public:
|
|||||||
int getVideoWidth() const override;
|
int getVideoWidth() const override;
|
||||||
float getVideoFps() const override;
|
float getVideoFps() const override;
|
||||||
bool inputFrame(const Frame::Ptr &frame) override;
|
bool inputFrame(const Frame::Ptr &frame) override;
|
||||||
|
bool update() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void onReady();
|
void onReady();
|
||||||
|
@ -144,6 +144,10 @@ bool H265Track::inputFrame_l(const Frame::Ptr &frame) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool H265Track::update() {
|
||||||
|
return getHEVCInfo(_vps, _sps, _width, _height, _fps);
|
||||||
|
}
|
||||||
|
|
||||||
void H265Track::onReady() {
|
void H265Track::onReady() {
|
||||||
if (!getHEVCInfo(_vps, _sps, _width, _height, _fps)) {
|
if (!getHEVCInfo(_vps, _sps, _width, _height, _fps)) {
|
||||||
_vps.clear();
|
_vps.clear();
|
||||||
|
@ -150,6 +150,7 @@ public:
|
|||||||
int getVideoHeight() const override;
|
int getVideoHeight() const override;
|
||||||
float getVideoFps() const override;
|
float getVideoFps() const override;
|
||||||
bool inputFrame(const Frame::Ptr &frame) override;
|
bool inputFrame(const Frame::Ptr &frame) override;
|
||||||
|
bool update() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void onReady();
|
void onReady();
|
||||||
|
@ -39,6 +39,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual Track::Ptr clone() = 0;
|
virtual Track::Ptr clone() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新track信息,比如触发sps/pps解析
|
||||||
|
*/
|
||||||
|
virtual bool update() { return false; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成sdp
|
* 生成sdp
|
||||||
* @return sdp对象
|
* @return sdp对象
|
||||||
|
@ -70,6 +70,7 @@ void PlayerProxy::setTranslationInfo()
|
|||||||
_transtalion_info.stream_info.clear();
|
_transtalion_info.stream_info.clear();
|
||||||
auto tracks = _muxer->getTracks();
|
auto tracks = _muxer->getTracks();
|
||||||
for (auto &track : tracks) {
|
for (auto &track : tracks) {
|
||||||
|
track->update();
|
||||||
_transtalion_info.stream_info.emplace_back();
|
_transtalion_info.stream_info.emplace_back();
|
||||||
auto &back = _transtalion_info.stream_info.back();
|
auto &back = _transtalion_info.stream_info.back();
|
||||||
back.bitrate = track->getBitRate();
|
back.bitrate = track->getBitRate();
|
||||||
|
@ -198,6 +198,7 @@ bool MP4MuxerInterface::addTrack(const Track::Ptr &track) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
track->update();
|
||||||
switch (track->getCodecId()) {
|
switch (track->getCodecId()) {
|
||||||
case CodecG711A:
|
case CodecG711A:
|
||||||
case CodecG711U:
|
case CodecG711U:
|
||||||
|
@ -57,6 +57,7 @@ AudioMeta::AudioMeta(const AudioTrack::Ptr &audio) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t getAudioRtmpFlags(const Track::Ptr &track) {
|
uint8_t getAudioRtmpFlags(const Track::Ptr &track) {
|
||||||
|
track->update();
|
||||||
switch (track->getTrackType()) {
|
switch (track->getTrackType()) {
|
||||||
case TrackAudio: {
|
case TrackAudio: {
|
||||||
auto audioTrack = std::dynamic_pointer_cast<AudioTrack>(track);
|
auto audioTrack = std::dynamic_pointer_cast<AudioTrack>(track);
|
||||||
@ -115,6 +116,7 @@ uint8_t getAudioRtmpFlags(const Track::Ptr &track) {
|
|||||||
|
|
||||||
void Metadata::addTrack(AMFValue &metadata, const Track::Ptr &track) {
|
void Metadata::addTrack(AMFValue &metadata, const Track::Ptr &track) {
|
||||||
Metadata::Ptr new_metadata;
|
Metadata::Ptr new_metadata;
|
||||||
|
track->update();
|
||||||
switch (track->getTrackType()) {
|
switch (track->getTrackType()) {
|
||||||
case TrackVideo: {
|
case TrackVideo: {
|
||||||
new_metadata = std::make_shared<VideoMeta>(std::dynamic_pointer_cast<VideoTrack>(track));
|
new_metadata = std::make_shared<VideoMeta>(std::dynamic_pointer_cast<VideoTrack>(track));
|
||||||
|
Loading…
Reference in New Issue
Block a user