source: svn/zas_dstar/pdrivers/block.c @ 22

Last change on this file since 22 was 22, checked in by phkim, 11 years ago
  1. phkim
  2. newcon3sk 를 kctv 로 브랜치 함
File size: 10.0 KB
Line 
1/******************************************************************************
2 *_Copyright (c) 2009 Digital Stream Technology Inc. All Rights Reserved.
3 *
4 * Module:      pd_dmx.c
5 *
6 * Description
7 *      Pseudo Driver for Demux
8 *
9 * @author Junku Park (hwatk@dstreamtech.com)
10 * @version $Revision: 1.1 $
11 *
12 ******************************************************************************/
13
14#include "dsthallocal.h"
15#include "dsthalerror.h"
16#include "dstoslayer.h"
17#include "pd_dmx.h"
18#include "pd_dmx_priv.h"
19
20#include <stdio.h>
21#include <stdlib.h>
22
23#ifdef DMALLOC   
24#include <dmalloc.h>   
25#endif   
26
27/******************************************************************************
28 * Global variable declaration
29 ******************************************************************************/
30
31/******************************************************************************
32 * Imported variable declaration
33 ******************************************************************************/
34
35/******************************************************************************
36 * Imported function declaration
37 ******************************************************************************/
38
39/******************************************************************************
40 * Local definitions
41 ******************************************************************************/
42
43/******************************************************************************
44 * Local typedefs
45 ******************************************************************************/
46typedef struct block_sys_t block_sys_t;
47struct block_sys_t
48{
49    block_t     self;
50    int         i_allocated_buffer;
51    DS_U8       p_allocated_buffer[];
52};
53
54/******************************************************************************
55 * Local variables declaration
56 ******************************************************************************/
57
58/******************************************************************************
59 * Local function prototypes
60 ******************************************************************************/
61void block_FifoEmpty( block_fifo_t *p_fifo );
62static DS_U64 alloc_cnt = 0;
63static DS_U64 total_siz = 0;
64
65#if 0
66___Block_Management___()
67#endif
68void block_Init( block_t *b, void *buf, int size )
69{
70    /* Fill all fields to their default */
71    b->p_next = b->p_prev = NULL;
72    b->i_flags = 0;
73    b->i_pts = b->i_dts = b->i_length = 0;
74    b->i_rate = 0;
75    b->p_buffer = buf;
76    b->i_buffer = size;
77    b->i_osize = size;
78//    b->pf_release = BlockNoRelease;
79}
80
81static void BlockRelease( block_t *p_block )
82{
83    total_siz -= p_block->i_osize;
84   
85    alloc_cnt--;
86    free( p_block );
87}
88
89/* Memory alignment */
90#define BLOCK_ALIGN        16
91/* Initial size of reserved header and footer */
92#define BLOCK_PADDING_SIZE 32
93/* Maximum size of reserved footer before we release with realloc() */
94#define BLOCK_WASTE_SIZE   2048
95
96block_t *block_Alloc( int i_size )
97{
98    /* We do only one malloc
99     * TODO: bench if doing 2 malloc but keeping a pool of buffer is better
100     * TODO: use memalign
101     * 16 -> align on 16
102     * 2 * BLOCK_PADDING_SIZE -> pre + post padding
103     */
104    const int i_alloc = i_size + 2 * BLOCK_PADDING_SIZE + BLOCK_ALIGN;
105    block_sys_t *p_sys = malloc( sizeof( *p_sys ) + i_alloc );
106
107    alloc_cnt++;
108    total_siz += i_size;
109   
110    if( p_sys == NULL )
111        return NULL;
112
113    /* Fill opaque data */
114    p_sys->i_allocated_buffer = i_alloc;
115
116    block_Init( &p_sys->self, p_sys->p_allocated_buffer + BLOCK_PADDING_SIZE
117                + BLOCK_ALIGN
118                - ((DS_U32)p_sys->p_allocated_buffer % BLOCK_ALIGN),
119                i_size );
120    p_sys->self.pf_release    = BlockRelease;
121
122    return &p_sys->self;
123}
124
125block_t *block_Realloc( block_t *p_block, int i_prebody, int i_body )
126{
127    block_sys_t *p_sys = (block_sys_t *)p_block;
128    int i_buffer_size = i_prebody + i_body;
129
130    if( i_buffer_size <= 0 )
131    {
132        block_Release( p_block );
133        return NULL;
134    }
135
136    if( p_block->pf_release != BlockRelease )
137    {
138        /* Special case when pf_release if overloaded
139         * TODO if used one day, then implement it in a smarter way */
140        block_t *p_dup = block_Duplicate( p_block );
141        block_Release( p_block );
142        if( !p_dup )
143            return NULL;
144
145        p_block = p_dup;
146        p_sys = (block_sys_t *)p_block;
147    }
148
149    /* Adjust reserved header if there is enough room */
150    if( p_block->p_buffer - i_prebody > p_sys->p_allocated_buffer &&
151        p_block->p_buffer - i_prebody < p_sys->p_allocated_buffer +
152        p_sys->i_allocated_buffer )
153    {
154        p_block->p_buffer -= i_prebody;
155        p_block->i_buffer += i_prebody;
156        i_prebody = 0;
157    }
158
159    /* Adjust payload size if there is enough room */
160    if( p_block->p_buffer + i_body < p_sys->p_allocated_buffer +
161        p_sys->i_allocated_buffer )
162    {
163        p_block->i_buffer = i_buffer_size;
164        i_body = 0;
165    }
166
167    /* Not enough room, reallocate the buffer */
168    if( i_body > 0 || i_prebody > 0 )
169    {
170        /* FIXME: this is really dumb, we should use realloc() */
171        block_t *p_rea = block_New( NULL, i_buffer_size );
172
173        if( p_rea )
174        {
175            p_rea->i_dts     = p_block->i_dts;
176            p_rea->i_pts     = p_block->i_pts;
177            p_rea->i_flags   = p_block->i_flags;
178            p_rea->i_length  = p_block->i_length;
179            p_rea->i_rate    = p_block->i_rate;
180            p_rea->i_samples = p_block->i_samples;
181
182            memcpy( p_rea->p_buffer + i_prebody, p_block->p_buffer,
183                    __MIN( p_block->i_buffer, p_rea->i_buffer - i_prebody ) );
184        }
185
186        block_Release( p_block );
187
188        return p_rea;
189    }
190
191    /* We have a very large reserved footer now? Release some of it.
192     * XXX it may not keep the algniment of p_buffer */
193    if( (p_sys->p_allocated_buffer + p_sys->i_allocated_buffer) -
194        (p_block->p_buffer + p_block->i_buffer) > BLOCK_WASTE_SIZE )
195    {
196        const int i_prebody = p_block->p_buffer - p_sys->p_allocated_buffer;
197        const int i_new = i_prebody + p_block->i_buffer + 1 * BLOCK_PADDING_SIZE;
198        block_sys_t *p_new = realloc( p_sys, sizeof (*p_sys) + i_new );
199
200        if( p_new != NULL )
201        {
202            p_sys = p_new;
203            p_sys->i_allocated_buffer = i_new;
204            p_block = &p_sys->self;
205            p_block->p_buffer = &p_sys->p_allocated_buffer[i_prebody];
206        }
207    }
208    return p_block;
209}
210
211void print_block_cnt(void)
212{
213    printf("alloc_cnt: %lld\n", alloc_cnt);
214    printf("total_siz: %lld\n", total_siz);
215}
216
217#if 0
218___FIFO_Management___()
219#endif
220
221/*****************************************************************************
222 * block_fifo_t management
223 *****************************************************************************/
224struct block_fifo_t
225{
226    pthread_mutex_t      lock;                         /* fifo data lock */
227    pthread_cond_t       wait;         /* fifo data conditional variable */
228
229    block_t             *p_first;
230    block_t            **pp_last;
231    int                  i_depth;
232    int                  i_size;
233    DS_BOOL              b_force_wake;
234};
235
236block_fifo_t *block_FifoNew( void )
237{
238    block_fifo_t *p_fifo = malloc( sizeof( block_fifo_t ) );
239    if( !p_fifo )
240        return NULL;
241
242    pthread_mutex_init( &p_fifo->lock, NULL );
243    pthread_cond_init( &p_fifo->wait, NULL );
244    p_fifo->p_first = NULL;
245    p_fifo->pp_last = &p_fifo->p_first;
246    p_fifo->i_depth = p_fifo->i_size = 0;
247    p_fifo->b_force_wake = DS_FALSE;
248
249    return p_fifo;
250}
251
252void block_FifoRelease( block_fifo_t *p_fifo )
253{
254    block_FifoEmpty( p_fifo );
255    pthread_cond_destroy( &p_fifo->wait );
256    pthread_mutex_destroy( &p_fifo->lock );
257    free( p_fifo );
258}
259
260void block_FifoEmpty( block_fifo_t *p_fifo )
261{
262    block_t *b;
263
264    pthread_mutex_lock( &p_fifo->lock );
265    for( b = p_fifo->p_first; b != NULL; )
266    {
267        block_t *p_next;
268
269        p_next = b->p_next;
270        block_Release( b );
271        b = p_next;
272    }
273
274    p_fifo->i_depth = p_fifo->i_size = 0;
275    p_fifo->p_first = NULL;
276    p_fifo->pp_last = &p_fifo->p_first;
277    pthread_mutex_unlock( &p_fifo->lock );
278}
279
280int block_FifoPut( block_fifo_t *p_fifo, block_t *p_block )
281{
282    int i_size = 0;
283    pthread_mutex_lock( &p_fifo->lock );
284
285    do
286    {
287        i_size += p_block->i_buffer;
288
289        *p_fifo->pp_last = p_block;
290        p_fifo->pp_last = &p_block->p_next;
291        p_fifo->i_depth++;
292        p_fifo->i_size += p_block->i_buffer;
293
294        p_block = p_block->p_next;
295
296    } while( p_block );
297
298    /* warn there is data in this fifo */
299    pthread_cond_signal( &p_fifo->wait );
300    pthread_mutex_unlock( &p_fifo->lock );
301
302    return i_size;
303}
304
305void block_FifoWake( block_fifo_t *p_fifo )
306{
307    pthread_mutex_lock( &p_fifo->lock );
308    if( p_fifo->p_first == NULL )
309        p_fifo->b_force_wake = DS_TRUE;
310    pthread_cond_signal( &p_fifo->wait );
311    pthread_mutex_unlock( &p_fifo->lock );
312}
313
314block_t *block_FifoGet( block_fifo_t *p_fifo )
315{
316    block_t *b;
317
318    pthread_mutex_lock( &p_fifo->lock );
319
320    /* Remember pthread_cond_wait() may cause spurious wakeups
321     * (on both Win32 and POSIX) */
322    while( ( p_fifo->p_first == NULL ) && !p_fifo->b_force_wake )
323    {
324        pthread_cond_wait( &p_fifo->wait, &p_fifo->lock );
325    }
326
327    b = p_fifo->p_first;
328
329    p_fifo->b_force_wake = DS_FALSE;
330    if( b == NULL )
331    {
332        /* Forced wakeup */
333        pthread_mutex_unlock( &p_fifo->lock );
334        return NULL;
335    }
336
337    p_fifo->p_first = b->p_next;
338    p_fifo->i_depth--;
339    p_fifo->i_size -= b->i_buffer;
340
341    if( p_fifo->p_first == NULL )
342    {
343        p_fifo->pp_last = &p_fifo->p_first;
344    }
345
346    pthread_mutex_unlock( &p_fifo->lock );
347
348    b->p_next = NULL;
349    return b;
350}
351
352block_t *block_FifoShow( block_fifo_t *p_fifo )
353{
354    block_t *b;
355
356    pthread_mutex_lock( &p_fifo->lock );
357
358    if( p_fifo->p_first == NULL )
359    {
360        pthread_cond_wait( &p_fifo->wait, &p_fifo->lock );
361    }
362
363    b = p_fifo->p_first;
364
365    pthread_mutex_unlock( &p_fifo->lock );
366
367    return( b );
368}
369
370int block_FifoSize( const block_fifo_t *p_fifo )
371{
372    return p_fifo->i_size;
373}
374
375int block_FifoCount( const block_fifo_t *p_fifo )
376{
377    return p_fifo->i_depth;
378}
Note: See TracBrowser for help on using the repository browser.