|
|
|
@ -171,6 +171,8 @@ typedef struct Vp3DecodeContext { |
|
|
|
|
Vp3Fragment *all_fragments; |
|
|
|
|
int fragment_start[3]; |
|
|
|
|
int data_offset[3]; |
|
|
|
|
uint8_t offset_x; |
|
|
|
|
uint8_t offset_y; |
|
|
|
|
|
|
|
|
|
int8_t (*motion_val[2])[2]; |
|
|
|
|
|
|
|
|
@ -1405,14 +1407,14 @@ static void vp3_draw_horiz_band(Vp3DecodeContext *s, int y) |
|
|
|
|
int offset[AV_NUM_DATA_POINTERS]; |
|
|
|
|
|
|
|
|
|
if (HAVE_THREADS && s->avctx->active_thread_type & FF_THREAD_FRAME) { |
|
|
|
|
int y_flipped = s->flipped_image ? s->avctx->height - y : y; |
|
|
|
|
int y_flipped = s->flipped_image ? s->height - y : y; |
|
|
|
|
|
|
|
|
|
/* At the end of the frame, report INT_MAX instead of the height of
|
|
|
|
|
* the frame. This makes the other threads' ff_thread_await_progress() |
|
|
|
|
* calls cheaper, because they don't have to clip their values. */ |
|
|
|
|
ff_thread_report_progress(&s->current_frame, |
|
|
|
|
y_flipped == s->avctx->height ? INT_MAX |
|
|
|
|
: y_flipped - 1, |
|
|
|
|
y_flipped == s->height ? INT_MAX |
|
|
|
|
: y_flipped - 1, |
|
|
|
|
0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1424,7 +1426,7 @@ static void vp3_draw_horiz_band(Vp3DecodeContext *s, int y) |
|
|
|
|
y -= h; |
|
|
|
|
|
|
|
|
|
if (!s->flipped_image) |
|
|
|
|
y = s->avctx->height - y - h; |
|
|
|
|
y = s->height - y - h; |
|
|
|
|
|
|
|
|
|
cy = y >> s->chroma_y_shift; |
|
|
|
|
offset[0] = s->current_frame.f->linesize[0] * y; |
|
|
|
@ -1721,8 +1723,8 @@ static av_cold int vp3_decode_init(AVCodecContext *avctx) |
|
|
|
|
s->version = 1; |
|
|
|
|
|
|
|
|
|
s->avctx = avctx; |
|
|
|
|
s->width = FFALIGN(avctx->width, 16); |
|
|
|
|
s->height = FFALIGN(avctx->height, 16); |
|
|
|
|
s->width = FFALIGN(avctx->coded_width, 16); |
|
|
|
|
s->height = FFALIGN(avctx->coded_height, 16); |
|
|
|
|
if (avctx->pix_fmt == AV_PIX_FMT_NONE) |
|
|
|
|
avctx->pix_fmt = AV_PIX_FMT_YUV420P; |
|
|
|
|
avctx->chroma_sample_location = AVCHROMA_LOC_CENTER; |
|
|
|
@ -2115,10 +2117,17 @@ static int vp3_decode_frame(AVCodecContext *avctx, |
|
|
|
|
int row = (s->height >> (3 + (i && s->chroma_y_shift))) - 1; |
|
|
|
|
apply_loop_filter(s, i, row, row + 1); |
|
|
|
|
} |
|
|
|
|
vp3_draw_horiz_band(s, s->avctx->height); |
|
|
|
|
vp3_draw_horiz_band(s, s->height); |
|
|
|
|
|
|
|
|
|
/* output frame, offset as needed */ |
|
|
|
|
if ((ret = av_frame_ref(data, s->current_frame.f)) < 0) |
|
|
|
|
return ret; |
|
|
|
|
for (i = 0; i < 3; i++) { |
|
|
|
|
AVFrame *dst = data; |
|
|
|
|
int off = (s->offset_x >> (i && s->chroma_y_shift)) + |
|
|
|
|
(s->offset_y >> (i && s->chroma_y_shift)) * dst->linesize[i]; |
|
|
|
|
dst->data[i] += off; |
|
|
|
|
} |
|
|
|
|
*got_frame = 1; |
|
|
|
|
|
|
|
|
|
if (!HAVE_THREADS || !(s->avctx->active_thread_type & FF_THREAD_FRAME)) { |
|
|
|
@ -2198,7 +2207,7 @@ static int theora_decode_header(AVCodecContext *avctx, GetBitContext *gb) |
|
|
|
|
{ |
|
|
|
|
Vp3DecodeContext *s = avctx->priv_data; |
|
|
|
|
int visible_width, visible_height, colorspace; |
|
|
|
|
int offset_x = 0, offset_y = 0; |
|
|
|
|
uint8_t offset_x = 0, offset_y = 0; |
|
|
|
|
int ret; |
|
|
|
|
AVRational fps, aspect; |
|
|
|
|
|
|
|
|
@ -2226,6 +2235,17 @@ static int theora_decode_header(AVCodecContext *avctx, GetBitContext *gb) |
|
|
|
|
offset_y = get_bits(gb, 8); /* offset y, from bottom */ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* sanity check */ |
|
|
|
|
if (av_image_check_size(visible_width, visible_height, 0, avctx) < 0 || |
|
|
|
|
visible_width + offset_x > s->width || |
|
|
|
|
visible_height + offset_y > s->height) { |
|
|
|
|
av_log(s, AV_LOG_ERROR, |
|
|
|
|
"Invalid frame dimensions - w:%d h:%d x:%d y:%d (%dx%d).\n", |
|
|
|
|
visible_width, visible_height, offset_x, offset_y, |
|
|
|
|
s->width, s->height); |
|
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fps.num = get_bits_long(gb, 32); |
|
|
|
|
fps.den = get_bits_long(gb, 32); |
|
|
|
|
if (fps.num && fps.den) { |
|
|
|
@ -2259,16 +2279,25 @@ static int theora_decode_header(AVCodecContext *avctx, GetBitContext *gb) |
|
|
|
|
skip_bits(gb, 3); /* reserved */ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// align_get_bits(gb);
|
|
|
|
|
|
|
|
|
|
if (visible_width <= s->width && visible_width > s->width - 16 && |
|
|
|
|
visible_height <= s->height && visible_height > s->height - 16 && |
|
|
|
|
!offset_x && (offset_y == s->height - visible_height)) |
|
|
|
|
ret = ff_set_dimensions(avctx, visible_width, visible_height); |
|
|
|
|
else |
|
|
|
|
ret = ff_set_dimensions(avctx, s->width, s->height); |
|
|
|
|
ret = ff_set_dimensions(avctx, s->width, s->height); |
|
|
|
|
if (ret < 0) |
|
|
|
|
return ret; |
|
|
|
|
if (!(avctx->flags2 & CODEC_FLAG2_IGNORE_CROP) && |
|
|
|
|
(visible_width != s->width || visible_height != s->height)) { |
|
|
|
|
avctx->width = visible_width; |
|
|
|
|
avctx->height = visible_height; |
|
|
|
|
// translate offsets from theora axis ([0,0] lower left)
|
|
|
|
|
// to normal axis ([0,0] upper left)
|
|
|
|
|
s->offset_x = offset_x; |
|
|
|
|
s->offset_y = s->height - visible_height - offset_y; |
|
|
|
|
|
|
|
|
|
if ((s->offset_x & 0x1F) && !(avctx->flags & CODEC_FLAG_UNALIGNED)) { |
|
|
|
|
s->offset_x &= ~0x1F; |
|
|
|
|
av_log(avctx, AV_LOG_WARNING, "Reducing offset_x from %d to %d" |
|
|
|
|
"chroma samples to preserve alignment.\n", |
|
|
|
|
offset_x, s->offset_x); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (colorspace == 1) |
|
|
|
|
avctx->color_primaries = AVCOL_PRI_BT470M; |
|
|
|
|