Re: [FFmpeg-devel] [PATCH 1/2] vp9: add support for resolution changes in inter frames.
On Tue, Apr 21, 2015 at 08:54:51PM -0400, Ronald S. Bultje wrote: > --- > libavcodec/vp9.c | 316 > ++- > libavcodec/vp9_mc_template.c | 171 +++ > libavcodec/vp9_parser.c | 5 +- > libavcodec/vp9dsp.c | 205 ++-- > libavcodec/vp9dsp.h | 9 ++ > 5 files changed, 535 insertions(+), 171 deletions(-) > create mode 100644 libavcodec/vp9_mc_template.c applied thanks [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB Republics decline into democracies and democracies degenerate into despotisms. -- Aristotle signature.asc Description: Digital signature ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH 1/2] vp9: add support for resolution changes in inter frames.
Hi, On Tue, Apr 21, 2015 at 11:25 PM, James Almer wrote: > On 22/04/15 12:20 AM, James Almer wrote: > > On 21/04/15 9:54 PM, Ronald S. Bultje wrote: > >> --- > >> libavcodec/vp9.c | 316 > ++- > >> libavcodec/vp9_mc_template.c | 171 +++ > >> libavcodec/vp9_parser.c | 5 +- > >> libavcodec/vp9dsp.c | 205 ++-- > >> libavcodec/vp9dsp.h | 9 ++ > >> 5 files changed, 535 insertions(+), 171 deletions(-) > >> create mode 100644 libavcodec/vp9_mc_template.c > >> > >> diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c > >> index 89257fa..ee73325 100644 > >> --- a/libavcodec/vp9.c > >> +++ b/libavcodec/vp9.c > >> @@ -242,7 +242,7 @@ typedef struct VP9Context { > >> // whole-frame cache > >> uint8_t *intra_pred_data[3]; > >> struct VP9Filter *lflvl; > >> -DECLARE_ALIGNED(32, uint8_t, edge_emu_buffer)[71*80]; > >> +DECLARE_ALIGNED(32, uint8_t, edge_emu_buffer)[135*144]; > >> > >> // block reconstruction intermediates > >> int block_alloc_using_2pass; > >> @@ -251,6 +251,8 @@ typedef struct VP9Context { > >> struct { int x, y; } min_mv, max_mv; > >> DECLARE_ALIGNED(32, uint8_t, tmp_y)[64*64]; > >> DECLARE_ALIGNED(32, uint8_t, tmp_uv)[2][32*32]; > >> +uint16_t mvscale[3][2]; > >> +uint8_t mvstep[3][2]; > >> } VP9Context; > >> > >> static const uint8_t bwh_tab[2][N_BS_SIZES][2] = { > >> @@ -577,6 +579,26 @@ static int decode_frame_header(AVCodecContext *ctx, > >> s->varcompref[1] = 2; > >> } > >> } > >> + > >> +for (i = 0; i < 3; i++) { > >> +AVFrame *ref = s->refs[s->refidx[i]].f; > >> +int refw = ref->width, refh = ref->height; > >> + > >> +if (refw == w && refh == h) { > >> +s->mvscale[i][0] = s->mvscale[i][1] = 0; > >> +} else { > >> +if (w * 2 < refw || h * 2 < refh || w > 16 * refw > || h > 16 * refh) { > >> +av_log(ctx, AV_LOG_ERROR, > >> + "Invalid ref frame dimensions %dx%d for > frame size %dx%d\n", > >> + refw, refh, w, h); > >> +return AVERROR_INVALIDDATA; > >> +} > >> +s->mvscale[i][0] = (refw << 14) / w; > >> +s->mvscale[i][1] = (refh << 14) / h; > >> +s->mvstep[i][0] = 16 * s->mvscale[i][0] >> 14; > >> +s->mvstep[i][1] = 16 * s->mvscale[i][1] >> 14; > >> +} > >> +} > >> } > >> } > >> s->refreshctx = s->errorres ? 0 : get_bits1(&s->gb); > >> @@ -2524,12 +2546,118 @@ static void intra_recon(AVCodecContext *ctx, > ptrdiff_t y_off, ptrdiff_t uv_off) > >> } > >> } > >> > >> -static av_always_inline void mc_luma_dir(VP9Context *s, vp9_mc_func > (*mc)[2], > >> - uint8_t *dst, ptrdiff_t > dst_stride, > >> - const uint8_t *ref, ptrdiff_t > ref_stride, > >> - ThreadFrame *ref_frame, > >> - ptrdiff_t y, ptrdiff_t x, > const VP56mv *mv, > >> - int bw, int bh, int w, int h) > >> +static av_always_inline void mc_luma_scaled(VP9Context *s, > vp9_scaled_mc_func smc, > >> +uint8_t *dst, ptrdiff_t > dst_stride, > >> +const uint8_t *ref, > ptrdiff_t ref_stride, > >> +ThreadFrame *ref_frame, > >> +ptrdiff_t y, ptrdiff_t x, > const VP56mv *mv, > >> +int bw, int bh, int w, int > h, > >> +const uint16_t *scale, > const uint8_t *step) > >> +{ > >> +#define scale_mv(n, dim) (((int64_t)n * scale[dim]) >> 14) > >> +// BUG libvpx seems to scale the two components separately. This > introduces > >> +// rounding errors but we have to reproduce them to be exactly > compatible > >> +// with the output from libvpx... > > > > Did you report it to libvpx? It's probably a better idea to fix the bug > in the reference > > library than purposely reproduce the buggy behavior in our > implementation to remain > > compatible. > > Just checked the link further down the patch (As i should have done before > replying). > Assuming it's the same bug as this one then forget what i said, they > decided to leave > the bitstream unchanged. Yes, sadly, not much can be done here on our end... Ronald ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH 1/2] vp9: add support for resolution changes in inter frames.
On 22/04/15 12:20 AM, James Almer wrote: > On 21/04/15 9:54 PM, Ronald S. Bultje wrote: >> --- >> libavcodec/vp9.c | 316 >> ++- >> libavcodec/vp9_mc_template.c | 171 +++ >> libavcodec/vp9_parser.c | 5 +- >> libavcodec/vp9dsp.c | 205 ++-- >> libavcodec/vp9dsp.h | 9 ++ >> 5 files changed, 535 insertions(+), 171 deletions(-) >> create mode 100644 libavcodec/vp9_mc_template.c >> >> diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c >> index 89257fa..ee73325 100644 >> --- a/libavcodec/vp9.c >> +++ b/libavcodec/vp9.c >> @@ -242,7 +242,7 @@ typedef struct VP9Context { >> // whole-frame cache >> uint8_t *intra_pred_data[3]; >> struct VP9Filter *lflvl; >> -DECLARE_ALIGNED(32, uint8_t, edge_emu_buffer)[71*80]; >> +DECLARE_ALIGNED(32, uint8_t, edge_emu_buffer)[135*144]; >> >> // block reconstruction intermediates >> int block_alloc_using_2pass; >> @@ -251,6 +251,8 @@ typedef struct VP9Context { >> struct { int x, y; } min_mv, max_mv; >> DECLARE_ALIGNED(32, uint8_t, tmp_y)[64*64]; >> DECLARE_ALIGNED(32, uint8_t, tmp_uv)[2][32*32]; >> +uint16_t mvscale[3][2]; >> +uint8_t mvstep[3][2]; >> } VP9Context; >> >> static const uint8_t bwh_tab[2][N_BS_SIZES][2] = { >> @@ -577,6 +579,26 @@ static int decode_frame_header(AVCodecContext *ctx, >> s->varcompref[1] = 2; >> } >> } >> + >> +for (i = 0; i < 3; i++) { >> +AVFrame *ref = s->refs[s->refidx[i]].f; >> +int refw = ref->width, refh = ref->height; >> + >> +if (refw == w && refh == h) { >> +s->mvscale[i][0] = s->mvscale[i][1] = 0; >> +} else { >> +if (w * 2 < refw || h * 2 < refh || w > 16 * refw || h >> > 16 * refh) { >> +av_log(ctx, AV_LOG_ERROR, >> + "Invalid ref frame dimensions %dx%d for >> frame size %dx%d\n", >> + refw, refh, w, h); >> +return AVERROR_INVALIDDATA; >> +} >> +s->mvscale[i][0] = (refw << 14) / w; >> +s->mvscale[i][1] = (refh << 14) / h; >> +s->mvstep[i][0] = 16 * s->mvscale[i][0] >> 14; >> +s->mvstep[i][1] = 16 * s->mvscale[i][1] >> 14; >> +} >> +} >> } >> } >> s->refreshctx = s->errorres ? 0 : get_bits1(&s->gb); >> @@ -2524,12 +2546,118 @@ static void intra_recon(AVCodecContext *ctx, >> ptrdiff_t y_off, ptrdiff_t uv_off) >> } >> } >> >> -static av_always_inline void mc_luma_dir(VP9Context *s, vp9_mc_func >> (*mc)[2], >> - uint8_t *dst, ptrdiff_t dst_stride, >> - const uint8_t *ref, ptrdiff_t >> ref_stride, >> - ThreadFrame *ref_frame, >> - ptrdiff_t y, ptrdiff_t x, const >> VP56mv *mv, >> - int bw, int bh, int w, int h) >> +static av_always_inline void mc_luma_scaled(VP9Context *s, >> vp9_scaled_mc_func smc, >> +uint8_t *dst, ptrdiff_t >> dst_stride, >> +const uint8_t *ref, ptrdiff_t >> ref_stride, >> +ThreadFrame *ref_frame, >> +ptrdiff_t y, ptrdiff_t x, const >> VP56mv *mv, >> +int bw, int bh, int w, int h, >> +const uint16_t *scale, const >> uint8_t *step) >> +{ >> +#define scale_mv(n, dim) (((int64_t)n * scale[dim]) >> 14) >> +// BUG libvpx seems to scale the two components separately. This >> introduces >> +// rounding errors but we have to reproduce them to be exactly >> compatible >> +// with the output from libvpx... > > Did you report it to libvpx? It's probably a better idea to fix the bug in > the reference > library than purposely reproduce the buggy behavior in our implementation to > remain > compatible. Just checked the link further down the patch (As i should have done before replying). Assuming it's the same bug as this one then forget what i said, they decided to leave the bitstream unchanged. ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH 1/2] vp9: add support for resolution changes in inter frames.
On 21/04/15 9:54 PM, Ronald S. Bultje wrote: > --- > libavcodec/vp9.c | 316 > ++- > libavcodec/vp9_mc_template.c | 171 +++ > libavcodec/vp9_parser.c | 5 +- > libavcodec/vp9dsp.c | 205 ++-- > libavcodec/vp9dsp.h | 9 ++ > 5 files changed, 535 insertions(+), 171 deletions(-) > create mode 100644 libavcodec/vp9_mc_template.c > > diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c > index 89257fa..ee73325 100644 > --- a/libavcodec/vp9.c > +++ b/libavcodec/vp9.c > @@ -242,7 +242,7 @@ typedef struct VP9Context { > // whole-frame cache > uint8_t *intra_pred_data[3]; > struct VP9Filter *lflvl; > -DECLARE_ALIGNED(32, uint8_t, edge_emu_buffer)[71*80]; > +DECLARE_ALIGNED(32, uint8_t, edge_emu_buffer)[135*144]; > > // block reconstruction intermediates > int block_alloc_using_2pass; > @@ -251,6 +251,8 @@ typedef struct VP9Context { > struct { int x, y; } min_mv, max_mv; > DECLARE_ALIGNED(32, uint8_t, tmp_y)[64*64]; > DECLARE_ALIGNED(32, uint8_t, tmp_uv)[2][32*32]; > +uint16_t mvscale[3][2]; > +uint8_t mvstep[3][2]; > } VP9Context; > > static const uint8_t bwh_tab[2][N_BS_SIZES][2] = { > @@ -577,6 +579,26 @@ static int decode_frame_header(AVCodecContext *ctx, > s->varcompref[1] = 2; > } > } > + > +for (i = 0; i < 3; i++) { > +AVFrame *ref = s->refs[s->refidx[i]].f; > +int refw = ref->width, refh = ref->height; > + > +if (refw == w && refh == h) { > +s->mvscale[i][0] = s->mvscale[i][1] = 0; > +} else { > +if (w * 2 < refw || h * 2 < refh || w > 16 * refw || h > > 16 * refh) { > +av_log(ctx, AV_LOG_ERROR, > + "Invalid ref frame dimensions %dx%d for frame > size %dx%d\n", > + refw, refh, w, h); > +return AVERROR_INVALIDDATA; > +} > +s->mvscale[i][0] = (refw << 14) / w; > +s->mvscale[i][1] = (refh << 14) / h; > +s->mvstep[i][0] = 16 * s->mvscale[i][0] >> 14; > +s->mvstep[i][1] = 16 * s->mvscale[i][1] >> 14; > +} > +} > } > } > s->refreshctx = s->errorres ? 0 : get_bits1(&s->gb); > @@ -2524,12 +2546,118 @@ static void intra_recon(AVCodecContext *ctx, > ptrdiff_t y_off, ptrdiff_t uv_off) > } > } > > -static av_always_inline void mc_luma_dir(VP9Context *s, vp9_mc_func (*mc)[2], > - uint8_t *dst, ptrdiff_t dst_stride, > - const uint8_t *ref, ptrdiff_t > ref_stride, > - ThreadFrame *ref_frame, > - ptrdiff_t y, ptrdiff_t x, const > VP56mv *mv, > - int bw, int bh, int w, int h) > +static av_always_inline void mc_luma_scaled(VP9Context *s, > vp9_scaled_mc_func smc, > +uint8_t *dst, ptrdiff_t > dst_stride, > +const uint8_t *ref, ptrdiff_t > ref_stride, > +ThreadFrame *ref_frame, > +ptrdiff_t y, ptrdiff_t x, const > VP56mv *mv, > +int bw, int bh, int w, int h, > +const uint16_t *scale, const > uint8_t *step) > +{ > +#define scale_mv(n, dim) (((int64_t)n * scale[dim]) >> 14) > +// BUG libvpx seems to scale the two components separately. This > introduces > +// rounding errors but we have to reproduce them to be exactly compatible > +// with the output from libvpx... Did you report it to libvpx? It's probably a better idea to fix the bug in the reference library than purposely reproduce the buggy behavior in our implementation to remain compatible. ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 1/2] vp9: add support for resolution changes in inter frames.
--- libavcodec/vp9.c | 316 ++- libavcodec/vp9_mc_template.c | 171 +++ libavcodec/vp9_parser.c | 5 +- libavcodec/vp9dsp.c | 205 ++-- libavcodec/vp9dsp.h | 9 ++ 5 files changed, 535 insertions(+), 171 deletions(-) create mode 100644 libavcodec/vp9_mc_template.c diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c index 89257fa..ee73325 100644 --- a/libavcodec/vp9.c +++ b/libavcodec/vp9.c @@ -242,7 +242,7 @@ typedef struct VP9Context { // whole-frame cache uint8_t *intra_pred_data[3]; struct VP9Filter *lflvl; -DECLARE_ALIGNED(32, uint8_t, edge_emu_buffer)[71*80]; +DECLARE_ALIGNED(32, uint8_t, edge_emu_buffer)[135*144]; // block reconstruction intermediates int block_alloc_using_2pass; @@ -251,6 +251,8 @@ typedef struct VP9Context { struct { int x, y; } min_mv, max_mv; DECLARE_ALIGNED(32, uint8_t, tmp_y)[64*64]; DECLARE_ALIGNED(32, uint8_t, tmp_uv)[2][32*32]; +uint16_t mvscale[3][2]; +uint8_t mvstep[3][2]; } VP9Context; static const uint8_t bwh_tab[2][N_BS_SIZES][2] = { @@ -577,6 +579,26 @@ static int decode_frame_header(AVCodecContext *ctx, s->varcompref[1] = 2; } } + +for (i = 0; i < 3; i++) { +AVFrame *ref = s->refs[s->refidx[i]].f; +int refw = ref->width, refh = ref->height; + +if (refw == w && refh == h) { +s->mvscale[i][0] = s->mvscale[i][1] = 0; +} else { +if (w * 2 < refw || h * 2 < refh || w > 16 * refw || h > 16 * refh) { +av_log(ctx, AV_LOG_ERROR, + "Invalid ref frame dimensions %dx%d for frame size %dx%d\n", + refw, refh, w, h); +return AVERROR_INVALIDDATA; +} +s->mvscale[i][0] = (refw << 14) / w; +s->mvscale[i][1] = (refh << 14) / h; +s->mvstep[i][0] = 16 * s->mvscale[i][0] >> 14; +s->mvstep[i][1] = 16 * s->mvscale[i][1] >> 14; +} +} } } s->refreshctx = s->errorres ? 0 : get_bits1(&s->gb); @@ -2524,12 +2546,118 @@ static void intra_recon(AVCodecContext *ctx, ptrdiff_t y_off, ptrdiff_t uv_off) } } -static av_always_inline void mc_luma_dir(VP9Context *s, vp9_mc_func (*mc)[2], - uint8_t *dst, ptrdiff_t dst_stride, - const uint8_t *ref, ptrdiff_t ref_stride, - ThreadFrame *ref_frame, - ptrdiff_t y, ptrdiff_t x, const VP56mv *mv, - int bw, int bh, int w, int h) +static av_always_inline void mc_luma_scaled(VP9Context *s, vp9_scaled_mc_func smc, +uint8_t *dst, ptrdiff_t dst_stride, +const uint8_t *ref, ptrdiff_t ref_stride, +ThreadFrame *ref_frame, +ptrdiff_t y, ptrdiff_t x, const VP56mv *mv, +int bw, int bh, int w, int h, +const uint16_t *scale, const uint8_t *step) +{ +#define scale_mv(n, dim) (((int64_t)n * scale[dim]) >> 14) +// BUG libvpx seems to scale the two components separately. This introduces +// rounding errors but we have to reproduce them to be exactly compatible +// with the output from libvpx... +int mx = scale_mv(mv->x * 2, 0) + scale_mv(x * 16, 0); +int my = scale_mv(mv->y * 2, 1) + scale_mv(y * 16, 1); +int refbw_m1, refbh_m1; +int th; + +y = my >> 4; +x = mx >> 4; +ref += y * ref_stride + x; +mx &= 15; +my &= 15; +refbw_m1 = ((bw - 1) * step[0] + mx) >> 4; +refbh_m1 = ((bh - 1) * step[1] + my) >> 4; +// FIXME bilinear filter only needs 0/1 pixels, not 3/4 +// we use +7 because the last 7 pixels of each sbrow can be changed in +// the longest loopfilter of the next sbrow +th = (y + refbh_m1 + 4 + 7) >> 6; +ff_thread_await_progress(ref_frame, FFMAX(th, 0), 0); +if (x < 3 || y < 3 || x + 4 >= w - refbw_m1 || y + 4 >= h - refbh_m1) { +s->vdsp.emulated_edge_mc(s->edge_emu_buffer, + ref - 3 * ref_stride - 3, + 144, ref_stride, + refbw_m1 + 8, refbh_m1 + 8, + x - 3, y - 3, w, h); +ref = s->edge_emu_buffer + 3 * 144 + 3; +ref_stride = 144; +} +smc(dst, dst_stride, ref, ref_stride, bh, mx, my, step[0], step[1]); +} + +static av_always_inline void mc_chroma_scaled(VP9Context *s, vp9_s