Now that every slice (and therefore every thread) uses its own DC array, one can simply set the out-of-slice DC values to its expected values (this is not possible for the decoders due to error resilience).
Unified · Split
| @@ -27,6 +27,7 @@ · 26 unmodified lines | |||
| 27 | const uint8_t (*ff_h263_get_mv_penalty(void))[MAX_DMV*2+1]; | 27 | const uint8_t (*ff_h263_get_mv_penalty(void))[MAX_DMV*2+1]; |
| 28 | 28 | ||
| 29 | void ff_h263_encode_init(MPVMainEncContext *m); | 29 | void ff_h263_encode_init(MPVMainEncContext *m); |
| 30 | void ff_h263_mpeg4_reset_dc(MPVEncContext *s); | ||
| 30 | void ff_h263_encode_gob_header(MPVEncContext *s, int mb_line); | 31 | void ff_h263_encode_gob_header(MPVEncContext *s, int mb_line); |
| 31 | void ff_h263_encode_mba(MPVEncContext *s); | 32 | void ff_h263_encode_mba(MPVEncContext *s); |
| 32 | 33 | ||
| @@ -361,6 +361,22 @@ static int h263_encode_picture_header(MPVMainEncContext *const m) · 360 unmodified lines | |||
| 361 | return 0; | 361 | return 0; |
| 362 | } | 362 | } |
| 363 | 363 | ||
| 364 | void ff_h263_mpeg4_reset_dc(MPVEncContext *s) | ||
| 365 | { | ||
| 366 | int16_t *dc = s->c.dc_val; | ||
| 367 | |||
| 368 | // The "- 1" is for the top-left entry | ||
| 369 | const int l_xy = s->c.block_index[2]; | ||
| 370 | for (int i = l_xy - 2 * s->c.b8_stride - 1; i < l_xy; i += 2) | ||
| 371 | AV_WN32A(dc + i, 1024 << 16 | 1024); | ||
| 372 | |||
| 373 | const int u_xy = s->c.block_index[4]; | ||
| 374 | const int v_xy = s->c.block_index[5]; | ||
| 375 | int16_t *dc2 = dc + v_xy - u_xy; | ||
| 376 | for (int i = u_xy - s->c.mb_stride - 1; i < u_xy; ++i) | ||
| 377 | dc[i] = dc2[i] = 1024; | ||
| 378 | } | ||
| 379 | |||
| 364 | /** | 380 | /** |
| 365 | * Encode a group of blocks header. | 381 | * Encode a group of blocks header. |
| 366 | */ | 382 | */ |
| @@ -606,11 +622,6 @@ static int h263_pred_dc(MPVEncContext *const s, int n, int16_t **dc_val_ptr) · 239 unmodified lines | |||
| 606 | int a = dc_val[-1]; | 622 | int a = dc_val[-1]; |
| 607 | int c = dc_val[-wrap]; | 623 | int c = dc_val[-wrap]; |
| 608 | 624 | ||
| 609 | /* No prediction outside GOB boundary */ | ||
| 610 | if (s->c.first_slice_line && n != 3) { | ||
| 611 | if (n != 2) c = 1024; | ||
| 612 | if (n != 1 && s->c.mb_x == s->c.resync_mb_x) a = 1024; | ||
| 613 | } | ||
| 614 | /* just DC prediction */ | 625 | /* just DC prediction */ |
| 615 | if (a != 1024 && c != 1024) | 626 | if (a != 1024 && c != 1024) |
| 616 | pred_dc = (a + c) >> 1; | 627 | pred_dc = (a + c) >> 1; |
| @@ -145,6 +145,36 @@ static inline void restore_ac_coeffs(MPVEncContext *const s, int16_t block[6][64 · 144 unmodified lines | |||
| 145 | } | 145 | } |
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | /** | ||
| 149 | * Predict the dc. | ||
| 150 | * @param n block index (0-3 are luma, 4-5 are chroma) | ||
| 151 | * @param dir_ptr pointer to an integer where the prediction direction will be stored | ||
| 152 | */ | ||
| 153 | static int mpeg4_pred_dc(MpegEncContext *s, int n, int *dir_ptr) | ||
| 154 | { | ||
| 155 | const int16_t *const dc_val = s->dc_val + s->block_index[n]; | ||
| 156 | const int wrap = s->block_wrap[n]; | ||
| 157 | |||
| 158 | /* B C | ||
| 159 | * A X | ||
| 160 | */ | ||
| 161 | const int a = dc_val[-1]; | ||
| 162 | const int b = dc_val[-1 - wrap]; | ||
| 163 | const int c = dc_val[-wrap]; | ||
| 164 | int pred; | ||
| 165 | |||
| 166 | // There is no need for out-of-slice handling here, as all values are set | ||
| 167 | // appropriately when a new slice is opened. | ||
| 168 | if (abs(a - b) < abs(b - c)) { | ||
| 169 | pred = c; | ||
| 170 | *dir_ptr = 1; /* top */ | ||
| 171 | } else { | ||
| 172 | pred = a; | ||
| 173 | *dir_ptr = 0; /* left */ | ||
| 174 | } | ||
| 175 | return pred; | ||
| 176 | } | ||
| 177 | |||
| 148 | /** | 178 | /** |
| 149 | * Return the optimal value (0 or 1) for the ac_pred element for the given MB in MPEG-4. | 179 | * Return the optimal value (0 or 1) for the ac_pred element for the given MB in MPEG-4. |
| 150 | * This function will also update s->c.block_last_index and s->c.ac_val. | 180 | * This function will also update s->c.block_last_index and s->c.ac_val. |
| @@ -737,7 +767,7 @@ static void mpeg4_encode_mb(MPVEncContext *const s, int16_t block[][64], · 586 unmodified lines | |||
| 737 | int i; | 767 | int i; |
| 738 | 768 | ||
| 739 | for (int i = 0; i < 6; i++) { | 769 | for (int i = 0; i < 6; i++) { |
| 740 | int pred = ff_mpeg4_pred_dc(&s->c, i, &dir[i]); | 770 | int pred = mpeg4_pred_dc(&s->c, i, &dir[i]); |
| 741 | int scale = i < 4 ? s->c.y_dc_scale : s->c.c_dc_scale; | 771 | int scale = i < 4 ? s->c.y_dc_scale : s->c.c_dc_scale; |
| 742 | 772 | ||
| 743 | pred = FASTDIV((pred + (scale >> 1)), scale); | 773 | pred = FASTDIV((pred + (scale >> 1)), scale); |
| @@ -3140,6 +3140,7 @@ static int encode_thread(AVCodecContext *c, void *arg){ · 3139 unmodified lines | |||
| 3140 | if (CONFIG_MPEG4_ENCODER) { | 3140 | if (CONFIG_MPEG4_ENCODER) { |
| 3141 | ff_mpeg4_encode_video_packet_header(s); | 3141 | ff_mpeg4_encode_video_packet_header(s); |
| 3142 | ff_mpeg4_clean_buffers(&s->c); | 3142 | ff_mpeg4_clean_buffers(&s->c); |
| 3143 | ff_h263_mpeg4_reset_dc(s); | ||
| 3143 | } | 3144 | } |
| 3144 | break; | 3145 | break; |
| 3145 | case AV_CODEC_ID_MPEG1VIDEO: | 3146 | case AV_CODEC_ID_MPEG1VIDEO: |
| @@ -3149,8 +3150,13 @@ static int encode_thread(AVCodecContext *c, void *arg){ · 3 unmodified lines | |||
| 3149 | ff_mpeg1_clean_buffers(&s->c); | 3150 | ff_mpeg1_clean_buffers(&s->c); |
| 3150 | } | 3151 | } |
| 3151 | break; | 3152 | break; |
| 3152 | case AV_CODEC_ID_H263: | 3153 | #if CONFIG_H263P_ENCODER |
| 3153 | case AV_CODEC_ID_H263P: | 3154 | case AV_CODEC_ID_H263P: |
| 3155 | if (s->c.dc_val) | ||
| 3156 | ff_h263_mpeg4_reset_dc(s); | ||
| 3157 | // fallthrough | ||
| 3158 | #endif | ||
| 3159 | case AV_CODEC_ID_H263: | ||
| 3154 | if (CONFIG_H263_ENCODER) { | 3160 | if (CONFIG_H263_ENCODER) { |
| 3155 | update_mb_info(s, 1); | 3161 | update_mb_info(s, 1); |
| 3156 | ff_h263_encode_gob_header(s, mb_y); | 3162 | ff_h263_encode_gob_header(s, mb_y); |