#22 Open
Repository
Branch
crop_rec_4k_ELNS
Repository
Branch
crop_rec_4k

Bitbucket cannot automatically merge this request.

The commits that make up this pull request have been removed.

Bitbucket cannot automatically merge this request due to conflicts.

Review the conflicts on the Overview tab. You can then either decline the request or merge it manually on your local system using the following commands:

hg update 91593cabf6c9
# Note: This will create a new head!
hg merge 5565c6e9aa60
hg commit -m 'Merged in crop_rec_4k_ELNS (pull request #22)'
Author
  1. Daniel Fort
Reviewers
Description

Add Extended Lens metadata to crop_rec_4k branch to allow for longer lens names used in manual lens info lua script.

Comments (26)

  1. Georg Hofstetter

    thanks for reviving this feature.
    can you probably split it into different commits? like splitting in these ones:

    commit “advanced lens information in ML core”
    commit “added LUA interface and functions to set manual lens data”
    commit “mlv_rec: add ELNS support”
    commit “mlv_lite: add ELNS support”
    commit “silent: handle advanced lens info”

    having such a chunk makes it absolutely impossible to e.g. cherry pick patches or merge them properly

  2. alessandro profiti

    I’m working in a merge from manual_lens_info to crop_rec_4k_mlv_snd. Last conflicts to solve and then I’l share. Can you review?

    1. Georg Hofstetter

      sure. added some comments below.

      when merging into mlv_snd subbranch, especially mlv_dump will have some extra effort as it’s block processing methods changed

      1. alessandro profiti

        yes, I noticed it.

        I’m currently solving conflict to raw.c and mem.c. Already solved what is related to MLV and RAW. Got some conflict also from refactor of timer function, so I have to understand what to preserve from crop_rec_4k

          1. Daniel Fort author

            You will need to split it before you make a PR to the Main repo and make separate commits on the files needed for ML core, LUA, mlv_rec, mlv_lite, silent and finally the manual lens scripts. Yeah, it is a lot of work to preserve the change history because you will have to merge then reverse most of the changes and edit the files before committing the merge for each of the categories g3gg0 listed. There might be an easy way to do this but I’m no Mercurial expert.

            1. alessandro profiti

              it’s possible to commit only part of the files after merging, but I don’t know if is possible to commit only a set of lines of a file like can be done with git…

              This will make thing much harder because there will be some mixed diff after merging due to need to manage changes not ported to lua_fix…

              I was hoping to make a standard merge to crop_rec_4k_mel_snd just to have all the past commit history from manual_lens_info

  3. Georg Hofstetter

    No need to keep the history.

    Just squash it together and separate commits as explained.

      1. Daniel Fort author

        Damn the torpedoes full speed ahead!

        The way I would do it would be to make a copy of your local repository, making sure you’re on your crop_rec_4k_mlv_snd_elns branch. Now in your ML fork make a new clean branch off of crop_rec_4k_mlv_snd and start copying and pasting from your saved copy and make commits as you go along.

        1. Georg Hofstetter

          or use tortoise hg’s workbench where you can simply select which files to commit. (git equivalent to staging) ;)

      2. Georg Hofstetter

        I would just copy the final files into the original repository and would commit the changed files step by step.

        First infrastructural changes (ml core) and then the independent modules

        1. alessandro profiti

          I saved a patch before committing all files from the merge.

          My idea was to be able to restart the branch and split all the changes into different commits after the PR was tested and revised.

          At the moment mlv_dump need to be fixed, as either selftest module. Also I need to understand how to modify mlv to implement what you suggested and I need a feedback if it’s working good as we manage to get from this branch

            1. alessandro profiti

              uhm… Probably is due to refactor of config.lua I committed before merging… I copied the improved version from my CF, and I assumed it was good because I was using in camera… probably I screwed up something while cleaning from debugging instruction

              Try reverting commits wich modify config.lua, You can see easily from history what changed

                1. Daniel Fort author

                  Thought we should switch over to your repository but I keep getting notes here. Haven’t tested mlv_rec or silent on this version but the xml for CR2 files is working nicely.

                  1. Daniel Fort author

                    mlv_rec isn’t working but silent with mlv_lite seems to be fine.

                    [EDIT] on this version--not tested on yours

  4. alessandro profiti

    New comments on mlv.c and mlv.h.

    If those structures are ok, we can move to edit mlv_rec,mlv_lite,silent and mlv_dum

    1. alessandro profiti

      Found a bug with lens name that cause camera to freeze.

      int string_length = strlen(lens_info.name); // from mlv_fill_elns in mlv.c
      

      changed with this to see if was the cause:

        int string_length = 63;
      

      I got mlv_rec and mlv_lite recording. Silent pictures wasn’t freezing camera anymore and it was more responsible, but produced pictures can’t be opened.

      Still no ELNS bloc in .mlv files

      Could be a string missing termination character of extended lens name, I already had this problem with standard LENS block, with i solved using snprintf() https://bitbucket.org/hudson/magic-lantern/commits/127423c619b07844b4f7a9c37c787a549cd93ed1

      @g3gg0 Need your help to check if there are memory problems

      edit: ASSERT((current_hdr->blockSize > 0) && (current_hdr->blockSize < 0x20000000)); with mlv_rec

      1. Daniel Fort author

        No camera freezes over here. That change didn’t seem to make any difference. Currently no ELNS block and silent still mlv not working.

        When choosing a lens with a long name the LENS block looks like this:

        Block: LENS
          Offset: 0x00000184
          Number: 5
            Size: 96
            Time: 0.806000 ms
             Name:        'Samyang 12mm f/2.8 ED AS NCS Fis000000000'
             Serial:      '000000000' (no valid S/N)
             Focal Len:   12 mm
             Focus Dist:  0 mm
             Aperture:    f/2.80
             IS Mode:     0
             AF Mode:     3
             Lens ID:     0x00000000
             Flags:       0x00000000
        

        1. alessandro profiti

          Don’t know why there are ‘0’ in LENS block. I get this:

          Block: LENS
            Offset: 0x0017ee60
            Number: 29
              Size: 96
              Time: 400.313000 ms
               Name:        'Samyang 8mm f/3.5 UMC Fish-Eye '
               Serial:      '000000000' (no valid S/N)
               Focal Len:   8 mm
               Focus Dist:  0 mm
               Aperture:    f/4.00
               IS Mode:     0
               AF Mode:     3
               Lens ID:     0x00000000
               Flags:       0x00000000
          

          Also can playback with mlv_play but get a black screen with MLVRawViewer 1.4.3 and MLVF

  5. Daniel Fort author

    mlv_dump seems to be fine with the latest changes. It works with an mlv recorded using the current manual_lens_info branch. Merged crop_rec_4k_mlv_snd changes still not working properly.

    Block: LENS
      Offset: 0x00000184
      Number: 5
        Size: 96
        Time: 0.801000 ms
         Name:        'Samyang 12mm f/2.8 ED AS NCS Fi'
         Serial:      '000000000' (no valid S/N)
         Focal Len:   12 mm
         Focus Dist:  0 mm
         Aperture:    f/2.80
         IS Mode:     0
         AF Mode:     3
         Lens ID:     0x00000000
         Flags:       0x00000000
    Block: ELNS
      Offset: 0x000001e4
      Number: 6
        Size: 95
        Time: 0.821000 ms
         Name:                'Samyang 12mm f/2.8 ED AS NCS Fisheye'
         Focal Length Min:    0 mm
         Focal Length Max:    0 mm
         Aperture Min:        f/0.00
         Aperture Max:        f/0.00
         Version:             0
         Extender Info:       0x00
         Capabilities:        0x00
         Chipped:             0x00
    

  6. alessandro profiti

    Here is the patch @daniel_fort :

    diff --git a/modules/mlv_lite/mlv_lite.c b/modules/mlv_lite/mlv_lite.c
    --- a/modules/mlv_lite/mlv_lite.c
    +++ b/modules/mlv_lite/mlv_lite.c
    @@ -359,10 +359,10 @@
     static GUARDED_BY(RawRecTask)   mlv_idnt_hdr_t idnt_hdr;
     static GUARDED_BY(RawRecTask)   mlv_expo_hdr_t expo_hdr;
     static GUARDED_BY(RawRecTask)   mlv_lens_hdr_t lens_hdr;
    -static GUARDED_BY(RawRecTask)   mlv_elns_hdr_t elns_hdr;
     static GUARDED_BY(RawRecTask)   mlv_rtci_hdr_t rtci_hdr;
     static GUARDED_BY(RawRecTask)   mlv_wbal_hdr_t wbal_hdr;
    -static GUARDED_BY(LiveViewTask) mlv_vidf_hdr_t vidf_hdr;
    +static GUARDED_BY(LiveViewTask) mlv_vidf_hdr_t vidf_hdr;
    +static GUARDED_BY(RawRecTask)   mlv_elns_hdr_t *elns_hdr;
     static GUARDED_BY(RawRecTask)   uint64_t mlv_start_timestamp = 0;
            GUARDED_BY(RawRecTask)   uint32_t raw_rec_trace_ctx = TRACE_ERROR;
    
    @@ -3048,7 +3048,7 @@
             fail |= !mlv_write_hdr(f, (mlv_hdr_t *)&idnt_hdr);
             fail |= !mlv_write_hdr(f, (mlv_hdr_t *)&expo_hdr);
             fail |= !mlv_write_hdr(f, (mlv_hdr_t *)&lens_hdr);
    -        fail |= !mlv_write_hdr(f, (mlv_hdr_t *)&elns_hdr);
    +        fail |= !mlv_write_hdr(f, (mlv_hdr_t *)elns_hdr);
             fail |= !mlv_write_hdr(f, (mlv_hdr_t *)&rtci_hdr);
             fail |= !mlv_write_hdr(f, (mlv_hdr_t *)&wbal_hdr);
             fail |= mlv_write_vers_blocks(f, mlv_start_timestamp);
    diff --git a/modules/mlv_rec/dng/dng.c b/modules/mlv_rec/dng/dng.c
    --- a/modules/mlv_rec/dng/dng.c
    +++ b/modules/mlv_rec/dng/dng.c
    @@ -669,7 +669,12 @@
                 {tcBaselineExposureOffset,      ttSRational,RATIONAL_ENTRY2(0, 1, header, &data_offset)},
                 {tcImageDescription,            ttAscii,    STRING_ENTRY(frame_info->info_str, header, &data_offset)},
             };
    -        
    +
    +        /* Use Lens Model from ELNS Block if present */
    +        char* lens = (frame_info->elns_str != NULL)
    +              && (strlen(frame_info->elns_str) > strlen(frame_info->lens_hdr.lensName))
    +              ? frame_info->elns_str : frame_info->lens_hdr.lensName;
    +
             struct directory_entry EXIF_IFD[EXIF_IFD_COUNT] =
             {
                 {tcExposureTime,                ttRational, RATIONAL_ENTRY2((int32_t)frame_info->expo_hdr.shutterValue/1000, 1000, header, &data_offset)},
    @@ -682,7 +687,7 @@
                 {tcFocalPlaneXResolutionExif,   ttRational, RATIONAL_ENTRY(focal_resolution_x, header, &data_offset, 2)},
                 {tcFocalPlaneYResolutionExif,   ttRational, RATIONAL_ENTRY(focal_resolution_y, header, &data_offset, 2)},
                 {tcFocalPlaneResolutionUnitExif,ttShort,    1,      camera_id[current_cam].focal_unit}, //inches
    -            {tcLensModelExif,               ttAscii,    STRING_ENTRY((char*)frame_info->lens_hdr.lensName, header, &data_offset)},
    +            {tcLensModelExif,               ttAscii,    STRING_ENTRY(lens, header, &data_offset)},
             };
    
             /* do not put image description, if the length is zero */
    diff --git a/modules/mlv_rec/dng/dng.h b/modules/mlv_rec/dng/dng.h
    --- a/modules/mlv_rec/dng/dng.h
    +++ b/modules/mlv_rec/dng/dng.h
    @@ -76,8 +76,8 @@
         mlv_rawc_hdr_t rawc_hdr;
         mlv_expo_hdr_t expo_hdr;
         mlv_lens_hdr_t lens_hdr;
    -    mlv_elns_hdr_t elns_hdr;
         mlv_wbal_hdr_t wbal_hdr;
    +    char *elns_str;
         char *info_str;
     };
    
    diff --git a/modules/mlv_rec/mlv.c b/modules/mlv_rec/mlv.c
    --- a/modules/mlv_rec/mlv.c
    +++ b/modules/mlv_rec/mlv.c
    @@ -62,7 +62,7 @@
         strncpy((char *)hdr->lensSerial, buf, 32);
     }
    
    -void mlv_fill_elns(mlv_elns_hdr_t *hdr, uint64_t start_timestamp)
    +void mlv_fill_elns(mlv_elns_hdr_t **hdr, uint64_t start_timestamp)
     {
         /* Calculate total block length: header + fixed data + variable lensName string */
         int string_length = strlen(lens_info.name);
    @@ -73,6 +73,7 @@
         mlv_set_type((mlv_hdr_t *)header, "ELNS");
         mlv_set_timestamp((mlv_hdr_t *)header, start_timestamp);
         header->blockSize = block_length;
    +    /* Fill ELNS data */
         header->focalLengthMin = lens_info.lens_focal_min;
         header->focalLengthMax = lens_info.lens_focal_max;
         header->apertureMin = RAW2VALUE(aperture, lens_info.raw_aperture_min) / 10.0;
    @@ -84,10 +85,10 @@
    
         /* Store lensName string at the end of mlv_elns_hdr_t */
         char *lens_hdr_payload = (char *)&header[1];
    -    strcpy(lens_hdr_payload, lens_info.name);
    +    snprintf(lens_hdr_payload, string_length + 1, "%s", lens_info.name);
    
         /* update block with new values */
    -    hdr = header;
    +    *hdr = header;
     }
    
     void mlv_fill_wbal(mlv_wbal_hdr_t *hdr, uint64_t start_timestamp)
    diff --git a/modules/mlv_rec/mlv.h b/modules/mlv_rec/mlv.h
    --- a/modules/mlv_rec/mlv.h
    +++ b/modules/mlv_rec/mlv.h
    @@ -176,9 +176,7 @@
         uint8_t     extenderInfo;       /* extender information, if provided by camera       */
         uint8_t     capabilities;       /* capability information, if provided by camera     */
         uint8_t     chipped;            /* when not zero, lens is communicating with camera  */
    -    uint8_t     length;             /* to allow lens with name longer than 32byte        */
      /* uint8_t     lensName[variable];    full lens string, null terminated                 */
    -    // TODO: Review Specs
     }  mlv_elns_hdr_t;
    
     typedef struct {
    @@ -304,7 +302,7 @@
     void mlv_fill_rtci(mlv_rtci_hdr_t *hdr, uint64_t start_timestamp);
     void mlv_fill_expo(mlv_expo_hdr_t *hdr, uint64_t start_timestamp);
     void mlv_fill_lens(mlv_lens_hdr_t *hdr, uint64_t start_timestamp);
    -void mlv_fill_elns(mlv_elns_hdr_t *hdr, uint64_t start_timestamp);
    +void mlv_fill_elns(mlv_elns_hdr_t **hdr, uint64_t start_timestamp);
     void mlv_fill_idnt(mlv_idnt_hdr_t *hdr, uint64_t start_timestamp);
     void mlv_fill_wbal(mlv_wbal_hdr_t *hdr, uint64_t start_timestamp);
     void mlv_fill_styl(mlv_styl_hdr_t *hdr, uint64_t start_timestamp);
    diff --git a/modules/mlv_rec/mlv_dump.c b/modules/mlv_rec/mlv_dump.c
    --- a/modules/mlv_rec/mlv_dump.c
    +++ b/modules/mlv_rec/mlv_dump.c
    @@ -1941,7 +1941,8 @@
         memset(&rtci_info, 0x00, sizeof(mlv_rtci_hdr_t));
         memset(&rawc_info, 0x00, sizeof(mlv_rawc_hdr_t));
         memset(&main_header, 0x00, sizeof(mlv_file_hdr_t));
    -
    +
    +    char elns_string[1024] = "";
         char info_string[1024] = "";
    
         /* this table contains the XREF chunk read from idx file, if existing */
    @@ -3468,7 +3469,8 @@
                                 frame_info.expo_hdr             = expo_info;
                                 frame_info.lens_hdr             = lens_info;
                                 frame_info.wbal_hdr             = wbal_info;
    -                            frame_info.rawc_hdr             = rawc_info;
    +                            frame_info.rawc_hdr             = rawc_info;
    +                            frame_info.elns_str             = elns_string;
                                 frame_info.info_str             = info_string;
                                 frame_info.rawi_hdr.xRes        = lv_rec_footer.xRes;
                                 frame_info.rawi_hdr.yRes        = lv_rec_footer.yRes;
    @@ -3780,30 +3782,24 @@
                 {
                     mlv_elns_hdr_t block_hdr = *(mlv_elns_hdr_t *)mlv_block;
    
    -                /* get the string length and malloc a buffer for that string */
    -                int str_length = block_hdr.length;
    -
    -                if(str_length)
    +                void *payload = BYTE_OFFSET(mlv_block, sizeof(mlv_elns_hdr_t));
    +                int str_length = MIN(block_hdr.blockSize - sizeof(block_hdr), sizeof(elns_string) - 1);
    +
    +                /* Fill lens model data for DNG processing */
    +                strncpy(elns_string, payload, str_length);
    +                elns_string[str_length] = '\000';
    +
    +                if(verbose)
                     {
    -                    void *payload = BYTE_OFFSET(mlv_block, sizeof(mlv_elns_hdr_t) - 1);
    -                    char *buf = malloc(str_length + 1);
    -
    -                    strncpy(buf, payload, str_length);
    -                    buf[str_length] = '\000';
    -
    -                    if(verbose)
    -                    {
    -                        print_msg(MSG_INFO, "     Name:                '%s'\n", buf);
    -                        print_msg(MSG_INFO, "     Focal Length Min:    %d mm\n", elns_info.focalLengthMin);
    -                        print_msg(MSG_INFO, "     Focal Length Max:    %d mm\n", elns_info.focalLengthMax);
    -                        print_msg(MSG_INFO, "     Aperture Min:        f/%.2f\n", (double)elns_info.apertureMin);
    -                        print_msg(MSG_INFO, "     Aperture Max:        f/%.2f\n", (double)elns_info.apertureMax);
    -                        print_msg(MSG_INFO, "     Version:             %d\n", elns_info.version);
    -                        print_msg(MSG_INFO, "     Extender Info:       0x%02X\n", elns_info.extenderInfo);
    -                        print_msg(MSG_INFO, "     Capabilities:        0x%02X\n", elns_info.capabilities);
    -                        print_msg(MSG_INFO, "     Chipped:             0x%02X\n", elns_info.chipped);
    -                    }
    -                    free(buf);
    +                    print_msg(MSG_INFO, "     Name:                '%s'\n", payload);
    +                    print_msg(MSG_INFO, "     Focal Length Min:    %d mm\n", block_hdr.focalLengthMin);
    +                    print_msg(MSG_INFO, "     Focal Length Max:    %d mm\n", block_hdr.focalLengthMax);
    +                    print_msg(MSG_INFO, "     Aperture Min:        f/%.2f\n", (double)block_hdr.apertureMin);
    +                    print_msg(MSG_INFO, "     Aperture Max:        f/%.2f\n", (double)block_hdr.apertureMax);
    +                    print_msg(MSG_INFO, "     Version:             %d\n", block_hdr.version);
    +                    print_msg(MSG_INFO, "     Extender Info:       0x%02X\n", block_hdr.extenderInfo);
    +                    print_msg(MSG_INFO, "     Capabilities:        0x%02X\n", block_hdr.capabilities);
    +                    print_msg(MSG_INFO, "     Chipped:             0x%02X\n", block_hdr.chipped);
                     }
                 }
                 else if(!memcmp(mlv_block->blockType, "ELVL", 4))
    diff --git a/modules/mlv_rec/mlv_rec.c b/modules/mlv_rec/mlv_rec.c
    --- a/modules/mlv_rec/mlv_rec.c
    +++ b/modules/mlv_rec/mlv_rec.c
    @@ -200,9 +200,9 @@
    
     static mlv_expo_hdr_t last_expo_hdr;
     static mlv_lens_hdr_t last_lens_hdr;
    -static mlv_elns_hdr_t last_elns_hdr;
     static mlv_wbal_hdr_t last_wbal_hdr;
    -static mlv_styl_hdr_t last_styl_hdr;
    +static mlv_styl_hdr_t last_styl_hdr;
    +static mlv_elns_hdr_t *last_elns_hdr;
    
    
     /* for debugging */
    @@ -1535,13 +1535,13 @@
                 trace_write(raw_rec_trace_ctx, "[polling_cbr] queueing INFO blocks");
                 mlv_expo_hdr_t *expo_hdr = malloc(sizeof(mlv_expo_hdr_t));
                 mlv_lens_hdr_t *lens_hdr = malloc(sizeof(mlv_lens_hdr_t));
    +            mlv_wbal_hdr_t *wbal_hdr = malloc(sizeof(mlv_wbal_hdr_t));
                 mlv_elns_hdr_t *elns_hdr = malloc(sizeof(mlv_elns_hdr_t));
    -            mlv_wbal_hdr_t *wbal_hdr = malloc(sizeof(mlv_wbal_hdr_t));
    
                 mlv_fill_expo(expo_hdr, mlv_start_timestamp);
                 mlv_fill_lens(lens_hdr, mlv_start_timestamp);
    -            mlv_fill_elns(elns_hdr, mlv_start_timestamp);
    -            mlv_fill_wbal(wbal_hdr, mlv_start_timestamp);
    +            mlv_fill_wbal(wbal_hdr, mlv_start_timestamp);
    +            mlv_fill_elns(&elns_hdr, mlv_start_timestamp);
    
                 msg_queue_post(mlv_block_queue, (uint32_t) expo_hdr);
                 msg_queue_post(mlv_block_queue, (uint32_t) lens_hdr);
    @@ -2674,10 +2674,10 @@
             mlv_rtci_hdr_t rtci_hdr;
             mlv_expo_hdr_t expo_hdr;
             mlv_lens_hdr_t lens_hdr;
    -        mlv_elns_hdr_t elns_hdr;
             mlv_idnt_hdr_t idnt_hdr;
             mlv_wbal_hdr_t wbal_hdr;
             mlv_styl_hdr_t styl_hdr;
    +        mlv_elns_hdr_t *elns_hdr;
    
             mlv_fill_rtci(&rtci_hdr, mlv_start_timestamp);
             mlv_fill_expo(&expo_hdr, mlv_start_timestamp);
    @@ -2694,12 +2694,12 @@
             idnt_hdr.timestamp = 4;
             wbal_hdr.timestamp = 5;
             styl_hdr.timestamp = 6;
    -        elns_hdr.timestamp = 7;
    +        elns_hdr->timestamp = 7;
    
             mlv_write_hdr(f, (mlv_hdr_t *)&rtci_hdr);
             mlv_write_hdr(f, (mlv_hdr_t *)&expo_hdr);
             mlv_write_hdr(f, (mlv_hdr_t *)&lens_hdr);
    -        mlv_write_hdr(f, (mlv_hdr_t *)&elns_hdr);
    +        mlv_write_hdr(f, (mlv_hdr_t *)elns_hdr);
             mlv_write_hdr(f, (mlv_hdr_t *)&idnt_hdr);
             mlv_write_hdr(f, (mlv_hdr_t *)&wbal_hdr);
             mlv_write_hdr(f, (mlv_hdr_t *)&styl_hdr);
    @@ -3211,7 +3211,7 @@
    
             mlv_expo_hdr_t old_expo = last_expo_hdr;
             mlv_lens_hdr_t old_lens = last_lens_hdr;
    -        mlv_elns_hdr_t old_elns = last_elns_hdr;
    +        mlv_elns_hdr_t *old_elns = last_elns_hdr;
    
             mlv_fill_expo(&last_expo_hdr, mlv_start_timestamp);
             mlv_fill_lens(&last_lens_hdr, mlv_start_timestamp);
    @@ -3220,7 +3220,7 @@
             /* update timestamp for comparing content changes */
             old_expo.timestamp = last_expo_hdr.timestamp;
             old_lens.timestamp = last_lens_hdr.timestamp;
    -        old_elns.timestamp = last_elns_hdr.timestamp;
    +        old_elns->timestamp = last_elns_hdr->timestamp;
    
             /* write new state if something changed */
             if(memcmp(&last_expo_hdr, &old_expo, sizeof(mlv_expo_hdr_t)))
    @@ -3240,8 +3240,8 @@
             /* write new state if something changed */
             if(memcmp(&last_elns_hdr, &old_elns, sizeof(mlv_elns_hdr_t)))
             {
    -            mlv_hdr_t *hdr = malloc(sizeof(mlv_elns_hdr_t));
    -            memcpy(hdr, &last_elns_hdr, sizeof(mlv_elns_hdr_t));
    +            mlv_hdr_t *hdr = malloc(last_elns_hdr->blockSize);
    +            memcpy(hdr, last_elns_hdr, last_elns_hdr->blockSize);
                 msg_queue_post(mlv_block_queue, (uint32_t) hdr);
             }
         }
    diff --git a/modules/silent/silent.c b/modules/silent/silent.c
    --- a/modules/silent/silent.c
    +++ b/modules/silent/silent.c
    @@ -28,10 +28,10 @@
     extern WEAK_FUNC(ret_0) void mlv_fill_rtci(mlv_rtci_hdr_t *hdr, uint64_t start_timestamp);
     extern WEAK_FUNC(ret_0) void mlv_fill_expo(mlv_expo_hdr_t *hdr, uint64_t start_timestamp);
     extern WEAK_FUNC(ret_0) void mlv_fill_lens(mlv_lens_hdr_t *hdr, uint64_t start_timestamp);
    -extern WEAK_FUNC(ret_0) void mlv_fill_elns(mlv_elns_hdr_t *hdr, uint64_t start_timestamp);
     extern WEAK_FUNC(ret_0) void mlv_fill_idnt(mlv_idnt_hdr_t *hdr, uint64_t start_timestamp);
     extern WEAK_FUNC(ret_0) void mlv_fill_wbal(mlv_wbal_hdr_t *hdr, uint64_t start_timestamp);
     extern WEAK_FUNC(ret_0) void mlv_fill_styl(mlv_styl_hdr_t *hdr, uint64_t start_timestamp);
    +extern WEAK_FUNC(ret_0) void mlv_fill_elns(mlv_elns_hdr_t **hdr, uint64_t start_timestamp);
     extern WEAK_FUNC(ret_0_long) uint64_t mlv_generate_guid();
     extern WEAK_FUNC(ret_0) void mlv_init_fileheader(mlv_file_hdr_t *hdr);
     extern WEAK_FUNC(ret_0) void mlv_set_type(mlv_hdr_t *hdr, char *type);
    @@ -366,11 +366,11 @@
         mlv_rtci_hdr_t rtci_hdr;
         mlv_expo_hdr_t expo_hdr;
         mlv_lens_hdr_t lens_hdr;
    -    mlv_elns_hdr_t elns_hdr;
         mlv_idnt_hdr_t idnt_hdr;
         mlv_wbal_hdr_t wbal_hdr;
         mlv_styl_hdr_t styl_hdr;
         mlv_vidf_hdr_t vidf_hdr;
    +    mlv_elns_hdr_t *elns_hdr;
         FILE* save_file = NULL;    
    
         /* default case: use last filename */
    @@ -489,7 +489,7 @@
         if (FIO_WriteFile(save_file, &rtci_hdr, rtci_hdr.blockSize) != (int)rtci_hdr.blockSize) goto write_error;
         if (FIO_WriteFile(save_file, &expo_hdr, expo_hdr.blockSize) != (int)expo_hdr.blockSize) goto write_error;
         if (FIO_WriteFile(save_file, &lens_hdr, lens_hdr.blockSize) != (int)lens_hdr.blockSize) goto write_error;
    -    if (FIO_WriteFile(save_file, &elns_hdr, elns_hdr.blockSize) != (int)elns_hdr.blockSize) goto write_error;
    +    if (FIO_WriteFile(save_file, elns_hdr, elns_hdr->blockSize) != (int)elns_hdr->blockSize) goto write_error;
    
         memset(&vidf_hdr, 0, sizeof(mlv_vidf_hdr_t));
         mlv_set_type((mlv_hdr_t *)&vidf_hdr, "VIDF");
    diff --git a/scripts/lib/config.lua b/scripts/lib/config.lua
    --- a/scripts/lib/config.lua
    +++ b/scripts/lib/config.lua
    @@ -79,8 +79,26 @@
    
     end
    
    +-- Load config from file if exists, otherwise create a new table in memory
     local create_internal = function(default,thisfile)
    +  local filename = string.format("%s%s.lcf", dryos.config_dir.path,thisfile)
    +  local cfg = config.findConfig(filename)
    
    +  if cfg == nil then
    +    -- Create a config from scratch
    +    cfg = {}
    +    cfg.filename = filename
    +    cfg.default = default -- TODO: Replicate .data's structure
    +    cfg.data = {}
    +    -- check for existing .cfg to load
    +    setmetatable(cfg,config)
    +    -- load previus config from file if available
    +    cfg.data = cfg:load()
    +    -- add to data structure
    +    table.insert(config.configs,cfg)
    +  end
    +
    +  return cfg
     end
    
     local function recursiveLoad(m,cfg)
    @@ -108,33 +126,17 @@
     ]]
     function config.create(default)
       local short_name = string.match(debug.getinfo(2,"S").short_src,"/([^/%.]+)%.[^/%.]+$")
    -  local filename = string.format("%s%s.lcf", dryos.config_dir.path,short_name)
    +  local cfg = create_internal(default,short_name)
    
    -  local cfg = config.findConfig(filename)
    -  if cfg ~= nil then
    -    -- Append config data
    -    for k,v in pairs(default) do
    -      cfg.data[k] = v
    -    end
    -  else
    -    -- Create a config from scratch
    -    cfg = {}
    -    cfg.filename = filename
    -    cfg.default = default -- TODO: Replicate .data's structure
    -    cfg.data = {}
    -    -- check for existing .cfg to load
    -    setmetatable(cfg,config)
    -    cfg.data = cfg:load()
    -    if cfg.data == nil then
    -      -- Create a config from scratch
    -      for k,v in pairs(default) do
    -        cfg.data[k] = v
    -      end
    -    end
    -    table.insert(config.configs,cfg)
    -   end
    +  -- Append config data
    +  for k,v in pairs(default) do
    +    cfg.default[k] = v
    +    cfg.data[k] = v
    +  end
    
    -   return cfg
    +  --  cfg.default = default -- TODO: Replicate .data's structure
    +
    +  return cfg
     end
    
     --[[---------------------------------------------------------------------------
    @@ -158,37 +160,18 @@
         insertMenu(default,m)
    
         local short_name = string.match(debug.getinfo(2,"S").short_src,"/([^/%.]+)%.[^/%.]+$")
    -    local filename = string.format("%s%s.lcf", dryos.config_dir.path,short_name)
    +    local cfg = create_internal(default,short_name)
    
    -    local cfg = config.findConfig(filename)
    -    if cfg ~= nil then
    -      -- Already present in config.configs, append menu
    -      if cfg.data[m.name] ~= nil then
    -        -- Avoid overwriting values when loading config form .cfg
    -        cfg.data[m.name].menu = m
    -        recursiveLoad(m,cfg.data[m.name])
    -      else
    -        insertMenu(cfg.data,m)
    -      end
    +    if cfg.data[m.name] == nil then
    +      -- Create a config for menu from scratch
    +      insertMenu(cfg.data,m)
         else
    -      -- Create a config from scratch
    -      cfg = {}
    -      cfg.filename = filename
    -      cfg.default = default -- TODO: Replicate .data's structure
    -      cfg.data = {}
    -      -- check for existing .cfg to load
    -      setmetatable(cfg,config)
    -      cfg.data = cfg:load()
    -      if cfg.data == nil then
    -        -- Create a config from scratch
    -        insertMenu(cfg.data,m)
    -      else
    -        -- load values to menu
    -        cfg.data[m.name].menu = m
    -        recursiveLoad(m,cfg.data[m.name])
    -      end
    -      table.insert(config.configs,cfg)
    -     end
    +      -- Already present in config.configs, load values to menu from config
    +      cfg.data[m.name].menu = m
    +      recursiveLoad(m,cfg.data[m.name])
    +    end
    +
    +    --    cfg.default = default -- TODO: Replicate .data's structure
    
         return cfg.data[m.name]
     end
    @@ -213,9 +196,6 @@
     @function saving
     ]]
     function config:saving()
    -local short_name = string.match(debug.getinfo(2,"S").short_src,"/([^/%.]+)%.[^/%.]+$")
    -local filename = string.format("%s%s.lcf", dryos.config_dir.path,short_name)
    -
       -- Copy values of each menu
       for k,v in pairs(self.data) do
         -- k -> A table representing a menu entry or a single entry of a simple config
    @@ -238,14 +218,15 @@
     ]]
     function config:save()
         local f = io.open(self.filename,"w")
    +    assert(f ~= nil, "Could not save config: "..self.filename)
    +    -- Serialize data into a loadable format
         f:write("return ")
    -    assert(f ~= nil, "Could not save config: "..self.filename)
    -    config.serialize(f,self.data)
    +    config.serialize(f,self.data,1)
         f:close()
     end
    
     --private
    -function config.serialize(f,o)
    +function config.serialize(f,o,lvl)
         if type(o) == "number" or type(o) == "boolean" then
             f:write(tostring(o))
         elseif type(o) == "string" then
    @@ -254,13 +235,17 @@
             f:write("{\n")
             for k,v in pairs(o) do
               if k ~= "menu" then
    -            f:write("\t[")
    -            config.serialize(f,k)
    +            -- Indent starting line
    +            f:write(string.rep("\t", lvl))
    +            f:write("[")
    +            config.serialize(f,k,lvl+1)
                 f:write("] = ")
    -            config.serialize(f,v)
    +            config.serialize(f,v,lvl+1)
                 f:write(",\n")
               end
             end
    +        -- Indent closing bracket
    +        f:write(string.rep("\t", lvl-1))
             f:write("}")
         else
             --something we don't know how to serialize, just skip it
    

    @g3gg0 Updated ELNS block specs and mlv_dump to process ELNS block for DNG correctly