Преглед на файлове

deps-libff: Add master/slave deferred clock methods

Enables clocks to wait if the main sync clock has not been started yet.  An example of this is a video stream (video/audio) being synced to the video clock.  If an audio frame gets produced before the video clock has started it will wait.
John Bradley преди 10 години
родител
ревизия
6e42f38386
променени са 2 файла, в които са добавени 73 реда и са изтрити 0 реда
  1. 66 0
      deps/libff/libff/ff-clock.c
  2. 7 0
      deps/libff/libff/ff-clock.h

+ 66 - 0
deps/libff/libff/ff-clock.c

@@ -18,12 +18,78 @@
 #include "ff-threading.h"
 
 #include <libavutil/avutil.h>
+#include <libavutil/time.h>
+
+// 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(struct ff_clock *clock)
 {
 	clock = av_mallocz(sizeof(struct ff_clock));

+ 7 - 0
deps/libff/libff/ff-clock.h

@@ -20,6 +20,7 @@
 #define AV_NOSYNC_THRESHOLD 10.0
 
 #include <stdbool.h>
+#include <stdint.h>
 #include <pthread.h>
 
 enum ff_av_sync_type {
@@ -33,10 +34,12 @@ 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;
 };
@@ -48,3 +51,7 @@ 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);