diff --git a/src/video_core/host1x/ffmpeg/ffmpeg.cpp b/src/video_core/host1x/ffmpeg/ffmpeg.cpp index 95394b5d2f..170b42872f 100644 --- a/src/video_core/host1x/ffmpeg/ffmpeg.cpp +++ b/src/video_core/host1x/ffmpeg/ffmpeg.cpp @@ -1,9 +1,6 @@ // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -// SPDX-FileCopyrightText: Copyright 2024 suyu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - // SPDX-FileCopyrightText: Copyright 2025 eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -54,8 +51,7 @@ AVPixelFormat GetGpuFormat(AVCodecContext* codec_context, const AVPixelFormat* p return codec_context->pix_fmt; } -std::string AVError(int errnum) -{ +std::string AVError(int errnum) { char errbuf[AV_ERROR_MAX_STRING_SIZE] = {}; av_make_error_string(errbuf, sizeof(errbuf) - 1, errnum); return errbuf; @@ -223,167 +219,6 @@ bool DecoderContext::OpenContext(const Decoder& decoder) { return true; } -// Nasty but allows linux builds to pass. -// Requires double checks when FFMPEG gets updated. -// Hopefully a future FFMPEG update will all and expose a solution in the public API. -namespace { - -typedef struct FFCodecDefault { - const char* key; - const char* value; -} FFCodecDefault; - -typedef struct FFCodec { - /** - * The public AVCodec. See codec.h for it. - */ - AVCodec p; - - /** - * Internal codec capabilities FF_CODEC_CAP_*. - */ - unsigned caps_internal : 29; - - /** - * This field determines the type of the codec (decoder/encoder) - * and also the exact callback cb implemented by the codec. - * cb_type uses enum FFCodecType values. - */ - unsigned cb_type : 3; - - int priv_data_size; - /** - * @name Frame-level threading support functions - * @{ - */ - /** - * Copy necessary context variables from a previous thread context to the current one. - * If not defined, the next thread will start automatically; otherwise, the codec - * must call ff_thread_finish_setup(). - * - * dst and src will (rarely) point to the same context, in which case memcpy should be skipped. - */ - int (*update_thread_context)(struct AVCodecContext* dst, const struct AVCodecContext* src); - - /** - * Copy variables back to the user-facing context - */ - int (*update_thread_context_for_user)(struct AVCodecContext* dst, - const struct AVCodecContext* src); - /** @} */ - - /** - * Private codec-specific defaults. - */ - const FFCodecDefault* defaults; - - /** - * Initialize codec static data, called from av_codec_iterate(). - * - * This is not intended for time consuming operations as it is - * run for every codec regardless of that codec being used. - */ - void (*init_static_data)(struct FFCodec* codec); - - int (*init)(struct AVCodecContext*); - - union { - /** - * Decode to an AVFrame. - * cb is in this state if cb_type is FF_CODEC_CB_TYPE_DECODE. - * - * @param avctx codec context - * @param[out] frame AVFrame for output - * @param[out] got_frame_ptr decoder sets to 0 or 1 to indicate that - * a non-empty frame was returned in frame. - * @param[in] avpkt AVPacket containing the data to be decoded - * @return amount of bytes read from the packet on success, - * negative error code on failure - */ - int (*decode)(struct AVCodecContext* avctx, struct AVFrame* frame, int* got_frame_ptr, - struct AVPacket* avpkt); - /** - * Decode subtitle data to an AVSubtitle. - * cb is in this state if cb_type is FF_CODEC_CB_TYPE_DECODE_SUB. - * - * Apart from that this is like the decode callback. - */ - int (*decode_sub)(struct AVCodecContext* avctx, struct AVSubtitle* sub, int* got_frame_ptr, - const struct AVPacket* avpkt); - /** - * Decode API with decoupled packet/frame dataflow. - * cb is in this state if cb_type is FF_CODEC_CB_TYPE_RECEIVE_FRAME. - * - * This function is called to get one output frame. It should call - * ff_decode_get_packet() to obtain input data. - */ - int (*receive_frame)(struct AVCodecContext* avctx, struct AVFrame* frame); - /** - * Encode data to an AVPacket. - * cb is in this state if cb_type is FF_CODEC_CB_TYPE_ENCODE - * - * @param avctx codec context - * @param[out] avpkt output AVPacket - * @param[in] frame AVFrame containing the input to be encoded - * @param[out] got_packet_ptr encoder sets to 0 or 1 to indicate that a - * non-empty packet was returned in avpkt. - * @return 0 on success, negative error code on failure - */ - int (*encode)(struct AVCodecContext* avctx, struct AVPacket* avpkt, - const struct AVFrame* frame, int* got_packet_ptr); - /** - * Encode subtitles to a raw buffer. - * cb is in this state if cb_type is FF_CODEC_CB_TYPE_ENCODE_SUB. - */ - int (*encode_sub)(struct AVCodecContext* avctx, uint8_t* buf, int buf_size, - const struct AVSubtitle* sub); - /** - * Encode API with decoupled frame/packet dataflow. - * cb is in this state if cb_type is FF_CODEC_CB_TYPE_RECEIVE_PACKET. - * - * This function is called to get one output packet. - * It should call ff_encode_get_frame() to obtain input data. - */ - int (*receive_packet)(struct AVCodecContext* avctx, struct AVPacket* avpkt); - } cb; - - int (*close)(struct AVCodecContext*); - - /** - * Flush buffers. - * Will be called when seeking - */ - void (*flush)(struct AVCodecContext*); - - /** - * Decoding only, a comma-separated list of bitstream filters to apply to - * packets before decoding. - */ - const char* bsfs; - - /** - * Array of pointers to hardware configurations supported by the codec, - * or NULL if no hardware supported. The array is terminated by a NULL - * pointer. - * - * The user can only access this field via avcodec_get_hw_config(). - */ - const struct AVCodecHWConfigInternal* const* hw_configs; - - /** - * List of supported codec_tags, terminated by FF_CODEC_TAGS_END. - */ - const uint32_t* codec_tags; -} FFCodec; - -#ifndef ANDROID -static av_always_inline const FFCodec* ffcodec(const AVCodec* codec) { - return (const FFCodec*)codec; -} -#endif -} // namespace - - bool DecoderContext::SendPacket(const Packet& packet) { m_temp_frame = std::make_shared(); m_got_frame = 0; @@ -394,10 +229,8 @@ bool DecoderContext::SendPacket(const Packet& packet) { if (!m_codec_context->hw_device_ctx && m_codec_context->codec_id == AV_CODEC_ID_H264) { m_decode_order = true; auto* codec{ffcodec(m_decoder.GetCodec())}; - if (const int ret = codec->cb.decode(m_codec_context, - m_temp_frame->GetFrame(), - &m_got_frame, - packet.GetPacket()); + if (const int ret = codec->cb.decode(m_codec_context, m_temp_frame->GetFrame(), + &m_got_frame, packet.GetPacket()); ret < 0) { LOG_DEBUG(Service_NVDRV, "avcodec_send_packet error {}", AVError(ret)); return false; @@ -417,7 +250,6 @@ bool DecoderContext::SendPacket(const Packet& packet) { std::shared_ptr DecoderContext::ReceiveFrame() { // Android can randomly crash when calling decode directly, so skip. // TODO update ffmpeg and hope that fixes it. -// TODO: This is causing issues on linux, need to bisect #ifndef ANDROID if (!m_codec_context->hw_device_ctx && m_codec_context->codec_id == AV_CODEC_ID_H264) { m_decode_order = true; @@ -475,8 +307,12 @@ std::shared_ptr DecoderContext::ReceiveFrame() { } #if defined(FF_API_INTERLACED_FRAME) || LIBAVUTIL_VERSION_MAJOR >= 59 - m_temp_frame->GetFrame()->interlaced_frame = - (m_temp_frame->GetFrame()->flags & AV_FRAME_FLAG_INTERLACED) != 0; + if (m_temp_frame->GetFrame()->flags & AV_FRAME_FLAG_INTERLACED) + m_temp_frame->GetFrame()->flags &= ~AV_FRAME_FLAG_INTERLACED; + else + m_temp_frame->GetFrame()->flags |= AV_FRAME_FLAG_INTERLACED; +#else + m_temp_frame->GetFrame()->interlaced_frame = !m_temp_frame->GetFrame()->interlaced_frame; #endif return std::move(m_temp_frame); } diff --git a/src/video_core/host1x/ffmpeg/ffmpeg.h b/src/video_core/host1x/ffmpeg/ffmpeg.h index bd0ad97adc..20e12b3616 100644 --- a/src/video_core/host1x/ffmpeg/ffmpeg.h +++ b/src/video_core/host1x/ffmpeg/ffmpeg.h @@ -22,7 +22,7 @@ extern "C" { #include #include #ifndef ANDROID -#include +#include #endif #if defined(__GNUC__) || defined(__clang__) @@ -106,7 +106,11 @@ public: } bool IsInterlaced() const { - return m_frame->interlaced_frame != 0; +#if defined(FF_API_INTERLACED_FRAME) || LIBAVUTIL_VERSION_MAJOR >= 59 + return m_frame->flags & AV_FRAME_FLAG_INTERLACED; +#else + return m_frame->interlaced_frame; +#endif } bool IsHardwareDecoded() const {