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 | int64_t picture_number; | 125 | int64_t picture_number; |
| 126 | int key_frame; | 126 | int key_frame; |
| 127 | ProgressFrame picture, last_picture; | 127 | ProgressFrame picture, last_picture; |
| 128 | void *hwaccel_picture_private, *hwaccel_last_picture_private; | ||
| 128 | uint32_t crcref; | 129 | uint32_t crcref; |
| 129 | enum AVPixelFormat pix_fmt; | 130 | enum AVPixelFormat pix_fmt; |
| 131 | enum AVPixelFormat configured_pix_fmt; | ||
| 130 | 132 | ||
| 131 | const AVFrame *cur_enc_frame; | 133 | const AVFrame *cur_enc_frame; |
| 132 | int plane_count; | 134 | int plane_count; |
| @@ -41,6 +41,9 @@ · 40 unmodified lines | |||
| 41 | #include "libavutil/refstruct.h" | 41 | #include "libavutil/refstruct.h" |
| 42 | #include "thread.h" | 42 | #include "thread.h" |
| 43 | #include "decode.h" | 43 | #include "decode.h" |
| 44 | #include "hwconfig.h" | ||
| 45 | #include "hwaccel_internal.h" | ||
| 46 | #include "config_components.h" | ||
| 44 | 47 | ||
| 45 | static inline int get_vlc_symbol(GetBitContext *gb, VlcState *const state, | 48 | static inline int get_vlc_symbol(GetBitContext *gb, VlcState *const state, |
| 46 | int bits) | 49 | int bits) |
| @@ -403,9 +406,12 @@ static int read_header(FFV1Context *f, RangeCoder *c) · 356 unmodified lines | |||
| 403 | if (ret < 0) | 406 | if (ret < 0) |
| 404 | return ret; | 407 | return ret; |
| 405 | 408 | ||
| 406 | f->avctx->pix_fmt = get_pixel_format(f); | 409 | if (f->configured_pix_fmt != f->pix_fmt) { |
| 407 | if (f->avctx->pix_fmt < 0) | 410 | f->avctx->pix_fmt = get_pixel_format(f); |
| 408 | return AVERROR(EINVAL); | 411 | if (f->avctx->pix_fmt < 0) |
| 412 | return AVERROR(EINVAL); | ||
| 413 | f->configured_pix_fmt = f->pix_fmt; | ||
| 414 | } | ||
| 409 | 415 | ||
| 410 | ff_dlog(f->avctx, "%d %d %d\n", | 416 | ff_dlog(f->avctx, "%d %d %d\n", |
| 411 | f->chroma_h_shift, f->chroma_v_shift, f->pix_fmt); | 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 | FFV1Context *f = avctx->priv_data; | 504 | FFV1Context *f = avctx->priv_data; |
| 499 | int ret; | 505 | int ret; |
| 500 | 506 | ||
| 507 | f->pix_fmt = AV_PIX_FMT_NONE; | ||
| 508 | f->configured_pix_fmt = AV_PIX_FMT_NONE; | ||
| 509 | |||
| 501 | if ((ret = ff_ffv1_common_init(avctx, f)) < 0) | 510 | if ((ret = ff_ffv1_common_init(avctx, f)) < 0) |
| 502 | return ret; | 511 | return ret; |
| 503 | 512 | ||
| @@ -682,13 +691,16 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, · 178 unmodified lines | |||
| 682 | FFV1Context *f = avctx->priv_data; | 691 | FFV1Context *f = avctx->priv_data; |
| 683 | int ret; | 692 | int ret; |
| 684 | AVFrame *p; | 693 | AVFrame *p; |
| 694 | const FFHWAccel *hwaccel = NULL; | ||
| 685 | 695 | ||
| 686 | /* This is copied onto the first slice's range coder context */ | 696 | /* This is copied onto the first slice's range coder context */ |
| 687 | RangeCoder c; | 697 | RangeCoder c; |
| 688 | 698 | ||
| 689 | ff_progress_frame_unref(&f->last_picture); | 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 | f->avctx = avctx; | 705 | f->avctx = avctx; |
| 694 | f->frame_damaged = 0; | 706 | f->frame_damaged = 0; |
| @@ -704,11 +716,18 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, · 9 unmodified lines | |||
| 704 | if (avctx->skip_frame >= AVDISCARD_ALL) | 716 | if (avctx->skip_frame >= AVDISCARD_ALL) |
| 705 | return avpkt->size; | 717 | return avpkt->size; |
| 706 | 718 | ||
| 719 | if (avctx->hwaccel) | ||
| 720 | hwaccel = ffhwaccel(avctx->hwaccel); | ||
| 721 | |||
| 707 | ret = ff_progress_frame_get_buffer(avctx, &f->picture, | 722 | ret = ff_progress_frame_get_buffer(avctx, &f->picture, |
| 708 | AV_GET_BUFFER_FLAG_REF); | 723 | AV_GET_BUFFER_FLAG_REF); |
| 709 | if (ret < 0) | 724 | if (ret < 0) |
| 710 | return ret; | 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 | p = f->picture.f; | 731 | p = f->picture.f; |
| 713 | 732 | ||
| 714 | p->pict_type = AV_PICTURE_TYPE_I; //FIXME I vs. P | 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 | p->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; | 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 | ff_thread_finish_setup(avctx); | 750 | ff_thread_finish_setup(avctx); |
| 725 | 751 | ||
| 726 | ret = decode_slices(avctx, c, avpkt); | 752 | /* Decode slices */ |
| 727 | if (ret < 0) | 753 | if (hwaccel) { |
| 728 | return ret; | 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 | ff_progress_frame_report(&f->picture, INT_MAX); | 786 | ff_progress_frame_report(&f->picture, INT_MAX); |
| 731 | 787 | ||
| 732 | ff_progress_frame_unref(&f->last_picture); | 788 | ff_progress_frame_unref(&f->last_picture); |
| 789 | av_refstruct_unref(&f->hwaccel_last_picture_private); | ||
| 733 | if ((ret = av_frame_ref(rframe, f->picture.f)) < 0) | 790 | if ((ret = av_frame_ref(rframe, f->picture.f)) < 0) |
| 734 | return ret; | 791 | return ret; |
| 735 | 792 | ||
| @@ -758,6 +815,7 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src) · 22 unmodified lines | |||
| 758 | fdst->ac = fsrc->ac; | 815 | fdst->ac = fsrc->ac; |
| 759 | fdst->colorspace = fsrc->colorspace; | 816 | fdst->colorspace = fsrc->colorspace; |
| 760 | fdst->pix_fmt = fsrc->pix_fmt; | 817 | fdst->pix_fmt = fsrc->pix_fmt; |
| 818 | fdst->configured_pix_fmt = fsrc->configured_pix_fmt; | ||
| 761 | 819 | ||
| 762 | fdst->ec = fsrc->ec; | 820 | fdst->ec = fsrc->ec; |
| 763 | fdst->intra = fsrc->intra; | 821 | fdst->intra = fsrc->intra; |
| @@ -793,6 +851,8 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src) · 29 unmodified lines | |||
| 793 | av_assert1(fdst->max_slice_count == fsrc->max_slice_count); | 851 | av_assert1(fdst->max_slice_count == fsrc->max_slice_count); |
| 794 | 852 | ||
| 795 | ff_progress_frame_replace(&fdst->picture, &fsrc->picture); | 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 | return 0; | 857 | return 0; |
| 798 | } | 858 | } |
| @@ -803,8 +863,10 @@ static av_cold int ffv1_decode_close(AVCodecContext *avctx) · 4 unmodified lines | |||
| 803 | FFV1Context *const s = avctx->priv_data; | 863 | FFV1Context *const s = avctx->priv_data; |
| 804 | 864 | ||
| 805 | ff_progress_frame_unref(&s->picture); | 865 | ff_progress_frame_unref(&s->picture); |
| 866 | av_refstruct_unref(&s->hwaccel_picture_private); | ||
| 867 | |||
| 806 | ff_progress_frame_unref(&s->last_picture); | 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 | ff_ffv1_close(s); | 871 | ff_ffv1_close(s); |
| 810 | 872 | ||
| @@ -826,4 +888,7 @@ const FFCodec ff_ffv1_decoder = { · 15 unmodified lines | |||
| 826 | .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | | 888 | .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | |
| 827 | FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | | 889 | FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | |
| 828 | FF_CODEC_CAP_USES_PROGRESSFRAMES, | 890 | FF_CODEC_CAP_USES_PROGRESSFRAMES, |
| 891 | .hw_configs = (const AVCodecHWConfigInternal *const []) { | ||
| 892 | NULL | ||
| 893 | }, | ||
| 829 | }; | 894 | }; |