Magic Lantern Firmware Wiki
Advertisement

VRAM segments with image data (YUV 422)[]

Those numbers are not 100% correct. A more elegant method (suggested by AJ) is to find a structure which contains the size of the VRAM buffers, and read the image size directly from there.

0x40D07800 / 4c233800 / 4f11d800[]

LiveView buffer maybe

  • each buffer updates at 10fps (does not change when NTSC is selected) => 30fps liveview
  • buffer address can be found at 0x246c (updates at 30fps)
  • see the table struct vram_info vram_info[3]; at RAM:0008194C
  • 1440 pitch, 720x480 image size, (3:2)
  • RCA monitor connected: 540x540 with black borders
  • HDMI monitor connected:
    • 1920x1080 (16:9) standby (not recording)
    • 720x486? while recording /* zebra already works in this mode */

0x44000080 / 0x46000080[]

  • each buffer is updated at 12.5 fps (PAL) or 15fps (NTSC)
  • they are updated alternatively according to AJ's guess => 25 or 30 fps
  • it seems not to change its size when external display is connected
  • in LiveView, idle, PHOTO mode: 2112 pitch, 1056*704 (3:2)
  • when NOT recording:
    • resolution can be found at (0x1300ce, 0x1300d0)
    • full HD: 1056x704
    • 720p: 1024x680 sometimes work, sometimes not
    • 480p non-crop: garbage
    • 480p crop: 640x480
  • when recording:
    • full HD: 3440 pitch, 1720x974 (approx. 16:9)
    • 720p: 2560 pitch, 1280 x 580
    • 480p: 1280 pitch, 640 x 480
  • zoom x5, x10: 2048 pitch, 1024x680 (3:2)

ASM Zedbra: segments in 5D2.

LV-Sizes:[]

Dimensions can be found at 0x3787c(x) and 0x37880(y) (FW 1.0.9)

Local Display:[]

Always 720x480

HDMI:[]

Standby:

  • Disp 1x/2x: 1320x880
  • Disp 3x: 1620x1080

Recording: Always 640x388

A/V-Out (Standby + Recording):[]

  • PAL: 640x464
  • NTSC: 640x388

BMP overlay (where ML writes stuff on screen)[]

8-bit palette: see Cropmarks

  • normal: 720x480 (3:2)
  • hdmi monitor: 960*540 (16:9)
  • SD monitor: 720x480 stretched?

How to find segments[]

Some ideas:

  • Scan for contiguous areas of memory which change like mad (AJ's method)
  • Dump some memory twice (while in LiveView or Recording) and plot the difference between them. Use pylab, octave or whatever numerical analysis program you like. Downsample them (e.g. x[0:-1:100] in pylab) if you have huge dumps.
  • Reading from Cxxxxxxx (and maybe from other addresses) may freeze the camera. Be careful.
  • Use FFT to guess the pitch, and then tweak it by hand
def guesspitch(s):
   F,f = fft(s), fftfreq(len(s))    
   for i in range(100): F[i] = 0
   a = argmax(abs(F[:10000]))
   print 1/f[a]
  • Use these functions for reading and splitting YUV data:
def readseg(file, start, size):
   f = open(file)
   f.seek(start)
   d = f.read(size)
   f.close()
   return [ord(x) for x in d]
def img(s,i,off,step,name,signed,pitch):
   nl = len(s)/pitch
   print nl
   s = s[off:]
   a = resize(s,nl*pitch).reshape(nl,pitch)
   a = a[:,0:pitch:step]
   fname = '%03d-%s.png' % (i,name)
   print a.min(), a.max()
   if signed: a = (a.astype(uint8).astype(int32) + 128).astype(uint8)
   else: a = a.astype(uint8)
   b = Image.fromarray(a)
   b.save(fname)
def imgseq(s, pitch, i=0, off=0):
   img(s,i,0+off,1,"full",0,pitch);
   img(s,i,1+off,2,"odd",0,pitch);
   img(s,i,0+off,2,"even",1,pitch);
   img(s,i,0+off,4,"even-even",1,pitch);
   img(s,i,2+off,4,"even-odd",1,pitch);

e.g.

s = readseg("4.BIN", 0x04000080, 1056*704*2)
guesspitch(s)
2112.0
imgseq(s, 2112)

Code: GPL

Code for running on the camera[]

static FILE * g_aj_logfile = INVALID_PTR;
unsigned int aj_create_log_file( char * name)
{
   g_aj_logfile = FIO_CreateFile( name );
   if ( g_aj_logfile == INVALID_PTR )
   {
      bmp_printf( FONT_SMALL, 120, 40, "FCreate: Err %s", name );
      return( 0 );  // FAILURE
   }
   return( 1 );  // SUCCESS
}
void aj_close_log_file( void )
{
   if (g_aj_logfile == INVALID_PTR)
      return;
   FIO_CloseFile( g_aj_logfile );
   g_aj_logfile = INVALID_PTR;
}
void dump_seg(uint32_t start, uint32_t size, char* filename)
{
    DEBUG();
    aj_create_log_file(filename);
    FIO_WriteFile( g_aj_logfile, (const void *) start, size );
    aj_close_log_file();
    DEBUG();
}
void dump_big_seg(int k, char* filename)
{
    DEBUG();
    aj_create_log_file(filename);
    
    int i;
    for (i = 0; i < 16; i++)
    {
		DEBUG();
		uint32_t start = (k << 28 | i << 24);
		bmp_printf(FONT_LARGE, 50, 50, "DUMP %x %8x ", i, start);
		FIO_WriteFile( g_aj_logfile, (const void *) start, 0x1000000 );
    }
   
    aj_close_log_file();
    DEBUG();
}
static void dump_vram()
{
	dump_big_seg(1, "B:/1.bin");
	dump_big_seg(4, "B:/4.bin");
}

Step-by-step example[]

Run ipython

  1. Load the code (img.py) from the mailing list
In [1]: run -i img.py
  1. Read the file downsampled by 100, 'cause the dumps are large:
In [2]: a = readsampled("./0.BIN")

And second file:

In [3]: b = readsampled("./1.BIN")

Find a difference...

In [4]: d = array(a) - array(b)

Do this to get a nice plot:

In [5]: d[d != 0] = 1

Notice one of the blocks starting around 1000000:

6

6. diff

In [6]: plot(d); show() 
Out[6]: [<matplotlib.lines.Line2D object at 0x9c93c2c>]

Remember downsampling factor:

In [7]: x = 1000000*100

Read 1MB from there:

In [8]: s = readseg("./0.BIN", x, 1000000)

Guess pitch with FFT:

In [9]: guesspitch(s)
2114.16490486

Starts to look like an image!

10

10. first guess

In [10]: imgseq(s, 2114)

And... Perfect sync!

11

11. second guess

In [11]: imgseq(s, 2112)

Image data starts from line 316; from 550d we know buffer is 1056*704

In [12]: s = readseg("./0.BIN", x+316*2112, 2112*704)

Almost there...

13

13. almost there

In [13]: imgseq(s, 2112)

In [14]: hex(x+316*2112)
Out[14]: '0x6001000'

From 550D, Alex guess it should end in 0080

In [15]: s = readseg("./0.BIN", 0x6000080, 2112*704)

Bingo!

16

16. bingo!

In [16]: imgseq(s, 2112)

Final result: 0x46000080 (with the caching bit from 550D).

References:

Advertisement