History

avcodec/mpegvideo_enc: Don't use unnecessarily much stack

encode_thread() puts two MPVEncContexts (2*6516B here) on the stack and zeroes one of them in order to temporarily store the variables that get changed during encoding a macroblock (when there is more than one candidate type for a macroblock). This is wasteful and therefore this commit adds a small (328B here) structure to store exactly the fields that actually need to be backed up. Then one can extend MPVEncContext without fearing too use up to much stack.

Andreas Rheinhardt committed 1 year ago

Commit 074d8341 parent f8360ed1 file · +89 −69Browse files

Showing the changes to libavcodec (1 of 1 file). Show all

Unified · Split

libavcodec/mpegvideo_enc.c+89−69
@@ -2632,80 +2632,100 @@ static void encode_mb(MPVEncContext *const s, int motion_x, int motion_y) · 2631 unmodified lines
2632 encode_mb_internal(s, motion_x, motion_y, 16, 16, 12, 0, 0, CHROMA_444);2632 encode_mb_internal(s, motion_x, motion_y, 16, 16, 12, 0, 0, CHROMA_444);
2633}2633}
2634 2634
2635static inline void copy_context_before_encode(MPVEncContext *const d,2635typedef struct MBBackup {
2636 const MPVEncContext *const s)2636 struct {
2637{2637 int mv[2][4][2];
2638 int i;2638 int last_mv[2][2][2];
2639 2639 int mv_type, mv_dir;
2640 memcpy(d->c.last_mv, s->c.last_mv, 2*2*2*sizeof(int)); //FIXME is memcpy faster than a loop?2640 int last_dc[3];
2641 2641 int mb_intra, mb_skipped, mb_skip_run;
2642 /* MPEG-1 */2642 int qscale;
2643 d->c.mb_skip_run = s->c.mb_skip_run;2643 int block_last_index[8];
2644 for(i=0; i<3; i++)2644 int interlaced_dct;
2645 d->c.last_dc[i] = s->c.last_dc[i];2645 int16_t (*block)[64];
2646 2646 } c;
2647 /* statistics */2647 int mv_bits, i_tex_bits, p_tex_bits, i_count, misc_bits, last_bits;
2648 d->mv_bits= s->mv_bits;2648 int dquant;
2649 d->i_tex_bits= s->i_tex_bits;2649 int esc3_level_length;
2650 d->p_tex_bits= s->p_tex_bits;2650 PutBitContext pb, pb2, tex_pb;
2651 d->i_count= s->i_count;2651} MBBackup;
2652 d->misc_bits= s->misc_bits;2652
2653 d->last_bits= 0;2653#define COPY_CONTEXT(BEFORE, AFTER, DST_TYPE, SRC_TYPE) \
2654 2654static inline void BEFORE ##_context_before_encode(DST_TYPE *const d, \
2655 d->c.mb_skipped = 0;2655 const SRC_TYPE *const s) \
2656 d->c.qscale = s->c.qscale;2656{ \
2657 d->dquant= s->dquant;2657 /* FIXME is memcpy faster than a loop? */ \
2658 2658 memcpy(d->c.last_mv, s->c.last_mv, 2*2*2*sizeof(int)); \
2659 d->esc3_level_length= s->esc3_level_length;2659 \
2660 /* MPEG-1 */ \
2661 d->c.mb_skip_run = s->c.mb_skip_run; \
2662 for (int i = 0; i < 3; i++) \
2663 d->c.last_dc[i] = s->c.last_dc[i]; \
2664 \
2665 /* statistics */ \
2666 d->mv_bits = s->mv_bits; \
2667 d->i_tex_bits = s->i_tex_bits; \
2668 d->p_tex_bits = s->p_tex_bits; \
2669 d->i_count = s->i_count; \
2670 d->misc_bits = s->misc_bits; \
2671 d->last_bits = 0; \
2672 \
2673 d->c.mb_skipped = 0; \
2674 d->c.qscale = s->c.qscale; \
2675 d->dquant = s->dquant; \
2676 \
2677 d->esc3_level_length = s->esc3_level_length; \
2678} \
2679 \
2680static inline void AFTER ## _context_after_encode(DST_TYPE *const d, \
2681 const SRC_TYPE *const s, \
2682 int data_partitioning) \
2683{ \
2684 /* FIXME is memcpy faster than a loop? */ \
2685 memcpy(d->c.mv, s->c.mv, 2*4*2*sizeof(int)); \
2686 memcpy(d->c.last_mv, s->c.last_mv, 2*2*2*sizeof(int)); \
2687 \
2688 /* MPEG-1 */ \
2689 d->c.mb_skip_run = s->c.mb_skip_run; \
2690 for (int i = 0; i < 3; i++) \
2691 d->c.last_dc[i] = s->c.last_dc[i]; \
2692 \
2693 /* statistics */ \
2694 d->mv_bits = s->mv_bits; \
2695 d->i_tex_bits = s->i_tex_bits; \
2696 d->p_tex_bits = s->p_tex_bits; \
2697 d->i_count = s->i_count; \
2698 d->misc_bits = s->misc_bits; \
2699 \
2700 d->c.mb_intra = s->c.mb_intra; \
2701 d->c.mb_skipped = s->c.mb_skipped; \
2702 d->c.mv_type = s->c.mv_type; \
2703 d->c.mv_dir = s->c.mv_dir; \
2704 d->pb = s->pb; \
2705 if (data_partitioning) { \
2706 d->pb2 = s->pb2; \
2707 d->tex_pb = s->tex_pb; \
2708 } \
2709 d->c.block = s->c.block; \
2710 for (int i = 0; i < 8; i++) \
2711 d->c.block_last_index[i] = s->c.block_last_index[i]; \
2712 d->c.interlaced_dct = s->c.interlaced_dct; \
2713 d->c.qscale = s->c.qscale; \
2714 \
2715 d->esc3_level_length = s->esc3_level_length; \
2660}2716}
2661 2717
2662static inline void copy_context_after_encode(MPVEncContext *const d,2718COPY_CONTEXT(backup, save, MBBackup, MPVEncContext)
2663 const MPVEncContext *const s,2719COPY_CONTEXT(reset, store, MPVEncContext, MBBackup)
2664 int data_partitioning)
2665{
2666 int i;
2667
2668 memcpy(d->c.mv, s->c.mv, 2*4*2*sizeof(int));
2669 memcpy(d->c.last_mv, s->c.last_mv, 2*2*2*sizeof(int)); //FIXME is memcpy faster than a loop?
2670
2671 /* MPEG-1 */
2672 d->c.mb_skip_run = s->c.mb_skip_run;
2673 for(i=0; i<3; i++)
2674 d->c.last_dc[i] = s->c.last_dc[i];
2675
2676 /* statistics */
2677 d->mv_bits= s->mv_bits;
2678 d->i_tex_bits= s->i_tex_bits;
2679 d->p_tex_bits= s->p_tex_bits;
2680 d->i_count= s->i_count;
2681 d->misc_bits= s->misc_bits;
2682
2683 d->c.mb_intra = s->c.mb_intra;
2684 d->c.mb_skipped = s->c.mb_skipped;
2685 d->c.mv_type = s->c.mv_type;
2686 d->c.mv_dir = s->c.mv_dir;
2687 d->pb= s->pb;
2688 if (data_partitioning) {
2689 d->pb2= s->pb2;
2690 d->tex_pb= s->tex_pb;
2691 }
2692 d->c.block = s->c.block;
2693 for(i=0; i<8; i++)
2694 d->c.block_last_index[i] = s->c.block_last_index[i];
2695 d->c.interlaced_dct = s->c.interlaced_dct;
2696 d->c.qscale = s->c.qscale;
2697
2698 d->esc3_level_length= s->esc3_level_length;
2699}
2700 2720
2701static void encode_mb_hq(MPVEncContext *const s, MPVEncContext *const backup, MPVEncContext *const best,2721static void encode_mb_hq(MPVEncContext *const s, MBBackup *const backup, MBBackup *const best,
2702 PutBitContext pb[2], PutBitContext pb2[2], PutBitContext tex_pb[2],2722 PutBitContext pb[2], PutBitContext pb2[2], PutBitContext tex_pb[2],
2703 int *dmin, int *next_block, int motion_x, int motion_y)2723 int *dmin, int *next_block, int motion_x, int motion_y)
2704{2724{
2705 int score;2725 int score;
2706 uint8_t *dest_backup[3];2726 uint8_t *dest_backup[3];
2707 2727
2708 copy_context_before_encode(s, backup);2728 reset_context_before_encode(s, backup);
2709 2729
2710 s->c.block = s->c.blocks[*next_block];2730 s->c.block = s->c.blocks[*next_block];
2711 s->pb = pb[*next_block];2731 s->pb = pb[*next_block];
@@ -2745,7 +2765,7 @@ static void encode_mb_hq(MPVEncContext *const s, MPVEncContext *const backup, MP · 33 unmodified lines
2745 *dmin= score;2765 *dmin= score;
2746 *next_block^=1;2766 *next_block^=1;
2747 2767
2748 copy_context_after_encode(best, s, s->c.data_partitioning);2768 save_context_after_encode(best, s, s->c.data_partitioning);
2749 }2769 }
2750}2770}
2751 2771
@@ -2963,7 +2983,7 @@ static int encode_thread(AVCodecContext *c, void *arg){ · 211 unmodified lines
2963 MPVEncContext *const s = *(void**)arg;2983 MPVEncContext *const s = *(void**)arg;
2964 int chr_h = 16 >> s->c.chroma_y_shift;2984 int chr_h = 16 >> s->c.chroma_y_shift;
2965 int i;2985 int i;
2966 MPVEncContext best_s = { 0 }, backup_s;2986 MBBackup best_s = { 0 }, backup_s;
2967 uint8_t bit_buf[2][MAX_MB_BYTES];2987 uint8_t bit_buf[2][MAX_MB_BYTES];
2968 uint8_t bit_buf2[2][MAX_MB_BYTES];2988 uint8_t bit_buf2[2][MAX_MB_BYTES];
2969 uint8_t bit_buf_tex[2][MAX_MB_BYTES];2989 uint8_t bit_buf_tex[2][MAX_MB_BYTES];
@@ -3164,7 +3184,7 @@ static int encode_thread(AVCodecContext *c, void *arg){ · 194 unmodified lines
3164 int next_block=0;3184 int next_block=0;
3165 int pb_bits_count, pb2_bits_count, tex_pb_bits_count;3185 int pb_bits_count, pb2_bits_count, tex_pb_bits_count;
3166 3186
3167 copy_context_before_encode(&backup_s, s);3187 backup_context_before_encode(&backup_s, s);
3168 backup_s.pb= s->pb;3188 backup_s.pb= s->pb;
3169 if (s->c.data_partitioning) {3189 if (s->c.data_partitioning) {
3170 backup_s.pb2= s->pb2;3190 backup_s.pb2= s->pb2;
@@ -3389,7 +3409,7 @@ static int encode_thread(AVCodecContext *c, void *arg){ · 218 unmodified lines
3389 }3409 }
3390 }3410 }
3391 3411
3392 copy_context_after_encode(s, &best_s, s->c.data_partitioning);3412 store_context_after_encode(s, &best_s, s->c.data_partitioning);
3393 3413
3394 pb_bits_count= put_bits_count(&s->pb);3414 pb_bits_count= put_bits_count(&s->pb);
3395 flush_put_bits(&s->pb);3415 flush_put_bits(&s->pb);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t