CedarX/Reverse Engineering

= Initial information =

CedarX are hardware accelerator for media files. Cedar x constain sub-engines that used for each meda type class


 * MPEG Engine
 * MPEG1
 * MPEG2
 * MPEG4
 * MS-MPEG
 * VP6
 * MJPEG (JPEG)
 * XDIV/DIVX (mpeg 3.11)
 * H264 Engine
 * H264
 * VP8
 * VC1 Engine
 * WMV9
 * RMVB Engine
 * Real Media
 * ISP Engine
 * AVC Encoder Engine
 * AVC Encoder Engine

On June 15 2012 Iain Bullard started reverse engineering the proprietary libraries.

Unfortunately driver are proxy that maps HW Regs to Userspace using mmap all stuff constain in libvecore.so

= Register IO Space = All actions blob doing using mimo in user-space mapped io-space reisters guide describe current findings VE Register guide = Object file observations = While android and linux are different beasts from the userspace sense, It could be that the code was written in such way, that it could compile to both targets. Meaning that object files could be similar enough.
 * open_cdxalloc as an free reimplementation of Allwinner's libcederxalloc.a.
 * CedarXWrapper as a LD_PRELOADed wrapper to help understanding the proprietary libraries.
 * CedarXPlayerTest as a basic player to use when testing.
 * ReCedro gitorious, has similar tools as those from IanB above, but with a different angle, works really well.

From android
The android-linux libvecore.a (md5sum 1c347a9ad3072ce3288bd6dba625b2a4) static lib contains the following files: android functions

From linux-armhf
The linux-armhf libvecore.so (md5sum a026d27307e5204db191878651cc6394) shared object contains the following functions: linux-armhf functions The rest of the bits are all open source, see the linux-sunxi github. The exception is libcedarxalloc.a, but as mentioned above, we have open_cdxalloc.

Function references
So far the following references can easily be observed with readelf -W -s. This is just an indication of some functions, by far complete as it would take way to long and is not really needed.

FFmpeg huffman tree builder: ff_huff_build_tree http://ffmpeg.org/doxygen/trunk/huffman_8c.html

libjpeg: get_soi http://sourceforge.net/p/libjpeg-turbo/code/HEAD/tree/trunk/jdmarker.c

libvp62: VP62_InitCoeffScaleFactors http://en.verysource.com/code/5378534_1/libvp62.h.html

H264/AVC Reference encoder/decoder: remove_frame_from_dpb http://iphome.hhi.de/suehring/tml/doc/lenc/html/mbuffer_8c.html#901bd781eb9aef8b79e98b8e10fbc2aa

VC1 Reference decoder: vc1_eResult vc1DECPIC_UnpackInterlaceMVModeParams http://wiki.multimedia.cx/index.php?title=Understanding_VC-1#vc1DECPIC_UnpackInterlaceMVModeParams

MPEG2: There seems to have happened some function renaming etc, the one that google found though was: ParseQuantMatrixExtension http://sources.team-mediaportal.com/svn/public/tags/Release%201.0.2/DirectShowFilters/TsReader/source/MpegPesParser.cpp = Memory Buffers =

CedarX requset lineral memory for decoding process.

= RE tools = utilites for RE Process CedarX/RE Toolkit

MPEG-Engine
All buffers constain pre/final image in YCrCb MPEG Engine have registers for Y and C component (Cb+Cr have same size as Y)

Reconstruct buffer constain ready frame from prev step

Forward buffer constain place for new frame

BACK buffer (not used in my mp4 playback)

ROT (Rotate-Scale buffer) - used when need rotate frame before show (??)

>>>>MEM ADDR>>>> 1) (FOR)->(REC)          (ROT) 2)        (FOR)->(REC) (ROT) 3)              (FOR)->

VC1-Engine
VC1 use YVU color space as input buffers, and YCrCb as output buffers

= Driver IOCTL guide = CedarX/Kernel Driver guide

= HW Registers guide = REGS_BASE = 0x01C00000 A10  IO register base addr

MACC_REGS_BASE = (REGS_BASE + 0x0E000) media accelerate VE IO space(4 kb)

Reset/Clock register
MACC_REGS_BASE + 0x00

On some cases logic not same with Cedar revisions (1619)

For the case of a 1625(A13)

Default: 00000007 write 0: 00000000 write~0: 1333030f read again after ~0 :0x7

VE Ready register
MACC_REGS_BASE + 0x1c

when ready == 0

when not ready == 0x3f00

VE Revision register
MACC_REGS_BASE + 0xF2

Can be used after IOCTL sequence

Constain SoC ID - as VE version

Possible cases:

0x1625 - a13

0x1623 - a10

0x1620 - ???

0x1619 - ???

MPEG Engine
Base address

MPEG_REGS_BASE = (MACC_REGS_BASE + 0x100)

Media File Header Register(mphr)
MPEG_REGS_BASE + 0x00

Video Object Plane Header Register (vophr)
MPEG_REGS_BASE + 0x04

Video file size(fsize)
MPEG_REGS_BASE + 0x08

constain video frame Width:Height in word:word format

Frame Size Register
MPEG_REGS_BASE + 0x0c

constain video frame size for example for 320x240 media file this register must be set 0x014000f0 witch means Width(31-16 bits):Height(15-1 bits) format

0x0140 = 320 0x00f0 = 240

Macro Block Address Register(mbaddr)
MPEG_REGS_BASE + 0x10

Control register(vectrl)
MPEG_REGS_BASE + 0x14

Constain IRQ enable bit

VE Trigger Register(vetrigger)
Used for decoding process lauch

MPEG_REGS_BASE + 0x18

Status register (vestat)
MPEG_REGS_BASE + 0x1c

Busy statuses 14 bit(not sure) - mc free (may be Macrocell or montion compensation)

13 bit(not sure) - Busy status

12 bit(not sure) - idct in empty (Inverse Discrete Cosine Transform)

11 bit(not sure) - iqis in empty (Inverse Quantization and Inverse Scan)

VE ??(trbtrdfld)(??)
Distance in time to last B or P frame

TRB =display_time(B)-display_time(I)

TRD =display_time(P)-display_time(I)

MPEG_REGS_BASE + 0x20

VE ??(trbtrdfrm)(??)
MPEG_REGS_BASE + 0x24

VLD Block Address Register (vldbaddr)
MPEG_REGS_BASE + 0x28

Variable-Length Decoder(VLD) Block Offset Register(vldboffset)
MPEG_REGS_BASE + 0x2c

Variable-Length Decoding(VLD) Length Register(vldlen)
MPEG_REGS_BASE + 0x30

Video Buffer Verifier(VBV) Address Register(vbvsize)
Constain Maximum VBV buffer address

MPEG_REGS_BASE + 0x34

VLD Offset Register(vldoffset) or ??
have SECOND usage

MPEG_REGS_BASE + 0x38

VLD length or ??(vldlen)(dcacaddr)(??)
have SECOND usage

MPEG_REGS_BASE + 0x3c

Block Address Register(blkaddr)
MPEG_REGS_BASE + 0x40

?? Address Register(??)(ncfaddr)
MPEG_REGS_BASE + 0x44

Reconstruct Buffer Luma Address Register (rec_yframaddr)
YCbCr color space Y component buffer

Constain Prev frame for decoder work.

MPEG_REGS_BASE + 0x48

Reconstruct Buffer Croma Address Register(rec_cframaddr)
Constain Prev frame for decoder work.

C component YCbCr

MPEG_REGS_BASE + 0x4c

Forward Buffer Luma Address Register(for_yframaddr)
Space for decoding frame Y Component

MPEG_REGS_BASE + 0x50

Forward Buffer Croma Address Register(for_cframaddr)
Place for croma (C) component decoding frame

MPEG_REGS_BASE + 0x54

BACK Buffer Luma Address Register(back_yframaddr)
MPEG_REGS_BASE + 0x58

BACK Buffer Croma Address Register(back_cframaddr)
MPEG_REGS_BASE + 0x5c

?? Register(??)(socx)
MPEG_REGS_BASE + 0x60

?? Register(??)(socy)
MPEG_REGS_BASE + 0x64

?? Register(??)(sol)
MPEG_REGS_BASE + 0x68

?? Register(??)(sdlx)
MPEG_REGS_BASE + 0x6c

?? Register(??)(sdly)
MPEG_REGS_BASE + 0x70

?? Register(??)(spriteshifter)
MPEG_REGS_BASE + 0x74

?? Register(??)(sdcx)
MPEG_REGS_BASE + 0x78

?? Register(??)(sdcy)
MPEG_REGS_BASE + 0x7c

Inverse Quantization Minimum Level Register(iqminput)
iq minimum settings(video compresson level) for MPEG decoding

for MJPEG decoding, in this register before frame decoding you must load (push) IQ tabe for current frame

MPEG_REGS_BASE + 0x80

Inverse Quantization Level Register(qcinput)
iq settings(compress level)

MPEG_REGS_BASE + 0x84

MS-MPEG header(msmpeg4_pichdr)(??)
MPEG_REGS_BASE + 0x88

VP6 header(vp6_pichdr)(??)
MPEG_REGS_BASE + 0x8c

Inverse Quantization and Inverse Discrete Cosine Transform Input Register(iqidctinput)(??)
MPEG_REGS_BASE + 0x90

Macro Block Height Register(mbah)(??)
look like macro cell size reg

MPEG_REGS_BASE + 0x94

Macro Block Vector 1(mbv1)(??)
MPEG_REGS_BASE + 0x98

Macro Block Vector 2(mbv2)(??)
MPEG_REGS_BASE + 0x9c

Macro Block Vector 3(mbv3)(??)
MPEG_REGS_BASE + 0xa0

Macro Block Vector 4(mbv4)(??)
MPEG_REGS_BASE + 0xa4

Macro Block Vector 5(mbv5)(??)
MPEG_REGS_BASE + 0xa8

Macro Block Vector 6(mbv6)(??)
MPEG_REGS_BASE + 0xac

Macro Block Vector 7(mbv7)(??)
MPEG_REGS_BASE + 0xb0

Macro Block Vector 8(mbv8)(??)
MPEG_REGS_BASE + 0xb4

JPEG Decoder Control Register(jpeg_sdctl)
MPEG_REGS_BASE + 0xb8

Jpeg MCU Register (jpeg_mcu)
MPEG_REGS_BASE + 0xbc

JPEG Restart interval Register (jpeg_resint)
MPEG_REGS_BASE + 0xc0

Error Flag Register(errflag)
MPEG_REGS_BASE + 0xc4

?? (crtmb)
MPEG_REGS_BASE + 0xc8

Rotate-Scale Buffer Luma Address Register(rotf_yfrmaddr)
Result buffer for MJPEG decoder, Luma Component

MPEG_REGS_BASE + 0xcc

Rotate-Scale Buffer Croma Address Register(rotf_cfrmaddr)
MPEG_REGS_BASE + 0xd0

Extra Functions Control Register(extra_func_ctrl)(sdRotDblkCtrl)
Control rotate and etc.

MPEG_REGS_BASE + 0xd4

JPEG MCU (macrocell) Start Address Register (Jpg_start_mcuco)
MPEG_REGS_BASE + 0xd8

JPEG MCU (macrocell) End Address Register (Jpg_end_mcuco)
MPEG_REGS_BASE + 0xdc

MJPEG/JPEG Huffman Table Reset Register
Before load new huffman table for MJPEG decoding this register must be set "0" for clean old huffman table

MPEG_REGS_BASE + 0xe0

JPEG Huffman Table Load Register
MJpeg decoder push dwords to it in batch,  look like values automaticly moves to shadow registers

MPEG_REGS_BASE + 0xe4

H264 Engine
Base address

H264_REGS_BASE = (MACC_REGS_BASE + 0x200)

Interupt enable reg = H264_REGS_BASE + 0x20

bitmask 0x0111 enable/disable IRQs from H264 decoder

?? register(??)
H264_REGS_BASE + 0x00

?? register(??)
H264_REGS_BASE + 0x04

?? register(??)
H264_REGS_BASE + 0x08

?? register(??)
H264_REGS_BASE + 0x0c

?? register(??)
H264_REGS_BASE + 0x10

VP8 Picture Header register(PicHeader)
H264_REGS_BASE + 0x14

?? register(Qindex)
H264_REGS_BASE + 0x18

?? register(PartitionOffset)
H264_REGS_BASE + 0x1c

Control register(Ctrl)
H264_REGS_BASE + 0x20

Trigger register(TriggerType)
H264_REGS_BASE + 0x24

Starus register(Status)
H264_REGS_BASE + 0x28

?? register(CurMbNum)
H264_REGS_BASE + 0x2c

?? register(VldBitInfo)
H264_REGS_BASE + 0x30

?? register(VldOffset)
H264_REGS_BASE + 0x34

?? register(VldLen)
H264_REGS_BASE + 0x38

Vld End Address Register(VldEndAddr)
H264_REGS_BASE + 0x3c

?? register(SdRotCtrl)
H264_REGS_BASE + 0x40

?? register(SdRotLumaBuf)
H264_REGS_BASE + 0x44

?? register(SdRotChromaBuf)
H264_REGS_BASE + 0x48

?? register(??)
H264_REGS_BASE + 0x4c

?? register(EntropyProbs)
H264_REGS_BASE + 0x50

?? register(FstDataPartionLen)
H264_REGS_BASE + 0x54

?? register(PicMbSize)
H264_REGS_BASE + 0x58

?? register(PicBoundarySize)
H264_REGS_BASE + 0x5c

?? register(MbAddr)
H264_REGS_BASE + 0x60

?? register(MbNeightbour1)
H264_REGS_BASE + 0x64

?? register(MbNeightbour2)
H264_REGS_BASE + 0x68

?? register(MbNeightbour3)
H264_REGS_BASE + 0x6c

?? register(MbNeightbour4)
H264_REGS_BASE + 0x70

?? register(MbNeightbour5)
H264_REGS_BASE + 0x74

?? register(??)
H264_REGS_BASE + 0x78

?? register(??)
H264_REGS_BASE + 0x7c

?? register(??)
H264_REGS_BASE + 0x80

?? register(MbQp)
H264_REGS_BASE + 0x90

Reconstruct Luma Address Register(ReconLumaBuf)
H264_REGS_BASE + 0xac

Forward Buffer Address Register(FwdLumaBuf)
H264_REGS_BASE + 0xb0

Back Buffer Luma Address Register(BackLumaBuf)
H264_REGS_BASE + 0xb4

Error Result Register(ErrorCase)
H264_REGS_BASE + 0xb8

Reconstruct Chroma Buffer Register(ReconChromaBuf)
H264_REGS_BASE + 0xd0

Forward Chroma Buffer Address Register(FwdChromaBuf)
H264_REGS_BASE + 0xd4

Back Chroma Buffer Address Register(BackChromaBuff)
H264_REGS_BASE + 0xd8

?? register(BasicBitsData)
H264_REGS_BASE + 0xdc

Alternate Buffer Chroma Address Register(AlternateChromaBuf)
H264_REGS_BASE + 0xec

Alternate Luma Buffer Address Register(AlternateLumaBuf)
H264_REGS_BASE + 0xe8

?? register(SegmentMbLevel0)
H264_REGS_BASE + 0xf0

?? register(SegmentMbLevel1)
H264_REGS_BASE + 0xf4

?? register(RefLfDelta)
H264_REGS_BASE + 0xf8

?? register(ModeLfDelta)
H264_REGS_BASE + 0xfc

VC1 Engine
Base address

VC1_REGS_BASE = (MACC_REGS_BASE + 0x300)

Interupt enable reg = VC1_REGS_BASE + 0x24

?? Register(ephs)
VC1_REGS_BASE + 0x00

?? Register(pic_ctrl)
VC1_REGS_BASE + 0x04

?? Register(pic_qp)
VC1_REGS_BASE + 0x08

?? Register(pic_mv)
VC1_REGS_BASE + 0x0c

?? Register(pic_inten_comp)
VC1_REGS_BASE + 0x10

?? Register(pic_interlace)
VC1_REGS_BASE + 0x14

?? Register(pichdrlen)
VC1_REGS_BASE + 0x18

?? Register(fsize)
VC1_REGS_BASE + 0x1c

?? Register(picsize)
VC1_REGS_BASE + 0x20

Decoder Control Register(dec_ctrl)
VC1_REGS_BASE + 0x24

?? Register(start_type)
VC1_REGS_BASE + 0x28

Status Register(status)
VC1_REGS_BASE + 0x2c

VBV Base Address Register(vbv_base_addr)
VC1_REGS_BASE + 0x30

VLD Offset Register(vld_offset)
VC1_REGS_BASE + 0x34

VBV Lenght Register Register(vbv_len)
VC1_REGS_BASE + 0x38

VBV End Address Register(vbv_end_addr)
VC1_REGS_BASE + 0x3c

Reconstruct Buffer Croma Address Register(rec_yframaddr)
VC1_REGS_BASE + 0x40

Reconstruct Buffer Luma Register(rec_uvframaddr)
YVU - color space

VC1_REGS_BASE + 0x44

Forward Buffer Croma Addreess Register(for_yframaddr)
VC1_REGS_BASE + 0x48

Forward Buffer Luma Address Register(for_uvframaddr)
VC1_REGS_BASE + 0x4c

Back Croma Address Register(back_yframaddr)
VC1_REGS_BASE + 0x50

Back Luma Adderss Register(black_uvframaddr)
VC1_REGS_BASE + 0x54

?? Register(??)
VC1_REGS_BASE + 0x58

?? Register(dcacpredaddr)
VC1_REGS_BASE + 0x5c

?? Register(bitplaneaddr)
VC1_REGS_BASE + 0x60

?? Register(mbinfoaddr)
VC1_REGS_BASE + 0x64

?? Register(??)
VC1_REGS_BASE + 0x68

?? Register(??)
VC1_REGS_BASE + 0x6c

?? Register(mbr)
VC1_REGS_BASE + 0x70

?? Register(mbhdr)
VC1_REGS_BASE + 0x74

?? Register(lumatransform)
VC1_REGS_BASE + 0x78

?? Register(mbcbf)
VC1_REGS_BASE + 0x7c

?? Register(mbmv1)
VC1_REGS_BASE + 0x80

?? Register(mbmv2)
VC1_REGS_BASE + 0x84

?? Register(mbmv3)
VC1_REGS_BASE + 0x88

?? Register(mbmv4)
VC1_REGS_BASE + 0x8c

?? Register(mbmv5)
VC1_REGS_BASE + 0x90

?? Register(mbmv6)
VC1_REGS_BASE + 0x94

?? Register(mbmv7)
VC1_REGS_BASE + 0x98

?? Register(mbmv8)
VC1_REGS_BASE + 0x9c

?? Register(mbmv9)
VC1_REGS_BASE + 0xa0

?? Register(mbmv10)
VC1_REGS_BASE + 0xa4

?? Register(mbmv11)
VC1_REGS_BASE + 0xa8

?? Register(mbmv12)
VC1_REGS_BASE + 0xac

?? Register(mbmv13)
VC1_REGS_BASE + 0xb0

?? Register(mbmv14)
VC1_REGS_BASE + 0xb4

?? Register(errorcase)
VC1_REGS_BASE + 0xb8

?? Register(crtmbnum)
VC1_REGS_BASE + 0xbc

?? Register(extra_ctrl)
VC1_REGS_BASE + 0xc0

?? Register(extra_cbufaddr)
VC1_REGS_BASE + 0xc4

RMVB Engine
Base address

RMVB_REGS_BASE = (MACC_REGS_BASE + 0x400)

Interupt enable reg = RMVB_REGS_BASE + 0x14

ISP ??
Base address

ISP_REGS_BASE = (MACC_REGS_BASE + 0xa00)

Interupt enable reg = ISP_REGS_BASE + 0x8

AVC Encoder engine
Base address

ISP_REGS_BASE = (MACC_REGS_BASE + 0xb00 )

Interupt enable reg = ISP_REGS_BASE + 0x8 = Decoding processes =

This part describe how in steps cedarx decoder must be used for each filetype

MPEG Engine reset/clock init procedure
CedarX/MPEG Engine Init procedure

JPEG-MJPEG Decoding process
CedarX/JPEG-MJPEG Decoding

MPEG4 Decoding process
!!!ALPHA VERSION!!!!

MPEG decoding request several operations:

1) Huffman decoding (VLD)(Varable Length Decoding)

2) Inverse Quantization (IQ)

3) Inverse Cosine Transform (IDCT)

4) Inverse Scan (IS)

5) ....

CedarX MPEG Engine can do it in automatic or semi-automatic mode

MPEG decoding procedure (Previous VOP)<- /             | STREAM -(DMUX) - montion -> (Motion Decoding) -> (Montion Compensation)    | \                                                               \  /                \- textures -> (VLD) -> (IS)-> (Inverse AC and DC prediction) \ | / | |/ /---/ / |                                                                             /  \-->(IQ)->(IDCT)--\                                                         / |                                                       /                    \--->(VOP Reconstruction)<>-/

MPEG4 decoding sequence

1) Do driver IOCTL Sequence

2) Do driver MMAP Sequence

3) Do MPEG Engine Sequence

4) config nfc(??) buffer

[MPEG_BASE+0x44] <- addr

5) config video source buffer

[MPEG_BASE+0x38] <- vbv buffer address [MPEG_BASE+0x3c] <- vbv length

6) config rotation buffer

[MPEG_BASE+0xcc] <- rot chroma [MPEG_BASE+0xd0] <- rot luma

7) config header (??)

[MPEG_BASE+0x0x] <- 0

8) config video size

[MPEG_BASE+0x08] <- H:W format

9) ??

[MPEG_BASE+0x10] <-0

10) do control (??) may be IRQ

[MPEG_BASE+0x10] <-0x80084198

11) Trigger something (??)

[MPEG_BASE+0x10] <-0x04000000

It look like find entry point

12) Config video size (other reg)(??)

[MPEG_BASE+0x0c] <-H:W

13) Set IQ level (??)

[MPEG_BASE+0x84] <- iq level (??)

14) Set MS-MPEG header

[MPEG_BASE+0x88] <- 0 (??)

15) config reconstruct buffer

[MPEG_BASE+0x4c] <- rec chroma [MPEG_BASE+0x48] <- rec luma

16) config for buffer

[MPEG_BASE+0x54] <- rec chroma [MPEG_BASE+0x50] <- rec luma

17) config back buffer

[MPEG_BASE+0x5c] <- rec chroma [MPEG_BASE+0x58] <- rec luma

18) clear status register

[MPEG_BASE+0x1c] <- ~0

19) clear ctrmb ??

[MPEG_BASE+0xc8] <- 0

20) clear error status

[MPEG_BASE+0xc4] <- 0

21) set new vbv offset (next frame??)

[MPEG_BASE+0x2c] <- offset to new frame

22) set vbv size

[MPEG_BASE+0x30] <- vbv_buffer_size

23) set end vbv

[MPEG_BASE+0x34] <- vbv_base + vbv_buffer_size-1

23) set VLD buffer

[MPEG_BASE+0x28] <- video source

24) touch trigger

[MPEG_BASE+0x18] <-0x0400300d

25) wait irq

26) clean IRQ status

[MPEG_BASE+0x1c] <- 0x0000c00f