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) { 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; 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) { void encoder_next_frame(encoder_state *encoder_state) {
const encoder_control * const encoder = encoder_state->encoder_control; const encoder_control * const encoder = encoder_state->encoder_control;
picture *old_pic;
// Remove the ref pic (if present) // Remove the ref pic (if present)
if (encoder_state->ref->used_size == (uint32_t)encoder->cfg->ref_frames) { 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 // Add current picture as reference
picture_list_add(encoder_state->ref, encoder_state->cur_pic); picture_list_add(encoder_state->ref, encoder_state->cur_pic);
// Allocate new memory to current picture // Allocate new memory to current picture
old_pic = encoder_state->cur_pic;
// TODO: reuse memory from old reference // 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); 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 // 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_y,old_pic->coeff_y);
MOVE_POINTER(encoder_state->cur_pic->coeff_u,encoder_state->ref->pics[0]->coeff_u); MOVE_POINTER(encoder_state->cur_pic->coeff_u,old_pic->coeff_u);
MOVE_POINTER(encoder_state->cur_pic->coeff_v,encoder_state->ref->pics[0]->coeff_v); MOVE_POINTER(encoder_state->cur_pic->coeff_v,old_pic->coeff_v);
picture_free(old_pic);
encoder_state->frame++; encoder_state->frame++;
encoder_state->poc++; encoder_state->poc++;

View file

@ -21,6 +21,7 @@
* \file * \file
*/ */
#include "threads.h"
#include "picture.h" #include "picture.h"
#include "strategyselector.h" #include "strategyselector.h"
@ -192,6 +193,11 @@ int picture_list_destroy(picture_list *list)
*/ */
int picture_list_add(picture_list *list,picture* pic) 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; int i = 0;
if (list->size == list->used_size) { if (list->size == list->used_size) {
if (!picture_list_resize(list, list->size*2)) return 0; 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 * \param picture_list list to use
* \return 1 on success * \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 // Must be within list boundaries
if (n >= list->used_size) if (n >= list->used_size)
@ -220,9 +226,10 @@ int picture_list_rem(picture_list *list, unsigned n, int8_t destroy)
return 0; return 0;
} }
if (destroy) { if (!picture_free(list->pics[n])) {
picture_free(list->pics[n]); fprintf(stderr, "Could not free picture!\n");
list->pics[n] = NULL; assert(0); //Stop here
return 0;
} }
// The last item is easy to remove // The last item is easy to remove
@ -230,9 +237,10 @@ int picture_list_rem(picture_list *list, unsigned n, int8_t destroy)
list->pics[n] = NULL; list->pics[n] = NULL;
list->used_size--; list->used_size--;
} else { } else {
int i = n;
// Shift all following pics one backward in the list // Shift all following pics one backward in the list
for (; n < list->used_size - 1; ++n) { for (i = n; i < list->used_size - 1; ++i) {
list->pics[n] = list->pics[n + 1]; list->pics[i] = list->pics[i + 1];
} }
list->pics[list->used_size - 1] = NULL; list->pics[list->used_size - 1] = NULL;
list->used_size--; 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->width_in_lcu = width_in_lcu;
pic->height_in_lcu = height_in_lcu; pic->height_in_lcu = height_in_lcu;
pic->referenced = 0; pic->referenced = 0;
pic->refcount = 1; //We give a reference to caller
// Allocate buffers // Allocate buffers
pic->y_data = MALLOC(pixel, luma_size); pic->y_data = MALLOC(pixel, luma_size);
pic->u_data = MALLOC(pixel, chroma_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 * \param pic picture pointer
* \return 1 on success, 0 on failure * \return 1 on success, 0 on failure
*/ */
int picture_free(picture * const pic) 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->u_data);
free(pic->v_data); free(pic->v_data);
free(pic->y_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 height_in_lcu; //!< \brief Picture width in number of LCU's.
int32_t width_in_lcu; //!< \brief Picture height 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. 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. cu_info* cu_array; //!< \brief Info for each CU at each depth.
uint8_t type; uint8_t type;
uint8_t slicetype; 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_resize(picture_list *list, unsigned size);
int picture_list_destroy(picture_list *list); int picture_list_destroy(picture_list *list);
int picture_list_add(picture_list *list, picture *pic); 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); 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_