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

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
26322632 encode_mb_internal(s, motion_x, motion_y, 16, 16, 12, 0, 0, CHROMA_444);
26332633 }
26342634
2635−static inline void copy_context_before_encode(MPVEncContext *const d,
2636− const MPVEncContext *const s)
2637−{
2638− int i;
2639−
2640− memcpy(d->c.last_mv, s->c.last_mv, 2*2*2*sizeof(int)); //FIXME is memcpy faster than a loop?
2641−
2642− /* MPEG-1 */
2643− d->c.mb_skip_run = s->c.mb_skip_run;
2644− for(i=0; i<3; i++)
2645− d->c.last_dc[i] = s->c.last_dc[i];
2646−
2647− /* statistics */
2648− d->mv_bits= s->mv_bits;
2649− d->i_tex_bits= s->i_tex_bits;
2650− d->p_tex_bits= s->p_tex_bits;
2651− d->i_count= s->i_count;
2652− d->misc_bits= s->misc_bits;
2653− d->last_bits= 0;
2654−
2655− d->c.mb_skipped = 0;
2656− d->c.qscale = s->c.qscale;
2657− d->dquant= s->dquant;
2658−
2659− d->esc3_level_length= s->esc3_level_length;
2635+typedef struct MBBackup {
2636+ struct {
2637+ int mv[2][4][2];
2638+ int last_mv[2][2][2];
2639+ int mv_type, mv_dir;
2640+ int last_dc[3];
2641+ int mb_intra, mb_skipped, mb_skip_run;
2642+ int qscale;
2643+ int block_last_index[8];
2644+ int interlaced_dct;
2645+ int16_t (*block)[64];
2646+ } c;
2647+ int mv_bits, i_tex_bits, p_tex_bits, i_count, misc_bits, last_bits;
2648+ int dquant;
2649+ int esc3_level_length;
2650+ PutBitContext pb, pb2, tex_pb;
2651+} MBBackup;
2652+
2653+#define COPY_CONTEXT(BEFORE, AFTER, DST_TYPE, SRC_TYPE) \
2654+static inline void BEFORE ##_context_before_encode(DST_TYPE *const d, \
2655+ const SRC_TYPE *const s) \
2656+{ \
2657+ /* FIXME is memcpy faster than a loop? */ \
2658+ memcpy(d->c.last_mv, s->c.last_mv, 2*2*2*sizeof(int)); \
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+ \
2680+static 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; \
26602716 }
26612717
2662−static inline void copy_context_after_encode(MPVEncContext *const d,
2663− const MPVEncContext *const s,
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−}
2718+COPY_CONTEXT(backup, save, MBBackup, MPVEncContext)
2719+COPY_CONTEXT(reset, store, MPVEncContext, MBBackup)
27002720
2701−static void encode_mb_hq(MPVEncContext *const s, MPVEncContext *const backup, MPVEncContext *const best,
2721+static void encode_mb_hq(MPVEncContext *const s, MBBackup *const backup, MBBackup *const best,
27022722 PutBitContext pb[2], PutBitContext pb2[2], PutBitContext tex_pb[2],
27032723 int *dmin, int *next_block, int motion_x, int motion_y)
27042724 {
27052725 int score;
27062726 uint8_t *dest_backup[3];
27072727
2708− copy_context_before_encode(s, backup);
2728+ reset_context_before_encode(s, backup);
27092729
27102730 s->c.block = s->c.blocks[*next_block];
27112731 s->pb = pb[*next_block];
@@ -2745,7 +2765,7 @@ static void encode_mb_hq(MPVEncContext *const s, MPVEncContext *const backup, MP · 33 unmodified lines
27452765 *dmin= score;
27462766 *next_block^=1;
27472767
2748− copy_context_after_encode(best, s, s->c.data_partitioning);
2768+ save_context_after_encode(best, s, s->c.data_partitioning);
27492769 }
27502770 }
27512771
@@ -2963,7 +2983,7 @@ static int encode_thread(AVCodecContext *c, void *arg){ · 211 unmodified lines
29632983 MPVEncContext *const s = *(void**)arg;
29642984 int chr_h = 16 >> s->c.chroma_y_shift;
29652985 int i;
2966− MPVEncContext best_s = { 0 }, backup_s;
2986+ MBBackup best_s = { 0 }, backup_s;
29672987 uint8_t bit_buf[2][MAX_MB_BYTES];
29682988 uint8_t bit_buf2[2][MAX_MB_BYTES];
29692989 uint8_t bit_buf_tex[2][MAX_MB_BYTES];
@@ -3164,7 +3184,7 @@ static int encode_thread(AVCodecContext *c, void *arg){ · 194 unmodified lines
31643184 int next_block=0;
31653185 int pb_bits_count, pb2_bits_count, tex_pb_bits_count;
31663186
3167− copy_context_before_encode(&backup_s, s);
3187+ backup_context_before_encode(&backup_s, s);
31683188 backup_s.pb= s->pb;
31693189 if (s->c.data_partitioning) {
31703190 backup_s.pb2= s->pb2;
@@ -3389,7 +3409,7 @@ static int encode_thread(AVCodecContext *c, void *arg){ · 218 unmodified lines
33893409 }
33903410 }
33913411
3392− copy_context_after_encode(s, &best_s, s->c.data_partitioning);
3412+ store_context_after_encode(s, &best_s, s->c.data_partitioning);
33933413
33943414 pb_bits_count= put_bits_count(&s->pb);
33953415 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