summaryrefslogtreecommitdiffstats
path: root/src/VLCInput.cpp
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2015-03-11 21:15:38 +0100
committerMatthias P. Braendli <matthias.braendli@mpb.li>2015-03-11 21:15:38 +0100
commit58378f49c75b7c6e184c499082328761b468da68 (patch)
treedf16e70225672ea19fb1df01f2af40aaae67dfaa /src/VLCInput.cpp
parent599d0fc5892725e471772e567555bf075ad2ae86 (diff)
downloadODR-AudioEnc-58378f49c75b7c6e184c499082328761b468da68.tar.gz
ODR-AudioEnc-58378f49c75b7c6e184c499082328761b468da68.tar.bz2
ODR-AudioEnc-58378f49c75b7c6e184c499082328761b468da68.zip
Add libvlc input
Be careful about sample rate conversion, VLC only wants to use the ugly resampler on some machines.
Diffstat (limited to 'src/VLCInput.cpp')
-rw-r--r--src/VLCInput.cpp164
1 files changed, 164 insertions, 0 deletions
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 <cstdio>
+#include <string>
+
+#include "VLCInput.h"
+
+#include "config.h"
+
+#if HAVE_VLC
+
+#include <sys/time.h>
+#include <boost/date_time/posix_time/posix_time.hpp>
+
+
+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
+