SGI: Video

O2 Vice MPEG2 discovery

The O2 has the vice engine. This was an architecture designed just before things like the Pentium got MMX and MIPS got MDMX. Instead of extra instructions on the main CPU, VICE is actually three completely seperate execution units that talk via a mapped region in main memory (not a big deal on the O2's UMA architecture). The three units are the MSP, BSP and a DMA engine. I'll talk more about the specifics of this architecture in future posts (time permitting). Additionally, two hardware versions of the VICE were released, DX and TRE with TRE being the most recent version.

This unit is used by two parts of Irix: the ImageVision library for accelerating 2D image operations and by dmedia for accelerating various image compression tasks. Specifically

Code: Select all

SGI versions 1, 2 and 3 (supported compression formats: uncompressed,

Microsoft AVI (Audio Video Interleaved)

MPEG1 (ISO 11172) - read, play, and append only

Raw DV/DVCPro DIF files - read, play, and export only

Notably missing is MPEG2. Everything I've read on the net supports this, as well, the O2 can't do realtime MPEG-2 (please, correct me if I'm wrong about this assumption.) However, I was able to locate some internal documentation for the VICE engine and references to MPEG-2 decoding is littered through the documentation. MPEG2 decoding was definitely one of the design goals.

Furthermore, I find some compelling evidence of the ability to decode MPEG2 in 6.5.30m. Because the MSP and BSP are seperate executing units, Irix must keep object files around to run on those units.

The ImageVision MSP/BSP objects are found in

Code: Select all


The dmedia objects are found in

Code: Select all


So... at the bottom of the dmedia stack there is some solid evidence that Irix supports mpeg2 decoding, because there is code to run on the Vice.

But does the rest of Irix know how to decode mpeg2? I cobbled some C together from the dmedia manpages and examples to introspect the dmedia image converters (the image compression section of dmedia) to see what converters it knows about.

Code: Select all

Contents of Parameter/Value List for IC 34:
DM_IC_ENGINE=The mpeg2 decoder
Contents of Parameter/Value List for IC 35:
Contents of Parameter/Value List for IC 37:

The output is bit conflicting (why is the dvc decoder listed with a "MPEG-2 Video"). I compiled this with the debug version of dmedia (export LD_LIBRARY_PATH=/usr/lib/debug) without any problems. But, the way I read the output is that, at least at the image compression level, there is support for hardware (DM_IC_SPEED=REALTIME) and software (DM_IC_SPEED=NONREALTIME) mpeg2 decoding. Now support for the compression scheme is only part (albeit a major one) of displaying mpeg2 on the screen. The next step is to learn more about dmMovie which supports the various container formats. Is there support for a mpeg2 container there?

I've attached a copy of the source of the tool to list the available imageconverters. If anyone else wants to run this on their O2, I'd be interested to see if there is any difference in versions of Irix (did 6.3 have dmedia?) I've become a bit obsessed by the VICE and I hope to keep updating this thread with more that I discover, especially about mpeg2.
:Octane2: :Indy: :O2: :O2: :O3x0: :Indigo2IMP:
Nice! Keep going!
:O2: r12 400 mapleleaf
New Zealand
Sounds very interesting! Keep going!
O2 r5k 200mhz and O2 r10k 250mhz
I don't have any O2 running on anything but 6.5.30m, which I think is what you are running on as well, but I went ahead and compiled and ran the program for the sake of verification. The output is attached.

I'd be glad to test anything else you have, or if you have any suggestions on things to delve into myself, I could try that too - I'm handy enough with C-like languages.
:O2: (janus): 400MHz R12k, 576MB, 73GB 15k, modded PSU fan
:Indigo2IMP: (indigo2): 195MHz R10k, 512MB, SI, 36GB
Sun Ultra80 (mizar): 4x450MHz USII, 4GB, XVR-1200, 2x73GB 15k ZFS
2x :1600SW: +ML, :Octane: 195MHz R10k, currently not booting
Thanks for the encouragement! It feels a bit weird spending all this time thinking about something that is, basically, unimportant in the grand scheme of things; the architecture was a dead end, Irix is long expired, and who cares about MPEG2 these days? Well, apparently, I do. It isn't some wish to go back, but, by golly, just because the rest of the world decided to be finished with this stuff doesn't mean I have to be finished with it!

I was a bit concerned about 'MPEG-2 Video' being listed for every vice related engine. Perhaps I was pulling the value from the string stored behind the dmedia library when it wasn't valid (e.g. left over from the previous image decoder)?

Reversing the order

Code: Select all

status = dmICGetDescription(i, params);
PrintParams(params, i);

Sure enough, something weird going on.

Code: Select all

Contents of Parameter/Value List for IC 37:

This certainly looks like a mpeg1 decoder, which we know works. Bad news? I dunno, there is still a lot of evidence pointing to a mpeg2 vice decoder. Even though the imageconverter library doesn't expose it, we still have those bits of code for the MSP and BSP on the vice. However, am I misinterpreting the names of those code files?

Experiment: run a mpeg1 file and see what .mex and .bex files it loads.

First, I wanted a minimal player that used dmedia (I don't think any of the legacy media stuff supports vice?). I found a simple example in /usr/share/src/dmedia/movie/miscGL/simplemoveGL. Second, I need a working mpeg1 movie file. This was in /usr/demos/O2/Birth_of_O2/data/product_manager/System_components/avModule.mpg. Third, I need a way to watch what system calls (specifically open calls) are made when I run the movie player with the mpeg1 file. par(1) does this easily enough.

Code: Select all

par -n open ./simplemovieGL /usr/demos/O2/Birth_of_O2/data/product_manager/System_components/avModule.mpg
...(some rld stuff)
6mS                 : open("/usr/lib32/", O_RDONLY, 05) = 3
7mS                 : open("/usr/lib32/", O_RDONLY, 05) = 3
7mS                 : open("/usr/lib32/", O_RDONLY, 05) = 3
8mS                 : open("/usr/lib32/", O_RDONLY, 05) = 3
9mS                 : open("/usr/lib32/", O_RDONLY, 05) = 3
10mS                 : open("/usr/lib32/", O_RDONLY, 05) = 3
11mS                 : open("/usr/lib32/", O_RDONLY, 05) = 3
11mS                 : open("/usr/lib32/", O_RDONLY, 05) = 3
12mS                 : open("/usr/lib32/", O_RDONLY, 05) = 3
13mS                 : open("/usr/lib32/", O_RDONLY, 05) = 3
15mS                 : open("/usr/lib32/", O_RDONLY, 05) = 3
16mS                 : open("/usr/lib32/", O_RDONLY, 05) = 3

I believe that the vice is exposed to the kernel via an entry in /dev that can be controlled via a variety of ioctls and wraps that up in a nice api.

Code: Select all

42mS                 : open("/dev/zero", O_RDWR, 01757312210) = 3
...(a bunch of X and openGL calls)
50mS                 : open("/usr/lib32/dmedia/imageconverters/", O_RDONLY, 05) = 4
66mS                 : open("/usr/lib32/dmedia/imageconverters/", O_RDONLY|O_NONBLOCK, 01505656520) = 4
68mS                 : open("/usr/lib32/dmedia/imageconverters/", O_RDONLY, 05) = 4
70mS                 : open("/usr/lib32/dmedia/imageconverters/", O_RDONLY, 05) = 4
73mS                 : open("/usr/lib32/dmedia/imageconverters/", O_RDONLY, 05) = 4
75mS                 : open("/usr/lib32/dmedia/imageconverters/", O_RDONLY, 05) = 4
76mS                 : open("/usr/lib32/dmedia/imageconverters/", O_RDONLY, 05) = 4
79mS                 : open("/dev/vicedms", O_RDWR, 0570) = 4

I think here is starting to control the vice

Code: Select all

80mS                 : open("/dev/dms", O_RDWR, 070) = 5
81mS                 : open("/dev/dms", O_RDWR, 070) = 6
83mS                 : open("/dev/dms", O_RDWR, 0130) = 7
89mS                 : open("/dev/dms", O_RDWR, 03) = 8
89mS                 : open("/dev/dms", O_RDWR, 0130) = 9
173mS                 : open("/dev/dms", O_RDWR, 03) = 10
195mS                 : open("/dev/vicedms", O_RDWR, 0570) = 4
196mS                 : open("/dev/dms", O_RDWR, 070) = 5
197mS                 : open("/dev/dms", O_RDWR, 070) = 6
199mS                 : open("/dev/dms", O_RDWR, 0130) = 7
204mS                 : open("/dev/dms", O_RDWR, 03) = 8
205mS                 : open("/dev/dms", O_RDWR, 0130) = 9
266mS                 : open("/dev/dms", O_RDWR, 03) = 10
...(a bunch of X and openGL calls
592mS                 : open("/var/arch/vicetre/mpeg1dec.mex", O_RDONLY, 017777605604) = 27
593mS                 : open("/var/arch/vicetre/mpeg1dec.bex", O_RDONLY, 010000) = 27

With the /dev/vicedms already open (from above) the library loads up the mpeg1dec.mex and mpeg1dec.bex files to the MSP and BSP, respectively. Thus, running an mpeg1 file uses the mpeg1dec.mex and mpeg1dec.bex files. So what? Well there are still

Code: Select all


in /var/archer/vicetre/. Who uses those files?

Code: Select all

$ strings /usr/lib32/dmedia/imageconverters/ | grep mpeg2

The very same that runs mpeg1. Then why does tell the dmIC library that it can do mpeg1 but not mpeg2?

A mystery.

The next question that emerges in my mind; what is going on in Finding the addresses of the mpeg1dec.mex and mpeg1dec.bex strings in could provide enough info to run dbx(1) or cvd(1) along with test_ic.c and see if I can't see how the dmIC introspection interacts with I'm mildly encouraged since there does exist a /usr/lib/dmedia/debug/ Perhaps, it has not been stripped of symbols and use the function names to understand where I am in the code. If it is stripped I think that it might be possible to at least follow the pattern for mpeg1 and see if I can find a branch that skips mpeg2. Maybe a decompiler will help here?
:Octane2: :Indy: :O2: :O2: :O3x0: :Indigo2IMP:
Jodys, i'm going to run the test_ic.c on my O2. I'm interested in what you have found already. Disassembly of is an option, though it is not for the faint of heart.

Above all, i just need some courage to run the system knowing that i have to turn it on and off for some time before i can run it 24/7. I need to make it a bit more silent...
:Crimson: :PI: :Indigo: :O2: :Indy: :Indigo2: :Indigo2IMP: :O200: :O2000: :Onyx2:
Looking at the docs for dbx I think I can set a break when entering a system call. From there I think I can at least isolate where in those files are loaded. I thought a useful first thing to try would be to at least build a call tree for mpeg1 which I think is doable with dbx and the symbols in

A question related to compiling with debug ('-g') turned on. How do you know if a given binary was compiled with '-g'?
:Octane2: :Indy: :O2: :O2: :O3x0: :Indigo2IMP:
there would be a DWARF section in the binary.
:PI: :O2: :Indigo2IMP: :Indigo2IMP:
I sadly don't have anything to offer to this thread, and my O2 is currently in a non-functional state, but I love that this is happening :)
I'd five you results as well but my compiler is not playing nice with me.
:Crimson: :Onyx: :O2000: :O200: :O200: :PI: :PI: :Indigo: :Indigo: :Indigo: :Octane: :O2: :1600SW: :Indigo2: :Indigo2: :Indigo2IMP: :Indigo2IMP: :Indy: :Indy: :Indy: :Cube:

Image <-------- A very happy forum member.
Interesting project, keep up the good work!
:O200: :Indigo: :O2: :Indigo2IMP:
(9.16 KiB) Downloaded 23 times

What strikes me is that even Macroexp and i have the same IRIX version, our test_ic.txt differ. I'm running an [email protected] system with AV board
:Crimson: :PI: :Indigo: :O2: :Indy: :Indigo2: :Indigo2IMP: :O200: :O2000: :Onyx2:
jodys wrote: question related to compiling with debug ('-g') turned on. How do you know if a given binary was compiled with '-g'?

The file command will tell you; file binaryname and it will say either stripped or not stripped.
Temporarily lost at sea...
World domination! Or something...

:Tezro: :Octane2:
It looks like tracing the execution won't be easy

Code: Select all

[email protected] debug$ pwd
[email protected] debug$ dwarfdump
No DWARF information present in
[email protected] debug$

but it won't be hard

Code: Select all

[email protected] debug$ file    ELF 32-bit MSB mips-2 dynamic lib MIPS - version 1
[email protected] debug$
:Octane2: :Indy: :O2: :O2: :O3x0: :Indigo2IMP:
I wasn't expecting a mips2 binary. How about elfdump?
:Crimson: :PI: :Indigo: :O2: :Indy: :Indigo2: :Indigo2IMP: :O200: :O2000: :Onyx2:
elfdump returns nothing, but reading its manpage led me to stdump(1). Looks like there is some amount of information here because I'm guessing MIPS2 implies that it was not compiled with n32.

Aside, in a unrelated message from Apr 1995 (probably pretty close to beginning of development on the o2)

Code: Select all

The symbol table formats are rather weird: we don't use DWARF for the
32-bit platforms yet - the format is called "mdebug", and is described in

Silicon Graphics Inc.                   Phone:  +1-415-390-2072

that explains the lack of dwarf info.

Anyways, it looks like neither or debug/ are compiled with any extra debug information. The most interesting revealed from stdump(1)

Code: Select all

Local Symbols:
from file dmic_interface.c  compiled -g0  Print aux if present
0. ( 0)(   0) dmic_interface.c File       Text       symref 40
1. ( 1)(133894176) dmICInitDso Proc       Text       [15] endref 3, int
2. ( 1)( 356) dmICInitDso End        Text       symref 1
3. ( 1)(133894532) Open       StaticProc Text       [17] endref 5, int
4. ( 1)( 236) Open       End        Text       symref 3
5. ( 1)(133894768) Close      StaticProc Text       [19] endref 7, int
6. ( 1)( 116) Close      End        Text       symref 5
7. ( 1)(133894884) GetDescription StaticProc Text       [21] endref 9, int
8. ( 1)( 300) GetDescription End        Text       symref 7
9. ( 1)(133895184) SetSrcPoolParams StaticProc Text       [23] endref 11, int
10. ( 1)(  60) SetSrcPoolParams End        Text       symref 9
11. ( 1)(133895244) SetDstPoolParams StaticProc Text       [25] endref 13, int
12. ( 1)(  60) SetDstPoolParams End        Text       symref 11
13. ( 1)(133895304) SetDstPool StaticProc Text       [27] endref 15, int
14. ( 1)(  80) SetDstPool End        Text       symref 13
15. ( 1)(133895384) GetDstFD   StaticProc Text       [29] endref 17, int
16. ( 1)(   8) GetDstFD   End        Text       symref 15
17. ( 1)(133895392) GetSrcFilled StaticProc Text       [31] endref 19, int
18. ( 1)(  76) GetSrcFilled End        Text       symref 17
19. ( 1)(133895468) GetDstFilled StaticProc Text       [33] endref 21, int
20. ( 1)(  76) GetDstFilled End        Text       symref 19
21. ( 1)(133895544) VerifySrcParams StaticProc Text       [35] endref 23, int
22. ( 1)( 184) VerifySrcParams End        Text       symref 21
23. ( 1)(133895728) VerifyDstParams StaticProc Text       [37] endref 25, int
24. ( 1)( 132) VerifyDstParams End        Text       symref 23
25. ( 1)(133895860) VerifyConvParams StaticProc Text       [39] endref 27, int
26. ( 1)(  12) VerifyConvParams End        Text       symref 25
27. ( 1)(133895872) GetDefSrcParams StaticProc Text       [41] endref 29, int
28. ( 1)( 128) GetDefSrcParams End        Text       symref 27
29. ( 1)(133896000) GetDefDstParams StaticProc Text       [43] endref 31, int
30. ( 1)( 128) GetDefDstParams End        Text       symref 29
31. ( 1)(133896128) GetDefConvParams StaticProc Text       [45] endref 33, int
32. ( 1)(  12) GetDefConvParams End        Text       symref 31
33. ( 1)(133896140) Send       StaticProc Text       [47] endref 35, int
34. ( 1)(2016) Send       End        Text       symref 33
35. ( 1)(133898156) Recv       StaticProc Text       [49] endref 37, int
36. ( 1)( 156) Recv       End        Text       symref 35
37. ( 1)(133898312) VerifySrcDstConv StaticProc Text       [51] endref 39, int
38. ( 1)( 184) VerifySrcDstConv End        Text       symref 37
39. ( 0)(   0) dmic_interface.c End        Text       symref 0

I'm thinking I can use the machine level instructions in dbx to start seeing what is happening. Again, part of the goal is to simply start seeing some of the call stack at various places in the code. I'm hoping to get at least some perspective with just the external symbols.
:Octane2: :Indy: :O2: :O2: :O3x0: :Indigo2IMP: