Message ID | 20201110134241.805-1-timo@rothenpieler.org |
---|---|
State | Accepted |
Headers | show |
Series | [FFmpeg-devel,v2,1/4] avcodec/av1dec: expose skip mode frame index | expand |
Context | Check | Description |
---|---|---|
andriy/x86_make | success | Make finished |
andriy/x86_make_fate | success | Make fate finished |
On 11/10/2020 10:42 AM, Timo Rothenpieler wrote: > Signed-off-by: Timo Rothenpieler <timo@rothenpieler.org> > Co-authored-by: James Almer <jamrial@gmail.com> > --- > libavcodec/av1dec.c | 80 +++++++++++++++++++++++++++++++++++++++++++++ > libavcodec/av1dec.h | 3 ++ > 2 files changed, 83 insertions(+) > > diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c > index 56712279aa..1afed66499 100644 > --- a/libavcodec/av1dec.c > +++ b/libavcodec/av1dec.c > @@ -145,6 +145,78 @@ static void global_motion_params(AV1DecContext *s) > } > } > > +static int get_relative_dist(const AV1RawSequenceHeader *seq, > + unsigned int a, unsigned int b) > +{ > + unsigned int diff = a - b; > + unsigned int m = 1 << seq->order_hint_bits_minus_1; > + return (diff & (m - 1)) - (diff & m); > +} > + > +static void skip_mode_params(AV1DecContext *s) > +{ > + const AV1RawFrameHeader *header = s->raw_frame_header; > + const AV1RawSequenceHeader *seq = s->raw_seq; > + > + int forward_idx, backward_idx; > + int forward_hint, backward_hint; > + int second_forward_idx, second_forward_hint; > + int ref_hint, dist, i; > + > + if (!header->skip_mode_present) > + return; Actually, i was partly wrong, AV1Frames are not zero initialized by av1_frame_alloc(), only when the decoder is initialized as part of the AV1DecContext allocation. So if you don't zero them here, you should probably do it in av1_frame_unref(), same as order_hint. > + > + forward_idx = -1; > + backward_idx = -1; > + for (i = 0; i < AV1_REFS_PER_FRAME; i++) { > + ref_hint = s->ref[header->ref_frame_idx[i]].order_hint; > + dist = get_relative_dist(seq, ref_hint, header->order_hint); > + if (dist < 0) { > + if (forward_idx < 0 || > + get_relative_dist(seq, ref_hint, forward_hint) > 0) { > + forward_idx = i; > + forward_hint = ref_hint; > + } > + } else if (dist > 0) { > + if (backward_idx < 0 || > + get_relative_dist(seq, ref_hint, backward_hint) < 0) { > + backward_idx = i; > + backward_hint = ref_hint; > + } > + } > + } > + > + if (forward_idx < 0) { > + return; > + } else if (backward_idx >= 0) { > + s->cur_frame.skip_mode_frame_idx[0] = > + AV1_REF_FRAME_LAST + FFMIN(forward_idx, backward_idx); > + s->cur_frame.skip_mode_frame_idx[1] = > + AV1_REF_FRAME_LAST + FFMAX(forward_idx, backward_idx); > + return; > + } > + > + second_forward_idx = -1; > + for (i = 0; i < AV1_REFS_PER_FRAME; i++) { > + ref_hint = s->ref[header->ref_frame_idx[i]].order_hint; > + if (get_relative_dist(seq, ref_hint, forward_hint) < 0) { > + if (second_forward_idx < 0 || > + get_relative_dist(seq, ref_hint, second_forward_hint) > 0) { > + second_forward_idx = i; > + second_forward_hint = ref_hint; > + } > + } > + } > + > + if (second_forward_idx < 0) > + return; > + > + s->cur_frame.skip_mode_frame_idx[0] = > + AV1_REF_FRAME_LAST + FFMIN(forward_idx, second_forward_idx); > + s->cur_frame.skip_mode_frame_idx[1] = > + AV1_REF_FRAME_LAST + FFMAX(forward_idx, second_forward_idx); > +} > + > static int init_tile_data(AV1DecContext *s) > > { > @@ -318,6 +390,7 @@ static void av1_frame_unref(AVCodecContext *avctx, AV1Frame *f) > av_buffer_unref(&f->hwaccel_priv_buf); > f->hwaccel_picture_private = NULL; > f->spatial_id = f->temporal_id = 0; > + f->order_hint = 0; > } > > static int av1_frame_ref(AVCodecContext *avctx, AV1Frame *dst, const AV1Frame *src) > @@ -343,6 +416,10 @@ static int av1_frame_ref(AVCodecContext *avctx, AV1Frame *dst, const AV1Frame *s > memcpy(dst->gm_params, > src->gm_params, > AV1_NUM_REF_FRAMES * 6 * sizeof(int32_t)); > + dst->order_hint = src->order_hint; > + memcpy(dst->skip_mode_frame_idx, > + src->skip_mode_frame_idx, > + 2 * sizeof(uint8_t)); > > return 0; > > @@ -613,6 +690,7 @@ static int get_current_frame(AVCodecContext *avctx) > } > > global_motion_params(s); > + skip_mode_params(s); > > return ret; > } > @@ -740,6 +818,8 @@ static int av1_decode_frame(AVCodecContext *avctx, void *frame, > s->cur_frame.spatial_id = header->spatial_id; > s->cur_frame.temporal_id = header->temporal_id; > > + s->cur_frame.order_hint = s->raw_frame_header->order_hint; > + > if (avctx->hwaccel) { > ret = avctx->hwaccel->start_frame(avctx, unit->data, > unit->data_size); > diff --git a/libavcodec/av1dec.h b/libavcodec/av1dec.h > index b58bc53961..8cf50f0d59 100644 > --- a/libavcodec/av1dec.h > +++ b/libavcodec/av1dec.h > @@ -41,6 +41,9 @@ typedef struct AV1Frame { > > uint8_t gm_type[AV1_NUM_REF_FRAMES]; > int32_t gm_params[AV1_NUM_REF_FRAMES][6]; > + > + uint8_t order_hint; > + uint8_t skip_mode_frame_idx[2]; > } AV1Frame; > > typedef struct TileGroupInfo { >
On 10.11.2020 15:19, James Almer wrote: > On 11/10/2020 10:42 AM, Timo Rothenpieler wrote: >> Signed-off-by: Timo Rothenpieler <timo@rothenpieler.org> >> Co-authored-by: James Almer <jamrial@gmail.com> >> --- >> libavcodec/av1dec.c | 80 +++++++++++++++++++++++++++++++++++++++++++++ >> libavcodec/av1dec.h | 3 ++ >> 2 files changed, 83 insertions(+) >> >> diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c >> index 56712279aa..1afed66499 100644 >> --- a/libavcodec/av1dec.c >> +++ b/libavcodec/av1dec.c >> @@ -145,6 +145,78 @@ static void global_motion_params(AV1DecContext *s) >> } >> } >> +static int get_relative_dist(const AV1RawSequenceHeader *seq, >> + unsigned int a, unsigned int b) >> +{ >> + unsigned int diff = a - b; >> + unsigned int m = 1 << seq->order_hint_bits_minus_1; >> + return (diff & (m - 1)) - (diff & m); >> +} >> + >> +static void skip_mode_params(AV1DecContext *s) >> +{ >> + const AV1RawFrameHeader *header = s->raw_frame_header; >> + const AV1RawSequenceHeader *seq = s->raw_seq; >> + >> + int forward_idx, backward_idx; >> + int forward_hint, backward_hint; >> + int second_forward_idx, second_forward_hint; >> + int ref_hint, dist, i; >> + >> + if (!header->skip_mode_present) >> + return; > > Actually, i was partly wrong, AV1Frames are not zero initialized by > av1_frame_alloc(), only when the decoder is initialized as part of the > AV1DecContext allocation. So if you don't zero them here, you should > probably do it in av1_frame_unref(), same as order_hint. > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe". Right now they'd just be in an undefined state when !skip_mode_present, which is fine by me, given that the field does not have a meaning in that case anyway. But zeroing the field is probably cleaner. Will add to patch locally
diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c index 56712279aa..1afed66499 100644 --- a/libavcodec/av1dec.c +++ b/libavcodec/av1dec.c @@ -145,6 +145,78 @@ static void global_motion_params(AV1DecContext *s) } } +static int get_relative_dist(const AV1RawSequenceHeader *seq, + unsigned int a, unsigned int b) +{ + unsigned int diff = a - b; + unsigned int m = 1 << seq->order_hint_bits_minus_1; + return (diff & (m - 1)) - (diff & m); +} + +static void skip_mode_params(AV1DecContext *s) +{ + const AV1RawFrameHeader *header = s->raw_frame_header; + const AV1RawSequenceHeader *seq = s->raw_seq; + + int forward_idx, backward_idx; + int forward_hint, backward_hint; + int second_forward_idx, second_forward_hint; + int ref_hint, dist, i; + + if (!header->skip_mode_present) + return; + + forward_idx = -1; + backward_idx = -1; + for (i = 0; i < AV1_REFS_PER_FRAME; i++) { + ref_hint = s->ref[header->ref_frame_idx[i]].order_hint; + dist = get_relative_dist(seq, ref_hint, header->order_hint); + if (dist < 0) { + if (forward_idx < 0 || + get_relative_dist(seq, ref_hint, forward_hint) > 0) { + forward_idx = i; + forward_hint = ref_hint; + } + } else if (dist > 0) { + if (backward_idx < 0 || + get_relative_dist(seq, ref_hint, backward_hint) < 0) { + backward_idx = i; + backward_hint = ref_hint; + } + } + } + + if (forward_idx < 0) { + return; + } else if (backward_idx >= 0) { + s->cur_frame.skip_mode_frame_idx[0] = + AV1_REF_FRAME_LAST + FFMIN(forward_idx, backward_idx); + s->cur_frame.skip_mode_frame_idx[1] = + AV1_REF_FRAME_LAST + FFMAX(forward_idx, backward_idx); + return; + } + + second_forward_idx = -1; + for (i = 0; i < AV1_REFS_PER_FRAME; i++) { + ref_hint = s->ref[header->ref_frame_idx[i]].order_hint; + if (get_relative_dist(seq, ref_hint, forward_hint) < 0) { + if (second_forward_idx < 0 || + get_relative_dist(seq, ref_hint, second_forward_hint) > 0) { + second_forward_idx = i; + second_forward_hint = ref_hint; + } + } + } + + if (second_forward_idx < 0) + return; + + s->cur_frame.skip_mode_frame_idx[0] = + AV1_REF_FRAME_LAST + FFMIN(forward_idx, second_forward_idx); + s->cur_frame.skip_mode_frame_idx[1] = + AV1_REF_FRAME_LAST + FFMAX(forward_idx, second_forward_idx); +} + static int init_tile_data(AV1DecContext *s) { @@ -318,6 +390,7 @@ static void av1_frame_unref(AVCodecContext *avctx, AV1Frame *f) av_buffer_unref(&f->hwaccel_priv_buf); f->hwaccel_picture_private = NULL; f->spatial_id = f->temporal_id = 0; + f->order_hint = 0; } static int av1_frame_ref(AVCodecContext *avctx, AV1Frame *dst, const AV1Frame *src) @@ -343,6 +416,10 @@ static int av1_frame_ref(AVCodecContext *avctx, AV1Frame *dst, const AV1Frame *s memcpy(dst->gm_params, src->gm_params, AV1_NUM_REF_FRAMES * 6 * sizeof(int32_t)); + dst->order_hint = src->order_hint; + memcpy(dst->skip_mode_frame_idx, + src->skip_mode_frame_idx, + 2 * sizeof(uint8_t)); return 0; @@ -613,6 +690,7 @@ static int get_current_frame(AVCodecContext *avctx) } global_motion_params(s); + skip_mode_params(s); return ret; } @@ -740,6 +818,8 @@ static int av1_decode_frame(AVCodecContext *avctx, void *frame, s->cur_frame.spatial_id = header->spatial_id; s->cur_frame.temporal_id = header->temporal_id; + s->cur_frame.order_hint = s->raw_frame_header->order_hint; + if (avctx->hwaccel) { ret = avctx->hwaccel->start_frame(avctx, unit->data, unit->data_size); diff --git a/libavcodec/av1dec.h b/libavcodec/av1dec.h index b58bc53961..8cf50f0d59 100644 --- a/libavcodec/av1dec.h +++ b/libavcodec/av1dec.h @@ -41,6 +41,9 @@ typedef struct AV1Frame { uint8_t gm_type[AV1_NUM_REF_FRAMES]; int32_t gm_params[AV1_NUM_REF_FRAMES][6]; + + uint8_t order_hint; + uint8_t skip_mode_frame_idx[2]; } AV1Frame; typedef struct TileGroupInfo {
Signed-off-by: Timo Rothenpieler <timo@rothenpieler.org> Co-authored-by: James Almer <jamrial@gmail.com> --- libavcodec/av1dec.c | 80 +++++++++++++++++++++++++++++++++++++++++++++ libavcodec/av1dec.h | 3 ++ 2 files changed, 83 insertions(+)