#include "libavutil/internal.h"
#include "libavutil/opt.h"
+#include "libavutil/pixdesc.h"
#include "error_resilience.h"
-#include "hwaccel.h"
+#include "hwconfig.h"
#include "idctdsp.h"
#include "internal.h"
#include "mpegutils.h"
#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
#define MB_TYPE_B_VLC_BITS 4
#define STUDIO_INTRA_BITS 9
+static int decode_studio_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb);
+
static VLC dc_lum, dc_chrom;
static VLC sprite_trajectory;
static VLC mb_type_b_vlc;
llabs(sprite_offset[0][i] + sprite_delta[i][1] * (h+16LL)) >= INT_MAX ||
llabs(sprite_offset[0][i] + sprite_delta[i][0] * (w+16LL) + sprite_delta[i][1] * (h+16LL)) >= INT_MAX ||
llabs(sprite_delta[i][0] * (w+16LL)) >= INT_MAX ||
- llabs(sprite_delta[i][1] * (w+16LL)) >= INT_MAX ||
+ llabs(sprite_delta[i][1] * (h+16LL)) >= INT_MAX ||
llabs(sd[0]) >= INT_MAX ||
llabs(sd[1]) >= INT_MAX ||
llabs(sprite_offset[0][i] + sd[0] * (w+16LL)) >= INT_MAX ||
len >>= s->quarter_sample;
if (s->real_sprite_warping_points == 1) {
- if (ctx->divx_version == 500 && ctx->divx_build == 413)
+ if (ctx->divx_version == 500 && ctx->divx_build == 413 && a >= s->quarter_sample)
sum = s->sprite_offset[0][n] / (1 << (a - s->quarter_sample));
else
sum = RSHIFT(s->sprite_offset[0][n] * (1 << s->quarter_sample), a);
int i;
do {
- if (show_bits_long(&s->gb, 19) == DC_MARKER)
+ if (show_bits(&s->gb, 19) == DC_MARKER)
return mb_num - 1;
cbpc = get_vlc2(&s->gb, ff_h263_intra_MCBPC_vlc.table, INTRA_MCBPC_VLC_BITS, 2);
if (s->pict_type == AV_PICTURE_TYPE_I) {
while (show_bits(&s->gb, 9) == 1)
skip_bits(&s->gb, 9);
- if (get_bits_long(&s->gb, 19) != DC_MARKER) {
+ if (get_bits(&s->gb, 19) != DC_MARKER) {
av_log(s->avctx, AV_LOG_ERROR,
"marker missing after first I partition at %d %d\n",
s->mb_x, s->mb_y);
{
align_get_bits(gb);
- while (get_bits_left(gb) >= 24 && show_bits_long(gb, 24) != 0x1) {
+ while (get_bits_left(gb) >= 24 && show_bits(gb, 24) != 0x1) {
get_bits(gb, 8);
}
}
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);
+ int shift = 3 - s->dct_precision;
mismatch = 1;
code >>= 1;
run = (1 << (additional_code_len - 1)) + code;
idx += run;
+ if (idx > 63)
+ return AVERROR_INVALIDDATA;
j = scantable[idx++];
block[j] = sign ? 1 : -1;
} else if (group >= 13 && group <= 20) {
/* Level value (Table B.49) */
+ if (idx > 63)
+ return AVERROR_INVALIDDATA;
j = scantable[idx++];
block[j] = get_xbits(&s->gb, additional_code_len);
} else if (group == 21) {
/* Escape */
+ if (idx > 63)
+ return AVERROR_INVALIDDATA;
j = scantable[idx++];
additional_code_len = s->avctx->bits_per_raw_sample + s->dct_precision + 4;
flc = get_bits(&s->gb, additional_code_len);
else
block[j] = flc;
}
- block[j] = ((8 * 2 * block[j] * quant_matrix[j] * s->qscale) >> s->dct_precision) / 32;
+ block[j] = ((block[j] * quant_matrix[j] * s->qscale) * (1 << shift)) / 16;
block[j] = av_clip(block[j], min, max);
mismatch ^= block[j];
}
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,
+ dpcm_residual, left, top, topleft, min_left_top, max_left_top, p, p2, output;
+ h = 16 >> (n ? s->chroma_y_shift : 0);
+ w = 16 >> (n ? s->chroma_x_shift : 0);
+
+ 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++) {
+ output = 1 << (s->avctx->bits_per_raw_sample - 1);
+ top = 1 << (s->avctx->bits_per_raw_sample - 1);
+
+ for (j = 0; j < w; j++) {
+ left = output;
+ topleft = top;
+
+ 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 {
+ if (rice_prefix_code == 12) {
+ av_log(s->avctx, AV_LOG_ERROR, "Forbidden rice_prefix_code\n");
+ return AVERROR_INVALIDDATA;
+ }
+ 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);
+
+ if (i != 0)
+ top = macroblock[idx-w];
+
+ p = left + top - topleft;
+ min_left_top = FFMIN(left, top);
+ if (p < min_left_top)
+ p = min_left_top;
+
+ max_left_top = FFMAX(left, top);
+ if (p > max_left_top)
+ p = max_left_top;
+
+ p2 = (FFMIN(min_left_top, topleft) + FFMAX(max_left_top, topleft)) >> 1;
+ if (p2 == p)
+ p2 = block_mean;
+
+ if (p2 > p)
+ dpcm_residual *= -1;
+
+ macroblock[idx++] = output = (dpcm_residual + p) & ((1 << s->avctx->bits_per_raw_sample) - 1);
+ }
+ }
+
+ return 0;
+}
+
static int mpeg4_decode_studio_mb(MpegEncContext *s, int16_t block_[12][64])
{
int i;
+ s->dpcm_direction = 0;
+
/* StudioMacroblock */
/* Assumes I-VOP */
s->mb_intra = 1;
} 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;
+ s->dpcm_direction = get_bits1(&s->gb) ? -1 : 1;
+ for (i = 0; i < 3; i++) {
+ if (mpeg4_decode_dpcm_macroblock(s, (*s->dpcm_macroblock)[i], i) < 0)
+ return AVERROR_INVALIDDATA;
+ }
}
if (get_bits_left(&s->gb) >= 24 && show_bits(&s->gb, 23) == 0) {
return SLICE_END;
}
+ //vcon-stp9L1.bits (first frame)
+ if (get_bits_left(&s->gb) == 0)
+ return SLICE_END;
+
+ //vcon-stp2L1.bits, vcon-stp3L1.bits, vcon-stp6L1.bits, vcon-stp7L1.bits, vcon-stp8L1.bits, vcon-stp10L1.bits (first frame)
+ if (get_bits_left(&s->gb) < 8U && show_bits(&s->gb, get_bits_left(&s->gb)) == 0)
+ return SLICE_END;
+
return SLICE_OK;
}
return 0;
}
-static int mpeg4_decode_profile_level(MpegEncContext *s, GetBitContext *gb)
+static int mpeg4_decode_profile_level(MpegEncContext *s, GetBitContext *gb, int *profile, int *level)
{
- s->avctx->profile = get_bits(gb, 4);
- s->avctx->level = get_bits(gb, 4);
+ *profile = get_bits(gb, 4);
+ *level = get_bits(gb, 4);
// for Simple profile, level 0
- if (s->avctx->profile == 0 && s->avctx->level == 8) {
- s->avctx->level = 0;
+ if (*profile == 0 && *level == 8) {
+ *level = 0;
}
return 0;
/* vol header */
skip_bits(gb, 1); /* random access */
s->vo_type = get_bits(gb, 8);
+
+ /* If we are in studio profile (per vo_type), check if its all consistent
+ * and if so continue pass control to decode_studio_vol_header().
+ * elIf something is inconsistent, error out
+ * else continue with (non studio) vol header decpoding.
+ */
+ if (s->vo_type == CORE_STUDIO_VO_TYPE ||
+ s->vo_type == SIMPLE_STUDIO_VO_TYPE) {
+ if (s->avctx->profile != FF_PROFILE_UNKNOWN && s->avctx->profile != FF_PROFILE_MPEG4_SIMPLE_STUDIO)
+ return AVERROR_INVALIDDATA;
+ s->studio_profile = 1;
+ s->avctx->profile = FF_PROFILE_MPEG4_SIMPLE_STUDIO;
+ return decode_studio_vol_header(ctx, gb);
+ } else if (s->studio_profile) {
+ return AVERROR_PATCHWELCOME;
+ }
+
if (get_bits1(gb) != 0) { /* is_ol_id */
vo_ver_id = get_bits(gb, 4); /* vo_ver_id */
skip_bits(gb, 3); /* vo_priority */
return 0;
}
-static void read_quant_matrix_ext(MpegEncContext *s, GetBitContext *gb)
+static int read_quant_matrix_ext(MpegEncContext *s, GetBitContext *gb)
{
int i, j, v;
if (get_bits1(gb)) {
+ if (get_bits_left(gb) < 64*8)
+ return AVERROR_INVALIDDATA;
/* intra_quantiser_matrix */
for (i = 0; i < 64; i++) {
v = get_bits(gb, 8);
}
if (get_bits1(gb)) {
+ if (get_bits_left(gb) < 64*8)
+ return AVERROR_INVALIDDATA;
/* non_intra_quantiser_matrix */
for (i = 0; i < 64; i++) {
get_bits(gb, 8);
}
if (get_bits1(gb)) {
+ if (get_bits_left(gb) < 64*8)
+ return AVERROR_INVALIDDATA;
/* chroma_intra_quantiser_matrix */
for (i = 0; i < 64; i++) {
v = get_bits(gb, 8);
}
if (get_bits1(gb)) {
+ if (get_bits_left(gb) < 64*8)
+ return AVERROR_INVALIDDATA;
/* chroma_non_intra_quantiser_matrix */
for (i = 0; i < 64; i++) {
get_bits(gb, 8);
}
next_start_code_studio(gb);
+ return 0;
}
static void extension_and_user_data(MpegEncContext *s, GetBitContext *gb, int id)
if (get_bits_left(gb) <= 32)
return 0;
+ s->partitioned_frame = 0;
+ s->interlaced_dct = 0;
s->decode_mb = mpeg4_decode_studio_mb;
decode_smpte_tc(ctx, gb);
int width, height;
int bits_per_raw_sample;
- skip_bits1(gb); /* random_accessible_vol */
- skip_bits(gb, 8); /* video_object_type_indication */
+ // random_accessible_vol and video_object_type_indication have already
+ // been read by the caller decode_vol_header()
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 */
/**
* Decode MPEG-4 headers.
- * @return <0 if no VOP found (or a damaged one)
+ *
+ * @param header If set the absence of a VOP is not treated as error; otherwise, it is treated as such.
+ * @return <0 if an error occurred
* FRAME_SKIPPED if a not coded VOP is found
- * 0 if a VOP is found
+ * 0 else
*/
-int ff_mpeg4_decode_picture_header(Mpeg4DecContext *ctx, GetBitContext *gb)
+int ff_mpeg4_decode_picture_header(Mpeg4DecContext *ctx, GetBitContext *gb, int header)
{
MpegEncContext *s = &ctx->m;
unsigned startcode, v;
/* search next start code */
align_get_bits(gb);
+ // If we have not switched to studio profile than we also did not switch bps
+ // that means something else (like a previous instance) outside set bps which
+ // would be inconsistant with the currect state, thus reset it
+ if (!s->studio_profile && s->avctx->bits_per_raw_sample != 8)
+ s->avctx->bits_per_raw_sample = 0;
+
if (s->codec_tag == AV_RL32("WV1F") && show_bits(gb, 24) == 0x575630) {
skip_bits(gb, 24);
if (get_bits(gb, 8) == 0xF0)
(ctx->divx_version >= 0 || ctx->xvid_build >= 0) || s->codec_tag == AV_RL32("QMP4")) {
av_log(s->avctx, AV_LOG_VERBOSE, "frame skip %d\n", gb->size_in_bits);
return FRAME_SKIPPED; // divx bug
+ } else if (header && get_bits_count(gb) == gb->size_in_bits) {
+ return 0; // ordinary return value for parsing of extradata
} else
return AVERROR_INVALIDDATA; // end of stream
}
continue;
}
vol++;
- if (s->studio_profile) {
- if ((ret = decode_studio_vol_header(ctx, gb)) < 0)
- return ret;
- } else {
- if ((ret = decode_vol_header(ctx, gb)) < 0)
- return ret;
- }
+ if ((ret = decode_vol_header(ctx, gb)) < 0)
+ return ret;
} else if (startcode == USER_DATA_STARTCODE) {
decode_user_data(ctx, gb);
} else if (startcode == GOP_STARTCODE) {
mpeg4_decode_gop_header(s, gb);
} else if (startcode == VOS_STARTCODE) {
- mpeg4_decode_profile_level(s, gb);
- if (s->avctx->profile == FF_PROFILE_MPEG4_SIMPLE_STUDIO &&
- (s->avctx->level > 0 && s->avctx->level < 9)) {
+ int profile, level;
+ mpeg4_decode_profile_level(s, gb, &profile, &level);
+ if (profile == FF_PROFILE_MPEG4_SIMPLE_STUDIO &&
+ (level > 0 && level < 9)) {
s->studio_profile = 1;
next_start_code_studio(gb);
extension_and_user_data(s, gb, 0);
+ } else if (s->studio_profile) {
+ avpriv_request_sample(s->avctx, "Mixes studio and non studio profile\n");
+ return AVERROR_PATCHWELCOME;
}
+ s->avctx->profile = profile;
+ s->avctx->level = level;
} else if (startcode == VISUAL_OBJ_STARTCODE) {
if (s->studio_profile) {
if ((ret = decode_studiovisualobject(ctx, gb)) < 0)
s->low_delay = 1;
s->avctx->has_b_frames = !s->low_delay;
- if (s->studio_profile)
+ if (s->studio_profile) {
+ if (!s->avctx->bits_per_raw_sample) {
+ av_log(s->avctx, AV_LOG_ERROR, "Missing VOL header\n");
+ return AVERROR_INVALIDDATA;
+ }
return decode_studio_vop_header(ctx, gb);
- else
+ } else
return decode_vop_header(ctx, gb);
}
if (ret < 0)
return ret;
- memcpy(((uint8_t*)s) + sizeof(MpegEncContext), ((uint8_t*)s1) + sizeof(MpegEncContext), sizeof(Mpeg4DecContext) - sizeof(MpegEncContext));
+ // copy all the necessary fields explicitly
+ s->time_increment_bits = s1->time_increment_bits;
+ s->shape = s1->shape;
+ s->vol_sprite_usage = s1->vol_sprite_usage;
+ s->sprite_brightness_change = s1->sprite_brightness_change;
+ s->num_sprite_warping_points = s1->num_sprite_warping_points;
+ s->rvlc = s1->rvlc;
+ s->resync_marker = s1->resync_marker;
+ s->t_frame = s1->t_frame;
+ s->new_pred = s1->new_pred;
+ s->enhancement_type = s1->enhancement_type;
+ s->scalability = s1->scalability;
+ s->use_intra_dc_vlc = s1->use_intra_dc_vlc;
+ s->intra_dc_threshold = s1->intra_dc_threshold;
+ s->divx_version = s1->divx_version;
+ s->divx_build = s1->divx_build;
+ s->xvid_build = s1->xvid_build;
+ s->lavc_build = s1->lavc_build;
+ s->showed_packed_warning = s1->showed_packed_warning;
+ s->vol_control_parameters = s1->vol_control_parameters;
+ s->cplx_estimation_trash_i = s1->cplx_estimation_trash_i;
+ s->cplx_estimation_trash_p = s1->cplx_estimation_trash_p;
+ s->cplx_estimation_trash_b = s1->cplx_estimation_trash_b;
+ s->rgb = s1->rgb;
+
+ memcpy(s->sprite_shift, s1->sprite_shift, sizeof(s1->sprite_shift));
+ memcpy(s->sprite_traj, s1->sprite_traj, sizeof(s1->sprite_traj));
if (CONFIG_MPEG4_DECODER && !init && s1->xvid_build >= 0)
ff_xvid_idct_init(&s->m.idsp, dst);
ctx->time_increment_bits = 4; /* default value for broken headers */
avctx->chroma_sample_location = AVCHROMA_LOC_LEFT;
- avctx->internal->allocate_progress = 1;
return 0;
}
Mpeg4DecContext *ctx = avctx->priv_data;
int i;
- if (!avctx->internal->is_copy) {
- for (i = 0; i < 12; i++)
- ff_free_vlc(&ctx->studio_intra_tab[i]);
+ for (i = 0; i < 12; i++)
+ ff_free_vlc(&ctx->studio_intra_tab[i]);
- ff_free_vlc(&ctx->studio_luma_dc);
- ff_free_vlc(&ctx->studio_chroma_dc);
- }
+ ff_free_vlc(&ctx->studio_luma_dc);
+ ff_free_vlc(&ctx->studio_chroma_dc);
return ff_h263_decode_end(avctx);
}
.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 |
AV_CODEC_CAP_TRUNCATED | AV_CODEC_CAP_DELAY |
AV_CODEC_CAP_FRAME_THREADS,
- .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
+ .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM |
+ FF_CODEC_CAP_ALLOCATE_PROGRESS,
.flush = ff_mpeg_flush,
.max_lowres = 3,
.pix_fmts = ff_h263_hwaccel_pixfmt_list_420,