static av_always_inline int update_dimensions(VP8Context *s, int width, int height, int is_vp7)
{
AVCodecContext *avctx = s->avctx; int i, ret, dim_reset = 0;
if (s->segmentation.update_feature_data) {
s->segmentation.absolute_vals = vp89_rac_get(c);
for (i = 0; i < 4; i++)
s->segmentation.base_quant[i] = vp8_rac_get_sint(c, 7);
for (i = 0; i < 4; i++)
s->segmentation.filter_level[i] = vp8_rac_get_sint(c, 6);
} if (s->segmentation.update_map) for (i = 0; i < 3; i++)
s->prob->segmentid[i] = vp89_rac_get(c) ? vp89_rac_get_uint(c, 8) : 255;
}
staticvoid update_lf_deltas(VP8Context *s)
{
VPXRangeCoder *c = &s->c; int i;
for (i = 0; i < 4; i++) { if (vp89_rac_get(c)) {
s->lf_delta.ref[i] = vp89_rac_get_uint(c, 6);
if (vp89_rac_get(c))
s->lf_delta.ref[i] = -s->lf_delta.ref[i];
}
}
for (i = MODE_I4x4; i <= VP8_MVMODE_SPLIT; i++) { if (vp89_rac_get(c)) {
s->lf_delta.mode[i] = vp89_rac_get_uint(c, 6);
if (vp89_rac_get(c))
s->lf_delta.mode[i] = -s->lf_delta.mode[i];
}
}
}
staticint setup_partitions(VP8Context *s, const uint8_t *buf, int buf_size)
{ const uint8_t *sizes = buf; int i; int ret;
for (i = 0; i < 4; i++) { if (s->segmentation.enabled) {
base_qi = s->segmentation.base_quant[i]; if (!s->segmentation.absolute_vals)
base_qi += s->quant.yac_qi;
} else
base_qi = s->quant.yac_qi;
staticvoid vp78_reset_probability_tables(VP8Context *s)
{ int i, j; for (i = 0; i < 4; i++) for (j = 0; j < 16; j++)
memcpy(s->prob->token[i][j], vp8_token_default_probs[i][vp8_coeff_band[j]], sizeof(s->prob->token[i][j]));
}
staticvoid vp78_update_probability_tables(VP8Context *s)
{
VPXRangeCoder *c = &s->c; int i, j, k, l, m;
for (i = 0; i < 4; i++) for (j = 0; j < 8; j++) for (k = 0; k < 3; k++) for (l = 0; l < NUM_DCT_TOKENS-1; l++) if (vpx_rac_get_prob_branchy(c, ff_vp8_token_update_probs[i][j][k][l])) { int prob = vp89_rac_get_uint(c, 8); for (m = 0; vp8_coeff_band_indexes[j][m] >= 0; m++)
s->prob->token[i][vp8_coeff_band_indexes[j][m]][k][l] = prob;
}
}
#define VP7_MVC_SIZE 17 #define VP8_MVC_SIZE 19
staticvoid vp78_update_pred16x16_pred8x8_mvc_probabilities(VP8Context *s, int mvc_size)
{
VPXRangeCoder *c = &s->c; int i, j;
if (vp89_rac_get(c)) for (i = 0; i < 4; i++)
s->prob->pred16x16[i] = vp89_rac_get_uint(c, 8); if (vp89_rac_get(c)) for (i = 0; i < 3; i++)
s->prob->pred8x8c[i] = vp89_rac_get_uint(c, 8);
// 17.2 MV probability update for (i = 0; i < 2; i++) for (j = 0; j < mvc_size; j++) if (vpx_rac_get_prob_branchy(c, vp8_mv_update_prob[i][j]))
s->prob->mvc[i][j] = vp8_rac_get_nn(c);
}
staticvoid copy_chroma(AVFrame *dst, const AVFrame *src, int width, int height)
{ int i, j;
for (j = 1; j < 3; j++) { for (i = 0; i < height / 2; i++)
memcpy(dst->data[j] + i * dst->linesize[j],
src->data[j] + i * src->linesize[j], width / 2);
}
}
staticvoid fade(uint8_t *dst, ptrdiff_t dst_linesize, const uint8_t *src, ptrdiff_t src_linesize, int width, int height, int alpha, int beta)
{ int i, j; for (j = 0; j < height; j++) { const uint8_t *src2 = src + j * src_linesize;
uint8_t *dst2 = dst + j * dst_linesize; for (i = 0; i < width; i++) {
uint8_t y = src2[i];
dst2[i] = av_clip_uint8(y + ((y * beta) >> 8) + alpha);
}
}
}
staticint vp7_fade_frame(VP8Context *s, int alpha, int beta)
{ int ret;
if (!s->keyframe && (alpha || beta)) { int width = s->mb_width * 16; int height = s->mb_height * 16; const AVFrame *src;
AVFrame *dst;
if (!s->framep[VP8_FRAME_PREVIOUS] ||
!s->framep[VP8_FRAME_GOLDEN]) {
av_log(s->avctx, AV_LOG_WARNING, "Discarding interframe without a prior keyframe!\n"); return AVERROR_INVALIDDATA;
}
src =
dst = s->framep[VP8_FRAME_PREVIOUS]->tf.f;
/* preserve the golden frame, write a new previous frame */ if (s->framep[VP8_FRAME_GOLDEN] == s->framep[VP8_FRAME_PREVIOUS]) {
VP8Frame *prev_frame = vp8_find_free_buffer(s);
ret = vp8_alloc_frame(s, prev_frame, 1); if (ret < 0) return ret;
s->framep[VP8_FRAME_PREVIOUS] = prev_frame;
staticint vp7_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_size)
{
VPXRangeCoder *c = &s->c; int part1_size, hscale, vscale, i, j, ret; int width = s->avctx->width; int height = s->avctx->height; int alpha = 0; int beta = 0; int fade_present = 1;
if (s->keyframe || s->profile > 0)
memset(s->inter_dc_pred, 0 , sizeof(s->inter_dc_pred));
/* B. Decoding information for all four macroblock-level features */ for (i = 0; i < 4; i++) {
s->feature_enabled[i] = vp89_rac_get(c); if (s->feature_enabled[i]) {
s->feature_present_prob[i] = vp89_rac_get_uint(c, 8);
/* C. Dequantization indices */
vp7_get_quants(s);
/* D. Golden frame update flag (a Flag) for interframes only */ if (!s->keyframe) {
s->update_golden = vp89_rac_get(c) ? VP8_FRAME_CURRENT : VP8_FRAME_NONE;
s->sign_bias[VP8_FRAME_GOLDEN] = 0;
}
s->update_last = 1;
s->update_probabilities = 1;
if (s->profile > 0) {
s->update_probabilities = vp89_rac_get(c); if (!s->update_probabilities)
s->prob[1] = s->prob[0];
if (!s->keyframe)
fade_present = vp89_rac_get(c);
}
if (vpx_rac_is_end(c)) return AVERROR_INVALIDDATA; /* E. Fading information for previous frame */ if (fade_present && vp89_rac_get(c)) {
alpha = (int8_t) vp89_rac_get_uint(c, 8);
beta = (int8_t) vp89_rac_get_uint(c, 8);
}
/* F. Loop filter type */ if (!s->profile)
s->filter.simple = vp89_rac_get(c);
/* G. DCT coefficient ordering specification */ if (vp89_rac_get(c)) for (i = 1; i < 16; i++)
s->prob[0].scan[i] = ff_zigzag_scan[vp89_rac_get_uint(c, 4)];
/* I. DCT coefficient probability update; 13.3 Token Probability Updates */
vp78_update_probability_tables(s);
s->mbskip_enabled = 0;
/* J. The remaining frame header data occurs ONLY FOR INTERFRAMES */ if (!s->keyframe) {
s->prob->intra = vp89_rac_get_uint(c, 8);
s->prob->last = vp89_rac_get_uint(c, 8);
vp78_update_pred16x16_pred8x8_mvc_probabilities(s, VP7_MVC_SIZE);
}
if (vpx_rac_is_end(c)) return AVERROR_INVALIDDATA;
if ((ret = vp7_fade_frame(s, alpha, beta)) < 0) return ret;
return0;
}
staticint vp8_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_size)
{
VPXRangeCoder *c = &s->c; int header_size, hscale, vscale, ret; int width = s->avctx->width; int height = s->avctx->height;
if (buf_size < 3) {
av_log(s->avctx, AV_LOG_ERROR, "Insufficient data (%d) for header\n", buf_size); return AVERROR_INVALIDDATA;
}
if (s->profile > 3)
av_log(s->avctx, AV_LOG_WARNING, "Unknown profile %d\n", s->profile);
if (!s->profile)
memcpy(s->put_pixels_tab, s->vp8dsp.put_vp8_epel_pixels_tab, sizeof(s->put_pixels_tab)); else// profile 1-3 use bilinear, 4+ aren't defined so whatever
memcpy(s->put_pixels_tab, s->vp8dsp.put_vp8_bilinear_pixels_tab, sizeof(s->put_pixels_tab));
if (header_size > buf_size - 7 * s->keyframe) {
av_log(s->avctx, AV_LOG_ERROR, "Header size larger than data provided\n"); return AVERROR_INVALIDDATA;
}
ret = ff_vpx_init_range_decoder(c, buf, header_size); if (ret < 0) return ret;
buf += header_size;
buf_size -= header_size;
if (s->keyframe) {
s->colorspace = vp89_rac_get(c); if (s->colorspace)
av_log(s->avctx, AV_LOG_WARNING, "Unspecified colorspace\n");
s->fullrange = vp89_rac_get(c);
}
if ((s->segmentation.enabled = vp89_rac_get(c)))
parse_segment_info(s); else
s->segmentation.update_map = 0; // FIXME: move this to some init function?
// if we aren't saving this frame's probabilities for future frames, // make a copy of the current probabilities if (!(s->update_probabilities = vp89_rac_get(c)))
s->prob[1] = s->prob[0];
s->update_last = s->keyframe || vp89_rac_get(c);
vp78_update_probability_tables(s);
if ((s->mbskip_enabled = vp89_rac_get(c)))
s->prob->mbskip = vp89_rac_get_uint(c, 8);
// Record the entropy coder state here so that hwaccels can use it.
s->c.code_word = vpx_rac_renorm(&s->c);
s->coder_state_at_header_end.input = s->c.buffer - (-s->c.bits / 8);
s->coder_state_at_header_end.range = s->c.high;
s->coder_state_at_header_end.value = s->c.code_word >> 16;
s->coder_state_at_header_end.bit_count = -s->c.bits % 8;
mb->partitioning = VP8_SPLITMVMODE_NONE; if (vpx_rac_get_prob_branchy(c, vp8_mode_contexts[cnt[CNT_ZERO]][0])) {
mb->mode = VP8_MVMODE_MV;
/* If we have three distinct MVs, merge first and last if they're the same */ if (cnt[CNT_SPLITMV] &&
AV_RN32A(&near_mv[1 + VP8_EDGE_TOP]) == AV_RN32A(&near_mv[1 + VP8_EDGE_TOPLEFT]))
cnt[CNT_NEAREST] += 1;
/* Swap near and nearest if necessary */ if (cnt[CNT_NEAR] > cnt[CNT_NEAREST]) {
FFSWAP(uint8_t, cnt[CNT_NEAREST], cnt[CNT_NEAR]);
FFSWAP(VP8mv, near_mv[CNT_NEAREST], near_mv[CNT_NEAR]);
}
if (vpx_rac_get_prob_branchy(c, vp8_mode_contexts[cnt[CNT_NEAREST]][1])) { if (vpx_rac_get_prob_branchy(c, vp8_mode_contexts[cnt[CNT_NEAR]][2])) { /* Choose the best mv out of 0,0 and the nearest mv */
clamp_mv(mv_bounds, &mb->mv, &near_mv[CNT_ZERO + (cnt[CNT_NEAREST] >= cnt[CNT_ZERO])]);
cnt[CNT_SPLITMV] = ((mb_edge[VP8_EDGE_LEFT]->mode == VP8_MVMODE_SPLIT) +
(mb_edge[VP8_EDGE_TOP]->mode == VP8_MVMODE_SPLIT)) * 2 +
(mb_edge[VP8_EDGE_TOPLEFT]->mode == VP8_MVMODE_SPLIT);
/** *@paramrarithmeticbitstreamreadercontext *@paramblockdestinationforblockcoefficients *@paramprobsprobabilitiestousewhenreadingtreesfromthebitstream *@paramiinitialcoeffindex,0unlessaseparateDCblockiscoded *@paramqmularrayholdingthedc/acdequantfactoratposition0/1 * *@return0ifnocoeffsweredecoded *otherwise,theindexofthelastcoeffdecodedplusone
*/ static av_always_inline int decode_block_coeffs_internal(VPXRangeCoder *r, int16_t block[16],
uint8_t probs[16][3][NUM_DCT_TOKENS - 1], int i, const uint8_t *token_prob, const int16_t qmul[2], const uint8_t scan[16], int vp7)
{
VPXRangeCoder c = *r; goto skip_eob; do { int coeff;
restart: if (!vpx_rac_get_prob_branchy(&c, token_prob[0])) // DCT_EOB break;
skip_eob: if (!vpx_rac_get_prob_branchy(&c, token_prob[1])) { // DCT_0 if (++i == 16) break; // invalid input; blocks should end with EOB
token_prob = probs[i][0]; if (vp7) goto restart; goto skip_eob;
}
if (!vpx_rac_get_prob_branchy(&c, token_prob[2])) { // DCT_1
coeff = 1;
token_prob = probs[i + 1][1];
} else { if (!vpx_rac_get_prob_branchy(&c, token_prob[3])) { // DCT 2,3,4
coeff = vpx_rac_get_prob_branchy(&c, token_prob[4]); if (coeff)
coeff += vpx_rac_get_prob(&c, token_prob[5]);
coeff += 2;
} else { // DCT_CAT* if (!vpx_rac_get_prob_branchy(&c, token_prob[6])) { if (!vpx_rac_get_prob_branchy(&c, token_prob[7])) { // DCT_CAT1
coeff = 5 + vpx_rac_get_prob(&c, vp8_dct_cat1_prob[0]);
} else { // DCT_CAT2
coeff = 7;
coeff += vpx_rac_get_prob(&c, vp8_dct_cat2_prob[0]) << 1;
coeff += vpx_rac_get_prob(&c, vp8_dct_cat2_prob[1]);
}
} else { // DCT_CAT3 and up int a = vpx_rac_get_prob(&c, token_prob[8]); int b = vpx_rac_get_prob(&c, token_prob[9 + a]); int cat = (a << 1) + b;
coeff = 3 + (8 << cat);
coeff += vp8_rac_get_coeff(&c, ff_vp8_dct_cat_prob[cat]);
}
}
token_prob = probs[i + 1][2];
}
block[scan[i]] = (vp89_rac_get(&c) ? -coeff : coeff) * qmul[!!i];
} while (++i < 16);
*r = c; return i;
}
static av_always_inline int inter_predict_dc(int16_t block[16], int16_t pred[2])
{
int16_t dc = block[0]; int ret = 0;
// luma blocks for (y = 0; y < 4; y++) for (x = 0; x < 4; x++) {
nnz_pred = l_nnz[y] + t_nnz[x];
nnz = decode_block_coeffs(c, td->block[y][x],
s->prob->token[luma_ctx],
luma_start, nnz_pred,
s->qmat[segment].luma_qmul,
s->prob[0].scan, is_vp7); /* nnz+block_dc may be one more than the actual last index,
* but we don't care */
td->non_zero_count_cache[y][x] = nnz + block_dc;
t_nnz[x] = l_nnz[y] = !!nnz;
nnz_total += nnz;
}
// chroma blocks // TODO: what to do about dimensions? 2nd dim for luma is x, // but for chroma it's (y<<1)|x for (i = 4; i < 6; i++) for (y = 0; y < 2; y++) for (x = 0; x < 2; x++) {
nnz_pred = l_nnz[i + 2 * y] + t_nnz[i + 2 * x];
nnz = decode_block_coeffs(c, td->block[i][(y << 1) + x],
s->prob->token[2], 0, nnz_pred,
s->qmat[segment].chroma_qmul,
s->prob[0].scan, is_vp7);
td->non_zero_count_cache[i][(y << 1) + x] = nnz;
t_nnz[i + 2 * x] = l_nnz[i + 2 * y] = !!nnz;
nnz_total += nnz;
}
// if there were no coded coeffs despite the macroblock not being marked skip, // we MUST not do the inner loop filter and should not do IDCT // Since skip isn't used for bitstream prediction, just manually set it. if (!nnz_total)
mb->skip = 1;
}
// only copy chroma for normal loop filter // or to initialize the top row to 127 if (!simple || !mb_y) {
XCHG(top_border_m1 + 16, src_cb - 8, xchg);
XCHG(top_border_m1 + 24, src_cr - 8, xchg);
XCHG(top_border + 16, src_cb, 1);
XCHG(top_border + 24, src_cr, 1);
}
}
static av_always_inline int check_dc_pred8x8_mode(int mode, int mb_x, int mb_y)
{ if (!mb_x) return mb_y ? TOP_DC_PRED8x8 : DC_128_PRED8x8; else return mb_y ? mode : LEFT_DC_PRED8x8;
}
static av_always_inline int check_tm_pred8x8_mode(int mode, int mb_x, int mb_y, int vp7)
{ if (!mb_x) return mb_y ? VERT_PRED8x8 : (vp7 ? DC_128_PRED8x8 : DC_129_PRED8x8); else return mb_y ? mode : HOR_PRED8x8;
}
static av_always_inline int check_intra_pred8x8_mode_emuedge(int mode, int mb_x, int mb_y, int vp7)
{ switch (mode) { case DC_PRED8x8: return check_dc_pred8x8_mode(mode, mb_x, mb_y); case VERT_PRED8x8: return !mb_y ? (vp7 ? DC_128_PRED8x8 : DC_127_PRED8x8) : mode; case HOR_PRED8x8: return !mb_x ? (vp7 ? DC_128_PRED8x8 : DC_129_PRED8x8) : mode; case PLANE_PRED8x8: /* TM */ return check_tm_pred8x8_mode(mode, mb_x, mb_y, vp7);
} return mode;
}
static av_always_inline int check_tm_pred4x4_mode(int mode, int mb_x, int mb_y, int vp7)
{ if (!mb_x) { return mb_y ? VERT_VP8_PRED : (vp7 ? DC_128_PRED : DC_129_PRED);
} else { return mb_y ? mode : HOR_VP8_PRED;
}
}
static av_always_inline int check_intra_pred4x4_mode_emuedge(int mode, int mb_x, int mb_y, int *copy_buf, int vp7)
{ switch (mode) { case VERT_PRED: if (!mb_x && mb_y) {
*copy_buf = 1; return mode;
} /* fall-through */ case DIAG_DOWN_LEFT_PRED: case VERT_LEFT_PRED: return !mb_y ? (vp7 ? DC_128_PRED : DC_127_PRED) : mode; case HOR_PRED: if (!mb_y) {
*copy_buf = 1; return mode;
} /* fall-through */ case HOR_UP_PRED: return !mb_x ? (vp7 ? DC_128_PRED : DC_129_PRED) : mode; case TM_VP8_PRED: return check_tm_pred4x4_mode(mode, mb_x, mb_y, vp7); case DC_PRED: /* 4x4 DC doesn't use the same "H.264-style" exceptions
* as 16x16/8x8 DC */ case DIAG_DOWN_RIGHT_PRED: case VERT_RIGHT_PRED: case HOR_DOWN_PRED: if (!mb_y || !mb_x)
*copy_buf = 1; return mode;
} return mode;
}
static av_always_inline void intra_predict(VP8Context *s, VP8ThreadData *td, uint8_t *const dst[3],
VP8Macroblock *mb, int mb_x, int mb_y, int is_vp7)
{ int x, y, mode, nnz;
uint32_t tr;
/* for the first row, we need to run xchg_mb_border to init the top edge
* to 127 otherwise, skip it if we aren't going to deblock */ if (mb_y && (s->deblock_filter || !mb_y) && td->thread_nr == 0)
xchg_mb_border(s->top_border[mb_x + 1], dst[0], dst[1], dst[2],
s->linesize, s->uvlinesize, mb_x, mb_y, s->mb_width,
s->filter.simple, 1);
// all blocks on the right edge of the macroblock use bottom edge // the top macroblock for their topright edge const uint8_t *tr_right = ptr - s->linesize + 16;
// if we're on the right edge of the frame, said edge is extended // from the top macroblock if (mb_y && mb_x == s->mb_width - 1) {
tr = tr_right[-1] * 0x01010101u;
tr_right = (uint8_t *) &tr;
}
if (mb->skip)
AV_ZERO128(td->non_zero_count_cache);
for (y = 0; y < 4; y++) { const uint8_t *topright = ptr + 4 - s->linesize; for (x = 0; x < 4; x++) { int copy = 0;
ptrdiff_t linesize = s->linesize;
uint8_t *dst = ptr + 4 * x;
LOCAL_ALIGNED(4, uint8_t, copy_dst, [5 * 8]);
staticconst uint8_t subpel_idx[3][8] = {
{ 0, 1, 2, 1, 2, 1, 2, 1 }, // nr. of left extra pixels, // also function pointer index
{ 0, 3, 5, 3, 5, 3, 5, 3 }, // nr. of extra pixels required
{ 0, 2, 3, 2, 3, 2, 3, 2 }, // nr. of right extra pixels
};
/** *lumaMCfunction * *@paramsVP8decodingcontext *@paramdsttargetbufferforblockdataatblockposition *@paramrefreferencepicturebufferatorigin(0,0) *@parammvmotionvector(relativetoblockposition)togetpixeldatafrom *@paramx_offhorizontalpositionofblockfromorigin(0,0) *@paramy_offverticalpositionofblockfromorigin(0,0) *@paramblock_wwidthofblock(16,8or4) *@paramblock_hheightofblock(alwayssameasblock_w) *@paramwidthwidthofsrc/dstplanedata *@paramheightheightofsrc/dstplanedata *@paramlinesizesizeofasinglelineofplanedata,includingpadding *@parammc_funcmotioncompensationfunctionpointers(bilinearorsixtapMC)
*/ static av_always_inline void vp8_mc_luma(VP8Context *s, VP8ThreadData *td, uint8_t *dst, const ProgressFrame *ref, const VP8mv *mv, int x_off, int y_off, int block_w, int block_h, int width, int height, ptrdiff_t linesize,
vp8_mc_func mc_func[3][3])
{ const uint8_t *src = ref->f->data[0];
if (AV_RN32A(mv)) {
ptrdiff_t src_linesize = linesize;
int mx = (mv->x * 2) & 7, mx_idx = subpel_idx[0][mx]; int my = (mv->y * 2) & 7, my_idx = subpel_idx[0][my];
static av_always_inline void vp8_mc_part(VP8Context *s, VP8ThreadData *td, uint8_t *const dst[3], const ProgressFrame *ref_frame, int x_off, int y_off, int bx_off, int by_off, int block_w, int block_h, int width, int height, const VP8mv *mv)
{
VP8mv uvmv = *mv;
if (!mb->skip) {
idct_mb(s, td, dst, mb);
} else {
AV_ZERO64(td->left_nnz);
AV_WN64(s->top_nnz[mb_x], 0); // array of 9, so unaligned
/* Reset DC block predictors if they would exist
* if the mb had coefficients */ if (mb->mode != MODE_I4x4 && mb->mode != VP8_MVMODE_SPLIT) {
td->left_nnz[8] = 0;
s->top_nnz[mb_x][8] = 0;
}
}
if (s->deblock_filter)
filter_level_for_mb(s, mb, &td->filter_strength[mb_x], is_vp7);
if (avctx->active_thread_type == FF_THREAD_FRAME)
ff_progress_frame_report(&curframe->tf, mb_y);
}
return0;
}
staticint vp7_decode_mb_row_sliced(AVCodecContext *avctx, void *tdata, int jobnr, int threadnr)
{ return vp78_decode_mb_row_sliced(avctx, tdata, jobnr, threadnr, IS_VP7);
}
staticint vp8_decode_mb_row_sliced(AVCodecContext *avctx, void *tdata, int jobnr, int threadnr)
{ return vp78_decode_mb_row_sliced(avctx, tdata, jobnr, threadnr, IS_VP8);
}
static av_always_inline int vp78_decode_frame(AVCodecContext *avctx, AVFrame *rframe, int *got_frame, const AVPacket *avpkt, int is_vp7)
{
VP8Context *s = avctx->priv_data; int ret, i, referenced, num_jobs; enum AVDiscard skip_thresh;
VP8Frame *av_uninit(curframe), *prev_frame;
if (is_vp7)
ret = vp7_decode_frame_header(s, avpkt->data, avpkt->size); else
ret = vp8_decode_frame_header(s, avpkt->data, avpkt->size);
if (ret < 0) goto err;
if (!is_vp7 && s->actually_webp) { // VP8 in WebP is supposed to be intra-only. Enforce this here // to ensure that output is reproducible with frame-threading. if (!s->keyframe) return AVERROR_INVALIDDATA; // avctx->pix_fmt already set in caller.
} elseif (!is_vp7 && s->pix_fmt == AV_PIX_FMT_NONE) {
s->pix_fmt = get_pixel_format(s); if (s->pix_fmt < 0) {
ret = AVERROR(EINVAL); goto err;
}
avctx->pix_fmt = s->pix_fmt;
}
// release no longer referenced frames for (i = 0; i < 5; i++) if (s->frames[i].tf.f &&
&s->frames[i] != prev_frame &&
&s->frames[i] != s->framep[VP8_FRAME_PREVIOUS] &&
&s->frames[i] != s->framep[VP8_FRAME_GOLDEN] &&
&s->frames[i] != s->framep[VP8_FRAME_ALTREF])
vp8_release_frame(&s->frames[i]);
if (!s->colorspace)
avctx->colorspace = AVCOL_SPC_BT470BG; if (s->fullrange)
avctx->color_range = AVCOL_RANGE_JPEG; else
avctx->color_range = AVCOL_RANGE_MPEG;
/* Given that arithmetic probabilities are updated every frame, it's quite *likelythatthevalueswehaveonarandominterframearecomplete *junkifwedidn'tstartdecodeonakeyframe.Sojustdon'tdisplay
* anything rather than junk. */ if (!s->keyframe && (!s->framep[VP8_FRAME_PREVIOUS] ||
!s->framep[VP8_FRAME_GOLDEN] ||
!s->framep[VP8_FRAME_ALTREF])) {
av_log(avctx, AV_LOG_WARNING, "Discarding interframe without a prior keyframe!\n");
ret = AVERROR_INVALIDDATA; goto err;
}
// check if golden and altref are swapped if (s->update_altref != VP8_FRAME_NONE)
s->next_framep[VP8_FRAME_ALTREF] = s->framep[s->update_altref]; else
s->next_framep[VP8_FRAME_ALTREF] = s->framep[VP8_FRAME_ALTREF];
memset(s->top_nnz, 0, s->mb_width * sizeof(*s->top_nnz)); /* Zero macroblock structures for top/top-left prediction *fromoutsidetheframe.*/ if(!s->mb_layout) memset(s->macroblocks+s->mb_height*2-1,0, (s->mb_width+1)*sizeof(*s->macroblocks)); if(!s->mb_layout&&s->keyframe) memset(s->intra4x4_pred_mode_top,DC_PRED,s->mb_width*4);
memset(s->ref_count,0,sizeof(s->ref_count));
if(s->mb_layout==1){ // Make sure the previous frame has read its segmentation map, // if we reuse the same map. if(prev_frame&&s->segmentation.enabled&& !s->segmentation.update_map) ff_progress_frame_await(&prev_frame->tf,1); if(is_vp7) ret=vp7_decode_mv_mb_modes(avctx,curframe,prev_frame); else ret=vp8_decode_mv_mb_modes(avctx,curframe,prev_frame); if(ret<0) gotoerr; }
skip_decode: // if future frames don't use the updated probabilities, // reset them to the values we saved if(!s->update_probabilities) s->prob[0]=s->prob[1];
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.