annotate libavcodec/h264_pthread.c @ 9:ea1ba68cf0ed

update to match api changes + add sscc produced source
author Nina Engelhardt <nengel@mailbox.tu-berlin.de>
date Wed, 05 Jun 2013 14:43:26 +0200
parents
children
rev   line source
nengel@2 1 #include "config.h"
nengel@2 2
nengel@2 3 #include "h264_types.h"
nengel@2 4 #include "h264_parser.h"
nengel@2 5 #include "h264_nal.h"
nengel@2 6 #include "h264_entropy.h"
nengel@2 7 #include "h264_rec.h"
nengel@2 8 #include "h264_misc.h"
nengel@2 9 // #undef NDEBUG
nengel@2 10 #include <assert.h>
nengel@2 11 #include <pthread.h>
nengel@2 12
nengel@2 13 #define XOANON 1
nengel@2 14
nengel@2 15 #ifdef XOANON
nengel@2 16 static int ed_rec_affinity[40] = { 0, 4, 8, 12, 16, 20, 24, 28, 32, 36,
nengel@2 17 1, 5, 9, 13, 17, 21, 25, 29, 33, 37,
nengel@2 18 2, 6, 10, 14, 18, 22, 26, 30, 34, 38,
nengel@2 19 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 };
nengel@2 20 static int ed_rec_smt_aff[80] = { 0, 40, 4, 44, 8, 48, 12, 52, 16, 56, 20, 60, 24, 64, 28, 68, 32, 72, 36, 76,
nengel@2 21 1, 41, 5, 45, 9, 49, 13, 53, 17, 57, 21, 61, 25, 65, 29, 69, 33, 73, 37, 77,
nengel@2 22 2, 42, 6, 46, 10, 50, 14, 54, 18, 58, 22, 62, 26, 66, 30, 70, 34, 74, 38, 78,
nengel@2 23 3, 43, 7, 47, 11, 51, 15, 55, 19, 59, 23, 63, 27, 67, 31, 71, 35, 75, 39, 79 };
nengel@2 24 #else
nengel@2 25 static int ed_rec_affinity[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
nengel@2 26 static int ed_rec_smt_aff[20] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, };
nengel@2 27 #endif
nengel@2 28
nengel@2 29 static int frames=0;
nengel@2 30
nengel@2 31 static void notify_one_worker(H264Context *h){
nengel@2 32 pthread_mutex_lock(&h->task_lock);
nengel@2 33 pthread_cond_signal(&h->task_cond);
nengel@2 34 pthread_mutex_unlock(&h->task_lock);
nengel@2 35 }
nengel@2 36
nengel@2 37 static void notify_all_workers(H264Context *h){
nengel@2 38 pthread_mutex_lock(&h->task_lock);
nengel@2 39 pthread_cond_broadcast(&h->task_cond);
nengel@2 40 pthread_mutex_unlock(&h->task_lock);
nengel@2 41 }
nengel@2 42
nengel@2 43 static void push_sbe (SliceBufferQueue *sbq, SliceBufferEntry *sbe, int notify ){
nengel@2 44 pthread_mutex_lock(&sbq->lock);
nengel@2 45 while (sbq->cnt >= sbq->size)
nengel@2 46 pthread_cond_wait(&sbq->cond, &sbq->lock);
nengel@2 47 sbq->queue[sbq->fi] = sbe;
nengel@2 48 sbq->cnt++;
nengel@2 49 sbq->fi++; sbq->fi %= sbq->size;
nengel@2 50 if (notify)
nengel@2 51 pthread_cond_signal(&sbq->cond);
nengel@2 52 pthread_mutex_unlock(&sbq->lock);
nengel@2 53 }
nengel@2 54
nengel@2 55 static SliceBufferEntry* pop_sbe (SliceBufferQueue *sbq, int block){
nengel@2 56 SliceBufferEntry *sbe=NULL;
nengel@2 57
nengel@2 58 pthread_mutex_lock(&sbq->lock);
nengel@2 59 if (block){
nengel@2 60 while (sbq->cnt <= 0)
nengel@2 61 pthread_cond_wait(&sbq->cond, &sbq->lock);
nengel@2 62 }else {
nengel@2 63 if (sbq->cnt <= 0)
nengel@2 64 goto nonblock;
nengel@2 65 }
nengel@2 66 sbe = sbq->queue[sbq->fo];
nengel@2 67 sbq->cnt--;
nengel@2 68 sbq->fo++; sbq->fo %= sbq->size;
nengel@2 69 pthread_cond_signal(&sbq->cond);
nengel@2 70 nonblock:
nengel@2 71 pthread_mutex_unlock(&sbq->lock);
nengel@2 72
nengel@2 73 return sbe;
nengel@2 74 }
nengel@2 75
nengel@2 76 // static void push_rle (RingLineQueue *rlq, SliceBufferEntry *sbe, int line, int notify){
nengel@2 77 //
nengel@2 78 // //check for free slots
nengel@2 79 // pthread_mutex_lock(&rlq->wslock);
nengel@2 80 // while (rlq->free <= 0){
nengel@2 81 // pthread_cond_wait(&rlq->wscond, &rlq->wslock);
nengel@2 82 // }
nengel@2 83 // //free slot is available, decrement one in this lock
nengel@2 84 // rlq->free--;
nengel@2 85 // pthread_mutex_unlock(&rlq->wslock);
nengel@2 86 //
nengel@2 87 // pthread_mutex_lock(&rlq->swlock);
nengel@2 88 // rlq->queue[rlq->fi]->sbe=sbe;
nengel@2 89 // rlq->queue[rlq->fi]->line=line;
nengel@2 90 // rlq->queue[rlq->fi]->mb_cnt=0;
nengel@2 91 // rlq->fi++; rlq->fi %= rlq->size;
nengel@2 92 // rlq->ready++;
nengel@2 93 // if(notify)
nengel@2 94 // pthread_cond_signal(&rlq->swcond);
nengel@2 95 // pthread_mutex_unlock(&rlq->swlock);
nengel@2 96 // }
nengel@2 97
nengel@2 98 // static RingLineEntry* pop_rle (RingLineQueue *rlq, int block){
nengel@2 99 // RingLineEntry *rle=NULL;
nengel@2 100 //
nengel@2 101 // pthread_mutex_lock(&rlq->swlock);
nengel@2 102 // if (block){
nengel@2 103 // while (rlq->ready <= 0)
nengel@2 104 // pthread_cond_wait(&rlq->swcond, &rlq->swlock);
nengel@2 105 // }else {
nengel@2 106 // if (rlq->ready <= 0)
nengel@2 107 // goto nonblock;
nengel@2 108 // }
nengel@2 109 // rle = rlq->queue[rlq->fo];
nengel@2 110 // rlq->fo++; rlq->fo %= rlq->size;
nengel@2 111 // rlq->ready--;
nengel@2 112 // nonblock:
nengel@2 113 // pthread_mutex_unlock(&rlq->swlock);
nengel@2 114 //
nengel@2 115 // return rle;
nengel@2 116 // }
nengel@2 117 //
nengel@2 118 // static void rel_rle (RingLineQueue *rlq){
nengel@2 119 // pthread_mutex_lock(&rlq->wslock);
nengel@2 120 // rlq->free++;
nengel@2 121 // pthread_cond_signal(&rlq->wscond);
nengel@2 122 // pthread_mutex_unlock(&rlq->wslock);
nengel@2 123 // }
nengel@2 124
nengel@2 125 static RingLineEntry* pop_rle (SliceBufferQueue *sbq, RingLineQueue *rlq, int *has_token){
nengel@2 126 RingLineEntry *rle=NULL;
nengel@2 127 SliceBufferEntry *sbe=NULL;
nengel@2 128 int line=-1;
nengel@2 129
nengel@2 130 pthread_mutex_lock(&sbq->lock);
nengel@2 131 if (sbq->cnt <= 0)
nengel@2 132 goto unlock;
nengel@2 133 sbe = sbq->queue[sbq->fo];
nengel@2 134 line = sbe->lines_taken;
nengel@2 135
nengel@2 136
nengel@2 137 pthread_mutex_lock(&rlq->swlock);
nengel@2 138 if (!*has_token){
nengel@2 139 if (rlq->free <= 0)
nengel@2 140 goto unlock2;
nengel@2 141 rlq->free--;
nengel@2 142 *has_token=1;
nengel@2 143 }
nengel@2 144 rle = rlq->queue[rlq->fo];
nengel@2 145 rlq->fo++; rlq->fo %= rlq->size;
nengel@2 146 rle->sbe=sbe;
nengel@2 147 rle->line = line;
nengel@2 148 rle->mb_cnt =0;
nengel@2 149 if (++sbe->lines_taken >= sbe->lines_total){
nengel@2 150 sbq->cnt--;
nengel@2 151 sbq->fo++; sbq->fo %= sbq->size;
nengel@2 152 pthread_cond_signal(&sbq->cond);
nengel@2 153 }
nengel@2 154 unlock2:
nengel@2 155 pthread_mutex_unlock(&rlq->swlock);
nengel@2 156 unlock:
nengel@2 157 pthread_mutex_unlock(&sbq->lock);
nengel@2 158
nengel@2 159
nengel@2 160 return rle;
nengel@2 161 }
nengel@2 162
nengel@2 163 static void rel_rle (RingLineQueue *rlq, int *rec_token){
nengel@2 164 pthread_mutex_lock(&rlq->swlock);
nengel@2 165 rlq->free++;
nengel@2 166 *rec_token=0;
nengel@2 167 // pthread_cond_signal(&rlq->swcond);
nengel@2 168 pthread_mutex_unlock(&rlq->swlock);
nengel@2 169
nengel@2 170 }
nengel@2 171
nengel@2 172 //get either a entropy or a line reconstruct task
nengel@2 173 static void pop_next_task(H264Context *h, SliceBufferEntry **psbe, RingLineEntry **prle, int *rec_token){
nengel@2 174
nengel@2 175 pthread_mutex_lock(&h->task_lock);
nengel@2 176
nengel@2 177 for(;;){
nengel@2 178 if ( (*psbe = pop_sbe(&h->sb_q[ENTROPY], 0)) ){
nengel@2 179 if (*rec_token){
nengel@2 180 rel_rle(&h->rl_q, rec_token);
nengel@2 181 pthread_cond_signal(&h->task_cond);
nengel@2 182 }
nengel@2 183 break;
nengel@2 184 }
nengel@2 185 else if ( (*prle = pop_rle(&h->sb_q[MBDEC], &h->rl_q, rec_token)) )
nengel@2 186 break;
nengel@2 187 pthread_cond_wait(&h->task_cond, &h->task_lock);
nengel@2 188 }
nengel@2 189
nengel@2 190 pthread_mutex_unlock(&h->task_lock);
nengel@2 191 }
nengel@2 192
nengel@2 193 void *parse_thread(void *arg){
nengel@2 194 H264Context *h = (H264Context *) arg;
nengel@2 195 ParserContext *pc = get_parse_context(h->ifile);
nengel@2 196 NalContext *nc = get_nal_context(h->width, h->height);
nengel@2 197 H264Slice *s;
nengel@2 198 SliceBufferEntry *sbe = NULL;
nengel@2 199
nengel@2 200 while(!pc->final_frame && frames++ <h->num_frames && !h->quit){
nengel@2 201 sbe = get_sb_entry(h);
nengel@2 202
nengel@2 203 av_read_frame_internal(pc, &sbe->gb);
nengel@2 204 s = &sbe->slice;
nengel@2 205
nengel@2 206 decode_nal_units(nc, s, &sbe->gb);
nengel@2 207
nengel@2 208 push_sbe(&h->sb_q[ENTROPY], sbe, 0);
nengel@2 209 notify_one_worker(h);
nengel@2 210 }
nengel@2 211
nengel@2 212 if (!h->no_mbd){
nengel@2 213 sbe = get_sb_entry(h);
nengel@2 214 sbe->state=-1;
nengel@2 215 sbe->slice.coded_pic_num=nc->coded_pic_num;
nengel@2 216 sbe->lines_total=h->threads;
nengel@2 217
nengel@2 218 push_sbe(&h->sb_q[REORDER], sbe, 1);
nengel@2 219 }else{
nengel@2 220 for (int i=0; i<h->threads; i++){
nengel@2 221 sbe = get_sb_entry(h);
nengel@2 222 sbe->state=-1;
nengel@2 223 push_sbe(&h->sb_q[ENTROPY], sbe, 1);
nengel@2 224 notify_one_worker(h);
nengel@2 225 }
nengel@2 226 }
nengel@2 227 free_nal_context(nc);
nengel@2 228 free_parse_context(pc);
nengel@2 229
nengel@2 230 pthread_exit(NULL);
nengel@2 231 return NULL;
nengel@2 232 }
nengel@2 233
nengel@2 234 int decode_slice_entropy(EntropyContext *ec, SliceBufferEntry *sbe){
nengel@2 235 int i,j;
nengel@2 236 H264Slice *s = &sbe->slice;
nengel@2 237 GetBitContext *gb = &sbe->gb;
nengel@2 238 CABACContext *c = &ec->c;
nengel@2 239 H264Mb *mbs = sbe->mbs;
nengel@2 240
nengel@2 241 if( !s->pps.cabac ){
nengel@2 242 av_log(AV_LOG_ERROR, "Only cabac encoded streams are supported\n");
nengel@2 243 return -1;
nengel@2 244 }
nengel@2 245
nengel@2 246 init_dequant_tables(s, ec);
nengel@2 247 ec->curr_qscale = s->qscale;
nengel@2 248 ec->last_qscale_diff = 0;
nengel@2 249 ec->chroma_qp[0] = get_chroma_qp( s, 0, s->qscale);
nengel@2 250 ec->chroma_qp[1] = get_chroma_qp( s, 1, s->qscale);
nengel@2 251
nengel@2 252 /* realign */
nengel@2 253 align_get_bits( gb );
nengel@2 254 /* init cabac */
nengel@2 255 ff_init_cabac_decoder( c, gb->buffer + get_bits_count(gb)/8, (get_bits_left(gb) + 7)/8);
nengel@2 256
nengel@2 257 ff_h264_init_cabac_states(ec, s, c);
nengel@2 258
nengel@2 259 for(j=0; j<ec->mb_height; j++){
nengel@2 260 init_entropy_buf(ec, s, j);
nengel@2 261 for(i=0; i<ec->mb_width; i++){
nengel@2 262 int eos,ret;
nengel@2 263 H264Mb *m = &mbs[i + j*ec->mb_width];
nengel@2 264 //memset(m, 0, sizeof(H264Mb));
nengel@2 265 m->mb_x=i;
nengel@2 266 m->mb_y=j;
nengel@2 267 ec->m = m;
nengel@2 268
nengel@2 269 ret = ff_h264_decode_mb_cabac(ec, s, c);
nengel@2 270 eos = get_cabac_terminate( c); (void) eos;
nengel@2 271
nengel@2 272 if( ret < 0 || c->bytestream > c->bytestream_end + 2) {
nengel@2 273 av_log(AV_LOG_ERROR, "error while decoding MB %d %d, bytestream (%td)\n", m->mb_x, m->mb_y, c->bytestream_end - c->bytestream);
nengel@2 274 return -1;
nengel@2 275 }
nengel@2 276 }
nengel@2 277 }
nengel@2 278
nengel@2 279 return 0;
nengel@2 280 }
nengel@2 281
nengel@2 282 static int decode_slice_mb(MBRecContext *d, RingLineEntry *rle, int frames){
nengel@2 283 SliceBufferEntry *sbe= rle->sbe;
nengel@2 284 H264Slice *s = &sbe->slice;
nengel@2 285 H264Mb *mbs = sbe->mbs;
nengel@2 286
nengel@2 287 int mb_width= d->mb_width;
nengel@2 288 int i;
nengel@2 289 const int line = rle->line;
nengel@2 290
nengel@2 291 init_mbrec_context(d, d->mrs, s, line);
nengel@2 292
nengel@2 293 H264Mb *m = &mbs[line*mb_width];
nengel@2 294 d->top=rle->prev_line->top;
nengel@2 295 d->top_next=rle->top;
nengel@2 296
nengel@2 297 // assert(rle->mb_cnt ==0);
nengel@2 298 for(i=0; i< mb_width; i++){
nengel@2 299 if (frames || line>0){
nengel@2 300 while (rle->mb_cnt >= rle->prev_line->mb_cnt -1);
nengel@2 301 }
nengel@2 302 h264_decode_mb_internal( d, d->mrs, s, &m[i]);
nengel@2 303 rle->mb_cnt++;
nengel@2 304 }
nengel@2 305 draw_edges(d, s, line);
nengel@2 306
nengel@2 307 return 0;
nengel@2 308 }
nengel@2 309
nengel@2 310 // static int decode_slice_mb_static(MBRecContext *d, H264Slice *s, RLThreadContext *r, RLThreadContext *rp, int frames){
nengel@2 311 // int mb_height= d->mb_height;
nengel@2 312 // int mb_width= d->mb_width;
nengel@2 313 // int thread_num = r->thread_num;
nengel@2 314 // int thread_total = r->thread_total;
nengel@2 315 // int i;
nengel@2 316 // int j = thread_num;
nengel@2 317 //
nengel@2 318 // r->mb_cnt=frames* mb_height*mb_width;
nengel@2 319 // for(; j<mb_height; j+=thread_total){
nengel@2 320 // H264Mb *m = &s->mbs[j*mb_width];
nengel@2 321 // for(i=0; i< mb_width; i++){
nengel@2 322 // if (j>0){
nengel@2 323 // while (r->mb_cnt- (thread_num? 0:mb_width) >= rp->mb_cnt-1);
nengel@2 324 // }
nengel@2 325 // h264_decode_mb_internal(d, s, m++);
nengel@2 326 // r->mb_cnt++;
nengel@2 327 // }
nengel@2 328 // draw_edges(d, s, j);
nengel@2 329 // }
nengel@2 330 // return 0;
nengel@2 331 // }
nengel@2 332
nengel@2 333 static void *ed_rec_thread(void *arg){
nengel@2 334 H264Context *h = (H264Context*) arg;
nengel@2 335 EntropyContext *ec=NULL;
nengel@2 336 MBRecContext *mrc=NULL;
nengel@2 337
nengel@2 338 RingLineEntry *rle=NULL;
nengel@2 339 SliceBufferEntry *sbe=NULL;
nengel@2 340 H264Slice *s;
nengel@2 341 int rec_token=0;
nengel@2 342
nengel@2 343 if (!h->no_mbd){
nengel@2 344 mrc = get_mbrec_context(h);
nengel@2 345 }
nengel@2 346 ec = get_entropy_context(h);
nengel@2 347
nengel@2 348 for(;;){
nengel@2 349 pop_next_task(h, &sbe, &rle, &rec_token);
nengel@2 350 if (sbe){
nengel@2 351 if (h->no_mbd && sbe->state<0){
nengel@2 352 break;
nengel@2 353 }
nengel@2 354 if (!sbe->initialized){
nengel@2 355 init_sb_entry(h, sbe);
nengel@2 356 }
nengel@2 357 decode_slice_entropy(ec, sbe);
nengel@2 358
nengel@2 359 if (h->no_mbd){
nengel@2 360 release_sb_entry(h, sbe);
nengel@2 361 sbe=NULL;
nengel@2 362 } else {
nengel@2 363 push_sbe(&h->sb_q[REORDER], sbe, 1);
nengel@2 364 }
nengel@2 365 } else if (rle){
nengel@2 366 if (rle->sbe->state<0)
nengel@2 367 break;
nengel@2 368 s = &rle->sbe->slice;
nengel@2 369
nengel@2 370 decode_slice_mb(mrc, rle, s->coded_pic_num);
nengel@2 371
nengel@2 372 if (rle->line == h->mb_height-1){
nengel@2 373 push_sbe(&h->sb_q[OUTPUT], rle->sbe, 1);
nengel@2 374 }
nengel@2 375 rle->mb_cnt++;
nengel@2 376 }
nengel@2 377 }
nengel@2 378
nengel@2 379 //make sure threads quit in order of rle assignment
nengel@2 380 if (!h->no_mbd){
nengel@2 381 while (rle->prev_line->mb_cnt <= h->mb_width);
nengel@2 382 rel_rle(&h->rl_q, &rec_token);
nengel@2 383 notify_one_worker(h);
nengel@2 384 rle->mb_cnt = h->mb_width +1;
nengel@2 385 if (rle->line == h->threads-1){
nengel@2 386 push_sbe(&h->sb_q[OUTPUT], rle->sbe, 1);
nengel@2 387 }
nengel@2 388
nengel@2 389 free_mbrec_context(mrc);
nengel@2 390 }
nengel@2 391
nengel@2 392 free_entropy_context(ec);
nengel@2 393
nengel@2 394 pthread_exit(NULL);
nengel@2 395 return NULL;
nengel@2 396 }
nengel@2 397
nengel@2 398 static void *reorder_thread(void *arg){
nengel@2 399 H264Context *h = (H264Context *) arg;
nengel@2 400 int i;
nengel@2 401 SliceBufferEntry *reorder[h->sb_size];
nengel@2 402 SliceBufferEntry *sbe, *next_sbe;
nengel@2 403 H264Slice *s;
nengel@2 404 int reorder_cnt=0;
nengel@2 405 unsigned next_pic_num=0;
nengel@2 406
nengel@2 407 for(;;){
nengel@2 408
nengel@2 409 sbe = pop_sbe(&h->sb_q[REORDER], 1);
nengel@2 410
nengel@2 411 s = &sbe->slice;
nengel@2 412 for(i=reorder_cnt; i>0; i--){
nengel@2 413 if (s->coded_pic_num < reorder[i-1]->slice.coded_pic_num)
nengel@2 414 break;
nengel@2 415 reorder[i]=reorder[i-1];
nengel@2 416 }
nengel@2 417 reorder[i]=sbe;
nengel@2 418
nengel@2 419 while(reorder_cnt>=0){
nengel@2 420 if (next_pic_num!=reorder[reorder_cnt]->slice.coded_pic_num){
nengel@2 421 break;
nengel@2 422 }
nengel@2 423 next_sbe = reorder[reorder_cnt];
nengel@2 424 H264Slice *es = &next_sbe->slice;
nengel@2 425
nengel@2 426 if (next_sbe->state<0)
nengel@2 427 goto end;
nengel@2 428
nengel@2 429 for (int i=0; i<2; i++){
nengel@2 430 for(int j=0; j< es->ref_count[i]; j++){
nengel@2 431 if (es->ref_list_cpn[i][j] ==-1)
nengel@2 432 continue;
nengel@2 433 int k;
nengel@2 434 for (k=0; k<h->max_dpb_cnt; k++){
nengel@2 435 if(h->dpb[k].reference >= 2 && h->dpb[k].cpn == es->ref_list_cpn[i][j]){
nengel@2 436 es->dp_ref_list[i][j] = &h->dpb[k];
nengel@2 437 break;
nengel@2 438 }
nengel@2 439 }
nengel@2 440 }
nengel@2 441 }
nengel@2 442 next_sbe->dp = get_dpb_entry(h, es);
nengel@2 443
nengel@2 444 push_sbe(&h->sb_q[MBDEC], next_sbe, 0);
nengel@2 445 notify_all_workers(h);
nengel@2 446
nengel@2 447 // for (int i=0; i< h->mb_height; i++){
nengel@2 448 // push_rle(&h->rl_q, next_sbe, i, 0);
nengel@2 449 // notify_one_worker(h);
nengel@2 450 // }
nengel@2 451
nengel@2 452
nengel@2 453 next_pic_num++;
nengel@2 454 reorder_cnt--;
nengel@2 455 }
nengel@2 456 reorder_cnt++;
nengel@2 457 }
nengel@2 458
nengel@2 459 end:
nengel@2 460 {
nengel@2 461 push_sbe(&h->sb_q[MBDEC], next_sbe, 0);
nengel@2 462 notify_all_workers(h);
nengel@2 463 if (h->no_mbd){
nengel@2 464 push_sbe(&h->sb_q[OUTPUT], next_sbe, 1);
nengel@2 465 }
nengel@2 466 // for (int i=0; i< h->threads; i++){
nengel@2 467 // push_rle(&h->rl_q, next_sbe, i, 0);
nengel@2 468 // notify_one_worker(h);
nengel@2 469 // }
nengel@2 470 }
nengel@2 471
nengel@2 472 pthread_exit(NULL);
nengel@2 473 return NULL;
nengel@2 474 }
nengel@2 475
nengel@2 476 void create_ed_rec_threads(H264Context *h){
nengel@2 477 cpu_set_t cpuset;
nengel@2 478 int* aff;
nengel@2 479
nengel@2 480 if (h->setaff){
nengel@2 481 aff = h->smt ? ed_rec_smt_aff : ed_rec_affinity ;
nengel@2 482 for (int i=0; i<h->threads; i++){
nengel@2 483 pthread_attr_init(&h->ed_rec_attr[i]);
nengel@2 484 CPU_ZERO(&cpuset);
nengel@2 485 CPU_SET(aff[i], &cpuset);
nengel@2 486 pthread_attr_setaffinity_np(&h->ed_rec_attr[i], sizeof(cpu_set_t), &cpuset);
nengel@2 487 pthread_create(&h->ed_rec_thr[i], &h->ed_rec_attr[i], ed_rec_thread, h);
nengel@2 488 }
nengel@2 489 } else {
nengel@2 490 for (int i=0; i<h->threads; i++){
nengel@2 491 pthread_create(&h->ed_rec_thr[i], NULL, ed_rec_thread, h);
nengel@2 492 }
nengel@2 493 }
nengel@2 494 }
nengel@2 495
nengel@2 496 void join_ed_rec_threads(H264Context *h){
nengel@2 497 for (int i=0; i< h->threads; i++){
nengel@2 498 pthread_join(h->ed_rec_thr[i], NULL);
nengel@2 499 }
nengel@2 500 }
nengel@2 501
nengel@2 502 void *output_thread(void *arg){
nengel@2 503 H264Context *h = (H264Context *) arg;
nengel@2 504
nengel@2 505 OutputContext *oc = get_output_context( h );
nengel@2 506
nengel@2 507 SliceBufferEntry *sbe = NULL;
nengel@2 508 H264Slice *s=NULL;
nengel@2 509 for(;;) {
nengel@2 510 DecodedPicture *out, *dp;
nengel@2 511 sbe = pop_sbe(&h->sb_q[OUTPUT], 1);
nengel@2 512
nengel@2 513 if (sbe->state <0)
nengel@2 514 break;
nengel@2 515
nengel@2 516 s = &sbe->slice;
nengel@2 517 for (int i=0; i<s->release_cnt; i++){
nengel@2 518 for(int j=0; j<h->max_dpb_cnt; j++){
nengel@2 519 if(h->dpb[j].cpn== s->release_ref_cpn[i]){
nengel@2 520 release_dpb_entry(h, &h->dpb[j], 2);
nengel@2 521 break;
nengel@2 522 }
nengel@2 523 }
nengel@2 524 }
nengel@2 525
nengel@2 526 dp=sbe->dp;
nengel@2 527 release_sb_entry(h, sbe);
nengel@2 528
nengel@2 529 out =output_frame(h, oc, dp, h->ofile, h->frame_width, h->frame_height);
nengel@2 530 if (out){
nengel@2 531 release_dpb_entry(h, out, 1);
nengel@2 532 }
nengel@2 533
nengel@2 534 print_report(oc->frame_number, oc->video_size, 0, h->verbose);
nengel@2 535
nengel@2 536 }
nengel@2 537 /* at the end of stream, we must flush the decoder buffers */
nengel@2 538 while (output_frame(h, oc, NULL, h->ofile, h->frame_width, h->frame_height));
nengel@2 539 print_report(oc->frame_number, oc->video_size, 1, h->verbose);
nengel@2 540
nengel@2 541 free_output_context(oc);
nengel@2 542
nengel@2 543 pthread_exit(NULL);
nengel@2 544 return NULL;
nengel@2 545 }
nengel@2 546
nengel@2 547 /*
nengel@2 548 * The following code is the main loop of the file converter
nengel@2 549 */
nengel@2 550 int h264_decode_pthread(H264Context *h) {
nengel@2 551 pthread_t parse_thr, reorder_thr, output_thr;
nengel@2 552
nengel@2 553 av_start_timer();
nengel@2 554
nengel@2 555 pthread_create(&parse_thr, NULL, parse_thread, h);
nengel@2 556 if (!h->no_mbd){
nengel@2 557 pthread_create(&reorder_thr, NULL, reorder_thread, h);
nengel@2 558 pthread_create(&output_thr, NULL, output_thread, h);
nengel@2 559 }
nengel@2 560 #if HAVE_LIBSDL2
nengel@2 561 pthread_t sdl_thr;
nengel@2 562 if (h->display){
nengel@2 563 pthread_create(&sdl_thr, NULL, sdl_thread, h);
nengel@2 564 }
nengel@2 565 #endif
nengel@2 566 create_ed_rec_threads(h);
nengel@2 567
nengel@2 568
nengel@2 569 if (h->rl_side_touch){
nengel@2 570 pthread_mutex_lock(&h->ilock);
nengel@2 571 while (h->init_threads< h->threads)
nengel@2 572 pthread_cond_wait(&h->icond, &h->ilock);
nengel@2 573 pthread_mutex_unlock(&h->ilock);
nengel@2 574
nengel@2 575 pthread_mutex_lock(&h->tlock);
nengel@2 576 h->touch_start =1;
nengel@2 577 pthread_cond_broadcast(&h->tcond);
nengel@2 578 pthread_mutex_unlock(&h->tlock);
nengel@2 579
nengel@2 580 pthread_mutex_lock(&h->tdlock);
nengel@2 581 while (h->touch_done < h->threads)
nengel@2 582 pthread_cond_wait(&h->tdcond, &h->tdlock);
nengel@2 583 pthread_mutex_unlock(&h->tdlock);
nengel@2 584
nengel@2 585 pthread_mutex_lock(&h->slock);
nengel@2 586 h->start =1;
nengel@2 587 pthread_cond_broadcast(&h->scond);
nengel@2 588 pthread_mutex_unlock(&h->slock);
nengel@2 589 }
nengel@2 590 join_ed_rec_threads(h);
nengel@2 591 pthread_join(parse_thr, NULL);
nengel@2 592 if (!h->no_mbd){
nengel@2 593 pthread_join(reorder_thr, NULL);
nengel@2 594 pthread_join(output_thr, NULL);
nengel@2 595 }
nengel@2 596 #if HAVE_LIBSDL2
nengel@2 597 if (h->display)
nengel@2 598 signal_sdl_exit(h);
nengel@2 599 pthread_join(sdl_thr, NULL);
nengel@2 600 #endif
nengel@2 601
nengel@2 602
nengel@2 603 return 0;
nengel@2 604 }