@ -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 < Frame > ( ) ;
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 < Frame > 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<Frame> 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 ) ;
}