Statistics
| Branch: | Revision:

ffmpeg / libavformat / avio.c @ f1d2b572

History | View | Annotate | Download (6.66 KB)

1
/*
2
 * Unbuffered io for ffmpeg system
3
 * Copyright (c) 2001 Fabrice Bellard
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21

    
22
/* needed for usleep() */
23
#define _XOPEN_SOURCE 600
24
#include <unistd.h>
25
#include "libavutil/avstring.h"
26
#include "libavcodec/opt.h"
27
#include "os_support.h"
28
#include "avformat.h"
29

    
30
#if LIBAVFORMAT_VERSION_MAJOR >= 53
31
/** @name Logging context. */
32
/*@{*/
33
static const char *urlcontext_to_name(void *ptr)
34
{
35
    URLContext *h = (URLContext *)ptr;
36
    if(h->prot) return h->prot->name;
37
    else        return "NULL";
38
}
39
static const AVOption options[] = {{NULL}};
40
static const AVClass urlcontext_class =
41
        { "URLContext", urlcontext_to_name, options };
42
/*@}*/
43
#endif
44

    
45
static int default_interrupt_cb(void);
46

    
47
URLProtocol *first_protocol = NULL;
48
URLInterruptCB *url_interrupt_cb = default_interrupt_cb;
49

    
50
URLProtocol *av_protocol_next(URLProtocol *p)
51
{
52
    if(p) return p->next;
53
    else  return first_protocol;
54
}
55

    
56
int av_register_protocol(URLProtocol *protocol)
57
{
58
    URLProtocol **p;
59
    p = &first_protocol;
60
    while (*p != NULL) p = &(*p)->next;
61
    *p = protocol;
62
    protocol->next = NULL;
63
    return 0;
64
}
65

    
66
#if LIBAVFORMAT_VERSION_MAJOR < 53
67
int register_protocol(URLProtocol *protocol)
68
{
69
    return av_register_protocol(protocol);
70
}
71
#endif
72

    
73
int url_open_protocol (URLContext **puc, struct URLProtocol *up,
74
                       const char *filename, int flags)
75
{
76
    URLContext *uc;
77
    int err;
78

    
79
    uc = av_malloc(sizeof(URLContext) + strlen(filename) + 1);
80
    if (!uc) {
81
        err = AVERROR(ENOMEM);
82
        goto fail;
83
    }
84
#if LIBAVFORMAT_VERSION_MAJOR >= 53
85
    uc->av_class = &urlcontext_class;
86
#endif
87
    uc->filename = (char *) &uc[1];
88
    strcpy(uc->filename, filename);
89
    uc->prot = up;
90
    uc->flags = flags;
91
    uc->is_streamed = 0; /* default = not streamed */
92
    uc->max_packet_size = 0; /* default: stream file */
93
    err = up->url_open(uc, filename, flags);
94
    if (err < 0) {
95
        av_free(uc);
96
        *puc = NULL;
97
        return err;
98
    }
99

    
100
    //We must be careful here as url_seek() could be slow, for example for http
101
    if(   (flags & (URL_WRONLY | URL_RDWR))
102
       || !strcmp(up->name, "file"))
103
        if(!uc->is_streamed && url_seek(uc, 0, SEEK_SET) < 0)
104
            uc->is_streamed= 1;
105
    *puc = uc;
106
    return 0;
107
 fail:
108
    *puc = NULL;
109
    return err;
110
}
111

    
112
int url_open(URLContext **puc, const char *filename, int flags)
113
{
114
    URLProtocol *up;
115
    const char *p;
116
    char proto_str[128], *q;
117

    
118
    p = filename;
119
    q = proto_str;
120
    while (*p != '\0' && *p != ':') {
121
        /* protocols can only contain alphabetic chars */
122
        if (!isalpha(*p))
123
            goto file_proto;
124
        if ((q - proto_str) < sizeof(proto_str) - 1)
125
            *q++ = *p;
126
        p++;
127
    }
128
    /* if the protocol has length 1, we consider it is a dos drive */
129
    if (*p == '\0' || is_dos_path(filename)) {
130
    file_proto:
131
        strcpy(proto_str, "file");
132
    } else {
133
        *q = '\0';
134
    }
135

    
136
    up = first_protocol;
137
    while (up != NULL) {
138
        if (!strcmp(proto_str, up->name))
139
            return url_open_protocol (puc, up, filename, flags);
140
        up = up->next;
141
    }
142
    *puc = NULL;
143
    return AVERROR(ENOENT);
144
}
145

    
146
int url_read(URLContext *h, unsigned char *buf, int size)
147
{
148
    int ret;
149
    if (h->flags & URL_WRONLY)
150
        return AVERROR(EIO);
151
    ret = h->prot->url_read(h, buf, size);
152
    return ret;
153
}
154

    
155
int url_read_complete(URLContext *h, unsigned char *buf, int size)
156
{
157
    int ret, len;
158
    int fast_retries = 5;
159

    
160
    len = 0;
161
    while (len < size) {
162
        ret = url_read(h, buf+len, size-len);
163
        if (ret == AVERROR(EAGAIN)) {
164
            ret = 0;
165
            if (fast_retries)
166
                fast_retries--;
167
            else
168
                usleep(1000);
169
        } else if (ret < 1)
170
            return ret < 0 ? ret : len;
171
        if (ret)
172
           fast_retries = FFMAX(fast_retries, 2);
173
        len += ret;
174
    }
175
    return len;
176
}
177

    
178
int url_write(URLContext *h, unsigned char *buf, int size)
179
{
180
    int ret;
181
    if (!(h->flags & (URL_WRONLY | URL_RDWR)))
182
        return AVERROR(EIO);
183
    /* avoid sending too big packets */
184
    if (h->max_packet_size && size > h->max_packet_size)
185
        return AVERROR(EIO);
186
    ret = h->prot->url_write(h, buf, size);
187
    return ret;
188
}
189

    
190
int64_t url_seek(URLContext *h, int64_t pos, int whence)
191
{
192
    int64_t ret;
193

    
194
    if (!h->prot->url_seek)
195
        return AVERROR(EPIPE);
196
    ret = h->prot->url_seek(h, pos, whence);
197
    return ret;
198
}
199

    
200
int url_close(URLContext *h)
201
{
202
    int ret = 0;
203
    if (!h) return 0; /* can happen when url_open fails */
204

    
205
    if (h->prot->url_close)
206
        ret = h->prot->url_close(h);
207
    av_free(h);
208
    return ret;
209
}
210

    
211
int url_exist(const char *filename)
212
{
213
    URLContext *h;
214
    if (url_open(&h, filename, URL_RDONLY) < 0)
215
        return 0;
216
    url_close(h);
217
    return 1;
218
}
219

    
220
int64_t url_filesize(URLContext *h)
221
{
222
    int64_t pos, size;
223

    
224
    size= url_seek(h, 0, AVSEEK_SIZE);
225
    if(size<0){
226
        pos = url_seek(h, 0, SEEK_CUR);
227
        if ((size = url_seek(h, -1, SEEK_END)) < 0)
228
            return size;
229
        size++;
230
        url_seek(h, pos, SEEK_SET);
231
    }
232
    return size;
233
}
234

    
235
int url_get_file_handle(URLContext *h)
236
{
237
    if (!h->prot->url_get_file_handle)
238
        return -1;
239
    return h->prot->url_get_file_handle(h);
240
}
241

    
242
int url_get_max_packet_size(URLContext *h)
243
{
244
    return h->max_packet_size;
245
}
246

    
247
void url_get_filename(URLContext *h, char *buf, int buf_size)
248
{
249
    av_strlcpy(buf, h->filename, buf_size);
250
}
251

    
252

    
253
static int default_interrupt_cb(void)
254
{
255
    return 0;
256
}
257

    
258
void url_set_interrupt_cb(URLInterruptCB *interrupt_cb)
259
{
260
    if (!interrupt_cb)
261
        interrupt_cb = default_interrupt_cb;
262
    url_interrupt_cb = interrupt_cb;
263
}
264

    
265
int av_url_read_pause(URLContext *h, int pause)
266
{
267
    if (!h->prot->url_read_pause)
268
        return AVERROR(ENOSYS);
269
    return h->prot->url_read_pause(h, pause);
270
}
271

    
272
int64_t av_url_read_seek(URLContext *h,
273
        int stream_index, int64_t timestamp, int flags)
274
{
275
    if (!h->prot->url_read_seek)
276
        return AVERROR(ENOSYS);
277
    return h->prot->url_read_seek(h, stream_index, timestamp, flags);
278
}