[FFmpeg-devel] [PATCHv4] mpeg4video: Add support for MPEG-4 Simple Studio Profile.

Michael Niedermayer michael at niedermayer.cc
Sat Feb 10 23:06:22 EET 2018


On Sat, Feb 10, 2018 at 03:36:21PM +0000, Kieran Kunhya wrote:
> $subj. Still depends on simple_idct template patch
> 
> Fixes crashes in ER
[...]
> diff --git a/libavcodec/mpeg4video.h b/libavcodec/mpeg4video.h
> index 0ba502d50b..3c9ec4ac42 100644
> --- a/libavcodec/mpeg4video.h
> +++ b/libavcodec/mpeg4video.h
> @@ -61,6 +61,10 @@
>  #define GOP_STARTCODE        0x1B3
>  #define VISUAL_OBJ_STARTCODE 0x1B5
>  #define VOP_STARTCODE        0x1B6
> +#define SLICE_STARTCODE      0x1B7
> +#define EXT_STARTCODE        0x1B8
> +
> +#define QUANT_MATRIX_EXT_ID  0x3
>  
>  /* smaller packets likely don't contain a real frame */
>  #define MAX_NVOP_SIZE 19
> @@ -108,8 +112,16 @@ typedef struct Mpeg4DecContext {
>      int cplx_estimation_trash_i;
>      int cplx_estimation_trash_p;
>      int cplx_estimation_trash_b;
> +
> +    VLC studio_intra_tab[12];
> +    VLC studio_luma_dc;
> +    VLC studio_chroma_dc;
> +
> +    int rgb;
>  } Mpeg4DecContext;
>  
> +static const uint8_t mpeg4_block_count[4] = {0, 6, 8, 12};
> +
>  /* dc encoding for MPEG-4 */
>  extern const uint8_t ff_mpeg4_DCtab_lum[13][2];
>  extern const uint8_t ff_mpeg4_DCtab_chrom[13][2];
> @@ -137,6 +149,10 @@ extern const uint16_t ff_mpeg4_resync_prefix[8];
>  
>  extern const uint8_t ff_mpeg4_dc_threshold[8];
>  
> +extern const uint16_t ff_mpeg4_studio_dc_luma[19][2];
> +extern const uint16_t ff_mpeg4_studio_dc_chroma[19][2];
> +extern const uint16_t ff_mpeg4_studio_intra[12][22][2];
> +
>  void ff_mpeg4_encode_mb(MpegEncContext *s,
>                          int16_t block[6][64],
>                          int motion_x, int motion_y);
> @@ -155,6 +171,7 @@ void ff_clean_mpeg4_qscales(MpegEncContext *s);
>  int ff_mpeg4_decode_partitions(Mpeg4DecContext *ctx);
>  int ff_mpeg4_get_video_packet_prefix_length(MpegEncContext *s);
>  int ff_mpeg4_decode_video_packet_header(Mpeg4DecContext *ctx);
> +int ff_mpeg4_decode_studio_slice_header(Mpeg4DecContext *ctx);
>  void ff_mpeg4_init_direct_mv(MpegEncContext *s);
>  void ff_mpeg4videodec_static_init(void);
>  int ff_mpeg4_workaround_bugs(AVCodecContext *avctx);
> diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c

> index 756753e2fc..d5449ce43d 100644
> --- a/libavcodec/mpeg4videodec.c
> +++ b/libavcodec/mpeg4videodec.c
> @@ -44,6 +44,7 @@
>  #define SPRITE_TRAJ_VLC_BITS 6
>  #define DC_VLC_BITS 9
>  #define MB_TYPE_B_VLC_BITS 4
> +#define STUDIO_INTRA_BITS 9
>  
>  static VLC dc_lum, dc_chrom;
>  static VLC sprite_trajectory;
> @@ -528,6 +529,64 @@ int ff_mpeg4_decode_video_packet_header(Mpeg4DecContext *ctx)
>      return 0;
>  }
>  
> +static inline int get_qscale(MpegEncContext *s)
> +{
> +    int qscale = get_bits(&s->gb, 5);
> +    if (s->q_scale_type)
> +        return ff_mpeg2_non_linear_qscale[qscale];
> +    else
> +        return qscale << 1;
> +}

duplicate of
libavcodec/mpeg12dec.c-static inline int get_qscale(MpegEncContext *s)
libavcodec/mpeg12dec.c-{
libavcodec/mpeg12dec.c-    int qscale = get_bits(&s->gb, 5);
libavcodec/mpeg12dec.c-    if (s->q_scale_type)
libavcodec/mpeg12dec.c:        return ff_mpeg2_non_linear_qscale[qscale];
libavcodec/mpeg12dec.c-    else
libavcodec/mpeg12dec.c-        return qscale << 1;
libavcodec/mpeg12dec.c-}



> +
> +static void reset_studio_dc_predictors(MpegEncContext *s)
> +{
> +    /* Reset DC Predictors */
> +    s->studio_dc_val[0] =
> +    s->studio_dc_val[1] =
> +    s->studio_dc_val[2] = 1 << (s->avctx->bits_per_raw_sample + s->dct_precision + s->intra_dc_precision - 1);
> +}
> +
> +/**
> + * Decode the next video packet.
> + * @return <0 if something went wrong
> + */
> +int ff_mpeg4_decode_studio_slice_header(Mpeg4DecContext *ctx)
> +{
> +    MpegEncContext *s = &ctx->m;
> +    GetBitContext *gb = &s->gb;
> +    unsigned vlc_len;
> +    uint16_t mb_num;
> +
> +    if (get_bits_left(gb) >= 32 && get_bits_long(gb, 32) == SLICE_START_CODE) {

> +        vlc_len = av_log2(((s->width + 15) / 16) * ((s->height + 15) / 16)) + 1;

can possibly be simplified with mb_width * mb_height 


> +        mb_num = get_bits(gb, vlc_len);
> +
> +        if (mb_num >= s->mb_num)
> +            return AVERROR_INVALIDDATA;
> +
> +        s->mb_x = mb_num % s->mb_width;
> +        s->mb_y = mb_num / s->mb_width;
> +
> +        if (ctx->shape != BIN_ONLY_SHAPE)
> +            s->qscale = get_qscale(s);
> +
> +        if (get_bits1(gb)) {  /* slice_extension_flag */
> +            skip_bits1(gb);   /* intra_slice */
> +            skip_bits1(gb);   /* slice_VOP_id_enable */
> +            skip_bits(gb, 6); /* slice_VOP_id */
> +            while (get_bits1(gb)) /* extra_bit_slice */
> +                skip_bits(gb, 8); /* extra_information_slice */
> +        }
> +
> +        reset_studio_dc_predictors(s);
> +    }
> +    else {
> +        return AVERROR_INVALIDDATA;
> +    }
> +
> +    return 0;
> +}
> +
>  /**
>   * Get the average motion vector for a GMC MB.
>   * @param n either 0 for the x component or 1 for y

> @@ -1721,6 +1780,192 @@ end:
>      return SLICE_OK;
>  }
>  
> +static void next_start_code_studio(GetBitContext *gb)
> +{
> +    align_get_bits(gb);
> +
> +    while (get_bits_left(gb) >= 24 && show_bits_long(gb, 24) != 0x1) {
> +        get_bits(gb, 8);
> +    }
> +}

Please use avpriv_find_start_code() or document why that should not be used.
Otherwise i guess it wont take long for someone to replace this by a call
to it or some other optimized existing start code search routine



> +
> +/* additional_code, vlc index */
> +static const uint8_t ac_state_tab[22][2] =
> +{
> +    {0, 0},
> +    {0, 1},
> +    {1, 1},
> +    {2, 1},
> +    {3, 1},
> +    {4, 1},
> +    {5, 1},
> +    {1, 2},
> +    {2, 2},
> +    {3, 2},
> +    {4, 2},
> +    {5, 2},
> +    {6, 2},
> +    {1, 3},
> +    {2, 4},
> +    {3, 5},
> +    {4, 6},
> +    {5, 7},
> +    {6, 8},
> +    {7, 9},
> +    {8, 10},
> +    {0, 11}
> +};
> +
> +static int mpeg4_decode_studio_block(MpegEncContext *s, int32_t block[64], int n)
> +{
> +    Mpeg4DecContext *ctx = s->avctx->priv_data;
> +
> +    int cc, dct_dc_size, dct_diff, code, j, idx = 1, group = 0, run = 0,
> +        additional_code_len, sign, mismatch;
> +    VLC *cur_vlc = &ctx->studio_intra_tab[0];
> +    uint8_t *const scantable = s->intra_scantable.permutated;
> +    const uint16_t *quant_matrix;
> +    uint32_t flc;
> +    const int min = -1 *  (1 << (s->avctx->bits_per_raw_sample + 6));
> +    const int max =      ((1 << (s->avctx->bits_per_raw_sample + 6)) - 1);
> +
> +    mismatch = 1;
> +
> +    memset(block, 0, 64 * sizeof(int32_t));
> +
> +    if (n < 4) {
> +        cc = 0;
> +        dct_dc_size = get_vlc2(&s->gb, ctx->studio_luma_dc.table, STUDIO_INTRA_BITS, 2);
> +        quant_matrix = s->intra_matrix;
> +    }
> +    else {
> +        cc = (n & 1) + 1;
> +        if (ctx->rgb)
> +            dct_dc_size = get_vlc2(&s->gb, ctx->studio_luma_dc.table, STUDIO_INTRA_BITS, 2);
> +        else
> +            dct_dc_size = get_vlc2(&s->gb, ctx->studio_chroma_dc.table, STUDIO_INTRA_BITS, 2);
> +        quant_matrix = s->chroma_intra_matrix;
> +    }
> +
> +    if (dct_dc_size < 0) {
> +        av_log(s->avctx, AV_LOG_ERROR, "illegal dct_dc_size vlc\n");
> +        return AVERROR_INVALIDDATA;
> +    }
> +    else if (dct_dc_size == 0) {
> +        dct_diff = 0;
> +    }
> +    else {
> +        dct_diff = get_xbits(&s->gb, dct_dc_size);
> +

> +        if (dct_dc_size > 8)
> +            check_marker(s->avctx, &s->gb, "dct_dc_size > 8");

the failure of check_marker should be propagated to the caller


> +    }
> +
> +    s->studio_dc_val[cc] += dct_diff;
> +
> +    if (s->mpeg_quant)
> +        block[0] = s->studio_dc_val[cc] * (8 >> s->intra_dc_precision);
> +    else
> +        block[0] = s->studio_dc_val[cc] * (8 >> s->intra_dc_precision) * (8 >> s->dct_precision);

This could likely use last_dc[] as other codecs do for this instead of 
introducing a new 3 element last dc array


> +    /* TODO: support mpeg_quant for AC coefficients */
> +
> +    block[0] = av_clip(block[0], min, max);
> +    mismatch ^= block[0];
> +
> +    /* AC Coefficients */
> +    while (1) {
> +        group = get_vlc2(&s->gb, cur_vlc->table, STUDIO_INTRA_BITS, 2);
> +
> +        if (group < 0) {
> +            av_log(s->avctx, AV_LOG_ERROR, "illegal ac coefficient group vlc\n");
> +            return AVERROR_INVALIDDATA;
> +        }
> +
> +        additional_code_len = ac_state_tab[group][0];
> +        cur_vlc = &ctx->studio_intra_tab[ac_state_tab[group][1]];
> +
> +        if (group == 0) {
> +            /* End of Block */
> +            break;
> +        }
> +        else if (group >= 1 && group <= 6) {
> +            /* Zero run length (Table B.47) */
> +            run = 1 << additional_code_len;
> +            if (additional_code_len)
> +                run += get_bits(&s->gb, additional_code_len);
> +            idx += run;
> +            continue;
> +        }
> +        else if (group >= 7 && group <= 12) {
> +            /* Zero run length and +/-1 level (Table B.48) */
> +            code = get_bits(&s->gb, additional_code_len);
> +            sign = code & 1;
> +            code >>= 1;
> +            run = (1 << (additional_code_len - 1)) + code;
> +            idx += run;
> +            j = scantable[idx++];
> +            block[j] = sign ? 1 : -1;
> +        }
> +        else if (group >= 13 && group <= 20) {
> +            /* Level value (Table B.49) */
> +            j = scantable[idx++];
> +            block[j] = get_xbits(&s->gb, additional_code_len);
> +        }
> +        else if (group == 21) {
> +            /* Escape */
> +            j = scantable[idx++];
> +            additional_code_len = s->avctx->bits_per_raw_sample + s->dct_precision + 4;
> +            flc = get_bits(&s->gb, additional_code_len);
> +            if (flc >> (additional_code_len-1))
> +                block[j] = -1 * (( flc ^ ((1 << additional_code_len) -1)) + 1);
> +            else
> +                block[j] = flc;
> +        }
> +        block[j] = ((8 * 2 * block[j] * quant_matrix[j] * s->qscale) >> s->dct_precision) / 32;
> +        block[j] = av_clip(block[j], min, max);
> +        mismatch ^= block[j];
> +    }
> +
> +    block[63] ^= mismatch & 1;
> +
> +    return 0;
> +}
> +

> +static int mpeg4_decode_studio_mb(MpegEncContext *s, int16_t block_[12][64])
> +{
> +    int i;
> +
> +    /* StudioMacroblock */
> +    /* Assumes I-VOP */

> +    s->mb_intra = 1;

This can probably be set outside the mb loop


> +    if (get_bits1(&s->gb)) { /* compression_mode */
> +        /* DCT */
> +        /* macroblock_type, 1 or 2-bit VLC */
> +        if (!get_bits1(&s->gb)) {
> +            skip_bits1(&s->gb);
> +            s->qscale = get_qscale(s);
> +        }
> +

> +        for (i = 0; i < mpeg4_block_count[s->chroma_format]; i++) {
> +            if (mpeg4_decode_studio_block(s, (*s->block32)[i], i) < 0)
> +                return AVERROR_INVALIDDATA;

the exact error code should be propagated unless it is intentional
that every potential future error is replaced. And its probably better
to document this as someone will otherwise change it


> +        }
> +    } else {
> +        /* DPCM */
> +        check_marker(s->avctx, &s->gb, "DPCM block start");
> +        avpriv_request_sample(s->avctx, "DPCM encoded block");
> +        next_start_code_studio(&s->gb);
> +        return SLICE_ERROR;
> +    }
> +
> +    if (get_bits_left(&s->gb) >= 24 && show_bits(&s->gb, 23) == 0) {
> +        next_start_code_studio(&s->gb);
> +        return SLICE_END;
> +    }
> +
> +    return SLICE_OK;
> +}
> +
>  static int mpeg4_decode_gop_header(MpegEncContext *s, GetBitContext *gb)
>  {
>      int hours, minutes, seconds;
> @@ -2606,6 +2851,238 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb)
>      return 0;
>  }
>  
> +static void read_quant_matrix_ext(MpegEncContext *s, GetBitContext *gb)
> +{
> +    int i, j, v;
> +
> +    if (get_bits1(gb)) {
> +        /* intra_quantiser_matrix */
> +        for (i = 0; i < 64; i++) {
> +            v = get_bits(gb, 8);
> +            j = s->idsp.idct_permutation[ff_zigzag_direct[i]];
> +            s->intra_matrix[j]        = v;
> +            s->chroma_intra_matrix[j] = v;
> +        }
> +    }
> +
> +    if (get_bits1(gb)) {
> +        /* non_intra_quantiser_matrix */
> +        for (i = 0; i < 64; i++) {
> +            get_bits(gb, 8);
> +        }
> +    }
> +
> +    if (get_bits1(gb)) {
> +        /* chroma_intra_quantiser_matrix */
> +        for (i = 0; i < 64; i++) {
> +            v = get_bits(gb, 8);
> +            j = s->idsp.idct_permutation[ff_zigzag_direct[i]];
> +            s->chroma_intra_matrix[j] = v;
> +        }
> +    }
> +
> +    if (get_bits1(gb)) {
> +        /* chroma_non_intra_quantiser_matrix */
> +        for (i = 0; i < 64; i++) {
> +            get_bits(gb, 8);
> +        }
> +    }
> +
> +    next_start_code_studio(gb);
> +}
> +
> +static void extension_and_user_data(MpegEncContext *s, GetBitContext *gb, int id)
> +{
> +    uint32_t startcode;
> +    uint8_t extension_type;
> +
> +    startcode = show_bits_long(gb, 32);
> +    if (startcode == USER_DATA_STARTCODE || startcode == EXT_STARTCODE) {
> +
> +        if ((id == 2 || id == 4) && startcode == EXT_STARTCODE) {
> +            skip_bits_long(gb, 32);
> +            extension_type = get_bits(gb, 4);
> +            if (extension_type == QUANT_MATRIX_EXT_ID)
> +                read_quant_matrix_ext(s, gb);
> +        }
> +    }
> +}
> +
> +static void decode_smpte_tc(Mpeg4DecContext *ctx, GetBitContext *gb)
> +{
> +    MpegEncContext *s = &ctx->m;
> +
> +    skip_bits(gb, 16); /* Time_code[63..48] */
> +    check_marker(s->avctx, gb, "after Time_code[63..48]");
> +    skip_bits(gb, 16); /* Time_code[47..32] */
> +    check_marker(s->avctx, gb, "after Time_code[47..32]");
> +    skip_bits(gb, 16); /* Time_code[31..16] */
> +    check_marker(s->avctx, gb, "after Time_code[31..16]");
> +    skip_bits(gb, 16); /* Time_code[15..0] */
> +    check_marker(s->avctx, gb, "after Time_code[15..0]");
> +    skip_bits(gb, 4); /* reserved_bits */
> +}
> +

> +/**
> + * Decode the next studio vop header.
> + * @return <0 if something went wrong
> + */
> +static int decode_studio_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb)
> +{
> +    MpegEncContext *s = &ctx->m;
> +    int i, v;
> +
> +    if (get_bits_left(gb) <= 32)
> +        return 0;
> +
> +    if (get_bits_long(gb, 32) != VOP_STARTCODE)
> +        return -1;

please use AVERROR codes for for error returns


> +
> +    s->decode_mb = mpeg4_decode_studio_mb;
> +
> +    decode_smpte_tc(ctx, gb);
> +
> +    skip_bits(gb, 10); /* temporal_reference */
> +    skip_bits(gb, 2); /* vop_structure */
> +    s->pict_type = get_bits(gb, 2) + AV_PICTURE_TYPE_I; /* vop_coding_type */
> +    if (get_bits1(gb)) { /* vop_coded */
> +        skip_bits1(gb); /* top_field_first */
> +        skip_bits1(gb); /* repeat_first_field */
> +        s->progressive_frame = get_bits1(gb) ^ 1; /* progressive_frame */
> +    }
> +
> +    if (s->pict_type == AV_PICTURE_TYPE_I) {
> +        if (get_bits1(gb))
> +            reset_studio_dc_predictors(s);
> +    }
> +
> +    if (ctx->shape != BIN_ONLY_SHAPE) {
> +        s->alternate_scan = get_bits1(gb);
> +        s->frame_pred_frame_dct = get_bits1(gb);
> +        s->dct_precision = get_bits(gb, 2);
> +        s->intra_dc_precision = get_bits(gb, 2);
> +        s->q_scale_type = get_bits1(gb);
> +    }
> +
> +    if (s->alternate_scan) {
> +        ff_init_scantable(s->idsp.idct_permutation, &s->inter_scantable,   ff_alternate_vertical_scan);
> +        ff_init_scantable(s->idsp.idct_permutation, &s->intra_scantable,   ff_alternate_vertical_scan);
> +        ff_init_scantable(s->idsp.idct_permutation, &s->intra_h_scantable, ff_alternate_vertical_scan);
> +        ff_init_scantable(s->idsp.idct_permutation, &s->intra_v_scantable, ff_alternate_vertical_scan);
> +    } else {
> +        ff_init_scantable(s->idsp.idct_permutation, &s->inter_scantable,   ff_zigzag_direct);
> +        ff_init_scantable(s->idsp.idct_permutation, &s->intra_scantable,   ff_zigzag_direct);
> +        ff_init_scantable(s->idsp.idct_permutation, &s->intra_h_scantable, ff_alternate_horizontal_scan);
> +        ff_init_scantable(s->idsp.idct_permutation, &s->intra_v_scantable, ff_alternate_vertical_scan);
> +    }
> +

> +    /* load default matrixes */
> +    for (i = 0; i < 64; i++) {
> +        int j = s->idsp.idct_permutation[i];
> +        v = ff_mpeg4_default_intra_matrix[i];
> +        s->intra_matrix[j]        = v;
> +        s->chroma_intra_matrix[j] = v;
> +
> +        v = ff_mpeg4_default_non_intra_matrix[i];
> +        s->inter_matrix[j]        = v;
> +        s->chroma_inter_matrix[j] = v;
> +    }

duplicate of:
        if ((s->mpeg_quant = get_bits1(gb))) { /* vol_quant_type */
            int i, v;

            /* load default matrixes */
            for (i = 0; i < 64; i++) {
                int j = s->idsp.idct_permutation[i];
                v = ff_mpeg4_default_intra_matrix[i];
                s->intra_matrix[j]        = v;
                s->chroma_intra_matrix[j] = v;

                v = ff_mpeg4_default_non_intra_matrix[i];
                s->inter_matrix[j]        = v;
                s->chroma_inter_matrix[j] = v;
            }


> +
> +    next_start_code_studio(gb);
> +    extension_and_user_data(s, gb, 4);
> +
> +    return 0;
> +}
> +
> +static void decode_studiovisualobject(Mpeg4DecContext *ctx, GetBitContext *gb)
> +{
> +    uint32_t startcode;
> +    MpegEncContext *s = &ctx->m;
> +    int visual_object_type, width, height;
> +
> +    startcode = get_bits_long(gb, 32);
> +
> +    /* StudioVisualObject() */
> +    if (startcode == VISUAL_OBJ_STARTCODE) {
> +        skip_bits(gb, 4); /* visual_object_verid */
> +        visual_object_type = get_bits(gb, 4);
> +
> +        next_start_code_studio(gb);
> +        extension_and_user_data(s, gb, 1);
> +
> +        if (visual_object_type == VOT_VIDEO_ID) {
> +            /* StudioVideoObjectLayer */
> +            skip_bits_long(gb, 32); /* video_object_start_code */
> +            skip_bits_long(gb, 32); /* video_object_layer_start_code */
> +            skip_bits1(gb); /* random_accessible_vol */
> +            skip_bits(gb, 8); /* video_object_type_indication */
> +            skip_bits(gb, 4); /* video_object_layer_verid */
> +            ctx->shape = get_bits(gb, 2); /* video_object_layer_shape */
> +            skip_bits(gb, 4); /* video_object_layer_shape_extension */
> +            skip_bits1(gb); /* progressive_sequence */
> +            if (ctx->shape != BIN_ONLY_SHAPE) {
> +                ctx->rgb = get_bits1(gb); /* rgb_components */

> +                s->chroma_format = get_bits(gb, 2); /* chroma_format */
> +                if (!s->chroma_format)
> +                    av_log(s->avctx, AV_LOG_ERROR, "illegal chroma format\n");

This should propagate the error to the caller


> +
> +                s->avctx->bits_per_raw_sample = get_bits(gb, 4); /* bit_depth */
> +                if (s->avctx->bits_per_raw_sample == 10) {
> +                    if (ctx->rgb) {
> +                        s->avctx->pix_fmt = AV_PIX_FMT_GBRP10;
> +                    }
> +                    else {
> +                        s->avctx->pix_fmt = s->chroma_format == CHROMA_422 ? AV_PIX_FMT_YUV422P10 : AV_PIX_FMT_YUV444P10;
> +                    }
> +                }
> +                else {
> +                    avpriv_request_sample(s->avctx, "MPEG-4 Studio profile bit-depth %u", s->avctx->bits_per_raw_sample);

this should error out.
it doesnt set pix_fmt like the other branches so it would leave 
bits_per_raw_sample and pix_fmt inconsistant which might be bad


[...]
> @@ -2202,7 +2231,8 @@ void ff_mpeg_draw_horiz_band(MpegEncContext *s, int y, int h)
>  void ff_init_block_index(MpegEncContext *s){ //FIXME maybe rename
>      const int linesize   = s->current_picture.f->linesize[0]; //not s->linesize as this would be wrong for field pics
>      const int uvlinesize = s->current_picture.f->linesize[1];
> -    const int mb_size= 4 - s->avctx->lowres;
> +    const int mb_width= (4 + (s->avctx->bits_per_raw_sample > 8)) - s->avctx->lowres;
> +    const int mb_height= 4 - s->avctx->lowres;

please use different variable names
mb_width and mb_height are generally used to represent the width and height in number of macroblocks
not the width or height of a single macroblock (which is basically fixed at 16 for mpegvideo

thanks

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Let us carefully observe those good qualities wherein our enemies excel us
and endeavor to excel them, by avoiding what is faulty, and imitating what
is excellent in them. -- Plutarch
-------------- 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/20180210/0b97aaec/attachment.sig>


More information about the ffmpeg-devel mailing list