1 /* fifo.c
2
3 Copyright (c) 2003-2021 HandBrake Team
4 This file is part of the HandBrake source code
5 Homepage: <http://handbrake.fr/>.
6 It may be used under the terms of the GNU General Public License v2.
7 For full terms see the file COPYING file or visit http://www.gnu.org/licenses/gpl-2.0.html
8 */
9
10 #include "libavcodec/avcodec.h"
11
12 #include "handbrake/handbrake.h"
13 #if HB_PROJECT_FEATURE_QSV
14 #include "handbrake/qsv_libav.h"
15 #include "handbrake/qsv_common.h"
16 #endif
17
18 #ifndef SYS_DARWIN
19 #if defined( SYS_FREEBSD ) || defined ( __FreeBSD__ ) || defined(SYS_NETBSD)
20 #include <stdlib.h>
21 #else
22 #include <malloc.h>
23 #endif
24 #endif
25
26 #define FIFO_TIMEOUT 200
27 //#define HB_FIFO_DEBUG 1
28 // defining HB_BUFFER_DEBUG and HB_NO_BUFFER_POOL allows tracking
29 // buffer memory leaks using valgrind. The source of the leak
30 // can be determined with "valgrind --leak-check=full"
31 //#define HB_BUFFER_DEBUG 1
32 //#define HB_NO_BUFFER_POOL 1
33
34 #if defined(HB_BUFFER_DEBUG)
35 #include <assert.h>
36 #endif
37
38 /* Fifo */
39 struct hb_fifo_s
40 {
41 hb_lock_t * lock;
42 hb_cond_t * cond_full;
43 int wait_full;
44 hb_cond_t * cond_empty;
45 int wait_empty;
46 hb_cond_t * cond_alert_full;
47 uint32_t capacity;
48 uint32_t thresh;
49 uint32_t size;
50 uint32_t buffer_size;
51 hb_buffer_t * first;
52 hb_buffer_t * last;
53
54 #if defined(HB_FIFO_DEBUG)
55 // Fifo list for debugging
56 hb_fifo_t * next;
57 #endif
58 };
59
60 #if defined(HB_FIFO_DEBUG)
61 static hb_fifo_t fifo_list =
62 {
63 .next = NULL
64 };
65 #endif
66
67 /* we round the requested buffer size up to the next power of 2 so there can
68 * be at most 32 possible pools when the size is a 32 bit int. To avoid a lot
69 * of slow & error-prone run-time checking we allow for all 32. */
70 #define MAX_BUFFER_POOLS 32
71 #define BUFFER_POOL_FIRST 10
72 #define BUFFER_POOL_LAST 25
73 /* the buffer pool only exists to avoid the two malloc and two free calls that
74 * it would otherwise take to allocate & free a buffer. but we don't want to
75 * tie up a lot of memory in the pool because this allocator isn't as general
76 * as malloc so memory tied up here puts more pressure on the malloc pool.
77 * A pool of 16 elements will avoid 94% of the malloc/free calls without wasting
78 * too much memory. */
79 #define BUFFER_POOL_MAX_ELEMENTS 32
80
81 struct hb_buffer_pools_s
82 {
83 int64_t allocated;
84 hb_lock_t *lock;
85 #if !defined(HB_NO_BUFFER_POOL)
86 hb_fifo_t *pool[MAX_BUFFER_POOLS];
87 #endif
88 #if defined(HB_BUFFER_DEBUG)
89 hb_list_t *alloc_list;
90 #endif
91 } buffers;
92
93
94 #if defined(HB_BUFFER_DEBUG)
95 static int hb_fifo_contains( hb_fifo_t *f, hb_buffer_t *b );
96 #endif
97
hb_buffer_pool_init(void)98 void hb_buffer_pool_init( void )
99 {
100 buffers.lock = hb_lock_init();
101 buffers.allocated = 0;
102
103 #if defined(HB_BUFFER_DEBUG)
104 buffers.alloc_list = hb_list_init();
105 #endif
106
107 #if !defined(HB_NO_BUFFER_POOL)
108 /* we allocate pools for sizes 2^10 through 2^25. requests larger than
109 * 2^25 will get passed through to malloc. */
110 int i;
111
112 // Create larger queue for 2^10 bucket since all allocations smaller than
113 // 2^10 come from here.
114 buffers.pool[BUFFER_POOL_FIRST] = hb_fifo_init(BUFFER_POOL_MAX_ELEMENTS*10, 1);
115 buffers.pool[BUFFER_POOL_FIRST]->buffer_size = 1 << 10;
116
117 /* requests smaller than 2^10 are satisfied from the 2^10 pool. */
118 for ( i = 1; i < BUFFER_POOL_FIRST; ++i )
119 {
120 buffers.pool[i] = buffers.pool[BUFFER_POOL_FIRST];
121 }
122 for ( i = BUFFER_POOL_FIRST + 1; i <= BUFFER_POOL_LAST; ++i )
123 {
124 buffers.pool[i] = hb_fifo_init(BUFFER_POOL_MAX_ELEMENTS, 1);
125 buffers.pool[i]->buffer_size = 1 << i;
126 }
127 #endif
128 }
129
130 #if defined(HB_FIFO_DEBUG)
131
dump_fifo(hb_fifo_t * f)132 static void dump_fifo(hb_fifo_t * f)
133 {
134 hb_buffer_t * b = f->first;
135
136 if (b)
137 {
138 while (b)
139 {
140 fprintf(stderr, "%p:%d:%d\n", b, b->size, b->alloc);
141 b = b->next;
142 }
143 fprintf(stderr, "\n");
144 }
145 }
146
fifo_list_add(hb_fifo_t * f)147 static void fifo_list_add( hb_fifo_t * f )
148 {
149 hb_fifo_t *next = fifo_list.next;
150
151 fifo_list.next = f;
152 f->next = next;
153 }
154
fifo_list_rem(hb_fifo_t * f)155 static void fifo_list_rem( hb_fifo_t * f )
156 {
157 hb_fifo_t *next, *prev;
158
159 prev = &fifo_list;
160 next = fifo_list.next;
161
162 while ( next && next != f )
163 {
164 prev = next;
165 next = next->next;
166 }
167 if ( next == f )
168 {
169 prev->next = f->next;
170 }
171 }
172
173 #if !defined(HB_NO_BUFFER_POOL)
174 // These routines are useful for finding and debugging problems
175 // with the fifos and buffer pools
buffer_pool_validate(hb_fifo_t * f)176 static void buffer_pool_validate( hb_fifo_t * f )
177 {
178 hb_buffer_t *b;
179
180 hb_lock( f->lock );
181 b = f->first;
182 while (b)
183 {
184 if (b->alloc != f->buffer_size)
185 {
186 fprintf(stderr, "Invalid buffer pool size! buf %p size %d pool size %d\n", b, b->alloc, f->buffer_size);
187 dump_fifo( f );
188 *(char*)0 = 1;
189 }
190 b = b->next;
191 }
192
193 hb_unlock( f->lock );
194 }
195
buffer_pools_validate(void)196 static void buffer_pools_validate( void )
197 {
198 int ii;
199 for ( ii = BUFFER_POOL_FIRST; ii <= BUFFER_POOL_LAST; ++ii )
200 {
201 buffer_pool_validate( buffers.pool[ii] );
202 }
203 }
204
fifo_list_validate(void)205 void fifo_list_validate( void )
206 {
207 hb_fifo_t *next = fifo_list.next;
208 hb_fifo_t *m;
209 hb_buffer_t *b, *c;
210 int count;
211
212 buffer_pools_validate();
213 while ( next )
214 {
215 count = 0;
216 hb_lock( next->lock );
217 b = next->first;
218
219 // Count the number of entries in this fifo
220 while (b)
221 {
222 c = b->next;
223 // check that the current buffer is not duplicated in this fifo
224 while (c)
225 {
226 if (c == b)
227 {
228 fprintf(stderr, "Duplicate buffer in fifo!\n");
229 dump_fifo(next);
230 *(char*)0 = 1;
231 }
232 c = c->next;
233 }
234
235 // check that the current buffer is not duplicated in another fifo
236 m = next->next;
237 while (m)
238 {
239 hb_lock( m->lock );
240 c = m->first;
241 while (c)
242 {
243 if (c == b)
244 {
245 fprintf(stderr, "Duplicate buffer in another fifo!\n");
246 dump_fifo(next);
247 *(char*)0 = 1;
248 }
249 c = c->next;
250 }
251 hb_unlock( m->lock );
252 m = m->next;
253 }
254
255 count++;
256 b = b->next;
257 }
258
259 if ( count != next->size )
260 {
261 fprintf(stderr, "Invalid fifo size! count %d size %d\n", count, next->size);
262 dump_fifo(next);
263 *(char*)0 = 1;
264 }
265 hb_unlock( next->lock );
266
267 next = next->next;
268 }
269 }
270 #endif
271 #endif
272
hb_buffer_pool_free(void)273 void hb_buffer_pool_free( void )
274 {
275 int i;
276 int64_t freed = 0;
277
278 hb_lock(buffers.lock);
279
280 #if defined(HB_BUFFER_DEBUG)
281 hb_deep_log(2, "leaked %d buffers", hb_list_count(buffers.alloc_list));
282 for (i = 0; i < hb_list_count(buffers.alloc_list); i++)
283 {
284 hb_buffer_t *b = hb_list_item(buffers.alloc_list, i);
285 hb_deep_log(2, "leaked buffer %p type %d size %d alloc %d",
286 b, b->s.type, b->size, b->alloc);
287 }
288 #endif
289
290 #if !defined(HB_NO_BUFFER_POOL)
291 hb_buffer_t * b;
292 int count;
293 for( i = BUFFER_POOL_FIRST; i <= BUFFER_POOL_LAST; ++i)
294 {
295 count = 0;
296 while( ( b = hb_fifo_get(buffers.pool[i]) ) )
297 {
298 if( b->data )
299 {
300 freed += b->alloc;
301 av_free(b->data);
302 }
303 free( b );
304 count++;
305 }
306 if ( count )
307 {
308 hb_deep_log( 2, "Freed %d buffers of size %d", count,
309 buffers.pool[i]->buffer_size);
310 }
311 }
312 #endif
313
314 #if defined(HB_BUFFER_DEBUG) && defined(HB_NO_BUFFER_POOL)
315 // defining HB_BUFFER_DEBUG and HB_NO_BUFFER_POOL allows tracking
316 // buffer memory leaks using valgrind. The source of the leak
317 // can be determined with "valgrind --leak-check=full"
318 for (i = 0; i < hb_list_count(buffers.alloc_list); i++)
319 {
320 hb_buffer_t *b = hb_list_item(buffers.alloc_list, i);
321 hb_list_rem(buffers.alloc_list, b);
322 }
323 #endif
324
325 hb_deep_log( 2, "Allocated %"PRId64" bytes of buffers on this pass and Freed %"PRId64" bytes, "
326 "%"PRId64" bytes leaked", buffers.allocated, freed, buffers.allocated - freed);
327 buffers.allocated = 0;
328 hb_unlock(buffers.lock);
329 }
330
size_to_pool(int size)331 static hb_fifo_t *size_to_pool( int size )
332 {
333 #if !defined(HB_NO_BUFFER_POOL)
334 int i;
335 for ( i = BUFFER_POOL_FIRST; i <= BUFFER_POOL_LAST; ++i )
336 {
337 if ( size <= (1 << i) )
338 {
339 return buffers.pool[i];
340 }
341 }
342 #endif
343 return NULL;
344 }
345
hb_buffer_init_internal(int size)346 hb_buffer_t * hb_buffer_init_internal( int size )
347 {
348 hb_buffer_t * b;
349 // Certain libraries (hrm ffmpeg) expect buffers passed to them to
350 // end on certain alignments (ffmpeg is 8). So allocate some extra bytes.
351 // Note that we can't simply align the end of our buffer because
352 // sometimes we feed data to these libraries starting from arbitrary
353 // points within the buffer.
354 int alloc = size + AV_INPUT_BUFFER_PADDING_SIZE;
355 hb_fifo_t *buffer_pool = size_to_pool( alloc );
356
357 if( buffer_pool )
358 {
359 b = hb_fifo_get( buffer_pool );
360
361 if( b )
362 {
363 /*
364 * Zero the contents of the buffer, would be nice if we
365 * didn't have to do this.
366 */
367 uint8_t *data = b->data;
368
369 memset( b, 0, sizeof(hb_buffer_t) );
370 b->alloc = buffer_pool->buffer_size;
371 b->size = size;
372 b->data = data;
373 b->s.start = AV_NOPTS_VALUE;
374 b->s.stop = AV_NOPTS_VALUE;
375 b->s.renderOffset = AV_NOPTS_VALUE;
376 b->s.scr_sequence = -1;
377
378 #if defined(HB_BUFFER_DEBUG)
379 hb_lock(buffers.lock);
380 hb_list_add(buffers.alloc_list, b);
381 hb_unlock(buffers.lock);
382 #endif
383 return( b );
384 }
385 }
386
387 /*
388 * No existing buffers, create a new one
389 */
390 if( !( b = calloc( sizeof( hb_buffer_t ), 1 ) ) )
391 {
392 hb_error( "out of memory" );
393 return NULL;
394 }
395
396 b->size = size;
397 b->alloc = buffer_pool ? buffer_pool->buffer_size : alloc;
398
399 if (size)
400 {
401 b->data = av_malloc(b->alloc);
402 if( !b->data )
403 {
404 hb_error( "out of memory" );
405 free( b );
406 return NULL;
407 }
408 #if defined(HB_BUFFER_DEBUG)
409 memset(b->data, 0, b->size);
410 #endif
411 hb_lock(buffers.lock);
412 buffers.allocated += b->alloc;
413 hb_unlock(buffers.lock);
414 }
415 b->s.start = AV_NOPTS_VALUE;
416 b->s.stop = AV_NOPTS_VALUE;
417 b->s.renderOffset = AV_NOPTS_VALUE;
418 b->s.scr_sequence = -1;
419 #if defined(HB_BUFFER_DEBUG)
420 hb_lock(buffers.lock);
421 hb_list_add(buffers.alloc_list, b);
422 hb_unlock(buffers.lock);
423 #endif
424 return b;
425 }
426
hb_buffer_init(int size)427 hb_buffer_t * hb_buffer_init( int size )
428 {
429 return hb_buffer_init_internal(size);
430 }
431
hb_buffer_eof_init(void)432 hb_buffer_t * hb_buffer_eof_init(void)
433 {
434 hb_buffer_t * buf = hb_buffer_init(0);
435 buf->s.flags = HB_BUF_FLAG_EOF;
436 return buf;
437 }
438
hb_buffer_realloc(hb_buffer_t * b,int size)439 void hb_buffer_realloc( hb_buffer_t * b, int size )
440 {
441 if ( size > b->alloc || b->data == NULL )
442 {
443 uint8_t * tmp;
444 uint32_t orig = b->data != NULL ? b->alloc : 0;
445 hb_fifo_t * buffer_pool = size_to_pool(size);
446
447 if (buffer_pool != NULL)
448 {
449 size = buffer_pool->buffer_size;
450 }
451 tmp = av_malloc(size);
452 if (tmp == NULL)
453 {
454 return;
455 }
456 if (b->data != NULL)
457 {
458 memcpy(tmp, b->data, b->alloc);
459 av_free(b->data);
460 }
461 b->data = tmp;
462 b->alloc = size;
463
464 hb_lock(buffers.lock);
465 buffers.allocated += size - orig;
466 hb_unlock(buffers.lock);
467 }
468 }
469
hb_buffer_reduce(hb_buffer_t * b,int size)470 void hb_buffer_reduce( hb_buffer_t * b, int size )
471 {
472
473 if ( size < b->alloc / 8 || b->data == NULL )
474 {
475 hb_buffer_t * tmp = hb_buffer_init( size );
476
477 hb_buffer_swap_copy( b, tmp );
478 memcpy( b->data, tmp->data, size );
479 tmp->next = NULL;
480 hb_buffer_close( &tmp );
481 }
482 }
483
hb_buffer_dup(const hb_buffer_t * src)484 hb_buffer_t * hb_buffer_dup( const hb_buffer_t * src )
485 {
486
487 hb_buffer_t * buf;
488
489 if ( src == NULL )
490 return NULL;
491
492 buf = hb_buffer_init( src->size );
493 if ( buf )
494 {
495 memcpy( buf->data, src->data, src->size );
496 buf->s = src->s;
497 buf->f = src->f;
498 if ( buf->s.type == FRAME_BUF )
499 hb_buffer_init_planes( buf );
500 }
501
502 #if HB_PROJECT_FEATURE_QSV
503 memcpy(&buf->qsv_details, &src->qsv_details, sizeof(src->qsv_details));
504 #endif
505
506 return buf;
507 }
508
hb_buffer_copy(hb_buffer_t * dst,const hb_buffer_t * src)509 int hb_buffer_copy(hb_buffer_t * dst, const hb_buffer_t * src)
510 {
511 if (src == NULL || dst == NULL)
512 return -1;
513
514 if ( dst->size < src->size )
515 return -1;
516
517 memcpy( dst->data, src->data, src->size );
518 dst->s = src->s;
519 dst->f = src->f;
520 if (dst->s.type == FRAME_BUF)
521 hb_buffer_init_planes(dst);
522
523 return 0;
524 }
525
hb_buffer_init_planes(hb_buffer_t * b)526 void hb_buffer_init_planes(hb_buffer_t * b)
527 {
528 uint8_t * data = b->data;
529 int pp;
530
531 for( pp = 0; pp <= b->f.max_plane; pp++ )
532 {
533 b->plane[pp].data = data;
534 b->plane[pp].stride = hb_image_stride(b->f.fmt, b->f.width, pp);
535 b->plane[pp].height_stride = hb_image_height_stride(b->f.fmt,
536 b->f.height, pp);
537 b->plane[pp].width = hb_image_width(b->f.fmt, b->f.width, pp);
538 b->plane[pp].height = hb_image_height(b->f.fmt, b->f.height, pp);
539 b->plane[pp].size = b->plane[pp].stride *
540 b->plane[pp].height_stride;
541 data += b->plane[pp].size;
542 }
543 }
544
545 // this routine gets a buffer for an uncompressed picture
546 // with pixel format pix_fmt and dimensions width x height.
hb_frame_buffer_init(int pix_fmt,int width,int height)547 hb_buffer_t * hb_frame_buffer_init( int pix_fmt, int width, int height )
548 {
549 const AVPixFmtDescriptor * desc = av_pix_fmt_desc_get(pix_fmt);
550 hb_buffer_t * buf;
551 uint8_t has_plane[4] = {0,};
552 int ii, pp, max_plane = 0;
553
554 if (desc == NULL)
555 {
556 return NULL;
557 }
558
559 int size = 0;
560 for (ii = 0; ii < desc->nb_components; ii++)
561 {
562 pp = desc->comp[ii].plane;
563 if (pp > max_plane)
564 {
565 max_plane = pp;
566 }
567 if (!has_plane[pp])
568 {
569 has_plane[pp] = 1;
570 size += hb_image_stride( pix_fmt, width, pp ) *
571 hb_image_height_stride( pix_fmt, height, pp );
572 }
573 }
574
575 buf = hb_buffer_init_internal(size);
576
577 if( buf == NULL )
578 return NULL;
579
580 buf->f.max_plane = max_plane;
581 buf->s.type = FRAME_BUF;
582 buf->f.width = width;
583 buf->f.height = height;
584 buf->f.fmt = pix_fmt;
585
586 hb_buffer_init_planes(buf);
587 return buf;
588 }
589
hb_frame_buffer_blank_stride(hb_buffer_t * buf)590 void hb_frame_buffer_blank_stride(hb_buffer_t * buf)
591 {
592 uint8_t * data;
593 int pp, yy, width, height, stride, height_stride;
594
595 for (pp = 0; pp <= buf->f.max_plane; pp++)
596 {
597 data = buf->plane[pp].data;
598 width = buf->plane[pp].width;
599 height = buf->plane[pp].height;
600 stride = buf->plane[pp].stride;
601 height_stride = buf->plane[pp].height_stride;
602
603 if (data != NULL)
604 {
605 // Blank right margin
606 for (yy = 0; yy < height; yy++)
607 {
608 memset(data + yy * stride + width, 0x80, stride - width);
609 }
610 // Blank bottom margin
611 for (yy = height; yy < height_stride; yy++)
612 {
613 memset(data + yy * stride, 0x80, stride);
614 }
615 }
616 }
617 }
618
hb_frame_buffer_mirror_stride(hb_buffer_t * buf)619 void hb_frame_buffer_mirror_stride(hb_buffer_t * buf)
620 {
621 uint8_t * data;
622 int pp, ii, yy, width, height, stride, height_stride;
623 int pos, margin, margin_front, margin_back;
624
625 for (pp = 0; pp <= buf->f.max_plane; pp++)
626 {
627 data = buf->plane[pp].data;
628 width = buf->plane[pp].width;
629 height = buf->plane[pp].height;
630 stride = buf->plane[pp].stride;
631 height_stride = buf->plane[pp].height_stride;
632 if (data != NULL)
633 {
634 margin = stride - width;
635 margin_front = margin / 2;
636 margin_back = margin - margin_front;
637 for (yy = 0; yy < height; yy++)
638 {
639 // Mirror final row pixels into front of stride region
640 pos = yy * stride + width;
641 for (ii = 0; ii < margin_back; ii++)
642 {
643 *(data + pos + ii) = *(data + pos - ii - 1);
644 }
645 // Mirror start of next row into end of stride region
646 pos = (yy + 1) * stride - 1;
647 for (ii = 0; ii < margin_front; ii++)
648 {
649 *(data + pos - ii) = *(data + pos + ii + 1);
650 }
651 }
652 // Mirror bottom rows into height_stride
653 pos = height * stride;
654 for (ii = 0; ii < height_stride - height; ii++)
655 {
656 memcpy(data + pos + ii * stride,
657 data + pos - ((ii + 1) * stride), stride);
658 }
659 }
660 }
661 }
662
663 // this routine reallocs a buffer for an uncompressed YUV420 video frame
664 // with dimensions width x height.
hb_video_buffer_realloc(hb_buffer_t * buf,int width,int height)665 void hb_video_buffer_realloc( hb_buffer_t * buf, int width, int height )
666 {
667 const AVPixFmtDescriptor * desc = av_pix_fmt_desc_get(buf->f.fmt);
668 uint8_t has_plane[4] = {0,};
669 int ii, pp;
670
671 if (desc == NULL)
672 {
673 return;
674 }
675
676 buf->f.max_plane = 0;
677 int size = 0;
678 for (ii = 0; ii < desc->nb_components; ii++)
679 {
680 pp = desc->comp[ii].plane;
681 if (pp > buf->f.max_plane)
682 {
683 buf->f.max_plane = pp;
684 }
685 if (!has_plane[pp])
686 {
687 has_plane[pp] = 1;
688 size += hb_image_stride(buf->f.fmt, width, pp) *
689 hb_image_height_stride(buf->f.fmt, height, pp );
690 }
691 }
692
693 hb_buffer_realloc(buf, size );
694
695 buf->f.width = width;
696 buf->f.height = height;
697 buf->size = size;
698
699 hb_buffer_init_planes(buf);
700 }
701
702 // this routine 'moves' data from src to dst by interchanging 'data',
703 // 'size' & 'alloc' between them and copying the rest of the fields
704 // from src to dst.
hb_buffer_swap_copy(hb_buffer_t * src,hb_buffer_t * dst)705 void hb_buffer_swap_copy( hb_buffer_t *src, hb_buffer_t *dst )
706 {
707 uint8_t *data = dst->data;
708 int size = dst->size;
709 int alloc = dst->alloc;
710
711 *dst = *src;
712
713 src->data = data;
714 src->size = size;
715 src->alloc = alloc;
716 }
717
718 // Frees the specified buffer list.
hb_buffer_close(hb_buffer_t ** _b)719 void hb_buffer_close( hb_buffer_t ** _b )
720 {
721 hb_buffer_t * b = *_b;
722
723 while( b )
724 {
725 #if HB_PROJECT_FEATURE_QSV
726 // Reclaim QSV resources before dropping the buffer.
727 // when decoding without QSV, the QSV atom will be NULL.
728 if(b->qsv_details.frame && b->qsv_details.ctx != NULL)
729 {
730 mfxFrameSurface1 *surface = (mfxFrameSurface1*)b->qsv_details.frame->data[3];
731 if(surface)
732 {
733 hb_qsv_release_surface_from_pool_by_surface_pointer(b->qsv_details.qsv_frames_ctx, surface);
734 b->qsv_details.frame->data[3] = 0;
735 }
736 av_frame_unref(b->qsv_details.frame);
737 }
738 if (b->qsv_details.qsv_atom != NULL && b->qsv_details.ctx != NULL)
739 {
740 hb_qsv_stage *stage = hb_qsv_get_last_stage(b->qsv_details.qsv_atom);
741 if (stage != NULL)
742 {
743 hb_qsv_wait_on_sync(b->qsv_details.ctx, stage);
744 if (stage->out.sync->in_use > 0)
745 {
746 ff_qsv_atomic_dec(&stage->out.sync->in_use);
747 }
748 if (stage->out.p_surface->Data.Locked > 0)
749 {
750 ff_qsv_atomic_dec(&stage->out.p_surface->Data.Locked);
751 }
752 }
753 hb_qsv_flush_stages(b->qsv_details.ctx->pipes,
754 (hb_qsv_list**)&b->qsv_details.qsv_atom);
755 }
756 #endif
757
758 hb_buffer_t * next = b->next;
759 hb_fifo_t *buffer_pool = size_to_pool( b->alloc );
760
761 b->next = NULL;
762
763 #if defined(HB_BUFFER_DEBUG)
764 hb_lock(buffers.lock);
765 hb_list_rem(buffers.alloc_list, b);
766 hb_unlock(buffers.lock);
767 #endif
768 if( buffer_pool && b->data && !hb_fifo_is_full( buffer_pool ) )
769 {
770 #if defined(HB_BUFFER_DEBUG)
771 if (hb_fifo_contains(buffer_pool, b))
772 {
773 hb_error("hb_buffer_close: buffer %p already freed", b);
774 assert(0);
775 }
776 #endif
777 hb_fifo_push_head( buffer_pool, b );
778 b = next;
779 continue;
780 }
781 // either the pool is full or this size doesn't use a pool
782 // free the buf
783 if( b->data )
784 {
785 av_free(b->data);
786 hb_lock(buffers.lock);
787 buffers.allocated -= b->alloc;
788 hb_unlock(buffers.lock);
789 }
790 free( b );
791 b = next;
792 }
793
794 *_b = NULL;
795 }
796
hb_image_init(int pix_fmt,int width,int height)797 hb_image_t * hb_image_init(int pix_fmt, int width, int height)
798 {
799 const AVPixFmtDescriptor * desc = av_pix_fmt_desc_get(pix_fmt);
800 uint8_t has_plane[4] = {0,};
801 int ii, pp;
802
803 if (desc == NULL)
804 {
805 return NULL;
806 }
807
808 hb_image_t *image = calloc(1, sizeof(hb_image_t));
809 if (image == NULL)
810 {
811 return NULL;
812 }
813
814 int size = 0;
815 for (ii = 0; ii < desc->nb_components; ii++)
816 {
817 // For non-planar formats, comp[ii].plane can contain the
818 // same value for multiple comp.
819 pp = desc->comp[ii].plane;
820 if (pp > image->max_plane)
821 {
822 image->max_plane = pp;
823 }
824 if (!has_plane[pp])
825 {
826 has_plane[pp] = 1;
827 size += hb_image_stride( pix_fmt, width, pp ) *
828 hb_image_height_stride( pix_fmt, height, pp );
829 }
830 }
831
832 image->data = av_malloc(size);
833 if (image->data == NULL)
834 {
835 free(image);
836 return NULL;
837 }
838 image->format = pix_fmt;
839 image->width = width;
840 image->height = height;
841 memset(image->data, 0, size);
842
843 uint8_t * data = image->data;
844 for (pp = 0; pp <= image->max_plane; pp++)
845 {
846 image->plane[pp].data = data;
847 image->plane[pp].stride = hb_image_stride(pix_fmt, width, pp);
848 image->plane[pp].height_stride =
849 hb_image_height_stride(pix_fmt, height, pp);
850 image->plane[pp].width = hb_image_width(pix_fmt, width, pp);
851 image->plane[pp].height = hb_image_height(pix_fmt, height, pp);
852 image->plane[pp].size = image->plane[pp].stride *
853 image->plane[pp].height_stride;
854 data += image->plane[pp].size;
855 }
856 return image;
857 }
858
hb_buffer_to_image(hb_buffer_t * buf)859 hb_image_t * hb_buffer_to_image(hb_buffer_t *buf)
860 {
861 hb_image_t *image = calloc(1, sizeof(hb_image_t));
862
863 image->data = av_malloc( buf->size );
864 if (image->data == NULL)
865 {
866 free(image);
867 return NULL;
868 }
869
870 image->format = buf->f.fmt;
871 image->width = buf->f.width;
872 image->height = buf->f.height;
873 image->color_prim = buf->f.color_prim;
874 image->color_transfer = buf->f.color_transfer;
875 image->color_matrix = buf->f.color_matrix;
876 memcpy(image->data, buf->data, buf->size);
877
878 int p;
879 uint8_t *data = image->data;
880 for (p = 0; p <= buf->f.max_plane; p++)
881 {
882 image->plane[p].data = data;
883 image->plane[p].width = buf->plane[p].width;
884 image->plane[p].height = buf->plane[p].height;
885 image->plane[p].stride = buf->plane[p].stride;
886 image->plane[p].height_stride = buf->plane[p].height_stride;
887 image->plane[p].size = buf->plane[p].size;
888 data += image->plane[p].size;
889 }
890 return image;
891 }
892
hb_image_close(hb_image_t ** _image)893 void hb_image_close(hb_image_t **_image)
894 {
895 if (_image == NULL)
896 return;
897
898 hb_image_t * image = *_image;
899 if (image != NULL)
900 {
901 av_free(image->data);
902 free(image);
903 *_image = NULL;
904 }
905 }
906
hb_fifo_init(int capacity,int thresh)907 hb_fifo_t * hb_fifo_init( int capacity, int thresh )
908 {
909 hb_fifo_t * f;
910 f = calloc( sizeof( hb_fifo_t ), 1 );
911 f->lock = hb_lock_init();
912 f->cond_full = hb_cond_init();
913 f->cond_empty = hb_cond_init();
914 f->capacity = capacity;
915 f->thresh = thresh;
916 f->buffer_size = 0;
917
918 #if defined(HB_FIFO_DEBUG)
919 // Add the fifo to the global fifo list
920 fifo_list_add( f );
921 #endif
922 return f;
923 }
924
hb_fifo_register_full_cond(hb_fifo_t * f,hb_cond_t * c)925 void hb_fifo_register_full_cond( hb_fifo_t * f, hb_cond_t * c )
926 {
927 f->cond_alert_full = c;
928 }
929
hb_fifo_size_bytes(hb_fifo_t * f)930 int hb_fifo_size_bytes( hb_fifo_t * f )
931 {
932 int ret = 0;
933 hb_buffer_t * link;
934
935 hb_lock( f->lock );
936 link = f->first;
937 while ( link )
938 {
939 ret += link->size;
940 link = link->next;
941 }
942 hb_unlock( f->lock );
943
944 return ret;
945 }
946
hb_fifo_size(hb_fifo_t * f)947 int hb_fifo_size( hb_fifo_t * f )
948 {
949 int ret;
950
951 hb_lock( f->lock );
952 ret = f->size;
953 hb_unlock( f->lock );
954
955 return ret;
956 }
957
hb_fifo_is_full(hb_fifo_t * f)958 int hb_fifo_is_full( hb_fifo_t * f )
959 {
960 int ret;
961
962 hb_lock( f->lock );
963 ret = ( f->size >= f->capacity );
964 hb_unlock( f->lock );
965
966 return ret;
967 }
968
hb_fifo_percent_full(hb_fifo_t * f)969 float hb_fifo_percent_full( hb_fifo_t * f )
970 {
971 float ret;
972
973 hb_lock( f->lock );
974 ret = f->size / f->capacity;
975 hb_unlock( f->lock );
976
977 return ret;
978 }
979
980 // Pulls the first packet out of this FIFO, blocking until such a packet is available.
981 // Returns NULL if this FIFO has been closed or flushed.
hb_fifo_get_wait(hb_fifo_t * f)982 hb_buffer_t * hb_fifo_get_wait( hb_fifo_t * f )
983 {
984 hb_buffer_t * b;
985
986 hb_lock( f->lock );
987 if( f->size < 1 )
988 {
989 f->wait_empty = 1;
990 hb_cond_timedwait( f->cond_empty, f->lock, FIFO_TIMEOUT );
991 if( f->size < 1 )
992 {
993 hb_unlock( f->lock );
994 return NULL;
995 }
996 }
997 b = f->first;
998 f->first = b->next;
999 b->next = NULL;
1000 f->size -= 1;
1001 if( f->wait_full && f->size == f->capacity - f->thresh )
1002 {
1003 f->wait_full = 0;
1004 hb_cond_signal( f->cond_full );
1005 }
1006 hb_unlock( f->lock );
1007
1008 return b;
1009 }
1010
1011 // Pulls a packet out of this FIFO, or returns NULL if no packet is available.
hb_fifo_get(hb_fifo_t * f)1012 hb_buffer_t * hb_fifo_get( hb_fifo_t * f )
1013 {
1014 hb_buffer_t * b;
1015
1016 hb_lock( f->lock );
1017 if( f->size < 1 )
1018 {
1019 hb_unlock( f->lock );
1020 return NULL;
1021 }
1022 b = f->first;
1023 f->first = b->next;
1024 b->next = NULL;
1025 f->size -= 1;
1026 if( f->wait_full && f->size == f->capacity - f->thresh )
1027 {
1028 f->wait_full = 0;
1029 hb_cond_signal( f->cond_full );
1030 }
1031 hb_unlock( f->lock );
1032
1033 return b;
1034 }
1035
hb_fifo_see_wait(hb_fifo_t * f)1036 hb_buffer_t * hb_fifo_see_wait( hb_fifo_t * f )
1037 {
1038 hb_buffer_t * b;
1039
1040 hb_lock( f->lock );
1041 if( f->size < 1 )
1042 {
1043 f->wait_empty = 1;
1044 hb_cond_timedwait( f->cond_empty, f->lock, FIFO_TIMEOUT );
1045 if( f->size < 1 )
1046 {
1047 hb_unlock( f->lock );
1048 return NULL;
1049 }
1050 }
1051 b = f->first;
1052 hb_unlock( f->lock );
1053
1054 return b;
1055 }
1056
1057 // Returns the first packet in the specified FIFO.
1058 // If the FIFO is empty, returns NULL.
hb_fifo_see(hb_fifo_t * f)1059 hb_buffer_t * hb_fifo_see( hb_fifo_t * f )
1060 {
1061 hb_buffer_t * b;
1062
1063 hb_lock( f->lock );
1064 if( f->size < 1 )
1065 {
1066 hb_unlock( f->lock );
1067 return NULL;
1068 }
1069 b = f->first;
1070 hb_unlock( f->lock );
1071
1072 return b;
1073 }
1074
hb_fifo_see2(hb_fifo_t * f)1075 hb_buffer_t * hb_fifo_see2( hb_fifo_t * f )
1076 {
1077 hb_buffer_t * b;
1078
1079 hb_lock( f->lock );
1080 if( f->size < 2 )
1081 {
1082 hb_unlock( f->lock );
1083 return NULL;
1084 }
1085 b = f->first->next;
1086 hb_unlock( f->lock );
1087
1088 return b;
1089 }
1090
1091 // Waits until the specified FIFO is no longer full or until FIFO_TIMEOUT milliseconds have elapsed.
1092 // Returns whether the FIFO is non-full upon return.
hb_fifo_full_wait(hb_fifo_t * f)1093 int hb_fifo_full_wait( hb_fifo_t * f )
1094 {
1095 int result;
1096
1097 hb_lock( f->lock );
1098 if( f->size >= f->capacity )
1099 {
1100 f->wait_full = 1;
1101 hb_cond_timedwait( f->cond_full, f->lock, FIFO_TIMEOUT );
1102 }
1103 result = ( f->size < f->capacity );
1104 hb_unlock( f->lock );
1105 return result;
1106 }
1107
1108 // Pushes the specified buffer onto the specified FIFO,
1109 // blocking until the FIFO has space available.
hb_fifo_push_wait(hb_fifo_t * f,hb_buffer_t * b)1110 void hb_fifo_push_wait( hb_fifo_t * f, hb_buffer_t * b )
1111 {
1112 if( !b )
1113 {
1114 return;
1115 }
1116
1117 hb_lock( f->lock );
1118 if( f->size >= f->capacity )
1119 {
1120 f->wait_full = 1;
1121 if (f->cond_alert_full != NULL)
1122 hb_cond_broadcast( f->cond_alert_full );
1123 hb_cond_timedwait( f->cond_full, f->lock, FIFO_TIMEOUT );
1124 }
1125 if( f->size > 0 )
1126 {
1127 f->last->next = b;
1128 }
1129 else
1130 {
1131 f->first = b;
1132 }
1133 f->last = b;
1134 f->size += 1;
1135 while( f->last->next )
1136 {
1137 f->size += 1;
1138 f->last = f->last->next;
1139 }
1140 if( f->wait_empty && f->size >= 1 )
1141 {
1142 f->wait_empty = 0;
1143 hb_cond_signal( f->cond_empty );
1144 }
1145 hb_unlock( f->lock );
1146 }
1147
1148 // Appends the specified packet list to the end of the specified FIFO.
hb_fifo_push(hb_fifo_t * f,hb_buffer_t * b)1149 void hb_fifo_push( hb_fifo_t * f, hb_buffer_t * b )
1150 {
1151 if( !b )
1152 {
1153 return;
1154 }
1155
1156 hb_lock( f->lock );
1157 if (f->size >= f->capacity &&
1158 f->cond_alert_full != NULL)
1159 {
1160 hb_cond_broadcast( f->cond_alert_full );
1161 }
1162 if( f->size > 0 )
1163 {
1164 f->last->next = b;
1165 }
1166 else
1167 {
1168 f->first = b;
1169 }
1170 f->last = b;
1171 f->size += 1;
1172 while( f->last->next )
1173 {
1174 f->size += 1;
1175 f->last = f->last->next;
1176 }
1177 if( f->wait_empty && f->size >= 1 )
1178 {
1179 f->wait_empty = 0;
1180 hb_cond_signal( f->cond_empty );
1181 }
1182 hb_unlock( f->lock );
1183 }
1184
1185 // Prepends the specified packet list to the start of the specified FIFO.
hb_fifo_push_head(hb_fifo_t * f,hb_buffer_t * b)1186 void hb_fifo_push_head( hb_fifo_t * f, hb_buffer_t * b )
1187 {
1188 hb_buffer_t * tmp;
1189 uint32_t size = 0;
1190
1191 if( !b )
1192 {
1193 return;
1194 }
1195
1196 hb_lock( f->lock );
1197 if (f->size >= f->capacity &&
1198 f->cond_alert_full != NULL)
1199 {
1200 hb_cond_broadcast( f->cond_alert_full );
1201 }
1202
1203 /*
1204 * If there are a chain of buffers prepend the lot
1205 */
1206 tmp = b;
1207 while( tmp->next )
1208 {
1209 tmp = tmp->next;
1210 size += 1;
1211 }
1212
1213 if( f->size > 0 )
1214 {
1215 tmp->next = f->first;
1216 }
1217 else
1218 {
1219 f->last = tmp;
1220 }
1221
1222 f->first = b;
1223 f->size += ( size + 1 );
1224
1225 hb_unlock( f->lock );
1226 }
1227
hb_fifo_close(hb_fifo_t ** _f)1228 void hb_fifo_close( hb_fifo_t ** _f )
1229 {
1230 hb_fifo_t * f = *_f;
1231 hb_buffer_t * b;
1232
1233 if ( f == NULL )
1234 return;
1235
1236 hb_deep_log( 2, "fifo_close: trashing %d buffer(s)", hb_fifo_size( f ) );
1237 while( ( b = hb_fifo_get( f ) ) )
1238 {
1239 hb_buffer_close( &b );
1240 }
1241
1242 hb_lock_close( &f->lock );
1243 hb_cond_close( &f->cond_empty );
1244 hb_cond_close( &f->cond_full );
1245
1246 #if defined(HB_FIFO_DEBUG)
1247 // Remove the fifo from the global fifo list
1248 fifo_list_rem( f );
1249 #endif
1250
1251 free( f );
1252
1253 *_f = NULL;
1254 }
1255
hb_fifo_flush(hb_fifo_t * f)1256 void hb_fifo_flush( hb_fifo_t * f )
1257 {
1258 hb_buffer_t * b;
1259
1260 while( ( b = hb_fifo_get( f ) ) )
1261 {
1262 hb_buffer_close( &b );
1263 }
1264 hb_lock( f->lock );
1265 hb_cond_signal( f->cond_empty );
1266 hb_cond_signal( f->cond_full );
1267 hb_unlock( f->lock );
1268
1269 }
1270
1271 #if defined(HB_BUFFER_DEBUG)
hb_fifo_contains(hb_fifo_t * f,hb_buffer_t * b)1272 static int hb_fifo_contains( hb_fifo_t *f, hb_buffer_t *b )
1273 {
1274 hb_buffer_t * tmp = f->first;
1275
1276 while (tmp != NULL)
1277 {
1278 if (b == tmp)
1279 {
1280 return 1;
1281 }
1282 tmp = tmp->next;
1283 }
1284 return 0;
1285 }
1286 #endif
1287