2#include <ossia/detail/config.hpp> 
    4#include <ossia/audio/audio_parameter.hpp> 
    5#include <ossia/dataflow/audio_stretch_mode.hpp> 
    6#include <ossia/dataflow/graph_node.hpp> 
    7#include <ossia/dataflow/nodes/media.hpp> 
    8#include <ossia/dataflow/nodes/sound.hpp> 
    9#include <ossia/dataflow/port.hpp> 
   10#include <ossia/detail/libav.hpp> 
   11#include <ossia/detail/pod_vector.hpp> 
   16#include <libavcodec/avcodec.h> 
   17#include <libavformat/avformat.h> 
   18#include <libavutil/frame.h> 
   19#include <libavutil/mem.h> 
   20#include <libswresample/swresample.h> 
   25class sound_libav final : 
public ossia::sound_node
 
   32      : packet{av_packet_alloc()}
 
   33      , frame{av_frame_alloc()}
 
   35    m_outlets.push_back(&audio_out);
 
   42    av_frame_free(&frame);
 
   43    av_packet_free(&packet);
 
   46  std::string label() const noexcept
 override { 
return "sound_libav"; }
 
   48  void set_start(std::size_t v) { start = v; }
 
   50  void set_upmix(std::size_t v) { upmix = v; }
 
   52  void set_sound(libav_handle hdl)
 
   56    m_handle = std::move(hdl);
 
   59    m_channel_q = boost::circular_buffer<float>(8192 * m_handle.channels());
 
   62  void transport(time_value flicks)
 override 
   66        m_handle.format, m_handle.codec, m_handle.stream, flicks.impl, AVSEEK_FLAG_ANY);
 
   69  void fetch_from_libav(
int samples_to_write)
 
   71    const std::size_t channels = this->channels();
 
   75    auto floats_to_write = channels * samples_to_write;
 
   76    while(m_channel_q.size() < floats_to_write)
 
   79      if(m_channel_q.capacity() < 4 * floats_to_write)
 
   81        m_channel_q.set_capacity(4 * floats_to_write);
 
   85      auto fmt_ctx = m_handle.format;
 
   86      auto codec_ctx = m_handle.codec;
 
   87      auto stream = m_handle.stream;
 
   91          av_packet_unref(packet);
 
   92          ret = av_read_frame(fmt_ctx, packet);
 
   94          while(ret >= 0 && ret != AVERROR(EOF) && packet->stream_index != stream->index)
 
   96            av_packet_unref(packet);
 
   97            ret = av_read_frame(fmt_ctx, packet);
 
   99          if(ret == AVERROR(EOF))
 
  109        ret = avcodec_send_packet(codec_ctx, packet);
 
  112          ret = avcodec_receive_frame(codec_ctx, frame);
 
  115            const int samples = frame->nb_samples;
 
  116            m_tmp.resize(samples * channels, boost::container::default_init);
 
  117            float* out_ptr = m_tmp.data();
 
  118            const int read_samples = swr_convert(
 
  119                m_handle.resample, (uint8_t**)&out_ptr, samples,
 
  120                (
const uint8_t**)frame->extended_data, samples);
 
  123                m_channel_q.end(), out_ptr, out_ptr + read_samples * channels);
 
  130  template <
typename T>
 
  132  fetch_audio(int64_t start, int64_t samples_to_write, T** audio_array_base) 
noexcept 
  134    const std::size_t channels = this->channels();
 
  138    fetch_from_libav(samples_to_write);
 
  141    for(
int k = 0; k < samples_to_write; k++)
 
  143      for(std::size_t chan = 0; chan < channels; chan++)
 
  145        if(m_channel_q.size() > 0)
 
  147          audio_array_base[chan][k] = m_channel_q.front();
 
  148          m_channel_q.pop_front();
 
  152          audio_array_base[chan][k] = 0.;
 
  158  void run(
const ossia::token_request& t, ossia::exec_state_facade e) 
noexcept override 
  167    const auto channels = m_handle.channels();
 
  168    const auto len = m_handle.totalPCMFrameCount();
 
  170    ossia::audio_port& ap = *audio_out;
 
  171    ap.set_channels(std::max((std::size_t)upmix, (std::size_t)channels));
 
  173    const auto [samples_to_read, samples_to_write]
 
  174        = snd::sample_info(e.bufferSize(), e.modelToSamples(), t);
 
  175    if(samples_to_write <= 0)
 
  178    assert(samples_to_write > 0);
 
  180    const auto samples_offset = t.physical_start(e.modelToSamples());
 
  183      if(t.prev_date < m_prev_date)
 
  188          if(t.prev_date != 0_tv)
 
  190            transport(t.prev_date);
 
  200          transport(t.prev_date);
 
  204      for(
int chan = 0; chan < channels; chan++)
 
  206        ap.channel(chan).resize(e.bufferSize());
 
  209      double stretch_ratio = update_stretch(t, e);
 
  213          *
this, t, e, stretch_ratio, channels, len, samples_to_read, samples_to_write,
 
  216      for(
int chan = 0; chan < channels; chan++)
 
  220            t.start_discontinuous, t.end_discontinuous, ap.channel(chan), samples_offset,
 
  224      ossia::snd::perform_upmix(this->upmix, channels, ap);
 
  225      ossia::snd::perform_start_offset(this->start, ap);
 
  227      m_prev_date = t.date;
 
  235  [[nodiscard]] std::size_t channels()
 const 
  237    return m_handle ? m_handle.channels() : 0;
 
  239  [[nodiscard]] std::size_t duration()
 const 
  241    return m_handle ? m_handle.totalPCMFrameCount() : 0;
 
  245  libav_handle m_handle{};
 
  247  ossia::audio_outlet audio_out;
 
  252  ossia::pod_vector<float> m_tmp{};
 
  253  boost::circular_buffer<float> m_channel_q;
 
The time_value class.
Definition ossia/editor/scenario/time_value.hpp:30