diff options
Diffstat (limited to 'libtoolame-dab/vlc_input.c')
-rw-r--r-- | libtoolame-dab/vlc_input.c | 430 |
1 files changed, 0 insertions, 430 deletions
diff --git a/libtoolame-dab/vlc_input.c b/libtoolame-dab/vlc_input.c deleted file mode 100644 index 11e04c7..0000000 --- a/libtoolame-dab/vlc_input.c +++ /dev/null @@ -1,430 +0,0 @@ -#include "vlc_input.h" - -#if defined(VLC_INPUT) -#include <stdlib.h> -#include <errno.h> -#include <pthread.h> -#include <semaphore.h> -#include <assert.h> -#include <unistd.h> -#include <string.h> -#include <stdio.h> - -int check_vlc_uses_size_t(); -struct vlc_buffer* vlc_buffer_new(); -void vlc_buffer_free(struct vlc_buffer* node); - -libvlc_instance_t *m_vlc; -libvlc_media_player_t *m_mp; - -unsigned int vlc_rate; -unsigned int vlc_channels; - -struct vlc_buffer *head_buffer; - -// now playing information can get written to -// a file. This writing happens in a separate thread -#define NOWPLAYING_LEN 512 -char vlc_nowplaying[NOWPLAYING_LEN]; -int vlc_nowplaying_running; -pthread_t vlc_nowplaying_thread; -const char* vlc_nowplaying_filename; - -struct icywriter_task_data { - char text[NOWPLAYING_LEN]; - int success; - sem_t sem; -}; - -struct icywriter_task_data icy_task_data; - - -pthread_mutex_t buffer_lock = PTHREAD_MUTEX_INITIALIZER; - -struct vlc_buffer* vlc_buffer_new() -{ - struct vlc_buffer* node; - node = malloc(sizeof(struct vlc_buffer)); - memset(node, 0, sizeof(struct vlc_buffer)); - return node; -} - -void vlc_buffer_free(struct vlc_buffer* node) -{ - if (node->buf) { - free(node->buf); - } - - free(node); -} - -size_t vlc_buffer_totalsize(struct vlc_buffer* node) -{ - size_t totalsize = 0; - for (; node != NULL; node = node->next) { - totalsize += node->size; - } - - return totalsize; -} - -// VLC Audio prerender callback, we must allocate a buffer here -void prepareRender_size_t( - void* p_audio_data, - uint8_t** pp_pcm_buffer, - size_t size) -{ - *pp_pcm_buffer = malloc(size); -} - -void prepareRender( - void* p_audio_data, - uint8_t** pp_pcm_buffer, - unsigned int size) -{ - *pp_pcm_buffer = malloc(size); -} - - -// Audio postrender callback -void handleStream_size_t( - 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) -{ - assert(channels == vlc_channels); - assert(rate == vlc_rate); - assert(bits_per_sample == 16); - - // 16 is a bit arbitrary, if it's too small we might enter - // a deadlock if toolame asks for too much data - const size_t max_length = 16 * size; - - for (;;) { - pthread_mutex_lock(&buffer_lock); - - if (vlc_buffer_totalsize(head_buffer) < max_length) { - struct vlc_buffer* newbuf = vlc_buffer_new(); - - newbuf->buf = p_pcm_buffer; - newbuf->size = size; - - // Append the new buffer to the end of the linked list - struct vlc_buffer* tail = head_buffer; - while (tail->next) { - tail = tail->next; - } - tail->next = newbuf; - - pthread_mutex_unlock(&buffer_lock); - return; - } - - pthread_mutex_unlock(&buffer_lock); - usleep(100); - } -} - -// convert from unsigned int size to size_t size -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, - unsigned int size, - int64_t pts) -{ - handleStream_size_t( - p_audio_data, - p_pcm_buffer, - channels, - rate, - nb_samples, - bits_per_sample, - size, - pts); -} - -int vlc_in_prepare( - unsigned verbosity, - unsigned int rate, - const char* uri, - unsigned channels, - const char* icy_write_file - ) -{ - fprintf(stderr, "Initialising VLC...\n"); - - vlc_nowplaying_running = 0; - vlc_nowplaying_filename = icy_write_file; - - long long int handleStream_address; - long long int prepareRender_address; - - int vlc_version_check = check_vlc_uses_size_t(); - if (vlc_version_check == 0) { - fprintf(stderr, "You are using VLC with unsigned int size callbacks\n"); - - handleStream_address = (long long int)(intptr_t)(void*)&handleStream; - prepareRender_address = (long long int)(intptr_t)(void*)&prepareRender; - } - else if (vlc_version_check == 1) { - fprintf(stderr, "You are using VLC with size_t size callbacks\n"); - - handleStream_address = (long long int)(intptr_t)(void*)&handleStream_size_t; - prepareRender_address = (long long int)(intptr_t)(void*)&prepareRender_size_t; - } - else { - fprintf(stderr, "Error detecting VLC version!\n"); - fprintf(stderr, " you are using %s\n", libvlc_get_version()); - return -1; - } - - vlc_rate = rate; - vlc_channels = channels; - - // 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" - "}", - vlc_rate, - handleStream_address, - prepareRender_address); - - char verb_options[512]; - snprintf(verb_options, sizeof(verb_options), - "--verbose=%d", 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, uri); - m_mp = libvlc_media_player_new_from_media(m); - libvlc_media_release(m); - - // Allocate the list - head_buffer = vlc_buffer_new(); - - // Start playing - int ret = libvlc_media_player_play(m_mp); - - if (ret == 0) { - libvlc_media_t *media = libvlc_media_player_get_media(m_mp); - libvlc_state_t st; - - ret = -1; - - int timeout; - for (timeout = 0; timeout < 100; timeout++) { - st = libvlc_media_get_state(media); - usleep(10*1000); - if (st != libvlc_NothingSpecial) { - ret = 0; - break; - } - } - } - - return ret; -} - -ssize_t vlc_in_read(void *buf, size_t len) -{ - if (len == 0) { - return 0; - } - - assert(buf); - - size_t requested = len; - for (;;) { - pthread_mutex_lock(&buffer_lock); - - if (vlc_buffer_totalsize(head_buffer) >= len) { - while (len >= head_buffer->size) { - if (head_buffer->buf && head_buffer->size) { - // Get all the data from this list element - memcpy(buf, head_buffer->buf, head_buffer->size); - - buf += head_buffer->size; - len -= head_buffer->size; - } - - if (head_buffer->next) { - struct vlc_buffer *next_head = head_buffer->next; - vlc_buffer_free(head_buffer); - head_buffer = next_head; - } - else { - vlc_buffer_free(head_buffer); - head_buffer = vlc_buffer_new(); - break; - } - } - - if (len > 0) { - assert(len < head_buffer->size); - assert(head_buffer->buf); - - memcpy(buf, head_buffer->buf, len); - - // split the current head into two parts - size_t remaining = head_buffer->size - len; - uint8_t *newbuf = malloc(remaining); - - memcpy(newbuf, head_buffer->buf + len, remaining); - free(head_buffer->buf); - head_buffer->buf = newbuf; - head_buffer->size = remaining; - } - - pthread_mutex_unlock(&buffer_lock); - return requested; - } - - pthread_mutex_unlock(&buffer_lock); - usleep(100); - - libvlc_media_t *media = libvlc_media_player_get_media(m_mp); - libvlc_state_t st = libvlc_media_get_state(media); - if (!(st == libvlc_Opening || - st == libvlc_Buffering || - st == libvlc_Playing) ) { - return -1; - } - - char* nowplaying_sz = libvlc_media_get_meta(media, libvlc_meta_NowPlaying); - if (nowplaying_sz) { - snprintf(vlc_nowplaying, NOWPLAYING_LEN, "%s", nowplaying_sz); - free(nowplaying_sz); - } - } - - abort(); -} - -// This task is run in a separate thread -void* vlc_in_write_icy_task(void* arg) -{ - struct icywriter_task_data* data = arg; - - FILE* fd = fopen(vlc_nowplaying_filename, "wb"); - if (fd) { - int ret = fputs(data->text, fd); - fclose(fd); - - if (ret >= 0) { - data->success = 1; - } - } - else { - data->success = 0; - } - - sem_post(&data->sem); - return NULL; -} - -void vlc_in_write_icy(void) -{ - if (vlc_nowplaying_filename == NULL) { - return; - } - else if (vlc_nowplaying_running == 0) { - memcpy(icy_task_data.text, vlc_nowplaying, NOWPLAYING_LEN); - icy_task_data.success = 0; - - int ret = sem_init(&icy_task_data.sem, 0, 0); - if (ret == 0) { - ret = pthread_create(&vlc_nowplaying_thread, NULL, vlc_in_write_icy_task, &icy_task_data); - - if (ret == 0) { - vlc_nowplaying_running = 1; - } - else { - fprintf(stderr, "ICY Text writer: thread start failed: %s\n", strerror(ret)); - } - } - else { - fprintf(stderr, "ICY Text writer: semaphore init failed: %s\n", strerror(errno)); - } - - } - else { - int ret = sem_trywait(&icy_task_data.sem); - if (ret == -1 && errno == EAGAIN) { - return; - } - else if (ret == 0) { - ret = pthread_join(vlc_nowplaying_thread, NULL); - if (ret != 0) { - fprintf(stderr, "ICY Text writer: pthread_join error: %s\n", strerror(ret)); - } - - vlc_nowplaying_running = 0; - } - else { - fprintf(stderr, "ICY Text writer: semaphore trywait failed: %s\n", strerror(errno)); - } - } -} - - -/* VLC up to version 2.1.0 used a different callback function signature. - * VLC 2.2.0 uses size_t - * - * \return 1 if the callback with size_t size should be used. - * 0 if the callback with unsigned int size should be used. - * -1 if there was an error. - */ -int check_vlc_uses_size_t() -{ - int retval = -1; - - char libvlc_version[256]; - strncpy(libvlc_version, libvlc_get_version(), 255); - - char *space_position = strstr(libvlc_version, " "); - - if (space_position) { - *space_position = '\0'; - } - - char *saveptr; - char *major_ver_sz = strtok_r(libvlc_version, ".", &saveptr); - if (major_ver_sz) { - int major_ver = atoi(major_ver_sz); - - char *minor_ver_sz = strtok_r(NULL, ".", &saveptr); - if (minor_ver_sz) { - int minor_ver = atoi(minor_ver_sz); - - retval = (major_ver >= 2 && minor_ver >= 2) ? 1 : 0; - } - } - - return retval; -} - -#endif // defined(VLC_INPUT) - |