Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-gpu
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc-gpu
Commits
1c18e067
Commit
1c18e067
authored
Jul 05, 2004
by
Laurent Aimar
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
* block.*: faster block_* and removed unused features.
parent
a304c042
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
209 additions
and
279 deletions
+209
-279
include/vlc_block.h
include/vlc_block.h
+164
-38
src/misc/block.c
src/misc/block.c
+45
-241
No files found.
include/vlc_block.h
View file @
1c18e067
...
...
@@ -24,9 +24,26 @@
#ifndef _VLC_BLOCK_H
#define _VLC_BLOCK_H 1
/*
* block
*/
/****************************************************************************
* block:
****************************************************************************
* - block_sys_t is opaque and thus block_t->p_sys is PRIVATE
* - i_flags may not always be set (ie could be 0, even for a key frame
* it depends where you receive the buffer (before/after a packetizer
* and the demux/packetizer implementations.
* - i_dts/i_pts could be 0, it means no pts
* - i_length: length in microseond of the packet, can be null except in the
* sout where it is mandatory.
* - i_rate 0 or a valid input rate, look at vlc_input.h
*
* - i_buffer number of valid data pointed by p_buffer
* you can freely decrease it but never increase it yourself
* (use block_Realloc)
* - p_buffer: pointer over datas. You should never overwrite it, you can
* only incremment it to skip datas, in others cases use block_Realloc
* (don't duplicate yourself in a bigger buffer, block_Realloc is
* optimised for prehader/postdatas increase)
****************************************************************************/
typedef
struct
block_sys_t
block_sys_t
;
/** The content doesn't follow the last block, or is probably broken */
...
...
@@ -62,63 +79,172 @@ struct block_t
int
i_buffer
;
uint8_t
*
p_buffer
;
/* This way the block_Release can be overloaded
* Don't mess with it now, if you need it the ask on ML
*/
void
(
*
pf_release
)
(
block_t
*
);
block_t
*
(
*
pf_modify
)
(
block_t
*
,
vlc_bool_t
);
block_t
*
(
*
pf_duplicate
)
(
block_t
*
);
block_t
*
(
*
pf_realloc
)
(
block_t
*
,
int
i_prebody
,
int
i_body
);
/* Following fields are private, user should never touch it */
/* XXX never touch that OK !!! the first that access that will
* have cvs account removed ;) XXX */
/* It's an object that should be valid as long as the block_t is valid */
/* It should become a true block manager to reduce malloc/free */
vlc_object_t
*
p_manager
;
/* private member for block_New, .... manager */
/* Following fields are private, user should never touch it */
/* XXX never touch that OK !!! the first that access that will
* have cvs account removed ;) XXX */
block_sys_t
*
p_sys
;
};
struct
block_fifo_t
/****************************************************************************
* Blocks functions:
****************************************************************************
* - block_New : create a new block with the requested size ( >= 0 ), return
* NULL for failure.
* - block_Release : release a block allocated with block_New.
* - block_Realloc : realloc a block,
* i_pre: how many bytes to insert before body if > 0, else how many
* bytes of body to skip (the latter can be done without using
* block_Realloc i_buffer -= -i_pre, p_buffer += -i_pre as i_pre < 0)
* i_body (>= 0): the final size of the body (decreasing it can directly
* be done with i_buffer = i_body).
* with preheader and or body (increase
* and decrease are supported). Use it as it is optimised.
* - block_Duplicate : create a copy of a block.
****************************************************************************/
#define block_New( a, b ) __block_New( VLC_OBJECT(a), b )
VLC_EXPORT
(
block_t
*
,
__block_New
,
(
vlc_object_t
*
,
int
)
);
VLC_EXPORT
(
block_t
*
,
block_Realloc
,
(
block_t
*
,
int
i_pre
,
int
i_body
)
);
static
inline
block_t
*
block_Duplicate
(
block_t
*
p_block
)
{
vlc_mutex_t
lock
;
/* fifo data lock */
vlc_cond_t
wait
;
/* fifo data conditional variable */
block_t
*
p_dup
=
block_New
(
p_block
->
p_manager
,
p_block
->
i_buffer
);
int
i_depth
;
block_t
*
p_first
;
block_t
**
pp_last
;
};
if
(
p_dup
&&
p_block
->
i_buffer
>
0
)
memcpy
(
p_dup
->
p_buffer
,
p_block
->
p_buffer
,
p_block
->
i_buffer
);
/*
* block
*/
#define block_New( a, b ) __block_New( VLC_OBJECT(a), b )
VLC_EXPORT
(
block_t
*
,
__block_New
,
(
vlc_object_t
*
,
int
)
);
return
p_dup
;
}
static
inline
void
block_Release
(
block_t
*
p_block
)
{
p_block
->
pf_release
(
p_block
);
}
static
inline
block_t
*
block_Modify
(
block_t
*
p_block
,
vlc_bool_t
b_willmodify
)
/****************************************************************************
* Chains of blocks functions helper
****************************************************************************
* - block_ChainAppend : append a block the the last block of a chain. Try to
* avoid using with a lot of data as it's really slow, prefer
* block_ChainLastAppend
* - block_ChainLastAppend : use a pointer over a pointer to the next blocks,
* and update it.
* - block_ChainRelease : release a chain of block
* - block_ChainExtract : extract data from a chain, return real bytes counts
* - block_ChainGather : gather a chain, free it and return a block.
****************************************************************************/
static
inline
void
block_ChainAppend
(
block_t
**
pp_list
,
block_t
*
p_block
)
{
return
p_block
->
pf_modify
(
p_block
,
b_willmodify
);
if
(
*
pp_list
==
NULL
)
{
*
pp_list
=
p_block
;
}
else
{
block_t
*
p
=
*
pp_list
;
while
(
p
->
p_next
)
p
=
p
->
p_next
;
p
->
p_next
=
p_block
;
}
}
static
inline
block_t
*
block_Duplicate
(
block_t
*
p_block
)
static
inline
void
block_ChainLastAppend
(
block_t
***
ppp_last
,
block_t
*
p_block
)
{
return
p_block
->
pf_duplicate
(
p_block
);
block_t
*
p_last
=
p_block
;
**
ppp_last
=
p_block
;
while
(
p_last
->
p_next
)
p_last
=
p_last
->
p_next
;
*
ppp_last
=
&
p_last
->
p_next
;
}
static
inline
block_t
*
block_Realloc
(
block_t
*
p_block
,
int
i_pre
,
int
i_body
)
static
inline
void
block_ChainRelease
(
block_t
*
p_block
)
{
return
p_block
->
pf_realloc
(
p_block
,
i_pre
,
i_body
);
while
(
p_block
)
{
block_t
*
p_next
=
p_block
->
p_next
;
block_Release
(
p_block
);
p_block
=
p_next
;
}
}
static
int
block_ChainExtract
(
block_t
*
p_list
,
void
*
p_data
,
int
i_max
)
{
block_t
*
b
;
int
i_total
=
0
;
uint8_t
*
p
=
(
uint8_t
*
)
p_data
;
for
(
b
=
p_list
;
b
!=
NULL
;
b
=
b
->
p_next
)
{
int
i_copy
=
__MIN
(
i_max
,
b
->
i_buffer
);
if
(
i_copy
>
0
)
{
memcpy
(
p
,
b
->
p_buffer
,
i_copy
);
i_max
-=
i_copy
;
i_total
+=
i_copy
;
p
+=
i_copy
;
if
(
i_max
==
0
)
return
i_total
;
}
}
return
i_total
;
}
VLC_EXPORT
(
void
,
block_ChainAppend
,
(
block_t
**
,
block_t
*
)
);
VLC_EXPORT
(
void
,
block_ChainLastAppend
,
(
block_t
***
ppp_last
,
block_t
*
)
);
VLC_EXPORT
(
void
,
block_ChainRelease
,
(
block_t
*
)
);
VLC_EXPORT
(
int
,
block_ChainExtract
,
(
block_t
*
,
void
*
,
int
)
);
VLC_EXPORT
(
block_t
*
,
block_ChainGather
,
(
block_t
*
)
);
/* a bit special, only for new/other block manager */
VLC_EXPORT
(
block_t
*
,
block_NewEmpty
,
(
void
)
);
static
inline
block_t
*
block_ChainGather
(
block_t
*
p_list
)
{
int
i_total
=
0
;
block_t
*
b
,
*
g
;
if
(
p_list
->
p_next
==
NULL
)
return
p_list
;
/* Already gathered */
for
(
b
=
p_list
;
b
!=
NULL
;
b
=
b
->
p_next
)
i_total
+=
b
->
i_buffer
;
g
=
block_New
(
p_list
->
p_manager
,
i_total
);
block_ChainExtract
(
p_list
,
g
->
p_buffer
,
g
->
i_buffer
);
g
->
i_flags
=
p_list
->
i_flags
;
g
->
i_pts
=
p_list
->
i_pts
;
g
->
i_dts
=
p_list
->
i_dts
;
/* free p_list */
block_ChainRelease
(
p_list
);
return
g
;
}
/****************************************************************************
* Fifos of blocks.
****************************************************************************
* Avoid touching block_fifo_t unless you really know what you are doing.
* ( Some race conditions has to be correctly handled, like in win32 ;)
* - block_FifoNew : create and init a new fifo
* - block_FifoRelease : destroy a fifo and free all blocks in it.
* - block_FifoEmpty : free all blocks in a fifo
* - block_FifoPut : put a block
* - block_FifoGet : get a packet from the fifo (and wait if it is empty)
* - block_FifoShow : show the first packet of the fifo (and wait if
* needed), becarefull, you can use it ONLY if you are sure to be the
* only one getting data from the fifo.
****************************************************************************/
struct
block_fifo_t
{
vlc_mutex_t
lock
;
/* fifo data lock */
vlc_cond_t
wait
;
/* fifo data conditional variable */
int
i_depth
;
block_t
*
p_first
;
block_t
**
pp_last
;
};
#define block_FifoNew( a ) __block_FifoNew( VLC_OBJECT(a) )
VLC_EXPORT
(
block_fifo_t
*
,
__block_FifoNew
,
(
vlc_object_t
*
)
);
...
...
src/misc/block.c
View file @
1c18e067
...
...
@@ -25,117 +25,76 @@
* Preamble
*****************************************************************************/
#include <stdlib.h>
#include <stdarg.h>
#include <vlc/vlc.h>
#include "vlc_block.h"
/*****************************************************************************
* Block functions.
*****************************************************************************/
/* private */
struct
block_sys_t
{
vlc_mutex_t
lock
;
uint8_t
*
p_allocated_buffer
;
int
i_allocated_buffer
;
vlc_bool_t
b_modify
;
/* has it been put in modified state */
int
i_duplicated
;
/* how many times has the content been
* duplicated */
};
static
void
BlockRelease
(
block_t
*
p_block
)
{
vlc_mutex_lock
(
&
p_block
->
p_sys
->
lock
);
p_block
->
p_sys
->
i_duplicated
--
;
if
(
p_block
->
p_sys
->
i_duplicated
<
0
)
{
vlc_mutex_unlock
(
&
p_block
->
p_sys
->
lock
);
vlc_mutex_destroy
(
&
p_block
->
p_sys
->
lock
);
free
(
p_block
->
p_sys
->
p_allocated_buffer
);
free
(
p_block
->
p_sys
);
free
(
p_block
);
return
;
}
vlc_mutex_unlock
(
&
p_block
->
p_sys
->
lock
);
free
(
p_block
);
}
static
block_t
*
__BlockDupContent
(
block_t
*
p_block
)
{
block_t
*
p_dup
;
p_dup
=
block_New
(
p_block
->
p_manager
,
p_block
->
i_buffer
);
memcpy
(
p_dup
->
p_buffer
,
p_block
->
p_buffer
,
p_block
->
i_buffer
);
p_dup
->
i_flags
=
p_block
->
i_flags
;
p_dup
->
i_pts
=
p_block
->
i_pts
;
p_dup
->
i_dts
=
p_block
->
i_dts
;
p_dup
->
i_length
=
p_block
->
i_length
;
p_dup
->
i_rate
=
p_block
->
i_rate
;
#define BLOCK_PADDING_SIZE 32
static
void
BlockRelease
(
block_t
*
);
return
p_dup
;
}
static
block_t
*
BlockModify
(
block_t
*
p_block
,
vlc_bool_t
b_will_modify
)
block_t
*
__block_New
(
vlc_object_t
*
p_obj
,
int
i_size
)
{
block_t
*
p_mod
=
p_block
;
/* by default */
vlc_mutex_lock
(
&
p_block
->
p_sys
->
lock
);
/* We do only one malloc
* TODO bench if doing 2 malloc but keeping a pool of buffer is better
* 16 -> align on 16
* 2*BLOCK_PADDING_SIZE -> pre + post padding
*/
const
int
i_alloc
=
i_size
+
2
*
BLOCK_PADDING_SIZE
+
16
;
block_t
*
p_block
=
malloc
(
sizeof
(
block_t
)
+
sizeof
(
block_sys_t
)
+
i_alloc
);
block_sys_t
*
p_sys
;
if
(
p_block
->
p_sys
->
b_modify
==
b_will_modify
)
{
vlc_mutex_unlock
(
&
p_block
->
p_sys
->
lock
);
return
p_block
;
}
if
(
p_block
==
NULL
)
return
NULL
;
if
(
p_block
->
p_sys
->
i_duplicated
==
0
)
{
p_block
->
p_sys
->
b_modify
=
b_will_modify
;
vlc_mutex_unlock
(
&
p_block
->
p_sys
->
lock
);
return
p_block
;
}
/* FIXME we could avoid that
* we just need to create a new p_sys with new mem FIXME */
p_mod
=
__BlockDupContent
(
p_block
);
vlc_mutex_unlock
(
&
p_block
->
p_sys
->
lock
);
/* Fill opaque data */
p_sys
=
(
block_sys_t
*
)(
(
uint8_t
*
)
p_block
+
sizeof
(
block_t
)
);
p_sys
->
i_allocated_buffer
=
i_alloc
;
p_sys
->
p_allocated_buffer
=
(
uint8_t
*
)
p_block
+
sizeof
(
block_t
)
+
sizeof
(
block_sys_t
);
BlockRelease
(
p_block
);
/* Fill all fields */
p_block
->
p_next
=
NULL
;
p_block
->
i_flags
=
0
;
p_block
->
i_pts
=
0
;
p_block
->
i_dts
=
0
;
p_block
->
i_length
=
0
;
p_block
->
i_rate
=
0
;
p_block
->
i_buffer
=
i_size
;
p_block
->
p_buffer
=
&
p_sys
->
p_allocated_buffer
[
32
+
15
-
((
long
)
p_sys
->
p_allocated_buffer
%
16
)];
p_block
->
pf_release
=
BlockRelease
;
p_block
->
p_manager
=
VLC_OBJECT
(
p_obj
->
p_vlc
);
/* Is ok, as no comunication between p_vlc */
p_block
->
p_sys
=
p_sys
;
return
p_
mod
;
return
p_
block
;
}
static
block_t
*
BlockDuplicate
(
block_t
*
p_block
)
block_t
*
block_Realloc
(
block_t
*
p_block
,
int
i_prebody
,
int
i_body
)
{
block_t
*
p_dup
;
int
i_buffer_size
;
vlc_mutex_lock
(
&
p_block
->
p_sys
->
lock
);
if
(
!
p_block
->
p_sys
->
b_modify
)
if
(
p_block
->
pf_release
!=
BlockRelease
)
{
p_block
->
p_sys
->
i_duplicated
++
;
vlc_mutex_unlock
(
&
p_block
->
p_sys
->
lock
);
p_dup
=
block_NewEmpty
(
);
memcpy
(
p_dup
,
p_block
,
sizeof
(
block_t
)
);
p_dup
->
p_next
=
NULL
;
return
p_dup
;
/* Special case when pf_release if overloaded
* TODO if used one day, them implement it in a smarter way */
block_t
*
p_dup
=
block_Duplicate
(
p_block
);
block_Release
(
p_block
);
p_block
=
p_dup
;
}
p_dup
=
__BlockDupContent
(
p_block
);
vlc_mutex_unlock
(
&
p_block
->
p_sys
->
lock
);
return
p_dup
;
}
static
block_t
*
BlockRealloc
(
block_t
*
p_block
,
int
i_prebody
,
int
i_body
)
{
int
i_buffer_size
=
i_prebody
+
i_body
;
i_buffer_size
=
i_prebody
+
i_body
;
if
(
i_body
<
0
||
i_buffer_size
<=
0
)
return
NULL
;
vlc_mutex_lock
(
&
p_block
->
p_sys
->
lock
);
if
(
i_prebody
<
(
p_block
->
p_buffer
-
p_block
->
p_sys
->
p_allocated_buffer
+
p_block
->
p_sys
->
i_allocated_buffer
)
||
p_block
->
p_buffer
-
i_prebody
>
p_block
->
p_sys
->
p_allocated_buffer
)
...
...
@@ -164,174 +123,19 @@ static block_t *BlockRealloc( block_t *p_block, int i_prebody, int i_body )
memcpy
(
p_rea
->
p_buffer
+
i_prebody
,
p_block
->
p_buffer
,
__MIN
(
p_block
->
i_buffer
,
p_rea
->
i_buffer
-
i_prebody
)
);
vlc_mutex_unlock
(
&
p_block
->
p_sys
->
lock
);
block_Release
(
p_block
);
return
p_rea
;
}
vlc_mutex_unlock
(
&
p_block
->
p_sys
->
lock
);
return
p_block
;
}
/*****************************************************************************
* Standard block management
*
*****************************************************************************/
/* to be used by other block management */
block_t
*
block_NewEmpty
(
void
)
{
block_t
*
p_block
;
p_block
=
malloc
(
sizeof
(
block_t
)
);
memset
(
p_block
,
0
,
sizeof
(
block_t
)
);
p_block
->
p_next
=
NULL
;
p_block
->
i_flags
=
0
;
p_block
->
i_pts
=
0
;
p_block
->
i_dts
=
0
;
p_block
->
i_length
=
0
;
p_block
->
i_rate
=
0
;
p_block
->
i_buffer
=
0
;
p_block
->
p_buffer
=
NULL
;
p_block
->
pf_release
=
NULL
;
p_block
->
pf_duplicate
=
NULL
;
p_block
->
pf_modify
=
NULL
;
p_block
->
pf_realloc
=
NULL
;
p_block
->
p_manager
=
NULL
;
p_block
->
p_sys
=
NULL
;
return
p_block
;
}
block_t
*
__block_New
(
vlc_object_t
*
p_obj
,
int
i_size
)
{
block_t
*
p_block
;
block_sys_t
*
p_sys
;
p_block
=
block_NewEmpty
();
p_block
->
pf_release
=
BlockRelease
;
p_block
->
pf_duplicate
=
BlockDuplicate
;
p_block
->
pf_modify
=
BlockModify
;
p_block
->
pf_realloc
=
BlockRealloc
;
/* that should be ok (no comunication between multiple p_vlc) */
p_block
->
p_manager
=
VLC_OBJECT
(
p_obj
->
p_vlc
);
p_block
->
p_sys
=
p_sys
=
malloc
(
sizeof
(
block_sys_t
)
);
vlc_mutex_init
(
p_obj
,
&
p_sys
->
lock
);
/* XXX align on 16 and add 32 prebuffer/posbuffer bytes */
p_sys
->
i_allocated_buffer
=
i_size
+
32
+
32
+
16
;
p_sys
->
p_allocated_buffer
=
malloc
(
p_sys
->
i_allocated_buffer
);
p_block
->
i_buffer
=
i_size
;
p_block
->
p_buffer
=
&
p_sys
->
p_allocated_buffer
[
32
+
15
-
((
long
)
p_sys
->
p_allocated_buffer
%
16
)];
p_sys
->
i_duplicated
=
0
;
p_sys
->
b_modify
=
VLC_TRUE
;
return
p_block
;
}
void
block_ChainAppend
(
block_t
**
pp_list
,
block_t
*
p_block
)
{
if
(
*
pp_list
==
NULL
)
{
*
pp_list
=
p_block
;
}
else
{
block_t
*
p
=
*
pp_list
;
while
(
p
->
p_next
)
{
p
=
p
->
p_next
;
}
p
->
p_next
=
p_block
;
}
}
void
block_ChainLastAppend
(
block_t
***
ppp_last
,
block_t
*
p_block
)
{
block_t
*
p_last
=
p_block
;
/* Append the block */
**
ppp_last
=
p_block
;
/* Update last pointer */
while
(
p_last
->
p_next
)
p_last
=
p_last
->
p_next
;
*
ppp_last
=
&
p_last
->
p_next
;
}
void
block_ChainRelease
(
block_t
*
p_block
)
{
while
(
p_block
)
{
block_t
*
p_next
;
p_next
=
p_block
->
p_next
;
p_block
->
pf_release
(
p_block
);
p_block
=
p_next
;
}
}
int
block_ChainExtract
(
block_t
*
p_list
,
void
*
p_data
,
int
i_max
)
static
void
BlockRelease
(
block_t
*
p_block
)
{
block_t
*
b
;
int
i_total
=
0
;
uint8_t
*
p
=
p_data
;
for
(
b
=
p_list
;
b
!=
NULL
;
b
=
b
->
p_next
)
{
int
i_copy
;
i_copy
=
__MIN
(
i_max
,
b
->
i_buffer
);
if
(
i_copy
>
0
)
{
memcpy
(
p
,
b
->
p_buffer
,
i_copy
);
i_max
-=
i_copy
;
i_total
+=
i_copy
;
p
+=
i_copy
;
if
(
i_max
==
0
)
{
return
i_total
;
}
}
}
return
i_total
;
free
(
p_block
);
}
block_t
*
block_ChainGather
(
block_t
*
p_list
)
{
int
i_total
=
0
;
block_t
*
b
,
*
g
;
if
(
p_list
->
p_next
==
NULL
)
{
/* only one, so no need */
return
p_list
;
}
for
(
b
=
p_list
;
b
!=
NULL
;
b
=
b
->
p_next
)
{
i_total
+=
b
->
i_buffer
;
}
g
=
block_New
(
p_list
->
p_manager
,
i_total
);
block_ChainExtract
(
p_list
,
g
->
p_buffer
,
g
->
i_buffer
);
g
->
i_flags
=
p_list
->
i_flags
;
g
->
i_pts
=
p_list
->
i_pts
;
g
->
i_dts
=
p_list
->
i_dts
;
/* free p_list */
block_ChainRelease
(
p_list
);
return
g
;
}
/*****************************************************************************
* block_fifo_t management
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment