Archive for September, 2007

Keyboard controller

Saturday, September 15th, 2007

During the afternoon I decided to play a bit with my FPGA development board. It has a PS/2 connector and I tried to make a PS/2 controller (using VHDL) that is able to receive PS/2 packets. I have no electrical engineering background, so what I did might just be plain wrong. But I had fun and the design seems simple and clean to me. Feedback is of course welcome!

For now, I just interfaced with a keyboard. My PS/2 controller waits for the start bit, then starts reading the bits (and calculates the parity in parallel). It uses the clock generated by the keyboard to do this. When the byte is received and the parity is correct, a signal is sent to inform another process that the data is available. This process runs using a 27Mhz oscillator and waits for the data to settle before it makes it available.

Of course it is not finished yet. It can’t send commands to the keyboard yet, in order to do this I first have to learn a bit more about tri-states. I haven’t tried connecting a mouse yet. I will do this too and figure out how this works in detail. When everything works, I will make my VHDL code available. Can someone suggest a good license for VHDL code? I will use the GPLv3, unless someone can suggest something that is more appropriate for hardware. Of course I can already show you the schematic of what I currently have:

Keyboard controller RTL

This development board also has VGA output (I implemented something for this already), DRAM, SD interface, RS232, USB, sound, buttons, a 7 segment display (got it working, this one requires scanning) and it has TV output! So it can be used to develop multimedia stuff like MPEG-2, MP3, MJPEG or so. It would be neat to write a decoder or encoder some day. But my idea is to create my own gameboy some day. Although I can not promise I will actually come to this.

Motion Vector packing

Monday, September 10th, 2007

To implement motion vector packing, I just generate semi-random motion vectors and write these to the bitstream. In that case the rest of the encoding process has to adapt to these (incorrect) vectors. Most importantly: this will result in a bigger residue, thus in a bigger file. But this way this part of the encoder can be tested.

The motion vector packing now works! I have also implemented calculating the residue and fixed many bugs in the other parts of the encoding process. Now the encoder writes intra+inter frames with the semi-random motion vectors for a single reference frame.

So what needs to be done now is searching for (optimal) motion vectors. Perhaps I can use the algorithm from the Snow codec for this, otherwise I will have to implement this myself. I also need support for two reference frames. Actually the support is there, it just has to be enabled properly :-). In order to produce smaller files I need to add quantization.

Despite what’s missing, I think I can say I quite succeeded with writing the Dirac codec during Summer of Code (about 2 months, with a break of one week because of exams). When Summer of Code started, one of the Schrodinger developers called me Biggest Optimist in the Universe and Beyond 2007. Although the encoder is not in a state that it can efficiently code all videos yet, the biggest part has been implemented already. But more importantly, my decoder can play back videos at a decent speed. So I got the “Biggest Optimist in the Universe and Beyond 2007 Award”, now I am waiting for the certificate, medal or whatever comes with the title ;-).

Mike and Michael from the FFmpeg project both wrote a blog entry to wrap up how they look at the last Summer of Code, my work on the Dirac codec is part of this. Summer of Code is finished now so I will start using the FFmpeg category for my future work on Dirac. Don’t worry, I will keep working on Dirac!

Intra frame coding fixed

Monday, September 3rd, 2007

In a previous post I mentioned that intra frame encoding works, but the reference implementation couldn’t decode my frames yet. Now I fixed this bug, it seemed to be a silly typo, I was using uint8_t instead of int8_t. With this fixed, the reference implementation is capable of decoding the frames encoded by my encoder.

Of course a lot is missing in the encoder. First I will focus on writing the bitstream for the inter frames. So I need motion vectors to write out. First I will just take some random vectors, calculate the residue using these vectors and write both to the bitstream. That way it will become easier to test if writing out this data works, before I start working on Motion Estimation.

Decoder performance

Sunday, September 2nd, 2007

Today I built the decoder with profiling and debugging information disabled to compare the speed with that of the reference implementation. When building the reference implementation I disabled MMX, so I am just comparing C code with C code. At the end my code can also be speed up using SIMD code.

To measure the speed, I used `time’. The first video I tried is a small video of just a few seconds. Using the reference implementation:

real 0m4.029s
user 0m3.704s
sys 0m0.272s

When using my decoder:

real 0m3.754s
user 0m3.528s
sys 0m0.192s

The first video is a longer video. Using the reference implementation:

real 0m59.709s
user 0m52.447s
sys 0m5.168s

Using my decoder:

real 0m55.814s
user 0m51.327s
sys 0m2.460s

I had a look at what makes the difference. It appears that because I cache halfpel interpolated reference frames I save lots of time. This is not being done for the reference implementation. The reference implementation recalculated the interpolated frame every time.