上一篇文章中获取segment地址列表的时候,出现了url相对地址,那么是如何转化为绝对url地址的呢?下面先来了解一些概念:
URL可以看做是URI的一个子集,上面的意思放在URL的范畴上可以做如下解释:
1. 就是如果想用相对路径来表示URL,则该URL与其父URL应该是同一种方法(例如:都是http,或都是ftp),否则需要用绝对路径来表示。
2. 如果相对路径表示的URL是以反斜杠开头的,[这段的英文有点绕,看的不是太清楚]则取其父URL第一个相同数量反斜杠位置的左侧部分[连续多个反斜杠?貌似http里面很少看到],加上相对路径表示URL,组成完整的URL。
例如:页面中的有一个URL是 /info/test.html ,它的父链是 ,则这个相对URL的完整链接是:。
3. 如果相对路径表示的URL不是以反斜杠开头,则移除该URL父链的最后一个部分,拼接上该相对路径表示的URL,组成完整的URL。
例如:页面中有一个URL是 test.html ,父链是,则完整链接是。
另外如果URL是 ../test.html,父链是,则完整链接是。这个和UNIX文件系统是的表示是一样的。
好了 除此之外,还需要注意另外一种情况:
如果html头部 有 标记,例如:则该页面上的基准URL都以此为准,不考虑其父链的情况。
说了这么多,如何用c代码来实现呢?这里列出ffmpeg中的相关函数,整理如下:
-
void ff_make_absolute_url(char *buf, int size, const char *base,
-
const char *rel)
-
{
-
char *sep, *path_query;
-
/* Absolute path, relative to the current server */
-
if (base && strstr(base, "://") && rel[0] == '/') {
-
if (base != buf)
-
av_strlcpy(buf, base, size);
-
sep = strstr(buf, "://");
-
if (sep) {
-
/* Take scheme from base url */
-
if (rel[1] == '/')
-
sep[1] = '\0';
-
else {
-
/* Take scheme and host from base url */
-
sep += 3;
-
sep = strchr(sep, '/');
-
if (sep)
-
*sep = '\0';
-
}
-
}
-
av_strlcat(buf, rel, size);
-
return;
-
}
-
/* If rel actually is an absolute url, just copy it */
-
if (!base || strstr(rel, "://") || rel[0] == '/') {
-
av_strlcpy(buf, rel, size);
-
return;
-
}
-
if (base != buf)
-
av_strlcpy(buf, base, size);
-
-
/* Strip off any query string from base */
-
path_query = strchr(buf, '?');
-
if (path_query != NULL)
-
*path_query = '\0';
-
-
/* Is relative path just a new query part? */
-
if (rel[0] == '?') {
-
av_strlcat(buf, rel, size);
-
return;
-
}
-
-
/* Remove the file name from the base url */
-
sep = strrchr(buf, '/');
-
if (sep)
-
sep[1] = '\0';
-
else
-
buf[0] = '\0';
-
while (av_strstart(rel, "../", NULL) && sep) {
-
/* Remove the path delimiter at the end */
-
sep[0] = '\0';
-
sep = strrchr(buf, '/');
-
/* If the next directory name to pop off is "..", break here */
-
if (!strcmp(sep ? &sep[1] : buf, "..")) {
-
/* Readd the slash we just removed */
-
av_strlcat(buf, "/", size);
-
break;
-
}
-
/* Cut off the directory name */
-
if (sep)
-
sep[1] = '\0';
-
else
-
buf[0] = '\0';
-
rel += 3;
-
}
-
av_strlcat(buf, rel, size);
-
}
其中有一些字符串的拼接函数,是ffmpeg封装的标注string的函数,如果想运行这段代码,可以参照下面的例子,分别对应上面提到的三种情况:
-
/**
-
* make absolute url from ffmpeg project
-
*
-
*/
-
#include <stdio.h>
-
#include <stdint.h> /* for intptr_t */
-
#include <string.h> /* for string */
-
-
int av_strstart(const char *str, const char *pfx, const char **ptr)
-
{
-
while (*pfx && *pfx == *str) {
-
pfx++;
-
str++;
-
}
-
if (!*pfx && ptr)
-
*ptr = str;
-
return !*pfx;
-
}
-
-
size_t av_strlcpy(char *dst, const char *src, size_t size)
-
{
-
size_t len = 0;
-
while (++len < size && *src)
-
*dst++ = *src++;
-
if (len <= size)
-
*dst = 0;
-
return len + strlen(src) - 1;
-
}
-
-
size_t av_strlcat(char *dst, const char *src, size_t size)
-
{
-
size_t len = strlen(dst);
-
if (size <= len + 1)
-
return len + strlen(src);
-
return len + av_strlcpy(dst + len, src, size - len);
-
}
-
-
/**
-
* make absolute url
-
*/
-
void ff_make_absolute_url(char *buf, int size, const char *base,
-
const char *rel)
-
{
-
char *sep, *path_query;
-
/* Absolute path, relative to the current server */
-
if (base && strstr(base, "://") && rel[0] == '/') {
-
if (base != buf)
-
av_strlcpy(buf, base, size);
-
sep = strstr(buf, "://");
-
if (sep) {
-
/* Take scheme from base url */
-
if (rel[1] == '/')
-
sep[1] = '\0';
-
else {
-
/* Take scheme and host from base url */
-
sep += 3;
-
sep = strchr(sep, '/');
-
if (sep)
-
*sep = '\0';
-
}
-
}
-
av_strlcat(buf, rel, size);
-
return;
-
}
-
/* If rel actually is an absolute url, just copy it */
-
if (!base || strstr(rel, "://") || rel[0] == '/') {
-
av_strlcpy(buf, rel, size);
-
return;
-
}
-
if (base != buf)
-
av_strlcpy(buf, base, size);
-
-
/* Strip off any query string from base */
-
path_query = strchr(buf, '?');
-
if (path_query != NULL)
-
*path_query = '\0';
-
-
/* Is relative path just a new query part? */
-
if (rel[0] == '?') {
-
av_strlcat(buf, rel, size);
-
return;
-
}
-
-
/* Remove the file name from the base url */
-
sep = strrchr(buf, '/');
-
if (sep)
-
sep[1] = '\0';
-
else
-
buf[0] = '\0';
-
while (av_strstart(rel, "../", NULL) && sep) {
-
/* Remove the path delimiter at the end */
-
sep[0] = '\0';
-
sep = strrchr(buf, '/');
-
/* If the next directory name to pop off is "..", break here */
-
if (!strcmp(sep ? &sep[1] : buf, "..")) {
-
/* Readd the slash we just removed */
-
av_strlcat(buf, "/", size);
-
break;
-
}
-
/* Cut off the directory name */
-
if (sep)
-
sep[1] = '\0';
-
else
-
buf[0] = '\0';
-
rel += 3;
-
}
-
av_strlcat(buf, rel, size);
-
}
-
-
/**
-
* main test
-
*/
-
void main(void)
-
{
-
char dst1[1024];
-
char dst2[1024];
-
char dst3[1024];
-
-
char base1[] = "";
-
char ref1[] = "/info/test.html";
-
ff_make_absolute_url(dst1, sizeof(dst1), base1, ref1);
-
printf("---------------------------------------------\n");
-
printf("%s\n", base1);
-
printf("%s\n", ref1);
-
printf("%s\n", dst1);
-
printf("---------------------------------------------\n");
-
-
char base2[] = "index.html";
-
char ref2[] = "test.html";
-
ff_make_absolute_url(dst2, sizeof(dst2), base2, ref2);
-
printf("%s\n", base2);
-
printf("%s\n", ref2);
-
printf("%s\n", dst2);
-
printf("---------------------------------------------\n");
-
-
char base3[] = "index.html";
-
char ref3[] = "../test.html";
-
ff_make_absolute_url(dst3, sizeof(dst3), base3, ref3);
-
printf("%s\n", base3);
-
printf("%s\n", ref3);
-
printf("%s\n", dst3);
-
printf("---------------------------------------------\n");
-
-
return;
-
}
运行结果是
-
---------------------------------------------
-
http://www.example.com/index.html
-
/info/test.html
-
http://www.example.com/info/test.html
-
---------------------------------------------
-
http://www.example.com/info/index.html
-
test.html
-
http://www.example.com/info/test.html
-
---------------------------------------------
-
http://www.example.com/info/index.html
-
../test.html
-
http://www.example.com/test.html
-
---------------------------------------------
与上文提到的结果是一致的,当然实际的HLS URL的情况复杂一点,但是原理是一致的。
本文参考了:
作者: 网址:http://blog.csdn.net/yihucha166/article/details/4388735
阅读(3498) | 评论(1) | 转发(0) |