Reference count for picture

This commit is contained in:
Laurent Fasnacht 2014-05-05 07:54:39 +02:00
parent 323054d5e2
commit 7f6f4fe9c1
4 changed files with 67 additions and 14 deletions

View file

@ -442,7 +442,7 @@ static void encoder_clear_refs(encoder_state *encoder_state) {
}
while (encoder_state->ref->used_size) {
picture_list_rem(encoder_state->ref, encoder_state->ref->used_size - 1, 1);
picture_list_rem(encoder_state->ref, encoder_state->ref->used_size - 1);
}
encoder_state->poc = 0;
@ -1375,21 +1375,25 @@ static void encode_VUI(encoder_state * const encoder_state)
void encoder_next_frame(encoder_state *encoder_state) {
const encoder_control * const encoder = encoder_state->encoder_control;
picture *old_pic;
// Remove the ref pic (if present)
if (encoder_state->ref->used_size == (uint32_t)encoder->cfg->ref_frames) {
picture_list_rem(encoder_state->ref, encoder_state->ref->used_size-1, 1);
picture_list_rem(encoder_state->ref, encoder_state->ref->used_size-1);
}
// Add current picture as reference
picture_list_add(encoder_state->ref, encoder_state->cur_pic);
// Allocate new memory to current picture
old_pic = encoder_state->cur_pic;
// TODO: reuse memory from old reference
encoder_state->cur_pic = picture_alloc(encoder_state->cur_pic->width, encoder_state->cur_pic->height, encoder_state->cur_pic->width_in_lcu, encoder_state->cur_pic->height_in_lcu);
// Copy pointer from the last cur_pic because we don't want to reallocate it
MOVE_POINTER(encoder_state->cur_pic->coeff_y,encoder_state->ref->pics[0]->coeff_y);
MOVE_POINTER(encoder_state->cur_pic->coeff_u,encoder_state->ref->pics[0]->coeff_u);
MOVE_POINTER(encoder_state->cur_pic->coeff_v,encoder_state->ref->pics[0]->coeff_v);
MOVE_POINTER(encoder_state->cur_pic->coeff_y,old_pic->coeff_y);
MOVE_POINTER(encoder_state->cur_pic->coeff_u,old_pic->coeff_u);
MOVE_POINTER(encoder_state->cur_pic->coeff_v,old_pic->coeff_v);
picture_free(old_pic);
encoder_state->frame++;
encoder_state->poc++;

View file

@ -21,6 +21,7 @@
* \file
*/
#include "threads.h"
#include "picture.h"
#include "strategyselector.h"
@ -192,6 +193,11 @@ int picture_list_destroy(picture_list *list)
*/
int picture_list_add(picture_list *list,picture* pic)
{
if (ATOMIC_INC(&(pic->refcount)) == 1) {
fprintf(stderr, "Tried to add an unreferenced picture. This is a bug!\n");
assert(0); //Stop for debugging
return 0;
}
int i = 0;
if (list->size == list->used_size) {
if (!picture_list_resize(list, list->size*2)) return 0;
@ -212,7 +218,7 @@ int picture_list_add(picture_list *list,picture* pic)
* \param picture_list list to use
* \return 1 on success
*/
int picture_list_rem(picture_list *list, unsigned n, int8_t destroy)
int picture_list_rem(picture_list * const list, const unsigned n)
{
// Must be within list boundaries
if (n >= list->used_size)
@ -220,19 +226,21 @@ int picture_list_rem(picture_list *list, unsigned n, int8_t destroy)
return 0;
}
if (destroy) {
picture_free(list->pics[n]);
list->pics[n] = NULL;
if (!picture_free(list->pics[n])) {
fprintf(stderr, "Could not free picture!\n");
assert(0); //Stop here
return 0;
}
// The last item is easy to remove
if (n == list->used_size - 1) {
list->pics[n] = NULL;
list->used_size--;
} else {
int i = n;
// Shift all following pics one backward in the list
for (; n < list->used_size - 1; ++n) {
list->pics[n] = list->pics[n + 1];
for (i = n; i < list->used_size - 1; ++i) {
list->pics[i] = list->pics[i + 1];
}
list->pics[list->used_size - 1] = NULL;
list->used_size--;
@ -262,6 +270,7 @@ picture *picture_alloc(const int32_t width, const int32_t height,
pic->width_in_lcu = width_in_lcu;
pic->height_in_lcu = height_in_lcu;
pic->referenced = 0;
pic->refcount = 1; //We give a reference to caller
// Allocate buffers
pic->y_data = MALLOC(pixel, luma_size);
pic->u_data = MALLOC(pixel, chroma_size);
@ -301,12 +310,14 @@ picture *picture_alloc(const int32_t width, const int32_t height,
}
/**
* \brief Free memory allocated to picture
* \brief Free memory allocated to picture (if we have no reference left)
* \param pic picture pointer
* \return 1 on success, 0 on failure
*/
int picture_free(picture * const pic)
{
int32_t new_refcount = ATOMIC_DEC(&(pic->refcount));
if (new_refcount > 0) return 1;
free(pic->u_data);
free(pic->v_data);
free(pic->y_data);

View file

@ -120,6 +120,7 @@ typedef struct picture_struct
int32_t height_in_lcu; //!< \brief Picture width in number of LCU's.
int32_t width_in_lcu; //!< \brief Picture height in number of LCU's.
uint8_t referenced; //!< \brief Whether this picture is referenced.
int32_t refcount; //!< \brief Number of references in reflist to the picture
cu_info* cu_array; //!< \brief Info for each CU at each depth.
uint8_t type;
uint8_t slicetype;
@ -224,7 +225,7 @@ picture_list * picture_list_init(int size);
int picture_list_resize(picture_list *list, unsigned size);
int picture_list_destroy(picture_list *list);
int picture_list_add(picture_list *list, picture *pic);
int picture_list_rem(picture_list *list, unsigned n, int8_t destroy);
int picture_list_rem(picture_list *list, unsigned n);
typedef unsigned (*cost_16bit_nxn_func)(pixel *block1, pixel *block2);

37
src/threads.h Normal file
View file

@ -0,0 +1,37 @@
#ifndef THREADS_H_
#define THREADS_H_
/*****************************************************************************
* This file is part of Kvazaar HEVC encoder.
*
* Copyright (C) 2013-2014 Tampere University of Technology and others (see
* COPYING file).
*
* Kvazaar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* Kvazaar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Kvazaar. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#include <pthread.h>
#ifdef __GNUC__
#define ATOMIC_INC(ptr) __sync_add_and_fetch((volatile int32_t*)ptr, 1)
#define ATOMIC_DEC(ptr) __sync_add_and_fetch((volatile int32_t*)ptr, -1)
#else //__GNUC__
//TODO: we assume !GCC => Windows... this may be bad
#define ATOMIC_INC(ptr) InterlockedIncrement((volatile LONG*)ptr)
#define ATOMIC_DEC(ptr) InterlockedDecrement((volatile LONG*)ptr)
#endif //__GNUC__
#endif //THREADS_H_