]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/utils.c
refactor url_split(), preparing for IPv6 support
[ffmpeg] / libavformat / utils.c
index 1e04bd217c8421360328542389f4ebd2970f8da4..8cd34c8e4830a38a198332d8342fe786cddebaca 100644 (file)
@@ -2067,6 +2067,11 @@ void av_close_input_file(AVFormatContext *s)
         av_free(st->codec);
         av_free(st);
     }
+    for(i=s->nb_programs-1; i>=0; i--) {
+        av_freep(&s->programs[i]->provider_name);
+        av_freep(&s->programs[i]->name);
+        av_freep(&s->programs[i]);
+    }
     flush_packet_queue(s);
     must_open_file = 1;
     if (s->iformat->flags & AVFMT_NOFILE) {
@@ -2113,6 +2118,43 @@ AVStream *av_new_stream(AVFormatContext *s, int id)
     return st;
 }
 
+AVProgram *av_new_program(AVFormatContext *ac, int id)
+{
+    AVProgram *program=NULL;
+    int i;
+
+#ifdef DEBUG_SI
+    av_log(ac, AV_LOG_DEBUG, "new_program: id=0x%04x\n", id);
+#endif
+
+    for(i=0; i<ac->nb_programs; i++)
+        if(ac->programs[i]->id == id)
+            program = ac->programs[i];
+
+    if(!program){
+        program = av_mallocz(sizeof(AVProgram));
+        if (!program)
+            return NULL;
+        dynarray_add(&ac->programs, &ac->nb_programs, program);
+        program->discard = AVDISCARD_NONE;
+    }
+    program->id = id;
+
+    return program;
+}
+
+void av_set_program_name(AVProgram *program, char *provider_name, char *name)
+{
+    assert(!provider_name == !name);
+    if(name){
+        av_free(program->provider_name);
+        av_free(program->         name);
+        program->provider_name = av_strdup(provider_name);
+        program->         name = av_strdup(         name);
+    }
+}
+
+
 /************************************************************/
 /* output media file */
 
@@ -2579,6 +2621,7 @@ int64_t parse_date(const char *datestr, int duration)
     p = datestr;
     q = NULL;
     if (!duration) {
+        /* parse the year-month-day part */
         for (i = 0; i < sizeof(date_fmt) / sizeof(date_fmt[0]); i++) {
             q = small_strptime(p, date_fmt[i], &dt);
             if (q) {
@@ -2586,6 +2629,8 @@ int64_t parse_date(const char *datestr, int duration)
             }
         }
 
+        /* if the year-month-day part is missing, then take the
+         * current year-month-day time */
         if (!q) {
             if (is_utc) {
                 dt = *gmtime(&now);
@@ -2600,6 +2645,7 @@ int64_t parse_date(const char *datestr, int duration)
         if (*p == 'T' || *p == 't' || *p == ' ')
             p++;
 
+        /* parse the hour-minute-second part */
         for (i = 0; i < sizeof(time_fmt) / sizeof(time_fmt[0]); i++) {
             q = small_strptime(p, time_fmt[i], &dt);
             if (q) {
@@ -2607,13 +2653,19 @@ int64_t parse_date(const char *datestr, int duration)
             }
         }
     } else {
+        /* parse datestr as a duration */
         if (p[0] == '-') {
             negative = 1;
             ++p;
         }
+        /* parse datestr as HH:MM:SS */
         q = small_strptime(p, time_fmt[0], &dt);
         if (!q) {
+            /* parse datestr as S+ */
             dt.tm_sec = strtol(p, (char **)&q, 10);
+            if (q == p)
+                /* the parsing didn't succeed */
+                return INT64_MIN;
             dt.tm_min = 0;
             dt.tm_hour = 0;
         }
@@ -2621,10 +2673,7 @@ int64_t parse_date(const char *datestr, int duration)
 
     /* Now we have all the fields that we can get */
     if (!q) {
-        if (duration)
-            return 0;
-        else
-            return now * INT64_C(1000000);
+        return INT64_MIN;
     }
 
     if (duration) {
@@ -2640,6 +2689,7 @@ int64_t parse_date(const char *datestr, int duration)
 
     t *= 1000000;
 
+    /* parse the .m... part */
     if (*q == '.') {
         int val, n;
         q++;
@@ -2828,68 +2878,49 @@ void url_split(char *proto, int proto_size,
                char *path, int path_size,
                const char *url)
 {
-    const char *p;
-    char *q;
-    int port;
+    const char *p, *ls, *at, *col;
 
-    port = -1;
+    if (port_ptr)               *port_ptr = -1;
+    if (proto_size > 0)         proto[0] = 0;
+    if (authorization_size > 0) authorization[0] = 0;
+    if (hostname_size > 0)      hostname[0] = 0;
+    if (path_size > 0)          path[0] = 0;
 
-    p = url;
-    q = proto;
-    while (*p != ':' && *p != '\0') {
-        if ((q - proto) < proto_size - 1)
-            *q++ = *p;
-        p++;
-    }
-    if (proto_size > 0)
-        *q = '\0';
-    if (authorization_size > 0)
-        authorization[0] = '\0';
-    if (*p == '\0') {
-        if (proto_size > 0)
-            proto[0] = '\0';
-        if (hostname_size > 0)
-            hostname[0] = '\0';
-        p = url;
+    /* parse protocol */
+    if ((p = strchr(url, ':'))) {
+        av_strlcpy(proto, url, FFMIN(proto_size, p + 1 - url));
+        p++; /* skip ':' */
+        if (*p == '/') p++;
+        if (*p == '/') p++;
     } else {
-        char *at,*slash; // PETR: position of '@' character and '/' character
+        /* no protocol means plain filename */
+        av_strlcpy(path, url, path_size);
+        return;
+    }
 
-        p++;
-        if (*p == '/')
-            p++;
-        if (*p == '/')
-            p++;
-        at = strchr(p,'@'); // PETR: get the position of '@'
-        slash = strchr(p,'/');  // PETR: get position of '/' - end of hostname
-        if (at && slash && at > slash) at = NULL; // PETR: not interested in '@' behind '/'
-
-        q = at ? authorization : hostname;  // PETR: if '@' exists starting with auth.
-
-         while ((at || *p != ':') && *p != '/' && *p != '?' && *p != '\0') { // PETR:
-            if (*p == '@') {    // PETR: passed '@'
-              if (authorization_size > 0)
-                  *q = '\0';
-              q = hostname;
-              at = NULL;
-            } else if (!at) {   // PETR: hostname
-              if ((q - hostname) < hostname_size - 1)
-                  *q++ = *p;
-            } else {
-              if ((q - authorization) < authorization_size - 1)
-                *q++ = *p;
-            }
-            p++;
+    /* separate path from hostname */
+    if ((ls = strchr(p, '/')))
+        av_strlcpy(path, ls, path_size);
+    else
+        ls = &p[strlen(p)]; // XXX
+
+    /* the rest is hostname, use that to parse auth/port */
+    if (ls != p) {
+        /* authorization (user[:pass]@hostname) */
+        if ((at = strchr(p, '@')) && at < ls) {
+            av_strlcpy(authorization, p,
+                       FFMIN(authorization_size, at + 1 - p));
+            p = at + 1; /* skip '@' */
         }
-        if (hostname_size > 0)
-            *q = '\0';
-        if (*p == ':') {
-            p++;
-            port = strtoul(p, (char **)&p, 10);
+
+        /* port */
+        if ((col = strchr(p, ':')) && col < ls) {
+            ls = col;
+            if (port_ptr) *port_ptr = atoi(col + 1); /* skip ':' */
         }
+
+        av_strlcpy(hostname, p, FFMIN(1 + ls - p, hostname_size));
     }
-    if (port_ptr)
-        *port_ptr = port;
-    av_strlcpy(path, p, path_size);
 }
 
 void av_set_pts_info(AVStream *s, int pts_wrap_bits,