From 58378f49c75b7c6e184c499082328761b468da68 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Wed, 11 Mar 2015 21:15:38 +0100 Subject: Add libvlc input Be careful about sample rate conversion, VLC only wants to use the ugly resampler on some machines. --- src/VLCInput.cpp | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 src/VLCInput.cpp (limited to 'src/VLCInput.cpp') diff --git a/src/VLCInput.cpp b/src/VLCInput.cpp new file mode 100644 index 0000000..555b1e1 --- /dev/null +++ b/src/VLCInput.cpp @@ -0,0 +1,164 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 2015 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. + * ------------------------------------------------------------------- + */ + +#include +#include + +#include "VLCInput.h" + +#include "config.h" + +#if HAVE_VLC + +#include +#include + + +using namespace std; + +// VLC Audio prerender callback +void prepareRender( + void* p_audio_data, + uint8_t** pp_pcm_buffer, + size_t size) +{ + VLCInput* in = (VLCInput*)p_audio_data; + + in->preRender(pp_pcm_buffer, size); +} + + +// Audio postrender callback +void handleStream( + void* p_audio_data, + uint8_t* p_pcm_buffer, + unsigned int channels, + unsigned int rate, + unsigned int nb_samples, + unsigned int bits_per_sample, + size_t size, + int64_t pts) +{ + VLCInput* in = (VLCInput*)p_audio_data; + + assert(channels == 2); + assert(rate == in->getRate()); + assert(bits_per_sample == 8*BYTES_PER_SAMPLE); + + in->postRender(p_pcm_buffer, size); +} + +int VLCInput::prepare() +{ + int err; + fprintf(stderr, "Initialising VLC...\n"); + + // VLC options + char smem_options[512]; + snprintf(smem_options, sizeof(smem_options), + "#transcode{acodec=s16l,samplerate=%d}:" + // We are using transcode because smem only support raw audio and + // video formats + "smem{" + "audio-postrender-callback=%lld," + "audio-prerender-callback=%lld," + "audio-data=%lld" + "}", + m_rate, + (long long int)(intptr_t)(void*)&handleStream, + (long long int)(intptr_t)(void*)&prepareRender, + (long long int)(intptr_t)this); + + char verb_options[512]; + snprintf(verb_options, sizeof(verb_options), + "--verbose=%d", m_verbosity); + + const char * const vlc_args[] = { + verb_options, + "--sout", smem_options // Stream to memory + }; + + // Launch VLC + m_vlc = libvlc_new(sizeof(vlc_args) / sizeof(vlc_args[0]), vlc_args); + + // Load the media + libvlc_media_t *m; + m = libvlc_media_new_location(m_vlc, m_uri.c_str()); + m_mp = libvlc_media_player_new_from_media(m); + libvlc_media_release(m); + + // Start playing + libvlc_media_player_play(m_mp); + + fprintf(stderr, "VLC launched.\n"); + return 0; +} + +void VLCInput::preRender(uint8_t** pp_pcm_buffer, size_t size) +{ + boost::mutex::scoped_lock lock(m_queue_mutex); + + m_current_buf.resize(size); + *pp_pcm_buffer = &m_current_buf[0]; +} + +void VLCInput::postRender(uint8_t* p_pcm_buffer, size_t size) +{ + boost::mutex::scoped_lock lock(m_queue_mutex); + + assert(m_current_buf.size() == size); + + size_t queue_size = m_queue.size(); + m_queue.resize(m_queue.size() + size); + std::copy(m_current_buf.begin(), m_current_buf.end(), + m_queue.begin() + queue_size); +} + +ssize_t VLCInput::m_read(uint8_t* buf, size_t length) +{ + ssize_t err = 0; + for (;;) { + boost::mutex::scoped_lock lock(m_queue_mutex); + + if (m_queue.size() >= length) { + for (size_t i = 0; i < length; i++) { + buf[i] = m_queue[i]; + } + m_queue.erase(m_queue.begin(), m_queue.begin() + length); + + return length; + } + + lock.unlock(); + boost::this_thread::sleep(boost::posix_time::milliseconds(1)); + } + return err; +} + +ssize_t VLCInput::read(uint8_t* buf, size_t length) +{ + int bytes_per_frame = m_channels * BYTES_PER_SAMPLE; + assert(length % bytes_per_frame == 0); + + ssize_t read = m_read(buf, length); + + return read; +} + +#endif // HAVE_VLC + -- cgit v1.2.3