flat arrays which have lower overhead than millions of mallocd() elements. Originally committed as revision 11399 to svn://svn.ffmpeg.org/ffmpeg/trunktags/v0.5
@@ -48,12 +48,15 @@ int ff_nut_sp_pts_cmp(syncpoint_t *a, syncpoint_t *b){ | |||||
} | } | ||||
void ff_nut_add_sp(NUTContext *nut, int64_t pos, int64_t back_ptr, int64_t ts){ | void ff_nut_add_sp(NUTContext *nut, int64_t pos, int64_t back_ptr, int64_t ts){ | ||||
syncpoint_t *sp2, *sp= av_mallocz(sizeof(syncpoint_t)); | |||||
syncpoint_t *sp= av_mallocz(sizeof(syncpoint_t)); | |||||
struct AVTreeNode *node= av_mallocz(av_tree_node_size); | |||||
sp->pos= pos; | sp->pos= pos; | ||||
sp->back_ptr= back_ptr; | sp->back_ptr= back_ptr; | ||||
sp->ts= ts; | sp->ts= ts; | ||||
sp2= av_tree_insert(&nut->syncpoints, sp, ff_nut_sp_pos_cmp); | |||||
if(sp2 && sp2 != sp) | |||||
av_tree_insert(&nut->syncpoints, sp, ff_nut_sp_pos_cmp, &node); | |||||
if(node){ | |||||
av_free(sp); | av_free(sp); | ||||
av_free(node); | |||||
} | |||||
} | } |
@@ -28,6 +28,8 @@ typedef struct AVTreeNode{ | |||||
int state; | int state; | ||||
}AVTreeNode; | }AVTreeNode; | ||||
const int av_tree_node_size = sizeof(AVTreeNode); | |||||
void *av_tree_find(const AVTreeNode *t, void *key, int (*cmp)(void *key, const void *b), void *next[2]){ | void *av_tree_find(const AVTreeNode *t, void *key, int (*cmp)(void *key, const void *b), void *next[2]){ | ||||
if(t){ | if(t){ | ||||
unsigned int v= cmp(t->elem, key); | unsigned int v= cmp(t->elem, key); | ||||
@@ -45,14 +47,14 @@ void *av_tree_find(const AVTreeNode *t, void *key, int (*cmp)(void *key, const v | |||||
return NULL; | return NULL; | ||||
} | } | ||||
void *av_tree_insert(AVTreeNode **tp, void *key, int (*cmp)(void *key, const void *b)){ | |||||
void *av_tree_insert(AVTreeNode **tp, void *key, int (*cmp)(void *key, const void *b), AVTreeNode **next){ | |||||
AVTreeNode *t= *tp; | AVTreeNode *t= *tp; | ||||
if(t){ | if(t){ | ||||
unsigned int v= cmp(t->elem, key); | unsigned int v= cmp(t->elem, key); | ||||
if(v){ | if(v){ | ||||
int i= v>>31; | int i= v>>31; | ||||
AVTreeNode **child= &t->child[i]; | AVTreeNode **child= &t->child[i]; | ||||
void *ret= av_tree_insert(child, key, cmp); | |||||
void *ret= av_tree_insert(child, key, cmp, next); | |||||
if(!ret){ | if(!ret){ | ||||
t->state -= ((int)v>>31)|1; | t->state -= ((int)v>>31)|1; | ||||
if(!(t->state&1)){ | if(!(t->state&1)){ | ||||
@@ -83,7 +85,7 @@ void *av_tree_insert(AVTreeNode **tp, void *key, int (*cmp)(void *key, const voi | |||||
return t->elem; | return t->elem; | ||||
} | } | ||||
}else{ | }else{ | ||||
*tp= av_mallocz(sizeof(AVTreeNode)); | |||||
*tp= *next; *next= NULL; | |||||
(*tp)->elem= key; | (*tp)->elem= key; | ||||
return NULL; | return NULL; | ||||
} | } | ||||
@@ -28,6 +28,7 @@ | |||||
#define FFMPEG_TREE_H | #define FFMPEG_TREE_H | ||||
struct AVTreeNode; | struct AVTreeNode; | ||||
extern const int av_tree_node_size; | |||||
/** | /** | ||||
* Finds an element. | * Finds an element. | ||||
@@ -46,13 +47,22 @@ void *av_tree_find(const struct AVTreeNode *root, void *key, int (*cmp)(void *ke | |||||
* @param rootp A pointer to a pointer to the root node of the tree. Note that | * @param rootp A pointer to a pointer to the root node of the tree. Note that | ||||
* the root node can change during insertions, this is required | * the root node can change during insertions, this is required | ||||
* to keep the tree balanced. | * to keep the tree balanced. | ||||
* @param next AVTreeNode used for the inserted element, must be allocated and | |||||
* zeroed by the user. And will be set to NULL if used by | |||||
* av_tree_insert(). This allows the use of flat arrays, which have | |||||
* lower overhead compared to many malloced elements. | |||||
* You might want to define a function like: | |||||
* void *tree_insert(struct AVTreeNode **rootp, void *key, int (*cmp)(void *key, const void *b), AVTreeNode **next){ | |||||
* if(!*next) *next= av_mallocz(av_tree_node_size); | |||||
* return av_tree_insert(rootp, key, cmp, next); | |||||
* } | |||||
* | * | ||||
* @return If no insertion happened, the found element. | * @return If no insertion happened, the found element. | ||||
* If an insertion happened, then either key or NULL will be returned. | * If an insertion happened, then either key or NULL will be returned. | ||||
* Which one it is depends on the tree state and the implementation. You | * Which one it is depends on the tree state and the implementation. You | ||||
* should make no assumptions that it's one or the other in the code. | * should make no assumptions that it's one or the other in the code. | ||||
*/ | */ | ||||
void *av_tree_insert(struct AVTreeNode **rootp, void *key, int (*cmp)(void *key, const void *b)); | |||||
void *av_tree_insert(struct AVTreeNode **rootp, void *key, int (*cmp)(void *key, const void *b), struct AVTreeNode **next); | |||||
void av_tree_destroy(struct AVTreeNode *t); | void av_tree_destroy(struct AVTreeNode *t); | ||||
#endif /* FFMPEG_TREE_H */ | #endif /* FFMPEG_TREE_H */ |