You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
137 lines
5.0 KiB
137 lines
5.0 KiB
--- a/libavformat/hls.c
|
|
+++ b/libavformat/hls.c
|
|
@@ -204,8 +204,94 @@
|
|
char *http_proxy; ///< holds the address of the HTTP proxy server
|
|
AVDictionary *avio_opts;
|
|
int strict_std_compliance;
|
|
+ char *key_uri_replace_old;
|
|
+ char *key_uri_replace_new;
|
|
} HLSContext;
|
|
|
|
+/* http://creativeandcritical.net/str-replace-c */
|
|
+static char *repl_str(const char *str, const char *from, const char *to)
|
|
+{
|
|
+ /* Adjust each of the below values to suit your needs. */
|
|
+
|
|
+ /* Increment positions cache size initially by this number. */
|
|
+ size_t cache_sz_inc = 16;
|
|
+ /* Thereafter, each time capacity needs to be increased,
|
|
+ * multiply the increment by this factor. */
|
|
+ const size_t cache_sz_inc_factor = 3;
|
|
+ /* But never increment capacity by more than this number. */
|
|
+ const size_t cache_sz_inc_max = 1048576;
|
|
+
|
|
+ char *pret, *ret = NULL;
|
|
+ const char *pstr2, *pstr = str;
|
|
+ size_t i, count = 0;
|
|
+#if (__STDC_VERSION__ >= 199901L)
|
|
+ uintptr_t *pos_cache_tmp, *pos_cache = NULL;
|
|
+#else
|
|
+ ptrdiff_t *pos_cache_tmp, *pos_cache = NULL;
|
|
+#endif
|
|
+ size_t cache_sz = 0;
|
|
+ size_t cpylen, orglen, retlen, tolen, fromlen = strlen(from);
|
|
+
|
|
+ /* Find all matches and cache their positions. */
|
|
+ while ((pstr2 = strstr(pstr, from)) != NULL) {
|
|
+ count++;
|
|
+
|
|
+ /* Increase the cache size when necessary. */
|
|
+ if (cache_sz < count) {
|
|
+ cache_sz += cache_sz_inc;
|
|
+ pos_cache_tmp = realloc(pos_cache, sizeof(*pos_cache) * cache_sz);
|
|
+ if (pos_cache_tmp == NULL) {
|
|
+ goto end_repl_str;
|
|
+ } else pos_cache = pos_cache_tmp;
|
|
+ cache_sz_inc *= cache_sz_inc_factor;
|
|
+ if (cache_sz_inc > cache_sz_inc_max) {
|
|
+ cache_sz_inc = cache_sz_inc_max;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ pos_cache[count-1] = pstr2 - str;
|
|
+ pstr = pstr2 + fromlen;
|
|
+ }
|
|
+
|
|
+ orglen = pstr - str + strlen(pstr);
|
|
+
|
|
+ /* Allocate memory for the post-replacement string. */
|
|
+ if (count > 0) {
|
|
+ tolen = strlen(to);
|
|
+ retlen = orglen + (tolen - fromlen) * count;
|
|
+ } else retlen = orglen;
|
|
+ ret = malloc(retlen + 1);
|
|
+ if (ret == NULL) {
|
|
+ goto end_repl_str;
|
|
+ }
|
|
+
|
|
+ if (count == 0) {
|
|
+ /* If no matches, then just duplicate the string. */
|
|
+ strcpy(ret, str);
|
|
+ } else {
|
|
+ /* Otherwise, duplicate the string whilst performing
|
|
+ * the replacements using the position cache. */
|
|
+ pret = ret;
|
|
+ memcpy(pret, str, pos_cache[0]);
|
|
+ pret += pos_cache[0];
|
|
+ for (i = 0; i < count; i++) {
|
|
+ memcpy(pret, to, tolen);
|
|
+ pret += tolen;
|
|
+ pstr = str + pos_cache[i] + fromlen;
|
|
+ cpylen = (i == count-1 ? orglen : pos_cache[i+1]) - pos_cache[i] - fromlen;
|
|
+ memcpy(pret, pstr, cpylen);
|
|
+ pret += cpylen;
|
|
+ }
|
|
+ ret[retlen] = '\0';
|
|
+ }
|
|
+
|
|
+end_repl_str:
|
|
+ /* Free the cache and return the post-replacement string,
|
|
+ * which will be NULL in the event of an error. */
|
|
+ free(pos_cache);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
static int read_chomp_line(AVIOContext *s, char *buf, int maxlen)
|
|
{
|
|
int len = ff_get_line(s, buf, maxlen);
|
|
@@ -1106,8 +1192,18 @@
|
|
AVDictionary *opts2 = NULL;
|
|
char iv[33], key[33], url[MAX_URL_SIZE];
|
|
if (strcmp(seg->key, pls->key_url)) {
|
|
+ char *key_url = NULL;
|
|
AVIOContext *pb;
|
|
- if (open_url(pls->parent, &pb, seg->key, c->avio_opts, opts, NULL) == 0) {
|
|
+
|
|
+ if (NULL != c->key_uri_replace_old && \
|
|
+ NULL != c-> key_uri_replace_new && \
|
|
+ '\0' != c->key_uri_replace_old[0]) {
|
|
+ key_url = repl_str(seg->key, c->key_uri_replace_old, c->key_uri_replace_new);
|
|
+ } else {
|
|
+ key_url = seg->key;
|
|
+ }
|
|
+
|
|
+ if (open_url(pls->parent, &pb, key_url, c->avio_opts, opts, NULL) == 0) {
|
|
ret = avio_read(pb, pls->key, sizeof(pls->key));
|
|
if (ret != sizeof(pls->key)) {
|
|
av_log(NULL, AV_LOG_ERROR, "Unable to read key file %s\n",
|
|
@@ -1119,6 +1215,10 @@
|
|
seg->key);
|
|
}
|
|
av_strlcpy(pls->key_url, seg->key, sizeof(pls->key_url));
|
|
+
|
|
+ if (key_url != seg->key) {
|
|
+ free(key_url);
|
|
+ }
|
|
}
|
|
ff_data_to_hex(iv, seg->iv, sizeof(seg->iv), 0);
|
|
ff_data_to_hex(key, pls->key, sizeof(pls->key), 0);
|
|
@@ -2128,6 +2228,8 @@
|
|
static const AVOption hls_options[] = {
|
|
{"live_start_index", "segment index to start live streams at (negative values are from the end)",
|
|
OFFSET(live_start_index), AV_OPT_TYPE_INT, {.i64 = -3}, INT_MIN, INT_MAX, FLAGS},
|
|
+ { "key_uri_old", "allow to replace part of AES key uri - old", OFFSET(key_uri_replace_old), AV_OPT_TYPE_STRING, { .str = "" }, 0, 0, FLAGS },
|
|
+ { "key_uri_new", "allow to replace part of AES key uri - new", OFFSET(key_uri_replace_new), AV_OPT_TYPE_STRING, { .str = "" }, 0, 0, FLAGS },
|
|
{NULL}
|
|
};
|
|
|
|
|