[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