History

First modification of multi-thread decoder

This is the first modification of VP8 multi-thread decoder, which uses same threads to decode macroblocks and then do loopfiltering for each frame. Inspired by Rob Clark, synchronization was done on every 8 macroblocks instead of every macroblock to reduce lock contention. Comparing with the original code, this implementation gave about 15%- 20% performance gain while decoding my test clips on a Core2 Quad platform (Linux). The work is not done yet. Test on other platforms are needed.

Yunqing Wang committed 16 years ago

Commit ba2e1071 parent 618c7d24 files · +532 −241Browse files

Unified · Split

4 files
  1. vp8/decoder/decoderthreading.h +1 −0
  2. vp8/decoder/onyxd_if.c +31 −0
  3. vp8/decoder/onyxd_int.h +7 −5
  4. vp8/decoder/threading.c +493 −236
vp8/decoder/decoderthreading.h+1−0
@@ -18,6 +18,7 @@ · 17 unmodified lines
18 18
19extern void vp8_mtdecode_mb_rows(VP8D_COMP *pbi,19extern void vp8_mtdecode_mb_rows(VP8D_COMP *pbi,
20 MACROBLOCKD *xd);20 MACROBLOCKD *xd);
21extern void vp8_mt_loop_filter_frame(VP8D_COMP *pbi);
21extern void vp8_stop_lfthread(VP8D_COMP *pbi);22extern void vp8_stop_lfthread(VP8D_COMP *pbi);
22extern void vp8_start_lfthread(VP8D_COMP *pbi);23extern void vp8_start_lfthread(VP8D_COMP *pbi);
23extern void vp8_decoder_remove_threads(VP8D_COMP *pbi);24extern void vp8_decoder_remove_threads(VP8D_COMP *pbi);
vp8/decoder/onyxd_if.c+31−0
@@ -367,6 +367,7 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign · 366 unmodified lines
367 return -1;367 return -1;
368 }368 }
369 369
370/*
370 if (!pbi->b_multithreaded_lf)371 if (!pbi->b_multithreaded_lf)
371 {372 {
372 struct vpx_usec_timer lpftimer;373 struct vpx_usec_timer lpftimer;
@@ -378,12 +379,42 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign · 5 unmodified lines
378 379
379 vpx_usec_timer_mark(&lpftimer);380 vpx_usec_timer_mark(&lpftimer);
380 pbi->time_loop_filtering += vpx_usec_timer_elapsed(&lpftimer);381 pbi->time_loop_filtering += vpx_usec_timer_elapsed(&lpftimer);
382 }else{
383 struct vpx_usec_timer lpftimer;
384 vpx_usec_timer_start(&lpftimer);
385 // Apply the loop filter if appropriate.
386
387 if (cm->filter_level > 0)
388 vp8_mt_loop_filter_frame(cm, &pbi->mb, cm->filter_level);
389
390 vpx_usec_timer_mark(&lpftimer);
391 pbi->time_loop_filtering += vpx_usec_timer_elapsed(&lpftimer);
381 }392 }
382 if (cm->filter_level > 0) {393 if (cm->filter_level > 0) {
383 cm->last_frame_type = cm->frame_type;394 cm->last_frame_type = cm->frame_type;
384 cm->last_filter_type = cm->filter_type;395 cm->last_filter_type = cm->filter_type;
385 cm->last_sharpness_level = cm->sharpness_level;396 cm->last_sharpness_level = cm->sharpness_level;
386 }397 }
398*/
399
400 if(pbi->common.filter_level)
401 {
402 struct vpx_usec_timer lpftimer;
403 vpx_usec_timer_start(&lpftimer);
404 // Apply the loop filter if appropriate.
405
406 if (pbi->b_multithreaded_lf && cm->multi_token_partition != ONE_PARTITION)
407 vp8_mt_loop_filter_frame(pbi); //cm, &pbi->mb, cm->filter_level);
408 else
409 vp8_loop_filter_frame(cm, &pbi->mb, cm->filter_level);
410
411 vpx_usec_timer_mark(&lpftimer);
412 pbi->time_loop_filtering += vpx_usec_timer_elapsed(&lpftimer);
413
414 cm->last_frame_type = cm->frame_type;
415 cm->last_filter_type = cm->filter_type;
416 cm->last_sharpness_level = cm->sharpness_level;
417 }
387 418
388 vp8_yv12_extend_frame_borders_ptr(cm->frame_to_show);419 vp8_yv12_extend_frame_borders_ptr(cm->frame_to_show);
389 420
vp8/decoder/onyxd_int.h+7−5
@@ -95,20 +95,22 @@ typedef struct VP8Decompressor · 94 unmodified lines
95 int current_mb_col_main;95 int current_mb_col_main;
96 int decoding_thread_count;96 int decoding_thread_count;
97 int allocated_decoding_thread_count;97 int allocated_decoding_thread_count;
98 int *current_mb_col; //Each row remembers its already decoded column.
99 int mt_baseline_filter_level[MAX_MB_SEGMENTS];
98 100
99 // variable for threading101 // variable for threading
100 DECLARE_ALIGNED(16, MACROBLOCKD, lpfmb);102 DECLARE_ALIGNED(16, MACROBLOCKD, lpfmb);
101#if CONFIG_MULTITHREAD103#if CONFIG_MULTITHREAD
102 pthread_t h_thread_lpf; // thread for postprocessing104 //pthread_t h_thread_lpf; // thread for postprocessing
103 sem_t h_event_lpf; // Event for post_proc completed105 sem_t h_event_end_lpf; // Event for post_proc completed
104 sem_t h_event_start_lpf;106 sem_t *h_event_start_lpf;
105#endif107#endif
106 MB_ROW_DEC *mb_row_di;108 MB_ROW_DEC *mb_row_di;
107 DECODETHREAD_DATA *de_thread_data;109 DECODETHREAD_DATA *de_thread_data;
108#if CONFIG_MULTITHREAD110#if CONFIG_MULTITHREAD
109 pthread_t *h_decoding_thread;111 pthread_t *h_decoding_thread;
110 sem_t *h_event_mbrdecoding;112 sem_t *h_event_start_decoding;
111 sem_t h_event_main;113 sem_t h_event_end_decoding;
112 // end of threading data114 // end of threading data
113#endif115#endif
114 vp8_reader *mbc;116 vp8_reader *mbc;
vp8/decoder/threading.c+493−236
@@ -23,6 +23,8 @@ · 22 unmodified lines
23#include "extend.h"23#include "extend.h"
24#include "vpx_ports/vpx_timer.h"24#include "vpx_ports/vpx_timer.h"
25 25
26#define MAX_ROWS 256
27
26extern void vp8_decode_mb_row(VP8D_COMP *pbi,28extern void vp8_decode_mb_row(VP8D_COMP *pbi,
27 VP8_COMMON *pc,29 VP8_COMMON *pc,
28 int mb_row,30 int mb_row,
@@ -31,11 +33,10 @@ extern void vp8_decode_mb_row(VP8D_COMP *pbi, · 2 unmodified lines
31extern void vp8_build_uvmvs(MACROBLOCKD *x, int fullpixel);33extern void vp8_build_uvmvs(MACROBLOCKD *x, int fullpixel);
32extern void vp8_decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd);34extern void vp8_decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd);
33 35
36void vp8_thread_loop_filter(VP8D_COMP *pbi, MB_ROW_DEC *mbrd, int ithread);
37
34void vp8_setup_decoding_thread_data(VP8D_COMP *pbi, MACROBLOCKD *xd, MB_ROW_DEC *mbrd, int count)38void vp8_setup_decoding_thread_data(VP8D_COMP *pbi, MACROBLOCKD *xd, MB_ROW_DEC *mbrd, int count)
35{39{
36
37
38
39#if CONFIG_MULTITHREAD40#if CONFIG_MULTITHREAD
40 VP8_COMMON *const pc = & pbi->common;41 VP8_COMMON *const pc = & pbi->common;
41 int i, j;42 int i, j;
@@ -46,8 +47,6 @@ void vp8_setup_decoding_thread_data(VP8D_COMP *pbi, MACROBLOCKD *xd, MB_ROW_DEC · 4 unmodified lines
46#if CONFIG_RUNTIME_CPU_DETECT47#if CONFIG_RUNTIME_CPU_DETECT
47 mbd->rtcd = xd->rtcd;48 mbd->rtcd = xd->rtcd;
48#endif49#endif
49
50
51 mbd->subpixel_predict = xd->subpixel_predict;50 mbd->subpixel_predict = xd->subpixel_predict;
52 mbd->subpixel_predict8x4 = xd->subpixel_predict8x4;51 mbd->subpixel_predict8x4 = xd->subpixel_predict8x4;
53 mbd->subpixel_predict8x8 = xd->subpixel_predict8x8;52 mbd->subpixel_predict8x8 = xd->subpixel_predict8x8;
@@ -82,6 +81,8 @@ void vp8_setup_decoding_thread_data(VP8D_COMP *pbi, MACROBLOCKD *xd, MB_ROW_DEC · 28 unmodified lines
82 }81 }
83 }82 }
84 83
84 for (i=0; i< pc->mb_rows; i++)
85 pbi->current_mb_col[i]=-1;
85#else86#else
86 (void) pbi;87 (void) pbi;
87 (void) xd;88 (void) xd;
@@ -90,6 +91,70 @@ void vp8_setup_decoding_thread_data(VP8D_COMP *pbi, MACROBLOCKD *xd, MB_ROW_DEC · 2 unmodified lines
90#endif91#endif
91}92}
92 93
94void vp8_setup_loop_filter_thread_data(VP8D_COMP *pbi, MACROBLOCKD *xd, MB_ROW_DEC *mbrd, int count)
95{
96#if CONFIG_MULTITHREAD
97 VP8_COMMON *const pc = & pbi->common;
98 int i, j;
99
100 for (i = 0; i < count; i++)
101 {
102 MACROBLOCKD *mbd = &mbrd[i].mbd;
103//#if CONFIG_RUNTIME_CPU_DETECT
104// mbd->rtcd = xd->rtcd;
105//#endif
106
107 //mbd->subpixel_predict = xd->subpixel_predict;
108 //mbd->subpixel_predict8x4 = xd->subpixel_predict8x4;
109 //mbd->subpixel_predict8x8 = xd->subpixel_predict8x8;
110 //mbd->subpixel_predict16x16 = xd->subpixel_predict16x16;
111 //mbd->gf_active_ptr = xd->gf_active_ptr;
112
113 mbd->mode_info = pc->mi - 1;
114 mbd->mode_info_context = pc->mi + pc->mode_info_stride * (i + 1);
115 mbd->mode_info_stride = pc->mode_info_stride;
116
117 //mbd->frame_type = pc->frame_type;
118 //mbd->frames_since_golden = pc->frames_since_golden;
119 //mbd->frames_till_alt_ref_frame = pc->frames_till_alt_ref_frame;
120
121 //mbd->pre = pc->yv12_fb[pc->lst_fb_idx];
122 //mbd->dst = pc->yv12_fb[pc->new_fb_idx];
123
124 //vp8_setup_block_dptrs(mbd);
125 //vp8_build_block_doffsets(mbd);
126 mbd->segmentation_enabled = xd->segmentation_enabled; //
127 mbd->mb_segement_abs_delta = xd->mb_segement_abs_delta; //
128 vpx_memcpy(mbd->segment_feature_data, xd->segment_feature_data, sizeof(xd->segment_feature_data)); //
129
130 //signed char ref_lf_deltas[MAX_REF_LF_DELTAS];
131 vpx_memcpy(mbd->ref_lf_deltas, xd->ref_lf_deltas, sizeof(xd->ref_lf_deltas));
132 //signed char mode_lf_deltas[MAX_MODE_LF_DELTAS];
133 vpx_memcpy(mbd->mode_lf_deltas, xd->mode_lf_deltas, sizeof(xd->mode_lf_deltas));
134 //unsigned char mode_ref_lf_delta_enabled;
135 //unsigned char mode_ref_lf_delta_update;
136 mbd->mode_ref_lf_delta_enabled = xd->mode_ref_lf_delta_enabled;
137 mbd->mode_ref_lf_delta_update = xd->mode_ref_lf_delta_update;
138
139 //mbd->mbmi.mode = DC_PRED;
140 //mbd->mbmi.uv_mode = DC_PRED;
141 //mbd->current_bc = &pbi->bc2;
142
143 //for (j = 0; j < 25; j++)
144 //{
145 // mbd->block[j].dequant = xd->block[j].dequant;
146 //}
147 }
148
149 for (i=0; i< pc->mb_rows; i++)
150 pbi->current_mb_col[i]=-1;
151#else
152 (void) pbi;
153 (void) xd;
154 (void) mbrd;
155 (void) count;
156#endif
157}
93 158
94THREAD_FUNCTION vp8_thread_decoding_proc(void *p_data)159THREAD_FUNCTION vp8_thread_decoding_proc(void *p_data)
95{160{
@@ -104,142 +169,145 @@ THREAD_FUNCTION vp8_thread_decoding_proc(void *p_data) · 8 unmodified lines
104 if (pbi->b_multithreaded_rd == 0)169 if (pbi->b_multithreaded_rd == 0)
105 break;170 break;
106 171
107 //if(WaitForSingleObject(pbi->h_event_mbrdecoding[ithread], INFINITE) == WAIT_OBJECT_0)172 //if(WaitForSingleObject(pbi->h_event_start_decoding[ithread], INFINITE) == WAIT_OBJECT_0)
108 if (sem_wait(&pbi->h_event_mbrdecoding[ithread]) == 0)173 if (sem_wait(&pbi->h_event_start_decoding[ithread]) == 0)
109 {174 {
110 if (pbi->b_multithreaded_rd == 0)175 if (pbi->b_multithreaded_rd == 0)
111 break;176 break;
112 else177 else
113 {178 {
114 VP8_COMMON *pc = &pbi->common;179 VP8_COMMON *pc = &pbi->common;
115 int mb_row = mbrd->mb_row;
116 MACROBLOCKD *xd = &mbrd->mbd;180 MACROBLOCKD *xd = &mbrd->mbd;
117 181
118 //printf("ithread:%d mb_row %d\n", ithread, mb_row);182 int mb_row;
119 int i;183 int num_part = 1 << pbi->common.multi_token_partition;
120 int recon_yoffset, recon_uvoffset;
121 int mb_col;
122 int ref_fb_idx = pc->lst_fb_idx;
123 int dst_fb_idx = pc->new_fb_idx;
124 int recon_y_stride = pc->yv12_fb[ref_fb_idx].y_stride;
125 int recon_uv_stride = pc->yv12_fb[ref_fb_idx].uv_stride;
126
127 volatile int *last_row_current_mb_col;184 volatile int *last_row_current_mb_col;
128 185
129 if (ithread > 0)186 for (mb_row = ithread+1; mb_row < pc->mb_rows; mb_row += (pbi->decoding_thread_count + 1))
130 last_row_current_mb_col = &pbi->mb_row_di[ithread-1].current_mb_col;
131 else
132 last_row_current_mb_col = &pbi->current_mb_col_main;
133
134 recon_yoffset = mb_row * recon_y_stride * 16;
135 recon_uvoffset = mb_row * recon_uv_stride * 8;
136 // reset above block coeffs
137
138 xd->above_context[Y1CONTEXT] = pc->above_context[Y1CONTEXT];
139 xd->above_context[UCONTEXT ] = pc->above_context[UCONTEXT];
140 xd->above_context[VCONTEXT ] = pc->above_context[VCONTEXT];
141 xd->above_context[Y2CONTEXT] = pc->above_context[Y2CONTEXT];
142 xd->left_context = mb_row_left_context;
143 vpx_memset(mb_row_left_context, 0, sizeof(mb_row_left_context));
144 xd->up_available = (mb_row != 0);
145
146 xd->mb_to_top_edge = -((mb_row * 16)) << 3;
147 xd->mb_to_bottom_edge = ((pc->mb_rows - 1 - mb_row) * 16) << 3;
148
149 for (mb_col = 0; mb_col < pc->mb_cols; mb_col++)
150 {187 {
151 188 int i;
152 while (mb_col > (*last_row_current_mb_col - 1) && *last_row_current_mb_col != pc->mb_cols - 1)189 int recon_yoffset, recon_uvoffset;
190 int mb_col;
191 int ref_fb_idx = pc->lst_fb_idx;
192 int dst_fb_idx = pc->new_fb_idx;
193 int recon_y_stride = pc->yv12_fb[ref_fb_idx].y_stride;
194 int recon_uv_stride = pc->yv12_fb[ref_fb_idx].uv_stride;
195
196 pbi->mb_row_di[ithread].mb_row = mb_row;
197 pbi->mb_row_di[ithread].mbd.current_bc = &pbi->mbc[mb_row%num_part];
198
199 last_row_current_mb_col = &pbi->current_mb_col[mb_row -1];
200
201 recon_yoffset = mb_row * recon_y_stride * 16;
202 recon_uvoffset = mb_row * recon_uv_stride * 8;
203 // reset above block coeffs
204
205 xd->above_context[Y1CONTEXT] = pc->above_context[Y1CONTEXT];
206 xd->above_context[UCONTEXT ] = pc->above_context[UCONTEXT];
207 xd->above_context[VCONTEXT ] = pc->above_context[VCONTEXT];
208 xd->above_context[Y2CONTEXT] = pc->above_context[Y2CONTEXT];
209 xd->left_context = mb_row_left_context;
210 vpx_memset(mb_row_left_context, 0, sizeof(mb_row_left_context));
211 xd->up_available = (mb_row != 0);
212
213 xd->mb_to_top_edge = -((mb_row * 16)) << 3;
214 xd->mb_to_bottom_edge = ((pc->mb_rows - 1 - mb_row) * 16) << 3;
215
216 for (mb_col = 0; mb_col < pc->mb_cols; mb_col++)
153 {217 {
154 x86_pause_hint();218 if ((mb_col & 7) == 0)
155 thread_sleep(0);219 {
156 }220 while (mb_col > (*last_row_current_mb_col - 8) && *last_row_current_mb_col != pc->mb_cols - 1)
221 {
222 x86_pause_hint();
223 thread_sleep(0);
224 }
225 }
157 226
158 // Take a copy of the mode and Mv information for this macroblock into the xd->mbmi227 // Take a copy of the mode and Mv information for this macroblock into the xd->mbmi
159 // the partition_bmi array is unused in the decoder, so don't copy it.228 // the partition_bmi array is unused in the decoder, so don't copy it.
160 vpx_memcpy(&xd->mbmi, &xd->mode_info_context->mbmi,229 vpx_memcpy(&xd->mbmi, &xd->mode_info_context->mbmi,
161 sizeof(MB_MODE_INFO) - sizeof(xd->mbmi.partition_bmi));230 sizeof(MB_MODE_INFO) - sizeof(xd->mbmi.partition_bmi));
162 231
163 if (xd->mbmi.mode == SPLITMV || xd->mbmi.mode == B_PRED)232 if (xd->mbmi.mode == SPLITMV || xd->mbmi.mode == B_PRED)
164 {
165 for (i = 0; i < 16; i++)
166 {233 {
167 BLOCKD *d = &xd->block[i];234 for (i = 0; i < 16; i++)
168 vpx_memcpy(&d->bmi, &xd->mode_info_context->bmi[i], sizeof(B_MODE_INFO));235 {
236 BLOCKD *d = &xd->block[i];
237 vpx_memcpy(&d->bmi, &xd->mode_info_context->bmi[i], sizeof(B_MODE_INFO));
238 }
169 }239 }
170 }
171
172 // Distance of Mb to the various image edges.
173 // These specified to 8th pel as they are always compared to values that are in 1/8th pel units
174 xd->mb_to_left_edge = -((mb_col * 16) << 3);
175 xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
176 240
177 xd->dst.y_buffer = pc->yv12_fb[dst_fb_idx].y_buffer + recon_yoffset;241 // Distance of Mb to the various image edges.
178 xd->dst.u_buffer = pc->yv12_fb[dst_fb_idx].u_buffer + recon_uvoffset;242 // These specified to 8th pel as they are always compared to values that are in 1/8th pel units
179 xd->dst.v_buffer = pc->yv12_fb[dst_fb_idx].v_buffer + recon_uvoffset;243 xd->mb_to_left_edge = -((mb_col * 16) << 3);
244 xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
180 245
181 xd->left_available = (mb_col != 0);246 xd->dst.y_buffer = pc->yv12_fb[dst_fb_idx].y_buffer + recon_yoffset;
247 xd->dst.u_buffer = pc->yv12_fb[dst_fb_idx].u_buffer + recon_uvoffset;
248 xd->dst.v_buffer = pc->yv12_fb[dst_fb_idx].v_buffer + recon_uvoffset;
182 249
183 // Select the appropriate reference frame for this MB250 xd->left_available = (mb_col != 0);
184 if (xd->mbmi.ref_frame == LAST_FRAME)
185 ref_fb_idx = pc->lst_fb_idx;
186 else if (xd->mbmi.ref_frame == GOLDEN_FRAME)
187 ref_fb_idx = pc->gld_fb_idx;
188 else
189 ref_fb_idx = pc->alt_fb_idx;
190 251
191 xd->pre.y_buffer = pc->yv12_fb[ref_fb_idx].y_buffer + recon_yoffset;252 // Select the appropriate reference frame for this MB
192 xd->pre.u_buffer = pc->yv12_fb[ref_fb_idx].u_buffer + recon_uvoffset;253 if (xd->mbmi.ref_frame == LAST_FRAME)
193 xd->pre.v_buffer = pc->yv12_fb[ref_fb_idx].v_buffer + recon_uvoffset;254 ref_fb_idx = pc->lst_fb_idx;
255 else if (xd->mbmi.ref_frame == GOLDEN_FRAME)
256 ref_fb_idx = pc->gld_fb_idx;
257 else
258 ref_fb_idx = pc->alt_fb_idx;
194 259
195 vp8_build_uvmvs(xd, pc->full_pixel);260 xd->pre.y_buffer = pc->yv12_fb[ref_fb_idx].y_buffer + recon_yoffset;
261 xd->pre.u_buffer = pc->yv12_fb[ref_fb_idx].u_buffer + recon_uvoffset;
262 xd->pre.v_buffer = pc->yv12_fb[ref_fb_idx].v_buffer + recon_uvoffset;
196 263
197 vp8_decode_macroblock(pbi, xd);264 vp8_build_uvmvs(xd, pc->full_pixel);
198 265
266 vp8_decode_macroblock(pbi, xd);
199 267
200 recon_yoffset += 16;268 recon_yoffset += 16;
201 recon_uvoffset += 8;269 recon_uvoffset += 8;
202 270
203 ++xd->mode_info_context; /* next mb */271 ++xd->mode_info_context; /* next mb */
204 272
205 xd->gf_active_ptr++; // GF useage flag for next MB273 xd->gf_active_ptr++; // GF useage flag for next MB
206 274
207 xd->above_context[Y1CONTEXT] += 4;275 xd->above_context[Y1CONTEXT] += 4;
208 xd->above_context[UCONTEXT ] += 2;276 xd->above_context[UCONTEXT ] += 2;
209 xd->above_context[VCONTEXT ] += 2;277 xd->above_context[VCONTEXT ] += 2;
210 xd->above_context[Y2CONTEXT] ++;278 xd->above_context[Y2CONTEXT] ++;
211 pbi->mb_row_di[ithread].current_mb_col = mb_col;
212 279
213 }280 //pbi->mb_row_di[ithread].current_mb_col = mb_col;
281 pbi->current_mb_col[mb_row] = mb_col;
282 }
214 283
215 // adjust to the next row of mbs284 // adjust to the next row of mbs
216 vp8_extend_mb_row(285 vp8_extend_mb_row(
217 &pc->yv12_fb[dst_fb_idx],286 &pc->yv12_fb[dst_fb_idx],
218 xd->dst.y_buffer + 16, xd->dst.u_buffer + 8, xd->dst.v_buffer + 8287 xd->dst.y_buffer + 16, xd->dst.u_buffer + 8, xd->dst.v_buffer + 8
219 );288 );
220 289
221 ++xd->mode_info_context; /* skip prediction column */290 ++xd->mode_info_context; /* skip prediction column */
222 291
223 // since we have multithread292 // since we have multithread
224 xd->mode_info_context += xd->mode_info_stride * pbi->decoding_thread_count;293 xd->mode_info_context += xd->mode_info_stride * pbi->decoding_thread_count;
225 294
226 //memcpy(&pbi->lpfmb, &pbi->mb, sizeof(pbi->mb));
227 if ((mb_row & 1) == 1)
228 {
229 pbi->last_mb_row_decoded = mb_row;295 pbi->last_mb_row_decoded = mb_row;
230 //printf("S%d", pbi->last_mb_row_decoded);
231 }
232
233 if (ithread == (pbi->decoding_thread_count - 1) || mb_row == pc->mb_rows - 1)
234 {
235 //SetEvent(pbi->h_event_main);
236 sem_post(&pbi->h_event_main);
237 296
238 }297 }
239 }298 }
240 }299 }
241 }300 // add this to each frame
301 if ((mbrd->mb_row == pbi->common.mb_rows-1) || ((mbrd->mb_row == pbi->common.mb_rows-2) && (pbi->common.mb_rows % (pbi->decoding_thread_count+1))==1))
302 {
303 //SetEvent(pbi->h_event_end_decoding);
304 sem_post(&pbi->h_event_end_decoding);
305 }
306
307 if ((pbi->b_multithreaded_lf) &&(pbi->common.filter_level))
308 vp8_thread_loop_filter(pbi, mbrd, ithread);
242 309
310 }
243#else311#else
244 (void) p_data;312 (void) p_data;
245#endif313#endif
@@ -247,96 +315,60 @@ THREAD_FUNCTION vp8_thread_decoding_proc(void *p_data) · 1 unmodified line
247 return 0 ;315 return 0 ;
248}316}
249 317
250THREAD_FUNCTION vp8_thread_loop_filter(void *p_data)318
319void vp8_thread_loop_filter(VP8D_COMP *pbi, MB_ROW_DEC *mbrd, int ithread)
251{320{
252#if CONFIG_MULTITHREAD321#if CONFIG_MULTITHREAD
253 VP8D_COMP *pbi = (VP8D_COMP *)p_data;
254 322
255 while (1)323 if (sem_wait(&pbi->h_event_start_lpf[ithread]) == 0)
256 {
257 if (pbi->b_multithreaded_lf == 0)
258 break;
259
260 //printf("before waiting for start_lpf\n");
261
262 //if(WaitForSingleObject(pbi->h_event_start_lpf, INFINITE) == WAIT_OBJECT_0)
263 if (sem_wait(&pbi->h_event_start_lpf) == 0)
264 {324 {
265 if (pbi->b_multithreaded_lf == 0) // we're shutting down325 // if (pbi->b_multithreaded_lf == 0) // we're shutting down ????
266 break;326 // break;
267 else327 // else
268 {328 {
269
270 VP8_COMMON *cm = &pbi->common;329 VP8_COMMON *cm = &pbi->common;
271 MACROBLOCKD *mbd = &pbi->lpfmb;330 MACROBLOCKD *mbd = &mbrd->mbd;
272 int default_filt_lvl = pbi->common.filter_level;331 int default_filt_lvl = pbi->common.filter_level;
273 332
274 YV12_BUFFER_CONFIG *post = &cm->yv12_fb[cm->new_fb_idx];333 YV12_BUFFER_CONFIG *post = cm->frame_to_show;
275 loop_filter_info *lfi = cm->lf_info;334 loop_filter_info *lfi = cm->lf_info;
276 int frame_type = cm->frame_type;335 //int frame_type = cm->frame_type;
277 336
278 int mb_row;337 int mb_row;
279 int mb_col;338 int mb_col;
280 339
281 int baseline_filter_level[MAX_MB_SEGMENTS];
282 int filter_level;340 int filter_level;
283 int alt_flt_enabled = mbd->segmentation_enabled;341 int alt_flt_enabled = mbd->segmentation_enabled;
284 342
285 int i;343 int i;
286 unsigned char *y_ptr, *u_ptr, *v_ptr;344 unsigned char *y_ptr, *u_ptr, *v_ptr;
287 345
288 volatile int *last_mb_row_decoded = &pbi->last_mb_row_decoded;346 volatile int *last_row_current_mb_col;
289
290 //MODE_INFO * this_mb_mode_info = cm->mi;
291 mbd->mode_info_context = cm->mi; // Point at base of Mb MODE_INFO list
292
293 // Note the baseline filter values for each segment
294 if (alt_flt_enabled)
295 {
296 for (i = 0; i < MAX_MB_SEGMENTS; i++)
297 {
298 if (mbd->mb_segement_abs_delta == SEGMENT_ABSDATA)
299 baseline_filter_level[i] = mbd->segment_feature_data[MB_LVL_ALT_LF][i];
300 else
301 {
302 baseline_filter_level[i] = default_filt_lvl + mbd->segment_feature_data[MB_LVL_ALT_LF][i];
303 baseline_filter_level[i] = (baseline_filter_level[i] >= 0) ? ((baseline_filter_level[i] <= MAX_LOOP_FILTER) ? baseline_filter_level[i] : MAX_LOOP_FILTER) : 0; // Clamp to valid range
304 }
305 }
306 }
307 else
308 {
309 for (i = 0; i < MAX_MB_SEGMENTS; i++)
310 baseline_filter_level[i] = default_filt_lvl;
311 }
312
313 // Initialize the loop filter for this frame.
314 if ((cm->last_filter_type != cm->filter_type) || (cm->last_sharpness_level != cm->sharpness_level))
315 vp8_init_loop_filter(cm);
316 else if (frame_type != cm->last_frame_type)
317 vp8_frame_init_loop_filter(lfi, frame_type);
318 347
319 // Set up the buffer pointers348 // Set up the buffer pointers
320 y_ptr = post->y_buffer;349 y_ptr = post->y_buffer + post->y_stride * 16 * (ithread +1);
321 u_ptr = post->u_buffer;350 u_ptr = post->u_buffer + post->uv_stride * 8 * (ithread +1);
322 v_ptr = post->v_buffer;351 v_ptr = post->v_buffer + post->uv_stride * 8 * (ithread +1);
323 352
324 // vp8_filter each macro block353 // vp8_filter each macro block
325 for (mb_row = 0; mb_row < cm->mb_rows; mb_row++)354 for (mb_row = ithread+1; mb_row < cm->mb_rows; mb_row+= (pbi->decoding_thread_count + 1))
326 {355 {
356 last_row_current_mb_col = &pbi->current_mb_col[mb_row -1];
327 357
328 while (mb_row >= *last_mb_row_decoded)
329 {
330 x86_pause_hint();
331 thread_sleep(0);
332 }
333
334 //printf("R%d", mb_row);
335 for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)358 for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
336 {359 {
337 int Segment = (alt_flt_enabled) ? mbd->mode_info_context->mbmi.segment_id : 0;360 int Segment = (alt_flt_enabled) ? mbd->mode_info_context->mbmi.segment_id : 0;
338 361
339 filter_level = baseline_filter_level[Segment];362 if ((mb_col & 7) == 0)
363 {
364 while (mb_col > (*last_row_current_mb_col-8) && *last_row_current_mb_col != cm->mb_cols - 1)
365 {
366 x86_pause_hint();
367 thread_sleep(0);
368 }
369 }
370
371 filter_level = pbi->mt_baseline_filter_level[Segment];
340 372
341 // Apply any context driven MB level adjustment373 // Apply any context driven MB level adjustment
342 vp8_adjust_mb_lf_value(mbd, &filter_level);374 vp8_adjust_mb_lf_value(mbd, &filter_level);
@@ -362,29 +394,28 @@ THREAD_FUNCTION vp8_thread_loop_filter(void *p_data) · 19 unmodified lines
362 v_ptr += 8;394 v_ptr += 8;
363 395
364 mbd->mode_info_context++; // step to next MB396 mbd->mode_info_context++; // step to next MB
365 397 pbi->current_mb_col[mb_row] = mb_col;
366 }398 }
367 399
368 y_ptr += post->y_stride * 16 - post->y_width;
369 u_ptr += post->uv_stride * 8 - post->uv_width;
370 v_ptr += post->uv_stride * 8 - post->uv_width;
371
372 mbd->mode_info_context++; // Skip border mb400 mbd->mode_info_context++; // Skip border mb
373 }
374 401
375 //printf("R%d\n", mb_row);402 y_ptr += post->y_stride * 16 * (pbi->decoding_thread_count + 1) - post->y_width;
376 // When done, signal main thread that ME is finished403 u_ptr += post->uv_stride * 8 * (pbi->decoding_thread_count + 1) - post->uv_width;
377 //SetEvent(pbi->h_event_lpf);404 v_ptr += post->uv_stride * 8 * (pbi->decoding_thread_count + 1) - post->uv_width;
378 sem_post(&pbi->h_event_lpf);
379 }
380 405
406 mbd->mode_info_context += pbi->decoding_thread_count * mbd->mode_info_stride; // Skip border mb
407 }
408 }
381 }409 }
382 }
383 410
411 // add this to each frame
412 if ((mbrd->mb_row == pbi->common.mb_rows-1) || ((mbrd->mb_row == pbi->common.mb_rows-2) && (pbi->common.mb_rows % (pbi->decoding_thread_count+1))==1))
413 {
414 sem_post(&pbi->h_event_end_lpf);
415 }
384#else416#else
385 (void) p_data;417 (void) pbi;
386#endif418#endif
387 return 0;
388}419}
389 420
390void vp8_decoder_create_threads(VP8D_COMP *pbi)421void vp8_decoder_create_threads(VP8D_COMP *pbi)
@@ -396,39 +427,38 @@ void vp8_decoder_create_threads(VP8D_COMP *pbi) · 5 unmodified lines
396 pbi->b_multithreaded_rd = 0;427 pbi->b_multithreaded_rd = 0;
397 pbi->b_multithreaded_lf = 0;428 pbi->b_multithreaded_lf = 0;
398 pbi->allocated_decoding_thread_count = 0;429 pbi->allocated_decoding_thread_count = 0;
399 core_count = (pbi->max_threads > 16) ? 16 : pbi->max_threads; //vp8_get_proc_core_count();430 core_count = (pbi->max_threads > 16) ? 16 : pbi->max_threads;
400 if (core_count > 1)
401 {
402 sem_init(&pbi->h_event_lpf, 0, 0);
403 sem_init(&pbi->h_event_start_lpf, 0, 0);
404 pbi->b_multithreaded_lf = 1;
405 pthread_create(&pbi->h_thread_lpf, 0, vp8_thread_loop_filter, (pbi));
406 }
407 431
408 if (core_count > 1)432 if (core_count > 1)
409 {433 {
410 pbi->b_multithreaded_rd = 1;434 pbi->b_multithreaded_rd = 1;
411 pbi->decoding_thread_count = core_count - 1;435 pbi->b_multithreaded_lf = 1; // this can be merged with pbi->b_multithreaded_rd ?
436 pbi->decoding_thread_count = core_count -1;
412 437
413 CHECK_MEM_ERROR(pbi->h_decoding_thread, vpx_malloc(sizeof(pthread_t) * pbi->decoding_thread_count));438 CHECK_MEM_ERROR(pbi->h_decoding_thread, vpx_malloc(sizeof(pthread_t) * pbi->decoding_thread_count));
414 CHECK_MEM_ERROR(pbi->h_event_mbrdecoding, vpx_malloc(sizeof(sem_t) * pbi->decoding_thread_count));439 CHECK_MEM_ERROR(pbi->h_event_start_decoding, vpx_malloc(sizeof(sem_t) * pbi->decoding_thread_count));
415 CHECK_MEM_ERROR(pbi->mb_row_di, vpx_memalign(32, sizeof(MB_ROW_DEC) * pbi->decoding_thread_count));440 CHECK_MEM_ERROR(pbi->mb_row_di, vpx_memalign(32, sizeof(MB_ROW_DEC) * pbi->decoding_thread_count));
416 vpx_memset(pbi->mb_row_di, 0, sizeof(MB_ROW_DEC) * pbi->decoding_thread_count);441 vpx_memset(pbi->mb_row_di, 0, sizeof(MB_ROW_DEC) * pbi->decoding_thread_count);
417 CHECK_MEM_ERROR(pbi->de_thread_data, vpx_malloc(sizeof(DECODETHREAD_DATA) * pbi->decoding_thread_count));442 CHECK_MEM_ERROR(pbi->de_thread_data, vpx_malloc(sizeof(DECODETHREAD_DATA) * pbi->decoding_thread_count));
418 443
444 CHECK_MEM_ERROR(pbi->current_mb_col, vpx_malloc(sizeof(int) * MAX_ROWS)); // pc->mb_rows));
445 CHECK_MEM_ERROR(pbi->h_event_start_lpf, vpx_malloc(sizeof(sem_t) * pbi->decoding_thread_count));
446
419 for (ithread = 0; ithread < pbi->decoding_thread_count; ithread++)447 for (ithread = 0; ithread < pbi->decoding_thread_count; ithread++)
420 {448 {
421 sem_init(&pbi->h_event_mbrdecoding[ithread], 0, 0);449 sem_init(&pbi->h_event_start_decoding[ithread], 0, 0);
450 sem_init(&pbi->h_event_start_lpf[ithread], 0, 0);
422 451
423 pbi->de_thread_data[ithread].ithread = ithread;452 pbi->de_thread_data[ithread].ithread = ithread;
424 pbi->de_thread_data[ithread].ptr1 = (void *)pbi;453 pbi->de_thread_data[ithread].ptr1 = (void *)pbi;
425 pbi->de_thread_data[ithread].ptr2 = (void *) &pbi->mb_row_di[ithread];454 pbi->de_thread_data[ithread].ptr2 = (void *) &pbi->mb_row_di[ithread];
426 455
427 pthread_create(&pbi->h_decoding_thread[ithread], 0, vp8_thread_decoding_proc, (&pbi->de_thread_data[ithread]));456 pthread_create(&pbi->h_decoding_thread[ithread], 0, vp8_thread_decoding_proc, (&pbi->de_thread_data[ithread]));
428
429 }457 }
430 458
431 sem_init(&pbi->h_event_main, 0, 0);459 sem_init(&pbi->h_event_end_decoding, 0, 0);
460 sem_init(&pbi->h_event_end_lpf, 0, 0);
461
432 pbi->allocated_decoding_thread_count = pbi->decoding_thread_count;462 pbi->allocated_decoding_thread_count = pbi->decoding_thread_count;
433 }463 }
434 464
@@ -443,39 +473,35 @@ void vp8_decoder_remove_threads(VP8D_COMP *pbi) · 8 unmodified lines
443 473
444 if (pbi->b_multithreaded_lf)474 if (pbi->b_multithreaded_lf)
445 {475 {
476 int i;
446 pbi->b_multithreaded_lf = 0;477 pbi->b_multithreaded_lf = 0;
447 sem_post(&pbi->h_event_start_lpf);478
448 pthread_join(pbi->h_thread_lpf, 0);479 for (i = 0; i < pbi->allocated_decoding_thread_count; i++)
449 sem_destroy(&pbi->h_event_start_lpf);480 sem_destroy(&pbi->h_event_start_lpf[i]);
481
482 sem_destroy(&pbi->h_event_end_lpf);
450 }483 }
451 484
452 //shutdown MB Decoding thread;485 //shutdown MB Decoding thread;
453 if (pbi->b_multithreaded_rd)486 if (pbi->b_multithreaded_rd)
454 {487 {
488 int i;
489
455 pbi->b_multithreaded_rd = 0;490 pbi->b_multithreaded_rd = 0;
491
456 // allow all threads to exit492 // allow all threads to exit
493 for (i = 0; i < pbi->allocated_decoding_thread_count; i++)
457 {494 {
458 int i;495 sem_post(&pbi->h_event_start_decoding[i]);
459 496 pthread_join(pbi->h_decoding_thread[i], NULL);
460 for (i = 0; i < pbi->allocated_decoding_thread_count; i++)
461 {
462
463 sem_post(&pbi->h_event_mbrdecoding[i]);
464 pthread_join(pbi->h_decoding_thread[i], NULL);
465 }
466 }497 }
467 {
468
469 int i;
470 for (i = 0; i < pbi->allocated_decoding_thread_count; i++)
471 {
472 sem_destroy(&pbi->h_event_mbrdecoding[i]);
473 }
474
475 498
499 for (i = 0; i < pbi->allocated_decoding_thread_count; i++)
500 {
501 sem_destroy(&pbi->h_event_start_decoding[i]);
476 }502 }
477 503
478 sem_destroy(&pbi->h_event_main);504 sem_destroy(&pbi->h_event_end_decoding);
479 505
480 if (pbi->h_decoding_thread)506 if (pbi->h_decoding_thread)
481 {507 {
@@ -483,10 +509,16 @@ void vp8_decoder_remove_threads(VP8D_COMP *pbi) · 1 unmodified line
483 pbi->h_decoding_thread = NULL;509 pbi->h_decoding_thread = NULL;
484 }510 }
485 511
486 if (pbi->h_event_mbrdecoding)512 if (pbi->h_event_start_decoding)
487 {513 {
488 vpx_free(pbi->h_event_mbrdecoding);514 vpx_free(pbi->h_event_start_decoding);
489 pbi->h_event_mbrdecoding = NULL;515 pbi->h_event_start_decoding = NULL;
516 }
517
518 if (pbi->h_event_start_lpf)
519 {
520 vpx_free(pbi->h_event_start_lpf);
521 pbi->h_event_start_lpf = NULL;
490 }522 }
491 523
492 if (pbi->mb_row_di)524 if (pbi->mb_row_di)
@@ -500,8 +532,13 @@ void vp8_decoder_remove_threads(VP8D_COMP *pbi) · 7 unmodified lines
500 vpx_free(pbi->de_thread_data);532 vpx_free(pbi->de_thread_data);
501 pbi->de_thread_data = NULL;533 pbi->de_thread_data = NULL;
502 }534 }
503 }
504 535
536 if (pbi->current_mb_col)
537 {
538 vpx_free(pbi->current_mb_col);
539 pbi->current_mb_col = NULL ;
540 }
541 }
505#else542#else
506 (void) pbi;543 (void) pbi;
507#endif544#endif
@@ -511,9 +548,12 @@ void vp8_decoder_remove_threads(VP8D_COMP *pbi) · 3 unmodified lines
511void vp8_start_lfthread(VP8D_COMP *pbi)548void vp8_start_lfthread(VP8D_COMP *pbi)
512{549{
513#if CONFIG_MULTITHREAD550#if CONFIG_MULTITHREAD
551 /*
514 memcpy(&pbi->lpfmb, &pbi->mb, sizeof(pbi->mb));552 memcpy(&pbi->lpfmb, &pbi->mb, sizeof(pbi->mb));
515 pbi->last_mb_row_decoded = 0;553 pbi->last_mb_row_decoded = 0;
516 sem_post(&pbi->h_event_start_lpf);554 sem_post(&pbi->h_event_start_lpf);
555 */
556 (void) pbi;
517#else557#else
518 (void) pbi;558 (void) pbi;
519#endif559#endif
@@ -522,14 +562,17 @@ void vp8_start_lfthread(VP8D_COMP *pbi) · 2 unmodified lines
522void vp8_stop_lfthread(VP8D_COMP *pbi)562void vp8_stop_lfthread(VP8D_COMP *pbi)
523{563{
524#if CONFIG_MULTITHREAD564#if CONFIG_MULTITHREAD
565 /*
525 struct vpx_usec_timer timer;566 struct vpx_usec_timer timer;
526 567
527 vpx_usec_timer_start(&timer);568 vpx_usec_timer_start(&timer);
528 569
529 sem_wait(&pbi->h_event_lpf);570 sem_wait(&pbi->h_event_end_lpf);
530 571
531 vpx_usec_timer_mark(&timer);572 vpx_usec_timer_mark(&timer);
532 pbi->time_loop_filtering += vpx_usec_timer_elapsed(&timer);573 pbi->time_loop_filtering += vpx_usec_timer_elapsed(&timer);
574 */
575 (void) pbi;
533#else576#else
534 (void) pbi;577 (void) pbi;
535#endif578#endif
@@ -545,49 +588,263 @@ void vp8_mtdecode_mb_rows(VP8D_COMP *pbi, · 9 unmodified lines
545 588
546 int ibc = 0;589 int ibc = 0;
547 int num_part = 1 << pbi->common.multi_token_partition;590 int num_part = 1 << pbi->common.multi_token_partition;
591 int i;
592 volatile int *last_row_current_mb_col = NULL;
548 593
549 vp8_setup_decoding_thread_data(pbi, xd, pbi->mb_row_di, pbi->decoding_thread_count);594 vp8_setup_decoding_thread_data(pbi, xd, pbi->mb_row_di, pbi->decoding_thread_count);
550 595
596 for (i = 0; i < pbi->decoding_thread_count; i++)
597 sem_post(&pbi->h_event_start_decoding[i]);
598
551 for (mb_row = 0; mb_row < pc->mb_rows; mb_row += (pbi->decoding_thread_count + 1))599 for (mb_row = 0; mb_row < pc->mb_rows; mb_row += (pbi->decoding_thread_count + 1))
552 {600 {
553 int i;601 int i;
554 pbi->current_mb_col_main = -1;
555 602
556 xd->current_bc = &pbi->mbc[ibc];603 xd->current_bc = &pbi->mbc[mb_row%num_part];
557 ibc++ ;
558 604
559 if (ibc == num_part)605 //vp8_decode_mb_row(pbi, pc, mb_row, xd);
560 ibc = 0;
561
562 for (i = 0; i < pbi->decoding_thread_count; i++)
563 {606 {
564 if ((mb_row + i + 1) >= pc->mb_rows)607 int i;
565 break;608 int recon_yoffset, recon_uvoffset;
609 int mb_col;
610 int ref_fb_idx = pc->lst_fb_idx;
611 int dst_fb_idx = pc->new_fb_idx;
612 int recon_y_stride = pc->yv12_fb[ref_fb_idx].y_stride;
613 int recon_uv_stride = pc->yv12_fb[ref_fb_idx].uv_stride;
614
615 // volatile int *last_row_current_mb_col = NULL;
616 if (mb_row > 0)
617 last_row_current_mb_col = &pbi->current_mb_col[mb_row -1];
618
619 vpx_memset(pc->left_context, 0, sizeof(pc->left_context));
620 recon_yoffset = mb_row * recon_y_stride * 16;
621 recon_uvoffset = mb_row * recon_uv_stride * 8;
622 // reset above block coeffs
623
624 xd->above_context[Y1CONTEXT] = pc->above_context[Y1CONTEXT];
625 xd->above_context[UCONTEXT ] = pc->above_context[UCONTEXT];
626 xd->above_context[VCONTEXT ] = pc->above_context[VCONTEXT];
627 xd->above_context[Y2CONTEXT] = pc->above_context[Y2CONTEXT];
628 xd->up_available = (mb_row != 0);
629
630 xd->mb_to_top_edge = -((mb_row * 16)) << 3;
631 xd->mb_to_bottom_edge = ((pc->mb_rows - 1 - mb_row) * 16) << 3;
632
633 for (mb_col = 0; mb_col < pc->mb_cols; mb_col++)
634 {
566 635
567 pbi->mb_row_di[i].mb_row = mb_row + i + 1;636 if ( mb_row > 0 && (mb_col & 7) == 0){
568 pbi->mb_row_di[i].mbd.current_bc = &pbi->mbc[ibc];637 //if ( mb_row > 0 ){
569 ibc++;638 while (mb_col > (*last_row_current_mb_col - 8) && *last_row_current_mb_col != pc->mb_cols - 1)
639 {
640 x86_pause_hint();
641 thread_sleep(0);
642 }
570 643
571 if (ibc == num_part)644 }
572 ibc = 0;
573 645
574 pbi->mb_row_di[i].current_mb_col = -1;646 // Take a copy of the mode and Mv information for this macroblock into the xd->mbmi
575 sem_post(&pbi->h_event_mbrdecoding[i]);647 // the partition_bmi array is unused in the decoder, so don't copy it.
576 }648 vpx_memcpy(&xd->mbmi, &xd->mode_info_context->mbmi,
649 sizeof(MB_MODE_INFO) - sizeof(xd->mbmi.partition_bmi));
650
651 if (xd->mbmi.mode == SPLITMV || xd->mbmi.mode == B_PRED)
652 {
653 for (i = 0; i < 16; i++)
654 {
655 BLOCKD *d = &xd->block[i];
656 vpx_memcpy(&d->bmi, &xd->mode_info_context->bmi[i], sizeof(B_MODE_INFO));
657 }
658 }
659
660 // Distance of Mb to the various image edges.
661 // These specified to 8th pel as they are always compared to values that are in 1/8th pel units
662 xd->mb_to_left_edge = -((mb_col * 16) << 3);
663 xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
664
665 xd->dst.y_buffer = pc->yv12_fb[dst_fb_idx].y_buffer + recon_yoffset;
666 xd->dst.u_buffer = pc->yv12_fb[dst_fb_idx].u_buffer + recon_uvoffset;
667 xd->dst.v_buffer = pc->yv12_fb[dst_fb_idx].v_buffer + recon_uvoffset;
668
669 xd->left_available = (mb_col != 0);
670
671 // Select the appropriate reference frame for this MB
672 if (xd->mbmi.ref_frame == LAST_FRAME)
673 ref_fb_idx = pc->lst_fb_idx;
674 else if (xd->mbmi.ref_frame == GOLDEN_FRAME)
675 ref_fb_idx = pc->gld_fb_idx;
676 else
677 ref_fb_idx = pc->alt_fb_idx;
678
679 xd->pre.y_buffer = pc->yv12_fb[ref_fb_idx].y_buffer + recon_yoffset;
680 xd->pre.u_buffer = pc->yv12_fb[ref_fb_idx].u_buffer + recon_uvoffset;
681 xd->pre.v_buffer = pc->yv12_fb[ref_fb_idx].v_buffer + recon_uvoffset;
682
683 vp8_build_uvmvs(xd, pc->full_pixel);
684
685 vp8_decode_macroblock(pbi, xd);
686
687 recon_yoffset += 16;
688 recon_uvoffset += 8;
689
690 ++xd->mode_info_context; /* next mb */
691
692 xd->gf_active_ptr++; // GF useage flag for next MB
693
694 xd->above_context[Y1CONTEXT] += 4;
695 xd->above_context[UCONTEXT ] += 2;
696 xd->above_context[VCONTEXT ] += 2;
697 xd->above_context[Y2CONTEXT] ++;
698
699 //pbi->current_mb_col_main = mb_col;
700 pbi->current_mb_col[mb_row] = mb_col;
701 }
702
703 // adjust to the next row of mbs
704 vp8_extend_mb_row(
705 &pc->yv12_fb[dst_fb_idx],
706 xd->dst.y_buffer + 16, xd->dst.u_buffer + 8, xd->dst.v_buffer + 8
707 );
577 708
578 vp8_decode_mb_row(pbi, pc, mb_row, xd);709 ++xd->mode_info_context; /* skip prediction column */
579 710
711 pbi->last_mb_row_decoded = mb_row;
712 }
580 xd->mode_info_context += xd->mode_info_stride * pbi->decoding_thread_count;713 xd->mode_info_context += xd->mode_info_stride * pbi->decoding_thread_count;
714 }
715
716 sem_wait(&pbi->h_event_end_decoding); // add back for each frame
717#else
718 (void) pbi;
719 (void) xd;
720#endif
721}
722
723
724void vp8_mt_loop_filter_frame( VP8D_COMP *pbi)
725{
726#if CONFIG_MULTITHREAD
727 VP8_COMMON *cm = &pbi->common;
728 MACROBLOCKD *mbd = &pbi->mb;
729 int default_filt_lvl = pbi->common.filter_level;
730
731 YV12_BUFFER_CONFIG *post = cm->frame_to_show;
732 loop_filter_info *lfi = cm->lf_info;
733 int frame_type = cm->frame_type;
734
735 int mb_row;
736 int mb_col;
737
738 int filter_level;
739 int alt_flt_enabled = mbd->segmentation_enabled;
740
741 int i;
742 unsigned char *y_ptr, *u_ptr, *v_ptr;
743
744 volatile int *last_row_current_mb_col=NULL;
745
746 vp8_setup_loop_filter_thread_data(pbi, mbd, pbi->mb_row_di, pbi->decoding_thread_count);
747
748 mbd->mode_info_context = cm->mi; // Point at base of Mb MODE_INFO list
749
750 // Note the baseline filter values for each segment
751 if (alt_flt_enabled)
752 {
753 for (i = 0; i < MAX_MB_SEGMENTS; i++)
754 {
755 // Abs value
756 if (mbd->mb_segement_abs_delta == SEGMENT_ABSDATA)
757 pbi->mt_baseline_filter_level[i] = mbd->segment_feature_data[MB_LVL_ALT_LF][i];
758 // Delta Value
759 else
760 {
761 pbi->mt_baseline_filter_level[i] = default_filt_lvl + mbd->segment_feature_data[MB_LVL_ALT_LF][i];
762 pbi->mt_baseline_filter_level[i] = (pbi->mt_baseline_filter_level[i] >= 0) ? ((pbi->mt_baseline_filter_level[i] <= MAX_LOOP_FILTER) ? pbi->mt_baseline_filter_level[i] : MAX_LOOP_FILTER) : 0; // Clamp to valid range
763 }
764 }
765 }
766 else
767 {
768 for (i = 0; i < MAX_MB_SEGMENTS; i++)
769 pbi->mt_baseline_filter_level[i] = default_filt_lvl;
770 }
771
772 // Initialize the loop filter for this frame.
773 if ((cm->last_filter_type != cm->filter_type) || (cm->last_sharpness_level != cm->sharpness_level))
774 vp8_init_loop_filter(cm);
775 else if (frame_type != cm->last_frame_type)
776 vp8_frame_init_loop_filter(lfi, frame_type);
777
778 for (i = 0; i < pbi->decoding_thread_count; i++)
779 sem_post(&pbi->h_event_start_lpf[i]);
780 // sem_post(&pbi->h_event_start_lpf);
781
782 // Set up the buffer pointers
783 y_ptr = post->y_buffer;
784 u_ptr = post->u_buffer;
785 v_ptr = post->v_buffer;
581 786
582 if (mb_row < pc->mb_rows - 1)787 // vp8_filter each macro block
788 for (mb_row = 0; mb_row < cm->mb_rows; mb_row+= (pbi->decoding_thread_count + 1))
789 {
790 if (mb_row > 0)
791 last_row_current_mb_col = &pbi->current_mb_col[mb_row -1];
792
793 for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
583 {794 {
584 sem_wait(&pbi->h_event_main);795 int Segment = (alt_flt_enabled) ? mbd->mode_info_context->mbmi.segment_id : 0;
796
797
798 if ( mb_row > 0 && (mb_col & 7) == 0){
799 // if ( mb_row > 0 ){
800 while (mb_col > (*last_row_current_mb_col-8) && *last_row_current_mb_col != cm->mb_cols - 1)
801 {
802 x86_pause_hint();
803 thread_sleep(0);
804 }
805 }
806
807 filter_level = pbi->mt_baseline_filter_level[Segment];
808
809 // Distance of Mb to the various image edges.
810 // These specified to 8th pel as they are always compared to values that are in 1/8th pel units
811 // Apply any context driven MB level adjustment
812 vp8_adjust_mb_lf_value(mbd, &filter_level);
813
814 if (filter_level)
815 {
816 if (mb_col > 0)
817 cm->lf_mbv(y_ptr, u_ptr, v_ptr, post->y_stride, post->uv_stride, &lfi[filter_level], cm->simpler_lpf);
818
819 if (mbd->mode_info_context->mbmi.dc_diff > 0)
820 cm->lf_bv(y_ptr, u_ptr, v_ptr, post->y_stride, post->uv_stride, &lfi[filter_level], cm->simpler_lpf);
821
822 // don't apply across umv border
823 if (mb_row > 0)
824 cm->lf_mbh(y_ptr, u_ptr, v_ptr, post->y_stride, post->uv_stride, &lfi[filter_level], cm->simpler_lpf);
825
826 if (mbd->mode_info_context->mbmi.dc_diff > 0)
827 cm->lf_bh(y_ptr, u_ptr, v_ptr, post->y_stride, post->uv_stride, &lfi[filter_level], cm->simpler_lpf);
828 }
829
830 y_ptr += 16;
831 u_ptr += 8;
832 v_ptr += 8;
833
834 mbd->mode_info_context++; // step to next MB
835 pbi->current_mb_col[mb_row] = mb_col;
585 }836 }
837 mbd->mode_info_context++; // Skip border mb
838
839 //update for multi-thread
840 y_ptr += post->y_stride * 16 * (pbi->decoding_thread_count + 1) - post->y_width;
841 u_ptr += post->uv_stride * 8 * (pbi->decoding_thread_count + 1) - post->uv_width;
842 v_ptr += post->uv_stride * 8 * (pbi->decoding_thread_count + 1) - post->uv_width;
843 mbd->mode_info_context += pbi->decoding_thread_count * mbd->mode_info_stride;
586 }844 }
587 845
588 pbi->last_mb_row_decoded = mb_row;846 sem_wait(&pbi->h_event_end_lpf);
589#else847#else
590 (void) pbi;848 (void) pbi;
591 (void) xd;
592#endif849#endif
593}850}

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