char *psz_key_path; /* url key path */
uint8_t aes_key[16]; /* AES-128 */
bool b_key_loaded;
+ uint8_t psz_AES_IV[AES_BLOCK_SIZE]; /* IV used when decypher the block */
+ bool b_iv_loaded;
vlc_mutex_t lock;
block_t *data; /* data */
bool b_cache; /* allow caching */
char *psz_current_key_path; /* URL path of the encrypted key */
- uint8_t psz_AES_IV[AES_BLOCK_SIZE]; /* IV used when decypher the block */
- bool b_iv_loaded;
+ uint8_t psz_current_AES_IV[AES_BLOCK_SIZE]; /* IV used when decypher the block */
+ bool b_current_iv_loaded;
} hls_stream_t;
struct stream_sys_t
dst->b_cache = src->b_cache;
dst->psz_current_key_path = src->psz_current_key_path ?
strdup( src->psz_current_key_path ) : NULL;
+ memcpy(dst->psz_current_AES_IV, src->psz_current_AES_IV, AES_BLOCK_SIZE);
+ dst->b_current_iv_loaded = src->b_current_iv_loaded;
dst->url = strdup(src->url);
if (dst->url == NULL)
{
segment->psz_key_path = NULL;
if (hls->psz_current_key_path)
segment->psz_key_path = strdup(hls->psz_current_key_path);
+ segment->b_iv_loaded = hls->b_current_iv_loaded;
+ memcpy(segment->psz_AES_IV, hls->psz_current_AES_IV, AES_BLOCK_SIZE);
return segment;
}
if (len <= 16) {
iv_hi = 0;
iv_lo = strtoull(string_hexa, &end, 16);
- if (end)
+ if (*end)
return VLC_EGENERIC;
} else {
- iv_lo = strtoull(&string_hexa[len-16], NULL, 16);
- if (end)
+ iv_lo = strtoull(&string_hexa[len-16], &end, 16);
+ if (*end)
return VLC_EGENERIC;
string_hexa[len-16] = '\0';
- iv_hi = strtoull(string_hexa, NULL, 16);
- if (end)
+ iv_hi = strtoull(string_hexa, &end, 16);
+ if (*end)
return VLC_EGENERIC;
}
static char *relative_URI(const char *psz_url, const char *psz_path)
{
char *ret = NULL;
+ const char *fmt;
assert(psz_url != NULL && psz_path != NULL);
if (unlikely(slash == NULL))
goto end;
*slash = '\0';
+ fmt = "%s%s";
} else {
int levels = 0;
while(len >= 3 && !strncmp(psz_path, "../", 3)) {
goto end;
*slash = '\0';
} while (levels--);
+ fmt = "%s/%s";
}
- if (asprintf(&ret, "%s/%s", new_url, psz_path) < 0)
+ if (asprintf(&ret, fmt, new_url, psz_path) < 0)
ret = NULL;
end:
* representation of the sequence number SHALL be placed in a 16-octet
* buffer and padded (on the left) with zeros.
*/
- hls->b_iv_loaded = false;
+ hls->b_current_iv_loaded = false;
}
else
{
* and MUST be prefixed with 0x or 0X.
*/
- if (string_to_IV(iv, hls->psz_AES_IV) == VLC_EGENERIC)
+ if (string_to_IV(iv, hls->psz_current_AES_IV) == VLC_EGENERIC)
{
msg_Err(s, "IV invalid");
err = VLC_EGENERIC;
}
else
- hls->b_iv_loaded = true;
+ hls->b_current_iv_loaded = true;
free(value);
}
}
return VLC_EGENERIC;
}
- if (hls->b_iv_loaded == false)
+ if (segment->b_iv_loaded == false)
{
- memset(hls->psz_AES_IV, 0, AES_BLOCK_SIZE);
- hls->psz_AES_IV[15] = segment->sequence & 0xff;
- hls->psz_AES_IV[14] = (segment->sequence >> 8)& 0xff;
- hls->psz_AES_IV[13] = (segment->sequence >> 16)& 0xff;
- hls->psz_AES_IV[12] = (segment->sequence >> 24)& 0xff;
+ memset(segment->psz_AES_IV, 0, AES_BLOCK_SIZE);
+ segment->psz_AES_IV[15] = segment->sequence & 0xff;
+ segment->psz_AES_IV[14] = (segment->sequence >> 8)& 0xff;
+ segment->psz_AES_IV[13] = (segment->sequence >> 16)& 0xff;
+ segment->psz_AES_IV[12] = (segment->sequence >> 24)& 0xff;
}
- i_gcrypt_err = gcry_cipher_setiv(aes_ctx, hls->psz_AES_IV,
- sizeof(hls->psz_AES_IV));
+ i_gcrypt_err = gcry_cipher_setiv(aes_ctx, segment->psz_AES_IV,
+ sizeof(segment->psz_AES_IV));
if (i_gcrypt_err)
{
/* determine next time to update playlist */
p_sys->playlist.last = now;
- p_sys->playlist.wakeup = now + ((mtime_t)(hls->max_segment_length * wait)
- * (mtime_t)1000000);
+ p_sys->playlist.wakeup = now;
+ /* If there is no new segments,use playlist duration as sleep period base */
+ if( likely( hls->max_segment_length > 0 ) )
+ p_sys->playlist.wakeup += (mtime_t)((hls->max_segment_length * wait) * CLOCK_FREQ);
+ else
+ p_sys->playlist.wakeup += (mtime_t)((hls->duration * wait) * CLOCK_FREQ);
}
mwait(p_sys->playlist.wakeup);
return VLC_EGENERIC;
segment->size = stream_Size(p_ts);
- assert(segment->size > 0);
- segment->data = block_Alloc(segment->size);
- if (segment->data == NULL)
- {
+ if (segment->size == 0) {
+ int chunk_size = 65536;
+ segment->data = block_Alloc(chunk_size);
+ if (!segment->data)
+ goto nomem;
+ do {
+ if (segment->data->i_buffer - segment->size < chunk_size) {
+ chunk_size *= 2;
+ block_t *p_block = block_Realloc(segment->data, 0, segment->data->i_buffer + chunk_size);
+ if (!p_block) {
+ block_Release(segment->data);
+ segment->data = NULL;
+ goto nomem;
+ }
+ segment->data = p_block;
+ }
+
+ ssize_t length = stream_Read(p_ts, segment->data->p_buffer + segment->size, chunk_size);
+ if (length <= 0) {
+ segment->data->i_buffer = segment->size;
+ break;
+ }
+ segment->size += length;
+ } while (vlc_object_alive(s));
+
stream_Delete(p_ts);
- return VLC_ENOMEM;
+ return VLC_SUCCESS;
}
+ segment->data = block_Alloc(segment->size);
+ if (segment->data == NULL)
+ goto nomem;
+
assert(segment->data->i_buffer == segment->size);
- ssize_t length = 0, curlen = 0;
- uint64_t size;
+ ssize_t curlen = 0;
do
{
/* NOTE: Beware the size reported for a segment by the HLS server may not
* be correct, when downloading the segment data. Therefore check the size
* and enlarge the segment data block if necessary.
*/
- size = stream_Size(p_ts);
+ uint64_t size = stream_Size(p_ts);
if (size > segment->size)
{
msg_Dbg(s, "size changed %"PRIu64, segment->size);
block_t *p_block = block_Realloc(segment->data, 0, size);
if (p_block == NULL)
{
- stream_Delete(p_ts);
block_Release(segment->data);
segment->data = NULL;
- return VLC_ENOMEM;
+ goto nomem;
}
segment->data = p_block;
segment->size = size;
assert(segment->data->i_buffer == segment->size);
p_block = NULL;
}
- length = stream_Read(p_ts, segment->data->p_buffer + curlen, segment->size - curlen);
+ ssize_t length = stream_Read(p_ts, segment->data->p_buffer + curlen, segment->size - curlen);
if (length <= 0)
break;
curlen += length;
stream_Delete(p_ts);
return VLC_SUCCESS;
+
+nomem:
+ stream_Delete(p_ts);
+ return VLC_ENOMEM;
}
/* Read M3U8 file */
hls_stream_t *hls = hls_Get(p_sys->hls_stream, current);
p_sys->playlist.last = mdate();
p_sys->playlist.wakeup = p_sys->playlist.last +
- ((mtime_t)hls->duration * UINT64_C(1000000));
+ ((mtime_t)hls->duration * CLOCK_FREQ );
if (vlc_clone(&p_sys->reload, hls_Reload, s, VLC_THREAD_PRIORITY_LOW))
{
mtime_t start = mdate();
// Wait for 10 seconds
- mtime_t timeout_limit = start + (10 * UINT64_C(1000000));
+ mtime_t timeout_limit = start + (10 * CLOCK_FREQ);
int res = vlc_cond_timedwait(&p_sys->read.wait, &p_sys->read.lock_wait, timeout_limit);