LCOV - code coverage report
Current view: top level - src/libavformat - concat.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 88 0.0 %
Date: 2017-05-26 21:11:57 Functions: 0 4 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Concat URL protocol
       3             :  * Copyright (c) 2006 Steve Lhomme
       4             :  * Copyright (c) 2007 Wolfram Gloger
       5             :  * Copyright (c) 2010 Michele OrrĂ¹
       6             :  *
       7             :  * This file is part of FFmpeg.
       8             :  *
       9             :  * FFmpeg is free software; you can redistribute it and/or
      10             :  * modify it under the terms of the GNU Lesser General Public
      11             :  * License as published by the Free Software Foundation; either
      12             :  * version 2.1 of the License, or (at your option) any later version.
      13             :  *
      14             :  * FFmpeg is distributed in the hope that it will be useful,
      15             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      17             :  * Lesser General Public License for more details.
      18             :  *
      19             :  * You should have received a copy of the GNU Lesser General Public
      20             :  * License along with FFmpeg; if not, write to the Free Software
      21             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      22             :  */
      23             : 
      24             : #include "libavutil/avstring.h"
      25             : #include "libavutil/mem.h"
      26             : 
      27             : #include "avformat.h"
      28             : #include "url.h"
      29             : 
      30             : #define AV_CAT_SEPARATOR "|"
      31             : 
      32             : struct concat_nodes {
      33             :     URLContext *uc;                ///< node's URLContext
      34             :     int64_t     size;              ///< url filesize
      35             : };
      36             : 
      37             : struct concat_data {
      38             :     struct concat_nodes *nodes;    ///< list of nodes to concat
      39             :     size_t               length;   ///< number of cat'ed nodes
      40             :     size_t               current;  ///< index of currently read node
      41             : };
      42             : 
      43           0 : static av_cold int concat_close(URLContext *h)
      44             : {
      45           0 :     int err = 0;
      46             :     size_t i;
      47           0 :     struct concat_data  *data  = h->priv_data;
      48           0 :     struct concat_nodes *nodes = data->nodes;
      49             : 
      50           0 :     for (i = 0; i != data->length; i++)
      51           0 :         err |= ffurl_close(nodes[i].uc);
      52             : 
      53           0 :     av_freep(&data->nodes);
      54             : 
      55           0 :     return err < 0 ? -1 : 0;
      56             : }
      57             : 
      58           0 : static av_cold int concat_open(URLContext *h, const char *uri, int flags)
      59             : {
      60           0 :     char *node_uri = NULL;
      61           0 :     int err = 0;
      62             :     int64_t size;
      63             :     size_t len, i;
      64             :     URLContext *uc;
      65           0 :     struct concat_data  *data = h->priv_data;
      66             :     struct concat_nodes *nodes;
      67             : 
      68           0 :     if (!av_strstart(uri, "concat:", &uri)) {
      69           0 :         av_log(h, AV_LOG_ERROR, "URL %s lacks prefix\n", uri);
      70           0 :         return AVERROR(EINVAL);
      71             :     }
      72             : 
      73           0 :     for (i = 0, len = 1; uri[i]; i++) {
      74           0 :         if (uri[i] == *AV_CAT_SEPARATOR) {
      75             :             /* integer overflow */
      76           0 :             if (++len == UINT_MAX / sizeof(*nodes)) {
      77           0 :                 av_freep(&h->priv_data);
      78           0 :                 return AVERROR(ENAMETOOLONG);
      79             :             }
      80             :         }
      81             :     }
      82             : 
      83           0 :     if (!(nodes = av_realloc(NULL, sizeof(*nodes) * len)))
      84           0 :         return AVERROR(ENOMEM);
      85             :     else
      86           0 :         data->nodes = nodes;
      87             : 
      88             :     /* handle input */
      89           0 :     if (!*uri)
      90           0 :         err = AVERROR(ENOENT);
      91           0 :     for (i = 0; *uri; i++) {
      92             :         /* parsing uri */
      93           0 :         len = strcspn(uri, AV_CAT_SEPARATOR);
      94           0 :         if ((err = av_reallocp(&node_uri, len + 1)) < 0)
      95           0 :             break;
      96           0 :         av_strlcpy(node_uri, uri, len + 1);
      97           0 :         uri += len + strspn(uri + len, AV_CAT_SEPARATOR);
      98             : 
      99             :         /* creating URLContext */
     100           0 :         err = ffurl_open_whitelist(&uc, node_uri, flags,
     101           0 :                                    &h->interrupt_callback, NULL, h->protocol_whitelist, h->protocol_blacklist, h);
     102           0 :         if (err < 0)
     103           0 :             break;
     104             : 
     105             :         /* creating size */
     106           0 :         if ((size = ffurl_size(uc)) < 0) {
     107           0 :             ffurl_close(uc);
     108           0 :             err = AVERROR(ENOSYS);
     109           0 :             break;
     110             :         }
     111             : 
     112             :         /* assembling */
     113           0 :         nodes[i].uc   = uc;
     114           0 :         nodes[i].size = size;
     115             :     }
     116           0 :     av_free(node_uri);
     117           0 :     data->length = i;
     118             : 
     119           0 :     if (err < 0)
     120           0 :         concat_close(h);
     121           0 :     else if (!(nodes = av_realloc(nodes, data->length * sizeof(*nodes)))) {
     122           0 :         concat_close(h);
     123           0 :         err = AVERROR(ENOMEM);
     124             :     } else
     125           0 :         data->nodes = nodes;
     126           0 :     return err;
     127             : }
     128             : 
     129           0 : static int concat_read(URLContext *h, unsigned char *buf, int size)
     130             : {
     131           0 :     int result, total = 0;
     132           0 :     struct concat_data  *data  = h->priv_data;
     133           0 :     struct concat_nodes *nodes = data->nodes;
     134           0 :     size_t i                   = data->current;
     135             : 
     136           0 :     while (size > 0) {
     137           0 :         result = ffurl_read(nodes[i].uc, buf, size);
     138           0 :         if (result < 0)
     139           0 :             return total ? total : result;
     140           0 :         if (!result) {
     141           0 :             if (i + 1 == data->length ||
     142           0 :                 ffurl_seek(nodes[++i].uc, 0, SEEK_SET) < 0)
     143             :                 break;
     144             :         }
     145           0 :         total += result;
     146           0 :         buf   += result;
     147           0 :         size  -= result;
     148             :     }
     149           0 :     data->current = i;
     150           0 :     return total;
     151             : }
     152             : 
     153           0 : static int64_t concat_seek(URLContext *h, int64_t pos, int whence)
     154             : {
     155             :     int64_t result;
     156           0 :     struct concat_data  *data  = h->priv_data;
     157           0 :     struct concat_nodes *nodes = data->nodes;
     158             :     size_t i;
     159             : 
     160           0 :     switch (whence) {
     161             :     case SEEK_END:
     162           0 :         for (i = data->length - 1; i && pos < -nodes[i].size; i--)
     163           0 :             pos += nodes[i].size;
     164           0 :         break;
     165             :     case SEEK_CUR:
     166             :         /* get the absolute position */
     167           0 :         for (i = 0; i != data->current; i++)
     168           0 :             pos += nodes[i].size;
     169           0 :         pos += ffurl_seek(nodes[i].uc, 0, SEEK_CUR);
     170           0 :         whence = SEEK_SET;
     171             :         /* fall through with the absolute position */
     172             :     case SEEK_SET:
     173           0 :         for (i = 0; i != data->length - 1 && pos >= nodes[i].size; i++)
     174           0 :             pos -= nodes[i].size;
     175           0 :         break;
     176             :     default:
     177           0 :         return AVERROR(EINVAL);
     178             :     }
     179             : 
     180           0 :     result = ffurl_seek(nodes[i].uc, pos, whence);
     181           0 :     if (result >= 0) {
     182           0 :         data->current = i;
     183           0 :         while (i)
     184           0 :             result += nodes[--i].size;
     185             :     }
     186           0 :     return result;
     187             : }
     188             : 
     189             : const URLProtocol ff_concat_protocol = {
     190             :     .name           = "concat",
     191             :     .url_open       = concat_open,
     192             :     .url_read       = concat_read,
     193             :     .url_seek       = concat_seek,
     194             :     .url_close      = concat_close,
     195             :     .priv_data_size = sizeof(struct concat_data),
     196             :     .default_whitelist = "concat,file,subfile",
     197             : };

Generated by: LCOV version 1.13