[FFmpeg-devel] [PATCH 2/2] avcodec/h264: fix draw_horiz_band with slice threads
James Darnley
jdarnley at obe.tv
Mon Sep 2 17:28:53 EEST 2019
From: Kieran Kunhya <kierank at obe.tv>
---
libavcodec/h264_slice.c | 29 +++++++++++++++++++++++------
1 file changed, 23 insertions(+), 6 deletions(-)
diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
index 5ceee107a0..fe2aa01ceb 100644
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@ -2527,18 +2527,33 @@ static void predict_field_decoding_flag(const H264Context *h, H264SliceContext *
/**
* Draw edges and report progress for the last MB row.
*/
-static void decode_finish_row(const H264Context *h, H264SliceContext *sl)
+static void decode_finish_row(const H264Context *h, H264SliceContext *sl, int slice_end)
{
int top = 16 * (sl->mb_y >> FIELD_PICTURE(h));
int pic_height = 16 * h->mb_height >> FIELD_PICTURE(h);
int height = 16 << FRAME_MBAFF(h);
int deblock_border = (16 + 4) << FRAME_MBAFF(h);
- if (sl->deblocking_filter) {
+ /* Slice-threaded draw_horiz_band not useful in this situation */
+ if (sl->deblocking_filter == 1) {
if ((top + height) >= pic_height)
height += deblock_border;
top -= deblock_border;
}
+ else if (sl->deblocking_filter == 2) {
+ int first_mb_y = sl->first_mb_addr / h->mb_width;
+
+ /* Draw the whole slice if it's possible:
+ * - If the beginning of the slice is at the start of a row
+ * - If we are at the end of the slice
+ * Previous slice is guaranteed not be included. */
+ if (!(sl->first_mb_addr % h->mb_width)) {
+ if (slice_end) {
+ top = 16 * (first_mb_y >> FIELD_PICTURE(h));
+ height = (16 << FRAME_MBAFF(h)) * ((sl->mb_y+1) - first_mb_y);
+ }
+ }
+ }
if (top >= pic_height || (top + height) < 0)
return;
@@ -2549,7 +2564,8 @@ static void decode_finish_row(const H264Context *h, H264SliceContext *sl)
top = 0;
}
- ff_h264_draw_horiz_band(h, sl, top, height);
+ if (slice_end)
+ ff_h264_draw_horiz_band(h, sl, top, height);
if (h->droppable || sl->h264->slice_ctx[0].er.error_occurred)
return;
@@ -2622,7 +2638,7 @@ static int decode_slice(struct AVCodecContext *avctx, void *arg)
for (;;) {
// START_TIMER
- int ret, eos;
+ int ret, eos, slice_end;
if (sl->mb_x + sl->mb_y * h->mb_width >= sl->next_slice_idx) {
av_log(h->avctx, AV_LOG_ERROR, "Slice overlaps with next at %d\n",
sl->next_slice_idx);
@@ -2669,10 +2685,11 @@ static int decode_slice(struct AVCodecContext *avctx, void *arg)
return AVERROR_INVALIDDATA;
}
+ slice_end = eos || sl->mb_y >= h->mb_height;
if (++sl->mb_x >= h->mb_width) {
loop_filter(h, sl, lf_x_start, sl->mb_x);
sl->mb_x = lf_x_start = 0;
- decode_finish_row(h, sl);
+ decode_finish_row(h, sl, slice_end);
++sl->mb_y;
if (FIELD_OR_MBAFF_PICTURE(h)) {
++sl->mb_y;
@@ -2729,7 +2746,7 @@ static int decode_slice(struct AVCodecContext *avctx, void *arg)
if (++sl->mb_x >= h->mb_width) {
loop_filter(h, sl, lf_x_start, sl->mb_x);
sl->mb_x = lf_x_start = 0;
- decode_finish_row(h, sl);
+ decode_finish_row(h, sl, 0);
++sl->mb_y;
if (FIELD_OR_MBAFF_PICTURE(h)) {
++sl->mb_y;
--
2.22.0
More information about the ffmpeg-devel
mailing list