NekoX/TMessagesProj/jni/voip/tgcalls/group/AudioStreamingPartPersisten...

123 lines
3.5 KiB
C++

#include "AudioStreamingPartPersistentDecoder.h"
#include "rtc_base/logging.h"
#include "rtc_base/third_party/base64/base64.h"
namespace tgcalls {
WrappedCodecParameters::WrappedCodecParameters(AVCodecParameters const *codecParameters) {
_value = avcodec_parameters_alloc();
avcodec_parameters_copy(_value, codecParameters);
}
WrappedCodecParameters::~WrappedCodecParameters() {
avcodec_parameters_free(&_value);
}
bool WrappedCodecParameters::isEqual(AVCodecParameters const *other) {
if (_value->codec_id != other->codec_id) {
return false;
}
if (_value->format != other->format) {
return false;
}
if (_value->channels != other->channels) {
return false;
}
return true;
}
class AudioStreamingPartPersistentDecoderState {
public:
AudioStreamingPartPersistentDecoderState(AVCodecParameters const *codecParameters, AVRational timeBase) :
_codecParameters(codecParameters),
_timeBase(timeBase) {
const AVCodec *codec = avcodec_find_decoder(codecParameters->codec_id);
if (codec) {
_codecContext = avcodec_alloc_context3(codec);
int ret = avcodec_parameters_to_context(_codecContext, codecParameters);
if (ret < 0) {
avcodec_free_context(&_codecContext);
_codecContext = nullptr;
} else {
_codecContext->pkt_timebase = timeBase;
_channelCount = _codecContext->channels;
ret = avcodec_open2(_codecContext, codec, nullptr);
if (ret < 0) {
avcodec_free_context(&_codecContext);
_codecContext = nullptr;
}
}
}
}
~AudioStreamingPartPersistentDecoderState() {
if (_codecContext) {
avcodec_free_context(&_codecContext);
}
}
int decode(AVPacket &packet, AVFrame *frame) {
int ret = avcodec_send_packet(_codecContext, &packet);
if (ret < 0) {
return ret;
}
int bytesPerSample = av_get_bytes_per_sample(_codecContext->sample_fmt);
if (bytesPerSample != 2 && bytesPerSample != 4) {
return -1;
}
ret = avcodec_receive_frame(_codecContext, frame);
return ret;
}
public:
WrappedCodecParameters _codecParameters;
AVRational _timeBase;
AVCodecContext *_codecContext = nullptr;
int _channelCount = 0;
};
AudioStreamingPartPersistentDecoder::AudioStreamingPartPersistentDecoder() {
}
AudioStreamingPartPersistentDecoder::~AudioStreamingPartPersistentDecoder() {
}
void AudioStreamingPartPersistentDecoder::maybeReset(AVCodecParameters const *codecParameters, AVRational timeBase) {
if (_state) {
bool isUpdated = false;
if (!_state->_codecParameters.isEqual(codecParameters)) {
isUpdated = true;
}
if (_state->_timeBase.num != timeBase.num || _state->_timeBase.den != timeBase.den) {
isUpdated = true;
}
if (!isUpdated) {
return;
}
}
if (_state) {
delete _state;
_state = nullptr;
}
_state = new AudioStreamingPartPersistentDecoderState(codecParameters, timeBase);
}
int AudioStreamingPartPersistentDecoder::decode(AVCodecParameters const *codecParameters, AVRational timeBase, AVPacket &packet, AVFrame *frame) {
maybeReset(codecParameters, timeBase);
if (!_state) {
return -1;
}
return _state->decode(packet, frame);
}
}