On 2013-02-14 08:38:12 +0100, Anton Khirnov wrote:
> ---
> Now with each thread properly having its own reference. More resistant to
> corrupted files and less ugly.
> ---
> libavcodec/mimic.c | 94
> ++++++++++++++++++++++++++++++++++++----------------
> 1 file changed, 66 insertions(+), 28 deletions(-)
>
> diff --git a/libavcodec/mimic.c b/libavcodec/mimic.c
> index 8ab1c9e..f2fad1d 100644
> --- a/libavcodec/mimic.c
> +++ b/libavcodec/mimic.c
> @@ -44,7 +44,7 @@ typedef struct {
> int cur_index;
> int prev_index;
>
> - AVFrame buf_ptrs [16];
> + ThreadFrame frames [16];
> AVPicture flipped_ptrs[16];
>
> DECLARE_ALIGNED(16, int16_t, dct_block)[64];
> @@ -109,10 +109,31 @@ static const uint8_t col_zag[64] = {
> 53, 60, 61, 54, 47, 55, 62, 63,
> };
>
> +static av_cold int mimic_decode_end(AVCodecContext *avctx)
> +{
> + MimicContext *ctx = avctx->priv_data;
> + int i;
> +
> + av_free(ctx->swap_buf);
> +
> + for (i = 0; i < FF_ARRAY_ELEMS(ctx->frames); i++) {
> + if (ctx->frames[i].f)
> + ff_thread_release_buffer(avctx, &ctx->frames[i]);
> + av_frame_free(&ctx->frames[i].f);
> + }
> +
> + if (!avctx->internal->is_copy)
> + ff_free_vlc(&ctx->vlc);
> +
> + return 0;
> +}
> +
> static av_cold int mimic_decode_init(AVCodecContext *avctx)
> {
> MimicContext *ctx = avctx->priv_data;
> - int ret;
> + int ret, i;
> +
> + avctx->internal->allocate_progress = 1;
>
> ctx->prev_index = 0;
> ctx->cur_index = 15;
> @@ -125,12 +146,21 @@ static av_cold int mimic_decode_init(AVCodecContext
> *avctx)
> ff_dsputil_init(&ctx->dsp, avctx);
> ff_init_scantable(ctx->dsp.idct_permutation, &ctx->scantable, col_zag);
>
> + for (i = 0; i < FF_ARRAY_ELEMS(ctx->frames); i++) {
> + ctx->frames[i].f = av_frame_alloc();
> + if (!ctx->frames[i].f) {
> + mimic_decode_end(avctx);
> + return AVERROR(ENOMEM);
> + }
> + }
> +
> return 0;
> }
>
> static int mimic_decode_update_thread_context(AVCodecContext *avctx, const
> AVCodecContext *avctx_from)
> {
> MimicContext *dst = avctx->priv_data, *src = avctx_from->priv_data;
> + int i, ret;
>
> if (avctx == avctx_from)
> return 0;
> @@ -138,10 +168,16 @@ static int
> mimic_decode_update_thread_context(AVCodecContext *avctx, const AVCod
> dst->cur_index = src->next_cur_index;
> dst->prev_index = src->next_prev_index;
>
> - memcpy(dst->buf_ptrs, src->buf_ptrs, sizeof(src->buf_ptrs));
> memcpy(dst->flipped_ptrs, src->flipped_ptrs, sizeof(src->flipped_ptrs));
>
> - memset(&dst->buf_ptrs[dst->cur_index], 0, sizeof(AVFrame));
> + for (i = 0; i < FF_ARRAY_ELEMS(dst->frames); i++) {
> + ff_thread_release_buffer(avctx, &dst->frames[i]);
> + if (src->frames[i].f->data[0]) {
> + ret = ff_thread_ref_frame(&dst->frames[i], &src->frames[i]);
> + if (ret < 0)
> + return ret;
> + }
> + }
>
> return 0;
> }
> @@ -264,7 +300,7 @@ static int decode(MimicContext *ctx, int quality, int
> num_coeffs,
> uint8_t *p =
> ctx->flipped_ptrs[index].data[0];
>
> if (index != ctx->cur_index && p) {
> - ff_thread_await_progress(&ctx->buf_ptrs[index],
> + ff_thread_await_progress(&ctx->frames[index],
> cur_row, 0);
> p += src -
>
> ctx->flipped_ptrs[ctx->prev_index].data[plane];
> @@ -275,7 +311,7 @@ static int decode(MimicContext *ctx, int quality, int
> num_coeffs,
> }
> }
> } else {
> - ff_thread_await_progress(&ctx->buf_ptrs[ctx->prev_index],
> + ff_thread_await_progress(&ctx->frames[ctx->prev_index],
> cur_row, 0);
> ctx->dsp.put_pixels_tab[1][0](dst, src, stride, 8);
> }
> @@ -285,7 +321,7 @@ static int decode(MimicContext *ctx, int quality, int
> num_coeffs,
> src += (stride - ctx->num_hblocks[plane]) << 3;
> dst += (stride - ctx->num_hblocks[plane]) << 3;
>
> - ff_thread_report_progress(&ctx->buf_ptrs[ctx->cur_index],
> + ff_thread_report_progress(&ctx->frames[ctx->cur_index],
> cur_row++, 0);
> }
> }
> @@ -357,15 +393,16 @@ static int mimic_decode_frame(AVCodecContext *avctx,
> void *data,
> return AVERROR_PATCHWELCOME;
> }
>
> - if (is_pframe && !ctx->buf_ptrs[ctx->prev_index].data[0]) {
> + if (is_pframe && !ctx->frames[ctx->prev_index].f->data[0]) {
> av_log(avctx, AV_LOG_ERROR, "decoding must start with keyframe\n");
> return AVERROR_INVALIDDATA;
> }
>
> - ctx->buf_ptrs[ctx->cur_index].reference = 1;
> - ctx->buf_ptrs[ctx->cur_index].pict_type = is_pframe ? AV_PICTURE_TYPE_P :
> - AV_PICTURE_TYPE_I;
> - if ((res = ff_thread_get_buffer(avctx, &ctx->buf_ptrs[ctx->cur_index]))
> < 0) {
> + ff_thread_release_buffer(avctx, &ctx->frames[ctx->cur_index]);
> + ctx->frames[ctx->cur_index].f->pict_type = is_pframe ? AV_PICTURE_TYPE_P
> :
> + AV_PICTURE_TYPE_I;
> + if ((res = ff_thread_get_buffer(avctx, &ctx->frames[ctx->cur_index],
> + AV_GET_BUFFER_FLAG_REF)) < 0) {
> av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
> return res;
> }
> @@ -374,7 +411,7 @@ static int mimic_decode_frame(AVCodecContext *avctx, void
> *data,
> ctx->next_cur_index = (ctx->cur_index - 1) & 15;
>
> prepare_avpic(ctx, &ctx->flipped_ptrs[ctx->cur_index],
> - &ctx->buf_ptrs[ctx->cur_index]);
> + ctx->frames[ctx->cur_index].f);
>
> ff_thread_finish_setup(avctx);
>
> @@ -388,41 +425,41 @@ static int mimic_decode_frame(AVCodecContext *avctx,
> void *data,
> init_get_bits(&ctx->gb, ctx->swap_buf, swap_buf_size << 3);
>
> res = decode(ctx, quality, num_coeffs, !is_pframe);
> - ff_thread_report_progress(&ctx->buf_ptrs[ctx->cur_index], INT_MAX, 0);
> + ff_thread_report_progress(&ctx->frames[ctx->cur_index], INT_MAX, 0);
> if (res < 0) {
> if (!(avctx->active_thread_type & FF_THREAD_FRAME)) {
> - ff_thread_release_buffer(avctx, &ctx->buf_ptrs[ctx->cur_index]);
> + ff_thread_release_buffer(avctx, &ctx->frames[ctx->cur_index]);
> return res;
> }
> }
>
> - *(AVFrame*)data = ctx->buf_ptrs[ctx->cur_index];
> + if ((res = av_frame_ref(data, ctx->frames[ctx->cur_index].f)) < 0)
> + return res;
> *got_frame = 1;
>
> ctx->prev_index = ctx->next_prev_index;
> ctx->cur_index = ctx->next_cur_index;
>
> /* Only release frames that aren't used for backreferences anymore */
> - if (ctx->buf_ptrs[ctx->cur_index].data[0])
> - ff_thread_release_buffer(avctx, &ctx->buf_ptrs[ctx->cur_index]);
> + ff_thread_release_buffer(avctx, &ctx->frames[ctx->cur_index]);
>
> return buf_size;
> }
>
> -static av_cold int mimic_decode_end(AVCodecContext *avctx)
> +static av_cold int mimic_init_thread_copy(AVCodecContext *avctx)
> {
> MimicContext *ctx = avctx->priv_data;
> int i;
>
> - av_free(ctx->swap_buf);
> -
> - if (avctx->internal->is_copy)
> - return 0;
> + avctx->internal->allocate_progress = 1;
>
> - for (i = 0; i < 16; i++)
> - if (ctx->buf_ptrs[i].data[0])
> - ff_thread_release_buffer(avctx, &ctx->buf_ptrs[i]);
> - ff_free_vlc(&ctx->vlc);
> + for (i = 0; i < FF_ARRAY_ELEMS(ctx->frames); i++) {
> + ctx->frames[i].f = av_frame_alloc();
> + if (!ctx->frames[i].f) {
> + mimic_decode_end(avctx);
> + return AVERROR(ENOMEM);
> + }
> + }
>
> return 0;
> }
> @@ -437,5 +474,6 @@ AVCodec ff_mimic_decoder = {
> .decode = mimic_decode_frame,
> .capabilities = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS,
> .long_name = NULL_IF_CONFIG_SMALL("Mimic"),
> - .update_thread_context =
> ONLY_IF_THREADS_ENABLED(mimic_decode_update_thread_context)
> + .update_thread_context =
> ONLY_IF_THREADS_ENABLED(mimic_decode_update_thread_context),
> + .init_thread_copy = ONLY_IF_THREADS_ENABLED(mimic_init_thread_copy),
> };
looks ok
Janne
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel