mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-04-24 17:12:34 +02:00
fic: set pict_type/key_frame after (instead of during) slice decoding.
This fixes a race condition that was already documented in the source code, and is also reported by tsan in fate-fic-avi.
This commit is contained in:
parent
9e2050b698
commit
73f863d751
@ -34,6 +34,7 @@ typedef struct FICThreadContext {
|
|||||||
int slice_h;
|
int slice_h;
|
||||||
int src_size;
|
int src_size;
|
||||||
int y_off;
|
int y_off;
|
||||||
|
int p_frame;
|
||||||
} FICThreadContext;
|
} FICThreadContext;
|
||||||
|
|
||||||
typedef struct FICContext {
|
typedef struct FICContext {
|
||||||
@ -133,16 +134,13 @@ static void fic_idct_put(uint8_t *dst, int stride, int16_t *block)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
static int fic_decode_block(FICContext *ctx, GetBitContext *gb,
|
static int fic_decode_block(FICContext *ctx, GetBitContext *gb,
|
||||||
uint8_t *dst, int stride, int16_t *block)
|
uint8_t *dst, int stride, int16_t *block, int *is_p)
|
||||||
{
|
{
|
||||||
int i, num_coeff;
|
int i, num_coeff;
|
||||||
|
|
||||||
/* Is it a skip block? */
|
/* Is it a skip block? */
|
||||||
if (get_bits1(gb)) {
|
if (get_bits1(gb)) {
|
||||||
/* This is a P-frame. */
|
*is_p = 1;
|
||||||
ctx->frame->key_frame = 0;
|
|
||||||
ctx->frame->pict_type = AV_PICTURE_TYPE_P;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,7 +180,8 @@ static int fic_decode_slice(AVCodecContext *avctx, void *tdata)
|
|||||||
for (x = 0; x < (ctx->aligned_width >> !!p); x += 8) {
|
for (x = 0; x < (ctx->aligned_width >> !!p); x += 8) {
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if ((ret = fic_decode_block(ctx, &gb, dst + x, stride, tctx->block)) != 0)
|
if ((ret = fic_decode_block(ctx, &gb, dst + x, stride,
|
||||||
|
tctx->block, &tctx->p_frame)) != 0)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,15 +347,6 @@ static int fic_decode_frame(AVCodecContext *avctx, void *data,
|
|||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Set the frametype to I initially. It will be set to P if the frame
|
|
||||||
* has any dependencies (skip blocks). There will be a race condition
|
|
||||||
* inside the slice decode function to set these, but we do not care.
|
|
||||||
* since they will only ever be set to 0/P.
|
|
||||||
*/
|
|
||||||
ctx->frame->key_frame = 1;
|
|
||||||
ctx->frame->pict_type = AV_PICTURE_TYPE_I;
|
|
||||||
|
|
||||||
/* Allocate slice data. */
|
/* Allocate slice data. */
|
||||||
av_fast_malloc(&ctx->slice_data, &ctx->slice_data_size,
|
av_fast_malloc(&ctx->slice_data, &ctx->slice_data_size,
|
||||||
nslices * sizeof(ctx->slice_data[0]));
|
nslices * sizeof(ctx->slice_data[0]));
|
||||||
@ -398,6 +388,15 @@ static int fic_decode_frame(AVCodecContext *avctx, void *data,
|
|||||||
NULL, nslices, sizeof(ctx->slice_data[0]))) < 0)
|
NULL, nslices, sizeof(ctx->slice_data[0]))) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
ctx->frame->key_frame = 1;
|
||||||
|
ctx->frame->pict_type = AV_PICTURE_TYPE_I;
|
||||||
|
for (slice = 0; slice < nslices; slice++) {
|
||||||
|
if (ctx->slice_data[slice].p_frame) {
|
||||||
|
ctx->frame->key_frame = 0;
|
||||||
|
ctx->frame->pict_type = AV_PICTURE_TYPE_P;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
av_frame_free(&ctx->final_frame);
|
av_frame_free(&ctx->final_frame);
|
||||||
ctx->final_frame = av_frame_clone(ctx->frame);
|
ctx->final_frame = av_frame_clone(ctx->frame);
|
||||||
if (!ctx->final_frame) {
|
if (!ctx->final_frame) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user