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