直播电视HLS协议分析及实现3---URL相对地址拼接

来源:互联网 发布:彩票双色球数据分析 编辑:程序博客网 时间:2024/05/16 20:53

    上一篇文章中获取segment地址列表的时候,出现了url相对地址,那么是如何转化为绝对url地址的呢?下面先来了解一些概念:

    URL
可以看做是URI的一个子集,上面的意思放在URL的范畴上可以做如下解释:

    1.就是如果想用相对路径来表示URL,则该URL与其父URL应该是同一种方法(例如:都是http,或都是ftp),否则需要用绝对路径来表示。

 

    2.如果相对路径表示的URL是以反斜杠开头的,[这段的英文有点绕,看的不是太清楚]则取其父URL第一个相同数量反斜杠位置的左侧部分[连续多个反斜杠?貌似http里面很少看到],加上相对路径表示URL,组成完整的URL

    例如:页面中的有一个URL /info/test.html ,它的父链是http://www.example.com/index.html,则这个相对URL的完整链接是:http://www.example.com/info/test.html

 

    3.如果相对路径表示的URL不是以反斜杠开头,则移除该URL父链的最后一个部分,拼接上该相对路径表示的URL,组成完整的URL

    例如:页面中有一个URL test.html ,父链是http://www.example.com/info/index.html,则完整链接是http://www.example.com/info/test.html

    另外如果URL ../test.html,父链是http://www.example.com/info/index.html,则完整链接是http://www.example.com/test.html。这个和UNIX文件系统是的表示是一样的。

    好了除此之外,还需要注意另外一种情况:

    如果html头部 <base>标记,例如:<base href="http://www.example.com/info/" />则该页面上的基准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[] = "http://www.example.com/index.html";    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[] = "http://www.example.com/info/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[] = "http://www.example.com/info/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的情况复杂一点,但是原理是一致的。

    本文参考了:
    作者:yihucha166      网址:http://blog.csdn.net/yihucha166/article/details/4388735


原创粉丝点击