<div dir="ltr"><div dir="ltr"><div>Hi,</div><div><br></div><div>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. <br></div><div><br></div><div>Depending on the format/codec combo I see:</div><div> - a monotone signal randomly interspersed with noise or silence.</div><div> - a short playback of a distorted tone</div><div> - correct length playback of a monotone with varying amplitude</div><div><br></div><div>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.</div><div><br></div><div>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.</div><div><br></div><div>Could anyone give me any pointers? <br></div><div><br></div><div>Kind regards</div><div><br></div><div>Jon Noble<br></div><div><br></div><div>Here is the relevant snippet of code from <a href="https://github.com/jonno85uk/mediahandling/blob/Issue4_encoding/ffmpeg/ffmpegstream.cpp" target="_blank">https://github.com/jonno85uk/mediahandling/blob/Issue4_encoding/ffmpeg/ffmpegstream.cpp</a></div><div><br></div><div>bool FFMpegStream::writeFrame(MediaFramePtr sample)<br>{<br> bool okay = true;<br> std::call_once(setup_encoder_, [&] { okay = setupEncoder(); });<br> if (!okay) {<br> logMessage(LogType::CRITICAL, "Failed to setup encoder");<br> return false;<br> }<br> if ( (sink_codec_ctx_ == nullptr) || (sink_frame_ == nullptr) ) {<br> logMessage(LogType::CRITICAL, "Stream has not been configured correctly for writing");<br> return false;<br> }<br><br> // send frame to encoder<br> if (sample) {<br> const auto data = sample->data();<br> assert(data.data_);<br> for (auto ix = 0; ix < AV_NUM_DATA_POINTERS; ++ix) {<br> sink_frame_->data[ix] = data.data_[ix];<br> }<br> if (data.sample_count_ >= 0) {<br> sink_frame_->pts = audio_samples_;<br> audio_samples_ += data.sample_count_;<br> } else {<br> sink_frame_->pts++;<br> }<br> auto ret = avcodec_send_frame(sink_codec_ctx_.get(), sink_frame_.get());<br> if (ret < 0) {<br> av_strerror(ret, err.data(), ERR_LEN);<br> const auto msg = fmt::format("Failed to send frame to encoder: {}", err.data());<br> logMessage(LogType::CRITICAL, msg);<br> return false;<br> }<br> } else {<br> const auto ret = avcodec_send_frame(sink_codec_ctx_.get(), nullptr);<br> if (ret < 0) {<br> av_strerror(ret, err.data(), ERR_LEN);<br> const auto msg = fmt::format("Failed to send frame to encoder: {}", err.data());<br> logMessage(LogType::CRITICAL, msg);<br> return false;<br> }<br> }<br> // Retrieve packet from encoder<br> int ret = 0;<br> while (ret >= 0) {<br> ret = avcodec_receive_packet(sink_codec_ctx_.get(), pkt_);<br> if (ret == AVERROR(EAGAIN)) {<br> return true;<br> } else if (ret < 0) {<br> if (ret != AVERROR_EOF) {<br> av_strerror(ret, err.data(), ERR_LEN);<br> const auto msg = fmt::format("Failed to receive packet from encoder, msg={}", err.data());<br> logMessage(LogType::CRITICAL, msg);<br> return false;<br> }<br> return true;<br> }<br><br> pkt_->stream_index = stream_->index;<br> av_packet_rescale_ts(pkt_, sink_codec_ctx_->time_base, stream_->time_base);<br> // Send packet to container writer<br> ret = av_interleaved_write_frame(&sink_->formatContext(), pkt_);<br> av_packet_unref(pkt_);<br> if (ret < 0 ){<br> av_strerror(ret, err.data(), ERR_LEN);<br> const auto msg = fmt::format("Failed to write frame to container, msg={}", err.data());<br> logMessage(LogType::CRITICAL, msg);<br> return false;<br> }<br> av_packet_unref(pkt_);<br> }<br> return true;<br>}</div></div></div>