1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * various utility functions for use within FFmpeg
3cabdff1aSopenharmony_ci * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
4cabdff1aSopenharmony_ci *
5cabdff1aSopenharmony_ci * This file is part of FFmpeg.
6cabdff1aSopenharmony_ci *
7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
11cabdff1aSopenharmony_ci *
12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15cabdff1aSopenharmony_ci * Lesser General Public License for more details.
16cabdff1aSopenharmony_ci *
17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20cabdff1aSopenharmony_ci */
21cabdff1aSopenharmony_ci
22cabdff1aSopenharmony_ci#include <stdint.h>
23cabdff1aSopenharmony_ci
24cabdff1aSopenharmony_ci#include "config.h"
25cabdff1aSopenharmony_ci
26cabdff1aSopenharmony_ci#include "libavutil/avstring.h"
27cabdff1aSopenharmony_ci#include "libavutil/bprint.h"
28cabdff1aSopenharmony_ci#include "libavutil/internal.h"
29cabdff1aSopenharmony_ci#include "libavutil/thread.h"
30cabdff1aSopenharmony_ci#include "libavutil/time.h"
31cabdff1aSopenharmony_ci
32cabdff1aSopenharmony_ci#include "libavcodec/internal.h"
33cabdff1aSopenharmony_ci
34cabdff1aSopenharmony_ci#include "avformat.h"
35cabdff1aSopenharmony_ci#include "avio_internal.h"
36cabdff1aSopenharmony_ci#include "internal.h"
37cabdff1aSopenharmony_ci#if CONFIG_NETWORK
38cabdff1aSopenharmony_ci#include "network.h"
39cabdff1aSopenharmony_ci#endif
40cabdff1aSopenharmony_ci
41cabdff1aSopenharmony_cistatic AVMutex avformat_mutex = AV_MUTEX_INITIALIZER;
42cabdff1aSopenharmony_ci
43cabdff1aSopenharmony_ci/**
44cabdff1aSopenharmony_ci * @file
45cabdff1aSopenharmony_ci * various utility functions for use within FFmpeg
46cabdff1aSopenharmony_ci */
47cabdff1aSopenharmony_ci
48cabdff1aSopenharmony_ciint ff_lock_avformat(void)
49cabdff1aSopenharmony_ci{
50cabdff1aSopenharmony_ci    return ff_mutex_lock(&avformat_mutex) ? -1 : 0;
51cabdff1aSopenharmony_ci}
52cabdff1aSopenharmony_ci
53cabdff1aSopenharmony_ciint ff_unlock_avformat(void)
54cabdff1aSopenharmony_ci{
55cabdff1aSopenharmony_ci    return ff_mutex_unlock(&avformat_mutex) ? -1 : 0;
56cabdff1aSopenharmony_ci}
57cabdff1aSopenharmony_ci
58cabdff1aSopenharmony_ci/* an arbitrarily chosen "sane" max packet size -- 50M */
59cabdff1aSopenharmony_ci#define SANE_CHUNK_SIZE (50000000)
60cabdff1aSopenharmony_ci
61cabdff1aSopenharmony_ci/* Read the data in sane-sized chunks and append to pkt.
62cabdff1aSopenharmony_ci * Return the number of bytes read or an error. */
63cabdff1aSopenharmony_cistatic int append_packet_chunked(AVIOContext *s, AVPacket *pkt, int size)
64cabdff1aSopenharmony_ci{
65cabdff1aSopenharmony_ci    int orig_size      = pkt->size;
66cabdff1aSopenharmony_ci    int ret;
67cabdff1aSopenharmony_ci
68cabdff1aSopenharmony_ci    do {
69cabdff1aSopenharmony_ci        int prev_size = pkt->size;
70cabdff1aSopenharmony_ci        int read_size;
71cabdff1aSopenharmony_ci
72cabdff1aSopenharmony_ci        /* When the caller requests a lot of data, limit it to the amount
73cabdff1aSopenharmony_ci         * left in file or SANE_CHUNK_SIZE when it is not known. */
74cabdff1aSopenharmony_ci        read_size = size;
75cabdff1aSopenharmony_ci        if (read_size > SANE_CHUNK_SIZE/10) {
76cabdff1aSopenharmony_ci            read_size = ffio_limit(s, read_size);
77cabdff1aSopenharmony_ci            // If filesize/maxsize is unknown, limit to SANE_CHUNK_SIZE
78cabdff1aSopenharmony_ci            if (ffiocontext(s)->maxsize < 0)
79cabdff1aSopenharmony_ci                read_size = FFMIN(read_size, SANE_CHUNK_SIZE);
80cabdff1aSopenharmony_ci        }
81cabdff1aSopenharmony_ci
82cabdff1aSopenharmony_ci        ret = av_grow_packet(pkt, read_size);
83cabdff1aSopenharmony_ci        if (ret < 0)
84cabdff1aSopenharmony_ci            break;
85cabdff1aSopenharmony_ci
86cabdff1aSopenharmony_ci        ret = avio_read(s, pkt->data + prev_size, read_size);
87cabdff1aSopenharmony_ci        if (ret != read_size) {
88cabdff1aSopenharmony_ci            av_shrink_packet(pkt, prev_size + FFMAX(ret, 0));
89cabdff1aSopenharmony_ci            break;
90cabdff1aSopenharmony_ci        }
91cabdff1aSopenharmony_ci
92cabdff1aSopenharmony_ci        size -= read_size;
93cabdff1aSopenharmony_ci    } while (size > 0);
94cabdff1aSopenharmony_ci    if (size > 0)
95cabdff1aSopenharmony_ci        pkt->flags |= AV_PKT_FLAG_CORRUPT;
96cabdff1aSopenharmony_ci
97cabdff1aSopenharmony_ci    if (!pkt->size)
98cabdff1aSopenharmony_ci        av_packet_unref(pkt);
99cabdff1aSopenharmony_ci    return pkt->size > orig_size ? pkt->size - orig_size : ret;
100cabdff1aSopenharmony_ci}
101cabdff1aSopenharmony_ci
102cabdff1aSopenharmony_ciint av_get_packet(AVIOContext *s, AVPacket *pkt, int size)
103cabdff1aSopenharmony_ci{
104cabdff1aSopenharmony_ci#if FF_API_INIT_PACKET
105cabdff1aSopenharmony_ciFF_DISABLE_DEPRECATION_WARNINGS
106cabdff1aSopenharmony_ci    av_init_packet(pkt);
107cabdff1aSopenharmony_ci    pkt->data = NULL;
108cabdff1aSopenharmony_ci    pkt->size = 0;
109cabdff1aSopenharmony_ciFF_ENABLE_DEPRECATION_WARNINGS
110cabdff1aSopenharmony_ci#else
111cabdff1aSopenharmony_ci    av_packet_unref(pkt);
112cabdff1aSopenharmony_ci#endif
113cabdff1aSopenharmony_ci    pkt->pos  = avio_tell(s);
114cabdff1aSopenharmony_ci
115cabdff1aSopenharmony_ci    return append_packet_chunked(s, pkt, size);
116cabdff1aSopenharmony_ci}
117cabdff1aSopenharmony_ci
118cabdff1aSopenharmony_ciint av_append_packet(AVIOContext *s, AVPacket *pkt, int size)
119cabdff1aSopenharmony_ci{
120cabdff1aSopenharmony_ci    if (!pkt->size)
121cabdff1aSopenharmony_ci        return av_get_packet(s, pkt, size);
122cabdff1aSopenharmony_ci    return append_packet_chunked(s, pkt, size);
123cabdff1aSopenharmony_ci}
124cabdff1aSopenharmony_ci
125cabdff1aSopenharmony_ciint av_filename_number_test(const char *filename)
126cabdff1aSopenharmony_ci{
127cabdff1aSopenharmony_ci    char buf[1024];
128cabdff1aSopenharmony_ci    return filename &&
129cabdff1aSopenharmony_ci           (av_get_frame_filename(buf, sizeof(buf), filename, 1) >= 0);
130cabdff1aSopenharmony_ci}
131cabdff1aSopenharmony_ci
132cabdff1aSopenharmony_ci/**********************************************************/
133cabdff1aSopenharmony_ci
134cabdff1aSopenharmony_ciunsigned int ff_codec_get_tag(const AVCodecTag *tags, enum AVCodecID id)
135cabdff1aSopenharmony_ci{
136cabdff1aSopenharmony_ci    while (tags->id != AV_CODEC_ID_NONE) {
137cabdff1aSopenharmony_ci        if (tags->id == id)
138cabdff1aSopenharmony_ci            return tags->tag;
139cabdff1aSopenharmony_ci        tags++;
140cabdff1aSopenharmony_ci    }
141cabdff1aSopenharmony_ci    return 0;
142cabdff1aSopenharmony_ci}
143cabdff1aSopenharmony_ci
144cabdff1aSopenharmony_cienum AVCodecID ff_codec_get_id(const AVCodecTag *tags, unsigned int tag)
145cabdff1aSopenharmony_ci{
146cabdff1aSopenharmony_ci    for (int i = 0; tags[i].id != AV_CODEC_ID_NONE; i++)
147cabdff1aSopenharmony_ci        if (tag == tags[i].tag)
148cabdff1aSopenharmony_ci            return tags[i].id;
149cabdff1aSopenharmony_ci    for (int i = 0; tags[i].id != AV_CODEC_ID_NONE; i++)
150cabdff1aSopenharmony_ci        if (ff_toupper4(tag) == ff_toupper4(tags[i].tag))
151cabdff1aSopenharmony_ci            return tags[i].id;
152cabdff1aSopenharmony_ci    return AV_CODEC_ID_NONE;
153cabdff1aSopenharmony_ci}
154cabdff1aSopenharmony_ci
155cabdff1aSopenharmony_cienum AVCodecID ff_get_pcm_codec_id(int bps, int flt, int be, int sflags)
156cabdff1aSopenharmony_ci{
157cabdff1aSopenharmony_ci    if (bps <= 0 || bps > 64)
158cabdff1aSopenharmony_ci        return AV_CODEC_ID_NONE;
159cabdff1aSopenharmony_ci
160cabdff1aSopenharmony_ci    if (flt) {
161cabdff1aSopenharmony_ci        switch (bps) {
162cabdff1aSopenharmony_ci        case 32:
163cabdff1aSopenharmony_ci            return be ? AV_CODEC_ID_PCM_F32BE : AV_CODEC_ID_PCM_F32LE;
164cabdff1aSopenharmony_ci        case 64:
165cabdff1aSopenharmony_ci            return be ? AV_CODEC_ID_PCM_F64BE : AV_CODEC_ID_PCM_F64LE;
166cabdff1aSopenharmony_ci        default:
167cabdff1aSopenharmony_ci            return AV_CODEC_ID_NONE;
168cabdff1aSopenharmony_ci        }
169cabdff1aSopenharmony_ci    } else {
170cabdff1aSopenharmony_ci        bps  += 7;
171cabdff1aSopenharmony_ci        bps >>= 3;
172cabdff1aSopenharmony_ci        if (sflags & (1 << (bps - 1))) {
173cabdff1aSopenharmony_ci            switch (bps) {
174cabdff1aSopenharmony_ci            case 1:
175cabdff1aSopenharmony_ci                return AV_CODEC_ID_PCM_S8;
176cabdff1aSopenharmony_ci            case 2:
177cabdff1aSopenharmony_ci                return be ? AV_CODEC_ID_PCM_S16BE : AV_CODEC_ID_PCM_S16LE;
178cabdff1aSopenharmony_ci            case 3:
179cabdff1aSopenharmony_ci                return be ? AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
180cabdff1aSopenharmony_ci            case 4:
181cabdff1aSopenharmony_ci                return be ? AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
182cabdff1aSopenharmony_ci            case 8:
183cabdff1aSopenharmony_ci                return be ? AV_CODEC_ID_PCM_S64BE : AV_CODEC_ID_PCM_S64LE;
184cabdff1aSopenharmony_ci            default:
185cabdff1aSopenharmony_ci                return AV_CODEC_ID_NONE;
186cabdff1aSopenharmony_ci            }
187cabdff1aSopenharmony_ci        } else {
188cabdff1aSopenharmony_ci            switch (bps) {
189cabdff1aSopenharmony_ci            case 1:
190cabdff1aSopenharmony_ci                return AV_CODEC_ID_PCM_U8;
191cabdff1aSopenharmony_ci            case 2:
192cabdff1aSopenharmony_ci                return be ? AV_CODEC_ID_PCM_U16BE : AV_CODEC_ID_PCM_U16LE;
193cabdff1aSopenharmony_ci            case 3:
194cabdff1aSopenharmony_ci                return be ? AV_CODEC_ID_PCM_U24BE : AV_CODEC_ID_PCM_U24LE;
195cabdff1aSopenharmony_ci            case 4:
196cabdff1aSopenharmony_ci                return be ? AV_CODEC_ID_PCM_U32BE : AV_CODEC_ID_PCM_U32LE;
197cabdff1aSopenharmony_ci            default:
198cabdff1aSopenharmony_ci                return AV_CODEC_ID_NONE;
199cabdff1aSopenharmony_ci            }
200cabdff1aSopenharmony_ci        }
201cabdff1aSopenharmony_ci    }
202cabdff1aSopenharmony_ci}
203cabdff1aSopenharmony_ci
204cabdff1aSopenharmony_ciunsigned int av_codec_get_tag(const AVCodecTag *const *tags, enum AVCodecID id)
205cabdff1aSopenharmony_ci{
206cabdff1aSopenharmony_ci    unsigned int tag;
207cabdff1aSopenharmony_ci    if (!av_codec_get_tag2(tags, id, &tag))
208cabdff1aSopenharmony_ci        return 0;
209cabdff1aSopenharmony_ci    return tag;
210cabdff1aSopenharmony_ci}
211cabdff1aSopenharmony_ci
212cabdff1aSopenharmony_ciint av_codec_get_tag2(const AVCodecTag * const *tags, enum AVCodecID id,
213cabdff1aSopenharmony_ci                      unsigned int *tag)
214cabdff1aSopenharmony_ci{
215cabdff1aSopenharmony_ci    for (int i = 0; tags && tags[i]; i++) {
216cabdff1aSopenharmony_ci        const AVCodecTag *codec_tags = tags[i];
217cabdff1aSopenharmony_ci        while (codec_tags->id != AV_CODEC_ID_NONE) {
218cabdff1aSopenharmony_ci            if (codec_tags->id == id) {
219cabdff1aSopenharmony_ci                *tag = codec_tags->tag;
220cabdff1aSopenharmony_ci                return 1;
221cabdff1aSopenharmony_ci            }
222cabdff1aSopenharmony_ci            codec_tags++;
223cabdff1aSopenharmony_ci        }
224cabdff1aSopenharmony_ci    }
225cabdff1aSopenharmony_ci    return 0;
226cabdff1aSopenharmony_ci}
227cabdff1aSopenharmony_ci
228cabdff1aSopenharmony_cienum AVCodecID av_codec_get_id(const AVCodecTag *const *tags, unsigned int tag)
229cabdff1aSopenharmony_ci{
230cabdff1aSopenharmony_ci    for (int i = 0; tags && tags[i]; i++) {
231cabdff1aSopenharmony_ci        enum AVCodecID id = ff_codec_get_id(tags[i], tag);
232cabdff1aSopenharmony_ci        if (id != AV_CODEC_ID_NONE)
233cabdff1aSopenharmony_ci            return id;
234cabdff1aSopenharmony_ci    }
235cabdff1aSopenharmony_ci    return AV_CODEC_ID_NONE;
236cabdff1aSopenharmony_ci}
237cabdff1aSopenharmony_ci
238cabdff1aSopenharmony_ciint ff_alloc_extradata(AVCodecParameters *par, int size)
239cabdff1aSopenharmony_ci{
240cabdff1aSopenharmony_ci    av_freep(&par->extradata);
241cabdff1aSopenharmony_ci    par->extradata_size = 0;
242cabdff1aSopenharmony_ci
243cabdff1aSopenharmony_ci    if (size < 0 || size >= INT32_MAX - AV_INPUT_BUFFER_PADDING_SIZE)
244cabdff1aSopenharmony_ci        return AVERROR(EINVAL);
245cabdff1aSopenharmony_ci
246cabdff1aSopenharmony_ci    par->extradata = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
247cabdff1aSopenharmony_ci    if (!par->extradata)
248cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
249cabdff1aSopenharmony_ci
250cabdff1aSopenharmony_ci    memset(par->extradata + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
251cabdff1aSopenharmony_ci    par->extradata_size = size;
252cabdff1aSopenharmony_ci
253cabdff1aSopenharmony_ci    return 0;
254cabdff1aSopenharmony_ci}
255cabdff1aSopenharmony_ci
256cabdff1aSopenharmony_ci/*******************************************************/
257cabdff1aSopenharmony_ci
258cabdff1aSopenharmony_ciuint64_t ff_ntp_time(void)
259cabdff1aSopenharmony_ci{
260cabdff1aSopenharmony_ci    return (av_gettime() / 1000) * 1000 + NTP_OFFSET_US;
261cabdff1aSopenharmony_ci}
262cabdff1aSopenharmony_ci
263cabdff1aSopenharmony_ciuint64_t ff_get_formatted_ntp_time(uint64_t ntp_time_us)
264cabdff1aSopenharmony_ci{
265cabdff1aSopenharmony_ci    uint64_t ntp_ts, frac_part, sec;
266cabdff1aSopenharmony_ci    uint32_t usec;
267cabdff1aSopenharmony_ci
268cabdff1aSopenharmony_ci    //current ntp time in seconds and micro seconds
269cabdff1aSopenharmony_ci    sec = ntp_time_us / 1000000;
270cabdff1aSopenharmony_ci    usec = ntp_time_us % 1000000;
271cabdff1aSopenharmony_ci
272cabdff1aSopenharmony_ci    //encoding in ntp timestamp format
273cabdff1aSopenharmony_ci    frac_part = usec * 0xFFFFFFFFULL;
274cabdff1aSopenharmony_ci    frac_part /= 1000000;
275cabdff1aSopenharmony_ci
276cabdff1aSopenharmony_ci    if (sec > 0xFFFFFFFFULL)
277cabdff1aSopenharmony_ci        av_log(NULL, AV_LOG_WARNING, "NTP time format roll over detected\n");
278cabdff1aSopenharmony_ci
279cabdff1aSopenharmony_ci    ntp_ts = sec << 32;
280cabdff1aSopenharmony_ci    ntp_ts |= frac_part;
281cabdff1aSopenharmony_ci
282cabdff1aSopenharmony_ci    return ntp_ts;
283cabdff1aSopenharmony_ci}
284cabdff1aSopenharmony_ci
285cabdff1aSopenharmony_ciuint64_t ff_parse_ntp_time(uint64_t ntp_ts)
286cabdff1aSopenharmony_ci{
287cabdff1aSopenharmony_ci    uint64_t sec = ntp_ts >> 32;
288cabdff1aSopenharmony_ci    uint64_t frac_part = ntp_ts & 0xFFFFFFFFULL;
289cabdff1aSopenharmony_ci    uint64_t usec = (frac_part * 1000000) / 0xFFFFFFFFULL;
290cabdff1aSopenharmony_ci
291cabdff1aSopenharmony_ci    return (sec * 1000000) + usec;
292cabdff1aSopenharmony_ci}
293cabdff1aSopenharmony_ci
294cabdff1aSopenharmony_ciint av_get_frame_filename2(char *buf, int buf_size, const char *path, int number, int flags)
295cabdff1aSopenharmony_ci{
296cabdff1aSopenharmony_ci    const char *p;
297cabdff1aSopenharmony_ci    char *q, buf1[20], c;
298cabdff1aSopenharmony_ci    int nd, len, percentd_found;
299cabdff1aSopenharmony_ci
300cabdff1aSopenharmony_ci    q = buf;
301cabdff1aSopenharmony_ci    p = path;
302cabdff1aSopenharmony_ci    percentd_found = 0;
303cabdff1aSopenharmony_ci    for (;;) {
304cabdff1aSopenharmony_ci        c = *p++;
305cabdff1aSopenharmony_ci        if (c == '\0')
306cabdff1aSopenharmony_ci            break;
307cabdff1aSopenharmony_ci        if (c == '%') {
308cabdff1aSopenharmony_ci            do {
309cabdff1aSopenharmony_ci                nd = 0;
310cabdff1aSopenharmony_ci                while (av_isdigit(*p)) {
311cabdff1aSopenharmony_ci                    if (nd >= INT_MAX / 10 - 255)
312cabdff1aSopenharmony_ci                        goto fail;
313cabdff1aSopenharmony_ci                    nd = nd * 10 + *p++ - '0';
314cabdff1aSopenharmony_ci                }
315cabdff1aSopenharmony_ci                c = *p++;
316cabdff1aSopenharmony_ci            } while (av_isdigit(c));
317cabdff1aSopenharmony_ci
318cabdff1aSopenharmony_ci            switch (c) {
319cabdff1aSopenharmony_ci            case '%':
320cabdff1aSopenharmony_ci                goto addchar;
321cabdff1aSopenharmony_ci            case 'd':
322cabdff1aSopenharmony_ci                if (!(flags & AV_FRAME_FILENAME_FLAGS_MULTIPLE) && percentd_found)
323cabdff1aSopenharmony_ci                    goto fail;
324cabdff1aSopenharmony_ci                percentd_found = 1;
325cabdff1aSopenharmony_ci                if (number < 0)
326cabdff1aSopenharmony_ci                    nd += 1;
327cabdff1aSopenharmony_ci                snprintf(buf1, sizeof(buf1), "%0*d", nd, number);
328cabdff1aSopenharmony_ci                len = strlen(buf1);
329cabdff1aSopenharmony_ci                if ((q - buf + len) > buf_size - 1)
330cabdff1aSopenharmony_ci                    goto fail;
331cabdff1aSopenharmony_ci                memcpy(q, buf1, len);
332cabdff1aSopenharmony_ci                q += len;
333cabdff1aSopenharmony_ci                break;
334cabdff1aSopenharmony_ci            default:
335cabdff1aSopenharmony_ci                goto fail;
336cabdff1aSopenharmony_ci            }
337cabdff1aSopenharmony_ci        } else {
338cabdff1aSopenharmony_ciaddchar:
339cabdff1aSopenharmony_ci            if ((q - buf) < buf_size - 1)
340cabdff1aSopenharmony_ci                *q++ = c;
341cabdff1aSopenharmony_ci        }
342cabdff1aSopenharmony_ci    }
343cabdff1aSopenharmony_ci    if (!percentd_found)
344cabdff1aSopenharmony_ci        goto fail;
345cabdff1aSopenharmony_ci    *q = '\0';
346cabdff1aSopenharmony_ci    return 0;
347cabdff1aSopenharmony_cifail:
348cabdff1aSopenharmony_ci    *q = '\0';
349cabdff1aSopenharmony_ci    return -1;
350cabdff1aSopenharmony_ci}
351cabdff1aSopenharmony_ci
352cabdff1aSopenharmony_ciint av_get_frame_filename(char *buf, int buf_size, const char *path, int number)
353cabdff1aSopenharmony_ci{
354cabdff1aSopenharmony_ci    return av_get_frame_filename2(buf, buf_size, path, number, 0);
355cabdff1aSopenharmony_ci}
356cabdff1aSopenharmony_ci
357cabdff1aSopenharmony_civoid av_url_split(char *proto, int proto_size,
358cabdff1aSopenharmony_ci                  char *authorization, int authorization_size,
359cabdff1aSopenharmony_ci                  char *hostname, int hostname_size,
360cabdff1aSopenharmony_ci                  int *port_ptr, char *path, int path_size, const char *url)
361cabdff1aSopenharmony_ci{
362cabdff1aSopenharmony_ci    const char *p, *ls, *at, *at2, *col, *brk;
363cabdff1aSopenharmony_ci
364cabdff1aSopenharmony_ci    if (port_ptr)
365cabdff1aSopenharmony_ci        *port_ptr = -1;
366cabdff1aSopenharmony_ci    if (proto_size > 0)
367cabdff1aSopenharmony_ci        proto[0] = 0;
368cabdff1aSopenharmony_ci    if (authorization_size > 0)
369cabdff1aSopenharmony_ci        authorization[0] = 0;
370cabdff1aSopenharmony_ci    if (hostname_size > 0)
371cabdff1aSopenharmony_ci        hostname[0] = 0;
372cabdff1aSopenharmony_ci    if (path_size > 0)
373cabdff1aSopenharmony_ci        path[0] = 0;
374cabdff1aSopenharmony_ci
375cabdff1aSopenharmony_ci    /* parse protocol */
376cabdff1aSopenharmony_ci    if ((p = strchr(url, ':'))) {
377cabdff1aSopenharmony_ci        av_strlcpy(proto, url, FFMIN(proto_size, p + 1 - url));
378cabdff1aSopenharmony_ci        p++; /* skip ':' */
379cabdff1aSopenharmony_ci        if (*p == '/')
380cabdff1aSopenharmony_ci            p++;
381cabdff1aSopenharmony_ci        if (*p == '/')
382cabdff1aSopenharmony_ci            p++;
383cabdff1aSopenharmony_ci    } else {
384cabdff1aSopenharmony_ci        /* no protocol means plain filename */
385cabdff1aSopenharmony_ci        av_strlcpy(path, url, path_size);
386cabdff1aSopenharmony_ci        return;
387cabdff1aSopenharmony_ci    }
388cabdff1aSopenharmony_ci
389cabdff1aSopenharmony_ci    /* separate path from hostname */
390cabdff1aSopenharmony_ci    ls = p + strcspn(p, "/?#");
391cabdff1aSopenharmony_ci    av_strlcpy(path, ls, path_size);
392cabdff1aSopenharmony_ci
393cabdff1aSopenharmony_ci    /* the rest is hostname, use that to parse auth/port */
394cabdff1aSopenharmony_ci    if (ls != p) {
395cabdff1aSopenharmony_ci        /* authorization (user[:pass]@hostname) */
396cabdff1aSopenharmony_ci        at2 = p;
397cabdff1aSopenharmony_ci        while ((at = strchr(p, '@')) && at < ls) {
398cabdff1aSopenharmony_ci            av_strlcpy(authorization, at2,
399cabdff1aSopenharmony_ci                       FFMIN(authorization_size, at + 1 - at2));
400cabdff1aSopenharmony_ci            p = at + 1; /* skip '@' */
401cabdff1aSopenharmony_ci        }
402cabdff1aSopenharmony_ci
403cabdff1aSopenharmony_ci        if (*p == '[' && (brk = strchr(p, ']')) && brk < ls) {
404cabdff1aSopenharmony_ci            /* [host]:port */
405cabdff1aSopenharmony_ci            av_strlcpy(hostname, p + 1,
406cabdff1aSopenharmony_ci                       FFMIN(hostname_size, brk - p));
407cabdff1aSopenharmony_ci            if (brk[1] == ':' && port_ptr)
408cabdff1aSopenharmony_ci                *port_ptr = atoi(brk + 2);
409cabdff1aSopenharmony_ci        } else if ((col = strchr(p, ':')) && col < ls) {
410cabdff1aSopenharmony_ci            av_strlcpy(hostname, p,
411cabdff1aSopenharmony_ci                       FFMIN(col + 1 - p, hostname_size));
412cabdff1aSopenharmony_ci            if (port_ptr)
413cabdff1aSopenharmony_ci                *port_ptr = atoi(col + 1);
414cabdff1aSopenharmony_ci        } else
415cabdff1aSopenharmony_ci            av_strlcpy(hostname, p,
416cabdff1aSopenharmony_ci                       FFMIN(ls + 1 - p, hostname_size));
417cabdff1aSopenharmony_ci    }
418cabdff1aSopenharmony_ci}
419cabdff1aSopenharmony_ci
420cabdff1aSopenharmony_ciint ff_mkdir_p(const char *path)
421cabdff1aSopenharmony_ci{
422cabdff1aSopenharmony_ci    int ret = 0;
423cabdff1aSopenharmony_ci    char *temp = av_strdup(path);
424cabdff1aSopenharmony_ci    char *pos = temp;
425cabdff1aSopenharmony_ci    char tmp_ch = '\0';
426cabdff1aSopenharmony_ci
427cabdff1aSopenharmony_ci    if (!path || !temp) {
428cabdff1aSopenharmony_ci        return -1;
429cabdff1aSopenharmony_ci    }
430cabdff1aSopenharmony_ci
431cabdff1aSopenharmony_ci    if (!av_strncasecmp(temp, "/", 1) || !av_strncasecmp(temp, "\\", 1)) {
432cabdff1aSopenharmony_ci        pos++;
433cabdff1aSopenharmony_ci    } else if (!av_strncasecmp(temp, "./", 2) || !av_strncasecmp(temp, ".\\", 2)) {
434cabdff1aSopenharmony_ci        pos += 2;
435cabdff1aSopenharmony_ci    }
436cabdff1aSopenharmony_ci
437cabdff1aSopenharmony_ci    for ( ; *pos != '\0'; ++pos) {
438cabdff1aSopenharmony_ci        if (*pos == '/' || *pos == '\\') {
439cabdff1aSopenharmony_ci            tmp_ch = *pos;
440cabdff1aSopenharmony_ci            *pos = '\0';
441cabdff1aSopenharmony_ci            ret = mkdir(temp, 0755);
442cabdff1aSopenharmony_ci            *pos = tmp_ch;
443cabdff1aSopenharmony_ci        }
444cabdff1aSopenharmony_ci    }
445cabdff1aSopenharmony_ci
446cabdff1aSopenharmony_ci    if ((*(pos - 1) != '/') && (*(pos - 1) != '\\')) {
447cabdff1aSopenharmony_ci        ret = mkdir(temp, 0755);
448cabdff1aSopenharmony_ci    }
449cabdff1aSopenharmony_ci
450cabdff1aSopenharmony_ci    av_free(temp);
451cabdff1aSopenharmony_ci    return ret;
452cabdff1aSopenharmony_ci}
453cabdff1aSopenharmony_ci
454cabdff1aSopenharmony_cichar *ff_data_to_hex(char *buff, const uint8_t *src, int s, int lowercase)
455cabdff1aSopenharmony_ci{
456cabdff1aSopenharmony_ci    static const char hex_table_uc[16] = { '0', '1', '2', '3',
457cabdff1aSopenharmony_ci                                           '4', '5', '6', '7',
458cabdff1aSopenharmony_ci                                           '8', '9', 'A', 'B',
459cabdff1aSopenharmony_ci                                           'C', 'D', 'E', 'F' };
460cabdff1aSopenharmony_ci    static const char hex_table_lc[16] = { '0', '1', '2', '3',
461cabdff1aSopenharmony_ci                                           '4', '5', '6', '7',
462cabdff1aSopenharmony_ci                                           '8', '9', 'a', 'b',
463cabdff1aSopenharmony_ci                                           'c', 'd', 'e', 'f' };
464cabdff1aSopenharmony_ci    const char *hex_table = lowercase ? hex_table_lc : hex_table_uc;
465cabdff1aSopenharmony_ci
466cabdff1aSopenharmony_ci    for (int i = 0; i < s; i++) {
467cabdff1aSopenharmony_ci        buff[i * 2]     = hex_table[src[i] >> 4];
468cabdff1aSopenharmony_ci        buff[i * 2 + 1] = hex_table[src[i] & 0xF];
469cabdff1aSopenharmony_ci    }
470cabdff1aSopenharmony_ci    buff[2 * s] = '\0';
471cabdff1aSopenharmony_ci
472cabdff1aSopenharmony_ci    return buff;
473cabdff1aSopenharmony_ci}
474cabdff1aSopenharmony_ci
475cabdff1aSopenharmony_ciint ff_hex_to_data(uint8_t *data, const char *p)
476cabdff1aSopenharmony_ci{
477cabdff1aSopenharmony_ci    int c, len, v;
478cabdff1aSopenharmony_ci
479cabdff1aSopenharmony_ci    len = 0;
480cabdff1aSopenharmony_ci    v   = 1;
481cabdff1aSopenharmony_ci    for (;;) {
482cabdff1aSopenharmony_ci        p += strspn(p, SPACE_CHARS);
483cabdff1aSopenharmony_ci        if (*p == '\0')
484cabdff1aSopenharmony_ci            break;
485cabdff1aSopenharmony_ci        c = av_toupper((unsigned char) *p++);
486cabdff1aSopenharmony_ci        if (c >= '0' && c <= '9')
487cabdff1aSopenharmony_ci            c = c - '0';
488cabdff1aSopenharmony_ci        else if (c >= 'A' && c <= 'F')
489cabdff1aSopenharmony_ci            c = c - 'A' + 10;
490cabdff1aSopenharmony_ci        else
491cabdff1aSopenharmony_ci            break;
492cabdff1aSopenharmony_ci        v = (v << 4) | c;
493cabdff1aSopenharmony_ci        if (v & 0x100) {
494cabdff1aSopenharmony_ci            if (data)
495cabdff1aSopenharmony_ci                data[len] = v;
496cabdff1aSopenharmony_ci            len++;
497cabdff1aSopenharmony_ci            v = 1;
498cabdff1aSopenharmony_ci        }
499cabdff1aSopenharmony_ci    }
500cabdff1aSopenharmony_ci    return len;
501cabdff1aSopenharmony_ci}
502cabdff1aSopenharmony_ci
503cabdff1aSopenharmony_civoid ff_parse_key_value(const char *str, ff_parse_key_val_cb callback_get_buf,
504cabdff1aSopenharmony_ci                        void *context)
505cabdff1aSopenharmony_ci{
506cabdff1aSopenharmony_ci    const char *ptr = str;
507cabdff1aSopenharmony_ci
508cabdff1aSopenharmony_ci    /* Parse key=value pairs. */
509cabdff1aSopenharmony_ci    for (;;) {
510cabdff1aSopenharmony_ci        const char *key;
511cabdff1aSopenharmony_ci        char *dest = NULL, *dest_end;
512cabdff1aSopenharmony_ci        int key_len, dest_len = 0;
513cabdff1aSopenharmony_ci
514cabdff1aSopenharmony_ci        /* Skip whitespace and potential commas. */
515cabdff1aSopenharmony_ci        while (*ptr && (av_isspace(*ptr) || *ptr == ','))
516cabdff1aSopenharmony_ci            ptr++;
517cabdff1aSopenharmony_ci        if (!*ptr)
518cabdff1aSopenharmony_ci            break;
519cabdff1aSopenharmony_ci
520cabdff1aSopenharmony_ci        key = ptr;
521cabdff1aSopenharmony_ci
522cabdff1aSopenharmony_ci        if (!(ptr = strchr(key, '=')))
523cabdff1aSopenharmony_ci            break;
524cabdff1aSopenharmony_ci        ptr++;
525cabdff1aSopenharmony_ci        key_len = ptr - key;
526cabdff1aSopenharmony_ci
527cabdff1aSopenharmony_ci        callback_get_buf(context, key, key_len, &dest, &dest_len);
528cabdff1aSopenharmony_ci        dest_end = dest ? dest + dest_len - 1 : NULL;
529cabdff1aSopenharmony_ci
530cabdff1aSopenharmony_ci        if (*ptr == '\"') {
531cabdff1aSopenharmony_ci            ptr++;
532cabdff1aSopenharmony_ci            while (*ptr && *ptr != '\"') {
533cabdff1aSopenharmony_ci                if (*ptr == '\\') {
534cabdff1aSopenharmony_ci                    if (!ptr[1])
535cabdff1aSopenharmony_ci                        break;
536cabdff1aSopenharmony_ci                    if (dest && dest < dest_end)
537cabdff1aSopenharmony_ci                        *dest++ = ptr[1];
538cabdff1aSopenharmony_ci                    ptr += 2;
539cabdff1aSopenharmony_ci                } else {
540cabdff1aSopenharmony_ci                    if (dest && dest < dest_end)
541cabdff1aSopenharmony_ci                        *dest++ = *ptr;
542cabdff1aSopenharmony_ci                    ptr++;
543cabdff1aSopenharmony_ci                }
544cabdff1aSopenharmony_ci            }
545cabdff1aSopenharmony_ci            if (*ptr == '\"')
546cabdff1aSopenharmony_ci                ptr++;
547cabdff1aSopenharmony_ci        } else {
548cabdff1aSopenharmony_ci            for (; *ptr && !(av_isspace(*ptr) || *ptr == ','); ptr++)
549cabdff1aSopenharmony_ci                if (dest && dest < dest_end)
550cabdff1aSopenharmony_ci                    *dest++ = *ptr;
551cabdff1aSopenharmony_ci        }
552cabdff1aSopenharmony_ci        if (dest)
553cabdff1aSopenharmony_ci            *dest = 0;
554cabdff1aSopenharmony_ci    }
555cabdff1aSopenharmony_ci}
556cabdff1aSopenharmony_ci
557cabdff1aSopenharmony_ciint avformat_network_init(void)
558cabdff1aSopenharmony_ci{
559cabdff1aSopenharmony_ci#if CONFIG_NETWORK
560cabdff1aSopenharmony_ci    int ret;
561cabdff1aSopenharmony_ci    if ((ret = ff_network_init()) < 0)
562cabdff1aSopenharmony_ci        return ret;
563cabdff1aSopenharmony_ci    if ((ret = ff_tls_init()) < 0)
564cabdff1aSopenharmony_ci        return ret;
565cabdff1aSopenharmony_ci#endif
566cabdff1aSopenharmony_ci    return 0;
567cabdff1aSopenharmony_ci}
568cabdff1aSopenharmony_ci
569cabdff1aSopenharmony_ciint avformat_network_deinit(void)
570cabdff1aSopenharmony_ci{
571cabdff1aSopenharmony_ci#if CONFIG_NETWORK
572cabdff1aSopenharmony_ci    ff_network_close();
573cabdff1aSopenharmony_ci    ff_tls_deinit();
574cabdff1aSopenharmony_ci#endif
575cabdff1aSopenharmony_ci    return 0;
576cabdff1aSopenharmony_ci}
577cabdff1aSopenharmony_ci
578cabdff1aSopenharmony_ciint ff_is_http_proto(const char *filename) {
579cabdff1aSopenharmony_ci    const char *proto = avio_find_protocol_name(filename);
580cabdff1aSopenharmony_ci    return proto ? (!av_strcasecmp(proto, "http") || !av_strcasecmp(proto, "https")) : 0;
581cabdff1aSopenharmony_ci}
582cabdff1aSopenharmony_ci
583cabdff1aSopenharmony_ciint ff_bprint_to_codecpar_extradata(AVCodecParameters *par, struct AVBPrint *buf)
584cabdff1aSopenharmony_ci{
585cabdff1aSopenharmony_ci    int ret;
586cabdff1aSopenharmony_ci    char *str;
587cabdff1aSopenharmony_ci
588cabdff1aSopenharmony_ci    ret = av_bprint_finalize(buf, &str);
589cabdff1aSopenharmony_ci    if (ret < 0)
590cabdff1aSopenharmony_ci        return ret;
591cabdff1aSopenharmony_ci    if (!av_bprint_is_complete(buf)) {
592cabdff1aSopenharmony_ci        av_free(str);
593cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
594cabdff1aSopenharmony_ci    }
595cabdff1aSopenharmony_ci
596cabdff1aSopenharmony_ci    par->extradata = str;
597cabdff1aSopenharmony_ci    /* Note: the string is NUL terminated (so extradata can be read as a
598cabdff1aSopenharmony_ci     * string), but the ending character is not accounted in the size (in
599cabdff1aSopenharmony_ci     * binary formats you are likely not supposed to mux that character). When
600cabdff1aSopenharmony_ci     * extradata is copied, it is also padded with AV_INPUT_BUFFER_PADDING_SIZE
601cabdff1aSopenharmony_ci     * zeros. */
602cabdff1aSopenharmony_ci    par->extradata_size = buf->len;
603cabdff1aSopenharmony_ci    return 0;
604cabdff1aSopenharmony_ci}
605