nengel@2: static void *entropy_thread(void *arg){ nengel@2: H264Context *h = (H264Context *) arg; nengel@2: EDSlice *s; nengel@2: nengel@2: H264Cabac hcabac; nengel@2: CABACContext cabac; nengel@2: nengel@2: ff_init_cabac_states(); nengel@2: nengel@2: if (init_cabac(h, &hcabac)<0) nengel@2: return NULL; nengel@2: nengel@2: for(;;){ nengel@2: { nengel@2: pthread_mutex_lock(&h->lock[ENTROPY]); nengel@2: while (h->ed_cnt<=0) nengel@2: pthread_cond_wait(&h->cond[ENTROPY], &h->lock[ENTROPY]); nengel@2: s= &h->ed_q[h->ed_fo]; nengel@2: pthread_mutex_unlock(&h->lock[ENTROPY]); nengel@2: h->ed_fo++; h->ed_fo %= MAX_SLICE_COUNT; nengel@2: } nengel@2: if (s->state<0) nengel@2: break; nengel@2: nengel@2: decode_slice_entropy(&hcabac, &cabac, s); nengel@2: nengel@2: { nengel@2: pthread_mutex_lock(&h->lock[MBDEC]); nengel@2: while (h->mbdec_cnt >= MAX_SLICE_COUNT) nengel@2: pthread_cond_wait(&h->cond[MBDEC], &h->lock[MBDEC]); nengel@2: h->mbdec_q[h->mbdec_fi] = *((MBSlice *) s); nengel@2: h->mbdec_cnt++; nengel@2: h->mbdec_fi++; h->mbdec_fi %= MAX_SLICE_COUNT; nengel@2: pthread_cond_signal(&h->cond[MBDEC]); nengel@2: pthread_mutex_unlock(&h->lock[MBDEC]); nengel@2: } nengel@2: { nengel@2: pthread_mutex_lock(&h->lock[ENTROPY]); nengel@2: h->ed_cnt--; nengel@2: pthread_cond_signal(&h->cond[ENTROPY]); nengel@2: pthread_mutex_unlock(&h->lock[ENTROPY]); nengel@2: } nengel@2: } nengel@2: nengel@2: { nengel@2: pthread_mutex_lock(&h->lock[MBDEC]); nengel@2: while (h->mbdec_cnt >= MAX_SLICE_COUNT) nengel@2: pthread_cond_wait(&h->cond[MBDEC], &h->lock[MBDEC]); nengel@2: h->mbdec_q[h->mbdec_fi] = *((MBSlice *) s); nengel@2: h->mbdec_cnt++; nengel@2: h->mbdec_fi++; h->mbdec_fi %= MAX_SLICE_COUNT; nengel@2: pthread_cond_signal(&h->cond[MBDEC]); nengel@2: pthread_mutex_unlock(&h->lock[MBDEC]); nengel@2: nengel@2: } nengel@2: nengel@2: free_cabac(&hcabac); nengel@2: nengel@2: pthread_exit(NULL); nengel@2: return NULL; nengel@2: nengel@2: } nengel@2: /* nengel@2: * The following code is the main loop of the file converter nengel@2: */ nengel@2: int av_transcode_1ed(int ifile, int ofile, int frame_width, int frame_height) { nengel@2: H264Context *h; nengel@2: pthread_t read_thr, parsenal_thr, entropy_thr, mbdec_thr, write_thr; nengel@2: nengel@2: h = ff_h264_decode_init(ifile, ofile, frame_width, frame_height); nengel@2: nengel@2: timer_start = av_gettime(); nengel@2: nengel@2: // pthread_create(&read_thr, NULL, read_thread, h); nengel@2: // pthread_create(&parsenal_thr, NULL, parsenal_thread, h); nengel@2: pthread_create(&entropy_thr, NULL, entropy_mbd_thread, h); nengel@2: nengel@2: // pthread_create(&mbdec_thr, NULL, mbdec_thread, h); nengel@2: nengel@2: // pthread_create(&write_thr, NULL, write_thread, h); nengel@2: nengel@2: // pthread_join(read_thr, NULL); nengel@2: // pthread_join(parsenal_thr, NULL); nengel@2: pthread_join(entropy_thr, NULL); nengel@2: // pthread_join(mbdec_thr, NULL); nengel@2: // printf("before write_thr\n"); nengel@2: // pthread_join(write_thr, NULL); nengel@2: nengel@2: /* finished ! */ nengel@2: ff_h264_decode_end(h); nengel@2: nengel@2: return 0; nengel@2: } nengel@2: nengel@2: static void reset_h264mb(EDSlice *s, int mb_width, int mb_height){ nengel@2: for (int i=0; imbs[i*mb_width + j]; nengel@2: nengel@2: m->left_mb_xy=0; nengel@2: m->top_mb_xy = 0; nengel@2: } nengel@2: } nengel@2: } nengel@2: nengel@2: static void *entropy_mbd_thread(void *arg){ nengel@2: H264Context *h = (H264Context *) arg; nengel@2: nengel@2: EDSlice slice, *s=&slice; nengel@2: MBSlice mbslice, *s2=&mbslice; nengel@2: H264Cabac hcabac; nengel@2: CABACContext cabac; nengel@2: int frames =0; nengel@2: MBDecContext mbdec, *d=&mbdec; nengel@2: int size=h->width*h->height; nengel@2: WriteContext write, *w=&write; nengel@2: AVCodecParserContext parser, *pc= &parser; nengel@2: NalContext nal, *n=&nal; nengel@2: nengel@2: nengel@2: memset(pc, 0, sizeof(AVCodecParserContext)); nengel@2: pc->buffer_size = 2048; nengel@2: pc->final_frame = 0; nengel@2: pc->cur_len= 0; nengel@2: pc->data = av_mallocz(2048 + FF_INPUT_BUFFER_PADDING_SIZE); nengel@2: pc->size = 2048; nengel@2: pc->eof_reached =0; nengel@2: pc->ifile = h->ifile; nengel@2: nengel@2: //init parse nengel@2: memset(n, 0, sizeof(NalContext)); nengel@2: n->width = h->width; nengel@2: n->height = h->height; nengel@2: n->mb_height = h->mb_height; nengel@2: n->mb_width = h->mb_width; nengel@2: n->b4_stride = n->mb_width*4 + 1; nengel@2: n->mb_stride = n->mb_width + 1; nengel@2: n->outputed_poc = INT_MIN; nengel@2: // memset(s, 0, sizeof(EDSlice)); nengel@2: // ff_init_slice(n, s); nengel@2: // nengel@2: nengel@2: memset(w, 0, sizeof(WriteContext)); nengel@2: w->bit_buffer_size= FFMAX(1024*256, 6*size + 200); nengel@2: w->bit_buffer= av_mallocz(w->bit_buffer_size); nengel@2: nengel@2: nengel@2: nengel@2: ff_h264dsp_init(&d->hdsp); nengel@2: ff_h264_pred_init(&d->hpc); nengel@2: dsputil_init(&d->dsp); nengel@2: d->hdsp.qpel_put= d->dsp.put_h264_qpel_pixels_tab; nengel@2: d->hdsp.qpel_avg= d->dsp.avg_h264_qpel_pixels_tab; nengel@2: d->mb_height = (h->height + 15) / 16; nengel@2: d->mb_width = (h->width + 15) / 16; nengel@2: d->linesize = h->width + EDGE_WIDTH*2; nengel@2: d->uvlinesize = d->linesize>>1; nengel@2: nengel@2: for(int i=0; i<16; i++){ nengel@2: d->block_offset[i]= 4*((scan8[i] - scan8[0])&7) + 4*d->linesize*((scan8[i] - scan8[0])>>3); nengel@2: } nengel@2: for(int i=0; i<4; i++){ nengel@2: d->block_offset[16+i]= nengel@2: d->block_offset[20+i]= 4*((scan8[i] - scan8[0])&7) + 4*d->uvlinesize*((scan8[i] - scan8[0])>>3); nengel@2: } nengel@2: nengel@2: d->scratchpad= av_mallocz((h->width+64)*4*16*2*sizeof(uint8_t)); nengel@2: nengel@2: ff_init_cabac_states(); nengel@2: nengel@2: if (init_cabac(h, &hcabac)<0) nengel@2: return NULL; nengel@2: nengel@2: while(!pc->final_frame && frames_max++ < 1000){ nengel@2: Picture *out; nengel@2: nengel@2: RawFrame *frm; nengel@2: Picture *pic=NULL; nengel@2: nengel@2: RawFrame frm_read; nengel@2: frm_read.state =0; nengel@2: av_read_frame_internal(pc, &frm_read); nengel@2: frm = &frm_read; nengel@2: nengel@2: if (frm->state < 0) nengel@2: break; nengel@2: /* nengel@2: { nengel@2: pthread_mutex_lock(&h->lock[PARSE2]); nengel@2: while (h->slice_cnt<=0) nengel@2: pthread_cond_wait(&h->cond[PARSE2], &h->lock[PARSE2]); nengel@2: h->slice_cnt--; nengel@2: s= &h->slices[h->slice_next++]; nengel@2: h->slice_next %= MAX_SLICE_COUNT; nengel@2: pthread_mutex_unlock(&h->lock[PARSE2]); nengel@2: }*/ nengel@2: ff_init_slice(n, s); nengel@2: reset_h264mb(s, n->mb_width, n->mb_height); nengel@2: for(int i=0; ipicture[i].reference==0){ nengel@2: pic= &h->picture[i]; nengel@2: break; nengel@2: } nengel@2: } nengel@2: // { nengel@2: // pthread_mutex_lock(&h->lock[PARSE3]); nengel@2: // while (h->free_pic_cnt<=0) nengel@2: // pthread_cond_wait(&h->cond[PARSE3], &h->lock[PARSE3]); nengel@2: // h->free_pic_cnt--; nengel@2: // /* use first free picture */ nengel@2: // for(int i=0; ipicture[i].reference==0){ nengel@2: // pic= &h->picture[i]; nengel@2: // break; nengel@2: // } nengel@2: // } nengel@2: // pthread_mutex_unlock(&h->lock[PARSE3]); nengel@2: // } nengel@2: ff_alloc_picture(n, s, pic); nengel@2: nengel@2: decode_nal_units(n, s, frm, pic); nengel@2: nengel@2: nengel@2: decode_slice_entropy(&hcabac, &cabac, s); nengel@2: memcpy( s2, s, sizeof(MBSlice)); //this only copys the COMMON_SLICE part nengel@2: av_freep(&s->gb.raw); nengel@2: decode_slice_mb_seq(d, s2); nengel@2: nengel@2: // if (s2->release_cnt>0) { nengel@2: // int i; nengel@2: // for (i=0; irelease_cnt; i++){ nengel@2: // if ((s2->release_ref[i]->reference & ~2) == 0) nengel@2: // default_release_buffer(h, s2->release_ref[i]); nengel@2: // else nengel@2: // s2->release_ref[i]->reference &= ~2; nengel@2: // } nengel@2: // s->release_cnt=0; nengel@2: // } nengel@2: nengel@2: if (s->release_cnt>0) { nengel@2: int i; nengel@2: for (i=0; irelease_cnt; i++){ nengel@2: s->release_ref[i]->reference &= ~2; nengel@2: } nengel@2: s->release_cnt=0; nengel@2: } nengel@2: nengel@2: nengel@2: { nengel@2: pthread_mutex_lock(&h->lock[PARSE2]); nengel@2: h->slice_cnt++; nengel@2: pthread_cond_signal(&h->cond[PARSE2]); nengel@2: pthread_mutex_unlock(&h->lock[PARSE2]); nengel@2: } nengel@2: nengel@2: out =output_frame(w, s2->current_picture, h->ofile, h->width, h->height); nengel@2: print_report(w->frame_number, w->video_size, 0); nengel@2: nengel@2: if (out){ nengel@2: // if ((out->reference & ~1) == 0) nengel@2: // default_release_buffer(h, out); nengel@2: // else nengel@2: out->reference &= ~1; nengel@2: } nengel@2: nengel@2: { nengel@2: pthread_mutex_lock(&h->lock[ENTROPY]); nengel@2: h->ed_cnt--; nengel@2: pthread_cond_signal(&h->cond[ENTROPY]); nengel@2: pthread_mutex_unlock(&h->lock[ENTROPY]); nengel@2: } nengel@2: } nengel@2: while (output_frame(w, NULL, h->ofile, h->width, h->height)); nengel@2: print_report(w->frame_number, w->video_size, 1); nengel@2: nengel@2: av_free(w->bit_buffer); nengel@2: nengel@2: {//propagate exit nengel@2: pthread_mutex_lock(&h->lock[WRITE]); nengel@2: while (h->write_cnt>= MAX_DELAYED_PIC_COUNT) nengel@2: pthread_cond_wait(&h->cond[WRITE], &h->lock[WRITE]); nengel@2: last_pic.reference = -1; nengel@2: h->write_q[h->write_fi] = &last_pic; nengel@2: h->write_cnt++; nengel@2: h->write_fi++; h->write_fi %= MAX_DELAYED_PIC_COUNT; nengel@2: pthread_cond_signal(&h->cond[WRITE]); nengel@2: pthread_mutex_unlock(&h->lock[WRITE]); nengel@2: nengel@2: } nengel@2: free_cabac(&hcabac); nengel@2: nengel@2: pthread_exit(NULL); nengel@2: return NULL; nengel@2: nengel@2: }