| 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 }
|