| 632 | } |
| 633 | |
| 634 | ScopedFrame Convert(const AVFrame* input_frame) { |
| 635 | ScopedFrame software_frame = DownloadIfNeeded(input_frame); |
| 636 | if (software_frame.get()->format == AV_PIX_FMT_RGBA) |
| 637 | return software_frame; |
| 638 | |
| 639 | sws_context_ = sws_getCachedContext( |
| 640 | sws_context_, |
| 641 | software_frame.get()->width, |
| 642 | software_frame.get()->height, |
| 643 | static_cast<AVPixelFormat>(software_frame.get()->format), |
| 644 | software_frame.get()->width, |
| 645 | software_frame.get()->height, |
| 646 | AV_PIX_FMT_RGBA, |
| 647 | SWS_BILINEAR, |
| 648 | nullptr, |
| 649 | nullptr, |
| 650 | nullptr); |
| 651 | if (!sws_context_) |
| 652 | throw std::runtime_error("sws_getCachedContext failed"); |
| 653 | |
| 654 | ScopedFrame rgba_frame; |
| 655 | rgba_frame.get()->format = AV_PIX_FMT_RGBA; |
| 656 | rgba_frame.get()->width = software_frame.get()->width; |
| 657 | rgba_frame.get()->height = software_frame.get()->height; |
| 658 | CheckAv(av_frame_get_buffer(rgba_frame.get(), 32), "av_frame_get_buffer rgba"); |
| 659 | CheckAv(av_frame_copy_props(rgba_frame.get(), software_frame.get()), "av_frame_copy_props rgba"); |
| 660 | CheckAv(av_frame_make_writable(rgba_frame.get()), "av_frame_make_writable rgba"); |
| 661 | |
| 662 | sws_scale( |
| 663 | sws_context_, |
| 664 | software_frame.get()->data, |
| 665 | software_frame.get()->linesize, |
| 666 | 0, |
| 667 | software_frame.get()->height, |
| 668 | rgba_frame.get()->data, |
| 669 | rgba_frame.get()->linesize); |
| 670 | return rgba_frame; |
| 671 | } |
| 672 | |
| 673 | private: |
| 674 | ScopedFrame DownloadIfNeeded(const AVFrame* input_frame) { |
no test coverage detected