]> git.tue.mpg.de Git - paraslash.git/commitdiff
server: Store max chunk size in database.
authorAndre Noll <maan@tuebingen.mpg.de>
Fri, 23 Dec 2016 16:18:21 +0000 (17:18 +0100)
committerAndre Noll <maan@tuebingen.mpg.de>
Sat, 25 Mar 2017 10:54:36 +0000 (11:54 +0100)
This number is needed up-front for the initialization of the fec data
structures.  Currently we recompute it from the chunk table each time
the file is opened for streaming.

We can only get rid of the chunk table concept if we tell the VSS by
other means how to obtain this information.

Fortunately there is an unused 4-byte field in the on-disk afhi
structure, which is always zero at the moment. This patch starts to
use this field to store the maximal chunk size.

For backwards compatibility, when the afhi structure is loaded from
disk at stream time, we check if the field is zero and recompute the
max chunk size as before in this case.

Although the maximal chunk size is generally only needed on the
server side, for consistence we expose it though a new status item
along with chunk_tv and friends.

aac_afh.c
afh.h
afh_common.c
aft.c
configure.ac
flac_afh.c
mp3_afh.c
ogg_afh_common.c
wma_afh.c

index 12ce82df8c7fa5df9371fdac7437fd85043be2ab..97b0f4741fba22f31fff7370a9fbb8941f995463 100644 (file)
--- a/aac_afh.c
+++ b/aac_afh.c
@@ -240,6 +240,7 @@ static int aac_get_file_info(char *map, size_t numbytes, __a_unused int fd,
        afhi->chunk_table[0] = ret;
        for (i = 1; i<= afhi->chunks_total; i++)
                afhi->chunk_table[i] += ret;
+       set_max_chunk_size(afhi);
        afhi->channels = channels;
        afhi->frequency = rate;
        ret = (afhi->chunk_table[afhi->chunks_total] - afhi->chunk_table[0]) * 8; /* bits */
diff --git a/afh.h b/afh.h
index 801c168c0ca1dc578745e9af87c60028a9774827..16c01be33517ff5af95588ab9816812e97635b21 100644 (file)
--- a/afh.h
+++ b/afh.h
@@ -40,6 +40,8 @@ struct afh_info {
         * the current audio file.
         */
        uint32_t *chunk_table;
+       /** Size of the largest chunk, introduced in v0.6.0. */
+       uint32_t max_chunk_size;
        /** Period of time between sending data chunks. */
        struct timeval chunk_tv;
        /**
@@ -64,7 +66,10 @@ struct audio_file_data {
        int fd;
        /** Vss needs this for streaming. */
        struct afh_info afhi;
-       /** Size of the largest chunk. */
+       /**
+        * Size of the largest chunk. Superseded by afhi->max_chunk_size. May
+        * be removed after v0.6.1.
+        */
        uint32_t max_chunk_size;
        /** Needed to get the audio file header. */
        uint8_t audio_format_id;
@@ -130,3 +135,4 @@ void clear_afhi(struct afh_info *afhi);
 unsigned afh_get_afhi_txt(int audio_format_num, struct afh_info *afhi, char **result);
 int afh_rewrite_tags(int audio_format_id, void *map, size_t mapsize,
                struct taginfo *tags, int output_fd, const char *filename);
+void set_max_chunk_size(struct afh_info *afhi);
index dfbf75132f4e4372eb0b4c95bff8ef25793dc545..75d8b5118db91586d46f339fff0d1d1f693dfc07 100644 (file)
@@ -374,6 +374,7 @@ unsigned afh_get_afhi_txt(int audio_format_num, struct afh_info *afhi, char **re
                "%s: %" PRIu32 "\n" /* seconds total */
                "%s: %lu: %lu\n" /* chunk time */
                "%s: %" PRIu32 "\n" /* num chunks */
+               "%s: %" PRIu32 "\n" /* max chunk size */
                "%s: %s\n" /* techinfo */
                "%s: %s\n" /* artist */
                "%s: %s\n" /* title */
@@ -388,6 +389,7 @@ unsigned afh_get_afhi_txt(int audio_format_num, struct afh_info *afhi, char **re
                status_item_list[SI_CHUNK_TIME], (long unsigned)afhi->chunk_tv.tv_sec,
                        (long unsigned)afhi->chunk_tv.tv_usec,
                status_item_list[SI_NUM_CHUNKS], afhi->chunks_total,
+               status_item_list[SI_MAX_CHUNK_SIZE], afhi->max_chunk_size,
                status_item_list[SI_TECHINFO], afhi->techinfo? afhi->techinfo : "",
                status_item_list[SI_ARTIST], afhi->tags.artist? afhi->tags.artist : "",
                status_item_list[SI_TITLE], afhi->tags.title? afhi->tags.title : "",
@@ -397,6 +399,37 @@ unsigned afh_get_afhi_txt(int audio_format_num, struct afh_info *afhi, char **re
        );
 }
 
+/**
+ * Determine the maximal chunk size by investigating the chunk table.
+ *
+ * \param afhi Value/result.
+ *
+ * This function iterates over the chunk table and sets ->max_chunk_size
+ * accordingly. The function exists only for backward compatibility since as of
+ * version 0.6.0, para_server stores the maximal chunk size in its database.
+ * This function is only called if the database value is zero, indicating that
+ * the file was added by an older server version.
+ */
+void set_max_chunk_size(struct afh_info *afhi)
+{
+       uint32_t n, max = 0, old = 0;
+
+       for (n = 0; n <= afhi->chunks_total; n++) {
+               uint32_t val = afhi->chunk_table[n];
+               /*
+                * If the first chunk is the header, do not consider it for the
+                * calculation of the largest chunk size.
+                */
+               if (n == 0 || (n == 1 && afhi->header_len > 0)) {
+                       old = val;
+                       continue;
+               }
+               max = PARA_MAX(max, val - old);
+               old = val;
+       }
+       afhi->max_chunk_size = max;
+}
+
 /**
  * Create a copy of the given file with altered meta tags.
  *
diff --git a/aft.c b/aft.c
index 1756ec04ab5582edd97ab1b73bd2d777657495ec..4e2e1f8dbe2af69df7f5927a11687a236975c5a3 100644 (file)
--- a/aft.c
+++ b/aft.c
@@ -335,8 +335,8 @@ enum afhi_offsets {
        CHUNKS_TOTAL_OFFSET = 20,
        /** The length of the audio file header (4 bytes). */
        HEADER_LEN_OFFSET = 24,
-       /** Was: The start of the audio file header (4 bytes). */
-       AFHI_UNUSED2_OFFSET = 28,
+       /** Size of the largest chunk in bytes. (4 bytes). */
+       AFHI_MAX_CHUNK_SIZE_OFFSET = 28,
        /** The seconds part of the chunk time (4 bytes). */
        CHUNK_TV_TV_SEC_OFFSET = 32,
        /** The microseconds part of the chunk time (4 bytes). */
@@ -376,7 +376,7 @@ static void save_afhi(struct afh_info *afhi, char *buf)
        write_u8(buf + AFHI_CHANNELS_OFFSET, afhi->channels);
        write_u32(buf + CHUNKS_TOTAL_OFFSET, afhi->chunks_total);
        write_u32(buf + HEADER_LEN_OFFSET, afhi->header_len);
-       write_u32(buf + AFHI_UNUSED2_OFFSET, 0);
+       write_u32(buf + AFHI_MAX_CHUNK_SIZE_OFFSET, afhi->max_chunk_size);
        write_u32(buf + CHUNK_TV_TV_SEC_OFFSET, afhi->chunk_tv.tv_sec);
        write_u32(buf + CHUNK_TV_TV_USEC_OFFSET, afhi->chunk_tv.tv_usec);
        p = buf + AFHI_INFO_STRING_OFFSET;
@@ -398,6 +398,7 @@ static void load_afhi(const char *buf, struct afh_info *afhi)
        afhi->channels = read_u8(buf + AFHI_CHANNELS_OFFSET);
        afhi->chunks_total = read_u32(buf + CHUNKS_TOTAL_OFFSET);
        afhi->header_len = read_u32(buf + HEADER_LEN_OFFSET);
+       afhi->max_chunk_size = read_u32(buf + AFHI_MAX_CHUNK_SIZE_OFFSET);
        afhi->chunk_tv.tv_sec = read_u32(buf + CHUNK_TV_TV_SEC_OFFSET);
        afhi->chunk_tv.tv_usec = read_u32(buf + CHUNK_TV_TV_USEC_OFFSET);
        afhi->techinfo = (char *)buf + AFHI_INFO_STRING_OFFSET;
@@ -415,26 +416,12 @@ static unsigned sizeof_chunk_table(struct afh_info *afhi)
        return 4 * (afhi->chunks_total + 1);
 }
 
-static uint32_t save_chunk_table(struct afh_info *afhi, char *buf)
+static void save_chunk_table(struct afh_info *afhi, char *buf)
 {
-       int i;
-       uint32_t max = 0, old = 0;
+       uint32_t n;
 
-       for (i = 0; i <= afhi->chunks_total; i++) {
-               uint32_t val = afhi->chunk_table[i];
-               write_u32(buf + 4 * i, val);
-               /*
-                * If the first chunk is the header, do not consider it for the
-                * calculation of the largest chunk size.
-                */
-               if (i == 0 || (i == 1 && afhi->header_len > 0)) {
-                       old = val;
-                       continue;
-               }
-               max = PARA_MAX(max, val - old);
-               old = val;
-       }
-       return max;
+       for (n = 0; n <= afhi->chunks_total; n++)
+               write_u32(buf + 4 * n, afhi->chunk_table[n]);
 }
 
 static void load_chunk_table(struct afh_info *afhi, const struct osl_object *ct)
@@ -638,7 +625,13 @@ static int save_afd(struct audio_file_data *afd)
                goto err;
        buf = shm_afd;
        buf += sizeof(*afd);
-       afd->max_chunk_size = save_chunk_table(&afd->afhi, buf);
+       save_chunk_table(&afd->afhi, buf);
+       if (afd->afhi.max_chunk_size == 0) { /* v0.5.x on-disk afhi */
+               set_max_chunk_size(&afd->afhi);
+               PARA_NOTICE_LOG("max chunk size unset, re-add required\n");
+       } else
+               PARA_INFO_LOG("using max chunk size from afhi\n");
+       afd->max_chunk_size = afd->afhi.max_chunk_size;
        *(struct audio_file_data *)shm_afd = *afd;
        shm_detach(shm_afd);
        return shmid;
@@ -947,6 +940,8 @@ static int print_list_item(struct ls_data *d, struct ls_options *opts,
        WRITE_STATUS_ITEM(b, SI_CHUNK_TIME, "%lu\n", tv2ms(&afhi->chunk_tv));
        WRITE_STATUS_ITEM(b, SI_NUM_CHUNKS, "%" PRIu32 "\n",
                afhi->chunks_total);
+       WRITE_STATUS_ITEM(b, SI_MAX_CHUNK_SIZE, "%" PRIu32 "\n",
+               afhi->max_chunk_size);
        WRITE_STATUS_ITEM(b, SI_TECHINFO, "%s\n", afhi->techinfo);
        WRITE_STATUS_ITEM(b, SI_ARTIST, "%s\n", afhi->tags.artist);
        WRITE_STATUS_ITEM(b, SI_TITLE, "%s\n", afhi->tags.title);
index 0b00cc2af9f006d492975a54210ce26f4e5aa56e..fe6d70c496bb2c2ce6565ab287c724dd3fc41f32 100644 (file)
@@ -1022,7 +1022,7 @@ attributes_txt decoder_flags audiod_status play_time attributes_bitmap
 offset seconds_total stream_start current_time audiod_uptime image_id
 lyrics_id duration directory lyrics_name image_name path hash channels
 last_played num_chunks chunk_time amplification artist title year album
-comment"
+comment max_chunk_size"
 
 result=
 for i in $status_items; do
index 385d4f0c3a0235b9be24cdc83666308c30b959b8..e2d5380240240ddfaf3ce2b989ab0847f2e6e4fb 100644 (file)
@@ -391,6 +391,7 @@ static int flac_afh_read_chunks(struct private_flac_afh_data *pfad)
                        break;
        }
        afhi->chunks_total = c;
+       set_max_chunk_size(afhi);
        ret = 1;
 free_decoder:
        FLAC__stream_decoder_finish(decoder);
index 2115f71c77ce745b356b917058792d0c64db42ef..e5d0ff138fcfc5efed849679ca430bff87726074 100644 (file)
--- a/mp3_afh.c
+++ b/mp3_afh.c
@@ -657,6 +657,7 @@ static int mp3_read_info(unsigned char *map, size_t numbytes, int fd,
        tv_divide(afhi->chunks_total, &total_time, &afhi->chunk_tv);
        PARA_DEBUG_LOG("%" PRIu32 "chunks, each %lums\n", afhi->chunks_total,
                tv2ms(&afhi->chunk_tv));
+       set_max_chunk_size(afhi);
        ret = mp3_get_id3(map, numbytes, fd, &afhi->tags);
        afhi->techinfo = make_message("%cbr, %s, %s tags", vbr? 'v' : 'c',
                header_mode(&header), tag_versions[ret]);
index 6e5a89347e383340f943e591254f64f05cc6f358..734fd58680b1f944f6adf51c76aebb19d1b5b5c7 100644 (file)
@@ -181,6 +181,7 @@ int ogg_get_file_info(char *map, size_t numbytes, struct afh_info *afhi,
                }
        }
        afhi->chunks_total = j;
+       set_max_chunk_size(afhi);
        set_chunk_tv(frames_per_chunk, afhi->frequency, &afhi->chunk_tv);
        ret = 0;
 out:
index 4c9d87e047af8d1d5873096db54ab4a9d17ab966..b405989636791e9a37adcd4ea4f5ae4719f478ae 100644 (file)
--- a/wma_afh.c
+++ b/wma_afh.c
@@ -229,6 +229,7 @@ static int wma_make_chunk_table(char *buf, size_t buf_size, uint32_t packet_size
                }
        }
        afhi->chunks_total = j;
+       set_max_chunk_size(afhi);
        set_chunk_tv(frames_per_chunk, afhi->frequency, &afhi->chunk_tv);
        return 1;
 fail: