History

Initial decoder implementation.

With minor contributions from: - Jean-Baptiste Kempf <jb@videolan.org> - Marvin Scholz <epirat07@gmail.com> - Hugo Beauzée-Luyssen <hugo@videolan.org>

Ronald S. Bultje committed 8 years ago

Commit e2892ff1 parent d32eb2d89 files · +30590 −2Browse files

Showing the changes to src/thread_task.c (1 of 89 files). Show all

Unified · Split

src/thread_task.c+137−0
@@ -0,0 +1,137 @@
1/*
2 * Copyright © 2018, VideoLAN and dav1d authors
3 * Copyright © 2018, Two Orioles, LLC
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice, this
10 * list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "config.h"
29
30#include "src/thread_task.h"
31
32void *dav1d_frame_task(void *const data) {
33 Dav1dFrameContext *const f = data;
34
35 for (;;) {
36 pthread_mutex_lock(&f->frame_thread.td.lock);
37 f->n_tile_data = 0;
38 int did_signal = 0;
39 while (!f->n_tile_data && !f->frame_thread.die) {
40 if (!did_signal) {
41 did_signal = 1;
42 pthread_cond_signal(&f->frame_thread.td.cond);
43 }
44 pthread_cond_wait(&f->frame_thread.td.cond,
45 &f->frame_thread.td.lock);
46 }
47 if (f->frame_thread.die) {
48 pthread_mutex_unlock(&f->frame_thread.td.lock);
49 break;
50 }
51 pthread_mutex_unlock(&f->frame_thread.td.lock);
52
53 decode_frame(f);
54 }
55
56 pthread_exit(NULL);
57 return NULL;
58}
59
60void *dav1d_tile_task(void *const data) {
61 Dav1dTileContext *const t = data;
62 struct FrameTileThreadData *const fttd = t->tile_thread.fttd;
63 const Dav1dFrameContext *const f = t->f;
64 const int tile_thread_idx = t - f->tc;
65 const uint64_t mask = 1ULL << tile_thread_idx;
66
67 for (;;) {
68 pthread_mutex_lock(&fttd->lock);
69 fttd->available |= mask;
70 int did_signal = 0;
71 while (!fttd->tasks_left && !t->tile_thread.die) {
72 if (!did_signal) {
73 did_signal = 1;
74 pthread_cond_signal(&fttd->icond);
75 }
76 pthread_cond_wait(&fttd->cond, &fttd->lock);
77 }
78 if (t->tile_thread.die) {
79 pthread_mutex_unlock(&fttd->lock);
80 break;
81 }
82 fttd->available &= ~mask;
83 const int task_idx = fttd->num_tasks - fttd->tasks_left--;
84 pthread_mutex_unlock(&fttd->lock);
85
86 if (f->frame_thread.pass == 1 || f->n_tc >= f->frame_hdr.tiling.cols) {
87 // we can (or in fact, if >, we need to) do full tile decoding.
88 // loopfilter happens in the main thread
89 Dav1dTileState *const ts = t->ts = &f->ts[task_idx];
90 for (t->by = ts->tiling.row_start; t->by < ts->tiling.row_end;
91 t->by += f->sb_step)
92 {
93 decode_tile_sbrow(t);
94
95 // signal progress
96 pthread_mutex_lock(&ts->tile_thread.lock);
97 atomic_store(&ts->progress, 1 + (t->by >> f->sb_shift));
98 pthread_cond_signal(&ts->tile_thread.cond);
99 pthread_mutex_unlock(&ts->tile_thread.lock);
100 }
101 } else {
102 const int sby = f->tile_thread.task_idx_to_sby_and_tile_idx[task_idx][0];
103 const int tile_idx = f->tile_thread.task_idx_to_sby_and_tile_idx[task_idx][1];
104 Dav1dTileState *const ts = &f->ts[tile_idx];
105
106 // the interleaved decoding can sometimes cause dependency issues
107 // if one part of the frame decodes signifcantly faster than others.
108 // Ideally, we'd "skip" tile_sbrows where dependencies are missing,
109 // and resume them later as dependencies are met. This also would
110 // solve the broadcast() below and allow us to use signal(). However,
111 // for now, we use linear dependency tracking because it's simpler.
112 if (atomic_load(&ts->progress) < sby) {
113 pthread_mutex_lock(&ts->tile_thread.lock);
114 while (atomic_load(&ts->progress) < sby)
115 pthread_cond_wait(&ts->tile_thread.cond,
116 &ts->tile_thread.lock);
117 pthread_mutex_unlock(&ts->tile_thread.lock);
118 }
119
120 // we need to interleave sbrow decoding for all tile cols in a
121 // tile row, since otherwise subsequent threads will be blocked
122 // waiting for the post-filter to complete
123 t->ts = ts;
124 t->by = sby << f->sb_shift;
125 decode_tile_sbrow(t);
126
127 // signal progress
128 pthread_mutex_lock(&ts->tile_thread.lock);
129 atomic_store(&ts->progress, 1 + sby);
130 pthread_cond_broadcast(&ts->tile_thread.cond);
131 pthread_mutex_unlock(&ts->tile_thread.lock);
132 }
133 }
134
135 pthread_exit(NULL);
136 return NULL;
137}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t