AudioSamples AudioDecoderContext::decode(const Packet &inPacket, size_t offset, OptionalErrorCode ec) { clear_if(ec); AudioSamples outSamples; int gotFrame = 0; auto st = decodeCommon(outSamples, inPacket, offset, gotFrame, avcodec_decode_audio_legacy); if (get<1>(st)) { throws_if(ec, get<0>(st), *get<1>(st)); return AudioSamples(); } if (!gotFrame) { outSamples.setComplete(false); } // Fix channels layout if (outSamples.channelsCount() && !outSamples.channelsLayout()) av_frame_set_channel_layout(outSamples.raw(), av_get_default_channel_layout(outSamples.channelsCount())); return outSamples; }
bool AudioResampler::pop(AudioSamples &dst, bool getall, error_code &ec) { clear_if(ec); if (!m_raw) { fflog(AV_LOG_ERROR, "SwrContext does not inited\n"); throws_if(ec, Errors::ResamplerNotInited); return false; } if (dst.sampleRate() != dstSampleRate() || dst.sampleFormat() != dstSampleFormat() || dst.channelsCount() != dstChannels() || dst.channelsLayout() != dstChannelLayout()) { throws_if(ec, Errors::ResamplerOutputChanges); return false; } auto result = swr_get_delay(m_raw, m_dstRate); //clog << " delay [pop]: " << result << endl; // Need more data if (result < dst.samplesCount() && getall == false) { return false; } auto sts = swr_convert_frame(m_raw, dst.raw(), nullptr); if (sts < 0) { throws_if(ec, sts, ffmpeg_category()); return false; } dst.setTimeBase(Rational(1, m_dstRate)); dst.setStreamIndex(m_streamIndex); dst.setComplete(true); // Ugly PTS handling. More clean one can be done by user code if (!m_nextPts.isValid()) { m_nextPts = Timestamp(0, dst.timeBase()); } dst.setPts(m_nextPts); m_nextPts = dst.pts() + Timestamp{dst.samplesCount(), dst.timeBase()}; //result = swr_get_delay(m_raw, m_dstRate); //clog << " delay [pop]: " << result << endl; // When no data, samples count sets to zero return dst.samplesCount() ? true : false; }
void AudioResampler::push(const AudioSamples &src, error_code &ec) { if (!m_raw) { fflog(AV_LOG_ERROR, "SwrContext does not inited\n"); throws_if(ec, Errors::ResamplerNotInited); return; } // Null samples is allowed if (src) { if (src.sampleRate() != srcSampleRate() || src.sampleFormat() != srcSampleFormat() || src.channelsCount() != srcChannels() || src.channelsLayout() != srcChannelLayout()) { throws_if(ec, Errors::ResamplerInputChanges); return; } } auto sts = swr_convert_frame(m_raw, nullptr, src.raw()); if (sts < 0) { fflog(AV_LOG_DEBUG, "Src is null: %d, payload: %p\n", src.isNull(), src.data()); throws_if(ec, sts, ffmpeg_category()); return; } // TODO: need protection if we still work in scheme: One Resampler Per Channel m_streamIndex = src.streamIndex(); // Need to restore PTS in output frames if (m_prevPts > src.pts()) // Reset case m_nextPts = Timestamp(); m_prevPts = src.pts(); //auto result = swr_get_delay(m_raw, m_dstRate); //clog << " delay [push]: " << result << endl; }