From 4114651e593a3fbafd1cd6a34c601af6c30ab090 Mon Sep 17 00:00:00 2001 From: xufuji456 <839789740@qq.com> Date: Sun, 22 Aug 2021 00:02:49 +0800 Subject: [PATCH] adjust buffer queue --- app/CMakeLists.txt | 2 +- app/src/main/cpp/visualizer/block_queue.c | 70 ++++++ app/src/main/cpp/visualizer/block_queue.h | 40 ++++ app/src/main/cpp/visualizer/execute_fft.c | 42 +--- app/src/main/cpp/visualizer/execute_fft.h | 19 +- app/src/main/cpp/visualizer/queue.c | 154 ------------- app/src/main/cpp/visualizer/vlc_queue.h | 258 ---------------------- 7 files changed, 126 insertions(+), 459 deletions(-) create mode 100644 app/src/main/cpp/visualizer/block_queue.c create mode 100644 app/src/main/cpp/visualizer/block_queue.h delete mode 100644 app/src/main/cpp/visualizer/queue.c delete mode 100644 app/src/main/cpp/visualizer/vlc_queue.h diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index c7f5747..4edbec1 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -35,7 +35,7 @@ add_library( # Sets the name of the library. src/main/cpp/fast_start.c src/main/cpp/ffprobe_cmd.cpp src/main/cpp/visualizer/fft.c - src/main/cpp/visualizer/queue.c + src/main/cpp/visualizer/block_queue.c src/main/cpp/visualizer/execute_fft.c src/main/cpp/visualizer/window.c ) diff --git a/app/src/main/cpp/visualizer/block_queue.c b/app/src/main/cpp/visualizer/block_queue.c new file mode 100644 index 0000000..6edc3cc --- /dev/null +++ b/app/src/main/cpp/visualizer/block_queue.c @@ -0,0 +1,70 @@ +// +// Created by frank on 2021/08/08. +// +#include "block_queue.h" +#include +#include + + +vlc_queue_t *vlc_queue_init(int size) { + vlc_queue_t *queue = (vlc_queue_t *)(malloc(sizeof(vlc_queue_t))); + queue->size = size; + queue->next_to_read = 0; + queue->next_to_write = 0; + int i; + queue->packets = (void **)(malloc(sizeof(*queue->packets) * size)); + for (i = 0; i < size; i++) { + queue->packets[i] = malloc(sizeof(AVPacket)); + } + pthread_mutex_init(&queue->mutex, NULL); + pthread_cond_init(&queue->cond, NULL); + return queue; +} + +void vlc_queue_free(vlc_queue_t *queue) { + int i; + for (i = 0; i < queue->size; i++) { + free(queue->packets[i]); + } + free(queue->packets); + free(queue); + pthread_cond_destroy(&queue->cond); + pthread_mutex_destroy(&queue->mutex); +} + +int vlc_queue_next(vlc_queue_t *queue, int current) { + return (current + 1) % queue->size; +} + +void *vlc_queue_push(vlc_queue_t *queue, void *data) { + pthread_mutex_lock(&queue->mutex);//lock + int current = queue->next_to_write; + int next_to_write; + for (;;) { + next_to_write = vlc_queue_next(queue, current); + if (next_to_write != queue->next_to_read) { + break; + } + pthread_cond_wait(&queue->cond, &queue->mutex); + } + queue->next_to_write = next_to_write; + queue->packets[current] = data;//TODO + pthread_cond_broadcast(&queue->cond); + pthread_mutex_unlock(&queue->mutex);//unlock + return queue->packets[current]; +} + +void *vlc_queue_pop(vlc_queue_t *queue) { + pthread_mutex_lock(&queue->mutex); + int current = queue->next_to_read; + for (;;) { + if (queue->next_to_write != queue->next_to_read) { + break; + } + pthread_cond_wait(&queue->cond, &queue->mutex); + } + queue->next_to_read = vlc_queue_next(queue, current); + pthread_cond_broadcast(&queue->cond); + pthread_mutex_unlock(&queue->mutex); + return queue->packets[current]; +} \ No newline at end of file diff --git a/app/src/main/cpp/visualizer/block_queue.h b/app/src/main/cpp/visualizer/block_queue.h new file mode 100644 index 0000000..3f8c2b0 --- /dev/null +++ b/app/src/main/cpp/visualizer/block_queue.h @@ -0,0 +1,40 @@ +// +// Created by frank on 2021/08/08. +// + +#ifndef BLOCK_QUEUE_H +#define BLOCK_QUEUE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct vlc_queue { + //the size of queue + int size; + //packet array + void **packets; + //the packet next to write + int next_to_write; + //the packet next to read + int next_to_read; + + pthread_mutex_t mutex; + pthread_cond_t cond; +} vlc_queue_t; + +vlc_queue_t *vlc_queue_init(int size); + +void vlc_queue_free(vlc_queue_t *queue); + +void *vlc_queue_push(vlc_queue_t *queue, void *data); + +void *vlc_queue_pop(vlc_queue_t *queue); + +#endif //BLOCK_QUEUE_H + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/app/src/main/cpp/visualizer/execute_fft.c b/app/src/main/cpp/visualizer/execute_fft.c index 7271b89..88f44ed 100644 --- a/app/src/main/cpp/visualizer/execute_fft.c +++ b/app/src/main/cpp/visualizer/execute_fft.c @@ -15,29 +15,6 @@ #define BAR_DECREMENT .075f #define ROTATION_MAX 20 -static inline void block_CopyProperties(block_t *dst, const block_t *src) -{ - dst->i_dts = src->i_dts; - dst->i_pts = src->i_pts; - dst->i_flags = src->i_flags; - dst->i_length = src->i_length; - dst->i_nb_samples = src->i_nb_samples; -} - -static inline block_t *block_Duplicate(const block_t *p_block) -{ -// block_t *p_dup = block_Alloc(p_block->i_buffer);//TODO - block_t *p_dup = (block_t*) malloc(sizeof(block_t)); - if(p_dup == NULL) return NULL; - p_dup->i_buffer = p_block->i_buffer; - p_dup->p_buffer = (uint8_t*) malloc(p_block->i_buffer);//TODO - - block_CopyProperties(p_dup, p_block); - memcpy(p_dup->p_buffer, p_block->p_buffer, p_block->i_buffer); - - return p_dup; -} - /*static*/ int open_visualizer(filter_sys_t *p_sys) { if (p_sys == NULL) @@ -58,7 +35,9 @@ static inline block_t *block_Duplicate(const block_t *p_block) window_get_param(&p_sys->wind_param); /* Create the FIFO for the audio data. */ - vlc_queue_Init(&p_sys->queue, offsetof (block_t, p_next)); +// vlc_queue_Init(&p_sys->queue, offsetof (block_t, p_next)); + vlc_queue_t *queue = vlc_queue_init(5); + p_sys->queue = *queue; p_sys->dead = false; /* Create the thread */ @@ -74,7 +53,8 @@ static inline block_t *block_Duplicate(const block_t *p_block) /*static*/ block_t *filter_audio(filter_sys_t *p_sys, block_t *p_in_buf) { - vlc_queue_Enqueue(&p_sys->queue, block_Duplicate(p_in_buf)); +// vlc_queue_Enqueue(&p_sys->queue, block_Duplicate(p_in_buf)); + vlc_queue_push(&p_sys->queue, p_in_buf); return p_in_buf; } @@ -83,7 +63,7 @@ static inline block_t *block_Duplicate(const block_t *p_block) filter_sys_t *p_sys = p_filter; /* Terminate the thread. */ - vlc_queue_Kill(&p_sys->queue, &p_sys->dead); + vlc_queue_free(&p_sys->queue); // vlc_join(p_sys->thread, NULL); pthread_join(p_sys->thread, NULL); @@ -97,7 +77,8 @@ static void *fft_thread(void *p_data) float height[NB_BANDS] = {0}; LOGE("start FFT thread..."); - while ((block = vlc_queue_DequeueKillable(&p_sys->queue, &p_sys->dead))) +// while ((block = vlc_queue_DequeueKillable(&p_sys->queue, &p_sys->dead))) + while ((block = vlc_queue_pop(&p_sys->queue))) { LOGE("running FFT transform..."); unsigned win_width, win_height; @@ -218,15 +199,14 @@ static void *fft_thread(void *p_data) /* Wait to swapp the frame on time. */ // vlc_tick_wait(block->i_pts + (block->i_length / 2)); // vlc_gl_Swap(gl); - usleep(block->i_pts + (block->i_length / 2)); + usleep(200*1000 /*block->i_pts + (block->i_length / 2)*/); LOGE("height[0]=%f, height[1]=%f, height=[2]=%f", height[0], height[1], height[2]); release: window_close(&wind_ctx); fft_close(p_state); -// block_Release(block);//TODO - if (block->p_buffer) free(block->p_buffer); - free(block); +// if (block->p_buffer) free(block->p_buffer); +// free(block); } return NULL; diff --git a/app/src/main/cpp/visualizer/execute_fft.h b/app/src/main/cpp/visualizer/execute_fft.h index e606b82..14d38cb 100644 --- a/app/src/main/cpp/visualizer/execute_fft.h +++ b/app/src/main/cpp/visualizer/execute_fft.h @@ -2,10 +2,10 @@ // Created by frank on 2021/8/16. // -#ifndef EXECUTE_FFT_H -#define EXECUTE_FFT_H +#ifndef PLAYER_CORE_RUN_FFT_H +#define PLAYER_CORE_RUN_FFT_H -#include "vlc_queue.h" +#include "block_queue.h" #include "fft.h" #include "window.h" @@ -23,28 +23,17 @@ typedef int64_t vlc_tick_t; typedef struct block_t block_t; -struct vlc_block_callbacks -{ - void (*free)(block_t *); -}; - struct block_t { block_t *p_next; uint8_t *p_buffer; /**< Payload start */ size_t i_buffer; /**< Payload length */ - uint8_t *p_start; /**< Buffer start */ - size_t i_size; /**< Buffer total size */ - uint32_t i_flags; unsigned i_nb_samples; /* Used for audio */ vlc_tick_t i_pts; - vlc_tick_t i_dts; vlc_tick_t i_length; - - const struct vlc_block_callbacks *cbs; }; typedef struct @@ -73,4 +62,4 @@ static void *fft_thread(void *); /*static*/ void close_visualizer(filter_sys_t *p_filter); -#endif //EXECUTE_FFT_H +#endif //PLAYER_CORE_RUN_FFT_H diff --git a/app/src/main/cpp/visualizer/queue.c b/app/src/main/cpp/visualizer/queue.c deleted file mode 100644 index 5b2ef7a..0000000 --- a/app/src/main/cpp/visualizer/queue.c +++ /dev/null @@ -1,154 +0,0 @@ -/***************************************************************************** - * queue.c: generic queue (FIFO) - ***************************************************************************** - * Copyright (C) 2020 Rémi Denis-Courmont - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. - *****************************************************************************/ - -#include -#include -#include - -#include "vlc_queue.h" - -/* Opaque struct type. - * - * ISO C uses the same representation for all pointer-to-struct types. - * Still different pointer types are not compatible, i.e. cannot alias. - * So use memcpy() to read/write pointer values. - */ -struct vlc_queue_entry; - -static void entry_set(struct vlc_queue_entry **pp, struct vlc_queue_entry *e) -{ - memcpy(pp, &e, sizeof (e)); -} - -static struct vlc_queue_entry *entry_get(struct vlc_queue_entry *const *pp) -{ - struct vlc_queue_entry *e; - - memcpy(&e, pp, sizeof (e)); - return e; -} - -static struct vlc_queue_entry **next_p(const struct vlc_queue_entry *e, - ptrdiff_t offset) -{ - return (struct vlc_queue_entry **)(((unsigned char *)e) + offset); -} - -static void next_set(struct vlc_queue_entry *e, struct vlc_queue_entry *next, - ptrdiff_t offset) -{ - entry_set(next_p(e, offset), next); -} - -static struct vlc_queue_entry *next_get(const struct vlc_queue_entry *e, - ptrdiff_t offset) -{ - return entry_get(next_p(e, offset)); -} - -void vlc_queue_Init(vlc_queue_t *q, ptrdiff_t next_offset) -{ - q->first = NULL; - q->lastp = &q->first; - q->next_offset = next_offset; - pthread_mutex_init(&q->lock, NULL); - pthread_cond_init(&q->wait, NULL); -} - -void vlc_queue_EnqueueUnlocked(vlc_queue_t *q, void *entry) -{ - struct vlc_queue_entry **lastp; - const ptrdiff_t offset = q->next_offset; - -// vlc_mutex_assert(&q->lock); - assert(entry_get(q->lastp) == NULL); - entry_set(q->lastp, entry); - - for (lastp = q->lastp; entry != NULL; entry = next_get(entry, offset)) - lastp = next_p(entry, offset); - - q->lastp = lastp; - vlc_queue_Signal(q); -} - -void *vlc_queue_DequeueUnlocked(vlc_queue_t *q) -{ -// vlc_mutex_assert(&q->lock); - - void *entry = q->first; - const ptrdiff_t offset = q->next_offset; - - if (entry != NULL) { - struct vlc_queue_entry *next = next_get(entry, offset); - - next_set(entry, NULL, offset); - q->first = next; - - if (next == NULL) - q->lastp = &q->first; - } - - return entry; -} - -void *vlc_queue_DequeueAllUnlocked(vlc_queue_t *q) -{ -// vlc_mutex_assert(&q->lock); - - void *entry = q->first; - - q->first = NULL; - q->lastp = &q->first; - - return entry; -} - -void vlc_queue_Enqueue(vlc_queue_t *q, void *entry) -{ - vlc_queue_Lock(q); - vlc_queue_EnqueueUnlocked(q, entry); - vlc_queue_Unlock(q); -} - -void *vlc_queue_Dequeue(vlc_queue_t *q) -{ - void *entry; - - vlc_queue_Lock(q); - - while (vlc_queue_IsEmpty(q)) - vlc_queue_Wait(q); - - entry = vlc_queue_DequeueUnlocked(q); - vlc_queue_Unlock(q); - - return entry; -} - -void *vlc_queue_DequeueAll(vlc_queue_t *q) -{ - void *entry; - - vlc_queue_Lock(q); - entry = vlc_queue_DequeueAllUnlocked(q); - vlc_queue_Unlock(q); - - return entry; -} diff --git a/app/src/main/cpp/visualizer/vlc_queue.h b/app/src/main/cpp/visualizer/vlc_queue.h deleted file mode 100644 index 920d942..0000000 --- a/app/src/main/cpp/visualizer/vlc_queue.h +++ /dev/null @@ -1,258 +0,0 @@ -/***************************************************************************** - * vlc_queue.h: generic queue functions - ***************************************************************************** - * Copyright (C) 2020 Rémi Denis-Courmont - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. - *****************************************************************************/ - -#ifndef VLC_QUEUE_H -#define VLC_QUEUE_H - -/** - * @defgroup queue Thread-safe queues (FIFO) - * @ingroup cext - * @{ - * @file vlc_queue.h - */ - -#include -#include -#include -#include - -/** - * Opaque type for queue entry. - */ -struct vlc_queue_entry; - -/** - * Thread-safe queue (a.k.a. FIFO). - */ -typedef struct vlc_queue -{ - struct vlc_queue_entry *first; - struct vlc_queue_entry **lastp; - ptrdiff_t next_offset; - pthread_mutex_t lock; - pthread_cond_t wait; -} vlc_queue_t; - -/** - * Initializes a queue. - * - * @param queue storage space for the queue - * @param next_offset offset of the pointer to the next element - * within a queue entry (as per @c offsetof()) - */ -void vlc_queue_Init(vlc_queue_t *queue, ptrdiff_t next_offset); - -/** - * @defgroup queue_ll Queue internals - * - * Low-level queue functions. - * - * In some cases, the high-level queue functions do not exactly fit the - * use case requirements, and it is necessary to access the queue internals. - * This typically occurs when threads wait for elements to be added to the - * queue at the same time as some other type of events. - * @{ - */ -/** - * Locks a queue. - * - * No more than one thread can lock a queue at any given time, and no other - * thread can modify the queue while it is locked. - * Accordingly, if the queue is already locked by another thread, this function - * waits. - * - * Use vlc_queue_Unlock() to release the lock. - * - * @warning Recursively locking a single queue is undefined. - * Also locking more than one queue at a time may lead to lock inversion: - * mind the locking order! - */ -static inline void vlc_queue_Lock(vlc_queue_t *q) -{ - pthread_mutex_lock(&q->lock); -} - -/** - * Unlocks a queue. - * - * This releases the lock on a queue, allowing other threads to manipulate the - * queue. The behaviour is undefined if the calling thread is not holding the - * queue lock. - */ -static inline void vlc_queue_Unlock(vlc_queue_t *q) -{ - pthread_mutex_unlock(&q->lock); -} - -/** - * Wakes one thread waiting for a queue entry up. - */ -static inline void vlc_queue_Signal(vlc_queue_t *q) -{ - pthread_cond_signal(&q->wait); -} - -/** - * Waits for a queue entry. - * - * @note This function is a cancellation point. - * In case of cancellation, the queue will be locked, - * as is consistent for condition variable semantics. - * - * @bug This function should probably not be aware of cancellation. - */ -static inline void vlc_queue_Wait(vlc_queue_t *q) -{ - pthread_cond_wait(&q->wait, &q->lock); -} - -/** - * Queues an entry (without locking). - * - * This function enqueues an entry, or rather a linked-list of entries, in a - * thread-safe queue, without taking the queue lock. - * - * @warning It is assumed that the caller already holds the queue lock; - * otherwise the behaviour is undefined. - * - * @param entry NULL-terminated list of entries to queue - * (if NULL, this function has no effects) - */ -void vlc_queue_EnqueueUnlocked(vlc_queue_t *, void *entry); - -/** - * Dequeues the oldest entry (without locking). - * - * This function dequeues an entry from a thread-safe queue. It is assumed - * that the caller already holds the queue lock; otherwise the behaviour is - * undefined. - * - * @warning It is assumed that the caller already holds the queue lock; - * otherwise the behaviour is undefined. - * - * @return the first entry in the queue, or NULL if the queue is empty - */ -void *vlc_queue_DequeueUnlocked(vlc_queue_t *); - -/** - * Dequeues all entries (without locking). - * - * This is equivalent to calling vlc_queue_DequeueUnlocked() repeatedly until - * the queue is emptied. However this function is much faster than that, as it - * does not need to update the linked-list pointers. - * - * @warning It is assumed that the caller already holds the queue lock; - * otherwise the behaviour is undefined. - * - * @return a linked-list of all entries (possibly NULL if none) - */ -void *vlc_queue_DequeueAllUnlocked(vlc_queue_t *); - -/** - * Checks if a queue is empty (without locking). - * - * @warning It is assumed that the caller already holds the queue lock; - * otherwise the behaviour is undefined. - * - * @retval false the queue contains one or more entries - * @retval true the queue is empty - */ -static inline bool vlc_queue_IsEmpty(const vlc_queue_t *q) -{ - return q->first == NULL; -} - -/** @} */ - -/** - * Queues an entry. - * - * This function enqueues an entry, or rather a linked-list of entries, in a - * thread-safe queue. - * - * @param entry list of entries (if NULL, this function has no effects) - */ -void vlc_queue_Enqueue(vlc_queue_t *, void *entry); - -/** - * Dequeues the oldest entry. - * - * This function dequeues an entry from a thread-safe queue. If the queue is - * empty, it will wait until at least one entry is available. - * - * @param offset offset of the next pointer within a queue entry - * - * @return the first entry in the queue, or NULL if the queue is empty - */ -void *vlc_queue_Dequeue(vlc_queue_t *); - -/** - * Dequeues all entries. - * - * This is equivalent to calling vlc_queue_Dequeue() repeatedly until the queue - * is emptied. However this function is much faster than that, as it - * does not need to update the linked-list pointers. - * - * @return a linked-list of all entries (possibly NULL if none) - */ -void *vlc_queue_DequeueAll(vlc_queue_t *); - -/** - * @defgroup queue_killable Killable queues - * - * Thread-safe queues with an end flag. - * - * @{ - */ - -/** - * Marks a queue ended. - */ -static inline void vlc_queue_Kill(vlc_queue_t *q, - bool */*restrict*/ tombstone) -{ - vlc_queue_Lock(q); - *tombstone = true; - vlc_queue_Signal(q); - vlc_queue_Unlock(q); - pthread_cond_destroy(&q->wait); - pthread_mutex_destroy(&q->lock); -} - -/** - * Dequeues one entry from a killable queue. - * - * @return an entry, or NULL if the queue is empty and has been ended. - */ -static inline void *vlc_queue_DequeueKillable(vlc_queue_t *q, - bool */*restrict*/ tombstone) -{ - void *entry; - - vlc_queue_Lock(q); - while (vlc_queue_IsEmpty(q) && !*tombstone) - vlc_queue_Wait(q); - - entry = vlc_queue_DequeueUnlocked(q); - vlc_queue_Unlock(q); - return entry; -} - -#endif