Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/third_party/aom/av1/decoder/dthread.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
3
 *
4
 * This source code is subject to the terms of the BSD 2 Clause License and
5
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6
 * was not distributed with this source code in the LICENSE file, you can
7
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8
 * Media Patent License 1.0 was not distributed with this source code in the
9
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10
 */
11
12
#include "config/aom_config.h"
13
14
#include "aom_mem/aom_mem.h"
15
#include "av1/common/reconinter.h"
16
#include "av1/decoder/dthread.h"
17
#include "av1/decoder/decoder.h"
18
19
// #define DEBUG_THREAD
20
21
// TODO(hkuang): Clean up all the #ifdef in this file.
22
0
void av1_frameworker_lock_stats(AVxWorker *const worker) {
23
0
#if CONFIG_MULTITHREAD
24
0
  FrameWorkerData *const worker_data = worker->data1;
25
0
  pthread_mutex_lock(&worker_data->stats_mutex);
26
#else
27
  (void)worker;
28
#endif
29
}
30
31
0
void av1_frameworker_unlock_stats(AVxWorker *const worker) {
32
0
#if CONFIG_MULTITHREAD
33
0
  FrameWorkerData *const worker_data = worker->data1;
34
0
  pthread_mutex_unlock(&worker_data->stats_mutex);
35
#else
36
  (void)worker;
37
#endif
38
}
39
40
0
void av1_frameworker_signal_stats(AVxWorker *const worker) {
41
0
#if CONFIG_MULTITHREAD
42
0
  FrameWorkerData *const worker_data = worker->data1;
43
0
44
0
// TODO(hkuang): Fix the pthread_cond_broadcast in windows wrapper.
45
#if defined(_WIN32) && !HAVE_PTHREAD_H
46
  pthread_cond_signal(&worker_data->stats_cond);
47
#else
48
  pthread_cond_broadcast(&worker_data->stats_cond);
49
0
#endif
50
0
51
#else
52
  (void)worker;
53
#endif
54
}
55
56
// This macro prevents thread_sanitizer from reporting known concurrent writes.
57
#if defined(__has_feature)
58
#if __has_feature(thread_sanitizer)
59
#define BUILDING_WITH_TSAN
60
#endif
61
#endif
62
63
// TODO(hkuang): Remove worker parameter as it is only used in debug code.
64
void av1_frameworker_wait(AVxWorker *const worker, RefCntBuffer *const ref_buf,
65
0
                          int row) {
66
0
#if CONFIG_MULTITHREAD
67
0
  if (!ref_buf) return;
68
0
69
0
#ifndef BUILDING_WITH_TSAN
70
0
  // The following line of code will get harmless tsan error but it is the key
71
0
  // to get best performance.
72
0
  if (ref_buf->row >= row && ref_buf->buf.corrupted != 1) return;
73
0
#endif
74
0
75
0
  {
76
0
    // Find the worker thread that owns the reference frame. If the reference
77
0
    // frame has been fully decoded, it may not have owner.
78
0
    AVxWorker *const ref_worker = ref_buf->frame_worker_owner;
79
0
    FrameWorkerData *const ref_worker_data =
80
0
        (FrameWorkerData *)ref_worker->data1;
81
0
    const AV1Decoder *const pbi = ref_worker_data->pbi;
82
0
83
#ifdef DEBUG_THREAD
84
    {
85
      FrameWorkerData *const worker_data = (FrameWorkerData *)worker->data1;
86
      printf("%d %p worker is waiting for %d %p worker (%d)  ref %d \r\n",
87
             worker_data->worker_id, worker, ref_worker_data->worker_id,
88
             ref_buf->frame_worker_owner, row, ref_buf->row);
89
    }
90
#endif
91
92
0
    av1_frameworker_lock_stats(ref_worker);
93
0
    while (ref_buf->row < row && pbi->cur_buf == ref_buf &&
94
0
           ref_buf->buf.corrupted != 1) {
95
0
      pthread_cond_wait(&ref_worker_data->stats_cond,
96
0
                        &ref_worker_data->stats_mutex);
97
0
    }
98
0
99
0
    if (ref_buf->buf.corrupted == 1) {
100
0
      FrameWorkerData *const worker_data = (FrameWorkerData *)worker->data1;
101
0
      av1_frameworker_unlock_stats(ref_worker);
102
0
      aom_internal_error(&worker_data->pbi->common.error,
103
0
                         AOM_CODEC_CORRUPT_FRAME,
104
0
                         "Worker %p failed to decode frame", worker);
105
0
    }
106
0
    av1_frameworker_unlock_stats(ref_worker);
107
0
  }
108
#else
109
  (void)worker;
110
  (void)ref_buf;
111
  (void)row;
112
  (void)ref_buf;
113
#endif  // CONFIG_MULTITHREAD
114
}
115
116
0
void av1_frameworker_broadcast(RefCntBuffer *const buf, int row) {
117
0
#if CONFIG_MULTITHREAD
118
0
  AVxWorker *worker = buf->frame_worker_owner;
119
0
120
#ifdef DEBUG_THREAD
121
  {
122
    FrameWorkerData *const worker_data = (FrameWorkerData *)worker->data1;
123
    printf("%d %p worker decode to (%d) \r\n", worker_data->worker_id,
124
           buf->frame_worker_owner, row);
125
  }
126
#endif
127
128
0
  av1_frameworker_lock_stats(worker);
129
0
  buf->row = row;
130
0
  av1_frameworker_signal_stats(worker);
131
0
  av1_frameworker_unlock_stats(worker);
132
#else
133
  (void)buf;
134
  (void)row;
135
#endif  // CONFIG_MULTITHREAD
136
}
137
138
void av1_frameworker_copy_context(AVxWorker *const dst_worker,
139
0
                                  AVxWorker *const src_worker) {
140
0
#if CONFIG_MULTITHREAD
141
0
  FrameWorkerData *const src_worker_data = (FrameWorkerData *)src_worker->data1;
142
0
  FrameWorkerData *const dst_worker_data = (FrameWorkerData *)dst_worker->data1;
143
0
  AV1_COMMON *const src_cm = &src_worker_data->pbi->common;
144
0
  AV1_COMMON *const dst_cm = &dst_worker_data->pbi->common;
145
0
  int i;
146
0
147
0
  // Wait until source frame's context is ready.
148
0
  av1_frameworker_lock_stats(src_worker);
149
0
  while (!src_worker_data->frame_context_ready) {
150
0
    pthread_cond_wait(&src_worker_data->stats_cond,
151
0
                      &src_worker_data->stats_mutex);
152
0
  }
153
0
154
0
  dst_cm->last_frame_seg_map = src_cm->seg.enabled
155
0
                                   ? src_cm->current_frame_seg_map
156
0
                                   : src_cm->last_frame_seg_map;
157
0
  dst_worker_data->pbi->need_resync = src_worker_data->pbi->need_resync;
158
0
  av1_frameworker_unlock_stats(src_worker);
159
0
160
0
  dst_cm->seq_params.bit_depth = src_cm->seq_params.bit_depth;
161
0
  dst_cm->seq_params.use_highbitdepth = src_cm->seq_params.use_highbitdepth;
162
0
  // TODO(zoeliu): To handle parallel decoding
163
0
  dst_cm->prev_frame =
164
0
      src_cm->show_existing_frame ? src_cm->prev_frame : src_cm->cur_frame;
165
0
  dst_cm->last_width =
166
0
      !src_cm->show_existing_frame ? src_cm->width : src_cm->last_width;
167
0
  dst_cm->last_height =
168
0
      !src_cm->show_existing_frame ? src_cm->height : src_cm->last_height;
169
0
  dst_cm->seq_params.subsampling_x = src_cm->seq_params.subsampling_x;
170
0
  dst_cm->seq_params.subsampling_y = src_cm->seq_params.subsampling_y;
171
0
  dst_cm->frame_type = src_cm->frame_type;
172
0
  dst_cm->last_show_frame = !src_cm->show_existing_frame
173
0
                                ? src_cm->show_frame
174
0
                                : src_cm->last_show_frame;
175
0
  for (i = 0; i < REF_FRAMES; ++i)
176
0
    dst_cm->ref_frame_map[i] = src_cm->next_ref_frame_map[i];
177
0
178
0
  memcpy(dst_cm->lf_info.lfthr, src_cm->lf_info.lfthr,
179
0
         (MAX_LOOP_FILTER + 1) * sizeof(loop_filter_thresh));
180
0
  dst_cm->lf.sharpness_level = src_cm->lf.sharpness_level;
181
0
  dst_cm->lf.filter_level[0] = src_cm->lf.filter_level[0];
182
0
  dst_cm->lf.filter_level[1] = src_cm->lf.filter_level[1];
183
0
  memcpy(dst_cm->lf.ref_deltas, src_cm->lf.ref_deltas, REF_FRAMES);
184
0
  memcpy(dst_cm->lf.mode_deltas, src_cm->lf.mode_deltas, MAX_MODE_LF_DELTAS);
185
0
  dst_cm->seg = src_cm->seg;
186
0
  memcpy(dst_cm->frame_contexts, src_cm->frame_contexts,
187
0
         FRAME_CONTEXTS * sizeof(dst_cm->frame_contexts[0]));
188
#else
189
  (void)dst_worker;
190
  (void)src_worker;
191
#endif  // CONFIG_MULTITHREAD
192
}