#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" extern "C" { AvPlayerInternal* APS5_VABI sceAvPlayerInit(AvPlayerInitData*); int APS5_VABI sceAvPlayerInitEx(const AvPlayerInitDataEx*, AvPlayerInternal**); int APS5_VABI sceAvPlayerPostInit(AvPlayerInternal*, const AvPlayerPostInitData*); int APS5_VABI sceAvPlayerSetLogCallback(void*, void*); int APS5_VABI sceAvPlayerAddSource(AvPlayerInternal*, const char*); int APS5_VABI sceAvPlayerStreamCount(AvPlayerInternal*); int APS5_VABI sceAvPlayerGetStreamInfo(AvPlayerInternal*, std::uint32_t, AvPlayerStreamInfo*); int APS5_VABI sceAvPlayerGetStreamInfoEx(AvPlayerInternal*, std::uint32_t, AvPlayerStreamInfoEx*); int APS5_VABI sceAvPlayerEnableStream(AvPlayerInternal*, std::uint32_t); int APS5_VABI sceAvPlayerChangeStream(AvPlayerInternal*, std::uint32_t, std::uint32_t); int APS5_VABI sceAvPlayerSetAvailableBandwidth(AvPlayerInternal*, std::uint32_t, std::uint32_t, std::uint32_t); int APS5_VABI sceAvPlayerStart(AvPlayerInternal*); int APS5_VABI sceAvPlayerStartEx(AvPlayerInternal*, const void*); int APS5_VABI sceAvPlayerStop(AvPlayerInternal*); int APS5_VABI sceAvPlayerPause(AvPlayerInternal*); int APS5_VABI sceAvPlayerResume(AvPlayerInternal*); int APS5_VABI sceAvPlayerJumpToTime(AvPlayerInternal*, std::uint64_t); int APS5_VABI sceAvPlayerSetLooping(AvPlayerInternal*, Bool); int APS5_VABI sceAvPlayerSetAvSyncMode(AvPlayerInternal*, std::uint32_t); int APS5_VABI sceAvPlayerSetTrickSpeed(AvPlayerInternal*, std::int32_t); Bool APS5_VABI sceAvPlayerGetVideoDataEx(AvPlayerInternal*, AvPlayerFrameInfoEx*); Bool APS5_VABI sceAvPlayerGetVideoData(AvPlayerInternal*, AvPlayerFrameInfo*); Bool APS5_VABI sceAvPlayerGetAudioData(AvPlayerInternal*, AvPlayerFrameInfo*); Bool APS5_VABI sceAvPlayerIsActive(AvPlayerInternal*); std::uint64_t APS5_VABI sceAvPlayerCurrentTime(AvPlayerInternal*); int APS5_VABI sceAvPlayerClose(AvPlayerInternal*); } namespace { constexpr int Width = 100; constexpr int Height = 60; constexpr int Pitch = 256; constexpr int FrameRate = 30; constexpr int FrameCount = 30; constexpr int SampleRate = 48000; constexpr std::uint32_t VideoStream = 0; constexpr std::uint32_t EnglishAudioStream = 1; constexpr std::uint32_t FrenchAudioStream = 2; constexpr int InvalidParams = static_cast(0x806A0001u); constexpr int OperationFailed = static_cast(0x806A0002u); constexpr std::int32_t LoopingBack = static_cast(0x806A00A1u); constexpr std::int32_t JumpComplete = static_cast(0x806A00A3u); constexpr std::int32_t EventStop = 1; constexpr std::int32_t EventReady = 2; constexpr std::int32_t EventPlay = 3; constexpr std::int32_t EventPause = 4; constexpr std::int32_t EventWarning = 0x20; const char* const MoviePath = "app0/avplayer.mp4"; constexpr std::array Movie{ 0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70, 0x69, 0x73, 0x6f, 0x6d, 0x00, 0x00, 0x02, 0x00, 0x69, 0x73, 0x6f, 0x6d, 0x69, 0x73, 0x6f, 0x32, 0x61, 0x76, 0x63, 0x31, 0x6d, 0x70, 0x34, 0x31, 0x00, 0x00, 0x0b, 0x56, 0x6d, 0x6f, 0x6f, 0x76, 0x00, 0x00, 0x00, 0x6c, 0x6d, 0x76, 0x68, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbb, 0x80, 0x00, 0x00, 0xbb, 0x80, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0xfb, 0x74, 0x72, 0x61, 0x6b, 0x00, 0x00, 0x00, 0x5c, 0x74, 0x6b, 0x68, 0x64, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbb, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x65, 0x64, 0x74, 0x73, 0x00, 0x00, 0x00, 0x1c, 0x65, 0x6c, 0x73, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xbb, 0x80, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x73, 0x6d, 0x64, 0x69, 0x61, 0x00, 0x00, 0x00, 0x20, 0x6d, 0x64, 0x68, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x15, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x68, 0x64, 0x6c, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x64, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x69, 0x64, 0x65, 0x6f, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x00, 0x00, 0x00, 0x03, 0x1e, 0x6d, 0x69, 0x6e, 0x66, 0x00, 0x00, 0x00, 0x14, 0x76, 0x6d, 0x68, 0x64, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x64, 0x69, 0x6e, 0x66, 0x00, 0x00, 0x00, 0x1c, 0x64, 0x72, 0x65, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x75, 0x72, 0x6c, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0xde, 0x73, 0x74, 0x62, 0x6c, 0x00, 0x00, 0x00, 0xb2, 0x73, 0x74, 0x73, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x61, 0x76, 0x63, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x3c, 0x00, 0x48, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0c, 0x4c, 0x61, 0x76, 0x63, 0x20, 0x6c, 0x69, 0x62, 0x78, 0x32, 0x36, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xff, 0xff, 0x00, 0x00, 0x00, 0x38, 0x61, 0x76, 0x63, 0x43, 0x01, 0x64, 0x00, 0x0b, 0xff, 0xe1, 0x00, 0x1a, 0x67, 0x64, 0x00, 0x0b, 0xac, 0x76, 0x11, 0x1c, 0x9e, 0x7b, 0x84, 0x00, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0xf0, 0x3c, 0x50, 0xa6, 0x11, 0x80, 0x01, 0x00, 0x07, 0x68, 0xe8, 0x43, 0x81, 0x0c, 0xb2, 0x2c, 0xfd, 0xf8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x14, 0x62, 0x74, 0x72, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x73, 0x74, 0x74, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x73, 0x74, 0x73, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0xb8, 0x63, 0x74, 0x74, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x28, 0x73, 0x74, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x8c, 0x73, 0x74, 0x73, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x84, 0x73, 0x74, 0x63, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x0b, 0x86, 0x00, 0x00, 0x0b, 0xfc, 0x00, 0x00, 0x0c, 0x87, 0x00, 0x00, 0x0c, 0xf0, 0x00, 0x00, 0x0d, 0x3e, 0x00, 0x00, 0x0d, 0xaf, 0x00, 0x00, 0x0d, 0xea, 0x00, 0x00, 0x0e, 0x67, 0x00, 0x00, 0x0e, 0xad, 0x00, 0x00, 0x0f, 0x21, 0x00, 0x00, 0x0f, 0xad, 0x00, 0x00, 0x0f, 0xf8, 0x00, 0x00, 0x10, 0x5f, 0x00, 0x00, 0x10, 0x9f, 0x00, 0x00, 0x11, 0x1a, 0x00, 0x00, 0x11, 0x5f, 0x00, 0x00, 0x11, 0xf9, 0x00, 0x00, 0x12, 0x40, 0x00, 0x00, 0x12, 0xaa, 0x00, 0x00, 0x13, 0x25, 0x00, 0x00, 0x13, 0x83, 0x00, 0x00, 0x13, 0xfe, 0x00, 0x00, 0x14, 0x3a, 0x00, 0x00, 0x14, 0xa8, 0x00, 0x00, 0x14, 0xfb, 0x00, 0x00, 0x15, 0x64, 0x00, 0x00, 0x15, 0xd1, 0x00, 0x00, 0x16, 0x28, 0x00, 0x00, 0x16, 0x95, 0x00, 0x00, 0x02, 0xf5, 0x74, 0x72, 0x61, 0x6b, 0x00, 0x00, 0x00, 0x5c, 0x74, 0x6b, 0x68, 0x64, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbb, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x65, 0x64, 0x74, 0x73, 0x00, 0x00, 0x00, 0x1c, 0x65, 0x6c, 0x73, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xbb, 0x80, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x6d, 0x6d, 0x64, 0x69, 0x61, 0x00, 0x00, 0x00, 0x20, 0x6d, 0x64, 0x68, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbb, 0x80, 0x00, 0x00, 0xbf, 0x80, 0x15, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x68, 0x64, 0x6c, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x6f, 0x75, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x6f, 0x75, 0x6e, 0x64, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x00, 0x00, 0x00, 0x02, 0x18, 0x6d, 0x69, 0x6e, 0x66, 0x00, 0x00, 0x00, 0x10, 0x73, 0x6d, 0x68, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x64, 0x69, 0x6e, 0x66, 0x00, 0x00, 0x00, 0x1c, 0x64, 0x72, 0x65, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x75, 0x72, 0x6c, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0xdc, 0x73, 0x74, 0x62, 0x6c, 0x00, 0x00, 0x00, 0x7e, 0x73, 0x74, 0x73, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x6e, 0x6d, 0x70, 0x34, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0xbb, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x65, 0x73, 0x64, 0x73, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x80, 0x80, 0x25, 0x00, 0x02, 0x00, 0x04, 0x80, 0x80, 0x80, 0x17, 0x40, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x40, 0x00, 0x00, 0x08, 0xcf, 0x05, 0x80, 0x80, 0x80, 0x05, 0x11, 0x90, 0x56, 0xe5, 0x00, 0x06, 0x80, 0x80, 0x80, 0x01, 0x02, 0x00, 0x00, 0x00, 0x14, 0x62, 0x74, 0x72, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x40, 0x00, 0x00, 0x08, 0xcf, 0x00, 0x00, 0x00, 0x20, 0x73, 0x74, 0x74, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x1c, 0x73, 0x74, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x73, 0x74, 0x73, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xd0, 0x73, 0x74, 0x63, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x0b, 0xcb, 0x00, 0x00, 0x0c, 0x09, 0x00, 0x00, 0x0c, 0x58, 0x00, 0x00, 0x0c, 0x94, 0x00, 0x00, 0x0c, 0xc3, 0x00, 0x00, 0x0d, 0x0f, 0x00, 0x00, 0x0d, 0x4c, 0x00, 0x00, 0x0d, 0x7a, 0x00, 0x00, 0x0d, 0xbd, 0x00, 0x00, 0x0e, 0x0b, 0x00, 0x00, 0x0e, 0x39, 0x00, 0x00, 0x0e, 0x75, 0x00, 0x00, 0x0e, 0xbb, 0x00, 0x00, 0x0e, 0xf1, 0x00, 0x00, 0x0f, 0x51, 0x00, 0x00, 0x0f, 0x7e, 0x00, 0x00, 0x0f, 0xc1, 0x00, 0x00, 0x10, 0x05, 0x00, 0x00, 0x10, 0x31, 0x00, 0x00, 0x10, 0x6c, 0x00, 0x00, 0x10, 0xbe, 0x00, 0x00, 0x10, 0xec, 0x00, 0x00, 0x11, 0x27, 0x00, 0x00, 0x11, 0x9e, 0x00, 0x00, 0x11, 0xcc, 0x00, 0x00, 0x12, 0x0b, 0x00, 0x00, 0x12, 0x4e, 0x00, 0x00, 0x12, 0x7b, 0x00, 0x00, 0x12, 0xca, 0x00, 0x00, 0x12, 0xf8, 0x00, 0x00, 0x13, 0x55, 0x00, 0x00, 0x13, 0x98, 0x00, 0x00, 0x13, 0xc7, 0x00, 0x00, 0x14, 0x0b, 0x00, 0x00, 0x14, 0x47, 0x00, 0x00, 0x14, 0x7b, 0x00, 0x00, 0x14, 0xc7, 0x00, 0x00, 0x15, 0x09, 0x00, 0x00, 0x15, 0x38, 0x00, 0x00, 0x15, 0x72, 0x00, 0x00, 0x15, 0xa2, 0x00, 0x00, 0x15, 0xf1, 0x00, 0x00, 0x16, 0x36, 0x00, 0x00, 0x16, 0x68, 0x00, 0x00, 0x16, 0xa3, 0x00, 0x00, 0x16, 0xd2, 0x00, 0x00, 0x17, 0x06, 0x00, 0x00, 0x17, 0x35, 0x00, 0x00, 0x00, 0x1a, 0x73, 0x67, 0x70, 0x64, 0x01, 0x00, 0x00, 0x00, 0x72, 0x6f, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0x00, 0x00, 0x00, 0x1c, 0x73, 0x62, 0x67, 0x70, 0x00, 0x00, 0x00, 0x00, 0x72, 0x6f, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0xb5, 0x74, 0x72, 0x61, 0x6b, 0x00, 0x00, 0x00, 0x5c, 0x74, 0x6b, 0x68, 0x64, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbb, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x65, 0x64, 0x74, 0x73, 0x00, 0x00, 0x00, 0x1c, 0x65, 0x6c, 0x73, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xbb, 0x80, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x2d, 0x6d, 0x64, 0x69, 0x61, 0x00, 0x00, 0x00, 0x20, 0x6d, 0x64, 0x68, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbb, 0x80, 0x00, 0x00, 0xbf, 0x80, 0x1a, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x68, 0x64, 0x6c, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x6f, 0x75, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x6f, 0x75, 0x6e, 0x64, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x00, 0x00, 0x00, 0x02, 0xd8, 0x6d, 0x69, 0x6e, 0x66, 0x00, 0x00, 0x00, 0x10, 0x73, 0x6d, 0x68, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x64, 0x69, 0x6e, 0x66, 0x00, 0x00, 0x00, 0x1c, 0x64, 0x72, 0x65, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x75, 0x72, 0x6c, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x9c, 0x73, 0x74, 0x62, 0x6c, 0x00, 0x00, 0x00, 0x7e, 0x73, 0x74, 0x73, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x6e, 0x6d, 0x70, 0x34, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0xbb, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x65, 0x73, 0x64, 0x73, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x80, 0x80, 0x25, 0x00, 0x03, 0x00, 0x04, 0x80, 0x80, 0x80, 0x17, 0x40, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0xd8, 0x00, 0x00, 0x3e, 0xd8, 0x05, 0x80, 0x80, 0x80, 0x05, 0x11, 0x88, 0x56, 0xe5, 0x00, 0x06, 0x80, 0x80, 0x80, 0x01, 0x02, 0x00, 0x00, 0x00, 0x14, 0x62, 0x74, 0x72, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0xd8, 0x00, 0x00, 0x3e, 0xd8, 0x00, 0x00, 0x00, 0x20, 0x73, 0x74, 0x74, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x1c, 0x73, 0x74, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xd4, 0x73, 0x74, 0x73, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0xd0, 0x73, 0x74, 0x63, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x0b, 0xd1, 0x00, 0x00, 0x0c, 0x0f, 0x00, 0x00, 0x0c, 0x5e, 0x00, 0x00, 0x0c, 0x9a, 0x00, 0x00, 0x0c, 0xc9, 0x00, 0x00, 0x0d, 0x15, 0x00, 0x00, 0x0d, 0x52, 0x00, 0x00, 0x0d, 0x80, 0x00, 0x00, 0x0d, 0xc3, 0x00, 0x00, 0x0e, 0x11, 0x00, 0x00, 0x0e, 0x3f, 0x00, 0x00, 0x0e, 0x7b, 0x00, 0x00, 0x0e, 0xc1, 0x00, 0x00, 0x0e, 0xf7, 0x00, 0x00, 0x0f, 0x57, 0x00, 0x00, 0x0f, 0x84, 0x00, 0x00, 0x0f, 0xc7, 0x00, 0x00, 0x10, 0x0b, 0x00, 0x00, 0x10, 0x37, 0x00, 0x00, 0x10, 0x72, 0x00, 0x00, 0x10, 0xc4, 0x00, 0x00, 0x10, 0xf2, 0x00, 0x00, 0x11, 0x2d, 0x00, 0x00, 0x11, 0xa4, 0x00, 0x00, 0x11, 0xd2, 0x00, 0x00, 0x12, 0x11, 0x00, 0x00, 0x12, 0x54, 0x00, 0x00, 0x12, 0x81, 0x00, 0x00, 0x12, 0xd0, 0x00, 0x00, 0x12, 0xfe, 0x00, 0x00, 0x13, 0x5b, 0x00, 0x00, 0x13, 0x9e, 0x00, 0x00, 0x13, 0xcd, 0x00, 0x00, 0x14, 0x11, 0x00, 0x00, 0x14, 0x4d, 0x00, 0x00, 0x14, 0x81, 0x00, 0x00, 0x14, 0xcd, 0x00, 0x00, 0x15, 0x0f, 0x00, 0x00, 0x15, 0x3e, 0x00, 0x00, 0x15, 0x78, 0x00, 0x00, 0x15, 0xa8, 0x00, 0x00, 0x15, 0xf7, 0x00, 0x00, 0x16, 0x3c, 0x00, 0x00, 0x16, 0x6e, 0x00, 0x00, 0x16, 0xa9, 0x00, 0x00, 0x16, 0xd8, 0x00, 0x00, 0x17, 0x0c, 0x00, 0x00, 0x17, 0x3b, 0x00, 0x00, 0x00, 0x1a, 0x73, 0x67, 0x70, 0x64, 0x01, 0x00, 0x00, 0x00, 0x72, 0x6f, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0x00, 0x00, 0x00, 0x1c, 0x73, 0x62, 0x67, 0x70, 0x00, 0x00, 0x00, 0x00, 0x72, 0x6f, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3d, 0x75, 0x64, 0x74, 0x61, 0x00, 0x00, 0x00, 0x35, 0x6d, 0x65, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x68, 0x64, 0x6c, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x64, 0x69, 0x72, 0x61, 0x70, 0x70, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x69, 0x6c, 0x73, 0x74, 0x00, 0x00, 0x00, 0x08, 0x66, 0x72, 0x65, 0x65, 0x00, 0x00, 0x0b, 0xe4, 0x6d, 0x64, 0x61, 0x74, 0x00, 0x00, 0x00, 0x2d, 0x65, 0x88, 0x81, 0x00, 0x0a, 0xff, 0xfe, 0xf7, 0xd4, 0xb7, 0xcc, 0xb2, 0xed, 0x78, 0x7e, 0xb6, 0x0b, 0xa8, 0xf7, 0xa0, 0xe3, 0x03, 0xf2, 0x84, 0x24, 0x3b, 0x57, 0xd1, 0x76, 0x6b, 0xa8, 0xfa, 0xfc, 0x01, 0x87, 0xd1, 0x55, 0x97, 0xbb, 0x94, 0x2d, 0x98, 0xbc, 0x9d, 0x1d, 0x00, 0x00, 0x00, 0x10, 0x41, 0x9a, 0x08, 0xd8, 0x46, 0x03, 0x38, 0x19, 0x10, 0xaf, 0xfe, 0xda, 0xa6, 0x58, 0xce, 0x80, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x50, 0x4a, 0x0a, 0x8a, 0xae, 0xfe, 0x78, 0xf6, 0xe3, 0x5a, 0xb6, 0xa5, 0xdc, 0x97, 0x63, 0xe9, 0xf4, 0xfa, 0x27, 0x02, 0x9a, 0x69, 0xb2, 0xf1, 0xaa, 0xa1, 0x34, 0xd3, 0x14, 0x55, 0x55, 0x56, 0x59, 0xa6, 0x8a, 0x2e, 0x3c, 0x78, 0xfc, 0xb2, 0xe5, 0xe0, 0x00, 0x00, 0x00, 0x09, 0x41, 0x9e, 0x10, 0x4e, 0x21, 0x5f, 0x00, 0x05, 0x3d, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x3c, 0x88, 0xda, 0x65, 0x91, 0x76, 0x49, 0xc1, 0x46, 0x9f, 0x8f, 0x3f, 0xd7, 0xc7, 0xef, 0xe7, 0xf4, 0xf5, 0xfb, 0xf9, 0xff, 0x5b, 0xfc, 0x79, 0x58, 0xf5, 0x63, 0xc0, 0x06, 0x3d, 0x58, 0xf2, 0x00, 0x78, 0x8f, 0x8e, 0xe0, 0xa5, 0x35, 0x96, 0xcb, 0x3d, 0xc2, 0x8b, 0xdf, 0xec, 0xa4, 0x58, 0x76, 0x3f, 0x96, 0xcb, 0xeb, 0x9e, 0xb4, 0x58, 0xb5, 0x49, 0xfc, 0xdb, 0x74, 0x88, 0x43, 0x13, 0x3e, 0x51, 0x32, 0xcb, 0x9e, 0xb3, 0x81, 0x3c, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x3a, 0xea, 0x0a, 0x8c, 0x9f, 0xb7, 0xf5, 0xfd, 0x7a, 0xbe, 0x3c, 0xea, 0xfa, 0x9a, 0x9a, 0x6a, 0xc1, 0xfe, 0x0c, 0x97, 0xdc, 0xf8, 0x6d, 0xb3, 0x0f, 0x7d, 0x00, 0x7c, 0x66, 0x03, 0x3e, 0x80, 0x32, 0x7c, 0x01, 0x9f, 0xdc, 0x0f, 0x8c, 0xdc, 0x00, 0x00, 0x00, 0x09, 0x01, 0x9e, 0x18, 0x9a, 0x90, 0x9f, 0x00, 0x0b, 0x28, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x08, 0x2a, 0x06, 0x8e, 0xf9, 0xff, 0x5f, 0xfe, 0xbf, 0xf9, 0x7f, 0xa7, 0xfc, 0xca, 0xb9, 0xaa, 0xad, 0x6f, 0xdb, 0x90, 0xad, 0x6b, 0x6b, 0x78, 0xa3, 0x1d, 0x5a, 0xb5, 0x43, 0x54, 0x35, 0x15, 0x42, 0x15, 0xad, 0x5a, 0xb1, 0x56, 0xa4, 0x1c, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x0a, 0x2a, 0x06, 0x8d, 0xf7, 0xfd, 0xff, 0xfa, 0xff, 0xb7, 0xfd, 0x7f, 0xe6, 0x54, 0xba, 0xb7, 0x14, 0xaa, 0x1f, 0xcb, 0x2d, 0xab, 0x5b, 0xc2, 0x1b, 0x2d, 0xb3, 0x64, 0xf6, 0x46, 0x36, 0x23, 0x6f, 0x5a, 0x64, 0x6d, 0x61, 0x4e, 0x00, 0x00, 0x00, 0x1b, 0x41, 0x9a, 0x19, 0x92, 0xea, 0x04, 0x08, 0x10, 0x16, 0x88, 0x23, 0x01, 0x84, 0x0f, 0x90, 0x18, 0x40, 0xf0, 0x02, 0x15, 0xff, 0xfe, 0xda, 0xa6, 0x58, 0xce, 0x81, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x0c, 0x2a, 0x06, 0x8e, 0x79, 0xfe, 0x9f, 0xfd, 0x7f, 0x9f, 0xfe, 0xdf, 0xe9, 0x95, 0x77, 0x5c, 0x15, 0xd7, 0x76, 0x37, 0xd2, 0x92, 0xa4, 0xf0, 0xd3, 0x7e, 0xfd, 0xfb, 0xe9, 0x7a, 0x2f, 0xed, 0xbd, 0x29, 0x4d, 0xea, 0x5e, 0xeb, 0x11, 0xaf, 0x00, 0x00, 0x00, 0x0a, 0x41, 0x9e, 0x21, 0x0b, 0x88, 0x57, 0xff, 0x00, 0x05, 0x3d, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x0a, 0x2a, 0x06, 0x8e, 0x7b, 0xfe, 0xdf, 0xfe, 0xdf, 0xcf, 0xff, 0x7f, 0xf3, 0x8b, 0x92, 0xcc, 0xeb, 0x9a, 0x12, 0x94, 0xa9, 0x2b, 0xc7, 0xa6, 0xbd, 0x7a, 0xf5, 0xca, 0x53, 0x9f, 0xa7, 0xd3, 0x32, 0x49, 0xcb, 0x5c, 0x93, 0x99, 0x2e, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x06, 0x2a, 0x06, 0x8e, 0xfb, 0xfe, 0xff, 0xfd, 0x7f, 0xdf, 0xfe, 0x7f, 0xde, 0xea, 0x4e, 0x29, 0x2e, 0xaf, 0x6d, 0x08, 0xc8, 0xd8, 0xfe, 0x11, 0xb1, 0xf0, 0x21, 0x6b, 0x5a, 0xb5, 0x9c, 0x21, 0x6d, 0x9b, 0x36, 0x5d, 0xb5, 0x64, 0x63, 0x14, 0x7d, 0x47, 0x68, 0xbd, 0x46, 0xde, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x9e, 0x29, 0x59, 0x24, 0x27, 0xff, 0x00, 0x0b, 0x29, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x0a, 0x2a, 0x06, 0x8e, 0x79, 0xff, 0x5f, 0xfe, 0xbf, 0xf9, 0x7f, 0x9f, 0xf6, 0xba, 0x92, 0x47, 0x5e, 0x3c, 0xf7, 0xc0, 0xd5, 0x5a, 0xda, 0xdf, 0x78, 0xc7, 0x56, 0xad, 0x4d, 0x48, 0x41, 0x54, 0x2b, 0xaa, 0xa2, 0xaa, 0x8c, 0x5c, 0x00, 0x00, 0x00, 0x1d, 0x41, 0x9a, 0x2a, 0x53, 0xea, 0x04, 0x08, 0x10, 0x16, 0xd6, 0x88, 0x23, 0x01, 0x5c, 0x05, 0x24, 0x05, 0x70, 0x14, 0x00, 0x02, 0x15, 0xff, 0xfe, 0xda, 0xa6, 0x58, 0xce, 0x81, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x0c, 0x2a, 0x06, 0x8d, 0xf3, 0xfd, 0xff, 0xfa, 0x7f, 0x3f, 0xf9, 0xff, 0xce, 0x2f, 0x2f, 0x85, 0xe4, 0x72, 0x3c, 0x72, 0x96, 0x2c, 0xf7, 0x84, 0x25, 0xaf, 0xf9, 0x78, 0xe6, 0x93, 0x5c, 0xe7, 0xd3, 0x59, 0xc1, 0x29, 0x49, 0x62, 0x5c, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x0c, 0x2a, 0x06, 0x8e, 0x79, 0xfe, 0xdf, 0xfe, 0xdf, 0xbf, 0xff, 0x8f, 0xfa, 0x65, 0x5b, 0x4e, 0x2b, 0x7d, 0x6e, 0x0a, 0x52, 0x92, 0xa4, 0xe7, 0x4d, 0xfb, 0xf7, 0xaf, 0x7b, 0xdf, 0x7b, 0x7d, 0x28, 0xb2, 0x97, 0x53, 0x25, 0xd0, 0xb7, 0x00, 0x00, 0x00, 0x0a, 0x41, 0x9e, 0x31, 0xc9, 0x62, 0x15, 0xff, 0x00, 0x05, 0x3c, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x02, 0x2a, 0x0a, 0x8f, 0x1d, 0xff, 0x7f, 0xfe, 0xbf, 0xe3, 0xff, 0x6f, 0xf9, 0x84, 0xb6, 0xab, 0x38, 0xca, 0x68, 0x46, 0x47, 0xc3, 0xe0, 0x8d, 0x92, 0x00, 0x04, 0xc9, 0x26, 0x0e, 0xa8, 0xc6, 0xfd, 0xf7, 0xf2, 0x64, 0x4c, 0x79, 0x01, 0x08, 0xc4, 0x83, 0xc1, 0x89, 0x24, 0xad, 0x40, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x9e, 0x3a, 0x19, 0xa4, 0x27, 0xff, 0x00, 0x0b, 0x28, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x0a, 0x2a, 0x06, 0x8e, 0x7b, 0xfe, 0xff, 0xfd, 0x7f, 0xf2, 0xff, 0x4f, 0xf9, 0x27, 0x15, 0x75, 0xd7, 0x3a, 0x72, 0xd0, 0x8c, 0x8e, 0x40, 0xe1, 0x1b, 0x00, 0xde, 0x16, 0xb5, 0xab, 0x5e, 0x50, 0x85, 0xb6, 0x6c, 0x6c, 0xd9, 0x68, 0xec, 0x23, 0x68, 0xad, 0x72, 0x9c, 0x2e, 0x8b, 0x80, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x0c, 0x2a, 0x0a, 0x8c, 0xe7, 0xfd, 0x7f, 0xfa, 0xff, 0x9f, 0xfc, 0xbf, 0xe4, 0x9a, 0xc8, 0xe3, 0x9e, 0x39, 0xe0, 0x7c, 0xb6, 0x3e, 0xea, 0xd8, 0x63, 0x65, 0xcb, 0x14, 0x59, 0x62, 0x98, 0xe8, 0x40, 0x28, 0xa6, 0x42, 0x88, 0x10, 0x40, 0x04, 0x9e, 0x00, 0x00, 0x00, 0x2c, 0x65, 0x88, 0x80, 0x80, 0x02, 0xbf, 0xfe, 0xf7, 0xd4, 0xb7, 0xcc, 0xb2, 0xcd, 0xa7, 0xeb, 0x60, 0xba, 0x8f, 0x7a, 0x0e, 0x30, 0x3d, 0xb0, 0x24, 0x3b, 0x57, 0xd1, 0x76, 0x6b, 0xa8, 0xfa, 0xfc, 0x01, 0x87, 0xd1, 0x55, 0x97, 0xbb, 0x94, 0x2d, 0x98, 0xbc, 0x9d, 0x1d, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x0c, 0x2a, 0x06, 0x8e, 0x79, 0xfe, 0x9f, 0xfd, 0x7f, 0x9f, 0xff, 0x1f, 0xf1, 0x95, 0x35, 0x1a, 0xaa, 0xbc, 0xb1, 0x29, 0x4a, 0x92, 0xbd, 0xe5, 0xaf, 0x5c, 0xe7, 0x29, 0xcf, 0x5a, 0x7a, 0xe3, 0x29, 0x58, 0x49, 0x59, 0xa1, 0x4e, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x08, 0x2a, 0x06, 0x8e, 0xf9, 0xff, 0x5f, 0xff, 0x0f, 0xdf, 0xff, 0x9f, 0xf3, 0x51, 0x5d, 0x5a, 0x77, 0xc6, 0x41, 0x4a, 0x52, 0x58, 0xa7, 0x08, 0x53, 0x7e, 0xf5, 0xdb, 0xfc, 0xbe, 0x5a, 0x5e, 0x9f, 0x87, 0x96, 0xd7, 0xba, 0x8b, 0x91, 0x70, 0x00, 0x00, 0x00, 0x10, 0x41, 0x9a, 0x08, 0xd8, 0xb8, 0xe0, 0x12, 0x04, 0x2b, 0xff, 0xfe, 0xda, 0xa6, 0x58, 0xce, 0x80, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x06, 0x2a, 0x0a, 0x8e, 0xfb, 0xff, 0x8f, 0xff, 0x6f, 0xfa, 0xff, 0xbf, 0xfb, 0x5d, 0x5a, 0xe6, 0xaa, 0xad, 0xcb, 0x42, 0x32, 0x31, 0x27, 0x04, 0x6c, 0x02, 0x40, 0x21, 0x08, 0x5a, 0xe1, 0x31, 0xa2, 0x8a, 0x28, 0xa2, 0x08, 0x8a, 0x24, 0x45, 0x10, 0x42, 0x10, 0xc0, 0x48, 0x5b, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x09, 0x41, 0x9e, 0x10, 0x4e, 0x21, 0x3f, 0x00, 0x0b, 0x28, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x0a, 0x2a, 0x06, 0x8e, 0x79, 0xff, 0x5f, 0xfe, 0xbf, 0xf7, 0xff, 0x6f, 0xf7, 0x89, 0x25, 0xa4, 0x6e, 0xc7, 0xf2, 0xb5, 0xab, 0x5d, 0x10, 0x85, 0xb6, 0x46, 0x3e, 0xa8, 0xf4, 0xb4, 0x51, 0x8c, 0x6d, 0xc9, 0x11, 0x61, 0x6e, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x0c, 0x2a, 0x06, 0x8d, 0xf7, 0xfd, 0x3f, 0xfd, 0xbf, 0x7f, 0xfe, 0x7f, 0xdb, 0x11, 0x7a, 0x6b, 0x9d, 0x66, 0x0d, 0xf4, 0xa6, 0x5d, 0xb3, 0x8f, 0x6d, 0xfb, 0xf7, 0xae, 0x53, 0x7d, 0x6f, 0x83, 0x7e, 0x9d, 0xf5, 0x85, 0x05, 0xca, 0x70, 0x00, 0x00, 0x00, 0x09, 0x01, 0x9e, 0x18, 0x9a, 0x90, 0x9f, 0x00, 0x0b, 0x29, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x0a, 0x2a, 0x06, 0x8e, 0xf9, 0xfe, 0xdf, 0xfe, 0xdf, 0xcf, 0xff, 0x8f, 0xf8, 0xdc, 0x69, 0x2e, 0x61, 0x4d, 0x08, 0xc8, 0xe8, 0x0e, 0x11, 0xb0, 0x4f, 0xc1, 0x29, 0x4a, 0x92, 0xbd, 0xe5, 0x2d, 0x7a, 0xd2, 0x94, 0xe5, 0xae, 0x73, 0x96, 0xb5, 0xa7, 0x31, 0x51, 0x2e, 0x00, 0x00, 0x00, 0x1b, 0x41, 0x9a, 0x19, 0x52, 0xea, 0x04, 0x08, 0x10, 0x16, 0x88, 0x23, 0x04, 0xc0, 0x36, 0x90, 0x4c, 0x03, 0x60, 0x02, 0x15, 0xff, 0xfe, 0xda, 0xa6, 0x58, 0xce, 0x81, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x02, 0x2a, 0x09, 0xa2, 0x77, 0x8e, 0xff, 0xbf, 0xff, 0xc5, 0xfe, 0x7f, 0xf2, 0xff, 0x7b, 0xa9, 0xaa, 0xb9, 0x26, 0xc0, 0xbc, 0x30, 0x91, 0x0c, 0x22, 0xa2, 0x83, 0x1a, 0xbe, 0x9c, 0x3a, 0x62, 0xd8, 0xb4, 0x6c, 0xba, 0x85, 0xcb, 0x70, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x0a, 0x2a, 0x09, 0xe2, 0x57, 0x3d, 0xff, 0x7f, 0xfe, 0xbf, 0xf9, 0x7f, 0xa7, 0xfc, 0xc3, 0x4b, 0x95, 0xbe, 0xab, 0x02, 0x10, 0x85, 0xae, 0x53, 0x1a, 0x28, 0x8a, 0x28, 0xa2, 0x8a, 0x28, 0xa2, 0x88, 0xa0, 0xab, 0x52, 0xa5, 0x4a, 0x70, 0x00, 0x00, 0x00, 0x09, 0x01, 0x9e, 0x21, 0x0b, 0x90, 0x9f, 0x00, 0x0b, 0x29, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x0c, 0x2a, 0x11, 0x62, 0x96, 0x73, 0xfe, 0xbf, 0xfe, 0xdf, 0xe3, 0xff, 0x6f, 0xfa, 0xd2, 0x24, 0xbe, 0x3c, 0x6b, 0x9b, 0x68, 0x46, 0x46, 0x24, 0x60, 0x8d, 0xf3, 0xf0, 0xe0, 0x98, 0x61, 0x8a, 0x3c, 0xd4, 0xa1, 0x25, 0x42, 0x57, 0xb1, 0x1b, 0x5a, 0x6c, 0x3c, 0x30, 0xa7, 0x17, 0x45, 0x88, 0xb8, 0x00, 0x00, 0x00, 0x3b, 0x41, 0x9a, 0x22, 0x12, 0xf8, 0x10, 0x29, 0x68, 0x99, 0x4c, 0x02, 0x15, 0xff, 0xe3, 0x43, 0xff, 0x9f, 0xd8, 0xff, 0xc0, 0xf8, 0xb6, 0xdf, 0xc2, 0x52, 0x94, 0x69, 0x14, 0xc9, 0x47, 0x2f, 0x8e, 0x9b, 0x7e, 0x4d, 0x5f, 0x02, 0xd9, 0x86, 0xa1, 0x7a, 0x02, 0x92, 0x01, 0xc9, 0x0c, 0x46, 0x22, 0xe8, 0xf7, 0x55, 0xf6, 0xfe, 0x47, 0xfd, 0xed, 0x00, 0x0c, 0x98, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x0c, 0x2a, 0x06, 0x8e, 0x79, 0xfe, 0xdf, 0xfe, 0xdf, 0xbf, 0xff, 0x8f, 0xfa, 0x60, 0xe2, 0xd7, 0xba, 0xd5, 0x0a, 0x52, 0x92, 0xa4, 0xe7, 0x4d, 0xfb, 0xf7, 0xde, 0xeb, 0xef, 0xdf, 0x4a, 0x7b, 0xb7, 0xdf, 0xca, 0xb9, 0x4b, 0x09, 0x70, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x06, 0x2a, 0x06, 0x8e, 0xfb, 0xfe, 0xff, 0xfd, 0x3f, 0x9f, 0xfc, 0xff, 0xda, 0x49, 0x97, 0x3a, 0xac, 0x50, 0x4a, 0x52, 0xdb, 0x96, 0xf1, 0x8e, 0xbf, 0x4f, 0xe5, 0x29, 0xa5, 0x24, 0xfd, 0x29, 0x57, 0x5c, 0xe6, 0x27, 0x34, 0x1c, 0x00, 0x00, 0x00, 0x0e, 0x41, 0x9e, 0x29, 0x89, 0x22, 0x15, 0xff, 0x1e, 0xa6, 0xf6, 0x3e, 0xe2, 0xb7, 0xf8, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x08, 0x2a, 0x06, 0x8e, 0x7b, 0xff, 0x5f, 0xfe, 0xbf, 0xf9, 0x7f, 0x9f, 0xf6, 0xba, 0xb6, 0x9a, 0xac, 0xb4, 0x68, 0x46, 0x47, 0xe0, 0x60, 0x8d, 0xf3, 0xc1, 0x0b, 0x5a, 0xd5, 0xaf, 0x86, 0x10, 0xb4, 0x76, 0x6c, 0xd8, 0xb4, 0x6c, 0xd9, 0x68, 0xd9, 0x68, 0xa2, 0xad, 0x91, 0xa7, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x9e, 0x31, 0xd9, 0x64, 0x27, 0xff, 0x00, 0x0b, 0x29, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x0a, 0x2a, 0x06, 0x8d, 0xf7, 0xfd, 0xff, 0xfa, 0xff, 0xbf, 0xfc, 0xff, 0xbc, 0x8b, 0xae, 0x23, 0x9e, 0x2a, 0x87, 0xf3, 0xad, 0x6d, 0x69, 0xc6, 0x3a, 0xb5, 0x6a, 0x85, 0xd0, 0x42, 0x1a, 0xbc, 0xea, 0xd5, 0x80, 0x69, 0x12, 0xe0, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x0c, 0x2a, 0x06, 0x8e, 0x79, 0xfe, 0x9f, 0xfd, 0x7f, 0x9f, 0xfe, 0xff, 0xed, 0x95, 0x72, 0xea, 0xd3, 0x38, 0xc1, 0xae, 0x52, 0xa4, 0xaf, 0x09, 0x6b, 0xd7, 0xae, 0x52, 0x9c, 0xf0, 0xce, 0x72, 0xf8, 0x25, 0x6b, 0x4c, 0x5a, 0xe8, 0x5b, 0x80, 0x00, 0x00, 0x00, 0x1c, 0x41, 0x9a, 0x32, 0x51, 0x1a, 0x81, 0x02, 0x04, 0x05, 0xaa, 0x5a, 0x21, 0x30, 0xb0, 0x18, 0x50, 0xb0, 0x18, 0xc0, 0x00, 0x85, 0x7f, 0xfe, 0xda, 0xa6, 0x58, 0xce, 0x80, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x0a, 0x2a, 0x06, 0x8e, 0xf9, 0xfe, 0xdf, 0xfe, 0xdf, 0xcf, 0xff, 0x6f, 0xf3, 0xcc, 0x97, 0x57, 0xaa, 0xde, 0xb2, 0x85, 0x29, 0x49, 0x52, 0x79, 0xa9, 0x4b, 0xdf, 0x7d, 0x37, 0xd1, 0xbd, 0xbe, 0xea, 0x5a, 0xf7, 0x51, 0x6b, 0x94, 0xe0, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x04, 0x2a, 0x06, 0x8e, 0xfb, 0xff, 0xa7, 0xff, 0x4f, 0xf6, 0xff, 0xaf, 0xfc, 0xca, 0x97, 0x2e, 0x2a, 0x02, 0xb5, 0xad, 0xad, 0x78, 0xc6, 0xba, 0xb5, 0x27, 0x0a, 0xc2, 0x19, 0xb5, 0x21, 0xd7, 0x5a, 0x05, 0x67, 0x54, 0x73, 0xf0, 0x00, 0x00, 0x00, 0x2c, 0x65, 0x88, 0x81, 0x00, 0x0a, 0xff, 0xfe, 0xf7, 0xd4, 0xb7, 0xcc, 0xb2, 0xc0, 0x26, 0xfb, 0x60, 0xba, 0x8f, 0x7a, 0x0e, 0x30, 0x3d, 0x2e, 0x65, 0x3b, 0x57, 0xd1, 0x76, 0x6b, 0xa8, 0xfa, 0xfc, 0x01, 0x87, 0xd1, 0x55, 0x97, 0xbb, 0x94, 0x2d, 0x98, 0xbc, 0x9d, 0x1d, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x0a, 0x2a, 0x06, 0x8e, 0x79, 0xff, 0x5f, 0xfe, 0xbf, 0xf9, 0x7f, 0xa7, 0xfc, 0xc2, 0x5d, 0xcb, 0xa4, 0xc1, 0xb2, 0xd6, 0xad, 0x7e, 0x30, 0x85, 0xb6, 0x6c, 0xb6, 0xc4, 0x51, 0xd9, 0xb1, 0x68, 0xf2, 0xbe, 0x14, 0xad, 0x31, 0x97, 0x80, 0x00, 0x00, 0x00, 0x11, 0x41, 0x9a, 0x08, 0xd8, 0xf8, 0x0d, 0x20, 0x14, 0xa4, 0x2b, 0xff, 0xfe, 0xda, 0xa6, 0x58, 0xce, 0x81, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x0c, 0x2a, 0x09, 0xe2, 0x56, 0xf9, 0xfe, 0xff, 0xfd, 0x3f, 0x9f, 0xfc, 0xff, 0xeb, 0x89, 0x5c, 0x45, 0xed, 0x90, 0x6c, 0x9c, 0xee, 0xe0, 0xc3, 0x57, 0xf2, 0xe6, 0xe6, 0x52, 0x87, 0x18, 0x76, 0x09, 0xd5, 0x81, 0x7d, 0x37, 0x15, 0x14, 0xe0, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x0c, 0x2a, 0x06, 0x8e, 0x79, 0xfe, 0xdf, 0xfe, 0xdf, 0xbf, 0xff, 0x8f, 0xf9, 0xe6, 0x4a, 0x97, 0x7a, 0xe7, 0xae, 0xf4, 0xd0, 0x8c, 0x8e, 0x00, 0xc1, 0x1b, 0xe7, 0x82, 0x12, 0x94, 0xa9, 0x2b, 0xde, 0x52, 0xd7, 0xae, 0x73, 0x48, 0x9c, 0xe7, 0x39, 0xd9, 0xaf, 0x5e, 0x62, 0x73, 0x8d, 0x78, 0x00, 0x00, 0x00, 0x09, 0x41, 0x9e, 0x10, 0x5e, 0x21, 0x5f, 0x00, 0x05, 0x3c, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x04, 0x2a, 0x09, 0xe2, 0x57, 0x7d, 0xff, 0x7f, 0xfe, 0xbf, 0xe3, 0xff, 0x3f, 0xf6, 0xb2, 0x5c, 0xb6, 0x4a, 0xa0, 0x73, 0x9e, 0x47, 0xd8, 0x45, 0xd1, 0xd1, 0xfa, 0x5d, 0x07, 0x68, 0xcb, 0x5f, 0xea, 0x7f, 0xc1, 0x64, 0x46, 0x4b, 0x12, 0xe0, 0x00, 0x00, 0x00, 0x09, 0x01, 0x9e, 0x18, 0x9a, 0x90, 0x9f, 0x00, 0x0b, 0x29, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x0a, 0x2a, 0x06, 0x8e, 0x79, 0xff, 0x5f, 0xfe, 0xbf, 0xf9, 0x7f, 0xa7, 0xfb, 0xda, 0x4d, 0x55, 0xce, 0x78, 0x6d, 0xa1, 0x19, 0x1f, 0xbe, 0x42, 0x37, 0xc0, 0x24, 0x2b, 0x5a, 0xda, 0xdb, 0xa3, 0x1d, 0x5a, 0xb5, 0x41, 0x0d, 0x4a, 0xb5, 0x2b, 0x0a, 0xae, 0x82, 0xc4, 0x1c, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x0a, 0x2a, 0x09, 0x62, 0x96, 0xf9, 0xfe, 0xff, 0xff, 0x17, 0xfb, 0x7f, 0xdf, 0xfd, 0xae, 0xae, 0x2e, 0xd9, 0x6a, 0x1f, 0x4d, 0xce, 0xbe, 0x85, 0x11, 0x3a, 0x6a, 0x35, 0xa3, 0x18, 0xb8, 0x5a, 0x71, 0x92, 0x73, 0x1a, 0xc5, 0x38, 0x00, 0x00, 0x00, 0x1b, 0x41, 0x9a, 0x19, 0x92, 0xea, 0x04, 0x08, 0x10, 0x16, 0x88, 0x7c, 0x05, 0x90, 0x19, 0x50, 0x16, 0x40, 0x67, 0x00, 0x85, 0x7f, 0xfe, 0xda, 0xa6, 0x58, 0xce, 0x81, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x0c, 0x2a, 0x06, 0x8e, 0x79, 0xfe, 0xdf, 0xfe, 0xdf, 0xcf, 0xff, 0x8f, 0xf8, 0xc3, 0x59, 0xc5, 0x6b, 0x2f, 0x7a, 0x68, 0x46, 0x46, 0x24, 0xf0, 0x8d, 0xf0, 0x7f, 0x0a, 0x52, 0x92, 0xa4, 0xf0, 0xd3, 0x7e, 0xfd, 0xea, 0x5e, 0x8d, 0xe5, 0xd4, 0xde, 0x52, 0x85, 0xef, 0x17, 0x00, 0x00, 0x00, 0x0a, 0x41, 0x9e, 0x21, 0x1b, 0x88, 0x57, 0xff, 0x00, 0x05, 0x3c, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x08, 0x2a, 0x0a, 0x8e, 0xfb, 0xfe, 0x9f, 0xfd, 0x7f, 0x9f, 0xfe, 0x7f, 0xdf, 0x07, 0x09, 0x37, 0xe7, 0xc6, 0x82, 0x52, 0x9c, 0x1d, 0x51, 0xa0, 0x79, 0x8f, 0x31, 0x81, 0x97, 0x3c, 0xc4, 0xbc, 0xc4, 0x86, 0x62, 0xc4, 0x04, 0x06, 0x5c, 0x9e, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x06, 0x2a, 0x06, 0x8e, 0xfb, 0xff, 0x8f, 0xff, 0x6f, 0xfa, 0xff, 0xbf, 0xfc, 0x92, 0x5b, 0x4a, 0xd6, 0x6c, 0x5a, 0xd6, 0xad, 0x70, 0xc2, 0x1b, 0x23, 0x18, 0xfb, 0x0b, 0x46, 0xd6, 0xb2, 0xcb, 0x4e, 0x91, 0xb5, 0xc5, 0x38, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x9e, 0x29, 0x59, 0x24, 0x27, 0xff, 0x00, 0x0b, 0x29, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x0a, 0x2a, 0x0a, 0x8e, 0x79, 0xfe, 0xff, 0xff, 0x17, 0xfd, 0xff, 0xdb, 0xfe, 0x48, 0xbd, 0x4a, 0xe7, 0xe3, 0x30, 0x71, 0x42, 0x16, 0xbb, 0x8c, 0x68, 0xa2, 0x8a, 0x28, 0x81, 0x14, 0x45, 0x12, 0x09, 0x08, 0x0a, 0xca, 0x10, 0xd7, 0x20, 0x11, 0xc0, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x0c, 0x2a, 0x06, 0x8d, 0xf7, 0xfd, 0x3f, 0xfd, 0xbf, 0x7f, 0xfd, 0x7f, 0xe7, 0x0a, 0xbe, 0x2a, 0xf3, 0xaf, 0x14, 0x35, 0xca, 0x58, 0xb3, 0xde, 0x12, 0xd7, 0xaf, 0x5c, 0xe6, 0x94, 0xbc, 0x7e, 0x34, 0xe5, 0x65, 0xa5, 0x38, 0xad, 0x32, 0x5c, 0x00, 0x00, 0x00, 0x1c, 0x41, 0x9a, 0x2a, 0x53, 0xea, 0x04, 0x08, 0x10, 0x16, 0xd6, 0x88, 0x6c, 0x0a, 0x40, 0x49, 0x40, 0xa4, 0x04, 0xb0, 0x00, 0x84, 0xff, 0xfe, 0xd6, 0xa5, 0x50, 0xce, 0x80, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x0a, 0x2a, 0x06, 0x8e, 0xf9, 0xfe, 0xdf, 0xfe, 0xdf, 0xbf, 0xff, 0xa7, 0xf8, 0xdc, 0x92, 0x71, 0x9a, 0xe7, 0x57, 0xb6, 0x84, 0x64, 0x5e, 0x41, 0x08, 0xd9, 0x1c, 0x82, 0xa5, 0x29, 0x2a, 0x4e, 0x74, 0xdf, 0x7d, 0xf4, 0xa5, 0xef, 0x4d, 0xfe, 0x5a, 0x5e, 0xf7, 0xb0, 0xa1, 0x64, 0x29, 0xc0, 0x00, 0x00, 0x00, 0x0a, 0x41, 0x9e, 0x31, 0xd9, 0x62, 0x15, 0xff, 0x00, 0x05, 0x3d, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x00, 0x2a, 0x0a, 0x8f, 0x5d, 0xff, 0x7f, 0xff, 0x8b, 0xfc, 0xff, 0xe5, 0xfe, 0xda, 0xa9, 0xaa, 0xb9, 0xae, 0xf5, 0xcf, 0x02, 0x49, 0x24, 0xc1, 0xd5, 0x18, 0xd2, 0x11, 0x45, 0xdd, 0xfb, 0x08, 0x88, 0x72, 0x64, 0x57, 0x3c, 0x00, 0x90, 0x20, 0x31, 0x2f, 0xf0, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x0a, 0x2a, 0x06, 0x8e, 0x7b, 0xfe, 0xff, 0xfd, 0x7f, 0xf2, 0xff, 0x4f, 0xf7, 0xb3, 0x46, 0x89, 0x36, 0x2d, 0x6b, 0x56, 0xbc, 0xa1, 0x0d, 0x9b, 0x36, 0x23, 0xb3, 0x65, 0xad, 0x6d, 0x88, 0x99, 0x08, 0xda, 0xbe, 0xc4, 0x65, 0xc0, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x9e, 0x3a, 0x19, 0xa4, 0x27, 0xff, 0x00, 0x0b, 0x29, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x0c, 0x2a, 0x0a, 0x8c, 0xe7, 0xfb, 0xff, 0xf5, 0xff, 0x4f, 0xfc, 0xbf, 0xde, 0x24, 0x70, 0x9b, 0xeb, 0xb0, 0xf9, 0x3e, 0xfb, 0xb8, 0x30, 0xc6, 0xe3, 0xc7, 0xe5, 0x14, 0x42, 0x60, 0x45, 0xc5, 0x4f, 0x95, 0x4a, 0x04, 0x70, 0xa5, 0x02, 0x1c, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x0c, 0x2a, 0x06, 0x8e, 0x7b, 0xfe, 0x9f, 0xfe, 0xdf, 0xbf, 0xff, 0x8f, 0xfa, 0x6e, 0x45, 0xea, 0xaf, 0x35, 0xb8, 0xd0, 0x8c, 0x8f, 0x88, 0xc1, 0x1b, 0x24, 0x7e, 0x12, 0x94, 0xa9, 0x2b, 0xde, 0x52, 0x9e, 0xbd, 0x73, 0x25, 0xaf, 0x5e, 0xb9, 0xeb, 0x58, 0x91, 0x61, 0x4e, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x30, 0x2a, 0x0a, 0x8a, 0xad, 0xff, 0xf5, 0xfd, 0xff, 0xdf, 0x89, 0xab, 0xbb, 0xbb, 0x5c, 0x90, 0x44, 0xf2, 0xe4, 0x7d, 0x84, 0xc3, 0x2a, 0x26, 0x50, 0xa8, 0x99, 0x42, 0xa2, 0x7a, 0x85, 0x44, 0xf5, 0x13, 0xa1, 0xea, 0x15, 0x13, 0xc3, 0x80, 0x21, 0x10, 0x04, 0x60, 0x8c, 0x1c, 0x01, 0x56, 0x2a, 0x0a, 0x8a, 0xac, 0xf9, 0xeb, 0xdb, 0x57, 0x77, 0xab, 0x97, 0x24, 0x96, 0x27, 0x5b, 0xc8, 0xce, 0x4a, 0xa1, 0x91, 0x4e, 0x1e, 0x8a, 0x7a, 0x1e, 0x44, 0xf4, 0x3c, 0x89, 0xd6, 0xf2, 0x27, 0x5b, 0xc8, 0xe6, 0x5b, 0xdc }; void Check(bool condition, const std::string& message) { if (!condition) throw std::runtime_error(message); } int LumaFor(int frame) { return 20 + frame * 7; } void WriteMovie() { std::filesystem::create_directories("app0"); std::ofstream file(MoviePath, std::ios::binary | std::ios::trunc); file.write(reinterpret_cast(Movie.data()), static_cast(Movie.size())); Check(static_cast(file), "cannot write the movie"); } struct Block { bool texture; std::align_val_t alignment; }; struct Allocations { std::mutex mutex; std::map blocks; int textures = 0; std::optional textureLimit; }; Allocations allocations; int ActiveTextureCountLocked() { return static_cast(std::count_if(allocations.blocks.begin(), allocations.blocks.end(), [](const auto& allocation) { return allocation.second.texture; })); } void* Allocate(std::uint32_t alignment, std::uint32_t size, bool texture) { const auto aligned = static_cast(std::max(alignment, 16)); { std::lock_guard lock(allocations.mutex); if (texture && allocations.textureLimit && ActiveTextureCountLocked() >= *allocations.textureLimit) return nullptr; } void* memory = ::operator new(size, aligned); std::lock_guard lock(allocations.mutex); allocations.blocks[memory] = {texture, aligned}; if (texture) ++allocations.textures; return memory; } void Release(void* memory, bool texture) { std::align_val_t aligned{}; { std::lock_guard lock(allocations.mutex); const auto found = allocations.blocks.find(memory); if (found == allocations.blocks.end() || found->second.texture != texture) std::abort(); aligned = found->second.alignment; allocations.blocks.erase(found); } ::operator delete(memory, aligned); } void* APS5_VABI AllocateMemory(void*, std::uint32_t alignment, std::uint32_t size) { return Allocate(alignment, size, false); } void APS5_VABI DeallocateMemory(void*, void* memory) { Release(memory, false); } void* APS5_VABI AllocateTexture(void*, std::uint32_t alignment, std::uint32_t size) { return Allocate(alignment, size, true); } void APS5_VABI DeallocateTexture(void*, void* memory) { Release(memory, true); } bool IsAllocation(const void* memory, bool texture) { std::lock_guard lock(allocations.mutex); const auto found = allocations.blocks.find(const_cast(memory)); return found != allocations.blocks.end() && found->second.texture == texture; } void SetTextureLimit(std::optional limit) { std::lock_guard lock(allocations.mutex); allocations.textureLimit = limit; } int TextureCount() { std::lock_guard lock(allocations.mutex); return ActiveTextureCountLocked(); } struct Events { std::mutex mutex; std::vector> received; bool Seen(std::int32_t id, std::int32_t warning = 0) { std::lock_guard lock(mutex); return std::any_of(received.begin(), received.end(), [&](const auto& event) { return event.first == id && event.second == warning; }); } void Clear() { std::lock_guard lock(mutex); received.clear(); } }; void APS5_VABI OnEvent(void* object, std::int32_t id, std::int32_t source, void* data) { auto* events = static_cast(object); if (source != 0 || (id == EventWarning) != (data != nullptr)) std::abort(); std::lock_guard lock(events->mutex); events->received.emplace_back(id, id == EventWarning ? *static_cast(data) : 0); } void APS5_VABI OnLog(void*, const char*) {} struct HostFile { std::ifstream stream; std::uint64_t size = 0; }; std::int32_t APS5_VABI OpenFile(void* object, const char* path) { auto* file = static_cast(object); if (std::strcmp(path, "/app0/replaced.mp4") != 0) return -1; file->stream.open(MoviePath, std::ios::binary); file->size = std::filesystem::file_size(MoviePath); return file->stream ? 0 : -1; } std::int32_t APS5_VABI CloseFile(void* object) { static_cast(object)->stream.close(); return 0; } std::int32_t APS5_VABI ReadFile(void* object, std::uint8_t* buffer, std::uint64_t position, std::uint32_t length) { auto* file = static_cast(object); file->stream.clear(); file->stream.seekg(static_cast(position)); file->stream.read(reinterpret_cast(buffer), length); return static_cast(file->stream.gcount()); } std::uint64_t APS5_VABI FileSize(void* object) { return static_cast(object)->size; } bool WaitFor(const std::function& condition, int milliseconds = 5000) { const auto deadline = std::chrono::steady_clock::now() + std::chrono::milliseconds(milliseconds); while (std::chrono::steady_clock::now() < deadline) { if (condition()) return true; std::this_thread::sleep_for(std::chrono::milliseconds(1)); } return condition(); } AvPlayerInitData InitData(Events* events) { AvPlayerInitData init{}; init.memory_replacement = {nullptr, AllocateMemory, DeallocateMemory, AllocateTexture, DeallocateTexture}; init.event_replacement = {events, events ? OnEvent : nullptr}; init.num_output_video_framebuffers = 4; init.default_language = "eng"; return init; } int FrameIndex(std::uint64_t timestamp) { return static_cast((timestamp * FrameRate + 500) / 1000); } void CheckVideoPicture(const AvPlayerFrameInfoEx& info) { const auto& video = info.details.video; Check(video.width == 112 && video.height == 64 && video.pitch == Pitch, "unexpected frame geometry"); Check(video.crop_left_offset == 0 && video.crop_top_offset == 0 && video.crop_right_offset == Pitch - Width && video.crop_bottom_offset == 4, "unexpected crop offsets"); Check(video.luma_bit_depth == 8 && video.chroma_bit_depth == 8, "unexpected bit depth"); Check(std::fabs(video.aspect_ratio - static_cast(Width) / Height) < 0.01f, "unexpected aspect ratio"); Check(std::memcmp(video.language_code, "eng", 4) == 0, "missing video language"); const int index = FrameIndex(info.timestamp); Check(index >= 0 && index < FrameCount, "frame timestamp out of range"); const auto* luma = static_cast(info.p_data); const auto* chroma = luma + Pitch * 64; for (const int row : {2, 30, 57, 63}) { Check(std::abs(luma[row * Pitch + 10] - LumaFor(index)) <= 6, "left luma mismatch for frame " + std::to_string(index)); Check(std::abs(luma[row * Pitch + 90] - (255 - LumaFor(index))) <= 6, "right luma mismatch for frame " + std::to_string(index)); } for (const int row : {0, 15, 31}) { Check(std::abs(chroma[row * Pitch + 20] - 128) <= 6 && std::abs(chroma[row * Pitch + 21] - 128) <= 6, "chroma mismatch"); } } void CheckVideoFrame(const AvPlayerFrameInfoEx& info) { CheckVideoPicture(info); Check(IsAllocation(info.p_data, true), "video frame is not a texture allocation"); } int Loudest(const AvPlayerFrameInfo& info) { const auto* samples = reinterpret_cast(info.p_data); int loudest = 0; for (std::uint32_t index = 0; index < info.details.audio.size / sizeof(std::int16_t); ++index) loudest = std::max(loudest, std::abs(static_cast(samples[index]))); return loudest; } void CheckAudioFrame(const AvPlayerFrameInfo& info, std::uint16_t channels, const char* language) { Check(info.details.audio.channel_count == channels && info.details.audio.sample_rate == SampleRate, "unexpected audio format"); Check(info.details.audio.size > 0 && info.details.audio.size <= 1024u * channels * 2 && info.details.audio.size % (channels * 2u) == 0, "unexpected audio size"); Check(std::memcmp(info.details.audio.language_code, language, 4) == 0, "unexpected audio language"); Check(IsAllocation(info.p_data, false), "audio frame is not a plain allocation"); } void CheckEnglishAudio(const AvPlayerFrameInfo& info) { CheckAudioFrame(info, 2, "eng"); Check(Loudest(info) <= 16, "the English track is not silent"); } void CheckStreamInfo(AvPlayerInternal* player) { Check(sceAvPlayerStreamCount(player) == 3, "unexpected stream count"); for (std::uint32_t index = 0; index < 3; ++index) { AvPlayerStreamInfo info{}; Check(sceAvPlayerGetStreamInfo(player, index, &info) == 0, "stream info failed"); Check(info.duration >= 950 && info.duration <= 1100, "unexpected stream duration"); if (index == VideoStream) { Check(info.type == 1, "video stream type"); Check(info.details.video.width == 112 && info.details.video.height == 64, "unexpected video stream size"); Check(std::strcmp(info.details.video.language_code, "eng") == 0, "unexpected video language"); } else { const bool english = index == EnglishAudioStream; Check(info.type == 0, "audio stream type"); Check(info.details.audio.channel_count == (english ? 2 : 1) && info.details.audio.sample_rate == SampleRate, "unexpected audio stream"); Check(std::strcmp(info.details.audio.language_code, english ? "eng" : "fra") == 0, "unexpected audio language"); } } AvPlayerStreamInfo unused{}; Check(sceAvPlayerGetStreamInfo(player, 3, &unused) == OperationFailed, "invalid stream accepted"); Check(sceAvPlayerGetStreamInfo(player, 0, nullptr) == InvalidParams, "null stream info accepted"); } void CheckStreamInfoEx(AvPlayerInternal* player) { for (std::uint32_t index = 0; index < 3; ++index) { AvPlayerStreamInfoEx info{}; info.this_size = sizeof(info); Check(sceAvPlayerGetStreamInfoEx(player, index, &info) == 0, "extended stream info failed"); Check(info.this_size == sizeof(info), "extended stream info size overwritten"); Check(info.duration >= 950 && info.duration <= 1100, "unexpected extended stream duration"); if (index == VideoStream) { const auto& video = info.details.video; Check(info.type == 1, "extended video stream type"); Check(video.width == 112 && video.height == 64 && video.pitch == Pitch, "unexpected extended video geometry"); Check(video.crop_left_offset == 0 && video.crop_top_offset == 0 && video.crop_right_offset == Pitch - Width && video.crop_bottom_offset == 4, "unexpected extended crop offsets"); Check(video.luma_bit_depth == 8 && video.chroma_bit_depth == 8 && !video.video_full_range_flag, "unexpected extended video format"); Check(std::fabs(video.aspect_ratio - static_cast(Width) / Height) < 0.01f, "unexpected extended aspect ratio"); Check(std::memcmp(video.language_code, "eng", 4) == 0, "unexpected extended video language"); } else { const bool english = index == EnglishAudioStream; const auto& audio = info.details.audio; Check(info.type == 0, "extended audio stream type"); Check(audio.channel_count == (english ? 2 : 1) && audio.sample_rate == SampleRate, "unexpected extended audio stream"); Check(std::memcmp(audio.language_code, english ? "eng" : "fra", 4) == 0, "unexpected extended audio language"); } } AvPlayerStreamInfoEx unused{}; Check(sceAvPlayerGetStreamInfoEx(player, 3, &unused) == OperationFailed, "invalid extended stream accepted"); Check(sceAvPlayerGetStreamInfoEx(player, 0, nullptr) == InvalidParams, "null extended stream info accepted"); Check(sceAvPlayerGetStreamInfoEx(nullptr, 0, &unused) == InvalidParams, "null player accepted"); } void TestPlayback() { Events events; AvPlayerInitData init = InitData(&events); auto* player = sceAvPlayerInit(&init); Check(player != nullptr, "init failed"); AvPlayerPostInitData post{}; post.demux_video_buffer_size = 64 * 1024; Check(sceAvPlayerPostInit(player, &post) == 0, "post init failed"); Check(sceAvPlayerPostInit(player, nullptr) == InvalidParams, "post init accepted null data"); Check(sceAvPlayerStreamCount(player) == OperationFailed, "stream count without a source"); Check(!sceAvPlayerIsActive(player), "active without a source"); Check(sceAvPlayerAddSource(player, "/app0/missing.mp4") == OperationFailed, "missing file accepted"); Check(sceAvPlayerAddSource(player, "/app0/avplayer.mp4") == 0, "add source failed"); Check(sceAvPlayerAddSource(player, "/app0/avplayer.mp4") == OperationFailed, "second source accepted"); Check(WaitFor([&] { return events.Seen(EventReady); }), "ready event missing"); CheckStreamInfo(player); Check(sceAvPlayerEnableStream(player, 7) == OperationFailed, "invalid stream enabled"); Check(sceAvPlayerEnableStream(player, VideoStream) == 0, "enable video failed"); Check(sceAvPlayerEnableStream(player, EnglishAudioStream) == 0, "enable audio failed"); Check(sceAvPlayerIsActive(player), "not active before start"); Check(sceAvPlayerPause(player) == OperationFailed, "pause accepted before start"); Check(sceAvPlayerStart(player) == 0, "start failed"); Check(WaitFor([&] { return events.Seen(EventPlay); }), "play event missing"); AvPlayerFrameInfoEx frame{}; AvPlayerFrameInfo sound{}; int frames = 0; int sounds = 0; std::uint64_t last = 0; Check(WaitFor([&] { if (sceAvPlayerGetAudioData(player, &sound)) { CheckEnglishAudio(sound); ++sounds; } if (sceAvPlayerGetVideoDataEx(player, &frame)) { CheckVideoFrame(frame); Check(frames == 0 || frame.timestamp > last, "video timestamps not increasing"); last = frame.timestamp; ++frames; } return frames >= 8 && sounds >= 8; }), "playback stalled"); Check(sceAvPlayerCurrentTime(player) > 0, "clock not running"); Check(sceAvPlayerSetTrickSpeed(player, 0) == InvalidParams, "zero trick speed accepted"); Check(sceAvPlayerSetTrickSpeed(player, 100) == 0, "normal trick speed rejected"); Check(sceAvPlayerPause(player) == 0, "pause failed"); Check(WaitFor([&] { return events.Seen(EventPause); }), "pause event missing"); const auto paused = sceAvPlayerCurrentTime(player); std::this_thread::sleep_for(std::chrono::milliseconds(100)); Check(!sceAvPlayerGetVideoDataEx(player, &frame) && !sceAvPlayerGetAudioData(player, &sound), "data delivered while paused"); Check(sceAvPlayerCurrentTime(player) == paused, "clock moved while paused"); Check(sceAvPlayerIsActive(player), "inactive while paused"); events.Clear(); Check(sceAvPlayerResume(player) == 0, "resume failed"); Check(sceAvPlayerResume(player) == OperationFailed, "resume accepted while playing"); Check(WaitFor([&] { return events.Seen(EventPlay); }), "resume event missing"); Check(sceAvPlayerJumpToTime(player, 700) == 0, "jump failed"); Check(WaitFor([&] { return events.Seen(EventWarning, JumpComplete); }), "jump completion missing"); Check(WaitFor([&] { return sceAvPlayerGetVideoDataEx(player, &frame) != 0; }), "no frame after the jump"); CheckVideoFrame(frame); Check(frame.timestamp >= 700 && frame.timestamp <= 767, "jump landed at " + std::to_string(frame.timestamp)); events.Clear(); const auto forward = sceAvPlayerCurrentTime(player); Check(sceAvPlayerSetTrickSpeed(player, -100) == 0, "reverse trick speed rejected"); std::this_thread::sleep_for(std::chrono::milliseconds(200)); Check(!sceAvPlayerGetVideoDataEx(player, &frame) && !sceAvPlayerGetAudioData(player, &sound), "data delivered in reverse"); const auto rewound = sceAvPlayerCurrentTime(player); Check(rewound + 150 <= forward, "clock did not run backwards: " + std::to_string(forward) + " to " + std::to_string(rewound)); Check(sceAvPlayerSetTrickSpeed(player, 100) == 0, "forward trick speed rejected after reverse"); Check(WaitFor([&] { return sceAvPlayerGetVideoDataEx(player, &frame) != 0; }), "no frame after reverse"); CheckVideoFrame(frame); Check(frame.timestamp + 100 >= rewound && frame.timestamp <= rewound + 100, "playback resumed at " + std::to_string(frame.timestamp) + " after rewinding to " + std::to_string(rewound)); Check(!events.Seen(EventWarning, JumpComplete), "rewinding reported a jump"); Check(sceAvPlayerSetAvSyncMode(player, 2) == InvalidParams, "invalid sync mode accepted"); Check(sceAvPlayerSetAvSyncMode(player, 1) == 0, "sync mode rejected"); Check(WaitFor([&] { if (sceAvPlayerGetVideoDataEx(player, &frame)) { CheckVideoFrame(frame); last = frame.timestamp; } while (sceAvPlayerGetAudioData(player, &sound)) CheckEnglishAudio(sound); return !sceAvPlayerIsActive(player); }), "playback never ended"); Check(FrameIndex(last) >= FrameCount - 2, "last frame missing"); Check(WaitFor([&] { return events.Seen(EventStop); }), "end of stream stop event missing"); Check(sceAvPlayerCurrentTime(player) >= 950, "clock not at the end"); Check(sceAvPlayerStop(player) == 0, "stop after the end failed"); events.Clear(); Check(sceAvPlayerSetLooping(player, 1) == 0, "looping rejected"); Check(sceAvPlayerStart(player) == 0, "restart failed"); bool wrapped = false; last = 0; frames = 0; Check(WaitFor([&] { while (sceAvPlayerGetAudioData(player, &sound)) CheckEnglishAudio(sound); if (sceAvPlayerGetVideoDataEx(player, &frame)) { CheckVideoFrame(frame); if (frames > 0 && frame.timestamp < last) wrapped = true; last = frame.timestamp; ++frames; } return wrapped && frames > FrameCount + 5; }), "looping never wrapped"); Check(events.Seen(EventWarning, LoopingBack), "looping warning missing"); Check(sceAvPlayerIsActive(player), "looping player went inactive"); Check(sceAvPlayerStop(player) == 0, "stop failed"); Check(sceAvPlayerStop(player) == OperationFailed, "second stop accepted"); Check(!sceAvPlayerIsActive(player), "active after stop"); Check(WaitFor([&] { return events.Seen(EventStop); }), "stop event missing"); Check(sceAvPlayerClose(player) == 0, "close failed"); Check(sceAvPlayerClose(nullptr) == InvalidParams, "null close accepted"); std::lock_guard lock(allocations.mutex); Check(allocations.blocks.empty(), "allocations leaked"); Check(allocations.textures >= 4, "video buffers not allocated as textures"); } void TestChangeStream() { Events events; AvPlayerInitData init = InitData(&events); auto* player = sceAvPlayerInit(&init); Check(player != nullptr, "init failed"); Check(sceAvPlayerChangeStream(player, EnglishAudioStream, FrenchAudioStream) == OperationFailed, "stream changed without a source"); Check(sceAvPlayerAddSource(player, "/app0/avplayer.mp4") == 0, "add source failed"); Check(WaitFor([&] { return events.Seen(EventReady); }), "ready event missing"); Check(sceAvPlayerChangeStream(nullptr, EnglishAudioStream, FrenchAudioStream) == InvalidParams, "null player accepted"); Check(sceAvPlayerEnableStream(player, VideoStream) == 0, "enable video failed"); Check(sceAvPlayerEnableStream(player, EnglishAudioStream) == 0, "enable audio failed"); Check(sceAvPlayerChangeStream(player, VideoStream, FrenchAudioStream) == OperationFailed, "video changed to audio"); Check(sceAvPlayerChangeStream(player, EnglishAudioStream, 9) == OperationFailed, "changed to a missing stream"); Check(sceAvPlayerChangeStream(player, FrenchAudioStream, EnglishAudioStream) == OperationFailed, "changed from a disabled stream"); Check(sceAvPlayerChangeStream(player, EnglishAudioStream, FrenchAudioStream) == 0, "change before start failed"); Check(sceAvPlayerChangeStream(player, FrenchAudioStream, EnglishAudioStream) == 0, "change back before start failed"); Check(sceAvPlayerStart(player) == 0, "start failed"); AvPlayerFrameInfo sound{}; AvPlayerFrameInfoEx frame{}; int english = 0; Check(WaitFor([&] { if (sceAvPlayerGetAudioData(player, &sound)) { CheckEnglishAudio(sound); ++english; } return english >= 2; }), "no English audio"); events.Clear(); Check(sceAvPlayerChangeStream(player, EnglishAudioStream, FrenchAudioStream) == 0, "change to the French track failed"); int french = 0; int loudest = 0; Check(WaitFor([&] { if (sceAvPlayerGetAudioData(player, &sound)) { if (french == 0 && std::memcmp(sound.details.audio.language_code, "eng", 4) == 0) { CheckEnglishAudio(sound); } else { CheckAudioFrame(sound, 1, "fra"); loudest = std::max(loudest, Loudest(sound)); ++french; } } return french >= 4; }), "no French audio after the change"); Check(loudest > 1000, "the French track decoded silent"); Check(WaitFor([&] { return sceAvPlayerGetVideoDataEx(player, &frame) != 0; }), "no video after the change"); CheckVideoFrame(frame); Check(!events.Seen(EventWarning, JumpComplete), "changing streams reported a jump"); Check(sceAvPlayerChangeStream(player, EnglishAudioStream, FrenchAudioStream) == OperationFailed, "changed from the replaced stream"); Check(sceAvPlayerClose(player) == 0, "close failed"); std::lock_guard lock(allocations.mutex); Check(allocations.blocks.empty(), "allocations leaked"); } void TestExtendedExports() { Events events; AvPlayerInitData init = InitData(&events); auto* player = sceAvPlayerInit(&init); Check(player != nullptr, "init failed"); Check(sceAvPlayerSetLogCallback(reinterpret_cast(&OnLog), nullptr) == 0, "log callback rejected"); Check(sceAvPlayerSetAvailableBandwidth(player, 4000, 1000, 8000) == 0, "bandwidth rejected"); Check(sceAvPlayerSetAvailableBandwidth(nullptr, 4000, 1000, 8000) == InvalidParams, "bandwidth accepted for a null player"); Check(sceAvPlayerAddSource(player, "/app0/avplayer.mp4") == 0, "add source failed"); Check(WaitFor([&] { return events.Seen(EventReady); }), "ready event missing"); CheckStreamInfoEx(player); Check(sceAvPlayerEnableStream(player, VideoStream) == 0, "enable video failed"); Check(sceAvPlayerStartEx(nullptr, nullptr) == InvalidParams, "start accepted a null player"); Check(sceAvPlayerStartEx(player, nullptr) == 0, "extended start failed"); Check(WaitFor([&] { return events.Seen(EventPlay); }), "play event missing"); AvPlayerFrameInfoEx frame{}; Check(WaitFor([&] { return sceAvPlayerGetVideoDataEx(player, &frame) != 0; }), "no frame after the extended start"); CheckVideoFrame(frame); Check(sceAvPlayerClose(player) == 0, "close failed"); } void TestWithoutAllocators() { AvPlayerInitData init = InitData(nullptr); init.memory_replacement = {}; auto* player = sceAvPlayerInit(&init); Check(player != nullptr, "init without allocators failed"); Check(sceAvPlayerAddSource(player, "/app0/avplayer.mp4") == 0, "add source failed"); AvPlayerFrameInfoEx frame{}; Check(WaitFor([&] { return sceAvPlayerGetVideoDataEx(player, &frame) != 0; }), "no frame without allocators"); CheckVideoPicture(frame); Check(!IsAllocation(frame.p_data, true) && !IsAllocation(frame.p_data, false), "frame came from a missing allocator"); Check(sceAvPlayerClose(player) == 0, "close failed"); AvPlayerInitDataEx extended{}; extended.this_size = sizeof(extended); AvPlayerInternal* handle = nullptr; Check(sceAvPlayerInitEx(&extended, &handle) == 0 && handle != nullptr, "extended init without allocators failed"); Check(sceAvPlayerInitEx(nullptr, &handle) == InvalidParams, "extended init accepted null data"); Check(sceAvPlayerClose(handle) == 0, "close failed"); } void TestOptionalVideoBuffersRespectMemoryLimit() { const auto run = [](int textureLimit, int expectedTextures) { SetTextureLimit(textureLimit); AvPlayerInitData init = InitData(nullptr); init.num_output_video_framebuffers = 2; auto* player = sceAvPlayerInit(&init); Check(player != nullptr, "init with limited texture memory failed"); Check(sceAvPlayerAddSource(player, "/app0/avplayer.mp4") == 0, "add source with limited texture memory failed"); Check(WaitFor([&] { return TextureCount() == expectedTextures && sceAvPlayerIsActive(player); }), "unexpected optional video buffer count"); AvPlayerFrameInfoEx frame{}; Check(WaitFor([&] { return sceAvPlayerGetVideoDataEx(player, &frame) != 0; }), "no frame with limited texture memory"); CheckVideoPicture(frame); Check(sceAvPlayerClose(player) == 0, "close with limited texture memory failed"); Check(TextureCount() == 0, "limited texture allocations were not released"); }; run(2, 2); run(4, 2); run(6, 6); SetTextureLimit(std::nullopt); } void TestFileReplacementAutoStart() { HostFile file; AvPlayerInitData init = InitData(nullptr); init.file_replacement = {&file, OpenFile, CloseFile, ReadFile, FileSize}; auto* player = sceAvPlayerInit(&init); Check(player != nullptr, "init failed"); Check(sceAvPlayerAddSource(player, "/app0/replaced.mp4") == 0, "replaced source failed"); AvPlayerFrameInfo frame{}; Check(WaitFor([&] { return sceAvPlayerGetVideoData(player, &frame) != 0; }), "auto start never produced a frame"); Check(frame.details.video.width == 112 && frame.details.video.height == 64 && IsAllocation(frame.p_data, true), "unexpected auto start frame"); Check(sceAvPlayerClose(player) == 0, "close failed"); Check(!file.stream.is_open(), "replaced file left open"); } void TestHandedOutFramesStayIntact() { constexpr int Buffers = 6; constexpr int Retained = Buffers - 2; AvPlayerInitData init = InitData(nullptr); init.num_output_video_framebuffers = Buffers; auto* player = sceAvPlayerInit(&init); Check(player != nullptr, "init failed"); Check(sceAvPlayerSetAvSyncMode(player, 1) == 0, "sync mode rejected"); Check(sceAvPlayerAddSource(player, "/app0/avplayer.mp4") == 0, "add source failed"); struct Taken { const std::uint8_t* luma; int index; }; std::deque taken; for (int round = 0; round < 16; ++round) { AvPlayerFrameInfoEx frame{}; Check(WaitFor([&] { return sceAvPlayerGetVideoDataEx(player, &frame) != 0; }), "no frame for round " + std::to_string(round)); CheckVideoFrame(frame); taken.push_back({static_cast(frame.p_data), FrameIndex(frame.timestamp)}); if (taken.size() > Retained) taken.pop_front(); std::this_thread::sleep_for(std::chrono::milliseconds(30)); for (std::size_t k = 0; k < taken.size(); ++k) { for (std::size_t other = k + 1; other < taken.size(); ++other) Check(taken[k].luma != taken[other].luma, "one buffer handed out twice among the last " + std::to_string(Retained) + " frames"); const int index = taken[k].index; Check(std::abs(taken[k].luma[30 * Pitch + 10] - LumaFor(index)) <= 6, "frame " + std::to_string(index) + " was overwritten " + std::to_string(taken.size() - 1 - k) + " frames after it was handed out"); } } Check(sceAvPlayerClose(player) == 0, "close failed"); } } int main() { try { WriteMovie(); TestPlayback(); TestChangeStream(); TestExtendedExports(); TestWithoutAllocators(); TestOptionalVideoBuffersRespectMemoryLimit(); TestFileReplacementAutoStart(); TestHandedOutFramesStayIntact(); std::puts("AvPlayer tests passed"); return 0; } catch (const std::exception& error) { std::fprintf(stderr, "%s\n", error.what()); return 1; } }