[FFmpeg-devel] [PATCH] mpeg4video: Add Studio DPCM support

Michael Niedermayer michael at niedermayer.cc
Thu Aug 23 14:11:31 EEST 2018


On Wed, Aug 22, 2018 at 12:29:57AM +0100, Kieran Kunhya wrote:
> $subj
> 
> Depends on Michael's patch.
> I have a FATE sample frame.

>  mpeg4videodec.c |  101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
>  mpegvideo.c     |   75 ++++++++++++++++++++++++++++++++---------
>  mpegvideo.h     |    2 +
>  3 files changed, 158 insertions(+), 20 deletions(-)
> 530459506bce209c83f6e3d477c2bbf77cd5d072  0001-mpeg4video-Add-Studio-DPCM-support.patch
> From 909fba9afc7edc94a8fd043899ff44c022a32d17 Mon Sep 17 00:00:00 2001
> From: Kieran Kunhya <kieran at kunhya.com>
> Date: Sun, 19 Aug 2018 02:31:42 +0100
> Subject: [PATCH] mpeg4video: Add Studio DPCM support
> 
> ---
>  libavcodec/mpeg4videodec.c | 101 +++++++++++++++++++++++++++++++++++++++++++--
>  libavcodec/mpegvideo.c     |  75 +++++++++++++++++++++++++--------
>  libavcodec/mpegvideo.h     |   2 +
>  3 files changed, 158 insertions(+), 20 deletions(-)
> 
> diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c
> index 1686ed1001..dda462c2ea 100644
> --- a/libavcodec/mpeg4videodec.c
> +++ b/libavcodec/mpeg4videodec.c
> @@ -24,6 +24,7 @@
>  
>  #include "libavutil/internal.h"
>  #include "libavutil/opt.h"
> +#include "libavutil/pixdesc.h"
>  #include "error_resilience.h"
>  #include "hwaccel.h"
>  #include "idctdsp.h"
> @@ -36,6 +37,7 @@
>  #include "profiles.h"
>  #include "thread.h"
>  #include "xvididct.h"
> +#include "unary.h"
>  
>  /* The defines below define the number of bits that are read at once for
>   * reading vlc values. Changing these may improve speed and data cache needs
> @@ -1923,10 +1925,101 @@ static int mpeg4_decode_studio_block(MpegEncContext *s, int32_t block[64], int n
>      return 0;
>  }
>  
> +static int mpeg4_decode_dpcm_macroblock(MpegEncContext *s, int16_t macroblock[256], int n)
> +{
> +    int i, j, w, h, idx = 0;
> +    int block_mean, rice_parameter, rice_prefix_code, rice_suffix_code;
> +    int dpcm_residual, a, b, c, p, p2;

> +    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(s->avctx->pix_fmt);
> +    h = 16 >> (n ? desc->log2_chroma_h : 0);
> +    w = 16 >> (n ? desc->log2_chroma_w : 0);

you can use chroma_x_shift, chroma_y_shift from the context, theres no
need to obtain a AVPixFmtDescriptor


> +
> +    block_mean = get_bits(&s->gb, s->avctx->bits_per_raw_sample);
> +    if (block_mean == 0){
> +        av_log(s->avctx, AV_LOG_ERROR, "Forbidden block_mean\n");
> +        return AVERROR_INVALIDDATA;
> +    }
> +    s->last_dc[n] = block_mean * (1 << (s->dct_precision + s->intra_dc_precision));
> +
> +    rice_parameter = get_bits(&s->gb, 4);
> +    if (rice_parameter == 0) {
> +        av_log(s->avctx, AV_LOG_ERROR, "Forbidden rice_parameter\n");
> +        return AVERROR_INVALIDDATA;
> +    }
> +
> +    if (rice_parameter == 15)
> +        rice_parameter = 0;
> +
> +    if (rice_parameter > 11) {
> +        av_log(s->avctx, AV_LOG_ERROR, "Forbidden rice_parameter\n");
> +        return AVERROR_INVALIDDATA;
> +    }
> +
> +    for (i = 0; i < h; i++) {
> +        for (j = 0; j < w; j++) {

> +            rice_prefix_code = get_unary(&s->gb, 1, 12);
> +
> +            /* Escape */
> +            if (rice_prefix_code == 11)
> +                dpcm_residual = get_bits(&s->gb, s->avctx->bits_per_raw_sample);
> +            else {
> +                rice_suffix_code = get_bitsz(&s->gb, rice_parameter);
> +                dpcm_residual = (rice_prefix_code << rice_parameter) + rice_suffix_code;
> +            }
> +
> +            /* Map to a signed residual */
> +            if (dpcm_residual & 1)
> +                dpcm_residual = (-1 * dpcm_residual) >> 1;
> +            else
> +                dpcm_residual = (dpcm_residual >> 1);

This could be optimized, not sure how common DPCM blocks are so maybe this
doesnt matter


> +
> +            /* Calculate predictors
> +               a = left
> +               b = top
> +               c = top left
> +             */

> +            if (j == 0)
> +                a = 1 << (s->avctx->bits_per_raw_sample - 1);
> +            else
> +                a = macroblock[idx-1];

you can move this out of the loop and just update "a" at the end of the loop, as
its the previous value


> +
> +            if (i == 0)
> +                b = 1 << (s->avctx->bits_per_raw_sample - 1);
> +            else
> +                b = macroblock[idx-w];
> +

> +            if ((j == 0) || (i == 0))
> +                c = 1 << (s->avctx->bits_per_raw_sample - 1);
> +            else
> +                c = macroblock[idx-w-1];

this too can be avoided by simply updating "c" at the end of teh loop and
setting it outside before the loop


> +
> +            p = a + b - c;
> +            if (p < FFMIN(a, b))
> +                p = FFMIN(a, b);
> +
> +            if (p > FFMAX(a, b))
> +                p = FFMAX(a, b);
> +
> +            p2 = (FFMIN3(a, b, c) + FFMAX3(a, b, c)) / 2;

using >> instead of /2 should be faster here
also FFMIN(a, b) and FFMAX(a, b) have already been calculated, they could be
reused to turn 3 argument MIN/MAX to 2 argument variants


[...]
> diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h
> index e16deb64e7..5b316c6adb 100644
> --- a/libavcodec/mpegvideo.h
> +++ b/libavcodec/mpegvideo.h
> @@ -509,6 +509,8 @@ typedef struct MpegEncContext {
>      int (*decode_mb)(struct MpegEncContext *s, int16_t block[12][64]); // used by some codecs to avoid a switch()
>  
>      int32_t (*block32)[12][64];

> +    int block_type;          // 0 = DCT, 1 = DPCM top to bottom scan, 2 = DPCM bottom to top scan

i suggest a "dpcm_direction" instead that uses // 0 = DCT, 1 = DPCM top to bottom scan, -1 = DPCM bottom to top scan
it would be more self explanatory

thx

[...]

-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

You can kill me, but you cannot change the truth.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20180823/019c14f6/attachment.sig>


More information about the ffmpeg-devel mailing list