| @@ -158,16 +158,10 @@ static int vaapi_encode_issue(AVCodecContext *avctx, · 157 unmodified lines |
| 158 | 158 | av_log(avctx, AV_LOG_DEBUG, ".\n"); |
| 159 | 159 | } |
| 160 | 160 | |
| 161 | | − av_assert0(pic->input_available && !pic->encode_issued); |
| 161 | + av_assert0(!pic->encode_issued); |
| 162 | 162 | for (i = 0; i < pic->nb_refs; i++) { |
| 163 | 163 | av_assert0(pic->refs[i]); |
| 164 | | − // If we are serialised then the references must have already |
| 165 | | − // completed. If not, they must have been issued but need not |
| 166 | | − // have completed yet. |
| 167 | | − if (ctx->issue_mode == ISSUE_MODE_SERIALISE_EVERYTHING) |
| 168 | | − av_assert0(pic->refs[i]->encode_complete); |
| 169 | | − else |
| 170 | | − av_assert0(pic->refs[i]->encode_issued); |
| 164 | + av_assert0(pic->refs[i]->encode_issued); |
| 171 | 165 | } |
| 172 | 166 | |
| 173 | 167 | av_log(avctx, AV_LOG_DEBUG, "Input surface is %#x.\n", pic->input_surface); |
| @@ -466,10 +460,7 @@ static int vaapi_encode_issue(AVCodecContext *avctx, · 292 unmodified lines |
| 466 | 460 | |
| 467 | 461 | pic->encode_issued = 1; |
| 468 | 462 | |
| 469 | | − if (ctx->issue_mode == ISSUE_MODE_SERIALISE_EVERYTHING) |
| 470 | | − return vaapi_encode_wait(avctx, pic); |
| 471 | | − else |
| 472 | | − return 0; |
| 463 | + return 0; |
| 473 | 464 | |
| 474 | 465 | fail_with_picture: |
| 475 | 466 | vaEndPicture(ctx->hwctx->display, ctx->va_context); |
| @@ -626,315 +617,330 @@ static int vaapi_encode_free(AVCodecContext *avctx, · 150 unmodified lines |
| 626 | 617 | return 0; |
| 627 | 618 | } |
| 628 | 619 | |
| 629 | | −static int vaapi_encode_step(AVCodecContext *avctx, |
| 630 | | − VAAPIEncodePicture *target) |
| 620 | +static void vaapi_encode_add_ref(AVCodecContext *avctx, |
| 621 | + VAAPIEncodePicture *pic, |
| 622 | + VAAPIEncodePicture *target, |
| 623 | + int is_ref, int in_dpb, int prev) |
| 631 | 624 | { |
| 632 | | − VAAPIEncodeContext *ctx = avctx->priv_data; |
| 633 | | − VAAPIEncodePicture *pic; |
| 634 | | − int i, err; |
| 625 | + int refs = 0; |
| 635 | 626 | |
| 636 | | − if (ctx->issue_mode == ISSUE_MODE_SERIALISE_EVERYTHING || |
| 637 | | − ctx->issue_mode == ISSUE_MODE_MINIMISE_LATENCY) { |
| 638 | | − // These two modes are equivalent, except that we wait for |
| 639 | | − // immediate completion on each operation if serialised. |
| 640 | | − |
| 641 | | − if (!target) { |
| 642 | | − // No target, nothing to do yet. |
| 643 | | − return 0; |
| 644 | | − } |
| 645 | | − |
| 646 | | − if (target->encode_complete) { |
| 647 | | − // Already done. |
| 648 | | − return 0; |
| 649 | | − } |
| 650 | | − |
| 651 | | − pic = target; |
| 652 | | − for (i = 0; i < pic->nb_refs; i++) { |
| 653 | | − if (!pic->refs[i]->encode_complete) { |
| 654 | | − err = vaapi_encode_step(avctx, pic->refs[i]); |
| 655 | | − if (err < 0) |
| 656 | | − return err; |
| 657 | | − } |
| 658 | | − } |
| 659 | | − |
| 660 | | − err = vaapi_encode_issue(avctx, pic); |
| 661 | | − if (err < 0) |
| 662 | | − return err; |
| 663 | | − |
| 664 | | − } else if (ctx->issue_mode == ISSUE_MODE_MAXIMISE_THROUGHPUT) { |
| 665 | | − int activity; |
| 666 | | − |
| 667 | | − // Run through the list of all available pictures repeatedly |
| 668 | | − // and issue the first one found which has all dependencies |
| 669 | | − // available (including previously-issued but not necessarily |
| 670 | | − // completed pictures). |
| 671 | | − do { |
| 672 | | − activity = 0; |
| 673 | | − for (pic = ctx->pic_start; pic; pic = pic->next) { |
| 674 | | − if (!pic->input_available || pic->encode_issued) |
| 675 | | − continue; |
| 676 | | − for (i = 0; i < pic->nb_refs; i++) { |
| 677 | | − if (!pic->refs[i]->encode_issued) |
| 678 | | − break; |
| 679 | | − } |
| 680 | | − if (i < pic->nb_refs) |
| 681 | | − continue; |
| 682 | | − err = vaapi_encode_issue(avctx, pic); |
| 683 | | − if (err < 0) |
| 684 | | − return err; |
| 685 | | − activity = 1; |
| 686 | | − // Start again from the beginning of the list, |
| 687 | | − // because issuing this picture may have satisfied |
| 688 | | − // forward dependencies of earlier ones. |
| 689 | | − break; |
| 690 | | − } |
| 691 | | − } while(activity); |
| 627 | + if (is_ref) { |
| 628 | + av_assert0(pic != target); |
| 629 | + av_assert0(pic->nb_refs < MAX_PICTURE_REFERENCES); |
| 630 | + pic->refs[pic->nb_refs++] = target; |
| 631 | + ++refs; |
| 632 | + } |
| 692 | 633 | |
| 693 | | − // If we had a defined target for this step then it will |
| 694 | | − // always have been issued by now. |
| 695 | | − if (target) { |
| 696 | | − av_assert0(target->encode_issued && "broken dependencies?"); |
| 697 | | − } |
| 634 | + if (in_dpb) { |
| 635 | + av_assert0(pic->nb_dpb_pics < MAX_DPB_SIZE); |
| 636 | + pic->dpb[pic->nb_dpb_pics++] = target; |
| 637 | + ++refs; |
| 638 | + } |
| 698 | 639 | |
| 699 | | − } else { |
| 700 | | − av_assert0(0); |
| 640 | + if (prev) { |
| 641 | + av_assert0(!pic->prev); |
| 642 | + pic->prev = target; |
| 643 | + ++refs; |
| 701 | 644 | } |
| 702 | 645 | |
| 703 | | − return 0; |
| 646 | + target->ref_count[0] += refs; |
| 647 | + target->ref_count[1] += refs; |
| 704 | 648 | } |
| 705 | 649 | |
| 706 | | −static int vaapi_encode_get_next(AVCodecContext *avctx, |
| 707 | | − VAAPIEncodePicture **pic_out) |
| 650 | +static void vaapi_encode_remove_refs(AVCodecContext *avctx, |
| 651 | + VAAPIEncodePicture *pic, |
| 652 | + int level) |
| 708 | 653 | { |
| 709 | | − VAAPIEncodeContext *ctx = avctx->priv_data; |
| 710 | | − VAAPIEncodePicture *start, *end, *pic; |
| 711 | 654 | int i; |
| 712 | 655 | |
| 713 | | − for (pic = ctx->pic_start; pic; pic = pic->next) { |
| 714 | | − if (pic->next) |
| 715 | | − av_assert0(pic->display_order + 1 == pic->next->display_order); |
| 716 | | − if (pic->display_order == ctx->input_order) { |
| 717 | | − *pic_out = pic; |
| 718 | | − return 0; |
| 719 | | − } |
| 656 | + if (pic->ref_removed[level]) |
| 657 | + return; |
| 658 | + |
| 659 | + for (i = 0; i < pic->nb_refs; i++) { |
| 660 | + av_assert0(pic->refs[i]); |
| 661 | + --pic->refs[i]->ref_count[level]; |
| 662 | + av_assert0(pic->refs[i]->ref_count[level] >= 0); |
| 720 | 663 | } |
| 721 | 664 | |
| 722 | | − pic = vaapi_encode_alloc(avctx); |
| 723 | | − if (!pic) |
| 724 | | − return AVERROR(ENOMEM); |
| 665 | + for (i = 0; i < pic->nb_dpb_pics; i++) { |
| 666 | + av_assert0(pic->dpb[i]); |
| 667 | + --pic->dpb[i]->ref_count[level]; |
| 668 | + av_assert0(pic->dpb[i]->ref_count[level] >= 0); |
| 669 | + } |
| 725 | 670 | |
| 726 | | − if (ctx->input_order == 0 || ctx->force_idr || |
| 727 | | − ctx->gop_counter >= ctx->gop_size) { |
| 728 | | − pic->type = PICTURE_TYPE_IDR; |
| 729 | | − ctx->force_idr = 0; |
| 730 | | − ctx->gop_counter = 1; |
| 731 | | − ctx->p_counter = 0; |
| 732 | | − } else if (ctx->p_counter >= ctx->p_per_i) { |
| 733 | | − pic->type = PICTURE_TYPE_I; |
| 734 | | − ++ctx->gop_counter; |
| 735 | | − ctx->p_counter = 0; |
| 736 | | − } else { |
| 737 | | − pic->type = PICTURE_TYPE_P; |
| 738 | | − pic->refs[0] = ctx->pic_end; |
| 739 | | − pic->nb_refs = 1; |
| 740 | | − ++ctx->gop_counter; |
| 741 | | − ++ctx->p_counter; |
| 671 | + av_assert0(pic->prev || pic->type == PICTURE_TYPE_IDR); |
| 672 | + if (pic->prev) { |
| 673 | + --pic->prev->ref_count[level]; |
| 674 | + av_assert0(pic->prev->ref_count[level] >= 0); |
| 742 | 675 | } |
| 743 | | − start = end = pic; |
| 744 | 676 | |
| 745 | | − if (pic->type != PICTURE_TYPE_IDR) { |
| 746 | | − // If that was not an IDR frame, add B-frames display-before and |
| 747 | | − // encode-after it, but not exceeding the GOP size. |
| 677 | + pic->ref_removed[level] = 1; |
| 678 | +} |
| 748 | 679 | |
| 749 | | − for (i = 0; i < ctx->b_per_p && |
| 750 | | − ctx->gop_counter < ctx->gop_size; i++) { |
| 751 | | − pic = vaapi_encode_alloc(avctx); |
| 752 | | − if (!pic) |
| 753 | | − goto fail; |
| 680 | +static void vaapi_encode_set_b_pictures(AVCodecContext *avctx, |
| 681 | + VAAPIEncodePicture *start, |
| 682 | + VAAPIEncodePicture *end, |
| 683 | + VAAPIEncodePicture *prev, |
| 684 | + int current_depth, |
| 685 | + VAAPIEncodePicture **last) |
| 686 | +{ |
| 687 | + VAAPIEncodeContext *ctx = avctx->priv_data; |
| 688 | + VAAPIEncodePicture *pic, *next, *ref; |
| 689 | + int i, len; |
| 754 | 690 | |
| 755 | | − pic->type = PICTURE_TYPE_B; |
| 756 | | − pic->refs[0] = ctx->pic_end; |
| 757 | | − pic->refs[1] = end; |
| 758 | | − pic->nb_refs = 2; |
| 691 | + av_assert0(start && end && start != end && start->next != end); |
| 759 | 692 | |
| 760 | | − pic->next = start; |
| 761 | | − pic->display_order = ctx->input_order + ctx->b_per_p - i - 1; |
| 762 | | − pic->encode_order = pic->display_order + 1; |
| 763 | | − start = pic; |
| 693 | + // If we are at the maximum depth then encode all pictures as |
| 694 | + // non-referenced B-pictures. Also do this if there is exactly one |
| 695 | + // picture left, since there will be nothing to reference it. |
| 696 | + if (current_depth == ctx->max_b_depth || start->next->next == end) { |
| 697 | + for (pic = start->next; pic; pic = pic->next) { |
| 698 | + if (pic == end) |
| 699 | + break; |
| 700 | + pic->type = PICTURE_TYPE_B; |
| 701 | + pic->b_depth = current_depth; |
| 702 | + |
| 703 | + vaapi_encode_add_ref(avctx, pic, start, 1, 1, 0); |
| 704 | + vaapi_encode_add_ref(avctx, pic, end, 1, 1, 0); |
| 705 | + vaapi_encode_add_ref(avctx, pic, prev, 0, 0, 1); |
| 764 | 706 | |
| 765 | | − ++ctx->gop_counter; |
| 707 | + for (ref = end->refs[1]; ref; ref = ref->refs[1]) |
| 708 | + vaapi_encode_add_ref(avctx, pic, ref, 0, 1, 0); |
| 766 | 709 | } |
| 767 | | − } |
| 710 | + *last = prev; |
| 768 | 711 | |
| 769 | | − if (ctx->input_order == 0) { |
| 770 | | − pic->display_order = 0; |
| 771 | | − pic->encode_order = 0; |
| 712 | + } else { |
| 713 | + // Split the current list at the midpoint with a referenced |
| 714 | + // B-picture, then descend into each side separately. |
| 715 | + len = 0; |
| 716 | + for (pic = start->next; pic != end; pic = pic->next) |
| 717 | + ++len; |
| 718 | + for (pic = start->next, i = 1; 2 * i < len; pic = pic->next, i++); |
| 772 | 719 | |
| 773 | | − ctx->pic_start = ctx->pic_end = pic; |
| 720 | + pic->type = PICTURE_TYPE_B; |
| 721 | + pic->b_depth = current_depth; |
| 774 | 722 | |
| 775 | | − } else { |
| 776 | | − for (i = 0, pic = start; pic; i++, pic = pic->next) { |
| 777 | | − pic->display_order = ctx->input_order + i; |
| 778 | | − if (end->type == PICTURE_TYPE_IDR) |
| 779 | | − pic->encode_order = ctx->input_order + i; |
| 780 | | − else if (pic == end) |
| 781 | | − pic->encode_order = ctx->input_order; |
| 782 | | − else |
| 783 | | − pic->encode_order = ctx->input_order + i + 1; |
| 784 | | − } |
| 723 | + pic->is_reference = 1; |
| 785 | 724 | |
| 786 | | − av_assert0(ctx->pic_end); |
| 787 | | − ctx->pic_end->next = start; |
| 788 | | − ctx->pic_end = end; |
| 789 | | − } |
| 790 | | − *pic_out = start; |
| 725 | + vaapi_encode_add_ref(avctx, pic, pic, 0, 1, 0); |
| 726 | + vaapi_encode_add_ref(avctx, pic, start, 1, 1, 0); |
| 727 | + vaapi_encode_add_ref(avctx, pic, end, 1, 1, 0); |
| 728 | + vaapi_encode_add_ref(avctx, pic, prev, 0, 0, 1); |
| 791 | 729 | |
| 792 | | − av_log(avctx, AV_LOG_DEBUG, "Pictures:"); |
| 793 | | − for (pic = ctx->pic_start; pic; pic = pic->next) { |
| 794 | | − av_log(avctx, AV_LOG_DEBUG, " %s (%"PRId64"/%"PRId64")", |
| 795 | | − picture_type_name[pic->type], |
| 796 | | − pic->display_order, pic->encode_order); |
| 797 | | − } |
| 798 | | − av_log(avctx, AV_LOG_DEBUG, "\n"); |
| 730 | + for (ref = end->refs[1]; ref; ref = ref->refs[1]) |
| 731 | + vaapi_encode_add_ref(avctx, pic, ref, 0, 1, 0); |
| 799 | 732 | |
| 800 | | − return 0; |
| 733 | + if (i > 1) |
| 734 | + vaapi_encode_set_b_pictures(avctx, start, pic, pic, |
| 735 | + current_depth + 1, &next); |
| 736 | + else |
| 737 | + next = pic; |
| 801 | 738 | |
| 802 | | −fail: |
| 803 | | − while (start) { |
| 804 | | − pic = start->next; |
| 805 | | − vaapi_encode_free(avctx, start); |
| 806 | | − start = pic; |
| 739 | + vaapi_encode_set_b_pictures(avctx, pic, end, next, |
| 740 | + current_depth + 1, last); |
| 807 | 741 | } |
| 808 | | − return AVERROR(ENOMEM); |
| 809 | 742 | } |
| 810 | 743 | |
| 811 | | −static int vaapi_encode_truncate_gop(AVCodecContext *avctx) |
| 744 | +static int vaapi_encode_pick_next(AVCodecContext *avctx, |
| 745 | + VAAPIEncodePicture **pic_out) |
| 812 | 746 | { |
| 813 | 747 | VAAPIEncodeContext *ctx = avctx->priv_data; |
| 814 | | − VAAPIEncodePicture *pic, *last_pic, *next; |
| 748 | + VAAPIEncodePicture *pic = NULL, *next, *start; |
| 749 | + int i, b_counter, closed_gop_end; |
| 815 | 750 | |
| 816 | | − av_assert0(!ctx->pic_start || ctx->pic_start->input_available); |
| 817 | | − |
| 818 | | − // Find the last picture we actually have input for. |
| 751 | + // If there are any B-frames already queued, the next one to encode |
| 752 | + // is the earliest not-yet-issued frame for which all references are |
| 753 | + // available. |
| 819 | 754 | for (pic = ctx->pic_start; pic; pic = pic->next) { |
| 820 | | − if (!pic->input_available) |
| 755 | + if (pic->encode_issued) |
| 756 | + continue; |
| 757 | + if (pic->type != PICTURE_TYPE_B) |
| 758 | + continue; |
| 759 | + for (i = 0; i < pic->nb_refs; i++) { |
| 760 | + if (!pic->refs[i]->encode_issued) |
| 761 | + break; |
| 762 | + } |
| 763 | + if (i == pic->nb_refs) |
| 821 | 764 | break; |
| 822 | | − last_pic = pic; |
| 823 | 765 | } |
| 824 | 766 | |
| 825 | 767 | if (pic) { |
| 826 | | − if (last_pic->type == PICTURE_TYPE_B) { |
| 827 | | − // Some fixing up is required. Change the type of this |
| 828 | | − // picture to P, then modify preceding B references which |
| 829 | | − // point beyond it to point at it instead. |
| 830 | | − |
| 831 | | − last_pic->type = PICTURE_TYPE_P; |
| 832 | | − last_pic->encode_order = last_pic->refs[1]->encode_order; |
| 833 | | − |
| 834 | | − for (pic = ctx->pic_start; pic != last_pic; pic = pic->next) { |
| 835 | | − if (pic->type == PICTURE_TYPE_B && |
| 836 | | − pic->refs[1] == last_pic->refs[1]) |
| 837 | | − pic->refs[1] = last_pic; |
| 838 | | − } |
| 768 | + av_log(avctx, AV_LOG_DEBUG, "Pick B-picture at depth %d to " |
| 769 | + "encode next.\n", pic->b_depth); |
| 770 | + *pic_out = pic; |
| 771 | + return 0; |
| 772 | + } |
| 839 | 773 | |
| 840 | | − last_pic->nb_refs = 1; |
| 841 | | − last_pic->refs[1] = NULL; |
| 842 | | − } else { |
| 843 | | − // We can use the current structure (no references point |
| 844 | | − // beyond the end), but there are unused pics to discard. |
| 774 | + // Find the B-per-Pth available picture to become the next picture |
| 775 | + // on the top layer. |
| 776 | + start = NULL; |
| 777 | + b_counter = 0; |
| 778 | + closed_gop_end = ctx->closed_gop || |
| 779 | + ctx->idr_counter == ctx->gop_per_idr; |
| 780 | + for (pic = ctx->pic_start; pic; pic = next) { |
| 781 | + next = pic->next; |
| 782 | + if (pic->encode_issued) { |
| 783 | + start = pic; |
| 784 | + continue; |
| 845 | 785 | } |
| 786 | + // If the next available picture is force-IDR, encode it to start |
| 787 | + // a new GOP immediately. |
| 788 | + if (pic->force_idr) |
| 789 | + break; |
| 790 | + if (b_counter == ctx->b_per_p) |
| 791 | + break; |
| 792 | + // If this picture ends a closed GOP or starts a new GOP then it |
| 793 | + // needs to be in the top layer. |
| 794 | + if (ctx->gop_counter + b_counter + closed_gop_end >= ctx->gop_size) |
| 795 | + break; |
| 796 | + // If the picture after this one is force-IDR, we need to encode |
| 797 | + // this one in the top layer. |
| 798 | + if (next && next->force_idr) |
| 799 | + break; |
| 800 | + ++b_counter; |
| 801 | + } |
| 846 | 802 | |
| 847 | | − // Discard all following pics, they will never be used. |
| 848 | | − for (pic = last_pic->next; pic; pic = next) { |
| 849 | | − next = pic->next; |
| 850 | | − vaapi_encode_free(avctx, pic); |
| 851 | | − } |
| 803 | + // At the end of the stream the last picture must be in the top layer. |
| 804 | + if (!pic && ctx->end_of_stream) { |
| 805 | + --b_counter; |
| 806 | + pic = ctx->pic_end; |
| 807 | + if (pic->encode_issued) |
| 808 | + return AVERROR_EOF; |
| 809 | + } |
| 852 | 810 | |
| 853 | | − last_pic->next = NULL; |
| 854 | | − ctx->pic_end = last_pic; |
| 811 | + if (!pic) { |
| 812 | + av_log(avctx, AV_LOG_DEBUG, "Pick nothing to encode next - " |
| 813 | + "need more input for reference pictures.\n"); |
| 814 | + return AVERROR(EAGAIN); |
| 815 | + } |
| 816 | + if (ctx->input_order <= ctx->decode_delay && !ctx->end_of_stream) { |
| 817 | + av_log(avctx, AV_LOG_DEBUG, "Pick nothing to encode next - " |
| 818 | + "need more input for timestamps.\n"); |
| 819 | + return AVERROR(EAGAIN); |
| 820 | + } |
| 821 | + |
| 822 | + if (pic->force_idr) { |
| 823 | + av_log(avctx, AV_LOG_DEBUG, "Pick forced IDR-picture to " |
| 824 | + "encode next.\n"); |
| 825 | + pic->type = PICTURE_TYPE_IDR; |
| 826 | + ctx->idr_counter = 1; |
| 827 | + ctx->gop_counter = 1; |
| 828 | + |
| 829 | + } else if (ctx->gop_counter + b_counter >= ctx->gop_size) { |
| 830 | + if (ctx->idr_counter == ctx->gop_per_idr) { |
| 831 | + av_log(avctx, AV_LOG_DEBUG, "Pick new-GOP IDR-picture to " |
| 832 | + "encode next.\n"); |
| 833 | + pic->type = PICTURE_TYPE_IDR; |
| 834 | + ctx->idr_counter = 1; |
| 835 | + } else { |
| 836 | + av_log(avctx, AV_LOG_DEBUG, "Pick new-GOP I-picture to " |
| 837 | + "encode next.\n"); |
| 838 | + pic->type = PICTURE_TYPE_I; |
| 839 | + ++ctx->idr_counter; |
| 840 | + } |
| 841 | + ctx->gop_counter = 1; |
| 855 | 842 | |
| 856 | 843 | } else { |
| 857 | | − // Input is available for all pictures, so we don't need to |
| 858 | | − // mangle anything. |
| 844 | + if (ctx->gop_counter + b_counter + closed_gop_end == ctx->gop_size) { |
| 845 | + av_log(avctx, AV_LOG_DEBUG, "Pick group-end P-picture to " |
| 846 | + "encode next.\n"); |
| 847 | + } else { |
| 848 | + av_log(avctx, AV_LOG_DEBUG, "Pick normal P-picture to " |
| 849 | + "encode next.\n"); |
| 850 | + } |
| 851 | + pic->type = PICTURE_TYPE_P; |
| 852 | + av_assert0(start); |
| 853 | + ctx->gop_counter += 1 + b_counter; |
| 859 | 854 | } |
| 855 | + pic->is_reference = 1; |
| 856 | + *pic_out = pic; |
| 860 | 857 | |
| 861 | | − av_log(avctx, AV_LOG_DEBUG, "Pictures ending truncated GOP:"); |
| 862 | | − for (pic = ctx->pic_start; pic; pic = pic->next) { |
| 863 | | − av_log(avctx, AV_LOG_DEBUG, " %s (%"PRId64"/%"PRId64")", |
| 864 | | − picture_type_name[pic->type], |
| 865 | | − pic->display_order, pic->encode_order); |
| 858 | + vaapi_encode_add_ref(avctx, pic, pic, 0, 1, 0); |
| 859 | + if (pic->type != PICTURE_TYPE_IDR) { |
| 860 | + vaapi_encode_add_ref(avctx, pic, start, |
| 861 | + pic->type == PICTURE_TYPE_P, |
| 862 | + b_counter > 0, 0); |
| 863 | + vaapi_encode_add_ref(avctx, pic, ctx->next_prev, 0, 0, 1); |
| 866 | 864 | } |
| 867 | | − av_log(avctx, AV_LOG_DEBUG, "\n"); |
| 865 | + if (ctx->next_prev) |
| 866 | + --ctx->next_prev->ref_count[0]; |
| 868 | 867 | |
| 868 | + if (b_counter > 0) { |
| 869 | + vaapi_encode_set_b_pictures(avctx, start, pic, pic, 1, |
| 870 | + &ctx->next_prev); |
| 871 | + } else { |
| 872 | + ctx->next_prev = pic; |
| 873 | + } |
| 874 | + ++ctx->next_prev->ref_count[0]; |
| 869 | 875 | return 0; |
| 870 | 876 | } |
| 871 | 877 | |
| 872 | 878 | static int vaapi_encode_clear_old(AVCodecContext *avctx) |
| 873 | 879 | { |
| 874 | 880 | VAAPIEncodeContext *ctx = avctx->priv_data; |
| 875 | | − VAAPIEncodePicture *pic, *old; |
| 876 | | − int i; |
| 881 | + VAAPIEncodePicture *pic, *prev, *next; |
| 877 | 882 | |
| 878 | | − while (ctx->pic_start != ctx->pic_end) { |
| 879 | | − old = ctx->pic_start; |
| 880 | | − if (old->encode_order > ctx->output_order) |
| 881 | | − break; |
| 883 | + av_assert0(ctx->pic_start); |
| 882 | 884 | |
| 883 | | − for (pic = old->next; pic; pic = pic->next) { |
| 884 | | − if (pic->encode_complete) |
| 885 | | − continue; |
| 886 | | − for (i = 0; i < pic->nb_refs; i++) { |
| 887 | | − if (pic->refs[i] == old) { |
| 888 | | − // We still need this picture because it's referred to |
| 889 | | − // directly by a later one, so it and all following |
| 890 | | − // pictures have to stay. |
| 891 | | − return 0; |
| 892 | | − } |
| 893 | | − } |
| 894 | | − } |
| 885 | + // Remove direct references once each picture is complete. |
| 886 | + for (pic = ctx->pic_start; pic; pic = pic->next) { |
| 887 | + if (pic->encode_complete && pic->next) |
| 888 | + vaapi_encode_remove_refs(avctx, pic, 0); |
| 889 | + } |
| 895 | 890 | |
| 896 | | − pic = ctx->pic_start; |
| 897 | | − ctx->pic_start = pic->next; |
| 898 | | − vaapi_encode_free(avctx, pic); |
| 891 | + // Remove indirect references once a picture has no direct references. |
| 892 | + for (pic = ctx->pic_start; pic; pic = pic->next) { |
| 893 | + if (pic->encode_complete && pic->ref_count[0] == 0) |
| 894 | + vaapi_encode_remove_refs(avctx, pic, 1); |
| 895 | + } |
| 896 | + |
| 897 | + // Clear out all complete pictures with no remaining references. |
| 898 | + prev = NULL; |
| 899 | + for (pic = ctx->pic_start; pic; pic = next) { |
| 900 | + next = pic->next; |
| 901 | + if (pic->encode_complete && pic->ref_count[1] == 0) { |
| 902 | + av_assert0(pic->ref_removed[0] && pic->ref_removed[1]); |
| 903 | + if (prev) |
| 904 | + prev->next = next; |
| 905 | + else |
| 906 | + ctx->pic_start = next; |
| 907 | + vaapi_encode_free(avctx, pic); |
| 908 | + } else { |
| 909 | + prev = pic; |
| 910 | + } |
| 899 | 911 | } |
| 900 | 912 | |
| 901 | 913 | return 0; |
| 902 | 914 | } |
| 903 | 915 | |
| 904 | | −int ff_vaapi_encode2(AVCodecContext *avctx, AVPacket *pkt, |
| 905 | | − const AVFrame *input_image, int *got_packet) |
| 916 | +int ff_vaapi_encode_send_frame(AVCodecContext *avctx, const AVFrame *frame) |
| 906 | 917 | { |
| 907 | 918 | VAAPIEncodeContext *ctx = avctx->priv_data; |
| 908 | 919 | VAAPIEncodePicture *pic; |
| 909 | 920 | int err; |
| 910 | 921 | |
| 911 | | − if (input_image) { |
| 912 | | − av_log(avctx, AV_LOG_DEBUG, "Encode frame: %ux%u (%"PRId64").\n", |
| 913 | | − input_image->width, input_image->height, input_image->pts); |
| 922 | + if (frame) { |
| 923 | + av_log(avctx, AV_LOG_DEBUG, "Input frame: %ux%u (%"PRId64").\n", |
| 924 | + frame->width, frame->height, frame->pts); |
| 914 | 925 | |
| 915 | | − if (input_image->pict_type == AV_PICTURE_TYPE_I) { |
| 916 | | − err = vaapi_encode_truncate_gop(avctx); |
| 917 | | − if (err < 0) |
| 918 | | − goto fail; |
| 919 | | − ctx->force_idr = 1; |
| 920 | | − } |
| 921 | | − |
| 922 | | − err = vaapi_encode_get_next(avctx, &pic); |
| 923 | | − if (err) { |
| 924 | | − av_log(avctx, AV_LOG_ERROR, "Input setup failed: %d.\n", err); |
| 925 | | − return err; |
| 926 | | − } |
| 926 | + pic = vaapi_encode_alloc(avctx); |
| 927 | + if (!pic) |
| 928 | + return AVERROR(ENOMEM); |
| 927 | 929 | |
| 928 | 930 | pic->input_image = av_frame_alloc(); |
| 929 | 931 | if (!pic->input_image) { |
| 930 | 932 | err = AVERROR(ENOMEM); |
| 931 | 933 | goto fail; |
| 932 | 934 | } |
| 933 | | − err = av_frame_ref(pic->input_image, input_image); |
| 935 | + err = av_frame_ref(pic->input_image, frame); |
| 934 | 936 | if (err < 0) |
| 935 | 937 | goto fail; |
| 936 | | − pic->input_surface = (VASurfaceID)(uintptr_t)input_image->data[3]; |
| 937 | | − pic->pts = input_image->pts; |
| 938 | + |
| 939 | + if (ctx->input_order == 0) |
| 940 | + pic->force_idr = 1; |
| 941 | + |
| 942 | + pic->input_surface = (VASurfaceID)(uintptr_t)frame->data[3]; |
| 943 | + pic->pts = frame->pts; |
| 938 | 944 | |
| 939 | 945 | if (ctx->input_order == 0) |
| 940 | 946 | ctx->first_pts = pic->pts; |
| @@ -943,72 +949,89 @@ int ff_vaapi_encode2(AVCodecContext *avctx, AVPacket *pkt, · 2 unmodified lines |
| 943 | 949 | if (ctx->output_delay > 0) |
| 944 | 950 | ctx->ts_ring[ctx->input_order % (3 * ctx->output_delay)] = pic->pts; |
| 945 | 951 | |
| 946 | | − pic->input_available = 1; |
| 952 | + pic->display_order = ctx->input_order; |
| 953 | + ++ctx->input_order; |
| 947 | 954 | |
| 948 | | − } else { |
| 949 | | − if (!ctx->end_of_stream) { |
| 950 | | − err = vaapi_encode_truncate_gop(avctx); |
| 951 | | − if (err < 0) |
| 952 | | − goto fail; |
| 953 | | − ctx->end_of_stream = 1; |
| 955 | + if (ctx->pic_start) { |
| 956 | + ctx->pic_end->next = pic; |
| 957 | + ctx->pic_end = pic; |
| 958 | + } else { |
| 959 | + ctx->pic_start = pic; |
| 960 | + ctx->pic_end = pic; |
| 954 | 961 | } |
| 962 | + |
| 963 | + } else { |
| 964 | + ctx->end_of_stream = 1; |
| 965 | + |
| 966 | + // Fix timestamps if we hit end-of-stream before the initial decode |
| 967 | + // delay has elapsed. |
| 968 | + if (ctx->input_order < ctx->decode_delay) |
| 969 | + ctx->dts_pts_diff = ctx->pic_end->pts - ctx->first_pts; |
| 955 | 970 | } |
| 956 | 971 | |
| 957 | | − ++ctx->input_order; |
| 958 | | − ++ctx->output_order; |
| 959 | | − av_assert0(ctx->output_order + ctx->output_delay + 1 == ctx->input_order); |
| 972 | + return 0; |
| 960 | 973 | |
| 961 | | − for (pic = ctx->pic_start; pic; pic = pic->next) |
| 962 | | − if (pic->encode_order == ctx->output_order) |
| 963 | | − break; |
| 974 | +fail: |
| 975 | + return err; |
| 976 | +} |
| 964 | 977 | |
| 965 | | − // pic can be null here if we don't have a specific target in this |
| 966 | | − // iteration. We might still issue encodes if things can be overlapped, |
| 967 | | − // even though we don't intend to output anything. |
| 978 | +int ff_vaapi_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt) |
| 979 | +{ |
| 980 | + VAAPIEncodeContext *ctx = avctx->priv_data; |
| 981 | + VAAPIEncodePicture *pic; |
| 982 | + int err; |
| 968 | 983 | |
| 969 | | − err = vaapi_encode_step(avctx, pic); |
| 970 | | − if (err < 0) { |
| 971 | | − av_log(avctx, AV_LOG_ERROR, "Encode failed: %d.\n", err); |
| 972 | | − goto fail; |
| 984 | + if (!ctx->pic_start) { |
| 985 | + if (ctx->end_of_stream) |
| 986 | + return AVERROR_EOF; |
| 987 | + else |
| 988 | + return AVERROR(EAGAIN); |
| 973 | 989 | } |
| 974 | 990 | |
| 975 | | − if (!pic) { |
| 976 | | − *got_packet = 0; |
| 977 | | − } else { |
| 978 | | − err = vaapi_encode_output(avctx, pic, pkt); |
| 979 | | − if (err < 0) { |
| 980 | | − av_log(avctx, AV_LOG_ERROR, "Output failed: %d.\n", err); |
| 981 | | − goto fail; |
| 982 | | − } |
| 991 | + pic = NULL; |
| 992 | + err = vaapi_encode_pick_next(avctx, &pic); |
| 993 | + if (err < 0) |
| 994 | + return err; |
| 995 | + av_assert0(pic); |
| 983 | 996 | |
| 984 | | − if (ctx->output_delay == 0) { |
| 985 | | − pkt->dts = pkt->pts; |
| 986 | | − } else if (ctx->output_order < ctx->decode_delay) { |
| 987 | | − if (ctx->ts_ring[ctx->output_order] < INT64_MIN + ctx->dts_pts_diff) |
| 988 | | − pkt->dts = INT64_MIN; |
| 989 | | − else |
| 990 | | − pkt->dts = ctx->ts_ring[ctx->output_order] - ctx->dts_pts_diff; |
| 991 | | − } else { |
| 992 | | − pkt->dts = ctx->ts_ring[(ctx->output_order - ctx->decode_delay) % |
| 993 | | − (3 * ctx->output_delay)]; |
| 994 | | − } |
| 997 | + pic->encode_order = ctx->encode_order++; |
| 995 | 998 | |
| 996 | | − *got_packet = 1; |
| 999 | + err = vaapi_encode_issue(avctx, pic); |
| 1000 | + if (err < 0) { |
| 1001 | + av_log(avctx, AV_LOG_ERROR, "Encode failed: %d.\n", err); |
| 1002 | + return err; |
| 997 | 1003 | } |
| 998 | 1004 | |
| 999 | | − err = vaapi_encode_clear_old(avctx); |
| 1005 | + err = vaapi_encode_output(avctx, pic, pkt); |
| 1000 | 1006 | if (err < 0) { |
| 1001 | | − av_log(avctx, AV_LOG_ERROR, "List clearing failed: %d.\n", err); |
| 1002 | | − goto fail; |
| 1007 | + av_log(avctx, AV_LOG_ERROR, "Output failed: %d.\n", err); |
| 1008 | + return err; |
| 1003 | 1009 | } |
| 1004 | 1010 | |
| 1011 | + if (ctx->output_delay == 0) { |
| 1012 | + pkt->dts = pkt->pts; |
| 1013 | + } else if (pic->encode_order < ctx->decode_delay) { |
| 1014 | + if (ctx->ts_ring[pic->encode_order] < INT64_MIN + ctx->dts_pts_diff) |
| 1015 | + pkt->dts = INT64_MIN; |
| 1016 | + else |
| 1017 | + pkt->dts = ctx->ts_ring[pic->encode_order] - ctx->dts_pts_diff; |
| 1018 | + } else { |
| 1019 | + pkt->dts = ctx->ts_ring[(pic->encode_order - ctx->decode_delay) % |
| 1020 | + (3 * ctx->output_delay)]; |
| 1021 | + } |
| 1022 | + av_log(avctx, AV_LOG_DEBUG, "Output packet: pts %"PRId64" dts %"PRId64".\n", |
| 1023 | + pkt->pts, pkt->dts); |
| 1024 | + |
| 1025 | + ctx->output_order = pic->encode_order; |
| 1026 | + vaapi_encode_clear_old(avctx); |
| 1027 | + |
| 1005 | 1028 | return 0; |
| 1029 | +} |
| 1006 | 1030 | |
| 1007 | | −fail: |
| 1008 | | − // Unclear what to clean up on failure. There are probably some things we |
| 1009 | | − // could do usefully clean up here, but for now just leave them for uninit() |
| 1010 | | − // to do instead. |
| 1011 | | − return err; |
| 1031 | +int ff_vaapi_encode2(AVCodecContext *avctx, AVPacket *pkt, |
| 1032 | + const AVFrame *input_image, int *got_packet) |
| 1033 | +{ |
| 1034 | + return AVERROR(ENOSYS); |
| 1012 | 1035 | } |
| 1013 | 1036 | |
| 1014 | 1037 | static av_cold void vaapi_encode_add_global_param(AVCodecContext *avctx, |
| @@ -1475,14 +1498,16 @@ static av_cold int vaapi_encode_init_gop_structure(AVCodecContext *avctx) · 460 unmodified lines |
| 1475 | 1498 | ref_l1 = attr.value >> 16 & 0xffff; |
| 1476 | 1499 | } |
| 1477 | 1500 | |
| 1478 | | − if (avctx->gop_size <= 1) { |
| 1501 | + if (ctx->codec->flags & FLAG_INTRA_ONLY || |
| 1502 | + avctx->gop_size <= 1) { |
| 1479 | 1503 | av_log(avctx, AV_LOG_VERBOSE, "Using intra frames only.\n"); |
| 1480 | 1504 | ctx->gop_size = 1; |
| 1481 | 1505 | } else if (ref_l0 < 1) { |
| 1482 | 1506 | av_log(avctx, AV_LOG_ERROR, "Driver does not support any " |
| 1483 | 1507 | "reference frames.\n"); |
| 1484 | 1508 | return AVERROR(EINVAL); |
| 1485 | | − } else if (ref_l1 < 1 || avctx->max_b_frames < 1) { |
| 1509 | + } else if (!(ctx->codec->flags & FLAG_B_PICTURES) || |
| 1510 | + ref_l1 < 1 || avctx->max_b_frames < 1) { |
| 1486 | 1511 | av_log(avctx, AV_LOG_VERBOSE, "Using intra and P-frames " |
| 1487 | 1512 | "(supported references: %d / %d).\n", ref_l0, ref_l1); |
| 1488 | 1513 | ctx->gop_size = avctx->gop_size; |
| @@ -1494,6 +1519,20 @@ static av_cold int vaapi_encode_init_gop_structure(AVCodecContext *avctx) · 5 unmodified lines |
| 1494 | 1519 | ctx->gop_size = avctx->gop_size; |
| 1495 | 1520 | ctx->p_per_i = INT_MAX; |
| 1496 | 1521 | ctx->b_per_p = avctx->max_b_frames; |
| 1522 | + if (ctx->codec->flags & FLAG_B_PICTURE_REFERENCES) { |
| 1523 | + ctx->max_b_depth = FFMIN(ctx->desired_b_depth, |
| 1524 | + av_log2(ctx->b_per_p) + 1); |
| 1525 | + } else { |
| 1526 | + ctx->max_b_depth = 1; |
| 1527 | + } |
| 1528 | + } |
| 1529 | + |
| 1530 | + if (ctx->codec->flags & FLAG_NON_IDR_KEY_PICTURES) { |
| 1531 | + ctx->closed_gop = !!(avctx->flags & AV_CODEC_FLAG_CLOSED_GOP); |
| 1532 | + ctx->gop_per_idr = ctx->idr_interval + 1; |
| 1533 | + } else { |
| 1534 | + ctx->closed_gop = 1; |
| 1535 | + ctx->gop_per_idr = 1; |
| 1497 | 1536 | } |
| 1498 | 1537 | |
| 1499 | 1538 | return 0; |
| @@ -1946,10 +1985,8 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) · 446 unmodified lines |
| 1946 | 1985 | goto fail; |
| 1947 | 1986 | } |
| 1948 | 1987 | |
| 1949 | | − ctx->input_order = 0; |
| 1950 | 1988 | ctx->output_delay = ctx->b_per_p; |
| 1951 | | − ctx->decode_delay = 1; |
| 1952 | | − ctx->output_order = - ctx->output_delay - 1; |
| 1989 | + ctx->decode_delay = ctx->max_b_depth; |
| 1953 | 1990 | |
| 1954 | 1991 | if (ctx->codec->sequence_params_size > 0) { |
| 1955 | 1992 | ctx->codec_sequence_params = |
| @@ -1977,10 +2014,6 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) · 21 unmodified lines |
| 1977 | 2014 | } |
| 1978 | 2015 | } |
| 1979 | 2016 | |
| 1980 | | − // This should be configurable somehow. (Needs testing on a machine |
| 1981 | | − // where it actually overlaps properly, though.) |
| 1982 | | − ctx->issue_mode = ISSUE_MODE_MAXIMISE_THROUGHPUT; |
| 1983 | | − |
| 1984 | 2017 | if (ctx->va_packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE && |
| 1985 | 2018 | ctx->codec->write_sequence_header && |
| 1986 | 2019 | avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { |