File npv/TODO changed (mode: 100644) (index 7fec801..ae774ef) |
|
1 |
|
do first:make seek/end/etc work again |
|
2 |
|
|
1 |
3 |
not ordered: |
not ordered: |
2 |
|
- make seek/end/etc work again |
|
3 |
4 |
- better/smoother/less drop/(correct?) video frame display strategy |
- better/smoother/less drop/(correct?) video frame display strategy |
4 |
5 |
- xcb(resize)/vulkan swapchain loss or "not optimal" ? (state re-factoring) |
- xcb(resize)/vulkan swapchain loss or "not optimal" ? (state re-factoring) |
5 |
6 |
- x11 map/unmap handling to: |
- x11 map/unmap handling to: |
|
... |
... |
not ordered: |
18 |
19 |
- "buffering" indicator |
- "buffering" indicator |
19 |
20 |
- subtitles |
- subtitles |
20 |
21 |
- osd (On Screen Display) |
- osd (On Screen Display) |
21 |
|
- use vulkan shaders (no glsl or hlsl), compute or not, in order to perform some yuvX pixel |
|
22 |
|
formats to srgb format conversions. do NOT use the vulkan yuvX samplers as |
|
23 |
|
they are mostly dirty hack tricks built into spirv translaters. |
|
|
22 |
|
- use vulkan shaders (no glsl or hlsl), compute or not, in order to perform |
|
23 |
|
some yuvX pixel formats to srgb format conversions. do NOT use the vulkan |
|
24 |
|
yuvX samplers as they are mostly dirty hack tricks built into spirv |
|
25 |
|
translaters. |
24 |
26 |
- vulkan thingy for better quality down/up scaling? |
- vulkan thingy for better quality down/up scaling? |
25 |
|
- actually off-loading alsa output and vulkan output to their thread? |
|
File npv/thdsws/local/code.frag.c changed (mode: 100644) (index 2028789..cc7d041) |
1 |
1 |
struct thdsws_ctx_private_t { |
struct thdsws_ctx_private_t { |
2 |
|
atomic_u32 futex; |
|
|
2 |
|
pthread_mutex_t mutex; |
|
3 |
|
u8 state; |
|
4 |
|
pthread_cond_t have_fr_to_scale; |
3 |
5 |
struct SwsContext *sws; |
struct SwsContext *sws; |
4 |
6 |
}; |
}; |
5 |
|
/* futex syscall does not have a libc wrapper */ |
|
6 |
|
static long futex(atomic_u32 *uaddr, long futex_op, long val) |
|
|
7 |
|
/*NSPC*/ |
|
8 |
|
static void state_lock(struct thdsws_ctx_private_t *ctx_priv) |
7 |
9 |
{ |
{ |
8 |
|
return syscall(SYS_futex, uaddr, futex_op, val, 0, 0, 0); |
|
|
10 |
|
int r; |
|
11 |
|
|
|
12 |
|
r = pthread_mutex_lock(&ctx_priv->mutex); |
|
13 |
|
if (r != 0) |
|
14 |
|
FATALTS("unable to lock the state\n"); |
|
15 |
|
} |
|
16 |
|
/*NSPC*/ |
|
17 |
|
static void state_unlock(struct thdsws_ctx_private_t *ctx_priv) |
|
18 |
|
{ |
|
19 |
|
int r; |
|
20 |
|
|
|
21 |
|
r = pthread_mutex_unlock(&ctx_priv->mutex); |
|
22 |
|
if (r != 0) |
|
23 |
|
FATALTS("unable to unlock the state\n"); |
9 |
24 |
} |
} |
10 |
25 |
static void do_work(struct thdsws_ctx_t *ctx, struct thdsws_ctx_private_t *ctx_priv) |
static void do_work(struct thdsws_ctx_t *ctx, struct thdsws_ctx_private_t *ctx_priv) |
11 |
26 |
{ |
{ |
|
... |
... |
static void do_work(struct thdsws_ctx_t *ctx, struct thdsws_ctx_private_t *ctx_p |
24 |
39 |
(uint8_t*const*)&ctx->scale.dst_slice, |
(uint8_t*const*)&ctx->scale.dst_slice, |
25 |
40 |
(int*)&ctx->scale.dst_stride); |
(int*)&ctx->scale.dst_stride); |
26 |
41 |
} |
} |
|
42 |
|
#define IDLE 0 |
|
43 |
|
#define RUNNING 1 |
27 |
44 |
static void worker(struct thdsws_ctx_t *ctx, |
static void worker(struct thdsws_ctx_t *ctx, |
28 |
45 |
struct thdsws_ctx_private_t *ctx_priv) |
struct thdsws_ctx_private_t *ctx_priv) |
29 |
46 |
{ |
{ |
30 |
|
long r; |
|
31 |
|
u32 futex_val; |
|
32 |
|
|
|
33 |
|
errno = 0; |
|
34 |
|
r = futex(&ctx_priv->futex, FUTEX_WAIT, IDLE); |
|
35 |
|
if (r == -1) { |
|
36 |
|
if (errno == EINTR || errno == EAGAIN) /* SIGSTOP/SIGCONT/etc */ |
|
37 |
|
return; |
|
38 |
|
FATALTSW("unable to wait on futex:%s\n", strerror(errno)); |
|
|
47 |
|
/* on entry the state must be locked */ |
|
48 |
|
if (ctx_priv->state == RUNNING) { |
|
49 |
|
state_unlock(ctx_priv); |
|
50 |
|
do_work(ctx, ctx_priv); |
|
51 |
|
state_lock(ctx_priv); |
|
52 |
|
ctx_priv->state = IDLE; |
39 |
53 |
} |
} |
|
54 |
|
/* state == IDLE */ |
|
55 |
|
loop { /* spurious IDLE protection */ |
|
56 |
|
int r; |
40 |
57 |
|
|
41 |
|
/* r == 0 */ |
|
42 |
|
|
|
43 |
|
/* internet says, double check for any spurious wakeup evt */ |
|
44 |
|
futex_val = atomic_load(&ctx_priv->futex); |
|
45 |
|
if (futex_val == IDLE) |
|
46 |
|
/* spurious wakeup */ |
|
47 |
|
return; |
|
48 |
|
do_work(ctx, ctx_priv); |
|
49 |
|
/* |
|
50 |
|
* XXX: the only location where the futex gets this value, apart from |
|
51 |
|
* _before_ the worker thread creation |
|
52 |
|
*/ |
|
53 |
|
atomic_store(&ctx_priv->futex, IDLE); |
|
|
58 |
|
/* while waiting the mutex is unlocked */ |
|
59 |
|
r = pthread_cond_wait(&ctx_priv->have_fr_to_scale, |
|
60 |
|
&ctx_priv->mutex); |
|
61 |
|
/* on exit the mutex is locked */ |
|
62 |
|
if (r != 0) |
|
63 |
|
FATALTSW("an error occured while waiting for a frame\n"); |
|
64 |
|
if (ctx_priv->state != IDLE) |
|
65 |
|
break; |
|
66 |
|
/* state == IDLE */ |
|
67 |
|
} |
54 |
68 |
} |
} |
|
69 |
|
#undef IDLE |
|
70 |
|
#undef RUNNING |
55 |
71 |
static void *worker_entry(void *arg) |
static void *worker_entry(void *arg) |
56 |
72 |
{ |
{ |
57 |
73 |
int r; |
int r; |
|
... |
... |
static void *worker_entry(void *arg) |
70 |
86 |
ctx = arg; |
ctx = arg; |
71 |
87 |
ctx_priv = ctx->private; |
ctx_priv = ctx->private; |
72 |
88 |
|
|
73 |
|
loop worker(ctx, ctx_priv); |
|
|
89 |
|
state_lock(ctx_priv); |
|
90 |
|
loop worker(ctx, ctx_priv); /* state must be locked on entry */ |
74 |
91 |
} |
} |
File npv/thdsws/main.c changed (mode: 100644) (index 25b44dd..1a7d68c) |
11 |
11 |
#include <stdatomic.h> |
#include <stdatomic.h> |
12 |
12 |
#include <unistd.h> |
#include <unistd.h> |
13 |
13 |
#include <time.h> |
#include <time.h> |
14 |
|
#include <sys/syscall.h> |
|
15 |
|
#include <linux/futex.h> |
|
16 |
14 |
#include "npv/c_fixing.h" |
#include "npv/c_fixing.h" |
17 |
15 |
#include "npv/global.h" |
#include "npv/global.h" |
18 |
16 |
#include "npv/thdsws/public.h" |
#include "npv/thdsws/public.h" |
|
22 |
20 |
/*----------------------------------------------------------------------------*/ |
/*----------------------------------------------------------------------------*/ |
23 |
21 |
#define FATALTS(fmt, ...) FATAL("scaler:" fmt, ##__VA_ARGS__) |
#define FATALTS(fmt, ...) FATAL("scaler:" fmt, ##__VA_ARGS__) |
24 |
22 |
#define FATALTSW(fmt, ...) FATAL("scaler worker:" fmt, ##__VA_ARGS__) |
#define FATALTSW(fmt, ...) FATAL("scaler worker:" fmt, ##__VA_ARGS__) |
25 |
|
#define IDLE 0 |
|
26 |
|
#define BUSY 1 |
|
27 |
23 |
/*----------------------------------------------------------------------------*/ |
/*----------------------------------------------------------------------------*/ |
28 |
24 |
#include "npv/thdsws/local/code.frag.c" |
#include "npv/thdsws/local/code.frag.c" |
29 |
25 |
#include "npv/thdsws/public/code.frag.c" |
#include "npv/thdsws/public/code.frag.c" |
30 |
26 |
/*----------------------------------------------------------------------------*/ |
/*----------------------------------------------------------------------------*/ |
31 |
27 |
#undef FATALTS |
#undef FATALTS |
32 |
28 |
#undef FATALTSW |
#undef FATALTSW |
33 |
|
#undef IDLE |
|
34 |
|
#undef BUSY |
|
35 |
29 |
/*----------------------------------------------------------------------------*/ |
/*----------------------------------------------------------------------------*/ |
36 |
30 |
#define CLEANUP |
#define CLEANUP |
37 |
31 |
#include "npv/namespace/ffmpeg.h" |
#include "npv/namespace/ffmpeg.h" |
File npv/thdsws/public/code.frag.c changed (mode: 100644) (index 2fb1bb9..92102bb) |
|
1 |
|
#define RUNNING 1 |
1 |
2 |
static void thdsws_run(struct thdsws_ctx_t *ctx) |
static void thdsws_run(struct thdsws_ctx_t *ctx) |
2 |
3 |
{ |
{ |
|
4 |
|
int r; |
3 |
5 |
struct thdsws_ctx_private_t *ctx_priv; |
struct thdsws_ctx_private_t *ctx_priv; |
4 |
6 |
|
|
5 |
7 |
ctx_priv = ctx->private; |
ctx_priv = ctx->private; |
6 |
|
atomic_store(&ctx_priv->futex, BUSY); |
|
7 |
|
loop { |
|
8 |
|
long r; |
|
9 |
8 |
|
|
10 |
|
errno = 0; |
|
11 |
|
r = futex(&ctx_priv->futex, FUTEX_WAKE, 1); |
|
12 |
|
if (r == -1) { |
|
13 |
|
if (errno == EAGAIN || errno == EINTR) |
|
14 |
|
continue; |
|
15 |
|
FATALTS("unable to wakeup the worker threads:%s\n", strerror(errno)); |
|
16 |
|
} |
|
17 |
|
if (r == 1) |
|
18 |
|
break; |
|
19 |
|
/* |
|
20 |
|
* r == 0 , |
|
21 |
|
* can happen if the worker thread is still initing and not |
|
22 |
|
* waiting on the futex yet or the worker thread did change its |
|
23 |
|
* state, but it is not waiting no the futex yet |
|
24 |
|
*/ |
|
25 |
|
} |
|
|
9 |
|
state_lock(ctx_priv); |
|
10 |
|
if (ctx_priv->state == RUNNING) |
|
11 |
|
FATALTS("the worker thread is already running, did you forget to wait for it to idle\n"); |
|
12 |
|
ctx_priv->state = RUNNING; |
|
13 |
|
state_unlock(ctx_priv); |
|
14 |
|
r = pthread_cond_signal(&ctx_priv->have_fr_to_scale); |
|
15 |
|
if (r != 0) |
|
16 |
|
FATALTS("unable to signal the worker thread a frame is to be scaled\n"); |
26 |
17 |
} |
} |
|
18 |
|
#undef RUNNING |
|
19 |
|
#define RUNNING 1 |
27 |
20 |
static bool thdsws_is_busy(struct thdsws_ctx_t *ctx) |
static bool thdsws_is_busy(struct thdsws_ctx_t *ctx) |
28 |
21 |
{ |
{ |
29 |
22 |
struct thdsws_ctx_private_t *ctx_priv; |
struct thdsws_ctx_private_t *ctx_priv; |
30 |
|
u32 futex_val; |
|
|
23 |
|
bool r; |
31 |
24 |
|
|
32 |
25 |
ctx_priv = ctx->private; |
ctx_priv = ctx->private; |
33 |
|
|
|
34 |
|
futex_val = atomic_load(&ctx_priv->futex); |
|
35 |
|
if (futex_val == IDLE) |
|
36 |
|
return false; |
|
37 |
|
return true; |
|
|
26 |
|
state_lock(ctx_priv); |
|
27 |
|
if (ctx_priv->state == RUNNING) |
|
28 |
|
r = true; |
|
29 |
|
else |
|
30 |
|
r = false; |
|
31 |
|
state_unlock(ctx_priv); |
|
32 |
|
return r; |
38 |
33 |
} |
} |
|
34 |
|
#undef RUNNING |
|
35 |
|
#define IDLE 0 |
39 |
36 |
static struct thdsws_ctx_t *thdsws_init_once(void) |
static struct thdsws_ctx_t *thdsws_init_once(void) |
40 |
37 |
{ |
{ |
41 |
38 |
int r; |
int r; |
|
... |
... |
static struct thdsws_ctx_t *thdsws_init_once(void) |
52 |
49 |
FATALTS("unable to allocate memory for private context\n"); |
FATALTS("unable to allocate memory for private context\n"); |
53 |
50 |
ctx->private = ctx_priv; |
ctx->private = ctx_priv; |
54 |
51 |
|
|
55 |
|
atomic_init(&ctx_priv->futex, IDLE); |
|
|
52 |
|
r = pthread_mutex_init(&ctx_priv->mutex, 0); |
|
53 |
|
if (r != 0) |
|
54 |
|
FATALTS("unable to create the state mutex\n"); |
|
55 |
|
r = pthread_cond_init(&ctx_priv->have_fr_to_scale, 0); |
|
56 |
|
if (r != 0) |
|
57 |
|
FATALTS("unable to create waiting condition\n"); |
56 |
58 |
|
|
57 |
59 |
r = pthread_attr_init(&attr); |
r = pthread_attr_init(&attr); |
58 |
60 |
if (r != 0) |
if (r != 0) |
|
... |
... |
static struct thdsws_ctx_t *thdsws_init_once(void) |
62 |
64 |
if (r != 0) |
if (r != 0) |
63 |
65 |
FATALTS("unable to set the worker thread attribute to detach mode\n"); |
FATALTS("unable to set the worker thread attribute to detach mode\n"); |
64 |
66 |
|
|
|
67 |
|
/* be really sure the entry state is correct _before_ thd creation */ |
|
68 |
|
ctx_priv->state = IDLE; |
65 |
69 |
r = pthread_create(&worker, &attr, &worker_entry, ctx); |
r = pthread_create(&worker, &attr, &worker_entry, ctx); |
66 |
70 |
if (r != 0) |
if (r != 0) |
67 |
71 |
FATALTS("unable to create the worker thread\n"); |
FATALTS("unable to create the worker thread\n"); |
68 |
72 |
pthread_attr_destroy(&attr); |
pthread_attr_destroy(&attr); |
69 |
73 |
return ctx; |
return ctx; |
70 |
74 |
} |
} |
|
75 |
|
#undef IDLE |
71 |
76 |
#define TIME_UNIT_NS 1000000 /* 1ms */ |
#define TIME_UNIT_NS 1000000 /* 1ms */ |
72 |
77 |
#define TIMEOUT_UNITS_N 100 /* 100 * 1 ms = 100 ms */ |
#define TIMEOUT_UNITS_N 100 /* 100 * 1 ms = 100 ms */ |
73 |
78 |
static void thdsws_wait_for_idle(struct thdsws_ctx_t *ctx) |
static void thdsws_wait_for_idle(struct thdsws_ctx_t *ctx) |
File npv/video/local/code.frag.c changed (mode: 100644) (index f43e609..5a0a591) |
... |
... |
static void init_once_local(void) |
12 |
12 |
blit_l[i].viewport.height = -1; |
blit_l[i].viewport.height = -1; |
13 |
13 |
++i; |
++i; |
14 |
14 |
} |
} |
|
15 |
|
receive_fr = avutil_video_fr_ref_alloc(); |
15 |
16 |
} |
} |
16 |
17 |
static void scaler_img_create(avutil_video_fr_ref_t *fr) |
static void scaler_img_create(avutil_video_fr_ref_t *fr) |
17 |
18 |
{ |
{ |
|
... |
... |
static void dec_a_grow(void) |
243 |
244 |
/* extract a fr ref, shift the a, push it back at the e, and unref its bufs */ |
/* extract a fr ref, shift the a, push it back at the e, and unref its bufs */ |
244 |
245 |
static void fr_drop(u16 fr) |
static void fr_drop(u16 fr) |
245 |
246 |
{ |
{ |
246 |
|
struct dec_fr_priv_t *fr_priv; |
|
|
247 |
|
struct dec_fr_priv_t *priv_save; |
247 |
248 |
avutil_video_fr_ref_t *save; |
avutil_video_fr_ref_t *save; |
248 |
249 |
|
|
249 |
|
fr_priv = dec_frs_p.priv_a[fr]; |
|
250 |
|
if (!fr_priv->was_qed_to_pe) |
|
|
250 |
|
priv_save = dec_frs_p.priv_a[fr]; |
|
251 |
|
if (!priv_save->was_qed_to_pe) |
251 |
252 |
WARNINGV("dropping undisplayed frame\n"); |
WARNINGV("dropping undisplayed frame\n"); |
252 |
253 |
save = dec_frs_p.a[fr]; |
save = dec_frs_p.a[fr]; |
253 |
254 |
avutil_video_fr_unref(save); |
avutil_video_fr_unref(save); |
|
255 |
|
memset(priv_save, 0, sizeof(*priv_save)); |
254 |
256 |
if (dec_frs_p.n > 1) { |
if (dec_frs_p.n > 1) { |
255 |
257 |
u16 e; |
u16 e; |
256 |
258 |
|
|
|
... |
... |
static void fr_drop(u16 fr) |
261 |
263 |
|
|
262 |
264 |
memmove(&dec_frs_p.priv_a[fr], &dec_frs_p.priv_a[fr + 1], |
memmove(&dec_frs_p.priv_a[fr], &dec_frs_p.priv_a[fr + 1], |
263 |
265 |
sizeof(*dec_frs_p.priv_a) * (e - (fr + 1))); |
sizeof(*dec_frs_p.priv_a) * (e - (fr + 1))); |
264 |
|
memset(dec_frs_p.priv_a[e - 1], 0, sizeof(**dec_frs_p.priv_a)); |
|
265 |
|
} else |
|
266 |
|
memset(dec_frs_p.priv_a[0], 0, sizeof(**dec_frs_p.priv_a)); |
|
|
266 |
|
dec_frs_p.priv_a[e - 1] = priv_save; |
|
267 |
|
} |
267 |
268 |
dec_frs_p.n--; |
dec_frs_p.n--; |
268 |
269 |
} |
} |
269 |
270 |
static void frs_drop(s64 now) |
static void frs_drop(s64 now) |
|
... |
... |
static void start_scaling(avutil_video_fr_ref_t *fr, |
525 |
526 |
scaler_p.ctx->scale.dst_slice = scaler_p.img.data; |
scaler_p.ctx->scale.dst_slice = scaler_p.img.data; |
526 |
527 |
scaler_p.ctx->scale.dst_stride = scaled_line_bytes_n; |
scaler_p.ctx->scale.dst_stride = scaled_line_bytes_n; |
527 |
528 |
thdsws_run(scaler_p.ctx); |
thdsws_run(scaler_p.ctx); |
528 |
|
dec_frs_p.being_scaled.fr = fr; |
|
529 |
|
dec_frs_p.being_scaled.fr_priv = fr_priv; |
|
530 |
529 |
} |
} |
531 |
530 |
static void timer_ack(void) |
static void timer_ack(void) |
532 |
531 |
{ |
{ |
File npv/video/main.c changed (mode: 100644) (index 0cbd7e2..0db8fe4) |
46 |
46 |
#define WARNINGVVK(fmt, ...) WARNINGVK("video:" fmt, ##__VA_ARGS__) |
#define WARNINGVVK(fmt, ...) WARNINGVK("video:" fmt, ##__VA_ARGS__) |
47 |
47 |
#define IF_FATALVVK(fmt, ...) IF_FATALVK("video:" fmt, ##__VA_ARGS__) |
#define IF_FATALVVK(fmt, ...) IF_FATALVK("video:" fmt, ##__VA_ARGS__) |
48 |
48 |
|
|
49 |
|
/* 4ms + ~5ms "scaling" ~ 100 frs per sec */ |
|
50 |
|
#define TIMER_INTERVAL_NSECS_N 4000000 |
|
|
49 |
|
#define TIMER_INTERVAL_NSECS_N 4000000 /* 4ms should be enough? */ |
51 |
50 |
/*----------------------------------------------------------------------------*/ |
/*----------------------------------------------------------------------------*/ |
52 |
51 |
#include "npv/video/local/state.frag.c" |
#include "npv/video/local/state.frag.c" |
53 |
52 |
/*----------------------------------------------------------------------------*/ |
/*----------------------------------------------------------------------------*/ |
File npv/video/public/code.frag.c changed (mode: 100644) (index e7b22d9..386bb83) |
... |
... |
static void timer_start(void) |
82 |
82 |
static u8 dec_fr_try_receive(void) |
static u8 dec_fr_try_receive(void) |
83 |
83 |
{ |
{ |
84 |
84 |
int r; |
int r; |
85 |
|
u16 fr; |
|
86 |
85 |
|
|
87 |
|
if (dec_frs_p.eof_receive) |
|
88 |
|
return EOF_DEC; |
|
89 |
|
if (dec_frs_p.n == dec_frs_p.n_max) |
|
90 |
|
dec_a_grow(); |
|
91 |
|
fr = dec_frs_p.n; |
|
92 |
|
r = avcodec_receive_video_fr(dec_ctx_p, dec_frs_p.a[fr]); |
|
|
86 |
|
dec_ctx_lock(); |
|
87 |
|
r = avcodec_receive_video_fr(dec_ctx_p, receive_fr); |
|
88 |
|
dec_ctx_unlock(); |
93 |
89 |
if (r == AVUTIL_AVERROR(EAGAIN)) |
if (r == AVUTIL_AVERROR(EAGAIN)) |
94 |
90 |
return AGAIN; |
return AGAIN; |
95 |
91 |
else if (r == 0) { |
else if (r == 0) { |
96 |
|
memset(dec_frs_p.priv_a[fr], 0, sizeof(**dec_frs_p.priv_a)); |
|
|
92 |
|
u16 last; |
|
93 |
|
|
|
94 |
|
dec_frs_lock(); |
|
95 |
|
if (dec_frs_p.n == dec_frs_p.n_max) |
|
96 |
|
dec_a_grow(); |
|
97 |
|
last = dec_frs_p.n; |
|
98 |
|
avutil_video_fr_ref_move(dec_frs_p.a[last], receive_fr); |
|
99 |
|
memset(dec_frs_p.priv_a[last], 0, sizeof(**dec_frs_p.priv_a)); |
97 |
100 |
++dec_frs_p.n; |
++dec_frs_p.n; |
|
101 |
|
dec_frs_unlock(); |
98 |
102 |
return HAVE_FR; |
return HAVE_FR; |
99 |
103 |
} else if (r == AVUTIL_AVERROR_EOF) { |
} else if (r == AVUTIL_AVERROR_EOF) { |
100 |
104 |
POUTVFF("last decoder frame reached (receiving)\n"); |
POUTVFF("last decoder frame reached (receiving)\n"); |
|
105 |
|
dec_frs_lock(); |
101 |
106 |
dec_frs_p.eof_receive = true; |
dec_frs_p.eof_receive = true; |
|
107 |
|
dec_frs_unlock(); |
102 |
108 |
return EOF_DEC; |
return EOF_DEC; |
103 |
109 |
} |
} |
104 |
110 |
FATALVFF("error while receiving frame from the decoder\n"); |
FATALVFF("error while receiving frame from the decoder\n"); |
|
... |
... |
static void dec_frs_receive_avail(void) { loop |
113 |
119 |
{ |
{ |
114 |
120 |
u8 r; |
u8 r; |
115 |
121 |
|
|
116 |
|
dec_frs_lock(); |
|
117 |
|
dec_ctx_lock(); |
|
118 |
122 |
r = dec_fr_try_receive(); |
r = dec_fr_try_receive(); |
119 |
|
dec_ctx_unlock(); |
|
120 |
|
dec_frs_unlock(); |
|
121 |
123 |
if (r == HAVE_FR) |
if (r == HAVE_FR) |
122 |
124 |
continue; |
continue; |
123 |
125 |
else if (r == AGAIN || r == EOF_DEC) |
else if (r == AGAIN || r == EOF_DEC) |
|
... |
... |
static void dec_frs_unlock(void) |
174 |
176 |
#define TS_FROM_CLK_OK 0 |
#define TS_FROM_CLK_OK 0 |
175 |
177 |
#define READY 0 |
#define READY 0 |
176 |
178 |
#define NOT_READY 1 |
#define NOT_READY 1 |
177 |
|
/* XXX: we do want to lock the frs q the least amount of time as possible */ |
|
|
179 |
|
/* |
|
180 |
|
* XXX: we do want to lock the frs q the least amount of time as possible. but |
|
181 |
|
* the main thd seems to have too much latency for the video output. may |
|
182 |
|
* need to move the video output to its own thd in the end. |
|
183 |
|
*/ |
178 |
184 |
static void timer_evt(void) |
static void timer_evt(void) |
179 |
185 |
{ |
{ |
180 |
186 |
u8 r; |
u8 r; |
|
... |
... |
static void timer_evt(void) |
207 |
213 |
return; |
return; |
208 |
214 |
scaler_is_busy = thdsws_is_busy(scaler_p.ctx); |
scaler_is_busy = thdsws_is_busy(scaler_p.ctx); |
209 |
215 |
if (!scaler_is_busy) { |
if (!scaler_is_busy) { |
|
216 |
|
/* the fr which was scaled may not be the selected one */ |
210 |
217 |
if (dec_frs_p.being_scaled.fr != NO_FR) { |
if (dec_frs_p.being_scaled.fr != NO_FR) { |
211 |
218 |
dec_frs_p.being_scaled.fr_priv->is_scaled = true; |
dec_frs_p.being_scaled.fr_priv->is_scaled = true; |
212 |
219 |
dec_frs_p.being_scaled.fr = NO_FR; |
dec_frs_p.being_scaled.fr = NO_FR; |
213 |
220 |
} |
} |
214 |
221 |
} |
} |
215 |
|
if (!fr_priv->is_scaled) { |
|
|
222 |
|
if (!fr_priv->is_scaled) { /* the selected fr */ |
216 |
223 |
if (scaler_is_busy) |
if (scaler_is_busy) |
217 |
224 |
return; |
return; |
218 |
225 |
start_scaling(fr, fr_priv, &scaler_dims_changed); |
start_scaling(fr, fr_priv, &scaler_dims_changed); |
|
226 |
|
dec_frs_p.being_scaled.fr = fr; |
|
227 |
|
dec_frs_p.being_scaled.fr_priv = fr_priv; |
219 |
228 |
return; |
return; |
220 |
229 |
} |
} |
221 |
230 |
r = swpchn_next_img(&swpchn_img); |
r = swpchn_next_img(&swpchn_img); |