nengel@2: #include "config.h" nengel@2: #include "h264.h" nengel@2: #include "h264_misc.h" nengel@2: #include nengel@2: nengel@2: H264Context *get_h264dec_context(const char *file_name, int ifile, int ofile, int width, int height, h264_options *opts){ nengel@2: int i; nengel@2: const int mb_height = (height + 15) / 16; nengel@2: const int mb_width = (width + 15) / 16; nengel@2: const int mb_stride = ((mb_width+1)/16 + 1) *16; //align mb_stride to 16 nengel@2: nengel@2: ff_init_cabac_states(); nengel@2: nengel@2: H264Context *h= av_mallocz(sizeof(H264Context)); nengel@2: nengel@2: start_timer(h, TOTAL); nengel@2: h->file_name = file_name; nengel@2: h->profile = opts->profile; nengel@2: for (i=0; itotal_time[i]=0; nengel@2: nengel@2: h->ifile=ifile; nengel@2: h->ofile =ofile; nengel@2: nengel@2: h->verbose =opts->verbose; nengel@2: h->no_mbd =opts->no_mbd; nengel@2: h->static_3d =opts->static_3d; nengel@2: h->pipe_bufs = opts->pipe_bufs; nengel@2: h->slice_bufs = opts->slice_bufs; nengel@2: nengel@2: h->ed_ppe_threads =0; nengel@2: if (opts->ppe_ed){ nengel@2: h->ed_ppe_threads = (opts->threads >opts->ppe_ed)? opts->ppe_ed :opts->threads; nengel@2: } nengel@2: nengel@2: h->threads = opts->threads - h->ed_ppe_threads; nengel@2: h->smt = opts->smt; nengel@2: if (h->smt){ nengel@2: h->threads *= 2; nengel@2: } nengel@2: nengel@2: h->num_frames = opts->numframes; nengel@2: nengel@2: h->frame_width = width; nengel@2: h->frame_height = height; nengel@2: nengel@2: while ((width/2) %STRIDE_ALIGN) nengel@2: width+=STRIDE_ALIGN; nengel@2: h->width = width; nengel@2: h->height = mb_height*16; nengel@2: nengel@2: h->mb_height = mb_height; nengel@2: h->mb_width = mb_width; nengel@2: h->mb_stride = mb_stride; nengel@2: h->b4_stride = mb_width*4 + 1; nengel@2: h->b_stride = mb_width*4; nengel@2: nengel@2: h->smb_width = opts->smb_size[0]; nengel@2: h->smb_height = opts->smb_size[1] < h->smb_width ? opts->smb_size[1] : h->smb_width; nengel@2: h->smbc = getSuperMBContext(h, h->smb_width, h->smb_height); nengel@2: nengel@2: h->wave_order = opts->wave_order; nengel@2: nengel@2: h->pipe_bufs = opts->pipe_bufs; nengel@2: nengel@2: h->max_dpb_cnt = DPB_SIZE + opts->pipe_bufs; nengel@2: h->free_dpb_cnt = h->max_dpb_cnt; nengel@2: h->dpb = av_mallocz (h->max_dpb_cnt* sizeof (DecodedPicture)); nengel@2: nengel@2: nengel@2: h->free_sb_cnt = h->threads*opts->slice_bufs + (h->no_mbd != 0) ; //one extra to overlap some latency of signaling/freeing slicebuffers in entropy only mode nengel@2: h->sb_size = h->free_sb_cnt; nengel@2: h->sb = av_mallocz(h->sb_size* sizeof(SliceBufferEntry)); nengel@2: nengel@2: h->rl_q.size = FFMAX(1, FFMIN( (h->height-3 - 512)/16, h->mb_width/2)) +1; nengel@2: h->rl_q.free = h->rl_q.size -1; nengel@2: h->rl_q.ready=0; nengel@2: h->rl_q.fi = h->rl_q.fo= 0; nengel@2: h->rl_q.queue = av_malloc(h->rl_q.size* sizeof(RingLineEntry*)); nengel@2: for (i=0; irl_q.size; i++){ nengel@2: if( posix_memalign((void**)&h->rl_q.queue[i],64,sizeof(RingLineEntry))) nengel@2: h->rl_q.queue[i]=NULL; nengel@2: h->rl_q.queue[i]->top = av_malloc(h->mb_width*sizeof(TopBorder)); nengel@2: } nengel@2: nengel@2: h->rl_q.queue[0]->prev_line = h->rl_q.queue[h->rl_q.size-1]; nengel@2: for (i=1; irl_q.size; i++){ nengel@2: h->rl_q.queue[i]->prev_line = h->rl_q.queue[i-1]; nengel@2: } nengel@2: nengel@2: if( HAVE_MMX | HAVE_ALTIVEC| HAVE_NEON ){ nengel@2: for(i=0; i<16; i++){ nengel@2: #define T(x) (x>>2) | ((x<<2) & 0xF) nengel@2: h->zigzag_scan[i] = T(zigzag_scan[i]); nengel@2: #undef T nengel@2: } nengel@2: for(i=0; i<64; i++){ nengel@2: #define T(x) (x>>3) | ((x&7)<<3) nengel@2: h->zigzag_scan8x8[i] = T(ff_zigzag_direct[i]); nengel@2: #undef T nengel@2: } nengel@2: }else{ nengel@2: memcpy(h->zigzag_scan, zigzag_scan, 16*sizeof(uint8_t)); nengel@2: memcpy(h->zigzag_scan8x8, ff_zigzag_direct, 64*sizeof(uint8_t)); nengel@2: } nengel@2: nengel@2: pthread_mutex_init(&h->smb_lock, NULL); nengel@2: pthread_mutex_init(&h->sdl_lock, NULL); nengel@2: pthread_cond_init(&h->sdl_cond, NULL); nengel@2: nengel@2: ///pthread initialization nengel@2: pthread_mutex_init(&h->ilock, NULL); nengel@2: pthread_cond_init(&h->icond, NULL); nengel@2: pthread_mutex_init(&h->slock, NULL); nengel@2: pthread_cond_init(&h->scond, NULL); nengel@2: pthread_mutex_init(&h->tlock, NULL); nengel@2: pthread_cond_init(&h->tcond, NULL); nengel@2: pthread_mutex_init(&h->tdlock, NULL); nengel@2: pthread_cond_init(&h->tdcond, NULL); nengel@2: h->start =!opts->numamap; //default dont wait for start signal nengel@2: h->statmbd = opts->statmbd; nengel@2: h->rl_side_touch= opts->numamap; nengel@2: h->touch_start=0; nengel@2: h->setaff =opts->statsched; nengel@2: h->init_threads=0; nengel@2: nengel@2: pthread_mutex_init(&h->task_lock, NULL); nengel@2: pthread_cond_init(&h->task_cond, NULL); nengel@2: for (i=0; ilock[i], NULL); nengel@2: pthread_cond_init (&h->cond[i], NULL); nengel@2: nengel@2: pthread_mutex_init (&h->sb_q[i].lock, NULL); nengel@2: pthread_cond_init (&h->sb_q[i].cond, NULL); nengel@2: h->sb_q[i].size = h->free_sb_cnt; //change to num threads later nengel@2: h->sb_q[i].queue = av_malloc(h->free_sb_cnt* sizeof(SliceBufferEntry*)); nengel@2: h->sb_q[i].cnt = h->sb_q[i].fi = h->sb_q[i].fo =0; nengel@2: } nengel@2: nengel@2: #if HAVE_LIBSDL2 nengel@2: h->sdlq.size=2; nengel@2: h->sdlq.ready=2; nengel@2: h->sdlq.queue = av_malloc(2* sizeof(SDL_Texture*)); nengel@2: pthread_mutex_init (&h->sdlq.sdl_lock, NULL); nengel@2: pthread_cond_init (&h->sdlq.sdl_cond, NULL); nengel@2: #endif nengel@2: nengel@2: h->display=opts->display; nengel@2: h->fullscreen=opts->fullscreen; nengel@2: nengel@2: return h; nengel@2: } nengel@2: nengel@2: nengel@2: void free_h264dec_context(H264Context *h) { nengel@2: int i; nengel@2: nengel@2: for(i=0; imax_dpb_cnt; i++) nengel@2: free_dp(&h->dpb[i]); nengel@2: av_free (h->dpb); nengel@2: nengel@2: for(i=0; isb_size; i++){ nengel@2: if (h->sb[i].initialized){ nengel@2: free_sb_entry(&h->sb[i]); nengel@2: } nengel@2: } nengel@2: av_freep(&h->sb); nengel@2: nengel@2: for (i=0; irl_q.size; i++){ nengel@2: av_freep(&h->rl_q.queue[i]->top); nengel@2: av_freep(&h->rl_q.queue[i]); nengel@2: } nengel@2: av_freep(&h->rl_q.queue); nengel@2: nengel@2: ///pthread cleanup nengel@2: pthread_mutex_destroy (&h->task_lock); nengel@2: pthread_cond_destroy (&h->task_cond); nengel@2: for (i=0; ilock[i]); nengel@2: pthread_cond_destroy (&h->cond[i]); nengel@2: nengel@2: pthread_mutex_destroy (&h->sb_q[i].lock); nengel@2: pthread_cond_destroy (&h->sb_q[i].cond); nengel@2: av_freep( &h->sb_q[i].queue); nengel@2: } nengel@2: pthread_mutex_destroy (&h->slock); nengel@2: pthread_cond_destroy (&h->scond); nengel@2: pthread_mutex_destroy (&h->ilock); nengel@2: pthread_cond_destroy (&h->icond); nengel@2: nengel@2: pthread_mutex_destroy(&h->smb_lock); nengel@2: pthread_mutex_destroy (&h->sdl_lock); nengel@2: pthread_cond_destroy (&h->sdl_cond); nengel@2: #if HAVE_LIBSDL2 nengel@2: av_free(h->sdlq.queue); nengel@2: pthread_mutex_destroy (&h->sdlq.sdl_lock); nengel@2: pthread_cond_destroy (&h->sdlq.sdl_cond); nengel@2: #endif nengel@2: nengel@2: stop_timer(h, TOTAL); nengel@2: if (h->threads==0){ nengel@2: for (i=0; itotal_time[i] /= h->num_frames; nengel@2: double others = h->total_time[TOTAL]; nengel@2: for (i=1; itotal_time[i]; nengel@2: if (h->profile == 1){ nengel@2: printf("\n[FRAME %.3fms] [FRONT %.3fms] [ENTROPY %.3fms] [MBREC %.3fms] [OTHERS %.3fms]\n", h->total_time[TOTAL], h->total_time[FRONT], h->total_time[ED], h->total_time[REC], others); nengel@2: }else if (h->profile ==2){ nengel@2: printf("\n[FRAME %.3fms] [FRONT %.3fms] [ENTROPY %.3fms] [PRED %.3fms] [OTHERS %.3fms]\n", h->total_time[TOTAL], h->total_time[FRONT], h->total_time[ED],h->total_time[REC], others); nengel@2: } nengel@2: } nengel@2: nengel@2: av_free(h); nengel@2: }