| @@ -33,6 +33,7 @@ · 32 unmodified lines |
| 33 | 33 | |
| 34 | 34 | #include "config_components.h" |
| 35 | 35 | |
| 36 | +#include <assert.h> |
| 36 | 37 | #include <stdint.h> |
| 37 | 38 | |
| 38 | 39 | #include "libavutil/emms.h" |
| @@ -420,6 +421,53 @@ static av_cold int init_matrices(MPVMainEncContext *const m, AVCodecContext *avc · 381 unmodified lines |
| 420 | 421 | return 0; |
| 421 | 422 | } |
| 422 | 423 | |
| 424 | +static av_cold int init_buffers(MPVMainEncContext *const m, AVCodecContext *avctx) |
| 425 | +{ |
| 426 | + MpegEncContext *const s = &m->s; |
| 427 | + // Align the following per-thread buffers to avoid false sharing. |
| 428 | + enum { |
| 429 | +#ifndef _MSC_VER |
| 430 | + /// The number is supposed to match/exceed the cache-line size. |
| 431 | + ALIGN = FFMAX(128, _Alignof(max_align_t)), |
| 432 | +#else |
| 433 | + ALIGN = 128, |
| 434 | +#endif |
| 435 | + ME_MAP_ALLOC_SIZE = FFALIGN(2 * ME_MAP_SIZE * sizeof(*s->me.map), ALIGN), |
| 436 | + DCT_ERROR_SIZE = FFALIGN(2 * sizeof(*s->dct_error_sum), ALIGN), |
| 437 | + }; |
| 438 | + static_assert(FFMAX(ME_MAP_ALLOC_SIZE, DCT_ERROR_SIZE) * MAX_THREADS + ALIGN - 1 <= SIZE_MAX, |
| 439 | + "Need checks for potential overflow."); |
| 440 | + unsigned nb_slices = s->slice_context_count; |
| 441 | + char *dct_error = NULL, *me_map; |
| 442 | + |
| 443 | + if (s->noise_reduction) { |
| 444 | + dct_error = av_mallocz(ALIGN - 1 + nb_slices * DCT_ERROR_SIZE); |
| 445 | + if (!dct_error) |
| 446 | + return AVERROR(ENOMEM); |
| 447 | + m->dct_error_sum_base = dct_error; |
| 448 | + dct_error += FFALIGN((uintptr_t)dct_error, ALIGN) - (uintptr_t)dct_error; |
| 449 | + } |
| 450 | + me_map = av_mallocz(ALIGN - 1 + nb_slices * ME_MAP_ALLOC_SIZE); |
| 451 | + if (!me_map) |
| 452 | + return AVERROR(ENOMEM); |
| 453 | + m->me_map_base = me_map; |
| 454 | + me_map += FFALIGN((uintptr_t)me_map, ALIGN) - (uintptr_t)me_map; |
| 455 | + |
| 456 | + for (unsigned i = 0; i < nb_slices; ++i) { |
| 457 | + MpegEncContext *const s2 = s->thread_context[i]; |
| 458 | + |
| 459 | + if (dct_error) { |
| 460 | + s2->dct_error_sum = (void*)dct_error; |
| 461 | + dct_error += DCT_ERROR_SIZE; |
| 462 | + } |
| 463 | + s2->me.map = (uint32_t*)me_map; |
| 464 | + s2->me.score_map = s2->me.map + ME_MAP_SIZE; |
| 465 | + me_map += ME_MAP_ALLOC_SIZE; |
| 466 | + } |
| 467 | + |
| 468 | + return 0; |
| 469 | +} |
| 470 | + |
| 423 | 471 | /* init video encoder */ |
| 424 | 472 | av_cold int ff_mpv_encode_init(AVCodecContext *avctx) |
| 425 | 473 | { |
| @@ -923,6 +971,10 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) · 497 unmodified lines |
| 923 | 971 | if (ret < 0) |
| 924 | 972 | return ret; |
| 925 | 973 | |
| 974 | + ret = init_buffers(m, avctx); |
| 975 | + if (ret < 0) |
| 976 | + return ret; |
| 977 | + |
| 926 | 978 | /* Allocate MV tables; the MV and MB tables will be copied |
| 927 | 979 | * to slice contexts by ff_update_duplicate_context(). */ |
| 928 | 980 | mv_table_size = (s->mb_height + 2) * s->mb_stride + 1; |
| @@ -1067,6 +1119,8 @@ av_cold int ff_mpv_encode_end(AVCodecContext *avctx) · 138 unmodified lines |
| 1067 | 1119 | av_freep(&s->b_field_mv_table_base); |
| 1068 | 1120 | av_freep(&s->b_field_select_table[0][0]); |
| 1069 | 1121 | av_freep(&s->p_field_select_table[0]); |
| 1122 | + av_freep(&m->dct_error_sum_base); |
| 1123 | + av_freep(&m->me_map_base); |
| 1070 | 1124 | |
| 1071 | 1125 | av_freep(&s->mb_type); |
| 1072 | 1126 | av_freep(&s->lambda_table); |