| 231 | } |
| 232 | |
| 233 | static int vpx_decode(AVCodecContext *avctx, AVFrame *picture, |
| 234 | int *got_frame, AVPacket *avpkt) |
| 235 | { |
| 236 | VPxContext *ctx = avctx->priv_data; |
| 237 | const void *iter = NULL; |
| 238 | const void *iter_alpha = NULL; |
| 239 | struct vpx_image *img, *img_alpha; |
| 240 | int ret; |
| 241 | uint8_t *side_data = NULL; |
| 242 | size_t side_data_size; |
| 243 | |
| 244 | ret = decode_frame(avctx, &ctx->decoder, avpkt->data, avpkt->size); |
| 245 | if (ret) |
| 246 | return ret; |
| 247 | |
| 248 | side_data = av_packet_get_side_data(avpkt, |
| 249 | AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, |
| 250 | &side_data_size); |
| 251 | if (side_data_size >= 8) { |
| 252 | const uint64_t additional_id = AV_RB64(side_data); |
| 253 | side_data += 8; |
| 254 | side_data_size -= 8; |
| 255 | if (additional_id == 1) { // 1 stands for alpha channel data. |
| 256 | if (!ctx->has_alpha_channel) { |
| 257 | ctx->has_alpha_channel = 1; |
| 258 | ret = vpx_init(avctx, &ctx->decoder_alpha); |
| 259 | if (ret) |
| 260 | return ret; |
| 261 | } |
| 262 | ret = decode_frame(avctx, &ctx->decoder_alpha, side_data, |
| 263 | side_data_size); |
| 264 | if (ret) |
| 265 | return ret; |
| 266 | } |
| 267 | } |
| 268 | |
| 269 | if ((img = vpx_codec_get_frame(&ctx->decoder, &iter)) && |
| 270 | (!ctx->has_alpha_channel || |
| 271 | (img_alpha = vpx_codec_get_frame(&ctx->decoder_alpha, &iter_alpha)))) { |
| 272 | uint8_t *planes[4]; |
| 273 | int linesizes[4]; |
| 274 | |
| 275 | if (img->d_w > img->w || img->d_h > img->h) { |
| 276 | av_log(avctx, AV_LOG_ERROR, "Display dimensions %dx%d exceed storage %dx%d\n", |
| 277 | img->d_w, img->d_h, img->w, img->h); |
| 278 | return AVERROR_EXTERNAL; |
| 279 | } |
| 280 | |
| 281 | if ((ret = set_pix_fmt(avctx, img, ctx->has_alpha_channel)) < 0) { |
| 282 | av_log(avctx, AV_LOG_ERROR, "Unsupported output colorspace (%d) / bit_depth (%d)\n", |
| 283 | img->fmt, img->bit_depth); |
| 284 | return ret; |
| 285 | } |
| 286 | |
| 287 | if ((int) img->d_w != avctx->width || (int) img->d_h != avctx->height) { |
| 288 | av_log(avctx, AV_LOG_INFO, "dimension change! %dx%d -> %dx%d\n", |
| 289 | avctx->width, avctx->height, img->d_w, img->d_h); |
| 290 | ret = ff_set_dimensions(avctx, img->d_w, img->d_h); |
nothing calls this directly
no test coverage detected