|
|
@@ -225,6 +225,10 @@ typedef struct Vp3DecodeContext { |
|
|
|
int superblock_count; |
|
|
|
int superblock_width; |
|
|
|
int superblock_height; |
|
|
|
int y_superblock_width; |
|
|
|
int y_superblock_height; |
|
|
|
int c_superblock_width; |
|
|
|
int c_superblock_height; |
|
|
|
int u_superblock_start; |
|
|
|
int v_superblock_start; |
|
|
|
unsigned char *superblock_coding; |
|
|
@@ -292,8 +296,10 @@ typedef struct Vp3DecodeContext { |
|
|
|
* This function sets up all of the various blocks mappings: |
|
|
|
* superblocks <-> fragments, macroblocks <-> fragments, |
|
|
|
* superblocks <-> macroblocks |
|
|
|
* |
|
|
|
* Returns 0 is successful; returns 1 if *anything* went wrong. |
|
|
|
*/ |
|
|
|
static void init_block_mapping(Vp3DecodeContext *s) |
|
|
|
static int init_block_mapping(Vp3DecodeContext *s) |
|
|
|
{ |
|
|
|
int i, j; |
|
|
|
signed int hilbert_walk_y[16]; |
|
|
@@ -387,9 +393,10 @@ static void init_block_mapping(Vp3DecodeContext *s) |
|
|
|
/* start of Y superblocks */ |
|
|
|
right_edge = s->fragment_width; |
|
|
|
bottom_edge = s->fragment_height; |
|
|
|
current_width = 0; |
|
|
|
current_width = -1; |
|
|
|
current_height = 0; |
|
|
|
superblock_row_inc = 3 * s->fragment_width; |
|
|
|
superblock_row_inc = 3 * s->fragment_width - |
|
|
|
(s->y_superblock_width * 4 - s->fragment_width); |
|
|
|
hilbert = hilbert_walk_y; |
|
|
|
|
|
|
|
/* the first operation for this variable is to advance by 1 */ |
|
|
@@ -400,9 +407,10 @@ static void init_block_mapping(Vp3DecodeContext *s) |
|
|
|
/* start of U superblocks */ |
|
|
|
right_edge = s->fragment_width / 2; |
|
|
|
bottom_edge = s->fragment_height / 2; |
|
|
|
current_width = 0; |
|
|
|
current_width = -1; |
|
|
|
current_height = 0; |
|
|
|
superblock_row_inc = 3 * (s->fragment_width / 2); |
|
|
|
superblock_row_inc = 3 * (s->fragment_width / 2) - |
|
|
|
(s->c_superblock_width * 4 - s->fragment_width / 2); |
|
|
|
hilbert = hilbert_walk_c; |
|
|
|
|
|
|
|
/* the first operation for this variable is to advance by 1 */ |
|
|
@@ -413,9 +421,10 @@ static void init_block_mapping(Vp3DecodeContext *s) |
|
|
|
/* start of V superblocks */ |
|
|
|
right_edge = s->fragment_width / 2; |
|
|
|
bottom_edge = s->fragment_height / 2; |
|
|
|
current_width = 0; |
|
|
|
current_width = -1; |
|
|
|
current_height = 0; |
|
|
|
superblock_row_inc = 3 * (s->fragment_width / 2); |
|
|
|
superblock_row_inc = 3 * (s->fragment_width / 2) - |
|
|
|
(s->c_superblock_width * 4 - s->fragment_width / 2); |
|
|
|
hilbert = hilbert_walk_c; |
|
|
|
|
|
|
|
/* the first operation for this variable is to advance by 1 */ |
|
|
@@ -423,9 +432,9 @@ static void init_block_mapping(Vp3DecodeContext *s) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (current_width >= right_edge) { |
|
|
|
if (current_width >= right_edge - 1) { |
|
|
|
/* reset width and move to next superblock row */ |
|
|
|
current_width = 0; |
|
|
|
current_width = -1; |
|
|
|
current_height += 4; |
|
|
|
|
|
|
|
/* fragment is now at the start of a new superblock row */ |
|
|
@@ -435,21 +444,23 @@ static void init_block_mapping(Vp3DecodeContext *s) |
|
|
|
/* iterate through all 16 fragments in a superblock */ |
|
|
|
for (j = 0; j < 16; j++) { |
|
|
|
current_fragment += hilbert[j]; |
|
|
|
current_width += travel_width[j]; |
|
|
|
current_height += travel_height[j]; |
|
|
|
|
|
|
|
/* check if the fragment is in bounds */ |
|
|
|
if ((current_width <= right_edge) && |
|
|
|
if ((current_width < right_edge) && |
|
|
|
(current_height < bottom_edge)) { |
|
|
|
s->superblock_fragments[mapping_index] = current_fragment; |
|
|
|
debug_init(" mapping fragment %d to superblock %d, position %d\n", |
|
|
|
s->superblock_fragments[mapping_index], i, j); |
|
|
|
debug_init(" mapping fragment %d to superblock %d, position %d (%d/%d x %d/%d)\n", |
|
|
|
s->superblock_fragments[mapping_index], i, j, |
|
|
|
current_width, right_edge, current_height, bottom_edge); |
|
|
|
} else { |
|
|
|
s->superblock_fragments[mapping_index] = -1; |
|
|
|
debug_init(" superblock %d, position %d has no fragment\n", |
|
|
|
i, j); |
|
|
|
debug_init(" superblock %d, position %d has no fragment (%d/%d x %d/%d)\n", |
|
|
|
i, j, |
|
|
|
current_width, right_edge, current_height, bottom_edge); |
|
|
|
} |
|
|
|
|
|
|
|
current_width += travel_width[j]; |
|
|
|
mapping_index++; |
|
|
|
} |
|
|
|
} |
|
|
@@ -458,9 +469,10 @@ static void init_block_mapping(Vp3DecodeContext *s) |
|
|
|
* all of the Y plane superblocks to build this mapping */ |
|
|
|
right_edge = s->macroblock_width; |
|
|
|
bottom_edge = s->macroblock_height; |
|
|
|
current_width = 0; |
|
|
|
current_width = -1; |
|
|
|
current_height = 0; |
|
|
|
superblock_row_inc = s->macroblock_width; |
|
|
|
superblock_row_inc = s->macroblock_width - |
|
|
|
(s->y_superblock_width * 2 - s->macroblock_width);; |
|
|
|
hilbert = hilbert_walk_mb; |
|
|
|
mapping_index = 0; |
|
|
|
current_macroblock = -1; |
|
|
@@ -478,10 +490,11 @@ static void init_block_mapping(Vp3DecodeContext *s) |
|
|
|
/* iterate through each potential macroblock in the superblock */ |
|
|
|
for (j = 0; j < 4; j++) { |
|
|
|
current_macroblock += hilbert_walk_mb[j]; |
|
|
|
current_width += travel_width_mb[j]; |
|
|
|
current_height += travel_height_mb[j]; |
|
|
|
|
|
|
|
/* check if the macroblock is in bounds */ |
|
|
|
if ((current_width <= right_edge) && |
|
|
|
if ((current_width < right_edge) && |
|
|
|
(current_height < bottom_edge)) { |
|
|
|
s->superblock_macroblocks[mapping_index] = current_macroblock; |
|
|
|
debug_init(" mapping macroblock %d to superblock %d, position %d\n", |
|
|
@@ -492,7 +505,6 @@ static void init_block_mapping(Vp3DecodeContext *s) |
|
|
|
i, j); |
|
|
|
} |
|
|
|
|
|
|
|
current_width += travel_width_mb[j]; |
|
|
|
mapping_index++; |
|
|
|
} |
|
|
|
} |
|
|
@@ -538,13 +550,13 @@ static void init_block_mapping(Vp3DecodeContext *s) |
|
|
|
/* C planes */ |
|
|
|
c_fragment = s->u_fragment_start + |
|
|
|
(i * s->fragment_width / 4) + (j / 2); |
|
|
|
s->all_fragments[c_fragment].macroblock = s->macroblock_count; |
|
|
|
s->all_fragments[c_fragment].macroblock = s->macroblock_count; |
|
|
|
s->macroblock_fragments[mapping_index++] = c_fragment; |
|
|
|
debug_init("%d ", c_fragment); |
|
|
|
|
|
|
|
c_fragment = s->v_fragment_start + |
|
|
|
(i * s->fragment_width / 4) + (j / 2); |
|
|
|
s->all_fragments[c_fragment].macroblock = s->macroblock_count; |
|
|
|
s->all_fragments[c_fragment].macroblock = s->macroblock_count; |
|
|
|
s->macroblock_fragments[mapping_index++] = c_fragment; |
|
|
|
debug_init("%d ", c_fragment); |
|
|
|
|
|
|
@@ -559,6 +571,8 @@ static void init_block_mapping(Vp3DecodeContext *s) |
|
|
|
|
|
|
|
current_fragment += s->fragment_width; |
|
|
|
} |
|
|
|
|
|
|
|
return 0; /* successful path out */ |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
@@ -1106,7 +1120,7 @@ static int get_motion_vector_fixed(GetBitContext *gb) |
|
|
|
* This function unpacks all of the superblock/macroblock/fragment coding |
|
|
|
* information from the bitstream. |
|
|
|
*/ |
|
|
|
static void unpack_superblocks(Vp3DecodeContext *s, GetBitContext *gb) |
|
|
|
static int unpack_superblocks(Vp3DecodeContext *s, GetBitContext *gb) |
|
|
|
{ |
|
|
|
int bit = 0; |
|
|
|
int current_superblock = 0; |
|
|
@@ -1212,6 +1226,11 @@ static void unpack_superblocks(Vp3DecodeContext *s, GetBitContext *gb) |
|
|
|
|
|
|
|
/* if the fragment is in bounds, check its coding status */ |
|
|
|
current_fragment = s->superblock_fragments[i * 16 + j]; |
|
|
|
if (current_fragment >= s->fragment_count) { |
|
|
|
printf (" vp3:unpack_superblocks(): bad fragment number (%d >= %d)\n", |
|
|
|
current_fragment, s->fragment_count); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
if (current_fragment != -1) { |
|
|
|
if (s->superblock_coding[i] == SB_NOT_CODED) { |
|
|
|
|
|
|
@@ -1286,13 +1305,15 @@ static void unpack_superblocks(Vp3DecodeContext *s, GetBitContext *gb) |
|
|
|
s->last_coded_y_fragment, |
|
|
|
s->first_coded_c_fragment, |
|
|
|
s->last_coded_c_fragment); |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
* This function unpacks all the coding mode data for individual macroblocks |
|
|
|
* from the bitstream. |
|
|
|
*/ |
|
|
|
static void unpack_modes(Vp3DecodeContext *s, GetBitContext *gb) |
|
|
|
static int unpack_modes(Vp3DecodeContext *s, GetBitContext *gb) |
|
|
|
{ |
|
|
|
int i, j, k; |
|
|
|
int scheme; |
|
|
@@ -1334,6 +1355,11 @@ static void unpack_modes(Vp3DecodeContext *s, GetBitContext *gb) |
|
|
|
if ((current_macroblock == -1) || |
|
|
|
(!s->macroblock_coded[current_macroblock])) |
|
|
|
continue; |
|
|
|
if (current_macroblock >= s->macroblock_count) { |
|
|
|
printf (" vp3:unpack_modes(): bad macroblock number (%d >= %d)\n", |
|
|
|
current_macroblock, s->macroblock_count); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
/* mode 7 means get 3 bits for each coding mode */ |
|
|
|
if (scheme == 7) |
|
|
@@ -1344,6 +1370,13 @@ static void unpack_modes(Vp3DecodeContext *s, GetBitContext *gb) |
|
|
|
for (k = 0; k < 6; k++) { |
|
|
|
current_fragment = |
|
|
|
s->macroblock_fragments[current_macroblock * 6 + k]; |
|
|
|
if (current_fragment == -1) |
|
|
|
continue; |
|
|
|
if (current_fragment >= s->fragment_count) { |
|
|
|
printf (" vp3:unpack_modes(): bad fragment number (%d >= %d)\n", |
|
|
|
current_fragment, s->fragment_count); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
if (s->all_fragments[current_fragment].coding_method != |
|
|
|
MODE_COPY) |
|
|
|
s->all_fragments[current_fragment].coding_method = |
|
|
@@ -1355,6 +1388,8 @@ static void unpack_modes(Vp3DecodeContext *s, GetBitContext *gb) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
@@ -1410,7 +1445,7 @@ static inline int adjust_vector(int *x, int *y, int c_plane) |
|
|
|
* This function unpacks all the motion vectors for the individual |
|
|
|
* macroblocks from the bitstream. |
|
|
|
*/ |
|
|
|
static void unpack_vectors(Vp3DecodeContext *s, GetBitContext *gb) |
|
|
|
static int unpack_vectors(Vp3DecodeContext *s, GetBitContext *gb) |
|
|
|
{ |
|
|
|
int i, j, k; |
|
|
|
int coding_mode; |
|
|
@@ -1448,8 +1483,18 @@ static void unpack_vectors(Vp3DecodeContext *s, GetBitContext *gb) |
|
|
|
if ((current_macroblock == -1) || |
|
|
|
(!s->macroblock_coded[current_macroblock])) |
|
|
|
continue; |
|
|
|
if (current_macroblock >= s->macroblock_count) { |
|
|
|
printf (" vp3:unpack_vectors(): bad macroblock number (%d >= %d)\n", |
|
|
|
current_macroblock, s->macroblock_count); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
current_fragment = s->macroblock_fragments[current_macroblock * 6]; |
|
|
|
if (current_fragment >= s->fragment_count) { |
|
|
|
printf (" vp3:unpack_vectors(): bad fragment number (%d >= %d\n", |
|
|
|
current_fragment, s->fragment_count); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
switch (s->all_fragments[current_fragment].coding_method) { |
|
|
|
|
|
|
|
case MODE_INTER_PLUS_MV: |
|
|
@@ -1559,6 +1604,13 @@ static void unpack_vectors(Vp3DecodeContext *s, GetBitContext *gb) |
|
|
|
for (k = 0; k < 6; k++) { |
|
|
|
current_fragment = |
|
|
|
s->macroblock_fragments[current_macroblock * 6 + k]; |
|
|
|
if (current_fragment == -1) |
|
|
|
continue; |
|
|
|
if (current_fragment >= s->fragment_count) { |
|
|
|
printf (" vp3:unpack_vectors(): bad fragment number (%d >= %d)\n", |
|
|
|
current_fragment, s->fragment_count); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
s->all_fragments[current_fragment].motion_halfpel_index = |
|
|
|
adjust_vector(&motion_x[k], &motion_y[k], |
|
|
|
((k == 4) || (k == 5))); |
|
|
@@ -1571,6 +1623,8 @@ static void unpack_vectors(Vp3DecodeContext *s, GetBitContext *gb) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
@@ -1632,7 +1686,7 @@ static int unpack_vlcs(Vp3DecodeContext *s, GetBitContext *gb, |
|
|
|
* This function unpacks all of the DCT coefficient data from the |
|
|
|
* bitstream. |
|
|
|
*/ |
|
|
|
static void unpack_dct_coeffs(Vp3DecodeContext *s, GetBitContext *gb) |
|
|
|
static int unpack_dct_coeffs(Vp3DecodeContext *s, GetBitContext *gb) |
|
|
|
{ |
|
|
|
int i; |
|
|
|
int dc_y_table; |
|
|
@@ -1716,6 +1770,8 @@ static void unpack_dct_coeffs(Vp3DecodeContext *s, GetBitContext *gb) |
|
|
|
residual_eob_run = unpack_vlcs(s, gb, &s->ac_vlc_4[ac_c_table], i, |
|
|
|
s->first_coded_c_fragment, s->last_coded_c_fragment, residual_eob_run); |
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
@@ -2072,6 +2128,7 @@ static void render_fragments(Vp3DecodeContext *s, |
|
|
|
(motion_source > lower_motion_limit)) { |
|
|
|
// printf (" vp3: help! motion source (%d) out of range (%d..%d)\n", |
|
|
|
// motion_source, upper_motion_limit, lower_motion_limit); |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
/* first, take care of copying a block from either the |
|
|
@@ -2210,6 +2267,10 @@ static int vp3_decode_init(AVCodecContext *avctx) |
|
|
|
{ |
|
|
|
Vp3DecodeContext *s = avctx->priv_data; |
|
|
|
int i; |
|
|
|
int c_width; |
|
|
|
int c_height; |
|
|
|
int y_superblock_count; |
|
|
|
int c_superblock_count; |
|
|
|
|
|
|
|
s->avctx = avctx; |
|
|
|
s->width = avctx->width; |
|
|
@@ -2222,11 +2283,20 @@ static int vp3_decode_init(AVCodecContext *avctx) |
|
|
|
* in the first frame decode */ |
|
|
|
s->quality_index = -1; |
|
|
|
|
|
|
|
s->superblock_width = (s->width + 31) / 32; |
|
|
|
s->superblock_height = (s->height + 31) / 32; |
|
|
|
s->superblock_count = s->superblock_width * s->superblock_height * 3 / 2; |
|
|
|
s->u_superblock_start = s->superblock_width * s->superblock_height; |
|
|
|
s->v_superblock_start = s->superblock_width * s->superblock_height * 5 / 4; |
|
|
|
s->y_superblock_width = (s->width + 31) / 32; |
|
|
|
s->y_superblock_height = (s->height + 31) / 32; |
|
|
|
y_superblock_count = s->y_superblock_width * s->y_superblock_height; |
|
|
|
|
|
|
|
/* work out the dimensions for the C planes */ |
|
|
|
c_width = s->width / 2; |
|
|
|
c_height = s->height / 2; |
|
|
|
s->c_superblock_width = (c_width + 31) / 32; |
|
|
|
s->c_superblock_height = (c_height + 31) / 32; |
|
|
|
c_superblock_count = s->c_superblock_width * s->c_superblock_height; |
|
|
|
|
|
|
|
s->superblock_count = y_superblock_count + (c_superblock_count * 2); |
|
|
|
s->u_superblock_start = y_superblock_count; |
|
|
|
s->v_superblock_start = s->u_superblock_start + c_superblock_count; |
|
|
|
s->superblock_coding = av_malloc(s->superblock_count); |
|
|
|
|
|
|
|
s->macroblock_width = (s->width + 15) / 16; |
|
|
@@ -2241,9 +2311,14 @@ static int vp3_decode_init(AVCodecContext *avctx) |
|
|
|
s->u_fragment_start = s->fragment_width * s->fragment_height; |
|
|
|
s->v_fragment_start = s->fragment_width * s->fragment_height * 5 / 4; |
|
|
|
|
|
|
|
debug_init(" width: %d x %d\n", s->width, s->height); |
|
|
|
debug_init(" superblocks: %d x %d, %d total\n", |
|
|
|
s->superblock_width, s->superblock_height, s->superblock_count); |
|
|
|
debug_init(" Y plane: %d x %d\n", s->width, s->height); |
|
|
|
debug_init(" C plane: %d x %d\n", c_width, c_height); |
|
|
|
debug_init(" Y superblocks: %d x %d, %d total\n", |
|
|
|
s->y_superblock_width, s->y_superblock_height, y_superblock_count); |
|
|
|
debug_init(" C superblocks: %d x %d, %d total\n", |
|
|
|
s->c_superblock_width, s->c_superblock_height, c_superblock_count); |
|
|
|
debug_init(" total superblocks = %d, U starts @ %d, V starts @ %d\n", |
|
|
|
s->superblock_count, s->u_superblock_start, s->v_superblock_start); |
|
|
|
debug_init(" macroblocks: %d x %d, %d total\n", |
|
|
|
s->macroblock_width, s->macroblock_height, s->macroblock_count); |
|
|
|
debug_init(" %d fragments, %d x %d, u starts @ %d, v starts @ %d\n", |
|
|
@@ -2333,12 +2408,10 @@ static int vp3_decode_frame(AVCodecContext *avctx, |
|
|
|
counter++; |
|
|
|
|
|
|
|
if (s->keyframe) { |
|
|
|
/* release the previous golden frame and get a new one */ |
|
|
|
if (s->golden_frame.data[0]) |
|
|
|
if ((s->golden_frame.data[0]) && |
|
|
|
(s->last_frame.data[0] == s->golden_frame.data[0])) |
|
|
|
avctx->release_buffer(avctx, &s->golden_frame); |
|
|
|
|
|
|
|
/* last frame, if allocated, is hereby invalidated */ |
|
|
|
if (s->last_frame.data[0]) |
|
|
|
else if (s->last_frame.data[0]) |
|
|
|
avctx->release_buffer(avctx, &s->last_frame); |
|
|
|
|
|
|
|
s->golden_frame.reference = 0; |
|
|
@@ -2374,10 +2447,28 @@ static int vp3_decode_frame(AVCodecContext *avctx, |
|
|
|
|
|
|
|
init_frame(s, &gb); |
|
|
|
|
|
|
|
unpack_superblocks(s, &gb); |
|
|
|
unpack_modes(s, &gb); |
|
|
|
unpack_vectors(s, &gb); |
|
|
|
unpack_dct_coeffs(s, &gb); |
|
|
|
#define KEYFRAMES_ONLY 1 |
|
|
|
#if KEYFRAMES_ONLY |
|
|
|
if (!s->keyframe) { |
|
|
|
|
|
|
|
memcpy(s->current_frame.data[0], s->golden_frame.data[0], |
|
|
|
s->current_frame.linesize[0] * s->height); |
|
|
|
memcpy(s->current_frame.data[1], s->golden_frame.data[1], |
|
|
|
s->current_frame.linesize[1] * s->height / 2); |
|
|
|
memcpy(s->current_frame.data[2], s->golden_frame.data[2], |
|
|
|
s->current_frame.linesize[2] * s->height / 2); |
|
|
|
|
|
|
|
} else { |
|
|
|
#endif |
|
|
|
|
|
|
|
if (unpack_superblocks(s, &gb) || |
|
|
|
unpack_modes(s, &gb) || |
|
|
|
unpack_vectors(s, &gb) || |
|
|
|
unpack_dct_coeffs(s, &gb)) { |
|
|
|
|
|
|
|
printf(" vp3: could not decode frame\n"); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
reverse_dc_prediction(s, 0, s->fragment_width, s->fragment_height); |
|
|
|
reverse_dc_prediction(s, s->u_fragment_start, |
|
|
@@ -2389,6 +2480,10 @@ static int vp3_decode_frame(AVCodecContext *avctx, |
|
|
|
render_fragments(s, s->u_fragment_start, s->width / 2, s->height / 2, 1); |
|
|
|
render_fragments(s, s->v_fragment_start, s->width / 2, s->height / 2, 2); |
|
|
|
|
|
|
|
#if KEYFRAMES_ONLY |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
*data_size=sizeof(AVFrame); |
|
|
|
*(AVFrame*)data= s->current_frame; |
|
|
|
|
|
|
@@ -2419,9 +2514,12 @@ static int vp3_decode_end(AVCodecContext *avctx) |
|
|
|
av_free(s->macroblock_coded); |
|
|
|
|
|
|
|
/* release all frames */ |
|
|
|
avctx->release_buffer(avctx, &s->golden_frame); |
|
|
|
avctx->release_buffer(avctx, &s->last_frame); |
|
|
|
avctx->release_buffer(avctx, &s->current_frame); |
|
|
|
if (s->golden_frame.data[0]) |
|
|
|
avctx->release_buffer(avctx, &s->golden_frame); |
|
|
|
if (s->last_frame.data[0]) |
|
|
|
avctx->release_buffer(avctx, &s->last_frame); |
|
|
|
/* no need to release the current_frame since it will always be pointing |
|
|
|
* to the same frame as either the golden or last frame */ |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|