Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc
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
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