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.
Showing the changes to libavcodec (2 of 2 files). Show all
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 | }; |