- para_client now supports RFC4716 private keys as generated with
ssh-keygen -m RFC4716. In fact, this key format has been made the
default, and the former PEM keys will be depreciated at some point.
+- The ogg audio format handlers learned to detect holes and now report
+ the correct duration also if ogg pages are missing in the file. This
+ affects ogg/vorbis ogg/speex and ogg/opus.
--------------------------------------
0.6.2 (2018-06-30) "elastic diversity"
ogg_sync_state oss;
ogg_page op;
char *buf;
- int ret, i, j, frames_per_chunk, ct_size;
- long long unsigned num_frames = 0;
+ int ret, i, j, frames_per_chunk, ct_size, prev_pageno = 0;
+ long long unsigned granule_skip = 0, num_frames = 0;
+ int64_t granule = 0, prev_granule = 0;
ogg_sync_init(&oss);
ret = -E_OGG_SYNC;
oss.returned = 0;
oss.fill = numbytes;
/* count ogg pages and get duration of the file */
- for (i = 0; ogg_sync_pageseek(&oss, &op) > 0; i++)
- num_frames = ogg_page_granulepos(&op);
+ for (i = 0; ogg_sync_pageseek(&oss, &op) > 0; i++) {
+ int this_pageno = ogg_page_pageno(&op);
+ int64_t this_granule = ogg_page_granulepos(&op);
+ if (this_granule >= 0)
+ granule = this_granule;
+ if (i > 0 && this_pageno != prev_pageno + 1) /* hole */
+ granule_skip += granule - prev_granule;
+ prev_pageno = this_pageno;
+ prev_granule = granule;
+ }
+ num_frames = granule - granule_skip;
PARA_INFO_LOG("%d pages, %llu frames\n", i, num_frames);
ret = -E_OGG_EMPTY;
if (i == 0)
oss.returned = afhi->header_len;
oss.fill = numbytes;
for (j = 1; ogg_sync_pageseek(&oss, &op) > 0; /* nothing */) {
- int granule = ogg_page_granulepos(&op);
+ granule = ogg_page_granulepos(&op);
while (granule >= (j + 1) * frames_per_chunk) {
j++;