[Libav-user] Distorted audio when muxing packets
Jonathan Noble
jonnobleuk at gmail.com
Sat Jan 25 10:36:35 EET 2020
Hi,
I've been trying to write compressed audio frames to a container with
av_interleaved_frame and I am seeing strange results. The source audio is a
single tone of constant amplitude, mono, which I can see I am decompressing
fine when I plot all the values to a graph.
Depending on the format/codec combo I see:
- a monotone signal randomly interspersed with noise or silence.
- a short playback of a distorted tone
- correct length playback of a monotone with varying amplitude
For the section of code where I compress and write a frame to a container,
it works perfectly for video. The ffmpeg library does not produce any
messages during writing.
I have searched on what could be the cause of this and the topic of
correctly setting packet->pts/dts comes up regularly. However, I believe I
am doing the correct thing.
Could anyone give me any pointers?
Kind regards
Jon Noble
Here is the relevant snippet of code from
https://github.com/jonno85uk/mediahandling/blob/Issue4_encoding/ffmpeg/ffmpegstream.cpp
bool FFMpegStream::writeFrame(MediaFramePtr sample)
{
bool okay = true;
std::call_once(setup_encoder_, [&] { okay = setupEncoder(); });
if (!okay) {
logMessage(LogType::CRITICAL, "Failed to setup encoder");
return false;
}
if ( (sink_codec_ctx_ == nullptr) || (sink_frame_ == nullptr) ) {
logMessage(LogType::CRITICAL, "Stream has not been configured correctly
for writing");
return false;
}
// send frame to encoder
if (sample) {
const auto data = sample->data();
assert(data.data_);
for (auto ix = 0; ix < AV_NUM_DATA_POINTERS; ++ix) {
sink_frame_->data[ix] = data.data_[ix];
}
if (data.sample_count_ >= 0) {
sink_frame_->pts = audio_samples_;
audio_samples_ += data.sample_count_;
} else {
sink_frame_->pts++;
}
auto ret = avcodec_send_frame(sink_codec_ctx_.get(), sink_frame_.get());
if (ret < 0) {
av_strerror(ret, err.data(), ERR_LEN);
const auto msg = fmt::format("Failed to send frame to encoder: {}",
err.data());
logMessage(LogType::CRITICAL, msg);
return false;
}
} else {
const auto ret = avcodec_send_frame(sink_codec_ctx_.get(), nullptr);
if (ret < 0) {
av_strerror(ret, err.data(), ERR_LEN);
const auto msg = fmt::format("Failed to send frame to encoder: {}",
err.data());
logMessage(LogType::CRITICAL, msg);
return false;
}
}
// Retrieve packet from encoder
int ret = 0;
while (ret >= 0) {
ret = avcodec_receive_packet(sink_codec_ctx_.get(), pkt_);
if (ret == AVERROR(EAGAIN)) {
return true;
} else if (ret < 0) {
if (ret != AVERROR_EOF) {
av_strerror(ret, err.data(), ERR_LEN);
const auto msg = fmt::format("Failed to receive packet from
encoder, msg={}", err.data());
logMessage(LogType::CRITICAL, msg);
return false;
}
return true;
}
pkt_->stream_index = stream_->index;
av_packet_rescale_ts(pkt_, sink_codec_ctx_->time_base,
stream_->time_base);
// Send packet to container writer
ret = av_interleaved_write_frame(&sink_->formatContext(), pkt_);
av_packet_unref(pkt_);
if (ret < 0 ){
av_strerror(ret, err.data(), ERR_LEN);
const auto msg = fmt::format("Failed to write frame to container,
msg={}", err.data());
logMessage(LogType::CRITICAL, msg);
return false;
}
av_packet_unref(pkt_);
}
return true;
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://ffmpeg.org/pipermail/libav-user/attachments/20200125/cdbae850/attachment.html>
More information about the Libav-user
mailing list