| 389 | } |
| 390 | |
| 391 | static int hnm_decode_frame(AVCodecContext *avctx, AVFrame *frame, |
| 392 | int *got_frame, AVPacket *avpkt) |
| 393 | { |
| 394 | Hnm4VideoContext *hnm = avctx->priv_data; |
| 395 | int ret; |
| 396 | uint16_t chunk_id; |
| 397 | |
| 398 | if (avpkt->size < 8) { |
| 399 | av_log(avctx, AV_LOG_ERROR, "packet too small\n"); |
| 400 | return AVERROR_INVALIDDATA; |
| 401 | } |
| 402 | |
| 403 | chunk_id = AV_RL16(avpkt->data + 4); |
| 404 | |
| 405 | if (chunk_id == HNM4_CHUNK_ID_PL) { |
| 406 | hnm_update_palette(avctx, avpkt->data, avpkt->size); |
| 407 | } else if (chunk_id == HNM4_CHUNK_ID_IZ) { |
| 408 | if (avpkt->size < 12) { |
| 409 | av_log(avctx, AV_LOG_ERROR, "packet too small\n"); |
| 410 | return AVERROR_INVALIDDATA; |
| 411 | } |
| 412 | if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) |
| 413 | return ret; |
| 414 | |
| 415 | unpack_intraframe(avctx, avpkt->data + 12, avpkt->size - 12); |
| 416 | memcpy(hnm->previous, hnm->current, hnm->width * hnm->height); |
| 417 | if (hnm->version == 0x4a) |
| 418 | memcpy(hnm->processed, hnm->current, hnm->width * hnm->height); |
| 419 | else |
| 420 | postprocess_current_frame(avctx); |
| 421 | copy_processed_frame(avctx, frame); |
| 422 | frame->pict_type = AV_PICTURE_TYPE_I; |
| 423 | frame->flags |= AV_FRAME_FLAG_KEY; |
| 424 | memcpy(frame->data[1], hnm->palette, 256 * 4); |
| 425 | *got_frame = 1; |
| 426 | } else if (chunk_id == HNM4_CHUNK_ID_IU) { |
| 427 | if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) |
| 428 | return ret; |
| 429 | |
| 430 | if (hnm->version == 0x4a) { |
| 431 | decode_interframe_v4a(avctx, avpkt->data + 8, avpkt->size - 8); |
| 432 | memcpy(hnm->processed, hnm->current, hnm->width * hnm->height); |
| 433 | } else { |
| 434 | int ret = decode_interframe_v4(avctx, avpkt->data + 8, avpkt->size - 8); |
| 435 | if (ret < 0) |
| 436 | return ret; |
| 437 | postprocess_current_frame(avctx); |
| 438 | } |
| 439 | copy_processed_frame(avctx, frame); |
| 440 | frame->pict_type = AV_PICTURE_TYPE_P; |
| 441 | frame->flags &= ~AV_FRAME_FLAG_KEY; |
| 442 | memcpy(frame->data[1], hnm->palette, 256 * 4); |
| 443 | *got_frame = 1; |
| 444 | FFSWAP(uint8_t *, hnm->current, hnm->previous); |
| 445 | } else { |
| 446 | av_log(avctx, AV_LOG_ERROR, "invalid chunk id: %d\n", chunk_id); |
| 447 | return AVERROR_INVALIDDATA; |
| 448 | } |
nothing calls this directly
no test coverage detected