From 5569139c43fc228095d839a64cc80f60eadd8f42 Mon Sep 17 00:00:00 2001 From: derrod Date: Sun, 30 Jul 2023 01:51:19 +0200 Subject: [PATCH] deps/libff: Remove unused code and header files --- deps/libff/libff/ff-audio-decoder.c | 205 -------- deps/libff/libff/ff-callbacks.c | 60 --- deps/libff/libff/ff-callbacks.h | 52 -- deps/libff/libff/ff-circular-queue.c | 137 ------ deps/libff/libff/ff-circular-queue.h | 58 --- deps/libff/libff/ff-clock.c | 141 ------ deps/libff/libff/ff-clock.h | 65 --- deps/libff/libff/ff-compat.h | 29 -- deps/libff/libff/ff-decoder.c | 387 --------------- deps/libff/libff/ff-decoder.h | 87 ---- deps/libff/libff/ff-demuxer.c | 627 ------------------------ deps/libff/libff/ff-demuxer.h | 92 ---- deps/libff/libff/ff-frame.h | 38 -- deps/libff/libff/ff-packet-queue.c | 156 ------ deps/libff/libff/ff-packet-queue.h | 68 --- deps/libff/libff/ff-threading-posix.c | 27 - deps/libff/libff/ff-threading-windows.c | 31 -- deps/libff/libff/ff-threading.h | 28 -- deps/libff/libff/ff-timer.c | 145 ------ deps/libff/libff/ff-timer.h | 53 -- deps/libff/libff/ff-video-decoder.c | 154 ------ 21 files changed, 2640 deletions(-) delete mode 100644 deps/libff/libff/ff-audio-decoder.c delete mode 100644 deps/libff/libff/ff-callbacks.c delete mode 100644 deps/libff/libff/ff-callbacks.h delete mode 100644 deps/libff/libff/ff-circular-queue.c delete mode 100644 deps/libff/libff/ff-circular-queue.h delete mode 100644 deps/libff/libff/ff-clock.c delete mode 100644 deps/libff/libff/ff-clock.h delete mode 100644 deps/libff/libff/ff-compat.h delete mode 100644 deps/libff/libff/ff-decoder.c delete mode 100644 deps/libff/libff/ff-decoder.h delete mode 100644 deps/libff/libff/ff-demuxer.c delete mode 100644 deps/libff/libff/ff-demuxer.h delete mode 100644 deps/libff/libff/ff-frame.h delete mode 100644 deps/libff/libff/ff-packet-queue.c delete mode 100644 deps/libff/libff/ff-packet-queue.h delete mode 100644 deps/libff/libff/ff-threading-posix.c delete mode 100644 deps/libff/libff/ff-threading-windows.c delete mode 100644 deps/libff/libff/ff-threading.h delete mode 100644 deps/libff/libff/ff-timer.c delete mode 100644 deps/libff/libff/ff-timer.h delete mode 100644 deps/libff/libff/ff-video-decoder.c diff --git a/deps/libff/libff/ff-audio-decoder.c b/deps/libff/libff/ff-audio-decoder.c deleted file mode 100644 index cbdb317c5..000000000 --- a/deps/libff/libff/ff-audio-decoder.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (c) 2015 John R. Bradley - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ff-callbacks.h" -#include "ff-circular-queue.h" -#include "ff-clock.h" -#include "ff-decoder.h" -#include "ff-frame.h" -#include "ff-packet-queue.h" -#include "ff-timer.h" - -#include -#include -#include - -#include - -#include "ff-compat.h" - -static inline void shrink_packet(struct ff_packet *packet, int packet_length) -{ - if (packet_length <= packet->base.size) { - int remaining = packet->base.size - packet_length; - - memmove(packet->base.data, &packet->base.data[packet_length], - remaining); - av_shrink_packet(&packet->base, remaining); - } -} - -static bool handle_reset_packet(struct ff_decoder *decoder, - struct ff_packet *packet) -{ - if (decoder->clock != NULL) - ff_clock_release(&decoder->clock); - decoder->clock = packet->clock; - av_free_packet(&packet->base); - - return true; -} - -static void drop_late_packets(struct ff_decoder *decoder, - struct ff_packet *packet) -{ - int64_t start_time = ff_clock_start_time(decoder->clock); - if (start_time != AV_NOPTS_VALUE) { - if (ff_decoder_set_frame_drop_state(decoder, start_time, - packet->base.pts)) - shrink_packet(packet, packet->base.size); - } -} - -static int decode_frame(struct ff_decoder *decoder, struct ff_packet *packet, - AVFrame *frame, bool *frame_complete) -{ - int packet_length; - int ret; - - while (true) { - if (decoder->eof) - ret = packet_queue_get(&decoder->packet_queue, packet, - 0); - else - ret = packet_queue_get(&decoder->packet_queue, packet, - 1); - - if (ret == FF_PACKET_EMPTY) { - return 0; - } else if (ret == FF_PACKET_FAIL) { - return -1; - } - - if (packet->base.data == - decoder->packet_queue.flush_packet.base.data) { - avcodec_flush_buffers(decoder->codec); - continue; - } - - // Packet has a new clock (reset packet) - if (packet->clock != NULL) - if (!handle_reset_packet(decoder, packet)) - return -1; - - while (packet->base.size > 0) { - int complete; - - drop_late_packets(decoder, packet); - - packet_length = avcodec_decode_audio4(decoder->codec, - frame, &complete, - &packet->base); - - if (packet_length < 0) - break; - - shrink_packet(packet, packet_length); - - if (complete == 0 || frame->nb_samples <= 0) - continue; - - *frame_complete = complete != 0; - - return frame->nb_samples * - av_get_bytes_per_sample(frame->format); - } - - if (packet->base.data != NULL) - av_packet_unref(&packet->base); - } -} - -static bool queue_frame(struct ff_decoder *decoder, AVFrame *frame, - double best_effort_pts) -{ - struct ff_frame *queue_frame; - bool call_initialize; - - ff_circular_queue_wait_write(&decoder->frame_queue); - - if (decoder->abort) { - return false; - } - - queue_frame = ff_circular_queue_peek_write(&decoder->frame_queue); - - AVCodecContext *codec = decoder->codec; - call_initialize = - (queue_frame->frame == NULL || - queue_frame->frame->channels != codec->channels || - queue_frame->frame->sample_rate != codec->sample_rate || - queue_frame->frame->format != codec->sample_fmt); - - if (queue_frame->frame != NULL) { - //FIXME: this shouldn't happen any more! - av_frame_free(&queue_frame->frame); - } - - queue_frame->frame = av_frame_clone(frame); - queue_frame->clock = ff_clock_retain(decoder->clock); - - if (call_initialize) - ff_callbacks_frame_initialize(queue_frame, decoder->callbacks); - - queue_frame->pts = best_effort_pts; - - ff_circular_queue_advance_write(&decoder->frame_queue, queue_frame); - - return true; -} - -void *ff_audio_decoder_thread(void *opaque_audio_decoder) -{ - struct ff_decoder *decoder = opaque_audio_decoder; - - struct ff_packet packet = {0}; - bool frame_complete; - AVFrame *frame = av_frame_alloc(); - int ret; - - while (!decoder->abort) { - ret = decode_frame(decoder, &packet, frame, &frame_complete); - if (ret == 0) { - break; - } else if (ret < 0) { - av_free_packet(&packet.base); - continue; - } - - // Did we get a audio frame? - if (frame_complete) { - // If we don't have a good PTS, try to guess based - // on last received PTS provided plus prediction - // This function returns a pts scaled to stream - // time base - double best_effort_pts = - ff_decoder_get_best_effort_pts(decoder, frame); - queue_frame(decoder, frame, best_effort_pts); - av_frame_unref(frame); - } - - av_free_packet(&packet.base); - } - - if (decoder->clock != NULL) - ff_clock_release(&decoder->clock); - - av_frame_free(&frame); - - decoder->finished = true; - - return NULL; -} diff --git a/deps/libff/libff/ff-callbacks.c b/deps/libff/libff/ff-callbacks.c deleted file mode 100644 index 9aa0b796e..000000000 --- a/deps/libff/libff/ff-callbacks.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2015 John R. Bradley - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ff-callbacks.h" - -bool ff_callbacks_frame(struct ff_callbacks *callbacks, struct ff_frame *frame) -{ - if (callbacks->frame == NULL) - return true; - - return callbacks->frame(frame, callbacks->opaque); -} - -bool ff_callbacks_format(struct ff_callbacks *callbacks, - AVCodecContext *codec_context) -{ - if (callbacks->format == NULL) - return true; - - return callbacks->format(codec_context, callbacks->opaque); -} - -bool ff_callbacks_initialize(struct ff_callbacks *callbacks) -{ - if (callbacks->initialize == NULL) - return true; - - return callbacks->initialize(callbacks->opaque); -} - -bool ff_callbacks_frame_initialize(struct ff_frame *frame, - struct ff_callbacks *callbacks) -{ - if (callbacks->frame_initialize == NULL) - return true; - - return callbacks->frame_initialize(frame, callbacks->opaque); -} - -bool ff_callbacks_frame_free(struct ff_frame *frame, - struct ff_callbacks *callbacks) -{ - if (callbacks->frame_free == NULL) - return true; - - return callbacks->frame_free(frame, callbacks->opaque); -} diff --git a/deps/libff/libff/ff-callbacks.h b/deps/libff/libff/ff-callbacks.h deleted file mode 100644 index cb1234d0d..000000000 --- a/deps/libff/libff/ff-callbacks.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2015 John R. Bradley - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#pragma once - -#include "ff-frame.h" - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef bool (*ff_callback_frame)(struct ff_frame *frame, void *opaque); -typedef bool (*ff_callback_format)(AVCodecContext *codec_context, void *opaque); -typedef bool (*ff_callback_initialize)(void *opaque); - -struct ff_callbacks { - ff_callback_frame frame; - ff_callback_format format; - ff_callback_initialize initialize; - ff_callback_frame frame_initialize; - ff_callback_frame frame_free; - void *opaque; -}; - -bool ff_callbacks_frame(struct ff_callbacks *callbacks, struct ff_frame *frame); -bool ff_callbacks_format(struct ff_callbacks *callbacks, - AVCodecContext *codec_context); -bool ff_callbacks_initialize(struct ff_callbacks *callbacks); -bool ff_callbacks_frame_initialize(struct ff_frame *frame, - struct ff_callbacks *callbacks); -bool ff_callbacks_frame_free(struct ff_frame *frame, - struct ff_callbacks *callbacks); - -#ifdef __cplusplus -} -#endif diff --git a/deps/libff/libff/ff-circular-queue.c b/deps/libff/libff/ff-circular-queue.c deleted file mode 100644 index 138180665..000000000 --- a/deps/libff/libff/ff-circular-queue.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2015 John R. Bradley - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ff-circular-queue.h" - -static void *queue_fetch_or_alloc(struct ff_circular_queue *cq, int index) -{ - if (cq->slots[index] == NULL) - cq->slots[index] = av_mallocz(cq->item_size); - - return cq->slots[index]; -} - -static void queue_lock(struct ff_circular_queue *cq) -{ - pthread_mutex_lock(&cq->mutex); -} - -static void queue_unlock(struct ff_circular_queue *cq) -{ - pthread_mutex_unlock(&cq->mutex); -} - -static void queue_signal(struct ff_circular_queue *cq) -{ - pthread_cond_signal(&cq->cond); -} - -static void queue_wait(struct ff_circular_queue *cq) -{ - pthread_cond_wait(&cq->cond, &cq->mutex); -} - -bool ff_circular_queue_init(struct ff_circular_queue *cq, int item_size, - int capacity) -{ - memset(cq, 0, sizeof(struct ff_circular_queue)); - - cq->item_size = item_size; - cq->capacity = capacity; - cq->abort = false; - - cq->slots = av_mallocz(capacity * sizeof(void *)); - - if (cq->slots == NULL) - goto fail; - - cq->size = 0; - cq->write_index = 0; - cq->read_index = 0; - - if (pthread_mutex_init(&cq->mutex, NULL) != 0) - goto fail1; - - if (pthread_cond_init(&cq->cond, NULL) != 0) - goto fail2; - - return true; - -fail2: - pthread_mutex_destroy(&cq->mutex); -fail1: - av_free(cq->slots); -fail: - return false; -} - -void ff_circular_queue_abort(struct ff_circular_queue *cq) -{ - queue_lock(cq); - cq->abort = true; - queue_signal(cq); - queue_unlock(cq); -} - -void ff_circular_queue_free(struct ff_circular_queue *cq) -{ - ff_circular_queue_abort(cq); - - if (cq->slots != NULL) - av_free(cq->slots); - - pthread_mutex_destroy(&cq->mutex); - pthread_cond_destroy(&cq->cond); -} - -void ff_circular_queue_wait_write(struct ff_circular_queue *cq) -{ - queue_lock(cq); - - while (cq->size >= cq->capacity && !cq->abort) - queue_wait(cq); - - queue_unlock(cq); -} - -void *ff_circular_queue_peek_write(struct ff_circular_queue *cq) -{ - return queue_fetch_or_alloc(cq, cq->write_index); -} - -void ff_circular_queue_advance_write(struct ff_circular_queue *cq, void *item) -{ - cq->slots[cq->write_index] = item; - cq->write_index = (cq->write_index + 1) % cq->capacity; - - queue_lock(cq); - ++cq->size; - queue_unlock(cq); -} - -void *ff_circular_queue_peek_read(struct ff_circular_queue *cq) -{ - return queue_fetch_or_alloc(cq, cq->read_index); -} - -void ff_circular_queue_advance_read(struct ff_circular_queue *cq) -{ - cq->read_index = (cq->read_index + 1) % cq->capacity; - queue_lock(cq); - --cq->size; - queue_signal(cq); - queue_unlock(cq); -} diff --git a/deps/libff/libff/ff-circular-queue.h b/deps/libff/libff/ff-circular-queue.h deleted file mode 100644 index f82b91648..000000000 --- a/deps/libff/libff/ff-circular-queue.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2015 John R. Bradley - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -struct ff_circular_queue { - pthread_mutex_t mutex; - pthread_cond_t cond; - - void **slots; - - int item_size; - int capacity; - int size; - - int write_index; - int read_index; - - bool abort; -}; - -typedef struct ff_circular_queue ff_circular_queue_t; - -bool ff_circular_queue_init(struct ff_circular_queue *cq, int item_size, - int capacity); -void ff_circular_queue_abort(struct ff_circular_queue *cq); -void ff_circular_queue_free(struct ff_circular_queue *cq); - -void ff_circular_queue_wait_write(struct ff_circular_queue *cq); -void *ff_circular_queue_peek_write(struct ff_circular_queue *cq); -void ff_circular_queue_advance_write(struct ff_circular_queue *cq, void *item); -void *ff_circular_queue_peek_read(struct ff_circular_queue *cq); -void ff_circular_queue_advance_read(struct ff_circular_queue *cq); - -#ifdef __cplusplus -} -#endif diff --git a/deps/libff/libff/ff-clock.c b/deps/libff/libff/ff-clock.c deleted file mode 100644 index 720cbdf3d..000000000 --- a/deps/libff/libff/ff-clock.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2015 John R. Bradley - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ff-clock.h" -#include "ff-threading.h" - -#include -#include - -// Amount of microseconds between checks to see if a clock has started -#define CLOCK_START_CHECK_INTERVAL 100 - -double ff_get_sync_clock(struct ff_clock *clock) -{ - return clock->sync_clock(clock->opaque); -} - -int64_t ff_clock_start_time(struct ff_clock *clock) -{ - int64_t start_time = AV_NOPTS_VALUE; - - pthread_mutex_lock(&clock->mutex); - if (clock->started) - start_time = clock->start_time; - pthread_mutex_unlock(&clock->mutex); - - return start_time; -} - -bool ff_clock_start(struct ff_clock *clock, enum ff_av_sync_type sync_type, - const bool *abort) -{ - bool release = false; - bool aborted = false; - - if (clock->sync_type == sync_type && !clock->started) { - pthread_mutex_lock(&clock->mutex); - if (!clock->started) { - clock->start_time = av_gettime(); - clock->started = true; - } - pthread_cond_signal(&clock->cond); - pthread_mutex_unlock(&clock->mutex); - } else { - while (!clock->started) { - pthread_mutex_lock(&clock->mutex); - int64_t current_time = - av_gettime() + CLOCK_START_CHECK_INTERVAL; - struct timespec sleep_time = { - .tv_sec = current_time / AV_TIME_BASE, - .tv_nsec = - (current_time % AV_TIME_BASE) * 1000}; - pthread_cond_timedwait(&clock->cond, &clock->mutex, - &sleep_time); - - aborted = *abort; - - // There is no way anyone can signal us since we are - // the only reference - if (clock->retain == 1) - release = true; - pthread_mutex_unlock(&clock->mutex); - - if (aborted || release) { - av_log(NULL, AV_LOG_ERROR, - "could not start " - "slave clock as master clock " - "was never started before " - "being released or aborted"); - break; - } - } - } - - if (release) - ff_clock_release(&clock); - - return !release && !aborted; -} - -struct ff_clock *ff_clock_init(void) -{ - struct ff_clock *clock = av_mallocz(sizeof(struct ff_clock)); - - if (clock == NULL) - return NULL; - - if (pthread_mutex_init(&clock->mutex, NULL) != 0) - goto fail; - - if (pthread_cond_init(&clock->cond, NULL) != 0) - goto fail1; - - return clock; - -fail1: - pthread_mutex_destroy(&clock->mutex); -fail: - av_free(clock); - - return NULL; -} - -struct ff_clock *ff_clock_retain(struct ff_clock *clock) -{ - ff_atomic_inc_long(&clock->retain); - - return clock; -} - -struct ff_clock *ff_clock_move(struct ff_clock **clock) -{ - struct ff_clock *retained_clock = ff_clock_retain(*clock); - ff_clock_release(clock); - - return retained_clock; -} - -void ff_clock_release(struct ff_clock **clock) -{ - if (ff_atomic_dec_long(&(*clock)->retain) == 0) { - pthread_cond_destroy(&(*clock)->cond); - pthread_mutex_destroy(&(*clock)->mutex); - av_free(*clock); - } - - *clock = NULL; -} diff --git a/deps/libff/libff/ff-clock.h b/deps/libff/libff/ff-clock.h deleted file mode 100644 index 0135c6493..000000000 --- a/deps/libff/libff/ff-clock.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2015 John R. Bradley - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#pragma once - -#define AV_SYNC_THRESHOLD 0.01 -#define AV_NOSYNC_THRESHOLD 10.0 - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -enum ff_av_sync_type { - AV_SYNC_AUDIO_MASTER, - AV_SYNC_VIDEO_MASTER, - AV_SYNC_EXTERNAL_MASTER, -}; - -typedef double (*ff_sync_clock)(void *opaque); - -struct ff_clock { - ff_sync_clock sync_clock; - enum ff_av_sync_type sync_type; - uint64_t start_time; - - pthread_mutex_t mutex; - pthread_cond_t cond; - volatile long retain; - bool started; - - void *opaque; -}; - -typedef struct ff_clock ff_clock_t; - -struct ff_clock *ff_clock_init(void); -double ff_get_sync_clock(struct ff_clock *clock); -struct ff_clock *ff_clock_retain(struct ff_clock *clock); -struct ff_clock *ff_clock_move(struct ff_clock **clock); -void ff_clock_release(struct ff_clock **clock); - -int64_t ff_clock_start_time(struct ff_clock *clock); -bool ff_clock_start(struct ff_clock *clock, enum ff_av_sync_type sync_type, - const bool *abort); - -#ifdef __cplusplus -} -#endif diff --git a/deps/libff/libff/ff-compat.h b/deps/libff/libff/ff-compat.h deleted file mode 100644 index a74415b98..000000000 --- a/deps/libff/libff/ff-compat.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2023 Lain Bailey - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#pragma once - -#if LIBAVCODEC_VERSION_MAJOR >= 57 -#define av_free_packet av_packet_unref -static inline int av_dup_packet_2(AVPacket *pkt) -{ - AVPacket tmp = *pkt; - int ret = av_packet_ref(pkt, &tmp); - av_packet_unref(&tmp); - return ret; -} -#define av_dup_packet av_dup_packet_2 -#endif diff --git a/deps/libff/libff/ff-decoder.c b/deps/libff/libff/ff-decoder.c deleted file mode 100644 index f621aa8c2..000000000 --- a/deps/libff/libff/ff-decoder.c +++ /dev/null @@ -1,387 +0,0 @@ -/* - * Copyright (c) 2015 John R. Bradley - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ff-decoder.h" - -#include -#include - -typedef void *(*ff_decoder_thread_t)(void *opaque_decoder); - -extern void *ff_audio_decoder_thread(void *opaque_audio_decoder); -extern void *ff_video_decoder_thread(void *opaque_video_decoder); - -struct ff_decoder *ff_decoder_init(AVCodecContext *codec_context, - AVStream *stream, - unsigned int packet_queue_size, - unsigned int frame_queue_size) -{ - bool success; - - assert(codec_context != NULL); - assert(stream != NULL); - - struct ff_decoder *decoder = av_mallocz(sizeof(struct ff_decoder)); - - if (decoder == NULL) - goto fail; - - decoder->codec = codec_context; - decoder->codec->opaque = decoder; - decoder->stream = stream; - decoder->abort = false; - decoder->finished = false; - - decoder->packet_queue_size = packet_queue_size; - if (!packet_queue_init(&decoder->packet_queue)) - goto fail1; - - decoder->timer_next_wake = (double)av_gettime() / 1000000.0; - decoder->previous_pts_diff = 40e-3; - decoder->current_pts_time = av_gettime(); - decoder->start_pts = 0; - decoder->predicted_pts = 0; - decoder->first_frame = true; - - success = ff_timer_init(&decoder->refresh_timer, ff_decoder_refresh, - decoder); - if (!success) - goto fail2; - - success = ff_circular_queue_init(&decoder->frame_queue, - sizeof(struct ff_frame), - frame_queue_size); - if (!success) - goto fail3; - - return decoder; - -fail3: - ff_timer_free(&decoder->refresh_timer); -fail2: - packet_queue_free(&decoder->packet_queue); -fail1: - av_free(decoder); -fail: - return NULL; -} - -bool ff_decoder_start(struct ff_decoder *decoder) -{ - assert(decoder != NULL); - - ff_decoder_thread_t decoder_thread; - if (decoder->codec->codec_type == AVMEDIA_TYPE_AUDIO) { - decoder_thread = ff_audio_decoder_thread; - } else if (decoder->codec->codec_type == AVMEDIA_TYPE_VIDEO) { - decoder_thread = ff_video_decoder_thread; - } else { - av_log(NULL, AV_LOG_ERROR, "no decoder found for type %d", - decoder->codec->codec_type); - return false; - } - - ff_decoder_schedule_refresh(decoder, 40); - - return (pthread_create(&decoder->decoder_thread, NULL, decoder_thread, - decoder) != 0); -} - -void ff_decoder_free(struct ff_decoder *decoder) -{ - void *decoder_thread_result; - int i; - - assert(decoder != NULL); - - decoder->abort = true; - - ff_circular_queue_abort(&decoder->frame_queue); - packet_queue_abort(&decoder->packet_queue); - - ff_timer_free(&decoder->refresh_timer); - - pthread_join(decoder->decoder_thread, &decoder_thread_result); - - for (i = 0; i < decoder->frame_queue.capacity; i++) { - void *item = decoder->frame_queue.slots[i]; - struct ff_frame *frame = (struct ff_frame *)item; - - ff_callbacks_frame_free(frame, decoder->callbacks); - - if (frame != NULL) { - if (frame->frame != NULL) - av_frame_unref(frame->frame); - if (frame->clock != NULL) - ff_clock_release(&frame->clock); - av_free(frame); - } - } - - packet_queue_free(&decoder->packet_queue); - ff_circular_queue_free(&decoder->frame_queue); - - avcodec_close(decoder->codec); - - av_free(decoder); -} - -void ff_decoder_schedule_refresh(struct ff_decoder *decoder, int delay) -{ - ff_timer_schedule(&decoder->refresh_timer, 1000 * delay); -} - -double ff_decoder_clock(void *opaque) -{ - struct ff_decoder *decoder = opaque; - double delta = (av_gettime() - decoder->current_pts_time) / 1000000.0; - return decoder->current_pts + delta; -} - -static double get_sync_adjusted_pts_diff(struct ff_clock *clock, double pts, - double pts_diff) -{ - double new_pts_diff = pts_diff; - double sync_time = ff_get_sync_clock(clock); - double diff = pts - sync_time; - double sync_threshold; - - sync_threshold = (pts_diff > AV_SYNC_THRESHOLD) ? pts_diff - : AV_SYNC_THRESHOLD; - - if (fabs(diff) < AV_NOSYNC_THRESHOLD) { - if (diff <= -sync_threshold) { - new_pts_diff = 0; - - } else if (diff >= sync_threshold) { - new_pts_diff = 2 * pts_diff; - } - } - - return new_pts_diff; -} - -void ff_decoder_refresh(void *opaque) -{ - struct ff_decoder *decoder = (struct ff_decoder *)opaque; - - struct ff_frame *frame; - - if (decoder->stream) { - if (decoder->frame_queue.size == 0) { - if (!decoder->eof || !decoder->finished) { - // We expected a frame, but there were none - // available - - // Schedule another call as soon as possible - ff_decoder_schedule_refresh(decoder, 1); - } else { - ff_callbacks_frame(decoder->callbacks, NULL); - decoder->refresh_timer.abort = true; - // no more refreshes, we are at the eof - av_log(NULL, AV_LOG_INFO, - "refresh timer stopping; eof"); - return; - } - } else { - double pts_diff; - double delay_until_next_wake; - bool late_first_frame = false; - - frame = ff_circular_queue_peek_read( - &decoder->frame_queue); - - // Get frame clock and start it if needed - ff_clock_t *clock = ff_clock_move(&frame->clock); - if (!ff_clock_start(clock, decoder->natural_sync_clock, - &decoder->refresh_timer.abort)) { - ff_clock_release(&clock); - - // Our clock was never started and deleted or - // aborted - - if (decoder->refresh_timer.abort) { - av_log(NULL, AV_LOG_INFO, - "refresh timer aborted"); - return; - } - - // Drop this frame? The only way this can happen - // is if one stream finishes before another and - // the input is looping or canceled. Until we - // get another clock we will unable to continue - - ff_decoder_schedule_refresh(decoder, 100); - - // Drop this frame as we have no way of timing - // it - ff_circular_queue_advance_read( - &decoder->frame_queue); - return; - } - - decoder->current_pts = frame->pts; - decoder->current_pts_time = av_gettime(); - - // the amount of time until we need to display this - // frame - pts_diff = frame->pts - decoder->previous_pts; - - // if the first frame is a very large value, we've most - // likely started mid-stream, and the initial diff - // should be ignored. - if (decoder->first_frame) { - late_first_frame = pts_diff >= 1.0; - decoder->first_frame = false; - } - - if (pts_diff <= 0 || late_first_frame) { - // if diff is invalid, use previous - pts_diff = decoder->previous_pts_diff; - } - - // save for next time - decoder->previous_pts_diff = pts_diff; - decoder->previous_pts = frame->pts; - - // if not synced against natural clock - if (clock->sync_type != decoder->natural_sync_clock) { - pts_diff = get_sync_adjusted_pts_diff( - clock, frame->pts, pts_diff); - } - - decoder->timer_next_wake += pts_diff; - - // compute the amount of time until next refresh - delay_until_next_wake = decoder->timer_next_wake - - (av_gettime() / 1000000.0L); - if (delay_until_next_wake < 0.010L) { - delay_until_next_wake = 0.010L; - } - - if (delay_until_next_wake > pts_diff) - delay_until_next_wake = pts_diff; - - ff_clock_release(&clock); - ff_callbacks_frame(decoder->callbacks, frame); - - ff_decoder_schedule_refresh( - decoder, - (int)(delay_until_next_wake * 1000 + 0.5L)); - - av_frame_free(&frame->frame); - - ff_circular_queue_advance_read(&decoder->frame_queue); - } - } else { - ff_decoder_schedule_refresh(decoder, 100); - } -} - -bool ff_decoder_full(struct ff_decoder *decoder) -{ - if (decoder == NULL) - return false; - - return (decoder->packet_queue.total_size > decoder->packet_queue_size); -} - -bool ff_decoder_accept(struct ff_decoder *decoder, struct ff_packet *packet) -{ - if (decoder && packet->base.stream_index == decoder->stream->index) { - packet_queue_put(&decoder->packet_queue, packet); - return true; - } - - return false; -} - -double ff_decoder_get_best_effort_pts(struct ff_decoder *decoder, - AVFrame *frame) -{ - // this is how long each frame is added to the amount of repeated frames - // according to the codec - double estimated_frame_delay; - int64_t best_effort_pts; - double d_pts; - - // This function is ffmpeg only, replace with frame->pkt_pts - // if you are trying to compile for libav as a temporary - // measure - best_effort_pts = av_frame_get_best_effort_timestamp(frame); - - if (best_effort_pts != AV_NOPTS_VALUE) { - // Fix the first pts if less than start_pts - if (best_effort_pts < decoder->start_pts) { - if (decoder->first_frame) { - best_effort_pts = decoder->start_pts; - } else { - av_log(NULL, AV_LOG_WARNING, - "multiple pts < " - "start_pts; setting start pts " - "to 0"); - decoder->start_pts = 0; - } - } - - best_effort_pts -= decoder->start_pts; - - // Since the best effort pts came from the stream we use his - // time base - d_pts = best_effort_pts * av_q2d(decoder->stream->time_base); - decoder->predicted_pts = d_pts; - } else { - d_pts = decoder->predicted_pts; - } - - // Update our predicted pts to include the repeated picture count - // Our predicted pts clock is based on the codecs time base - estimated_frame_delay = av_frame_get_pkt_duration(frame) * - av_q2d(decoder->codec->time_base); - // Add repeat frame delay - estimated_frame_delay += - frame->repeat_pict / (1.0L / estimated_frame_delay); - - decoder->predicted_pts += estimated_frame_delay; - - return d_pts; -} - -bool ff_decoder_set_frame_drop_state(struct ff_decoder *decoder, - int64_t start_time, int64_t pts) -{ - if (pts != AV_NOPTS_VALUE) { - int64_t rescaled_pts = av_rescale_q( - pts, decoder->stream->time_base, AV_TIME_BASE_Q); - int64_t master_clock = av_gettime() - start_time; - - int64_t diff = master_clock - rescaled_pts; - - if (diff > (AV_TIME_BASE / 2)) { - decoder->codec->skip_frame = decoder->frame_drop; - decoder->codec->skip_idct = decoder->frame_drop; - decoder->codec->skip_loop_filter = decoder->frame_drop; - return true; - } else { - decoder->codec->skip_frame = AVDISCARD_DEFAULT; - decoder->codec->skip_idct = AVDISCARD_DEFAULT; - decoder->codec->skip_loop_filter = AVDISCARD_DEFAULT; - return false; - } - } - - return false; -} diff --git a/deps/libff/libff/ff-decoder.h b/deps/libff/libff/ff-decoder.h deleted file mode 100644 index 622223b49..000000000 --- a/deps/libff/libff/ff-decoder.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2015 John R. Bradley - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#pragma once - -#include "ff-callbacks.h" -#include "ff-circular-queue.h" -#include "ff-clock.h" -#include "ff-packet-queue.h" -#include "ff-timer.h" - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct ff_decoder { - AVCodecContext *codec; - AVStream *stream; - - pthread_t decoder_thread; - struct ff_timer refresh_timer; - - struct ff_callbacks *callbacks; - struct ff_packet_queue packet_queue; - struct ff_circular_queue frame_queue; - unsigned int packet_queue_size; - - double timer_next_wake; - double previous_pts; // previous decoded frame's pts - double previous_pts_diff; // previous decoded frame pts delay - double predicted_pts; // predicted pts of next frame - double current_pts; // pts of the most recently dispatched frame - int64_t current_pts_time; // clock time when current_pts was set - int64_t start_pts; - - bool hwaccel_decoder; - enum AVDiscard frame_drop; - struct ff_clock *clock; - enum ff_av_sync_type natural_sync_clock; - - bool first_frame; - bool eof; - bool abort; - bool finished; -}; - -typedef struct ff_decoder ff_decoder_t; - -struct ff_decoder *ff_decoder_init(AVCodecContext *codec_context, - AVStream *stream, - unsigned int packet_queue_size, - unsigned int frame_queue_size); -bool ff_decoder_start(struct ff_decoder *decoder); -void ff_decoder_free(struct ff_decoder *decoder); - -bool ff_decoder_full(struct ff_decoder *decoder); -bool ff_decoder_accept(struct ff_decoder *decoder, struct ff_packet *packet); - -double ff_decoder_clock(void *opaque); - -void ff_decoder_schedule_refresh(struct ff_decoder *decoder, int delay); -void ff_decoder_refresh(void *opaque); - -double ff_decoder_get_best_effort_pts(struct ff_decoder *decoder, - AVFrame *frame); - -bool ff_decoder_set_frame_drop_state(struct ff_decoder *decoder, - int64_t start_time, int64_t pts); - -#ifdef __cplusplus -} -#endif diff --git a/deps/libff/libff/ff-demuxer.c b/deps/libff/libff/ff-demuxer.c deleted file mode 100644 index f27148677..000000000 --- a/deps/libff/libff/ff-demuxer.c +++ /dev/null @@ -1,627 +0,0 @@ -/* - * Copyright (c) 2015 John R. Bradley - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ff-demuxer.h" - -#include -#include -#include -#include - -#include - -#include "ff-compat.h" - -#define DEFAULT_AV_SYNC_TYPE AV_SYNC_VIDEO_MASTER - -#define AUDIO_FRAME_QUEUE_SIZE 1 -#define VIDEO_FRAME_QUEUE_SIZE 1 - -#define AUDIO_PACKET_QUEUE_SIZE (5 * 16 * 1024) -#define VIDEO_PACKET_QUEUE_SIZE (5 * 256 * 1024) - -static void *demux_thread(void *opaque_demuxer); - -struct ff_demuxer *ff_demuxer_init() -{ - struct ff_demuxer *demuxer; - - av_register_all(); - avdevice_register_all(); - avfilter_register_all(); - avformat_network_init(); - - demuxer = av_mallocz(sizeof(struct ff_demuxer)); - if (demuxer == NULL) - return NULL; - - demuxer->clock.sync_type = DEFAULT_AV_SYNC_TYPE; - demuxer->options.frame_drop = AVDISCARD_DEFAULT; - demuxer->options.audio_frame_queue_size = AUDIO_FRAME_QUEUE_SIZE; - demuxer->options.video_frame_queue_size = VIDEO_FRAME_QUEUE_SIZE; - demuxer->options.audio_packet_queue_size = AUDIO_PACKET_QUEUE_SIZE; - demuxer->options.video_packet_queue_size = VIDEO_PACKET_QUEUE_SIZE; - demuxer->options.is_hw_decoding = false; - - return demuxer; -} - -bool ff_demuxer_open(struct ff_demuxer *demuxer, char *input, - char *input_format) -{ - int ret; - - demuxer->input = av_strdup(input); - if (input_format != NULL) - demuxer->input_format = av_strdup(input_format); - - ret = pthread_create(&demuxer->demuxer_thread, NULL, demux_thread, - demuxer); - return ret == 0; -} - -void ff_demuxer_free(struct ff_demuxer *demuxer) -{ - void *demuxer_thread_result; - - demuxer->abort = true; - - pthread_join(demuxer->demuxer_thread, &demuxer_thread_result); - - if (demuxer->input != NULL) - av_free(demuxer->input); - - if (demuxer->input_format != NULL) - av_free(demuxer->input_format); - - if (demuxer->audio_decoder != NULL) - ff_decoder_free(demuxer->audio_decoder); - - if (demuxer->video_decoder != NULL) - ff_decoder_free(demuxer->video_decoder); - - if (demuxer->format_context) - avformat_close_input(&demuxer->format_context); - - av_free(demuxer); -} - -void ff_demuxer_set_callbacks(struct ff_callbacks *callbacks, - ff_callback_frame frame, - ff_callback_format format, - ff_callback_initialize initialize, - ff_callback_frame frame_initialize, - ff_callback_frame frame_free, void *opaque) -{ - callbacks->opaque = opaque; - callbacks->frame = frame; - callbacks->format = format; - callbacks->initialize = initialize; - callbacks->frame_initialize = frame_initialize; - callbacks->frame_free = frame_free; -} - -static int demuxer_interrupted_callback(void *opaque) -{ - return opaque != NULL && ((struct ff_demuxer *)opaque)->abort; -} - -static double ff_external_clock(void *opaque) -{ - (void)opaque; - - return av_gettime() / 1000000.0; -} - -static bool set_clock_sync_type(struct ff_demuxer *demuxer) -{ - if (demuxer->video_decoder == NULL) { - if (demuxer->clock.sync_type == AV_SYNC_VIDEO_MASTER) - demuxer->clock.sync_type = AV_SYNC_AUDIO_MASTER; - } - - if (demuxer->audio_decoder == NULL) { - if (demuxer->clock.sync_type == AV_SYNC_AUDIO_MASTER) - demuxer->clock.sync_type = AV_SYNC_VIDEO_MASTER; - } - - switch (demuxer->clock.sync_type) { - case AV_SYNC_AUDIO_MASTER: - demuxer->clock.sync_clock = ff_decoder_clock; - demuxer->clock.opaque = demuxer->audio_decoder; - break; - case AV_SYNC_VIDEO_MASTER: - demuxer->clock.sync_clock = ff_decoder_clock; - demuxer->clock.opaque = demuxer->video_decoder; - break; - case AV_SYNC_EXTERNAL_MASTER: - demuxer->clock.sync_clock = ff_external_clock; - demuxer->clock.opaque = NULL; - break; - default: - return false; - } - - return true; -} - -AVHWAccel *find_hwaccel_codec(AVCodecContext *codec_context) -{ - AVHWAccel *hwaccel = NULL; - - while ((hwaccel = av_hwaccel_next(hwaccel)) != NULL) { - if (hwaccel->id == codec_context->codec_id && - (hwaccel->pix_fmt == AV_PIX_FMT_VDA_VLD || - hwaccel->pix_fmt == AV_PIX_FMT_DXVA2_VLD || - hwaccel->pix_fmt == AV_PIX_FMT_VAAPI_VLD)) { - return hwaccel; - } - } - - return NULL; -} - -enum AVPixelFormat get_hwaccel_format(struct AVCodecContext *s, - const enum AVPixelFormat *fmt) -{ - (void)s; - (void)fmt; - - // for now force output to common denominator - return AV_PIX_FMT_YUV420P; -} - -static bool initialize_decoder(struct ff_demuxer *demuxer, - AVCodecContext *codec_context, AVStream *stream, - bool hwaccel_decoder) -{ - switch (codec_context->codec_type) { - case AVMEDIA_TYPE_AUDIO: - demuxer->audio_decoder = ff_decoder_init( - codec_context, stream, - demuxer->options.audio_packet_queue_size, - demuxer->options.audio_frame_queue_size); - - demuxer->audio_decoder->hwaccel_decoder = hwaccel_decoder; - demuxer->audio_decoder->frame_drop = - demuxer->options.frame_drop; - demuxer->audio_decoder->natural_sync_clock = - AV_SYNC_AUDIO_MASTER; - demuxer->audio_decoder->callbacks = &demuxer->audio_callbacks; - - if (!ff_callbacks_format(&demuxer->audio_callbacks, - codec_context)) { - ff_decoder_free(demuxer->audio_decoder); - demuxer->audio_decoder = NULL; - return false; - } - - demuxer->audio_decoder = demuxer->audio_decoder; - return true; - - case AVMEDIA_TYPE_VIDEO: - demuxer->video_decoder = ff_decoder_init( - codec_context, stream, - demuxer->options.video_packet_queue_size, - demuxer->options.video_frame_queue_size); - - demuxer->video_decoder->hwaccel_decoder = hwaccel_decoder; - demuxer->video_decoder->frame_drop = - demuxer->options.frame_drop; - demuxer->video_decoder->natural_sync_clock = - AV_SYNC_VIDEO_MASTER; - demuxer->video_decoder->callbacks = &demuxer->video_callbacks; - - if (!ff_callbacks_format(&demuxer->video_callbacks, - codec_context)) { - ff_decoder_free(demuxer->video_decoder); - demuxer->video_decoder = NULL; - return false; - } - - return true; - default: - return false; - } -} - -typedef enum AVPixelFormat (*AVGetFormatCb)(struct AVCodecContext *s, - const enum AVPixelFormat *fmt); - -static bool find_decoder(struct ff_demuxer *demuxer, AVStream *stream) -{ - AVCodecContext *codec_context = NULL; - AVCodec *codec = NULL; - AVDictionary *options_dict = NULL; - int ret; - - bool hwaccel_decoder = false; - codec_context = stream->codec; - - // enable reference counted frames since we may have a buffer size - // > 1 - codec_context->refcounted_frames = 1; - - // png/tiff decoders have serious issues with multiple threads - if (codec_context->codec_id == AV_CODEC_ID_PNG || - codec_context->codec_id == AV_CODEC_ID_TIFF || - codec_context->codec_id == AV_CODEC_ID_JPEG2000 || - codec_context->codec_id == AV_CODEC_ID_WEBP) - codec_context->thread_count = 1; - - if (demuxer->options.is_hw_decoding) { - AVHWAccel *hwaccel = find_hwaccel_codec(codec_context); - - if (hwaccel) { - AVCodec *codec_vda = - avcodec_find_decoder_by_name(hwaccel->name); - - if (codec_vda != NULL) { - AVGetFormatCb original_get_format = - codec_context->get_format; - - codec_context->get_format = get_hwaccel_format; - codec_context->opaque = hwaccel; - - ret = avcodec_open2(codec_context, codec_vda, - &options_dict); - if (ret < 0) { - av_log(NULL, AV_LOG_WARNING, - "no hardware decoder found for" - " codec with id %d", - codec_context->codec_id); - codec_context->get_format = - original_get_format; - codec_context->opaque = NULL; - } else { - codec = codec_vda; - hwaccel_decoder = true; - } - } - } - } - - if (codec == NULL) { - if (codec_context->codec_id == AV_CODEC_ID_VP8) - codec = avcodec_find_decoder_by_name("libvpx"); - else if (codec_context->codec_id == AV_CODEC_ID_VP9) - codec = avcodec_find_decoder_by_name("libvpx-vp9"); - - if (!codec) - codec = avcodec_find_decoder(codec_context->codec_id); - if (codec == NULL) { - av_log(NULL, AV_LOG_WARNING, - "no decoder found for" - " codec with id %d", - codec_context->codec_id); - return false; - } - if (avcodec_open2(codec_context, codec, &options_dict) < 0) { - av_log(NULL, AV_LOG_WARNING, - "unable to open decoder" - " with codec id %d", - codec_context->codec_id); - return false; - } - } - - return initialize_decoder(demuxer, codec_context, stream, - hwaccel_decoder); -} - -void ff_demuxer_flush(struct ff_demuxer *demuxer) -{ - if (demuxer->video_decoder != NULL && - demuxer->video_decoder->stream != NULL) { - packet_queue_flush(&demuxer->video_decoder->packet_queue); - packet_queue_put_flush_packet( - &demuxer->video_decoder->packet_queue); - } - - if (demuxer->audio_decoder != NULL && - demuxer->audio_decoder->stream != NULL) { - packet_queue_flush(&demuxer->audio_decoder->packet_queue); - packet_queue_put_flush_packet( - &demuxer->audio_decoder->packet_queue); - } -} - -void ff_demuxer_reset(struct ff_demuxer *demuxer) -{ - struct ff_packet packet = {0}; - struct ff_clock *clock = ff_clock_init(); - clock->sync_type = demuxer->clock.sync_type; - clock->sync_clock = demuxer->clock.sync_clock; - clock->opaque = demuxer->clock.opaque; - - packet.clock = clock; - - if (demuxer->audio_decoder != NULL) { - ff_clock_retain(clock); - packet_queue_put(&demuxer->audio_decoder->packet_queue, - &packet); - } - - if (demuxer->video_decoder != NULL) { - ff_clock_retain(clock); - packet_queue_put(&demuxer->video_decoder->packet_queue, - &packet); - } -} - -static bool open_input(struct ff_demuxer *demuxer, - AVFormatContext **format_context) -{ - AVInputFormat *input_format = NULL; - - AVIOInterruptCB interrupted_callback; - interrupted_callback.callback = demuxer_interrupted_callback; - interrupted_callback.opaque = demuxer; - - *format_context = avformat_alloc_context(); - (*format_context)->interrupt_callback = interrupted_callback; - - if (demuxer->input_format != NULL) { - input_format = av_find_input_format(demuxer->input_format); - if (input_format == NULL) - av_log(NULL, AV_LOG_WARNING, - "unable to find input " - "format %s", - demuxer->input_format); - } - - if (avformat_open_input(format_context, demuxer->input, input_format, - &demuxer->options.custom_options) != 0) - return false; - - return avformat_find_stream_info(*format_context, NULL) >= 0; -} - -static inline void set_decoder_start_time(struct ff_decoder *decoder, - int64_t start_time) -{ - if (decoder) - decoder->start_pts = av_rescale_q(start_time, AV_TIME_BASE_Q, - decoder->stream->time_base); -} - -static bool find_and_initialize_stream_decoders(struct ff_demuxer *demuxer) -{ - AVFormatContext *format_context = demuxer->format_context; - unsigned int i; - AVStream *audio_stream = NULL; - AVStream *video_stream = NULL; - int64_t start_time = INT64_MAX; - - for (i = 0; i < format_context->nb_streams; i++) { - AVCodecContext *codec = format_context->streams[i]->codec; - - if (codec->codec_type == AVMEDIA_TYPE_VIDEO && !video_stream) - video_stream = format_context->streams[i]; - - if (codec->codec_type == AVMEDIA_TYPE_AUDIO && !audio_stream) - audio_stream = format_context->streams[i]; - } - - int default_stream_index = - av_find_default_stream_index(demuxer->format_context); - - if (default_stream_index >= 0) { - AVStream *stream = - format_context->streams[default_stream_index]; - - if (stream->codec->codec_type == AVMEDIA_TYPE_AUDIO) - demuxer->clock.sync_type = AV_SYNC_AUDIO_MASTER; - else if (stream->codec->codec_type == AVMEDIA_TYPE_VIDEO) - demuxer->clock.sync_type = AV_SYNC_VIDEO_MASTER; - } - - if (video_stream != NULL) - find_decoder(demuxer, video_stream); - - if (audio_stream != NULL) - find_decoder(demuxer, audio_stream); - - if (demuxer->video_decoder == NULL && demuxer->audio_decoder == NULL) { - return false; - } - - if (!set_clock_sync_type(demuxer)) { - return false; - } - - for (i = 0; i < format_context->nb_streams; i++) { - AVStream *st = format_context->streams[i]; - int64_t st_start_time; - - if (st->discard == AVDISCARD_ALL || - st->start_time == AV_NOPTS_VALUE) { - continue; - } - - st_start_time = av_rescale_q(st->start_time, st->time_base, - AV_TIME_BASE_Q); - start_time = FFMIN(start_time, st_start_time); - } - - if (format_context->start_time != AV_NOPTS_VALUE) { - if (start_time > format_context->start_time || - start_time == INT64_MAX) { - start_time = format_context->start_time; - } - } - - if (start_time != INT64_MAX) { - set_decoder_start_time(demuxer->video_decoder, start_time); - set_decoder_start_time(demuxer->audio_decoder, start_time); - } - - if (demuxer->audio_decoder != NULL) { - if (ff_callbacks_initialize(&demuxer->audio_callbacks)) { - ff_decoder_start(demuxer->audio_decoder); - } else { - ff_decoder_free(demuxer->audio_decoder); - demuxer->audio_decoder = NULL; - if (!set_clock_sync_type(demuxer)) - return false; - } - } - - if (demuxer->video_decoder != NULL) { - if (ff_callbacks_initialize(&demuxer->video_callbacks)) { - ff_decoder_start(demuxer->video_decoder); - } else { - ff_decoder_free(demuxer->video_decoder); - demuxer->video_decoder = NULL; - if (!set_clock_sync_type(demuxer)) - return false; - } - } - - return set_clock_sync_type(demuxer); -} - -static bool handle_seek(struct ff_demuxer *demuxer) -{ - int ret; - - if (demuxer->seek_request) { - AVStream *seek_stream = NULL; - int64_t seek_target = demuxer->seek_pos; - - if (demuxer->video_decoder != NULL) { - seek_stream = demuxer->video_decoder->stream; - - } else if (demuxer->audio_decoder != NULL) { - seek_stream = demuxer->audio_decoder->stream; - } - - if (seek_stream != NULL && - demuxer->format_context->duration != AV_NOPTS_VALUE) { - seek_target = av_rescale_q(seek_target, AV_TIME_BASE_Q, - seek_stream->time_base); - } - - ret = av_seek_frame(demuxer->format_context, 0, seek_target, - demuxer->seek_flags); - if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "unable to seek stream: %s", - av_err2str(ret)); - demuxer->seek_pos = 0; - demuxer->seek_request = false; - return false; - - } else { - if (demuxer->seek_flush) - ff_demuxer_flush(demuxer); - ff_demuxer_reset(demuxer); - } - - demuxer->seek_request = false; - } - return true; -} - -static void seek_beginning(struct ff_demuxer *demuxer) -{ - if (demuxer->format_context->duration == AV_NOPTS_VALUE) { - demuxer->seek_flags = AVSEEK_FLAG_FRAME; - demuxer->seek_pos = 0; - } else { - demuxer->seek_flags = AVSEEK_FLAG_BACKWARD; - demuxer->seek_pos = demuxer->format_context->start_time; - } - demuxer->seek_request = true; - demuxer->seek_flush = false; - av_log(NULL, AV_LOG_VERBOSE, "looping media %s", demuxer->input); -} - -static void *demux_thread(void *opaque) -{ - struct ff_demuxer *demuxer = (struct ff_demuxer *)opaque; - int result; - - struct ff_packet packet = {0}; - - if (!open_input(demuxer, &demuxer->format_context)) - goto fail; - - av_dump_format(demuxer->format_context, 0, demuxer->input, 0); - - if (!find_and_initialize_stream_decoders(demuxer)) - goto fail; - - ff_demuxer_reset(demuxer); - - while (!demuxer->abort) { - // failed to seek (looping?) - if (!handle_seek(demuxer)) - break; - - if (ff_decoder_full(demuxer->audio_decoder) || - ff_decoder_full(demuxer->video_decoder)) { - av_usleep(10 * 1000); // 10ms - continue; - } - - result = av_read_frame(demuxer->format_context, &packet.base); - if (result < 0) { - bool eof = false; - if (result == AVERROR_EOF) { - eof = true; - } else if (demuxer->format_context->pb != NULL) { - AVIOContext *io_context = - demuxer->format_context->pb; - if (io_context->error == 0) { - av_usleep(100 * 1000); // 100ms - continue; - } else { - if (io_context->eof_reached != 0) - eof = true; - } - } - - if (eof) { - if (demuxer->options.is_looping) { - seek_beginning(demuxer); - } else { - break; - } - continue; - } else { - av_log(NULL, AV_LOG_ERROR, - "av_read_frame() failed: %s", - av_err2str(result)); - break; - } - } - - if (ff_decoder_accept(demuxer->video_decoder, &packet)) - continue; - else if (ff_decoder_accept(demuxer->audio_decoder, &packet)) - continue; - else - av_free_packet(&packet.base); - } - if (demuxer->audio_decoder != NULL) - demuxer->audio_decoder->eof = true; - if (demuxer->video_decoder != NULL) - demuxer->video_decoder->eof = true; -fail: - demuxer->abort = true; - - return NULL; -} diff --git a/deps/libff/libff/ff-demuxer.h b/deps/libff/libff/ff-demuxer.h deleted file mode 100644 index f6aa1096f..000000000 --- a/deps/libff/libff/ff-demuxer.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2015 John R. Bradley - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#pragma once - -#include "ff-circular-queue.h" -#include "ff-decoder.h" -#include "ff-packet-queue.h" - -#include - -#define FF_DEMUXER_FAIL -1 -#define FF_DEMUXER_SUCCESS 1 - -#include "ff-callbacks.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct ff_demuxer_options { - int audio_packet_queue_size; - int video_packet_queue_size; - int audio_frame_queue_size; - int video_frame_queue_size; - bool is_hw_decoding; - bool is_looping; - enum AVDiscard frame_drop; - AVDictionary *custom_options; -}; - -typedef struct ff_demuxer_options ff_demuxer_options_t; - -struct ff_demuxer { - AVIOContext *io_context; - AVFormatContext *format_context; - - struct ff_clock clock; - - struct ff_demuxer_options options; - - struct ff_decoder *audio_decoder; - struct ff_callbacks audio_callbacks; - - struct ff_decoder *video_decoder; - struct ff_callbacks video_callbacks; - - pthread_t demuxer_thread; - - int64_t seek_pos; - bool seek_request; - int seek_flags; - bool seek_flush; - - bool abort; - - char *input; - char *input_format; -}; - -typedef struct ff_demuxer ff_demuxer_t; - -struct ff_demuxer *ff_demuxer_init(); -bool ff_demuxer_open(struct ff_demuxer *demuxer, char *input, - char *input_format); -void ff_demuxer_free(struct ff_demuxer *demuxer); - -void ff_demuxer_set_callbacks(struct ff_callbacks *callbacks, - ff_callback_frame frame, - ff_callback_format format, - ff_callback_initialize initialize, - ff_callback_frame frame_initialize, - ff_callback_frame frame_free, void *opaque); - -void ff_demuxer_flush(struct ff_demuxer *demuxer); - -#ifdef __cplusplus -} -#endif diff --git a/deps/libff/libff/ff-frame.h b/deps/libff/libff/ff-frame.h deleted file mode 100644 index 8c9c6c1af..000000000 --- a/deps/libff/libff/ff-frame.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2015 John R. Bradley - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#pragma once - -#include "ff-clock.h" - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct ff_frame { - AVFrame *frame; - struct ff_clock *clock; - double pts; - int64_t duration; -}; - -typedef struct ff_frame ff_frame_t; - -#ifdef __cplusplus -} -#endif diff --git a/deps/libff/libff/ff-packet-queue.c b/deps/libff/libff/ff-packet-queue.c deleted file mode 100644 index 40e4666c1..000000000 --- a/deps/libff/libff/ff-packet-queue.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2015 John R. Bradley - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ff-packet-queue.h" -#include "ff-compat.h" - -bool packet_queue_init(struct ff_packet_queue *q) -{ - memset(q, 0, sizeof(struct ff_packet_queue)); - - if (pthread_mutex_init(&q->mutex, NULL) != 0) - goto fail; - - if (pthread_cond_init(&q->cond, NULL) != 0) - goto fail1; - - av_init_packet(&q->flush_packet.base); - q->flush_packet.base.data = (uint8_t *)"FLUSH"; - - return true; - -fail1: - pthread_mutex_destroy(&q->mutex); -fail: - return false; -} - -void packet_queue_abort(struct ff_packet_queue *q) -{ - pthread_mutex_lock(&q->mutex); - q->abort = true; - pthread_cond_signal(&q->cond); - pthread_mutex_unlock(&q->mutex); -} - -void packet_queue_free(struct ff_packet_queue *q) -{ - packet_queue_flush(q); - - pthread_mutex_destroy(&q->mutex); - pthread_cond_destroy(&q->cond); - - av_free_packet(&q->flush_packet.base); -} - -int packet_queue_put(struct ff_packet_queue *q, struct ff_packet *packet) -{ - struct ff_packet_list *new_packet; - - new_packet = av_malloc(sizeof(struct ff_packet_list)); - - if (new_packet == NULL) - return FF_PACKET_FAIL; - - new_packet->packet = *packet; - new_packet->next = NULL; - - pthread_mutex_lock(&q->mutex); - - if (q->last_packet == NULL) - q->first_packet = new_packet; - else - q->last_packet->next = new_packet; - - q->last_packet = new_packet; - - q->count++; - q->total_size += new_packet->packet.base.size; - - pthread_cond_signal(&q->cond); - pthread_mutex_unlock(&q->mutex); - - return FF_PACKET_SUCCESS; -} - -int packet_queue_put_flush_packet(struct ff_packet_queue *q) -{ - return packet_queue_put(q, &q->flush_packet); -} - -int packet_queue_get(struct ff_packet_queue *q, struct ff_packet *packet, - bool block) -{ - struct ff_packet_list *potential_packet; - int return_status; - - pthread_mutex_lock(&q->mutex); - - while (true) { - potential_packet = q->first_packet; - - if (potential_packet != NULL) { - q->first_packet = potential_packet->next; - - if (q->first_packet == NULL) - q->last_packet = NULL; - - q->count--; - q->total_size -= potential_packet->packet.base.size; - *packet = potential_packet->packet; - av_free(potential_packet); - return_status = FF_PACKET_SUCCESS; - break; - - } else if (!block) { - return_status = FF_PACKET_EMPTY; - break; - - } else { - pthread_cond_wait(&q->cond, &q->mutex); - if (q->abort) { - return_status = FF_PACKET_FAIL; - break; - } - } - } - - pthread_mutex_unlock(&q->mutex); - - return return_status; -} - -void packet_queue_flush(struct ff_packet_queue *q) -{ - struct ff_packet_list *packet; - - pthread_mutex_lock(&q->mutex); - - for (packet = q->first_packet; packet != NULL; - packet = q->first_packet) { - q->first_packet = packet->next; - av_free_packet(&packet->packet.base); - if (packet->packet.clock != NULL) - ff_clock_release(&packet->packet.clock); - av_freep(&packet); - } - - q->last_packet = q->first_packet = NULL; - q->count = 0; - q->total_size = 0; - - pthread_mutex_unlock(&q->mutex); -} diff --git a/deps/libff/libff/ff-packet-queue.h b/deps/libff/libff/ff-packet-queue.h deleted file mode 100644 index febb18958..000000000 --- a/deps/libff/libff/ff-packet-queue.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2015 John R. Bradley - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#pragma once - -#include "ff-clock.h" - -#include -#include -#include - -#define FF_PACKET_FAIL -1 -#define FF_PACKET_EMPTY 0 -#define FF_PACKET_SUCCESS 1 - -#ifdef __cplusplus -extern "C" { -#endif - -struct ff_packet { - AVPacket base; - ff_clock_t *clock; -}; - -struct ff_packet_list { - struct ff_packet packet; - struct ff_packet_list *next; -}; - -struct ff_packet_queue { - struct ff_packet_list *first_packet; - struct ff_packet_list *last_packet; - pthread_mutex_t mutex; - pthread_cond_t cond; - struct ff_packet flush_packet; - int count; - unsigned int total_size; - bool abort; -}; - -typedef struct ff_packet_queue ff_packet_queue_t; - -bool packet_queue_init(struct ff_packet_queue *q); -void packet_queue_abort(struct ff_packet_queue *q); -void packet_queue_free(struct ff_packet_queue *q); -int packet_queue_put(struct ff_packet_queue *q, struct ff_packet *packet); -int packet_queue_put_flush_packet(struct ff_packet_queue *q); -int packet_queue_get(struct ff_packet_queue *q, struct ff_packet *packet, - bool block); - -void packet_queue_flush(struct ff_packet_queue *q); - -#ifdef __cplusplus -} -#endif diff --git a/deps/libff/libff/ff-threading-posix.c b/deps/libff/libff/ff-threading-posix.c deleted file mode 100644 index 6c7845b56..000000000 --- a/deps/libff/libff/ff-threading-posix.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2023 Lain Bailey - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ff-threading.h" - -long ff_atomic_inc_long(volatile long *val) -{ - return __sync_add_and_fetch(val, 1); -} - -long ff_atomic_dec_long(volatile long *val) -{ - return __sync_sub_and_fetch(val, 1); -} diff --git a/deps/libff/libff/ff-threading-windows.c b/deps/libff/libff/ff-threading-windows.c deleted file mode 100644 index 40b5837b0..000000000 --- a/deps/libff/libff/ff-threading-windows.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2023 Lain Bailey - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ff-threading.h" - -#define WIN32_LEAN_AND_MEAN -#include -#undef WIN32_LEAN_AND_MEAN - -long ff_atomic_inc_long(volatile long *val) -{ - return InterlockedIncrement(val); -} - -long ff_atomic_dec_long(volatile long *val) -{ - return InterlockedDecrement(val); -} diff --git a/deps/libff/libff/ff-threading.h b/deps/libff/libff/ff-threading.h deleted file mode 100644 index 70fdd3b73..000000000 --- a/deps/libff/libff/ff-threading.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2015 John R. Bradley - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -long ff_atomic_inc_long(volatile long *val); -long ff_atomic_dec_long(volatile long *val); - -#ifdef __cplusplus -} -#endif diff --git a/deps/libff/libff/ff-timer.c b/deps/libff/libff/ff-timer.c deleted file mode 100644 index e3ffa34b9..000000000 --- a/deps/libff/libff/ff-timer.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) 2015 John R. Bradley - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ff-timer.h" - -#include -#include -#include -#include - -static void *timer_thread(void *opaque) -{ - struct ff_timer *timer = (struct ff_timer *)opaque; - int ret; - - while (true) { - bool callback = false; - pthread_mutex_lock(&timer->mutex); - - if (timer->abort) { - pthread_mutex_unlock(&timer->mutex); - break; - } - - uint64_t current_time = av_gettime(); - if (current_time < timer->next_wake) { - struct timespec sleep_time = { - .tv_sec = timer->next_wake / AV_TIME_BASE, - .tv_nsec = (timer->next_wake % AV_TIME_BASE) * - 1000}; - - ret = pthread_cond_timedwait( - &timer->cond, &timer->mutex, &sleep_time); - if (ret != ETIMEDOUT) { - // failed to wait, just sleep - av_usleep((unsigned)(timer->next_wake - - current_time)); - } - - pthread_mutex_unlock(&timer->mutex); - continue; - - // we can be woken up merely to set a sooner wake time - - } else { - // no new next_wake, sleep until we get something - av_usleep(1000); - } - - // we woke up for some reason - current_time = av_gettime(); - if (timer->next_wake <= current_time || timer->needs_wake) { - callback = true; - timer->needs_wake = false; - } - - pthread_mutex_unlock(&timer->mutex); - - if (callback) - timer->callback(timer->opaque); - } - - return NULL; -} - -bool ff_timer_init(struct ff_timer *timer, ff_timer_callback callback, - void *opaque) -{ - memset(timer, 0, sizeof(struct ff_timer)); - timer->abort = false; - timer->callback = callback; - timer->opaque = opaque; - - if (pthread_mutexattr_init(&timer->mutexattr) != 0) - goto fail; - if (pthread_mutexattr_settype(&timer->mutexattr, - PTHREAD_MUTEX_RECURSIVE)) - goto fail1; - if (pthread_mutex_init(&timer->mutex, &timer->mutexattr) != 0) - goto fail1; - if (pthread_cond_init(&timer->cond, NULL) != 0) - goto fail2; - - if (pthread_create(&timer->timer_thread, NULL, timer_thread, timer) != - 0) - goto fail3; - - return true; - -fail3: - pthread_cond_destroy(&timer->cond); -fail2: - pthread_mutex_destroy(&timer->mutex); -fail1: - pthread_mutexattr_destroy(&timer->mutexattr); -fail: - return false; -} - -void ff_timer_free(struct ff_timer *timer) -{ - void *thread_result; - - assert(timer != NULL); - - pthread_mutex_lock(&timer->mutex); - timer->abort = true; - pthread_cond_signal(&timer->cond); - pthread_mutex_unlock(&timer->mutex); - - pthread_join(timer->timer_thread, &thread_result); - - pthread_mutex_destroy(&timer->mutex); - pthread_mutexattr_destroy(&timer->mutexattr); - pthread_cond_destroy(&timer->cond); -} - -void ff_timer_schedule(struct ff_timer *timer, uint64_t microseconds) -{ - uint64_t cur_time = av_gettime(); - uint64_t new_wake_time = cur_time + microseconds; - - pthread_mutex_lock(&timer->mutex); - - timer->needs_wake = true; - if (new_wake_time < timer->next_wake || cur_time > timer->next_wake) - timer->next_wake = new_wake_time; - - pthread_cond_signal(&timer->cond); - - pthread_mutex_unlock(&timer->mutex); -} diff --git a/deps/libff/libff/ff-timer.h b/deps/libff/libff/ff-timer.h deleted file mode 100644 index 7a6d45f7d..000000000 --- a/deps/libff/libff/ff-timer.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2015 John R. Bradley - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#pragma once - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef void (*ff_timer_callback)(void *opaque); - -struct ff_timer { - ff_timer_callback callback; - void *opaque; - - pthread_mutex_t mutex; - pthread_mutexattr_t mutexattr; - pthread_cond_t cond; - - pthread_t timer_thread; - uint64_t next_wake; - bool needs_wake; - - bool abort; -}; - -typedef struct ff_timer ff_timer_t; - -bool ff_timer_init(struct ff_timer *timer, ff_timer_callback callback, - void *opaque); -void ff_timer_free(struct ff_timer *timer); -void ff_timer_schedule(struct ff_timer *timer, uint64_t microseconds); - -#ifdef __cplusplus -} -#endif diff --git a/deps/libff/libff/ff-video-decoder.c b/deps/libff/libff/ff-video-decoder.c deleted file mode 100644 index 507e9a636..000000000 --- a/deps/libff/libff/ff-video-decoder.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) 2015 John R. Bradley - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ff-callbacks.h" -#include "ff-circular-queue.h" -#include "ff-clock.h" -#include "ff-decoder.h" -#include "ff-frame.h" -#include "ff-packet-queue.h" -#include "ff-timer.h" - -#include -#include - -#include - -#include "ff-compat.h" - -static bool queue_frame(struct ff_decoder *decoder, AVFrame *frame, - double best_effort_pts) -{ - struct ff_frame *queue_frame; - bool call_initialize; - - ff_circular_queue_wait_write(&decoder->frame_queue); - - if (decoder->abort) { - return false; - } - - queue_frame = ff_circular_queue_peek_write(&decoder->frame_queue); - - // Check if we need to communicate a different format has been received - // to any callbacks - AVCodecContext *codec = decoder->codec; - call_initialize = (queue_frame->frame == NULL || - queue_frame->frame->width != codec->width || - queue_frame->frame->height != codec->height || - queue_frame->frame->format != codec->pix_fmt); - - if (queue_frame->frame != NULL) { - // This shouldn't happen any more, the frames are freed in - // ff_decoder_refresh. - av_frame_free(&queue_frame->frame); - } - - queue_frame->frame = av_frame_clone(frame); - queue_frame->clock = ff_clock_retain(decoder->clock); - - if (call_initialize) - ff_callbacks_frame_initialize(queue_frame, decoder->callbacks); - - queue_frame->pts = best_effort_pts; - - ff_circular_queue_advance_write(&decoder->frame_queue, queue_frame); - - return true; -} - -void *ff_video_decoder_thread(void *opaque_video_decoder) -{ - struct ff_decoder *decoder = (struct ff_decoder *)opaque_video_decoder; - - struct ff_packet packet = {0}; - int complete; - AVFrame *frame = av_frame_alloc(); - int ret; - bool key_frame; - - while (!decoder->abort) { - if (decoder->eof) - ret = packet_queue_get(&decoder->packet_queue, &packet, - 0); - else - ret = packet_queue_get(&decoder->packet_queue, &packet, - 1); - - if (ret == FF_PACKET_EMPTY || ret == FF_PACKET_FAIL) { - // should we just use abort here? - break; - } - - if (packet.base.data == - decoder->packet_queue.flush_packet.base.data) { - avcodec_flush_buffers(decoder->codec); - continue; - } - - // We received a reset packet with a new clock - if (packet.clock != NULL) { - if (decoder->clock != NULL) - ff_clock_release(&decoder->clock); - decoder->clock = ff_clock_move(&packet.clock); - av_free_packet(&packet.base); - continue; - } - - int64_t start_time = ff_clock_start_time(decoder->clock); - key_frame = packet.base.flags & AV_PKT_FLAG_KEY; - - // We can only make decisions on keyframes for - // hw decoders (maybe just OSX?) - // For now, always make drop decisions on keyframes - bool frame_drop_check = key_frame; - // Must have a proper packet pts to drop frames here - frame_drop_check &= start_time != AV_NOPTS_VALUE; - - if (frame_drop_check) - ff_decoder_set_frame_drop_state(decoder, start_time, - packet.base.pts); - - avcodec_decode_video2(decoder->codec, frame, &complete, - &packet.base); - - // Did we get an entire video frame? This doesn't guarantee - // there is a picture to show for some codecs, but we still want - // to adjust our various internal clocks for the next frame - if (complete) { - // If we don't have a good PTS, try to guess based - // on last received PTS provided plus prediction - // This function returns a pts scaled to stream - // time base - double best_effort_pts = - ff_decoder_get_best_effort_pts(decoder, frame); - - queue_frame(decoder, frame, best_effort_pts); - av_frame_unref(frame); - } - - av_free_packet(&packet.base); - } - - if (decoder->clock != NULL) - ff_clock_release(&decoder->clock); - - av_frame_free(&frame); - - decoder->finished = true; - - return NULL; -}