[libbluray-devel] Reduce inline file entry memory footprint

Petri Hintukainen git at videolan.org
Fri Jun 9 12:33:39 CEST 2017


libudfread | branch: master | Petri Hintukainen <phintuka at gmail.com> | Wed Jun  7 23:04:51 2017 +0300| [1a4788b34e1e14a6c8c204a6f2f9d9ae895633b9] | committer: Petri Hintukainen

Reduce inline file entry memory footprint

> http://git.videolan.org/gitweb.cgi/libudfread.git/?a=commit;h=1a4788b34e1e14a6c8c204a6f2f9d9ae895633b9
---

 src/ecma167.c | 12 ++++++------
 src/ecma167.h | 15 +++++++++++----
 src/udfread.c | 26 +++++++++++++-------------
 3 files changed, 30 insertions(+), 23 deletions(-)

diff --git a/src/ecma167.c b/src/ecma167.c
index 6c694f9..00c4a4d 100644
--- a/src/ecma167.c
+++ b/src/ecma167.c
@@ -300,16 +300,16 @@ static struct file_entry *_decode_file_entry(const uint8_t *p, size_t size,
 
     fe->file_type = tag.file_type;
     fe->length    = _get_u64(p + 56);
-    fe->num_ad    = num_ad;
     fe->ad_type   = tag.flags & 7;
 
     if (content_inline) {
         /* data of small files can be embedded in file entry */
         /* copy embedded file data */
         fe->content_inline = 1;
-        memcpy(fe->data.content, p + p_ad, l_ad);
+        memcpy(fe->u.data.content, p + p_ad, l_ad);
     } else {
-        _decode_file_ads(p + p_ad, fe->ad_type, partition, &fe->data.ad[0], num_ad);
+        fe->u.ads.num_ad = num_ad;
+        _decode_file_ads(p + p_ad, fe->ad_type, partition, &fe->u.ads.ad[0], num_ad);
     }
 
     return fe;
@@ -339,15 +339,15 @@ int decode_allocation_extent(struct file_entry **p_fe, const uint8_t *p, size_t
         return 0;
     }
 
-    fe = (struct file_entry *)realloc(fe, sizeof(struct file_entry) + sizeof(struct long_ad) * (fe->num_ad + num_ad));
+    fe = (struct file_entry *)realloc(fe, sizeof(struct file_entry) + sizeof(struct long_ad) * (fe->u.ads.num_ad + num_ad));
     if (!fe) {
         return -1;
     }
     *p_fe = fe;
 
     /* decode new allocation descriptors */
-    _decode_file_ads(p + 24, fe->ad_type, partition, &fe->data.ad[fe->num_ad], num_ad);
-    fe->num_ad += num_ad;
+    _decode_file_ads(p + 24, fe->ad_type, partition, &fe->u.ads.ad[fe->u.ads.num_ad], num_ad);
+    fe->u.ads.num_ad += num_ad;
 
     return 0;
 }
diff --git a/src/ecma167.h b/src/ecma167.h
index e483f05..38b73a2 100644
--- a/src/ecma167.h
+++ b/src/ecma167.h
@@ -214,11 +214,18 @@ struct file_entry {
     uint8_t        content_inline; /* 1 if file data is embedded in file entry */
     uint8_t        ad_type;        /* from icb_flags; used when parsing allocation extents */
 
-    uint32_t       num_ad;
     union {
-        struct long_ad ad[1];      /* Most files have only single extent, files in 3D BDs can have 100+. */
-        uint8_t        content[1]; /* content of small files is embedded here */
-    } data;
+        /* "normal" file */
+        struct {
+            uint32_t       num_ad;
+            struct long_ad ad[1];      /* Most files have only single extent, files in 3D BDs can have 100+. */
+        } ads;
+
+        /* inline file */
+        struct {
+            uint8_t        content[1]; /* content of small files is embedded here */
+        } data;
+    } u;
 };
 
 struct file_entry *decode_file_entry    (const uint8_t *p, size_t size, uint16_t partition);
diff --git a/src/udfread.c b/src/udfread.c
index 936e415..a0f050b 100644
--- a/src/udfread.c
+++ b/src/udfread.c
@@ -514,13 +514,13 @@ static int _map_metadata_partition(udfread_block_input *input,
 
         if (fe->content_inline) {
             udf_error("invalid metadata file (content inline)\n");
-        } else if (!fe->num_ad) {
+        } else if (!fe->u.ads.num_ad) {
             udf_error("invalid metadata file (no allocation descriptors)\n");
         } else if (fe->file_type == UDF_FT_METADATA) {
-            part->p[1].lba = pd->start_block + fe->data.ad[0].lba;
+            part->p[1].lba = pd->start_block + fe->u.ads.ad[0].lba;
             udf_log("metadata file at lba %u\n", part->p[1].lba);
         } else if (fe->file_type == UDF_FT_METADATA_MIRROR) {
-            part->p[1].mirror_lba = pd->start_block + fe->data.ad[0].lba;
+            part->p[1].mirror_lba = pd->start_block + fe->u.ads.ad[0].lba;
             udf_log("metadata mirror file at lba %u\n", part->p[1].mirror_lba);
         } else {
             udf_error("unknown metadata file type %u\n", fe->file_type);
@@ -839,13 +839,13 @@ static struct file_entry *_read_file_entry(udfread *udf,
 
     /* read possible additional allocation extents */
     if (fe) {
-        while (fe->num_ad > 0 &&
-               fe->data.ad[fe->num_ad - 1].extent_type == ECMA_AD_EXTENT_AD) {
+        while (fe->u.ads.num_ad > 0 &&
+               fe->u.ads.ad[fe->u.ads.num_ad - 1].extent_type == ECMA_AD_EXTENT_AD) {
 
             /* drop pointer to this extent from the end of AD list */
-            fe->num_ad--;
+            fe->u.ads.num_ad--;
 
-            icb = &fe->data.ad[fe->num_ad];
+            icb = &fe->u.ads.ad[fe->u.ads.num_ad];
             udf_log("_read_file_entry: reading allocation extent @%u\n", icb->lba);
 
             buf = _read_metadata(udf, icb, &tag_id);
@@ -963,16 +963,16 @@ static struct udf_dir *_read_dir(udfread *udf, const struct long_ad *icb)
     if (fe->content_inline) {
         dir = (struct udf_dir *)calloc(1, sizeof(struct udf_dir));
         if (dir) {
-            if (_parse_dir(&fe->data.content[0], fe->length, dir) < 0) {
+            if (_parse_dir(&fe->u.data.content[0], fe->length, dir) < 0) {
                 udf_error("failed parsing inline directory file\n");
                 _free_dir(&dir);
             }
         }
 
-    } else if (fe->num_ad == 0) {
+    } else if (fe->u.ads.num_ad == 0) {
         udf_error("empty directory file");
     } else {
-        dir = _read_dir_file(udf, &fe->data.ad[0]);
+        dir = _read_dir_file(udf, &fe->u.ads.ad[0]);
     }
 
     free_file_entry(&fe);
@@ -1400,8 +1400,8 @@ static uint32_t _file_lba(UDFFILE *p, uint32_t file_block)
 
     fe = p->fe;
 
-    for (i = 0; i < fe->num_ad; i++) {
-        const struct long_ad *ad = &fe->data.ad[0];
+    for (i = 0; i < fe->u.ads.num_ad; i++) {
+        const struct long_ad *ad = &fe->u.ads.ad[0];
         ad_size = (ad[i].length + UDF_BLOCK_SIZE - 1) / UDF_BLOCK_SIZE;
         if (file_block < ad_size) {
 
@@ -1560,7 +1560,7 @@ ssize_t udfread_file_read(UDFFILE *p, void *buf, size_t bytes)
 
     /* small files may be stored inline in file entry */
     if (p->fe->content_inline) {
-        memcpy(buf, &p->fe->data.content + p->pos, bytes);
+        memcpy(buf, &p->fe->u.data.content + p->pos, bytes);
         p->pos += bytes;
         return bytes;
     }



More information about the libbluray-devel mailing list