#include "FfmpegAudioStream.h" #include "FfmpegUtil.h" using namespace std; namespace { bool operator==(const AudioFormat& x, const AVCodecContext& y) { return x.samples == y.sample_rate && x.channels == y.channels && x.format == y.sample_fmt; } AudioFormat& toAudioFormat( AudioFormat& audioFormat, const AVCodecContext& codecCtx) { audioFormat.samples = codecCtx.sample_rate; audioFormat.channels = codecCtx.channels; audioFormat.format = codecCtx.sample_fmt; return audioFormat; } } // namespace FfmpegAudioStream::FfmpegAudioStream( AVFormatContext* inputCtx, int index, enum AVMediaType avMediaType, MediaFormat mediaFormat, double seekFrameMargin) : FfmpegStream(inputCtx, index, avMediaType, seekFrameMargin), mediaFormat_(mediaFormat) {} FfmpegAudioStream::~FfmpegAudioStream() {} void FfmpegAudioStream::checkStreamDecodeParams() { auto timeBase = getTimeBase(); if (timeBase.first > 0) { CHECK_EQ(timeBase.first, inputCtx_->streams[index_]->time_base.num); CHECK_EQ(timeBase.second, inputCtx_->streams[index_]->time_base.den); } } void FfmpegAudioStream::updateStreamDecodeParams() { auto timeBase = getTimeBase(); if (timeBase.first == 0) { mediaFormat_.format.audio.timeBaseNum = inputCtx_->streams[index_]->time_base.num; mediaFormat_.format.audio.timeBaseDen = inputCtx_->streams[index_]->time_base.den; } } int FfmpegAudioStream::initFormat() { AudioFormat& format = mediaFormat_.format.audio; if (format.samples == 0) { format.samples = codecCtx_->sample_rate; } if (format.channels == 0) { format.channels = codecCtx_->channels; } if (format.format == AV_SAMPLE_FMT_NONE) { format.format = codecCtx_->sample_fmt; VLOG(2) << "set stream format sample_fmt: " << format.format; } checkStreamDecodeParams(); updateStreamDecodeParams(); if (format.samples > 0 && format.channels > 0 && format.format != AV_SAMPLE_FMT_NONE) { return 0; } else { return -1; } } unique_ptr FfmpegAudioStream::sampleFrameData() { AudioFormat& audioFormat = mediaFormat_.format.audio; if (!sampler_ || !(sampler_->getInFormat() == *codecCtx_)) { AudioFormat newInFormat; newInFormat = toAudioFormat(newInFormat, *codecCtx_); sampler_ = make_unique(newInFormat, audioFormat); VLOG(1) << "Set sampler input audio format" << ", samples: " << newInFormat.samples << ", channels: " << newInFormat.channels << ", format: " << newInFormat.format << " : output audio sampler format" << ", samples: " << audioFormat.samples << ", channels: " << audioFormat.channels << ", format: " << audioFormat.format; int ret = sampler_->init(); if (ret < 0) { VLOG(1) << "Fail to initialize audio sampler"; return nullptr; } } return sampler_->sample(frame_); }