33 unsigned maxWidth_,
unsigned height_,
bool canDoInterlace_)
36 , renderSettings(display_.getRenderSettings())
41 , canDoInterlace(canDoInterlace_)
42 , lastRotate(motherBoard_.getCurrentTime())
43 , eventDistributor(motherBoard_.getReactor().getEventDistributor())
67 "Video recording stopped, because you "
68 "changed machine or changed a video setting "
86 std::unique_ptr<RawFrame> finishedFrame, EmuTime::param time)
89 auto delta = time - lastRotate;
90 auto middle = time + delta / 2;
98 bool doDeinterlace =
false;
99 bool doInterlace =
false;
100 bool doDeflicker =
false;
101 auto currType = finishedFrame->getField();
102 if (canDoInterlace) {
105 doDeinterlace =
true;
121 assert(recycleIdx < 4);
122 auto recycleFrame = std::move(
lastFrames[recycleIdx]);
144 doDeinterlace =
false;
157 }
else if (doInterlace) {
162 }
else if (doDeflicker) {
179 "Recording stopped with error: ",
187 if (canDoInterlace) {
188 if (!recycleFrame) [[unlikely]] {
189 recycleFrame = std::make_unique<RawFrame>(
198void PostProcessor::executeUntil(EmuTime::param )
202 Event::create<FinishFrameEvent>(
206using WorkBuffer = std::vector<MemBuffer<char, SSE_ALIGNMENT>>;
207static void getScaledFrame(
FrameSource& paintFrame,
unsigned bpp,
208 std::span<const void*> lines,
211 auto height = narrow<unsigned>(lines.size());
212 unsigned width = (height == 240) ? 320 : 640;
213 unsigned pitch = width * ((bpp == 32) ? 4 : 2);
214 const void* linePtr =
nullptr;
215 void* work =
nullptr;
216 for (
auto i :
xrange(height)) {
217 if (linePtr == work) {
220 work = workBuffer.emplace_back(pitch).data();
225 auto* work2 =
static_cast<uint32_t*
>(work);
227 auto line = paintFrame.
getLinePtr320_240(i, std::span<uint32_t, 320>{work2, 320});
228 linePtr = line.data();
230 assert (height == 480);
231 auto line = paintFrame.
getLinePtr640_480(i, std::span<uint32_t, 640>{work2, 640});
232 linePtr = line.data();
239 auto* work2 =
static_cast<uint16_t*
>(work);
241 auto line = paintFrame.
getLinePtr320_240(i, std::span<uint16_t, 320>{work2, 320});
242 linePtr = line.data();
244 assert (height == 480);
245 auto line = paintFrame.
getLinePtr640_480(i, std::span<uint16_t, 640>{work2, 640});
246 linePtr = line.data();
260 VLA(
const void*, lines, height2);
263 unsigned width = (height2 == 240) ? 320 : 640;
void addImage(FrameSource *frame, EmuTime::param time)
void printWarning(std::string_view message)
static std::unique_ptr< Deflicker > create(const PixelFormat &format, std::span< std::unique_ptr< RawFrame >, 4 > lastFrames)
Represents the output window/screen of openMSX.
CliComm & getCliComm() const
void distributeEvent(Event &&event)
Schedule the given event for delivery.
Interface for getting lines from a video frame.
std::span< const Pixel, 640 > getLinePtr640_480(unsigned line, std::span< Pixel, 640 > buf) const
Get a pointer to a given line in this frame, the frame is scaled to 640x480 pixels.
virtual unsigned getLineWidth(unsigned line) const =0
Gets the number of display pixels on the given line.
std::span< const Pixel, 320 > getLinePtr320_240(unsigned line, std::span< Pixel, 320 > buf) const
Get a pointer to a given line in this frame, the frame is scaled to 320x240 pixels.
@ FIELD_NONINTERLACED
Interlacing is off for this frame.
@ FIELD_ODD
Interlacing is on and this is an odd frame.
const PixelFormat & getPixelFormat() const
A frame buffer where pixels can be written to.
const PixelFormat & getPixelFormat() const
virtual std::unique_ptr< RawFrame > rotateFrames(std::unique_ptr< RawFrame > finishedFrame, EmuTime::param time)
Sets up the "abcdFrame" variables for a new frame.
PostProcessor(MSXMotherBoard &motherBoard, Display &display, OutputSurface &screen, const std::string &videoSource, unsigned maxWidth, unsigned height, bool canDoInterlace)
void takeRawScreenShot(unsigned height, const std::string &filename) override
Create a raw (=non-post-processed) screenshot.
FrameSource * paintFrame
Represents a frame as it should be displayed.
std::unique_ptr< SuperImposedFrame > superImposedFrame
Result of superimposing 2 frames.
unsigned getBpp() const
Get the number of bits per pixel for the pixels in these frames.
static unsigned getLineWidth(FrameSource *frame, unsigned y, unsigned step)
Returns the maximum width for lines [y..y+step).
std::unique_ptr< DeinterlacedFrame > deinterlacedFrame
Combined the last two frames in a deinterlaced frame.
const FrameSource * superImposeVdpFrame
std::array< std::unique_ptr< RawFrame >, 4 > lastFrames
The last 4 fully rendered (unscaled) MSX frames.
std::unique_ptr< DoubledFrame > interlacedFrame
Each line of the last frame twice, to get double vertical resolution.
RenderSettings & renderSettings
Render settings.
std::unique_ptr< Deflicker > deflicker
Combine the last 4 frames into one 'flicker-free' frame.
AviRecorder * recorder
Video recorder, nullptr when not recording.
~PostProcessor() override
OutputSurface & screen
The surface which is visible to the user.
bool getDeflicker() const
Deflicker [on, off].
bool getDeinterlace() const
Deinterlacing [on, off].
bool getInterleaveBlackFrame() const
Is black frame interleaving enabled?
Every class that wants to get scheduled at some point must inherit from this class.
void setSyncPoint(EmuTime::param timestamp)
static std::unique_ptr< SuperImposedFrame > create(const PixelFormat &format)
int getVideoSource() const
Returns the ID for this VideoLayer.
int getVideoSourceSetting() const
This file implemented 3 utility functions:
std::vector< MemBuffer< char, SSE_ALIGNMENT > > WorkBuffer
const T & get(const Event &event)
auto max_value(InputIterator first, InputIterator last, Proj proj={})
#define VLA(TYPE, NAME, LENGTH)
constexpr auto xrange(T e)