1 /*
2 * Copyright(c) 2019 Intel Corporation
3 * SPDX - License - Identifier: BSD - 2 - Clause - Patent
4 */
5 
6 #include <stdlib.h>
7 
8 #include "EbSystemResourceManager.h"
9 
10 /**************************************
11  * eb_fifo_ctor
12  **************************************/
eb_fifo_ctor(EbFifo * fifo_ptr,uint32_t initial_count,uint32_t max_count,EbObjectWrapper * first_wrapper_ptr,EbObjectWrapper * last_wrapper_ptr,EbMuxingQueue * queue_ptr)13 static EbErrorType eb_fifo_ctor(
14     EbFifo          *fifo_ptr,
15     uint32_t         initial_count,
16     uint32_t         max_count,
17     EbObjectWrapper *first_wrapper_ptr,
18     EbObjectWrapper *last_wrapper_ptr,
19     EbMuxingQueue   *queue_ptr)
20 {
21     // Create Counting Semaphore
22     EB_CREATESEMAPHORE(EbHandle, fifo_ptr->counting_semaphore, sizeof(EbHandle), EB_SEMAPHORE, initial_count, max_count);
23 
24     // Create Buffer Pool Mutex
25     EB_CREATEMUTEX(EbHandle, fifo_ptr->lockout_mutex, sizeof(EbHandle), EB_MUTEX);
26 
27     // Initialize Fifo First & Last ptrs
28     fifo_ptr->first_ptr           = first_wrapper_ptr;
29     fifo_ptr->last_ptr            = last_wrapper_ptr;
30 
31     // Copy the Muxing Queue ptr this Fifo belongs to
32     fifo_ptr->queue_ptr           = queue_ptr;
33 
34     return EB_ErrorNone;
35 }
36 
37 /**************************************
38  * eb_fifo_push_back
39  **************************************/
eb_fifo_push_back(EbFifo * fifo_ptr,EbObjectWrapper * wrapper_ptr)40 static EbErrorType eb_fifo_push_back(
41     EbFifo          *fifo_ptr,
42     EbObjectWrapper *wrapper_ptr)
43 {
44     EbErrorType return_error = EB_ErrorNone;
45 
46     // If FIFO is empty
47     if(fifo_ptr->first_ptr == (EbObjectWrapper*) EB_NULL) {
48         fifo_ptr->first_ptr = wrapper_ptr;
49         fifo_ptr->last_ptr  = wrapper_ptr;
50     } else {
51         fifo_ptr->last_ptr->next_ptr = wrapper_ptr;
52         fifo_ptr->last_ptr = wrapper_ptr;
53     }
54 
55     fifo_ptr->last_ptr->next_ptr = (EbObjectWrapper*) EB_NULL;
56 
57     return return_error;
58 }
59 
60 /**************************************
61  * eb_fifo_pop_front
62  **************************************/
eb_fifo_pop_front(EbFifo * fifo_ptr,EbObjectWrapper ** wrapper_ptr)63 static EbErrorType eb_fifo_pop_front(
64     EbFifo           *fifo_ptr,
65     EbObjectWrapper **wrapper_ptr)
66 {
67     EbErrorType return_error = EB_ErrorNone;
68 
69     // Set wrapper_ptr to head of BufferPool
70     *wrapper_ptr = fifo_ptr->first_ptr;
71 
72     // Update tail of BufferPool if the BufferPool is now empty
73     fifo_ptr->last_ptr = (fifo_ptr->first_ptr == fifo_ptr->last_ptr) ? (EbObjectWrapper*) EB_NULL: fifo_ptr->last_ptr;
74 
75     // Update head of BufferPool
76     fifo_ptr->first_ptr = fifo_ptr->first_ptr->next_ptr;
77 
78     return return_error;
79 }
80 
81 /**************************************
82  * eb_circular_buffer_ctor
83  **************************************/
eb_circular_buffer_ctor(EbCircularBuffer ** buffer_dbl_ptr,uint32_t buffer_total_count)84 static EbErrorType eb_circular_buffer_ctor(
85     EbCircularBuffer **buffer_dbl_ptr,
86     uint32_t           buffer_total_count)
87 {
88     uint32_t buffer_index;
89     EbCircularBuffer *buffer_ptr;
90 
91     EB_MALLOC(EbCircularBuffer*, buffer_ptr, sizeof(EbCircularBuffer), EB_N_PTR);
92 
93     *buffer_dbl_ptr = buffer_ptr;
94 
95     buffer_ptr->buffer_total_count = buffer_total_count;
96 
97     EB_MALLOC(EbPtr *, buffer_ptr->array_ptr, sizeof(EbPtr) * buffer_ptr->buffer_total_count, EB_N_PTR);
98 
99     for(buffer_index=0; buffer_index < buffer_ptr->buffer_total_count; ++buffer_index) {
100         buffer_ptr->array_ptr[buffer_index] = EB_NULL;
101     }
102 
103     buffer_ptr->head_index = 0;
104     buffer_ptr->tail_index = 0;
105 
106     buffer_ptr->current_count = 0;
107 
108     return EB_ErrorNone;
109 }
110 
111 /**************************************
112  * eb_circular_buffer_empty_check
113  **************************************/
eb_circular_buffer_empty_check(EbCircularBuffer * buffer_ptr)114 static EB_BOOL eb_circular_buffer_empty_check(
115     EbCircularBuffer *buffer_ptr)
116 {
117     return ((buffer_ptr->head_index == buffer_ptr->tail_index) && (buffer_ptr->array_ptr[buffer_ptr->head_index] == EB_NULL)) ? EB_TRUE : EB_FALSE;
118 }
119 
120 /**************************************
121  * eb_circular_buffer_pop_front
122  **************************************/
eb_circular_buffer_pop_front(EbCircularBuffer * buffer_ptr,EbPtr * object_ptr)123 static EbErrorType eb_circular_buffer_pop_front(
124     EbCircularBuffer *buffer_ptr,
125     EbPtr            *object_ptr)
126 {
127     EbErrorType return_error = EB_ErrorNone;
128 
129     // Copy the head of the buffer into the object_ptr
130     *object_ptr = buffer_ptr->array_ptr[buffer_ptr->head_index];
131     buffer_ptr->array_ptr[buffer_ptr->head_index] = EB_NULL;
132 
133     // Increment the head & check for rollover
134     buffer_ptr->head_index = (buffer_ptr->head_index == buffer_ptr->buffer_total_count - 1) ? 0 : buffer_ptr->head_index + 1;
135 
136     // Decrement the Current Count
137     --buffer_ptr->current_count;
138 
139     return return_error;
140 }
141 
142 /**************************************
143  * eb_circular_buffer_push_back
144  **************************************/
eb_circular_buffer_push_back(EbCircularBuffer * buffer_ptr,EbPtr object_ptr)145 static EbErrorType eb_circular_buffer_push_back(
146     EbCircularBuffer *buffer_ptr,
147     EbPtr             object_ptr)
148 {
149     EbErrorType return_error = EB_ErrorNone;
150 
151     // Copy the pointer into the array
152     buffer_ptr->array_ptr[buffer_ptr->tail_index] = object_ptr;
153 
154     // Increment the tail & check for rollover
155     buffer_ptr->tail_index = (buffer_ptr->tail_index == buffer_ptr->buffer_total_count - 1) ? 0 : buffer_ptr->tail_index + 1;
156 
157     // Increment the Current Count
158     ++buffer_ptr->current_count;
159 
160     return return_error;
161 }
162 
163 /**************************************
164  * eb_circular_buffer_push_front
165  **************************************/
eb_circular_buffer_push_front(EbCircularBuffer * buffer_ptr,EbPtr object_ptr)166 static EbErrorType eb_circular_buffer_push_front(
167     EbCircularBuffer *buffer_ptr,
168     EbPtr             object_ptr)
169 {
170     EbErrorType return_error = EB_ErrorNone;
171 
172     // Decrement the head_index
173     buffer_ptr->head_index = (buffer_ptr->head_index == 0) ? buffer_ptr->buffer_total_count - 1 : buffer_ptr->head_index - 1;
174 
175     // Copy the pointer into the array
176     buffer_ptr->array_ptr[buffer_ptr->head_index] = object_ptr;
177 
178     // Increment the Current Count
179     ++buffer_ptr->current_count;
180 
181     return return_error;
182 }
183 
184 /**************************************
185  * eb_muxing_queue_ctor
186  **************************************/
eb_muxing_queue_ctor(EbMuxingQueue ** queue_dbl_ptr,uint32_t object_total_count,uint32_t process_total_count,EbFifo *** process_fifo_ptr_array_ptr)187 static EbErrorType eb_muxing_queue_ctor(
188     EbMuxingQueue **queue_dbl_ptr,
189     uint32_t        object_total_count,
190     uint32_t        process_total_count,
191     EbFifo       ***process_fifo_ptr_array_ptr)
192 {
193     EbMuxingQueue *queue_ptr;
194     uint32_t process_index;
195     EbErrorType     return_error = EB_ErrorNone;
196 
197     EB_MALLOC(EbMuxingQueue *, queue_ptr, sizeof(EbMuxingQueue), EB_N_PTR);
198     *queue_dbl_ptr = queue_ptr;
199 
200     queue_ptr->process_total_count = process_total_count;
201 
202     // Lockout Mutex
203     EB_CREATEMUTEX(EbHandle, queue_ptr->lockout_mutex, sizeof(EbHandle), EB_MUTEX);
204 
205     // Construct Object Circular Buffer
206     return_error = eb_circular_buffer_ctor(
207         &queue_ptr->object_queue,
208         object_total_count);
209     if (return_error == EB_ErrorInsufficientResources){
210         return EB_ErrorInsufficientResources;
211     }
212     // Construct Process Circular Buffer
213     return_error = eb_circular_buffer_ctor(
214         &queue_ptr->process_queue,
215         queue_ptr->process_total_count);
216     if (return_error == EB_ErrorInsufficientResources){
217         return EB_ErrorInsufficientResources;
218     }
219     // Construct the Process Fifos
220     EB_MALLOC(EbFifo**, queue_ptr->process_fifo_ptr_array, sizeof(EbFifo*) * queue_ptr->process_total_count, EB_N_PTR);
221 
222     for(process_index=0; process_index < queue_ptr->process_total_count; ++process_index) {
223         EB_MALLOC(EbFifo*, queue_ptr->process_fifo_ptr_array[process_index], sizeof(EbFifo) * queue_ptr->process_total_count, EB_N_PTR);
224         return_error = eb_fifo_ctor(
225             queue_ptr->process_fifo_ptr_array[process_index],
226             0,
227             object_total_count,
228             (EbObjectWrapper *)EB_NULL,
229             (EbObjectWrapper *)EB_NULL,
230             queue_ptr);
231         if (return_error == EB_ErrorInsufficientResources){
232             return EB_ErrorInsufficientResources;
233         }
234     }
235 
236     *process_fifo_ptr_array_ptr = queue_ptr->process_fifo_ptr_array;
237 
238     return return_error;
239 }
240 
241 /**************************************
242  * eb_muxing_queue_assignation
243  **************************************/
eb_muxing_queue_assignation(EbMuxingQueue * queue_ptr)244 static EbErrorType eb_muxing_queue_assignation(
245     EbMuxingQueue *queue_ptr)
246 {
247     EbErrorType return_error = EB_ErrorNone;
248     EbFifo *process_fifo_ptr;
249     EbObjectWrapper *wrapper_ptr;
250 
251     // while loop
252     while((eb_circular_buffer_empty_check(queue_ptr->object_queue)  == EB_FALSE) &&
253             (eb_circular_buffer_empty_check(queue_ptr->process_queue) == EB_FALSE)) {
254         // Get the next process
255         eb_circular_buffer_pop_front(
256             queue_ptr->process_queue,
257             (void **) &process_fifo_ptr);
258 
259         // Get the next object
260         eb_circular_buffer_pop_front(
261             queue_ptr->object_queue,
262             (void **) &wrapper_ptr);
263 
264         // Block on the Process Fifo's Mutex
265         eb_vp9_block_on_mutex(process_fifo_ptr->lockout_mutex);
266 
267         // Put the object on the fifo
268         eb_fifo_push_back(
269             process_fifo_ptr,
270             wrapper_ptr);
271 
272         // Release the Process Fifo's Mutex
273         eb_vp9_release_mutex(process_fifo_ptr->lockout_mutex);
274 
275         // Post the semaphore
276         eb_vp9_post_semaphore(process_fifo_ptr->counting_semaphore);
277     }
278 
279     return return_error;
280 }
281 
282 /**************************************
283  * eb_muxing_queue_object_push_back
284  **************************************/
eb_muxing_queue_object_push_back(EbMuxingQueue * queue_ptr,EbObjectWrapper * object_ptr)285 static EbErrorType eb_muxing_queue_object_push_back(
286     EbMuxingQueue   *queue_ptr,
287     EbObjectWrapper *object_ptr)
288 {
289     EbErrorType return_error = EB_ErrorNone;
290 
291     eb_circular_buffer_push_back(
292         queue_ptr->object_queue,
293         object_ptr);
294 
295     eb_muxing_queue_assignation(queue_ptr);
296 
297     return return_error;
298 }
299 
300 /**************************************
301 * eb_muxing_queue_object_push_front
302 **************************************/
eb_muxing_queue_object_push_front(EbMuxingQueue * queue_ptr,EbObjectWrapper * object_ptr)303 static EbErrorType eb_muxing_queue_object_push_front(
304     EbMuxingQueue   *queue_ptr,
305     EbObjectWrapper *object_ptr)
306 {
307     EbErrorType return_error = EB_ErrorNone;
308 
309     eb_circular_buffer_push_front(
310         queue_ptr->object_queue,
311         object_ptr);
312 
313     eb_muxing_queue_assignation(queue_ptr);
314 
315     return return_error;
316 }
317 
318 /*********************************************************************
319  * eb_vp9_object_release_enable
320  *   Enables the release_enable member of EbObjectWrapper.  Used by
321  *   certain objects (e.g. SequenceControlSet) to control whether
322  *   EbObjectWrappers are allowed to be released or not.
323  *
324  *   resource_ptr
325  *      pointer to the SystemResource that manages the EbObjectWrapper.
326  *      The emptyFifo's lockout_mutex is used to write protect the
327  *      modification of the EbObjectWrapper.
328  *
329  *   wrapper_ptr
330  *      pointer to the EbObjectWrapper to be modified.
331  *********************************************************************/
eb_vp9_object_release_enable(EbObjectWrapper * wrapper_ptr)332 EbErrorType eb_vp9_object_release_enable(
333     EbObjectWrapper *wrapper_ptr)
334 {
335     EbErrorType return_error = EB_ErrorNone;
336 
337     eb_vp9_block_on_mutex(wrapper_ptr->system_resource_ptr->empty_queue->lockout_mutex);
338 
339     wrapper_ptr->release_enable = EB_TRUE;
340 
341     eb_vp9_release_mutex(wrapper_ptr->system_resource_ptr->empty_queue->lockout_mutex);
342 
343     return return_error;
344 }
345 
346 /*********************************************************************
347  * eb_vp9_object_release_disable
348  *   Disables the release_enable member of EbObjectWrapper.  Used by
349  *   certain objects (e.g. SequenceControlSet) to control whether
350  *   EbObjectWrappers are allowed to be released or not.
351  *
352  *   resource_ptr
353  *      pointer to the SystemResource that manages the EbObjectWrapper.
354  *      The emptyFifo's lockout_mutex is used to write protect the
355  *      modification of the EbObjectWrapper.
356  *
357  *   wrapper_ptr
358  *      pointer to the EbObjectWrapper to be modified.
359  *********************************************************************/
eb_vp9_object_release_disable(EbObjectWrapper * wrapper_ptr)360 EbErrorType eb_vp9_object_release_disable(
361     EbObjectWrapper *wrapper_ptr)
362 {
363     EbErrorType return_error = EB_ErrorNone;
364 
365     eb_vp9_block_on_mutex(wrapper_ptr->system_resource_ptr->empty_queue->lockout_mutex);
366 
367     wrapper_ptr->release_enable = EB_FALSE;
368 
369     eb_vp9_release_mutex(wrapper_ptr->system_resource_ptr->empty_queue->lockout_mutex);
370 
371     return return_error;
372 }
373 
374 /*********************************************************************
375  * eb_vp9_object_inc_live_count
376  *   Increments the live_count member of EbObjectWrapper.  Used by
377  *   certain objects (e.g. SequenceControlSet) to count the number of active
378  *   pointers of a EbObjectWrapper in pipeline at any point in time.
379  *
380  *   resource_ptr
381  *      pointer to the SystemResource that manages the EbObjectWrapper.
382  *      The emptyFifo's lockout_mutex is used to write protect the
383  *      modification of the EbObjectWrapper.
384  *
385  *   wrapper_ptr
386  *      pointer to the EbObjectWrapper to be modified.
387  *********************************************************************/
eb_vp9_object_inc_live_count(EbObjectWrapper * wrapper_ptr,uint32_t increment_number)388 EbErrorType eb_vp9_object_inc_live_count(
389     EbObjectWrapper *wrapper_ptr,
390     uint32_t         increment_number)
391 {
392     EbErrorType return_error = EB_ErrorNone;
393 
394     eb_vp9_block_on_mutex(wrapper_ptr->system_resource_ptr->empty_queue->lockout_mutex);
395 
396     wrapper_ptr->live_count += increment_number;
397 
398     eb_vp9_release_mutex(wrapper_ptr->system_resource_ptr->empty_queue->lockout_mutex);
399 
400     return return_error;
401 }
402 
403 /*********************************************************************
404  * eb_vp9_system_resource_ctor
405  *   Constructor for EbSystemResource.  Fully constructs all members
406  *   of EbSystemResource including the object with the passed
407  *   object_ctor function.
408  *
409  *   resource_ptr
410  *     pointer that will contain the SystemResource to be constructed.
411  *
412  *   object_total_count
413  *     Number of objects to be managed by the SystemResource.
414  *
415  *   full_fifo_enabled
416  *     Bool that describes if the SystemResource is to have an output
417  *     fifo.  An outputFifo is not used by certain objects (e.g.
418  *     SequenceControlSet).
419  *
420  *   object_ctor
421  *     Function pointer to the constructor of the object managed by
422  *     SystemResource referenced by resource_ptr. No object level
423  *     construction is performed if object_ctor is NULL.
424  *
425  *   object_init_data_ptr
426 
427  *     pointer to data block to be used during the construction of
428  *     the object. object_init_data_ptr is passed to object_ctor when
429  *     object_ctor is called.
430  *********************************************************************/
eb_vp9_system_resource_ctor(EbSystemResource ** resource_dbl_ptr,uint32_t object_total_count,uint32_t producer_process_total_count,uint32_t consumer_process_total_count,EbFifo *** producer_fifo_ptr_array_ptr,EbFifo *** consumer_fifo_ptr_array_ptr,EB_BOOL full_fifo_enabled,EB_CTOR object_ctor,EbPtr object_init_data_ptr)431 EbErrorType eb_vp9_system_resource_ctor(
432     EbSystemResource **resource_dbl_ptr,
433     uint32_t           object_total_count,
434     uint32_t           producer_process_total_count,
435     uint32_t           consumer_process_total_count,
436     EbFifo          ***producer_fifo_ptr_array_ptr,
437     EbFifo          ***consumer_fifo_ptr_array_ptr,
438     EB_BOOL            full_fifo_enabled,
439     EB_CTOR            object_ctor,
440     EbPtr              object_init_data_ptr)
441 {
442     uint32_t wrapperIndex;
443     EbErrorType return_error = EB_ErrorNone;
444     // Allocate the System Resource
445     EbSystemResource *resource_ptr;
446 
447     EB_MALLOC(EbSystemResource*, resource_ptr, sizeof(EbSystemResource), EB_N_PTR);
448     *resource_dbl_ptr = resource_ptr;
449 
450     resource_ptr->object_total_count = object_total_count;
451 
452     // Allocate array for wrapper pointers
453     EB_MALLOC(EbObjectWrapper**, resource_ptr->wrapper_ptr_pool, sizeof(EbObjectWrapper*) * resource_ptr->object_total_count, EB_N_PTR);
454 
455     // Initialize each wrapper
456     for (wrapperIndex=0; wrapperIndex < resource_ptr->object_total_count; ++wrapperIndex) {
457         EB_MALLOC(EbObjectWrapper*, resource_ptr->wrapper_ptr_pool[wrapperIndex], sizeof(EbObjectWrapper), EB_N_PTR);
458         resource_ptr->wrapper_ptr_pool[wrapperIndex]->live_count            = 0;
459         resource_ptr->wrapper_ptr_pool[wrapperIndex]->release_enable        = EB_TRUE;
460         resource_ptr->wrapper_ptr_pool[wrapperIndex]->system_resource_ptr    = resource_ptr;
461 
462         // Call the Constructor for each element
463         if(object_ctor) {
464             return_error = object_ctor(
465                 &resource_ptr->wrapper_ptr_pool[wrapperIndex]->object_ptr,
466                 object_init_data_ptr);
467             if (return_error == EB_ErrorInsufficientResources){
468                 return EB_ErrorInsufficientResources;
469             }
470         }
471     }
472 
473     // Initialize the Empty Queue
474     return_error = eb_muxing_queue_ctor(
475         &resource_ptr->empty_queue,
476         resource_ptr->object_total_count,
477         producer_process_total_count,
478         producer_fifo_ptr_array_ptr);
479     if (return_error == EB_ErrorInsufficientResources){
480         return EB_ErrorInsufficientResources;
481     }
482     // Fill the Empty Fifo with every ObjectWrapper
483     for (wrapperIndex=0; wrapperIndex < resource_ptr->object_total_count; ++wrapperIndex) {
484         eb_muxing_queue_object_push_back(
485             resource_ptr->empty_queue,
486             resource_ptr->wrapper_ptr_pool[wrapperIndex]);
487     }
488 
489     // Initialize the Full Queue
490     if (full_fifo_enabled == EB_TRUE) {
491         return_error = eb_muxing_queue_ctor(
492             &resource_ptr->full_queue,
493             resource_ptr->object_total_count,
494             consumer_process_total_count,
495             consumer_fifo_ptr_array_ptr);
496         if (return_error == EB_ErrorInsufficientResources){
497             return EB_ErrorInsufficientResources;
498         }
499     } else {
500         resource_ptr->full_queue  = (EbMuxingQueue *)EB_NULL;
501         consumer_fifo_ptr_array_ptr = (EbFifo ***)EB_NULL;
502     }
503 
504     return return_error;
505 }
506 
507 /*********************************************************************
508  * EbSystemResourceReleaseProcess
509  *********************************************************************/
eb_release_process(EbFifo * process_fifo_ptr)510 static EbErrorType eb_release_process(
511     EbFifo *process_fifo_ptr)
512 {
513     EbErrorType return_error = EB_ErrorNone;
514 
515     eb_vp9_block_on_mutex(process_fifo_ptr->queue_ptr->lockout_mutex);
516 
517     eb_circular_buffer_push_front(
518         process_fifo_ptr->queue_ptr->process_queue,
519         process_fifo_ptr);
520 
521     eb_muxing_queue_assignation(process_fifo_ptr->queue_ptr);
522 
523     eb_vp9_release_mutex(process_fifo_ptr->queue_ptr->lockout_mutex);
524 
525     return return_error;
526 }
527 
528 /*********************************************************************
529  * EbSystemResourcePostObject
530  *   Queues a full EbObjectWrapper to the SystemResource. This
531  *   function posts the SystemResource fullFifo counting_semaphore.
532  *   This function is write protected by the SystemResource fullFifo
533  *   lockout_mutex.
534  *
535  *   resource_ptr
536  *      pointer to the SystemResource that the EbObjectWrapper is
537  *      posted to.
538  *
539  *   wrapper_ptr
540  *      pointer to EbObjectWrapper to be posted.
541  *********************************************************************/
eb_vp9_post_full_object(EbObjectWrapper * object_ptr)542 EbErrorType eb_vp9_post_full_object(
543     EbObjectWrapper *object_ptr)
544 {
545     EbErrorType return_error = EB_ErrorNone;
546 
547     eb_vp9_block_on_mutex(object_ptr->system_resource_ptr->full_queue->lockout_mutex);
548 
549     eb_muxing_queue_object_push_back(
550         object_ptr->system_resource_ptr->full_queue,
551         object_ptr);
552 
553     eb_vp9_release_mutex(object_ptr->system_resource_ptr->full_queue->lockout_mutex);
554 
555     return return_error;
556 }
557 
558 /*********************************************************************
559  * EbSystemResourceReleaseObject
560  *   Queues an empty EbObjectWrapper to the SystemResource. This
561  *   function posts the SystemResource emptyFifo counting_semaphore.
562  *   This function is write protected by the SystemResource emptyFifo
563  *   lockout_mutex.
564  *
565  *   object_ptr
566  *      pointer to EbObjectWrapper to be released.
567  *********************************************************************/
eb_vp9_release_object(EbObjectWrapper * object_ptr)568 EbErrorType eb_vp9_release_object(
569     EbObjectWrapper *object_ptr)
570 {
571     EbErrorType return_error = EB_ErrorNone;
572 
573     eb_vp9_block_on_mutex(object_ptr->system_resource_ptr->empty_queue->lockout_mutex);
574 
575     // Decrement live_count
576     object_ptr->live_count = (object_ptr->live_count == 0) ? object_ptr->live_count : object_ptr->live_count - 1;
577 
578     if((object_ptr->release_enable == EB_TRUE) && (object_ptr->live_count == 0)) {
579 
580         // Set live_count to EB_ObjectWrapperReleasedValue
581         object_ptr->live_count = EB_ObjectWrapperReleasedValue;
582 
583         eb_muxing_queue_object_push_front(
584             object_ptr->system_resource_ptr->empty_queue,
585             object_ptr);
586 
587     }
588 
589     eb_vp9_release_mutex(object_ptr->system_resource_ptr->empty_queue->lockout_mutex);
590 
591     return return_error;
592 }
593 
594 /*********************************************************************
595  * EbSystemResourceGetEmptyObject
596  *   Dequeues an empty EbObjectWrapper from the SystemResource.  This
597  *   function blocks on the SystemResource emptyFifo counting_semaphore.
598  *   This function is write protected by the SystemResource emptyFifo
599  *   lockout_mutex.
600  *
601  *   resource_ptr
602  *      pointer to the SystemResource that provides the empty
603  *      EbObjectWrapper.
604  *
605  *   wrapper_dbl_ptr
606  *      Double pointer used to pass the pointer to the empty
607  *      EbObjectWrapper pointer.
608  *********************************************************************/
eb_vp9_get_empty_object(EbFifo * empty_fifo_ptr,EbObjectWrapper ** wrapper_dbl_ptr)609 EbErrorType eb_vp9_get_empty_object(
610     EbFifo           *empty_fifo_ptr,
611     EbObjectWrapper **wrapper_dbl_ptr)
612 {
613     EbErrorType return_error = EB_ErrorNone;
614 
615     // Queue the Fifo requesting the empty fifo
616     eb_release_process(empty_fifo_ptr);
617 
618     // Block on the counting Semaphore until an empty buffer is available
619     eb_vp9_block_on_semaphore(empty_fifo_ptr->counting_semaphore);
620 
621     // Acquire lockout Mutex
622     eb_vp9_block_on_mutex(empty_fifo_ptr->lockout_mutex);
623 
624     // Get the empty object
625     eb_fifo_pop_front(
626         empty_fifo_ptr,
627         wrapper_dbl_ptr);
628 
629     // Reset the wrapper's live_count
630     (*wrapper_dbl_ptr)->live_count = 0;
631 
632     // Object release enable
633     (*wrapper_dbl_ptr)->release_enable = EB_TRUE;
634 
635     // Release Mutex
636     eb_vp9_release_mutex(empty_fifo_ptr->lockout_mutex);
637 
638     return return_error;
639 }
640 
641 /*********************************************************************
642  * EbSystemResourceGetFullObject
643  *   Dequeues an full EbObjectWrapper from the SystemResource. This
644  *   function blocks on the SystemResource fullFifo counting_semaphore.
645  *   This function is write protected by the SystemResource fullFifo
646  *   lockout_mutex.
647  *
648  *   resource_ptr
649  *      pointer to the SystemResource that provides the full
650  *      EbObjectWrapper.
651  *
652  *   wrapper_dbl_ptr
653  *      Double pointer used to pass the pointer to the full
654  *      EbObjectWrapper pointer.
655  *********************************************************************/
eb_vp9_get_full_object(EbFifo * full_fifo_ptr,EbObjectWrapper ** wrapper_dbl_ptr)656 EbErrorType eb_vp9_get_full_object(
657     EbFifo           *full_fifo_ptr,
658     EbObjectWrapper **wrapper_dbl_ptr)
659 {
660     EbErrorType return_error = EB_ErrorNone;
661 
662     // Queue the Fifo requesting the full fifo
663     eb_release_process(full_fifo_ptr);
664 
665     // Block on the counting Semaphore until an empty buffer is available
666     eb_vp9_block_on_semaphore(full_fifo_ptr->counting_semaphore);
667 
668     // Acquire lockout Mutex
669     eb_vp9_block_on_mutex(full_fifo_ptr->lockout_mutex);
670 
671     eb_fifo_pop_front(
672         full_fifo_ptr,
673         wrapper_dbl_ptr);
674 
675     // Release Mutex
676     eb_vp9_release_mutex(full_fifo_ptr->lockout_mutex);
677 
678     return return_error;
679 }
680 /**************************************
681 * EbFifoPopFront
682 **************************************/
eb_fifo_peak_front(EbFifo * fifo_ptr)683 static EB_BOOL eb_fifo_peak_front(
684     EbFifo            *fifo_ptr){
685 
686     // Set wrapper_ptr to head of BufferPool
687     if (fifo_ptr->first_ptr == (EbObjectWrapper*)EB_NULL)
688         return EB_TRUE;
689     else
690         return EB_FALSE;
691 }
692 
eb_vp9_get_full_object_non_blocking(EbFifo * full_fifo_ptr,EbObjectWrapper ** wrapper_dbl_ptr)693 EbErrorType eb_vp9_get_full_object_non_blocking(
694     EbFifo          *full_fifo_ptr,
695     EbObjectWrapper **wrapper_dbl_ptr){
696 
697     EbErrorType return_error = EB_ErrorNone;
698     EB_BOOL     fifo_empty;
699     // Queue the Fifo requesting the full fifo
700     eb_release_process(full_fifo_ptr);
701 
702     // Acquire lockout Mutex
703     eb_vp9_block_on_mutex(full_fifo_ptr->lockout_mutex);
704 
705     fifo_empty = eb_fifo_peak_front(
706         full_fifo_ptr);
707 
708     // Release Mutex
709     eb_vp9_release_mutex(full_fifo_ptr->lockout_mutex);
710 
711     if (fifo_empty == EB_FALSE)
712         eb_vp9_get_full_object(
713             full_fifo_ptr,
714             wrapper_dbl_ptr);
715     else
716         *wrapper_dbl_ptr = (EbObjectWrapper*)EB_NULL;
717 
718     return return_error;
719 }
720