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