This commit adds support for hardware accelerated decoding to the decoder. The previous commits already refactored the decoder, this commit simply adds calls to hooks to decode.
Unified · Split
| @@ -125,8 +125,10 @@ typedef struct FFV1Context { · 124 unmodified lines | ||
| 125 | 125 | int64_t picture_number; |
| 126 | 126 | int key_frame; |
| 127 | 127 | ProgressFrame picture, last_picture; |
| 128 | + void *hwaccel_picture_private, *hwaccel_last_picture_private; | |
| 128 | 129 | uint32_t crcref; |
| 129 | 130 | enum AVPixelFormat pix_fmt; |
| 131 | + enum AVPixelFormat configured_pix_fmt; | |
| 130 | 132 | |
| 131 | 133 | const AVFrame *cur_enc_frame; |
| 132 | 134 | int plane_count; |
| @@ -41,6 +41,9 @@ · 40 unmodified lines | ||
| 41 | 41 | #include "libavutil/refstruct.h" |
| 42 | 42 | #include "thread.h" |
| 43 | 43 | #include "decode.h" |
| 44 | +#include "hwconfig.h" | |
| 45 | +#include "hwaccel_internal.h" | |
| 46 | +#include "config_components.h" | |
| 44 | 47 | |
| 45 | 48 | static inline int get_vlc_symbol(GetBitContext *gb, VlcState *const state, |
| 46 | 49 | int bits) |
| @@ -403,9 +406,12 @@ static int read_header(FFV1Context *f, RangeCoder *c) · 356 unmodified lines | ||
| 403 | 406 | if (ret < 0) |
| 404 | 407 | return ret; |
| 405 | 408 | |
| 406 | − f->avctx->pix_fmt = get_pixel_format(f); | |
| 407 | − if (f->avctx->pix_fmt < 0) | |
| 408 | − return AVERROR(EINVAL); | |
| 409 | + if (f->configured_pix_fmt != f->pix_fmt) { | |
| 410 | + f->avctx->pix_fmt = get_pixel_format(f); | |
| 411 | + if (f->avctx->pix_fmt < 0) | |
| 412 | + return AVERROR(EINVAL); | |
| 413 | + f->configured_pix_fmt = f->pix_fmt; | |
| 414 | + } | |
| 409 | 415 | |
| 410 | 416 | ff_dlog(f->avctx, "%d %d %d\n", |
| 411 | 417 | f->chroma_h_shift, f->chroma_v_shift, f->pix_fmt); |
| @@ -498,6 +504,9 @@ static av_cold int decode_init(AVCodecContext *avctx) · 86 unmodified lines | ||
| 498 | 504 | FFV1Context *f = avctx->priv_data; |
| 499 | 505 | int ret; |
| 500 | 506 | |
| 507 | + f->pix_fmt = AV_PIX_FMT_NONE; | |
| 508 | + f->configured_pix_fmt = AV_PIX_FMT_NONE; | |
| 509 | + | |
| 501 | 510 | if ((ret = ff_ffv1_common_init(avctx, f)) < 0) |
| 502 | 511 | return ret; |
| 503 | 512 | |
| @@ -682,13 +691,16 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, · 178 unmodified lines | ||
| 682 | 691 | FFV1Context *f = avctx->priv_data; |
| 683 | 692 | int ret; |
| 684 | 693 | AVFrame *p; |
| 694 | + const FFHWAccel *hwaccel = NULL; | |
| 685 | 695 | |
| 686 | 696 | /* This is copied onto the first slice's range coder context */ |
| 687 | 697 | RangeCoder c; |
| 688 | 698 | |
| 689 | 699 | ff_progress_frame_unref(&f->last_picture); |
| 690 | − FFSWAP(ProgressFrame, f->picture, f->last_picture); | |
| 700 | + av_refstruct_unref(&f->hwaccel_last_picture_private); | |
| 691 | 701 | |
| 702 | + FFSWAP(ProgressFrame, f->picture, f->last_picture); | |
| 703 | + FFSWAP(void *, f->hwaccel_picture_private, f->hwaccel_last_picture_private); | |
| 692 | 704 | |
| 693 | 705 | f->avctx = avctx; |
| 694 | 706 | f->frame_damaged = 0; |
| @@ -704,11 +716,18 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, · 9 unmodified lines | ||
| 704 | 716 | if (avctx->skip_frame >= AVDISCARD_ALL) |
| 705 | 717 | return avpkt->size; |
| 706 | 718 | |
| 719 | + if (avctx->hwaccel) | |
| 720 | + hwaccel = ffhwaccel(avctx->hwaccel); | |
| 721 | + | |
| 707 | 722 | ret = ff_progress_frame_get_buffer(avctx, &f->picture, |
| 708 | 723 | AV_GET_BUFFER_FLAG_REF); |
| 709 | 724 | if (ret < 0) |
| 710 | 725 | return ret; |
| 711 | 726 | |
| 727 | + ret = ff_hwaccel_frame_priv_alloc(avctx, &f->hwaccel_picture_private); | |
| 728 | + if (ret < 0) | |
| 729 | + return ret; | |
| 730 | + | |
| 712 | 731 | p = f->picture.f; |
| 713 | 732 | |
| 714 | 733 | p->pict_type = AV_PICTURE_TYPE_I; //FIXME I vs. P |
| @@ -721,15 +740,53 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, · 6 unmodified lines | ||
| 721 | 740 | p->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; |
| 722 | 741 | } |
| 723 | 742 | |
| 743 | + /* Start */ | |
| 744 | + if (hwaccel) { | |
| 745 | + ret = hwaccel->start_frame(avctx, avpkt->data, avpkt->size); | |
| 746 | + if (ret < 0) | |
| 747 | + return ret; | |
| 748 | + } | |
| 749 | + | |
| 724 | 750 | ff_thread_finish_setup(avctx); |
| 725 | 751 | |
| 726 | − ret = decode_slices(avctx, c, avpkt); | |
| 727 | − if (ret < 0) | |
| 728 | − return ret; | |
| 752 | + /* Decode slices */ | |
| 753 | + if (hwaccel) { | |
| 754 | + uint8_t *buf_end = avpkt->data + avpkt->size; | |
| 755 | + | |
| 756 | + if (!(p->flags & AV_FRAME_FLAG_KEY) && f->last_picture.f) | |
| 757 | + ff_progress_frame_await(&f->last_picture, f->slice_count - 1); | |
| 758 | + | |
| 759 | + for (int i = f->slice_count - 1; i >= 0; i--) { | |
| 760 | + uint8_t *pos; | |
| 761 | + uint32_t len; | |
| 762 | + ret = find_next_slice(avctx, avpkt->data, buf_end, i, | |
| 763 | + &pos, &len); | |
| 764 | + if (ret < 0) | |
| 765 | + return ret; | |
| 766 | + | |
| 767 | + buf_end -= len; | |
| 768 | + | |
| 769 | + ret = hwaccel->decode_slice(avctx, pos, len); | |
| 770 | + if (ret < 0) | |
| 771 | + return ret; | |
| 772 | + } | |
| 773 | + } else { | |
| 774 | + ret = decode_slices(avctx, c, avpkt); | |
| 775 | + if (ret < 0) | |
| 776 | + return ret; | |
| 777 | + } | |
| 778 | + | |
| 779 | + /* Finalize */ | |
| 780 | + if (hwaccel) { | |
| 781 | + ret = hwaccel->end_frame(avctx); | |
| 782 | + if (ret < 0) | |
| 783 | + return ret; | |
| 784 | + } | |
| 729 | 785 | |
| 730 | 786 | ff_progress_frame_report(&f->picture, INT_MAX); |
| 731 | 787 | |
| 732 | 788 | ff_progress_frame_unref(&f->last_picture); |
| 789 | + av_refstruct_unref(&f->hwaccel_last_picture_private); | |
| 733 | 790 | if ((ret = av_frame_ref(rframe, f->picture.f)) < 0) |
| 734 | 791 | return ret; |
| 735 | 792 | |
| @@ -758,6 +815,7 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src) · 22 unmodified lines | ||
| 758 | 815 | fdst->ac = fsrc->ac; |
| 759 | 816 | fdst->colorspace = fsrc->colorspace; |
| 760 | 817 | fdst->pix_fmt = fsrc->pix_fmt; |
| 818 | + fdst->configured_pix_fmt = fsrc->configured_pix_fmt; | |
| 761 | 819 | |
| 762 | 820 | fdst->ec = fsrc->ec; |
| 763 | 821 | fdst->intra = fsrc->intra; |
| @@ -793,6 +851,8 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src) · 29 unmodified lines | ||
| 793 | 851 | av_assert1(fdst->max_slice_count == fsrc->max_slice_count); |
| 794 | 852 | |
| 795 | 853 | ff_progress_frame_replace(&fdst->picture, &fsrc->picture); |
| 854 | + av_refstruct_replace(&fdst->hwaccel_picture_private, | |
| 855 | + fsrc->hwaccel_picture_private); | |
| 796 | 856 | |
| 797 | 857 | return 0; |
| 798 | 858 | } |
| @@ -803,8 +863,10 @@ static av_cold int ffv1_decode_close(AVCodecContext *avctx) · 4 unmodified lines | ||
| 803 | 863 | FFV1Context *const s = avctx->priv_data; |
| 804 | 864 | |
| 805 | 865 | ff_progress_frame_unref(&s->picture); |
| 866 | + av_refstruct_unref(&s->hwaccel_picture_private); | |
| 867 | + | |
| 806 | 868 | ff_progress_frame_unref(&s->last_picture); |
| 807 | − av_freep(&avctx->stats_out); | |
| 869 | + av_refstruct_unref(&s->hwaccel_last_picture_private); | |
| 808 | 870 | |
| 809 | 871 | ff_ffv1_close(s); |
| 810 | 872 | |
| @@ -826,4 +888,7 @@ const FFCodec ff_ffv1_decoder = { · 15 unmodified lines | ||
| 826 | 888 | .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | |
| 827 | 889 | FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | |
| 828 | 890 | FF_CODEC_CAP_USES_PROGRESSFRAMES, |
| 891 | + .hw_configs = (const AVCodecHWConfigInternal *const []) { | |
| 892 | + NULL | |
| 893 | + }, | |
| 829 | 894 | }; |