diff libavcodec/cell/spe_mbd.c @ 2:897f711a7157

rearrange to work with autoconf
author Nina Engelhardt <nengel@mailbox.tu-berlin.de>
date Tue, 25 Sep 2012 15:55:33 +0200
parents
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/libavcodec/cell/spe_mbd.c	Tue Sep 25 15:55:33 2012 +0200
     1.3 @@ -0,0 +1,356 @@
     1.4 +/*
     1.5 + * Copyright (c) 2009 TUDelft 
     1.6 + * 
     1.7 + * Cell Parallel SPU - 2DWave Macroblock Decoding. 
     1.8 + */
     1.9 +
    1.10 +/**
    1.11 + * @file libavcodec/cell/spu/h264_main_spu.c
    1.12 + * Cell Parallel SPU - 2DWave Macroblock Decoding
    1.13 + * @author C C Chi <c.c.chi@student.tudelft.nl>
    1.14 + * 
    1.15 + * SIMD kernels 
    1.16 + * H.264/AVC motion compensation
    1.17 + * @author Mauricio Alvarez <alvarez@ac.upc.edu>
    1.18 + * @author Albert Paradis <apar7632@hotmail.com>
    1.19 + */ 
    1.20 +
    1.21 +
    1.22 +/* Enable this lines to enable simulator statistic or generate traces */
    1.23 +
    1.24 +//#define ENABLE_SIMULATOR
    1.25 +//#define ENABLE_PARAVER_TRACING_CELL
    1.26 +
    1.27 +#ifdef ENABLE_SIMULATOR
    1.28 +	#include "/opt/ibm/systemsim-cell/include/callthru/spu/profile.h"
    1.29 +#endif
    1.30 +
    1.31 +#ifdef ENABLE_TRACES
    1.32 +	#include "spu_trace.h"
    1.33 +#endif
    1.34 +#include <unistd.h>
    1.35 +#include <stdio.h>
    1.36 +#include <spu_intrinsics.h>
    1.37 +#include <spu_mfcio.h>
    1.38 +#include <libsync.h>
    1.39 +#include <sys/time.h>
    1.40 +#include <assert.h>
    1.41 +
    1.42 +//#include "dsputil_cell.h"
    1.43 +#include "types_spu.h"
    1.44 +#include "h264_intra_spu.h"
    1.45 +#include "h264_decode_mb_spu.h"
    1.46 +#include "h264_mc_spu.h"
    1.47 +#include "h264_tables.h"
    1.48 +#include "h264_dma.h"
    1.49 +
    1.50 +
    1.51 +/** functions for supporting tracing with paraver for the SPU 
    1.52 + *
    1.53 + */
    1.54 +inline void trace_init_SPU(){
    1.55 +#ifdef ENABLE_PARAVER_TRACING_CELL
    1.56 +	SPUtrace_init ();
    1.57 +#endif
    1.58 +}
    1.59 +
    1.60 +inline void trace_fini_SPU(){
    1.61 +#ifdef ENABLE_PARAVER_TRACING_CELL
    1.62 +	SPUtrace_fini ();
    1.63 +#endif
    1.64 +}
    1.65 +
    1.66 +inline void trace_event_SPU(int event, int id){
    1.67 +#ifdef ENABLE_PARAVER_TRACING_CELL
    1.68 +	SPUtrace_event (event, id);
    1.69 +#else
    1.70 +	(void) event;
    1.71 +	(void) id;
    1.72 +#endif
    1.73 +}
    1.74 +
    1.75 +// for simulator statistic
    1.76 +inline void clear_statistic(){
    1.77 +#ifdef ENABLE_SIMULATOR
    1.78 +	prof_clear();
    1.79 +#endif
    1.80 +}
    1.81 +
    1.82 +inline void start_statistic(){
    1.83 +#ifdef ENABLE_SIMULATOR
    1.84 +	prof_start();
    1.85 +#endif
    1.86 +}
    1.87 +
    1.88 +inline void stop_statistic(){
    1.89 +#ifdef ENABLE_SIMULATOR
    1.90 +	prof_stop();
    1.91 +#endif
    1.92 +}
    1.93 +
    1.94 +H264Context_spu h_context;  // struct that contain all the params to decode a macroblock
    1.95 +
    1.96 +DECLARE_ALIGNED_16(spe_pos, dma_temp); //dma temp for sending
    1.97 +//mb position of neighbouring spes
    1.98 +DECLARE_ALIGNED_16(volatile spe_pos, src_spe); //written by SPE_ID -1
    1.99 +//DECLARE_ALIGNED_16(spe_pos, tgt_spe); //written by SPE_ID +1
   1.100 +
   1.101 +/**	
   1.102 +*	Initializes the buffering of the mb data and associated mc data. The init_mb_buffer needs to 
   1.103 +*	be called before any get_next_mb and only once at the beginning of the slice.
   1.104 +*
   1.105 +*	Note: init_mc_buffer and get_next_mb expect the width of the picture to be more than 2 mb's
   1.106 +*/
   1.107 +#define TAG_OFFSET_MB MBD_buf1
   1.108 +#define TAG_OFFSET_MC MBD_mc_buf1
   1.109 +static void init_mb_buffer(H264Context_spu* h){
   1.110 +	H264slice *s = h->s;
   1.111 +	H264Mb *next_mb;
   1.112 +	int mb_height = s->mb_height;
   1.113 +	int mb_width = s->mb_width;
   1.114 +
   1.115 +	h->mc_idx =0;
   1.116 +	
   1.117 +	h->mb_dec = 0;
   1.118 +	h->mb_mc = 0;
   1.119 +	h->mb_dma = 0;
   1.120 +		
   1.121 +	h->curr_line %= mb_height;
   1.122 +	h->next_mb_idx = h->curr_line * mb_width;
   1.123 +	h->mb_id = h->curr_line * mb_width;
   1.124 +	h->n_mc= h->curr_line * mb_width;
   1.125 +	
   1.126 +	next_mb = s->blocks + h->mb_id;
   1.127 +	spu_dma_get(&h->mb_buf[h->mb_dma], (unsigned) next_mb, sizeof(H264Mb), h->mb_dma + TAG_OFFSET_MB);
   1.128 +	h->mb_dma++;
   1.129 +	h->mb_id++;
   1.130 +	
   1.131 +	next_mb = s->blocks + h->mb_id;
   1.132 +	spu_dma_get(&h->mb_buf[h->mb_dma], (unsigned) next_mb, sizeof(H264Mb), h->mb_dma + TAG_OFFSET_MB);
   1.133 +	h->mb_dma++;
   1.134 +	h->mb_id++;
   1.135 +	wait_dma_id(0 + TAG_OFFSET_MB);	
   1.136 +	
   1.137 +	H264Mb *mb = &h->mb_buf[0];
   1.138 +	H264mc *mc = &h->mc_buf[0];
   1.139 +	if(!IS_INTRA(mb->mb_type)){
   1.140 +		calc_mc_params(mb, mc);
   1.141 +		fill_ref_buf(h, mb, mc);
   1.142 +	}
   1.143 +	h->n_mc++;
   1.144 +	h->mb_mc++;
   1.145 +}
   1.146 +
   1.147 +static void *get_next_mb(H264Context_spu *h){
   1.148 +	H264slice *s = h->s;
   1.149 +	H264spe *spe = &h->spe;
   1.150 +	H264Mb *mb_buf = h->mb_buf;	
   1.151 +	H264mc *mc_buf = h->mc_buf;
   1.152 +	H264Mb *next_mb;
   1.153 +	H264Mb *next_dma_mb;
   1.154 +	
   1.155 +	if (h->curr_line >= s->mb_height)
   1.156 +		return NULL;
   1.157 +	
   1.158 +	if (h->mb_id < h->mb_total){
   1.159 +		next_dma_mb = s->blocks + h->mb_id;
   1.160 +		spu_dma_get(&mb_buf[h->mb_dma], (unsigned) next_dma_mb, sizeof(H264Mb), h->mb_dma + TAG_OFFSET_MB);
   1.161 +		h->mb_dma = (h->mb_dma+1)%3;
   1.162 +		h->mb_id++;
   1.163 +		if (h->mb_id%s->mb_width ==0){
   1.164 +			h->mb_id+=(spe->spe_total-1)*s->mb_width;			
   1.165 +		}
   1.166 +	}
   1.167 +	
   1.168 +	h->mc = &mc_buf[h->mc_idx];
   1.169 +	wait_dma_id(h->mc_idx + TAG_OFFSET_MC);
   1.170 +	h->mc_idx = (h->mc_idx+1)%2;
   1.171 +	if (h->n_mc < h->mb_total){
   1.172 +		wait_dma_id(h->mb_mc + TAG_OFFSET_MB);
   1.173 +		H264Mb *mb = &mb_buf[h->mb_mc];
   1.174 +		H264mc *mc = &mc_buf[h->mc_idx];
   1.175 +		if(!IS_INTRA(mb->mb_type)){
   1.176 +			calc_mc_params(mb, mc);
   1.177 +			fill_ref_buf(h, mb, mc);
   1.178 +		}
   1.179 +		h->n_mc++;
   1.180 +		if (h->n_mc%s->mb_width ==0){
   1.181 +			h->n_mc+=(spe->spe_total-1)*s->mb_width;			
   1.182 +		}
   1.183 +	}
   1.184 +	h->next_mb_idx++;
   1.185 +	if (h->next_mb_idx % s->mb_width ==0){
   1.186 +		h->next_mb_idx+=(spe->spe_total-1)*s->mb_width;
   1.187 +		h->curr_line+=spe->spe_total;		
   1.188 +	}
   1.189 +	
   1.190 +	h->mb_mc = (h->mb_mc+1)%3;	
   1.191 +	next_mb = &mb_buf[h->mb_dec];
   1.192 +	h->mb_dec = (h->mb_dec+1)%3;
   1.193 +	return next_mb;
   1.194 +}
   1.195 +
   1.196 +static void *get_next_mb_blocking(H264Context_spu *h){
   1.197 +	H264slice *s = h->s;
   1.198 +	H264spe *spe = &h->spe;
   1.199 +	H264Mb *mb_buf = h->mb_buf;
   1.200 +	H264mc *mc_buf = h->mc_buf;
   1.201 +	H264Mb *next_mb;
   1.202 +	H264Mb *next_dma_mb;
   1.203 +
   1.204 +	if (h->mb_id >= h->mb_total)
   1.205 +		return NULL;
   1.206 +
   1.207 +	//printf("%d\n", h->mb_id);
   1.208 +	next_dma_mb = s->blocks + h->mb_id;
   1.209 +	spu_dma_get(&mb_buf[0], (unsigned) next_dma_mb, sizeof(H264Mb), MBD_buf1);
   1.210 +	//h->mb_dma = (h->mb_dma+1)%3;
   1.211 +	h->mb_id++;
   1.212 +	if (h->mb_id%s->mb_width ==0){
   1.213 +		h->mb_id+=(spe->spe_total-1)*s->mb_width;
   1.214 +	}
   1.215 +	wait_dma_id(MBD_buf1);
   1.216 +
   1.217 +	h->mc = &mc_buf[0];	
   1.218 +	//h->mc_idx = (h->mc_idx+1)%2;
   1.219 +	//if (h->n_mc < h->mb_total){
   1.220 +	H264Mb *mb = &mb_buf[0];
   1.221 +	H264mc *mc = &mc_buf[0];
   1.222 +	if(!IS_INTRA(mb->mb_type)){
   1.223 +		calc_mc_params(mb, mc);
   1.224 +		fill_ref_buf(h, mb, mc);
   1.225 +	}
   1.226 +	//h->n_mc++;
   1.227 +	/*if (h->n_mc%s->mb_width ==0){
   1.228 +		h->n_mc+=(spe->spe_total-1)*s->mb_width;
   1.229 +	}*/	
   1.230 +//	wait_dma_id(MBD_mc_buf1);
   1.231 +
   1.232 +// 	h->next_mb_idx++;
   1.233 +// 	if (h->next_mb_idx % s->mb_width ==0){
   1.234 +// 		h->next_mb_idx+=(spe->spe_total-1)*s->mb_width;
   1.235 +// 		h->curr_line+=spe->spe_total;
   1.236 +// 	}
   1.237 +
   1.238 +// 	h->mb_mc = (h->mb_mc+1)%3;
   1.239 +	next_mb = &mb_buf[0];
   1.240 +// 	h->mb_dec = (h->mb_dec+1)%3;
   1.241 +	return next_mb;
   1.242 +}
   1.243 +
   1.244 +
   1.245 +#undef TAG_OFFSET_MB
   1.246 +#undef TAG_OFFSET_MC
   1.247 +static inline int dep_resolved(H264Context_spu *h){
   1.248 +	H264slice *s = h->s;
   1.249 +	int spe_id = h->spe.spe_id;
   1.250 +	volatile int mb_proc_dep = src_spe.count;
   1.251 +	if (spe_id==0)
   1.252 +		return (h->mb_proc < mb_proc_dep-1 +s->mb_width)? 1:0;
   1.253 +	else
   1.254 +		return (h->mb_proc < mb_proc_dep-1)? 1:0;
   1.255 +}
   1.256 +
   1.257 +void update_tgt_spe_dep(H264Context_spu *h, int end){
   1.258 +	H264Mb *mb = h->mb;
   1.259 +	H264slice *s = h->s;
   1.260 +	H264spe *spe = &h->spe;
   1.261 +	int mb_x = mb->mb_x;
   1.262 +	
   1.263 +	if (end || (mb_x%2==0 && mb_x!=0) || mb_x==s->mb_width-1){
   1.264 +		spe_pos* dma_spe = &dma_temp;
   1.265 +		spe_pos* tgt_spe = (spe_pos*) ((unsigned) spe->tgt_spe + (unsigned) &src_spe); //located in target spe local store
   1.266 +		dma_spe->count = end? h->mb_proc+1: h->mb_proc;
   1.267 +		spu_dma_barrier_put(dma_spe, (unsigned) tgt_spe, sizeof(dma_temp), MBD_put);
   1.268 +	}
   1.269 +	h->mb_proc++;
   1.270 +}
   1.271 +
   1.272 +
   1.273 +int main(unsigned long long id, unsigned long long argp)
   1.274 +{
   1.275 +	(void) id;
   1.276 +	H264Context_spu* h = &h_context;
   1.277 +	H264spe *spe_params = (H264spe *) (unsigned) argp;    
   1.278 +	
   1.279 +	spu_dma_get(&h->spe, (unsigned) spe_params, sizeof(H264spe), MBD_slice); //ID_slice is used out of convienience
   1.280 +	wait_dma_id(MBD_slice);
   1.281 +
   1.282 +    //clear_statistic();
   1.283 +    dsputil_h264_init_cell(&h->dsp);
   1.284 +    ff_cropTbl_init();
   1.285 +    init_pred_ptrs(&h->hpc);
   1.286 +
   1.287 +	//send slice_buf to ppe
   1.288 +	spu_write_out_mbox((unsigned) h->slice_buf);
   1.289 +	h->sl_idx=0;
   1.290 +	// initialize tracing with paraver
   1.291 +    //trace_init_SPU();
   1.292 +	h->frames =0;	
   1.293 +	src_spe.count =0;
   1.294 +	h->mb_proc = 0;
   1.295 +
   1.296 +	h->mb_id=0;
   1.297 +	h->mc_idx=0;
   1.298 +	h->mb_dec=0;
   1.299 +	h->mb_mc=0;
   1.300 +	h->mb_dma=0;
   1.301 +	h->next_mb_idx=0;
   1.302 +
   1.303 +	h->blocking=0;
   1.304 +
   1.305 +
   1.306 +	H264spe* p = &h->spe;
   1.307 +	h->curr_line =p->spe_id;
   1.308 +	h->mb_total = p->mb_height*p->mb_width;
   1.309 +	int stride_y = 32;
   1.310 +	int stride_c = 16;
   1.311 +	//init block_offset array
   1.312 +	init_block_offset(stride_y, stride_c);
   1.313 +	for(;;){
   1.314 +		spu_read_in_mbox();
   1.315 +
   1.316 +		h->s = &h->slice_buf[h->sl_idx];
   1.317 +		h->sl_idx++; h->sl_idx%=2;
   1.318 +
   1.319 +		if (h->s->state< 0){			
   1.320 +			break;
   1.321 +		}
   1.322 +
   1.323 +		{
   1.324 +			if(!h->blocking){
   1.325 +				init_mb_buffer(h);
   1.326 +				while((h->mb=(H264Mb *)get_next_mb(h))){
   1.327 +					while(!dep_resolved(h));
   1.328 +					//printf("frame %d mbx %d\t mby %d id %d\n", h->frames, h->mb->mb_x, h->mb->mb_y, p-	>spe_id);
   1.329 +					hl_decode_mb_internal(h, stride_y, stride_c);
   1.330 +				}
   1.331 +				update_tgt_spe_dep(h, 1);
   1.332 +			}else{
   1.333 +				h->mb_id=0;
   1.334 +				while((h->mb=(H264Mb *)get_next_mb_blocking(h))){
   1.335 +					while(!dep_resolved(h));
   1.336 +					//printf("frame %d mbx %d\t mby %d id %d\n", h->frames, h->mb->mb_x, h->mb->mb_y, p-	>spe_id);
   1.337 +					hl_decode_mb_internal(h, stride_y, stride_c);
   1.338 +				}
   1.339 +				update_tgt_spe_dep(h, 1);
   1.340 +			}
   1.341 +			
   1.342 +		}
   1.343 +
   1.344 +		h->frames++;
   1.345 +		
   1.346 +		if (p->spe_id == ((h->frames*p->mb_height -1)%p->spe_total)){
   1.347 +			//printf("spe %d, %d\n", atomic_read(p->rl_cnt), h->frames);
   1.348 +			//MBSlice is copied beforehand.
   1.349 +			//only inc cnt.
   1.350 +			atomic_inc(p->rl_cnt);		
   1.351 +		}
   1.352 +		{
   1.353 +			atomic_dec(p->cnt);
   1.354 +		}
   1.355 +	}
   1.356 +	
   1.357 +	return 0;
   1.358 +}
   1.359 +