/* ------------------------------------------------------------------ * Copyright (C) 2022 Matthias P. Braendli * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. * See the License for the specific language governing permissions * and limitations under the License. * ------------------------------------------------------------------- */ /*! \file VLCInput.h * * This input uses libvlc to get audio data. It is extremely useful, and allows * the encoder to use all inputs VLC supports. */ #pragma once #include "config.h" #if HAVE_VLC #include #include #include #include #include #include #include #include #include #include "SampleQueue.h" #include "common.h" #include "InputInterface.h" #include "utils.h" /*! Common functionality for the direct libvlc input and the * threaded libvlc input */ class VLCInput : public InputInterface { public: VLCInput(const std::string& uri, int rate, unsigned channels, unsigned verbosity, std::string& cache, std::vector& additional_opts, SampleQueue& queue) : m_uri(uri), m_verbosity(verbosity), m_channels(channels), m_rate(rate), m_cache(cache), m_additional_opts(additional_opts), m_vlc(nullptr), m_mp(nullptr), m_fault(false), m_running(false), m_samplequeue(queue) {} VLCInput(const VLCInput& other) = delete; VLCInput& operator=(const VLCInput& other) = delete; virtual ~VLCInput(); /*! Initialise VLC and start playing, and start * the libVLC thread that fills m_samplequeue */ virtual void prepare() override; virtual bool read_source(size_t num_bytes) override; /*! Write the last received ICY-Text to the * file. */ ICY_TEXT_t get_icy_text() const; //! Callbacks for VLC /*! Notification of VLC exit */ void exit_cb(void); /*! Prepare a buffer for VLC */ void preRender_cb( uint8_t** pp_pcm_buffer, size_t size); /*! Notification from VLC that the buffer is now filled. * VLC also tells us how many channels and how many * samples */ void postRender_cb(unsigned int channels, size_t size); int getRate() { return m_rate; } virtual bool fault_detected(void) const override { return m_fault; }; private: /*! Stop the player and release resources */ void cleanup(void); /*! Fill exactly length bytes into buf. Blocking. * * \return number of bytes written into buf, or * -1 in case of error */ ssize_t m_read(uint8_t* buf, size_t length); /*! Buffer used in the callback functions for VLC */ std::vector m_current_buf; std::mutex m_queue_mutex; /*! Buffer containing all available samples from VLC */ std::deque m_queue; std::string m_uri; unsigned m_verbosity; unsigned m_channels; int m_rate; //! Whether to enable network caching in VLC or not std::string m_cache; //! Given as-is to libvlc, useful for additional arguments std::vector m_additional_opts; /*! VLC can give us the ICY-Text from an Icecast stream, * which we optionally write into a text file for ODR-PadEnc */ mutable std::mutex m_nowplaying_mutex; ICY_TEXT_t m_nowplaying; // VLC pointers libvlc_instance_t *m_vlc; libvlc_media_player_t *m_mp; // For the thread /* The thread running process takes samples from m_queue and writes * them into m_samplequeue. This decouples m_queue from m_samplequeue * which is directly used by odr-audioenc.cpp */ void process(); std::atomic m_fault; std::atomic m_running; std::thread m_thread; SampleQueue& m_samplequeue; }; #endif // HAVE_VLC