Commit 6ea4bb0b72 for ffmpeg
commit 6ea4bb0b72376871a92b55bc8064ae737afe9e14
Author: Rainbaby <r@bgr.jp>
Date: Fri Aug 28 16:18:07 2026 +0900
avcodec/cavsdec: set coded dimensions from macroblock grid
The decoder writes whole macroblocks, so give ff_set_dimensions() the
macroblock aligned size and restore the display size after, as
h264_slice.c does. A non-progressive sequence uses the interlaced
MbHeight of clause 7.2.2; the parser now reports the same height.
Signed-off-by: Rainbaby <r@bgr.jp>
diff --git a/libavcodec/cavs_parser.c b/libavcodec/cavs_parser.c
index 8dccc0923a..b3f67d6aef 100644
--- a/libavcodec/cavs_parser.c
+++ b/libavcodec/cavs_parser.c
@@ -81,11 +81,11 @@ static int parse_seq_header(AVCodecParserContext *s, AVCodecContext *avctx,
{
int frame_rate_code;
int width, height;
- int mb_width, mb_height;
+ int mb_width, mb_height, progressive;
skip_bits(gb, 8); // profile
skip_bits(gb, 8); // level
- skip_bits1(gb); // progressive sequence
+ progressive = get_bits1(gb);
width = get_bits(gb, 14);
height = get_bits(gb, 14);
@@ -94,7 +94,8 @@ static int parse_seq_header(AVCodecParserContext *s, AVCodecContext *avctx,
return AVERROR_INVALIDDATA;
}
mb_width = (width + 15) >> 4;
- mb_height = (height + 15) >> 4;
+ /* an interlaced sequence has an even MbHeight (clause 7.2.2) */
+ mb_height = progressive ? (height + 15) >> 4 : ((height + 31) >> 5) * 2;
skip_bits(gb, 2); // chroma format
skip_bits(gb, 3); // sample_precision
diff --git a/libavcodec/cavsdec.c b/libavcodec/cavsdec.c
index 1ec50af121..67002049f0 100644
--- a/libavcodec/cavsdec.c
+++ b/libavcodec/cavsdec.c
@@ -1231,17 +1231,20 @@ static int decode_pic(AVSContext *h)
static int decode_seq_header(AVSContext *h)
{
int frame_rate_code;
+ int profile, level, aspect_ratio;
int width, height;
+ int mb_width, mb_height;
+ int progressive_seq, low_delay;
int ret;
- h->profile = get_bits(&h->gb, 8);
- if (h->profile != 0x20) {
+ profile = get_bits(&h->gb, 8);
+ if (profile != 0x20) {
avpriv_report_missing_feature(h->avctx,
"only support JiZhun profile");
return AVERROR_PATCHWELCOME;
}
- h->level = get_bits(&h->gb, 8);
- skip_bits1(&h->gb); //progressive sequence
+ level = get_bits(&h->gb, 8);
+ progressive_seq = get_bits1(&h->gb);
width = get_bits(&h->gb, 14);
height = get_bits(&h->gb, 14);
@@ -1256,7 +1259,7 @@ static int decode_seq_header(AVSContext *h)
}
skip_bits(&h->gb, 2); //chroma format
skip_bits(&h->gb, 3); //sample_precision
- h->aspect_ratio = get_bits(&h->gb, 4);
+ aspect_ratio = get_bits(&h->gb, 4);
frame_rate_code = get_bits(&h->gb, 4);
if (frame_rate_code == 0 || frame_rate_code > 13) {
av_log(h->avctx, AV_LOG_WARNING,
@@ -1267,16 +1270,34 @@ static int decode_seq_header(AVSContext *h)
skip_bits(&h->gb, 18); //bit_rate_lower
skip_bits1(&h->gb); //marker_bit
skip_bits(&h->gb, 12); //bit_rate_upper
- h->low_delay = get_bits1(&h->gb);
+ low_delay = get_bits1(&h->gb);
+
+ mb_width = (width + 15) >> 4;
+ /* interlaced: an even number of MB rows (clause 7.2.2) */
+ mb_height = progressive_seq ? (height + 15) >> 4
+ : ((height + 31) >> 5) * 2;
+ /* the grid sizes the arrays of ff_cavs_init_top_lines(), allocated once */
+ if (h->top_qp && (mb_width != h->mb_width || mb_height != h->mb_height)) {
+ avpriv_report_missing_feature(h->avctx, "Macroblock grid changing");
+ return AVERROR_PATCHWELCOME;
+ }
- ret = ff_set_dimensions(h->avctx, width, height);
+ /* horizontal_size and vertical_size are only the displayed part */
+ ret = ff_set_dimensions(h->avctx, mb_width * 16, mb_height * 16);
if (ret < 0)
return ret;
-
- h->width = width;
- h->height = height;
- h->mb_width = (h->width + 15) >> 4;
- h->mb_height = (h->height + 15) >> 4;
+ h->avctx->width = width;
+ h->avctx->height = height;
+
+ /* commit last: a rejected header must leave the decoder as it was */
+ h->profile = profile;
+ h->level = level;
+ h->aspect_ratio = aspect_ratio;
+ h->width = width;
+ h->height = height;
+ h->mb_width = mb_width;
+ h->mb_height = mb_height;
+ h->low_delay = low_delay;
h->avctx->framerate = ff_mpeg12_frame_rate_tab[frame_rate_code];
if (!h->top_qp)
return ff_cavs_init_top_lines(h);