// Copyright (c) 2026- PPSSPP Project. // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, version 2.0 or later versions. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License 2.0 for more details. // A copy of the GPL 2.0 should have been included with the program. // If not, see http://www.gnu.org/licenses/ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #pragma once #include #include "Common/CommonTypes.h" struct AVCodecContext; struct AVFrame; // A plain "hand it one access unit, get a frame back" H.264 decoder. // // This exists for sceVideocodec, which is a low level interface to the PSP Media Engine. // PPSSPP's MediaEngine can't serve that - it is built around sceMpeg's own model, with the // PSMF demuxer, the ringbuffer and its own frame pacing wrapped around the decoder, so this // is a second path in addition to that. Implementing the old path around this might happen later. // // Output is whatever pixel format the decoder produced, normally YUV420P; the caller converts. class AvcDecoder { public: AvcDecoder(); ~AvcDecoder(); // Not copyable. AvcDecoder(const AvcDecoder &) = delete; AvcDecoder &operator=(const AvcDecoder &) = delete; // Decodes one access unit. Returns true when a frame came out - H.264 reorders, so a frame // is not produced for every unit fed in, and that is not an error. bool Decode(const u8 *data, int size); // Throws away any decoder state, for a seek or a new stream. void Flush(); bool HasFrame() const { return haveFrame_; } int Width() const { return width_; } int Height() const { return height_; } // Only meaningful while HasFrame(). Planes are Y, Cb, Cr; strides are in bytes and are not // necessarily the width. const u8 *Plane(int index) const; int Stride(int index) const; // True if we were built without ffmpeg, in which case nothing decodes. static bool IsAvailable(); private: AVCodecContext *codecCtx_ = nullptr; AVFrame *frame_ = nullptr; // The access unit, copied so we can pad it - ffmpeg reads a little past the end of a packet. // Kept between calls so the usual case doesn't allocate. std::vector packetBuf_; bool haveFrame_ = false; int width_ = 0; int height_ = 0; };