| rev |
line source |
|
nengel@2
|
1 #include "config.h"
|
|
nengel@2
|
2 #include "h264.h"
|
|
nengel@2
|
3 #include "h264_misc.h"
|
|
nengel@2
|
4 #include <math.h>
|
|
nengel@2
|
5
|
|
nengel@2
|
6 H264Context *get_h264dec_context(const char *file_name, int ifile, int ofile, int width, int height, h264_options *opts){
|
|
nengel@2
|
7 int i;
|
|
nengel@2
|
8 const int mb_height = (height + 15) / 16;
|
|
nengel@2
|
9 const int mb_width = (width + 15) / 16;
|
|
nengel@2
|
10 const int mb_stride = ((mb_width+1)/16 + 1) *16; //align mb_stride to 16
|
|
nengel@2
|
11
|
|
nengel@2
|
12 ff_init_cabac_states();
|
|
nengel@2
|
13
|
|
nengel@2
|
14 H264Context *h= av_mallocz(sizeof(H264Context));
|
|
nengel@2
|
15
|
|
nengel@2
|
16 start_timer(h, TOTAL);
|
|
nengel@2
|
17 h->file_name = file_name;
|
|
nengel@2
|
18 h->profile = opts->profile;
|
|
nengel@2
|
19 for (i=0; i<PROFILE_STAGES; i++)
|
|
nengel@2
|
20 h->total_time[i]=0;
|
|
nengel@2
|
21
|
|
nengel@2
|
22 h->ifile=ifile;
|
|
nengel@2
|
23 h->ofile =ofile;
|
|
nengel@2
|
24
|
|
nengel@2
|
25 h->verbose =opts->verbose;
|
|
nengel@2
|
26 h->no_mbd =opts->no_mbd;
|
|
nengel@2
|
27 h->static_3d =opts->static_3d;
|
|
nengel@2
|
28 h->pipe_bufs = opts->pipe_bufs;
|
|
nengel@2
|
29 h->slice_bufs = opts->slice_bufs;
|
|
nengel@2
|
30
|
|
nengel@2
|
31 h->ed_ppe_threads =0;
|
|
nengel@2
|
32 if (opts->ppe_ed){
|
|
nengel@2
|
33 h->ed_ppe_threads = (opts->threads >opts->ppe_ed)? opts->ppe_ed :opts->threads;
|
|
nengel@2
|
34 }
|
|
nengel@2
|
35
|
|
nengel@2
|
36 h->threads = opts->threads - h->ed_ppe_threads;
|
|
nengel@2
|
37 h->smt = opts->smt;
|
|
nengel@2
|
38 if (h->smt){
|
|
nengel@2
|
39 h->threads *= 2;
|
|
nengel@2
|
40 }
|
|
nengel@2
|
41
|
|
nengel@2
|
42 h->num_frames = opts->numframes;
|
|
nengel@2
|
43
|
|
nengel@2
|
44 h->frame_width = width;
|
|
nengel@2
|
45 h->frame_height = height;
|
|
nengel@2
|
46
|
|
nengel@2
|
47 while ((width/2) %STRIDE_ALIGN)
|
|
nengel@2
|
48 width+=STRIDE_ALIGN;
|
|
nengel@2
|
49 h->width = width;
|
|
nengel@2
|
50 h->height = mb_height*16;
|
|
nengel@2
|
51
|
|
nengel@2
|
52 h->mb_height = mb_height;
|
|
nengel@2
|
53 h->mb_width = mb_width;
|
|
nengel@2
|
54 h->mb_stride = mb_stride;
|
|
nengel@2
|
55 h->b4_stride = mb_width*4 + 1;
|
|
nengel@2
|
56 h->b_stride = mb_width*4;
|
|
nengel@2
|
57
|
|
nengel@2
|
58 h->smb_width = opts->smb_size[0];
|
|
nengel@2
|
59 h->smb_height = opts->smb_size[1] < h->smb_width ? opts->smb_size[1] : h->smb_width;
|
|
nengel@2
|
60 h->smbc = getSuperMBContext(h, h->smb_width, h->smb_height);
|
|
nengel@2
|
61
|
|
nengel@2
|
62 h->wave_order = opts->wave_order;
|
|
nengel@2
|
63
|
|
nengel@2
|
64 h->pipe_bufs = opts->pipe_bufs;
|
|
nengel@2
|
65
|
|
nengel@2
|
66 h->max_dpb_cnt = DPB_SIZE + opts->pipe_bufs;
|
|
nengel@2
|
67 h->free_dpb_cnt = h->max_dpb_cnt;
|
|
nengel@2
|
68 h->dpb = av_mallocz (h->max_dpb_cnt* sizeof (DecodedPicture));
|
|
nengel@2
|
69
|
|
nengel@2
|
70
|
|
nengel@2
|
71 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
|
72 h->sb_size = h->free_sb_cnt;
|
|
nengel@2
|
73 h->sb = av_mallocz(h->sb_size* sizeof(SliceBufferEntry));
|
|
nengel@2
|
74
|
|
nengel@2
|
75 h->rl_q.size = FFMAX(1, FFMIN( (h->height-3 - 512)/16, h->mb_width/2)) +1;
|
|
nengel@2
|
76 h->rl_q.free = h->rl_q.size -1;
|
|
nengel@2
|
77 h->rl_q.ready=0;
|
|
nengel@2
|
78 h->rl_q.fi = h->rl_q.fo= 0;
|
|
nengel@2
|
79 h->rl_q.queue = av_malloc(h->rl_q.size* sizeof(RingLineEntry*));
|
|
nengel@2
|
80 for (i=0; i<h->rl_q.size; i++){
|
|
nengel@2
|
81 if( posix_memalign((void**)&h->rl_q.queue[i],64,sizeof(RingLineEntry)))
|
|
nengel@2
|
82 h->rl_q.queue[i]=NULL;
|
|
nengel@2
|
83 h->rl_q.queue[i]->top = av_malloc(h->mb_width*sizeof(TopBorder));
|
|
nengel@2
|
84 }
|
|
nengel@2
|
85
|
|
nengel@2
|
86 h->rl_q.queue[0]->prev_line = h->rl_q.queue[h->rl_q.size-1];
|
|
nengel@2
|
87 for (i=1; i<h->rl_q.size; i++){
|
|
nengel@2
|
88 h->rl_q.queue[i]->prev_line = h->rl_q.queue[i-1];
|
|
nengel@2
|
89 }
|
|
nengel@2
|
90
|
|
nengel@2
|
91 if( HAVE_MMX | HAVE_ALTIVEC| HAVE_NEON ){
|
|
nengel@2
|
92 for(i=0; i<16; i++){
|
|
nengel@2
|
93 #define T(x) (x>>2) | ((x<<2) & 0xF)
|
|
nengel@2
|
94 h->zigzag_scan[i] = T(zigzag_scan[i]);
|
|
nengel@2
|
95 #undef T
|
|
nengel@2
|
96 }
|
|
nengel@2
|
97 for(i=0; i<64; i++){
|
|
nengel@2
|
98 #define T(x) (x>>3) | ((x&7)<<3)
|
|
nengel@2
|
99 h->zigzag_scan8x8[i] = T(ff_zigzag_direct[i]);
|
|
nengel@2
|
100 #undef T
|
|
nengel@2
|
101 }
|
|
nengel@2
|
102 }else{
|
|
nengel@2
|
103 memcpy(h->zigzag_scan, zigzag_scan, 16*sizeof(uint8_t));
|
|
nengel@2
|
104 memcpy(h->zigzag_scan8x8, ff_zigzag_direct, 64*sizeof(uint8_t));
|
|
nengel@2
|
105 }
|
|
nengel@2
|
106
|
|
nengel@2
|
107 pthread_mutex_init(&h->smb_lock, NULL);
|
|
nengel@2
|
108 pthread_mutex_init(&h->sdl_lock, NULL);
|
|
nengel@2
|
109 pthread_cond_init(&h->sdl_cond, NULL);
|
|
nengel@2
|
110
|
|
nengel@2
|
111 ///pthread initialization
|
|
nengel@2
|
112 pthread_mutex_init(&h->ilock, NULL);
|
|
nengel@2
|
113 pthread_cond_init(&h->icond, NULL);
|
|
nengel@2
|
114 pthread_mutex_init(&h->slock, NULL);
|
|
nengel@2
|
115 pthread_cond_init(&h->scond, NULL);
|
|
nengel@2
|
116 pthread_mutex_init(&h->tlock, NULL);
|
|
nengel@2
|
117 pthread_cond_init(&h->tcond, NULL);
|
|
nengel@2
|
118 pthread_mutex_init(&h->tdlock, NULL);
|
|
nengel@2
|
119 pthread_cond_init(&h->tdcond, NULL);
|
|
nengel@2
|
120 h->start =!opts->numamap; //default dont wait for start signal
|
|
nengel@2
|
121 h->statmbd = opts->statmbd;
|
|
nengel@2
|
122 h->rl_side_touch= opts->numamap;
|
|
nengel@2
|
123 h->touch_start=0;
|
|
nengel@2
|
124 h->setaff =opts->statsched;
|
|
nengel@2
|
125 h->init_threads=0;
|
|
nengel@2
|
126
|
|
nengel@2
|
127 pthread_mutex_init(&h->task_lock, NULL);
|
|
nengel@2
|
128 pthread_cond_init(&h->task_cond, NULL);
|
|
nengel@2
|
129 for (i=0; i<STAGES; i++){
|
|
nengel@2
|
130 pthread_mutex_init (&h->lock[i], NULL);
|
|
nengel@2
|
131 pthread_cond_init (&h->cond[i], NULL);
|
|
nengel@2
|
132
|
|
nengel@2
|
133 pthread_mutex_init (&h->sb_q[i].lock, NULL);
|
|
nengel@2
|
134 pthread_cond_init (&h->sb_q[i].cond, NULL);
|
|
nengel@2
|
135 h->sb_q[i].size = h->free_sb_cnt; //change to num threads later
|
|
nengel@2
|
136 h->sb_q[i].queue = av_malloc(h->free_sb_cnt* sizeof(SliceBufferEntry*));
|
|
nengel@2
|
137 h->sb_q[i].cnt = h->sb_q[i].fi = h->sb_q[i].fo =0;
|
|
nengel@2
|
138 }
|
|
nengel@2
|
139
|
|
nengel@2
|
140 #if HAVE_LIBSDL2
|
|
nengel@2
|
141 h->sdlq.size=2;
|
|
nengel@2
|
142 h->sdlq.ready=2;
|
|
nengel@2
|
143 h->sdlq.queue = av_malloc(2* sizeof(SDL_Texture*));
|
|
nengel@2
|
144 pthread_mutex_init (&h->sdlq.sdl_lock, NULL);
|
|
nengel@2
|
145 pthread_cond_init (&h->sdlq.sdl_cond, NULL);
|
|
nengel@2
|
146 #endif
|
|
nengel@2
|
147
|
|
nengel@2
|
148 h->display=opts->display;
|
|
nengel@2
|
149 h->fullscreen=opts->fullscreen;
|
|
nengel@2
|
150
|
|
nengel@2
|
151 return h;
|
|
nengel@2
|
152 }
|
|
nengel@2
|
153
|
|
nengel@2
|
154
|
|
nengel@2
|
155 void free_h264dec_context(H264Context *h) {
|
|
nengel@2
|
156 int i;
|
|
nengel@2
|
157
|
|
nengel@2
|
158 for(i=0; i<h->max_dpb_cnt; i++)
|
|
nengel@2
|
159 free_dp(&h->dpb[i]);
|
|
nengel@2
|
160 av_free (h->dpb);
|
|
nengel@2
|
161
|
|
nengel@2
|
162 for(i=0; i<h->sb_size; i++){
|
|
nengel@2
|
163 if (h->sb[i].initialized){
|
|
nengel@2
|
164 free_sb_entry(&h->sb[i]);
|
|
nengel@2
|
165 }
|
|
nengel@2
|
166 }
|
|
nengel@2
|
167 av_freep(&h->sb);
|
|
nengel@2
|
168
|
|
nengel@2
|
169 for (i=0; i<h->rl_q.size; i++){
|
|
nengel@2
|
170 av_freep(&h->rl_q.queue[i]->top);
|
|
nengel@2
|
171 av_freep(&h->rl_q.queue[i]);
|
|
nengel@2
|
172 }
|
|
nengel@2
|
173 av_freep(&h->rl_q.queue);
|
|
nengel@2
|
174
|
|
nengel@2
|
175 ///pthread cleanup
|
|
nengel@2
|
176 pthread_mutex_destroy (&h->task_lock);
|
|
nengel@2
|
177 pthread_cond_destroy (&h->task_cond);
|
|
nengel@2
|
178 for (i=0; i<STAGES; i++){
|
|
nengel@2
|
179 pthread_mutex_destroy (&h->lock[i]);
|
|
nengel@2
|
180 pthread_cond_destroy (&h->cond[i]);
|
|
nengel@2
|
181
|
|
nengel@2
|
182 pthread_mutex_destroy (&h->sb_q[i].lock);
|
|
nengel@2
|
183 pthread_cond_destroy (&h->sb_q[i].cond);
|
|
nengel@2
|
184 av_freep( &h->sb_q[i].queue);
|
|
nengel@2
|
185 }
|
|
nengel@2
|
186 pthread_mutex_destroy (&h->slock);
|
|
nengel@2
|
187 pthread_cond_destroy (&h->scond);
|
|
nengel@2
|
188 pthread_mutex_destroy (&h->ilock);
|
|
nengel@2
|
189 pthread_cond_destroy (&h->icond);
|
|
nengel@2
|
190
|
|
nengel@2
|
191 pthread_mutex_destroy(&h->smb_lock);
|
|
nengel@2
|
192 pthread_mutex_destroy (&h->sdl_lock);
|
|
nengel@2
|
193 pthread_cond_destroy (&h->sdl_cond);
|
|
nengel@2
|
194 #if HAVE_LIBSDL2
|
|
nengel@2
|
195 av_free(h->sdlq.queue);
|
|
nengel@2
|
196 pthread_mutex_destroy (&h->sdlq.sdl_lock);
|
|
nengel@2
|
197 pthread_cond_destroy (&h->sdlq.sdl_cond);
|
|
nengel@2
|
198 #endif
|
|
nengel@2
|
199
|
|
nengel@2
|
200 stop_timer(h, TOTAL);
|
|
nengel@2
|
201 if (h->threads==0){
|
|
nengel@2
|
202 for (i=0; i<PROFILE_STAGES; i++)
|
|
nengel@2
|
203 h->total_time[i] /= h->num_frames;
|
|
nengel@2
|
204 double others = h->total_time[TOTAL];
|
|
nengel@2
|
205 for (i=1; i<PROFILE_STAGES; i++)
|
|
nengel@2
|
206 others-=h->total_time[i];
|
|
nengel@2
|
207 if (h->profile == 1){
|
|
nengel@2
|
208 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
|
209 }else if (h->profile ==2){
|
|
nengel@2
|
210 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
|
211 }
|
|
nengel@2
|
212 }
|
|
nengel@2
|
213
|
|
nengel@2
|
214 av_free(h);
|
|
nengel@2
|
215 } |