jPSXdec is a cross-platform PlayStation 1 media decoder/converter.
Get the latest version here.

Saturday, February 2, 2008

Amalgamation

Been busy with a bunch of different aspects of jpsxdec. Only the GUI and Code Design will be in the next release (v0.31 today!). The rest will show up in releases after that.

GUI
Even though it's a pretty lame GUI now, I hope it will drop the bar of entry a little.


Code Design
I had difficulty deciding on highest-level interface between the GUI/CLI and the logic. So I set it aside and worked on other things.

PSX YUV->yuv4mpeg2 conversion matrix
This will allow jpsxdec to output more accurate .yuv image sequences.

Frame Rate Calculation
I thought it was a good idea to guess the exact FF7 frame rate algorithm via trial-and-error. 8 hours later I finally saw that FF7 frame lengths do actually follow a pattern, but a ridiculous one. I hoped it would come to a frame rate of exactly 15/100.1% (half the rate of NTSC). That is close, but there was no way I could guess the underlying algorithm of this...


if (iMovieType == WACKED_NTSC1 && iThisFrame == 101)
iThisFrameLength = 11;
if (iMovieType == WACKED_NTSC2 && iThisFrame == 100)
iThisFrameLength = 11;
else if (iThisFrame == 200)
iThisFrameLength = 11;
else if (iThisFrame >= 203 && iThisFrame <= 298) {
if (((iThisFrame - 203) % 4) == 0)
iThisFrameLength = 11;
else if (((iThisFrame - 203) % 4) == 1)
iThisFrameLength = 9;
else
iThisFrameLength = 10;
}
else if (iThisFrame == 299)
iThisFrameLength = 11;
else if (iThisFrame >= 303 && iThisFrame <= 398) {
if (((iThisFrame - 303) % 4) == 0)
iThisFrameLength = 11;
else if (((iThisFrame - 303) % 4) == 1)
iThisFrameLength = 9;
else
iThisFrameLength = 10;
}
else if (iThisFrame == 399)
iThisFrameLength = 11;
else if (iThisFrame >= 402 && iThisFrame < 497) {
if (((iThisFrame - 402) % 4) == 0)
iThisFrameLength = 11;
else if (((iThisFrame - 402) % 4) == 2)
iThisFrameLength = 9;
else
iThisFrameLength = 10;
}
else if (iThisFrame == 498)
iThisFrameLength = 11;
else if (iThisFrame == 501)
iThisFrameLength = 11;
else if (iThisFrame >= 504 && iThisFrame <= 600) {
if (((iThisFrame - 504) % 4) == 0)
iThisFrameLength = 9;
else if (((iThisFrame - 504) % 4) == 2)
iThisFrameLength = 11;
else
iThisFrameLength = 10;
}
else
iThisFrameLength = 10;

Raw CD reading (Windows)
Made a native program to read raw CD sectors via DeviceIoControl. It's a simple interactive prompt that accepts commands to open/close a CD and read sectors. I even setup a Java program to communicate with the native program via stdin/out. Unfortunately it was slow, and was very vulnerable to deadlock while reading from stdin. I also started adding ASPI for raw CD reading, but there seems to be a lot more to using that API.

Encoding via VFW (Video for Windows)
I worked out a little program to convert a series of raw image and audio data into an AVI, using the oh-so-familiar Video for Windows popup. I wonder if it can handle accepting all the audio at once, then all the video at once....


JNI
Even though I said it would be a pain in the butt, I guess it's really not so bad. It's kinda like translating VB6 COM code into C++. This will likely speed up raw CD reading, and save me from communicating via stdin/out.

Code Design
Finally got back to this again. Since no solution was particularly attractive, I went with the simplest one. This will only use one optional callback listener (for progress status).

However, I have begun to think that the 'pull' architecture is not the best approach to begin with. A 'push' architecture is more applicable to this situation: as sectors are read from the disc, they need to be 'pushed' into the appropriate streams. Listeners can be added to collect the streams of interest. If jpsxdec was to ever play media in real time (not likely), this would be the necessary design. In any case, the 'push' approach would make decoding a little faster because there is less seek time.

No comments:

Post a Comment