[Libav-user] Distorted audio when muxing packets

Jonathan Noble jonnobleuk at gmail.com
Fri Jan 24 22:18:01 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/20200124/de510559/attachment.html>


More information about the Libav-user mailing list