[Libav-user] Distorted audio when muxing packets

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[Libav-user] Distorted audio when muxing packets

Jonathan Noble
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


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;
}

_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".