Merge commit '9f61abc8111c7c43f49ca012e957a108b9cc7610'
This also deprecates our old duplicated callbacks. * commit '9f61abc8111c7c43f49ca012e957a108b9cc7610': lavf: allow custom IO for all files Merged-by: Derek Buitenhuis <derek.buitenhuis@gmail.com>
This commit is contained in:
commit
bc9a5965c8
@ -15,6 +15,9 @@ libavutil: 2015-08-28
|
|||||||
|
|
||||||
API changes, most recent first:
|
API changes, most recent first:
|
||||||
|
|
||||||
|
2016-xx-xx - xxxxxxx - lavf 57.25.0 - avformat.h
|
||||||
|
Add AVFormatContext.opaque, io_open and io_close, allowing custom IO
|
||||||
|
|
||||||
2016-02-01 - xxxxxxx - lavf 57.24.100
|
2016-02-01 - xxxxxxx - lavf 57.24.100
|
||||||
Add protocol_whitelist to AVFormatContext, AVIOContext
|
Add protocol_whitelist to AVFormatContext, AVIOContext
|
||||||
|
|
||||||
|
@ -1780,7 +1780,6 @@ typedef struct AVFormatContext {
|
|||||||
/**
|
/**
|
||||||
* User data.
|
* User data.
|
||||||
* This is a place for some private data of the user.
|
* This is a place for some private data of the user.
|
||||||
* Mostly usable with control_message_cb or any future callbacks in device's context.
|
|
||||||
*/
|
*/
|
||||||
void *opaque;
|
void *opaque;
|
||||||
|
|
||||||
@ -1811,6 +1810,7 @@ typedef struct AVFormatContext {
|
|||||||
*/
|
*/
|
||||||
enum AVCodecID data_codec_id;
|
enum AVCodecID data_codec_id;
|
||||||
|
|
||||||
|
#if FF_API_OLD_OPEN_CALLBACKS
|
||||||
/**
|
/**
|
||||||
* Called to open further IO contexts when needed for demuxing.
|
* Called to open further IO contexts when needed for demuxing.
|
||||||
*
|
*
|
||||||
@ -1825,8 +1825,12 @@ typedef struct AVFormatContext {
|
|||||||
* @See av_format_set_open_cb()
|
* @See av_format_set_open_cb()
|
||||||
*
|
*
|
||||||
* Demuxing: Set by user.
|
* Demuxing: Set by user.
|
||||||
|
*
|
||||||
|
* @deprecated Use io_open and io_close.
|
||||||
*/
|
*/
|
||||||
|
attribute_deprecated
|
||||||
int (*open_cb)(struct AVFormatContext *s, AVIOContext **p, const char *url, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options);
|
int (*open_cb)(struct AVFormatContext *s, AVIOContext **p, const char *url, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options);
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ',' separated list of allowed protocols.
|
* ',' separated list of allowed protocols.
|
||||||
@ -1834,6 +1838,34 @@ typedef struct AVFormatContext {
|
|||||||
* - decoding: set by user through AVOptions (NO direct access)
|
* - decoding: set by user through AVOptions (NO direct access)
|
||||||
*/
|
*/
|
||||||
char *protocol_whitelist;
|
char *protocol_whitelist;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A callback for opening new IO streams.
|
||||||
|
*
|
||||||
|
* Certain muxers or demuxers (e.g. for various playlist-based formats) need
|
||||||
|
* to open additional files during muxing or demuxing. This callback allows
|
||||||
|
* the caller to provide custom IO in such cases.
|
||||||
|
*
|
||||||
|
* @param s the format context
|
||||||
|
* @param pb on success, the newly opened IO context should be returned here
|
||||||
|
* @param url the url to open
|
||||||
|
* @param flags a combination of AVIO_FLAG_*
|
||||||
|
* @param options a dictionary of additional options, with the same
|
||||||
|
* semantics as in avio_open2()
|
||||||
|
* @return 0 on success, a negative AVERROR code on failure
|
||||||
|
*
|
||||||
|
* @note Certain muxers and demuxers do nesting, i.e. they open one or more
|
||||||
|
* additional internal format contexts. Thus the AVFormatContext pointer
|
||||||
|
* passed to this callback may be different from the one facing the caller.
|
||||||
|
* It will, however, have the same 'opaque' field.
|
||||||
|
*/
|
||||||
|
int (*io_open)(struct AVFormatContext *s, AVIOContext **pb, const char *url,
|
||||||
|
int flags, AVDictionary **options);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A callback for closing the streams opened with AVFormatContext.io_open().
|
||||||
|
*/
|
||||||
|
void (*io_close)(struct AVFormatContext *s, AVIOContext *pb);
|
||||||
} AVFormatContext;
|
} AVFormatContext;
|
||||||
|
|
||||||
int av_format_get_probe_score(const AVFormatContext *s);
|
int av_format_get_probe_score(const AVFormatContext *s);
|
||||||
@ -1851,8 +1883,10 @@ void * av_format_get_opaque(const AVFormatContext *s);
|
|||||||
void av_format_set_opaque(AVFormatContext *s, void *opaque);
|
void av_format_set_opaque(AVFormatContext *s, void *opaque);
|
||||||
av_format_control_message av_format_get_control_message_cb(const AVFormatContext *s);
|
av_format_control_message av_format_get_control_message_cb(const AVFormatContext *s);
|
||||||
void av_format_set_control_message_cb(AVFormatContext *s, av_format_control_message callback);
|
void av_format_set_control_message_cb(AVFormatContext *s, av_format_control_message callback);
|
||||||
AVOpenCallback av_format_get_open_cb(const AVFormatContext *s);
|
#if FF_API_OLD_OPEN_CALLBACKS
|
||||||
void av_format_set_open_cb(AVFormatContext *s, AVOpenCallback callback);
|
attribute_deprecated AVOpenCallback av_format_get_open_cb(const AVFormatContext *s);
|
||||||
|
attribute_deprecated void av_format_set_open_cb(AVFormatContext *s, AVOpenCallback callback);
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function will cause global side data to be injected in the next packet
|
* This function will cause global side data to be injected in the next packet
|
||||||
|
@ -448,8 +448,7 @@ static int write_manifest(AVFormatContext *s, int final)
|
|||||||
AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0);
|
AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0);
|
||||||
|
|
||||||
snprintf(temp_filename, sizeof(temp_filename), "%s.tmp", s->filename);
|
snprintf(temp_filename, sizeof(temp_filename), "%s.tmp", s->filename);
|
||||||
ret = ffio_open_whitelist(&out, temp_filename, AVIO_FLAG_WRITE,
|
ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, NULL);
|
||||||
&s->interrupt_callback, NULL, s->protocol_whitelist);
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename);
|
av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename);
|
||||||
return ret;
|
return ret;
|
||||||
@ -549,7 +548,7 @@ static int write_manifest(AVFormatContext *s, int final)
|
|||||||
avio_printf(out, "\t</Period>\n");
|
avio_printf(out, "\t</Period>\n");
|
||||||
avio_printf(out, "</MPD>\n");
|
avio_printf(out, "</MPD>\n");
|
||||||
avio_flush(out);
|
avio_flush(out);
|
||||||
avio_close(out);
|
ff_format_io_close(s, &out);
|
||||||
return ff_rename(temp_filename, s->filename, s);
|
return ff_rename(temp_filename, s->filename, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -624,6 +623,9 @@ static int dash_write_header(AVFormatContext *s)
|
|||||||
os->ctx = ctx;
|
os->ctx = ctx;
|
||||||
ctx->oformat = oformat;
|
ctx->oformat = oformat;
|
||||||
ctx->interrupt_callback = s->interrupt_callback;
|
ctx->interrupt_callback = s->interrupt_callback;
|
||||||
|
ctx->opaque = s->opaque;
|
||||||
|
ctx->io_close = s->io_close;
|
||||||
|
ctx->io_open = s->io_open;
|
||||||
|
|
||||||
if (!(st = avformat_new_stream(ctx, NULL))) {
|
if (!(st = avformat_new_stream(ctx, NULL))) {
|
||||||
ret = AVERROR(ENOMEM);
|
ret = AVERROR(ENOMEM);
|
||||||
|
@ -140,7 +140,8 @@ static void hds_free(AVFormatContext *s)
|
|||||||
return;
|
return;
|
||||||
for (i = 0; i < s->nb_streams; i++) {
|
for (i = 0; i < s->nb_streams; i++) {
|
||||||
OutputStream *os = &c->streams[i];
|
OutputStream *os = &c->streams[i];
|
||||||
avio_closep(&os->out);
|
if (os->out)
|
||||||
|
ff_format_io_close(s, &os->out);
|
||||||
if (os->ctx && os->ctx_inited)
|
if (os->ctx && os->ctx_inited)
|
||||||
av_write_trailer(os->ctx);
|
av_write_trailer(os->ctx);
|
||||||
if (os->ctx)
|
if (os->ctx)
|
||||||
@ -170,8 +171,7 @@ static int write_manifest(AVFormatContext *s, int final)
|
|||||||
|
|
||||||
snprintf(filename, sizeof(filename), "%s/index.f4m", s->filename);
|
snprintf(filename, sizeof(filename), "%s/index.f4m", s->filename);
|
||||||
snprintf(temp_filename, sizeof(temp_filename), "%s/index.f4m.tmp", s->filename);
|
snprintf(temp_filename, sizeof(temp_filename), "%s/index.f4m.tmp", s->filename);
|
||||||
ret = ffio_open_whitelist(&out, temp_filename, AVIO_FLAG_WRITE,
|
ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, NULL);
|
||||||
&s->interrupt_callback, NULL, s->protocol_whitelist);
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename);
|
av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename);
|
||||||
return ret;
|
return ret;
|
||||||
@ -189,7 +189,7 @@ static int write_manifest(AVFormatContext *s, int final)
|
|||||||
int b64_size = AV_BASE64_SIZE(os->metadata_size);
|
int b64_size = AV_BASE64_SIZE(os->metadata_size);
|
||||||
char *base64 = av_malloc(b64_size);
|
char *base64 = av_malloc(b64_size);
|
||||||
if (!base64) {
|
if (!base64) {
|
||||||
avio_close(out);
|
ff_format_io_close(s, &out);
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
}
|
}
|
||||||
av_base64_encode(base64, b64_size, os->metadata, os->metadata_size);
|
av_base64_encode(base64, b64_size, os->metadata, os->metadata_size);
|
||||||
@ -202,7 +202,7 @@ static int write_manifest(AVFormatContext *s, int final)
|
|||||||
}
|
}
|
||||||
avio_printf(out, "</manifest>\n");
|
avio_printf(out, "</manifest>\n");
|
||||||
avio_flush(out);
|
avio_flush(out);
|
||||||
avio_close(out);
|
ff_format_io_close(s, &out);
|
||||||
return ff_rename(temp_filename, filename, s);
|
return ff_rename(temp_filename, filename, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,8 +239,7 @@ static int write_abst(AVFormatContext *s, OutputStream *os, int final)
|
|||||||
"%s/stream%d.abst", s->filename, index);
|
"%s/stream%d.abst", s->filename, index);
|
||||||
snprintf(temp_filename, sizeof(temp_filename),
|
snprintf(temp_filename, sizeof(temp_filename),
|
||||||
"%s/stream%d.abst.tmp", s->filename, index);
|
"%s/stream%d.abst.tmp", s->filename, index);
|
||||||
ret = ffio_open_whitelist(&out, temp_filename, AVIO_FLAG_WRITE,
|
ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, NULL);
|
||||||
&s->interrupt_callback, NULL, s->protocol_whitelist);
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename);
|
av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename);
|
||||||
return ret;
|
return ret;
|
||||||
@ -283,15 +282,14 @@ static int write_abst(AVFormatContext *s, OutputStream *os, int final)
|
|||||||
}
|
}
|
||||||
update_size(out, afrt_pos);
|
update_size(out, afrt_pos);
|
||||||
update_size(out, 0);
|
update_size(out, 0);
|
||||||
avio_close(out);
|
ff_format_io_close(s, &out);
|
||||||
return ff_rename(temp_filename, filename, s);
|
return ff_rename(temp_filename, filename, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int init_file(AVFormatContext *s, OutputStream *os, int64_t start_ts)
|
static int init_file(AVFormatContext *s, OutputStream *os, int64_t start_ts)
|
||||||
{
|
{
|
||||||
int ret, i;
|
int ret, i;
|
||||||
ret = ffio_open_whitelist(&os->out, os->temp_filename, AVIO_FLAG_WRITE,
|
ret = s->io_open(s, &os->out, os->temp_filename, AVIO_FLAG_WRITE, NULL);
|
||||||
&s->interrupt_callback, NULL, s->protocol_whitelist);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
avio_wb32(os->out, 0);
|
avio_wb32(os->out, 0);
|
||||||
@ -304,13 +302,13 @@ static int init_file(AVFormatContext *s, OutputStream *os, int64_t start_ts)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void close_file(OutputStream *os)
|
static void close_file(AVFormatContext *s, OutputStream *os)
|
||||||
{
|
{
|
||||||
int64_t pos = avio_tell(os->out);
|
int64_t pos = avio_tell(os->out);
|
||||||
avio_seek(os->out, 0, SEEK_SET);
|
avio_seek(os->out, 0, SEEK_SET);
|
||||||
avio_wb32(os->out, pos);
|
avio_wb32(os->out, pos);
|
||||||
avio_flush(os->out);
|
avio_flush(os->out);
|
||||||
avio_closep(&os->out);
|
ff_format_io_close(s, &os->out);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hds_write_header(AVFormatContext *s)
|
static int hds_write_header(AVFormatContext *s)
|
||||||
@ -475,7 +473,7 @@ static int hds_flush(AVFormatContext *s, OutputStream *os, int final,
|
|||||||
|
|
||||||
avio_flush(os->ctx->pb);
|
avio_flush(os->ctx->pb);
|
||||||
os->packets_written = 0;
|
os->packets_written = 0;
|
||||||
close_file(os);
|
close_file(s, os);
|
||||||
|
|
||||||
snprintf(target_filename, sizeof(target_filename),
|
snprintf(target_filename, sizeof(target_filename),
|
||||||
"%s/stream%dSeg1-Frag%d", s->filename, index, os->fragment_index);
|
"%s/stream%dSeg1-Frag%d", s->filename, index, os->fragment_index);
|
||||||
|
@ -180,7 +180,7 @@ struct variant {
|
|||||||
|
|
||||||
typedef struct HLSContext {
|
typedef struct HLSContext {
|
||||||
AVClass *class;
|
AVClass *class;
|
||||||
AVFormatContext *avfmt;
|
AVFormatContext *ctx;
|
||||||
int n_variants;
|
int n_variants;
|
||||||
struct variant **variants;
|
struct variant **variants;
|
||||||
int n_playlists;
|
int n_playlists;
|
||||||
@ -635,7 +635,7 @@ static int open_url(HLSContext *c, URLContext **uc, const char *url, AVDictionar
|
|||||||
av_dict_copy(&tmp, c->avio_opts, 0);
|
av_dict_copy(&tmp, c->avio_opts, 0);
|
||||||
av_dict_copy(&tmp, opts, 0);
|
av_dict_copy(&tmp, opts, 0);
|
||||||
|
|
||||||
ret = ffurl_open_whitelist(uc, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp, c->avfmt->protocol_whitelist);
|
ret = ffurl_open_whitelist(uc, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp, c->ctx->protocol_whitelist);
|
||||||
if( ret >= 0) {
|
if( ret >= 0) {
|
||||||
// update cookies on http response with setcookies.
|
// update cookies on http response with setcookies.
|
||||||
URLContext *u = *uc;
|
URLContext *u = *uc;
|
||||||
@ -680,8 +680,7 @@ static int parse_playlist(HLSContext *c, const char *url,
|
|||||||
av_dict_set(&opts, "headers", c->headers, 0);
|
av_dict_set(&opts, "headers", c->headers, 0);
|
||||||
av_dict_set(&opts, "http_proxy", c->http_proxy, 0);
|
av_dict_set(&opts, "http_proxy", c->http_proxy, 0);
|
||||||
|
|
||||||
ret = ffio_open_whitelist(&in, url, AVIO_FLAG_READ,
|
ret = c->ctx->io_open(c->ctx, &in, url, AVIO_FLAG_READ, &opts);
|
||||||
c->interrupt_callback, &opts, c->avfmt->protocol_whitelist);
|
|
||||||
av_dict_free(&opts);
|
av_dict_free(&opts);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
@ -849,7 +848,7 @@ static int parse_playlist(HLSContext *c, const char *url,
|
|||||||
fail:
|
fail:
|
||||||
av_free(new_url);
|
av_free(new_url);
|
||||||
if (close_in)
|
if (close_in)
|
||||||
avio_close(in);
|
ff_format_io_close(c->ctx, &in);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1518,7 +1517,7 @@ static int hls_read_header(AVFormatContext *s)
|
|||||||
HLSContext *c = s->priv_data;
|
HLSContext *c = s->priv_data;
|
||||||
int ret = 0, i, j, stream_offset = 0;
|
int ret = 0, i, j, stream_offset = 0;
|
||||||
|
|
||||||
c->avfmt = s;
|
c->ctx = s;
|
||||||
c->interrupt_callback = &s->interrupt_callback;
|
c->interrupt_callback = &s->interrupt_callback;
|
||||||
c->strict_std_compliance = s->strict_std_compliance;
|
c->strict_std_compliance = s->strict_std_compliance;
|
||||||
|
|
||||||
|
@ -210,8 +210,7 @@ static int hls_encryption_start(AVFormatContext *s)
|
|||||||
AVIOContext *pb;
|
AVIOContext *pb;
|
||||||
uint8_t key[KEYSIZE];
|
uint8_t key[KEYSIZE];
|
||||||
|
|
||||||
if ((ret = ffio_open_whitelist(&pb, hls->key_info_file, AVIO_FLAG_READ,
|
if ((ret = s->io_open(s, &pb, hls->key_info_file, AVIO_FLAG_READ, NULL)) < 0) {
|
||||||
&s->interrupt_callback, NULL, s->protocol_whitelist)) < 0) {
|
|
||||||
av_log(hls, AV_LOG_ERROR,
|
av_log(hls, AV_LOG_ERROR,
|
||||||
"error opening key info file %s\n", hls->key_info_file);
|
"error opening key info file %s\n", hls->key_info_file);
|
||||||
return ret;
|
return ret;
|
||||||
@ -226,7 +225,7 @@ static int hls_encryption_start(AVFormatContext *s)
|
|||||||
ff_get_line(pb, hls->iv_string, sizeof(hls->iv_string));
|
ff_get_line(pb, hls->iv_string, sizeof(hls->iv_string));
|
||||||
hls->iv_string[strcspn(hls->iv_string, "\r\n")] = '\0';
|
hls->iv_string[strcspn(hls->iv_string, "\r\n")] = '\0';
|
||||||
|
|
||||||
avio_close(pb);
|
ff_format_io_close(s, &pb);
|
||||||
|
|
||||||
if (!*hls->key_uri) {
|
if (!*hls->key_uri) {
|
||||||
av_log(hls, AV_LOG_ERROR, "no key URI specified in key info file\n");
|
av_log(hls, AV_LOG_ERROR, "no key URI specified in key info file\n");
|
||||||
@ -238,14 +237,13 @@ static int hls_encryption_start(AVFormatContext *s)
|
|||||||
return AVERROR(EINVAL);
|
return AVERROR(EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = ffio_open_whitelist(&pb, hls->key_file, AVIO_FLAG_READ,
|
if ((ret = s->io_open(s, &pb, hls->key_file, AVIO_FLAG_READ, NULL)) < 0) {
|
||||||
&s->interrupt_callback, NULL, s->protocol_whitelist)) < 0) {
|
|
||||||
av_log(hls, AV_LOG_ERROR, "error opening key file %s\n", hls->key_file);
|
av_log(hls, AV_LOG_ERROR, "error opening key file %s\n", hls->key_file);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = avio_read(pb, key, sizeof(key));
|
ret = avio_read(pb, key, sizeof(key));
|
||||||
avio_close(pb);
|
ff_format_io_close(s, &pb);
|
||||||
if (ret != sizeof(key)) {
|
if (ret != sizeof(key)) {
|
||||||
av_log(hls, AV_LOG_ERROR, "error reading key file %s\n", hls->key_file);
|
av_log(hls, AV_LOG_ERROR, "error reading key file %s\n", hls->key_file);
|
||||||
if (ret >= 0 || ret == AVERROR_EOF)
|
if (ret >= 0 || ret == AVERROR_EOF)
|
||||||
@ -272,6 +270,9 @@ static int hls_mux_init(AVFormatContext *s)
|
|||||||
oc->oformat = hls->oformat;
|
oc->oformat = hls->oformat;
|
||||||
oc->interrupt_callback = s->interrupt_callback;
|
oc->interrupt_callback = s->interrupt_callback;
|
||||||
oc->max_delay = s->max_delay;
|
oc->max_delay = s->max_delay;
|
||||||
|
oc->opaque = s->opaque;
|
||||||
|
oc->io_open = s->io_open;
|
||||||
|
oc->io_close = s->io_close;
|
||||||
av_dict_copy(&oc->metadata, s->metadata, 0);
|
av_dict_copy(&oc->metadata, s->metadata, 0);
|
||||||
|
|
||||||
if(hls->vtt_oformat) {
|
if(hls->vtt_oformat) {
|
||||||
@ -395,8 +396,7 @@ static int hls_window(AVFormatContext *s, int last)
|
|||||||
|
|
||||||
set_http_options(&options, hls);
|
set_http_options(&options, hls);
|
||||||
snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", s->filename);
|
snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", s->filename);
|
||||||
if ((ret = ffio_open_whitelist(&out, temp_filename, AVIO_FLAG_WRITE,
|
if ((ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, NULL)) < 0)
|
||||||
&s->interrupt_callback, &options, s->protocol_whitelist)) < 0)
|
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
for (en = hls->segments; en; en = en->next) {
|
for (en = hls->segments; en; en = en->next) {
|
||||||
@ -446,8 +446,7 @@ static int hls_window(AVFormatContext *s, int last)
|
|||||||
avio_printf(out, "#EXT-X-ENDLIST\n");
|
avio_printf(out, "#EXT-X-ENDLIST\n");
|
||||||
|
|
||||||
if( hls->vtt_m3u8_name ) {
|
if( hls->vtt_m3u8_name ) {
|
||||||
if ((ret = ffio_open_whitelist(&sub_out, hls->vtt_m3u8_name, AVIO_FLAG_WRITE,
|
if ((ret = s->io_open(s, &sub_out, hls->vtt_m3u8_name, AVIO_FLAG_WRITE, &options)) < 0)
|
||||||
&s->interrupt_callback, &options, s->protocol_whitelist)) < 0)
|
|
||||||
goto fail;
|
goto fail;
|
||||||
avio_printf(sub_out, "#EXTM3U\n");
|
avio_printf(sub_out, "#EXTM3U\n");
|
||||||
avio_printf(sub_out, "#EXT-X-VERSION:%d\n", version);
|
avio_printf(sub_out, "#EXT-X-VERSION:%d\n", version);
|
||||||
@ -477,8 +476,8 @@ static int hls_window(AVFormatContext *s, int last)
|
|||||||
|
|
||||||
fail:
|
fail:
|
||||||
av_dict_free(&options);
|
av_dict_free(&options);
|
||||||
avio_closep(&out);
|
ff_format_io_close(s, &out);
|
||||||
avio_closep(&sub_out);
|
ff_format_io_close(s, &sub_out);
|
||||||
if (ret >= 0 && use_rename)
|
if (ret >= 0 && use_rename)
|
||||||
ff_rename(temp_filename, s->filename, s);
|
ff_rename(temp_filename, s->filename, s);
|
||||||
return ret;
|
return ret;
|
||||||
@ -543,20 +542,17 @@ static int hls_start(AVFormatContext *s)
|
|||||||
err = AVERROR(ENOMEM);
|
err = AVERROR(ENOMEM);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
err = ffio_open_whitelist(&oc->pb, filename, AVIO_FLAG_WRITE,
|
err = s->io_open(s, &oc->pb, oc->filename, AVIO_FLAG_WRITE, NULL);
|
||||||
&s->interrupt_callback, &options, s->protocol_whitelist);
|
|
||||||
av_free(filename);
|
av_free(filename);
|
||||||
av_dict_free(&options);
|
av_dict_free(&options);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
} else
|
} else
|
||||||
if ((err = ffio_open_whitelist(&oc->pb, oc->filename, AVIO_FLAG_WRITE,
|
if ((err = s->io_open(s, &oc->pb, oc->filename, AVIO_FLAG_WRITE, &options)) < 0)
|
||||||
&s->interrupt_callback, &options, s->protocol_whitelist)) < 0)
|
|
||||||
goto fail;
|
goto fail;
|
||||||
if (c->vtt_basename) {
|
if (c->vtt_basename) {
|
||||||
set_http_options(&options, c);
|
set_http_options(&options, c);
|
||||||
if ((err = ffio_open_whitelist(&vtt_oc->pb, vtt_oc->filename, AVIO_FLAG_WRITE,
|
if ((err = s->io_open(s, &vtt_oc->pb, vtt_oc->filename, AVIO_FLAG_WRITE, &options)) < 0)
|
||||||
&s->interrupt_callback, &options, s->protocol_whitelist)) < 0)
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
av_dict_free(&options);
|
av_dict_free(&options);
|
||||||
@ -795,9 +791,9 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
|
|||||||
av_opt_set(hls->avf->priv_data, "mpegts_flags", "resend_headers", 0);
|
av_opt_set(hls->avf->priv_data, "mpegts_flags", "resend_headers", 0);
|
||||||
hls->number++;
|
hls->number++;
|
||||||
} else {
|
} else {
|
||||||
avio_closep(&oc->pb);
|
ff_format_io_close(s, &oc->pb);
|
||||||
if (hls->vtt_avf)
|
if (hls->vtt_avf)
|
||||||
avio_close(hls->vtt_avf->pb);
|
ff_format_io_close(s, &hls->vtt_avf->pb);
|
||||||
|
|
||||||
ret = hls_start(s);
|
ret = hls_start(s);
|
||||||
}
|
}
|
||||||
@ -828,7 +824,7 @@ static int hls_write_trailer(struct AVFormatContext *s)
|
|||||||
av_write_trailer(oc);
|
av_write_trailer(oc);
|
||||||
if (oc->pb) {
|
if (oc->pb) {
|
||||||
hls->size = avio_tell(hls->avf->pb) - hls->start_pos;
|
hls->size = avio_tell(hls->avf->pb) - hls->start_pos;
|
||||||
avio_closep(&oc->pb);
|
ff_format_io_close(s, &oc->pb);
|
||||||
hls_append_segment(hls, hls->duration, hls->start_pos, hls->size);
|
hls_append_segment(hls, hls->duration, hls->start_pos, hls->size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -836,7 +832,7 @@ static int hls_write_trailer(struct AVFormatContext *s)
|
|||||||
if (vtt_oc->pb)
|
if (vtt_oc->pb)
|
||||||
av_write_trailer(vtt_oc);
|
av_write_trailer(vtt_oc);
|
||||||
hls->size = avio_tell(hls->vtt_avf->pb) - hls->start_pos;
|
hls->size = avio_tell(hls->vtt_avf->pb) - hls->start_pos;
|
||||||
avio_closep(&vtt_oc->pb);
|
ff_format_io_close(s, &vtt_oc->pb);
|
||||||
}
|
}
|
||||||
av_freep(&hls->basename);
|
av_freep(&hls->basename);
|
||||||
avformat_free_context(oc);
|
avformat_free_context(oc);
|
||||||
|
@ -377,10 +377,6 @@ int ff_img_read_packet(AVFormatContext *s1, AVPacket *pkt)
|
|||||||
int size[3] = { 0 }, ret[3] = { 0 };
|
int size[3] = { 0 }, ret[3] = { 0 };
|
||||||
AVIOContext *f[3] = { NULL };
|
AVIOContext *f[3] = { NULL };
|
||||||
AVCodecContext *codec = s1->streams[0]->codec;
|
AVCodecContext *codec = s1->streams[0]->codec;
|
||||||
AVOpenCallback open_func = s1->open_cb;
|
|
||||||
|
|
||||||
if (!open_func)
|
|
||||||
open_func = ffio_open2_wrapper;
|
|
||||||
|
|
||||||
if (!s->is_pipe) {
|
if (!s->is_pipe) {
|
||||||
/* loop over input */
|
/* loop over input */
|
||||||
@ -407,8 +403,7 @@ int ff_img_read_packet(AVFormatContext *s1, AVPacket *pkt)
|
|||||||
!s->loop &&
|
!s->loop &&
|
||||||
!s->split_planes) {
|
!s->split_planes) {
|
||||||
f[i] = s1->pb;
|
f[i] = s1->pb;
|
||||||
} else if (open_func(s1, &f[i], filename, AVIO_FLAG_READ,
|
} else if (s1->io_open(s1, &f[i], filename, AVIO_FLAG_READ, NULL) < 0) {
|
||||||
&s1->interrupt_callback, NULL) < 0) {
|
|
||||||
if (i >= 1)
|
if (i >= 1)
|
||||||
break;
|
break;
|
||||||
av_log(s1, AV_LOG_ERROR, "Could not open file : %s\n",
|
av_log(s1, AV_LOG_ERROR, "Could not open file : %s\n",
|
||||||
@ -496,7 +491,7 @@ int ff_img_read_packet(AVFormatContext *s1, AVPacket *pkt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!s->is_pipe && f[i] != s1->pb)
|
if (!s->is_pipe && f[i] != s1->pb)
|
||||||
avio_closep(&f[i]);
|
ff_format_io_close(s1, &f[i]);
|
||||||
if (ret[i] > 0)
|
if (ret[i] > 0)
|
||||||
pkt->size += ret[i];
|
pkt->size += ret[i];
|
||||||
}
|
}
|
||||||
@ -525,7 +520,7 @@ fail:
|
|||||||
if (!s->is_pipe) {
|
if (!s->is_pipe) {
|
||||||
for (i = 0; i < 3; i++) {
|
for (i = 0; i < 3; i++) {
|
||||||
if (f[i] != s1->pb)
|
if (f[i] != s1->pb)
|
||||||
avio_closep(&f[i]);
|
ff_format_io_close(s1, &f[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
|
@ -111,8 +111,7 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt)
|
|||||||
for (i = 0; i < 4; i++) {
|
for (i = 0; i < 4; i++) {
|
||||||
snprintf(img->tmp[i], sizeof(img->tmp[i]), "%s.tmp", filename);
|
snprintf(img->tmp[i], sizeof(img->tmp[i]), "%s.tmp", filename);
|
||||||
av_strlcpy(img->target[i], filename, sizeof(img->target[i]));
|
av_strlcpy(img->target[i], filename, sizeof(img->target[i]));
|
||||||
if (avio_open2(&pb[i], img->use_rename ? img->tmp[i] : filename, AVIO_FLAG_WRITE,
|
if (s->io_open(s, &pb[i], img->use_rename ? img->tmp[i] : filename, AVIO_FLAG_WRITE, NULL) < 0) {
|
||||||
&s->interrupt_callback, NULL) < 0) {
|
|
||||||
av_log(s, AV_LOG_ERROR, "Could not open file : %s\n", img->use_rename ? img->tmp[i] : filename);
|
av_log(s, AV_LOG_ERROR, "Could not open file : %s\n", img->use_rename ? img->tmp[i] : filename);
|
||||||
return AVERROR(EIO);
|
return AVERROR(EIO);
|
||||||
}
|
}
|
||||||
@ -137,11 +136,11 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt)
|
|||||||
avio_write(pb[0], pkt->data , ysize);
|
avio_write(pb[0], pkt->data , ysize);
|
||||||
avio_write(pb[1], pkt->data + ysize , usize);
|
avio_write(pb[1], pkt->data + ysize , usize);
|
||||||
avio_write(pb[2], pkt->data + ysize + usize, usize);
|
avio_write(pb[2], pkt->data + ysize + usize, usize);
|
||||||
avio_closep(&pb[1]);
|
ff_format_io_close(s, &pb[1]);
|
||||||
avio_closep(&pb[2]);
|
ff_format_io_close(s, &pb[2]);
|
||||||
if (desc->nb_components > 3) {
|
if (desc->nb_components > 3) {
|
||||||
avio_write(pb[3], pkt->data + ysize + 2*usize, ysize);
|
avio_write(pb[3], pkt->data + ysize + 2*usize, ysize);
|
||||||
avio_closep(&pb[3]);
|
ff_format_io_close(s, &pb[3]);
|
||||||
}
|
}
|
||||||
} else if (img->muxer) {
|
} else if (img->muxer) {
|
||||||
int ret;
|
int ret;
|
||||||
@ -179,7 +178,7 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt)
|
|||||||
}
|
}
|
||||||
avio_flush(pb[0]);
|
avio_flush(pb[0]);
|
||||||
if (!img->is_pipe) {
|
if (!img->is_pipe) {
|
||||||
avio_closep(&pb[0]);
|
ff_format_io_close(s, &pb[0]);
|
||||||
for (i = 0; i < nb_renames; i++) {
|
for (i = 0; i < nb_renames; i++) {
|
||||||
ff_rename(img->tmp[i], img->target[i], s);
|
ff_rename(img->tmp[i], img->target[i], s);
|
||||||
}
|
}
|
||||||
|
@ -548,4 +548,10 @@ int ffio_open2_wrapper(struct AVFormatContext *s, AVIOContext **pb, const char *
|
|||||||
*/
|
*/
|
||||||
#define FFERROR_REDO FFERRTAG('R','E','D','O')
|
#define FFERROR_REDO FFERRTAG('R','E','D','O')
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A wrapper around AVFormatContext.io_close that should be used
|
||||||
|
* intead of calling the pointer directly.
|
||||||
|
*/
|
||||||
|
void ff_format_io_close(AVFormatContext *s, AVIOContext **pb);
|
||||||
|
|
||||||
#endif /* AVFORMAT_INTERNAL_H */
|
#endif /* AVFORMAT_INTERNAL_H */
|
||||||
|
@ -344,28 +344,24 @@ static int read_header(AVFormatContext *avctx)
|
|||||||
if (strlen(avctx->filename) > 2) {
|
if (strlen(avctx->filename) > 2) {
|
||||||
int i;
|
int i;
|
||||||
char *filename = av_strdup(avctx->filename);
|
char *filename = av_strdup(avctx->filename);
|
||||||
AVOpenCallback open_func = avctx->open_cb;
|
|
||||||
|
|
||||||
if (!filename)
|
if (!filename)
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
if (!open_func)
|
|
||||||
open_func = ffio_open2_wrapper;
|
|
||||||
|
|
||||||
for (i = 0; i < 100; i++) {
|
for (i = 0; i < 100; i++) {
|
||||||
snprintf(filename + strlen(filename) - 2, 3, "%02d", i);
|
snprintf(filename + strlen(filename) - 2, 3, "%02d", i);
|
||||||
if (open_func(avctx, &mlv->pb[i], filename, AVIO_FLAG_READ, &avctx->interrupt_callback, NULL) < 0)
|
if (avctx->io_open(avctx, &mlv->pb[i], filename, AVIO_FLAG_READ, NULL) < 0)
|
||||||
break;
|
break;
|
||||||
if (check_file_header(mlv->pb[i], guid) < 0) {
|
if (check_file_header(mlv->pb[i], guid) < 0) {
|
||||||
av_log(avctx, AV_LOG_WARNING, "ignoring %s; bad format or guid mismatch\n", filename);
|
av_log(avctx, AV_LOG_WARNING, "ignoring %s; bad format or guid mismatch\n", filename);
|
||||||
avio_closep(&mlv->pb[i]);
|
ff_format_io_close(avctx, &mlv->pb[i]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
av_log(avctx, AV_LOG_INFO, "scanning %s\n", filename);
|
av_log(avctx, AV_LOG_INFO, "scanning %s\n", filename);
|
||||||
ret = scan_file(avctx, vst, ast, i);
|
ret = scan_file(avctx, vst, ast, i);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
av_log(avctx, AV_LOG_WARNING, "ignoring %s; %s\n", filename, av_err2str(ret));
|
av_log(avctx, AV_LOG_WARNING, "ignoring %s; %s\n", filename, av_err2str(ret));
|
||||||
avio_closep(&mlv->pb[i]);
|
ff_format_io_close(avctx, &mlv->pb[i]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -466,7 +462,7 @@ static int read_close(AVFormatContext *s)
|
|||||||
int i;
|
int i;
|
||||||
for (i = 0; i < 100; i++)
|
for (i = 0; i < 100; i++)
|
||||||
if (mlv->pb[i])
|
if (mlv->pb[i])
|
||||||
avio_closep(&mlv->pb[i]);
|
ff_format_io_close(s, &mlv->pb[i]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2922,14 +2922,8 @@ static int test_same_origin(const char *src, const char *ref) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mov_open_dref(MOVContext *c, AVIOContext **pb, const char *src, MOVDref *ref,
|
static int mov_open_dref(MOVContext *c, AVIOContext **pb, const char *src, MOVDref *ref)
|
||||||
AVIOInterruptCB *int_cb)
|
|
||||||
{
|
{
|
||||||
AVOpenCallback open_func = c->fc->open_cb;
|
|
||||||
|
|
||||||
if (!open_func)
|
|
||||||
open_func = ffio_open2_wrapper;
|
|
||||||
|
|
||||||
/* try relative path, we do not try the absolute because it can leak information about our
|
/* try relative path, we do not try the absolute because it can leak information about our
|
||||||
system to an attacker */
|
system to an attacker */
|
||||||
if (ref->nlvl_to > 0 && ref->nlvl_from > 0) {
|
if (ref->nlvl_to > 0 && ref->nlvl_from > 0) {
|
||||||
@ -2962,7 +2956,7 @@ static int mov_open_dref(MOVContext *c, AVIOContext **pb, const char *src, MOVDr
|
|||||||
av_strlcat(filename, "../", sizeof(filename));
|
av_strlcat(filename, "../", sizeof(filename));
|
||||||
|
|
||||||
av_strlcat(filename, ref->path + l + 1, sizeof(filename));
|
av_strlcat(filename, ref->path + l + 1, sizeof(filename));
|
||||||
if (!c->use_absolute_path && !c->fc->open_cb) {
|
if (!c->use_absolute_path) {
|
||||||
int same_origin = test_same_origin(src, filename);
|
int same_origin = test_same_origin(src, filename);
|
||||||
|
|
||||||
if (!same_origin) {
|
if (!same_origin) {
|
||||||
@ -2982,16 +2976,13 @@ static int mov_open_dref(MOVContext *c, AVIOContext **pb, const char *src, MOVDr
|
|||||||
|
|
||||||
if (strlen(filename) + 1 == sizeof(filename))
|
if (strlen(filename) + 1 == sizeof(filename))
|
||||||
return AVERROR(ENOENT);
|
return AVERROR(ENOENT);
|
||||||
if (!open_func(c->fc, pb, filename, AVIO_FLAG_READ, int_cb, NULL))
|
if (!c->fc->io_open(c->fc, pb, filename, AVIO_FLAG_READ, NULL))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else if (c->use_absolute_path) {
|
} else if (c->use_absolute_path) {
|
||||||
av_log(c->fc, AV_LOG_WARNING, "Using absolute path on user request, "
|
av_log(c->fc, AV_LOG_WARNING, "Using absolute path on user request, "
|
||||||
"this is a possible security issue\n");
|
"this is a possible security issue\n");
|
||||||
if (!open_func(c->fc, pb, ref->path, AVIO_FLAG_READ, int_cb, NULL))
|
if (!c->fc->io_open(c->fc, pb, ref->path, AVIO_FLAG_READ, NULL))
|
||||||
return 0;
|
|
||||||
} else if (c->fc->open_cb) {
|
|
||||||
if (!open_func(c->fc, pb, ref->path, AVIO_FLAG_READ, int_cb, NULL))
|
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
av_log(c->fc, AV_LOG_ERROR,
|
av_log(c->fc, AV_LOG_ERROR,
|
||||||
@ -3052,8 +3043,7 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
|
|||||||
if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) {
|
if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) {
|
||||||
MOVDref *dref = &sc->drefs[sc->dref_id - 1];
|
MOVDref *dref = &sc->drefs[sc->dref_id - 1];
|
||||||
if (c->enable_drefs) {
|
if (c->enable_drefs) {
|
||||||
if (mov_open_dref(c, &sc->pb, c->fc->filename, dref,
|
if (mov_open_dref(c, &sc->pb, c->fc->filename, dref) < 0)
|
||||||
&c->fc->interrupt_callback) < 0)
|
|
||||||
av_log(c->fc, AV_LOG_ERROR,
|
av_log(c->fc, AV_LOG_ERROR,
|
||||||
"stream %d, error opening alias: path='%s', dir='%s', "
|
"stream %d, error opening alias: path='%s', dir='%s', "
|
||||||
"filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n",
|
"filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n",
|
||||||
@ -4583,7 +4573,7 @@ static int mov_read_close(AVFormatContext *s)
|
|||||||
sc->drefs_count = 0;
|
sc->drefs_count = 0;
|
||||||
|
|
||||||
if (!sc->pb_is_copied)
|
if (!sc->pb_is_copied)
|
||||||
avio_closep(&sc->pb);
|
ff_format_io_close(s, &sc->pb);
|
||||||
|
|
||||||
sc->pb = NULL;
|
sc->pb = NULL;
|
||||||
av_freep(&sc->chunk_offsets);
|
av_freep(&sc->chunk_offsets);
|
||||||
|
@ -5534,7 +5534,7 @@ static int shift_data(AVFormatContext *s)
|
|||||||
* writing, so we re-open the same output, but for reading. It also avoids
|
* writing, so we re-open the same output, but for reading. It also avoids
|
||||||
* a read/seek/write/seek back and forth. */
|
* a read/seek/write/seek back and forth. */
|
||||||
avio_flush(s->pb);
|
avio_flush(s->pb);
|
||||||
ret = ffio_open_whitelist(&read_pb, s->filename, AVIO_FLAG_READ, &s->interrupt_callback, NULL, s->protocol_whitelist);
|
ret = s->io_open(s, &read_pb, s->filename, AVIO_FLAG_READ, NULL);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
av_log(s, AV_LOG_ERROR, "Unable to re-open %s output file for "
|
av_log(s, AV_LOG_ERROR, "Unable to re-open %s output file for "
|
||||||
"the second pass (faststart)\n", s->filename);
|
"the second pass (faststart)\n", s->filename);
|
||||||
@ -5566,7 +5566,7 @@ static int shift_data(AVFormatContext *s)
|
|||||||
avio_write(s->pb, read_buf[read_buf_id], n);
|
avio_write(s->pb, read_buf[read_buf_id], n);
|
||||||
pos += n;
|
pos += n;
|
||||||
} while (pos < pos_end);
|
} while (pos < pos_end);
|
||||||
avio_close(read_pb);
|
ff_format_io_close(s, &read_pb);
|
||||||
|
|
||||||
end:
|
end:
|
||||||
av_free(buf);
|
av_free(buf);
|
||||||
|
@ -99,12 +99,33 @@ static const AVClass av_format_context_class = {
|
|||||||
.get_category = get_category,
|
.get_category = get_category,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int io_open_default(AVFormatContext *s, AVIOContext **pb,
|
||||||
|
const char *url, int flags, AVDictionary **options)
|
||||||
|
{
|
||||||
|
#if FF_API_OLD_OPEN_CALLBACKS
|
||||||
|
FF_DISABLE_DEPRECATION_WARNINGS
|
||||||
|
if (s->open_cb)
|
||||||
|
return s->open_cb(s, pb, url, flags, &s->interrupt_callback, options);
|
||||||
|
FF_ENABLE_DEPRECATION_WARNINGS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ffio_open_whitelist(pb, url, flags, &s->interrupt_callback, options, s->protocol_whitelist);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void io_close_default(AVFormatContext *s, AVIOContext *pb)
|
||||||
|
{
|
||||||
|
avio_close(pb);
|
||||||
|
}
|
||||||
|
|
||||||
static void avformat_get_context_defaults(AVFormatContext *s)
|
static void avformat_get_context_defaults(AVFormatContext *s)
|
||||||
{
|
{
|
||||||
memset(s, 0, sizeof(AVFormatContext));
|
memset(s, 0, sizeof(AVFormatContext));
|
||||||
|
|
||||||
s->av_class = &av_format_context_class;
|
s->av_class = &av_format_context_class;
|
||||||
|
|
||||||
|
s->io_open = io_open_default;
|
||||||
|
s->io_close = io_close_default;
|
||||||
|
|
||||||
av_opt_set_defaults(s);
|
av_opt_set_defaults(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,6 +156,9 @@ static int segment_mux_init(AVFormatContext *s)
|
|||||||
oc->interrupt_callback = s->interrupt_callback;
|
oc->interrupt_callback = s->interrupt_callback;
|
||||||
oc->max_delay = s->max_delay;
|
oc->max_delay = s->max_delay;
|
||||||
av_dict_copy(&oc->metadata, s->metadata, 0);
|
av_dict_copy(&oc->metadata, s->metadata, 0);
|
||||||
|
oc->opaque = s->opaque;
|
||||||
|
oc->io_close = s->io_close;
|
||||||
|
oc->io_open = s->io_open;
|
||||||
|
|
||||||
for (i = 0; i < s->nb_streams; i++) {
|
for (i = 0; i < s->nb_streams; i++) {
|
||||||
AVStream *st;
|
AVStream *st;
|
||||||
@ -240,8 +243,7 @@ static int segment_start(AVFormatContext *s, int write_header)
|
|||||||
if ((err = set_segment_filename(s)) < 0)
|
if ((err = set_segment_filename(s)) < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
if ((err = ffio_open_whitelist(&oc->pb, oc->filename, AVIO_FLAG_WRITE,
|
if ((err = s->io_open(s, &oc->pb, oc->filename, AVIO_FLAG_WRITE, NULL)) < 0) {
|
||||||
&s->interrupt_callback, NULL, s->protocol_whitelist)) < 0) {
|
|
||||||
av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", oc->filename);
|
av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", oc->filename);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -266,8 +268,7 @@ static int segment_list_open(AVFormatContext *s)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
snprintf(seg->temp_list_filename, sizeof(seg->temp_list_filename), seg->use_rename ? "%s.tmp" : "%s", seg->list);
|
snprintf(seg->temp_list_filename, sizeof(seg->temp_list_filename), seg->use_rename ? "%s.tmp" : "%s", seg->list);
|
||||||
ret = ffio_open_whitelist(&seg->list_pb, seg->temp_list_filename, AVIO_FLAG_WRITE,
|
ret = s->io_open(s, &seg->list_pb, seg->temp_list_filename, AVIO_FLAG_WRITE, NULL);
|
||||||
&s->interrupt_callback, NULL, s->protocol_whitelist);
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
av_log(s, AV_LOG_ERROR, "Failed to open segment list '%s'\n", seg->list);
|
av_log(s, AV_LOG_ERROR, "Failed to open segment list '%s'\n", seg->list);
|
||||||
return ret;
|
return ret;
|
||||||
@ -376,7 +377,7 @@ static int segment_end(AVFormatContext *s, int write_trailer, int is_last)
|
|||||||
segment_list_print_entry(seg->list_pb, seg->list_type, entry, s);
|
segment_list_print_entry(seg->list_pb, seg->list_type, entry, s);
|
||||||
if (seg->list_type == LIST_TYPE_M3U8 && is_last)
|
if (seg->list_type == LIST_TYPE_M3U8 && is_last)
|
||||||
avio_printf(seg->list_pb, "#EXT-X-ENDLIST\n");
|
avio_printf(seg->list_pb, "#EXT-X-ENDLIST\n");
|
||||||
avio_closep(&seg->list_pb);
|
ff_format_io_close(s, &seg->list_pb);
|
||||||
if (seg->use_rename)
|
if (seg->use_rename)
|
||||||
ff_rename(seg->temp_list_filename, seg->list, s);
|
ff_rename(seg->temp_list_filename, seg->list, s);
|
||||||
} else {
|
} else {
|
||||||
@ -390,7 +391,7 @@ static int segment_end(AVFormatContext *s, int write_trailer, int is_last)
|
|||||||
seg->segment_count++;
|
seg->segment_count++;
|
||||||
|
|
||||||
end:
|
end:
|
||||||
avio_closep(&oc->pb);
|
ff_format_io_close(oc, &oc->pb);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -591,7 +592,7 @@ static int select_reference_stream(AVFormatContext *s)
|
|||||||
|
|
||||||
static void seg_free_context(SegmentContext *seg)
|
static void seg_free_context(SegmentContext *seg)
|
||||||
{
|
{
|
||||||
avio_closep(&seg->list_pb);
|
ff_format_io_close(seg->avf, &seg->list_pb);
|
||||||
avformat_free_context(seg->avf);
|
avformat_free_context(seg->avf);
|
||||||
seg->avf = NULL;
|
seg->avf = NULL;
|
||||||
}
|
}
|
||||||
@ -700,8 +701,7 @@ static int seg_write_header(AVFormatContext *s)
|
|||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (seg->write_header_trailer) {
|
if (seg->write_header_trailer) {
|
||||||
if ((ret = ffio_open_whitelist(&oc->pb, seg->header_filename ? seg->header_filename : oc->filename, AVIO_FLAG_WRITE,
|
if ((ret = s->io_open(s, &oc->pb, oc->filename, AVIO_FLAG_WRITE, NULL)) < 0) {
|
||||||
&s->interrupt_callback, NULL, s->protocol_whitelist)) < 0) {
|
|
||||||
av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", oc->filename);
|
av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", oc->filename);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@ -722,7 +722,7 @@ static int seg_write_header(AVFormatContext *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
avio_closep(&oc->pb);
|
ff_format_io_close(oc, &oc->pb);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
seg->segment_frame_count = 0;
|
seg->segment_frame_count = 0;
|
||||||
@ -740,12 +740,11 @@ static int seg_write_header(AVFormatContext *s)
|
|||||||
if (!seg->write_header_trailer || seg->header_filename) {
|
if (!seg->write_header_trailer || seg->header_filename) {
|
||||||
if (seg->header_filename) {
|
if (seg->header_filename) {
|
||||||
av_write_frame(oc, NULL);
|
av_write_frame(oc, NULL);
|
||||||
avio_closep(&oc->pb);
|
ff_format_io_close(oc, &oc->pb);
|
||||||
} else {
|
} else {
|
||||||
close_null_ctxp(&oc->pb);
|
close_null_ctxp(&oc->pb);
|
||||||
}
|
}
|
||||||
if ((ret = ffio_open_whitelist(&oc->pb, oc->filename, AVIO_FLAG_WRITE,
|
if ((ret = oc->io_open(oc, &oc->pb, oc->filename, AVIO_FLAG_WRITE, NULL)) < 0)
|
||||||
&s->interrupt_callback, NULL, s->protocol_whitelist)) < 0)
|
|
||||||
goto fail;
|
goto fail;
|
||||||
if (!seg->individual_header_trailer)
|
if (!seg->individual_header_trailer)
|
||||||
oc->pb->seekable = 0;
|
oc->pb->seekable = 0;
|
||||||
@ -891,7 +890,7 @@ static int seg_write_trailer(struct AVFormatContext *s)
|
|||||||
}
|
}
|
||||||
fail:
|
fail:
|
||||||
if (seg->list)
|
if (seg->list)
|
||||||
avio_closep(&seg->list_pb);
|
ff_format_io_close(s, &seg->list_pb);
|
||||||
|
|
||||||
av_dict_free(&seg->format_options);
|
av_dict_free(&seg->format_options);
|
||||||
av_opt_free(seg);
|
av_opt_free(seg);
|
||||||
|
@ -223,7 +223,7 @@ static int write_manifest(AVFormatContext *s, int final)
|
|||||||
|
|
||||||
snprintf(filename, sizeof(filename), "%s/Manifest", s->filename);
|
snprintf(filename, sizeof(filename), "%s/Manifest", s->filename);
|
||||||
snprintf(temp_filename, sizeof(temp_filename), "%s/Manifest.tmp", s->filename);
|
snprintf(temp_filename, sizeof(temp_filename), "%s/Manifest.tmp", s->filename);
|
||||||
ret = ffio_open_whitelist(&out, temp_filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL, s->protocol_whitelist);
|
ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, NULL);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename);
|
av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename);
|
||||||
return ret;
|
return ret;
|
||||||
@ -285,7 +285,7 @@ static int write_manifest(AVFormatContext *s, int final)
|
|||||||
}
|
}
|
||||||
avio_printf(out, "</SmoothStreamingMedia>\n");
|
avio_printf(out, "</SmoothStreamingMedia>\n");
|
||||||
avio_flush(out);
|
avio_flush(out);
|
||||||
avio_close(out);
|
ff_format_io_close(s, &out);
|
||||||
return ff_rename(temp_filename, filename, s);
|
return ff_rename(temp_filename, filename, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -412,7 +412,7 @@ static int parse_fragment(AVFormatContext *s, const char *filename, int64_t *sta
|
|||||||
AVIOContext *in;
|
AVIOContext *in;
|
||||||
int ret;
|
int ret;
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
if ((ret = ffio_open_whitelist(&in, filename, AVIO_FLAG_READ, &s->interrupt_callback, NULL, s->protocol_whitelist)) < 0)
|
if ((ret = s->io_open(s, &in, filename, AVIO_FLAG_READ, NULL)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
ret = AVERROR(EIO);
|
ret = AVERROR(EIO);
|
||||||
*moof_size = avio_rb32(in);
|
*moof_size = avio_rb32(in);
|
||||||
@ -453,7 +453,7 @@ static int parse_fragment(AVFormatContext *s, const char *filename, int64_t *sta
|
|||||||
avio_seek(in, end, SEEK_SET);
|
avio_seek(in, end, SEEK_SET);
|
||||||
}
|
}
|
||||||
fail:
|
fail:
|
||||||
avio_close(in);
|
ff_format_io_close(s, &in);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -489,10 +489,10 @@ static int copy_moof(AVFormatContext *s, const char* infile, const char *outfile
|
|||||||
{
|
{
|
||||||
AVIOContext *in, *out;
|
AVIOContext *in, *out;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
if ((ret = ffio_open_whitelist(&in, infile, AVIO_FLAG_READ, &s->interrupt_callback, NULL, s->protocol_whitelist)) < 0)
|
if ((ret = s->io_open(s, &in, infile, AVIO_FLAG_READ, NULL)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
if ((ret = ffio_open_whitelist(&out, outfile, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL, s->protocol_whitelist)) < 0) {
|
if ((ret = s->io_open(s, &out, outfile, AVIO_FLAG_WRITE, NULL)) < 0) {
|
||||||
avio_close(in);
|
ff_format_io_close(s, &in);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
while (size > 0) {
|
while (size > 0) {
|
||||||
@ -507,8 +507,8 @@ static int copy_moof(AVFormatContext *s, const char* infile, const char *outfile
|
|||||||
size -= n;
|
size -= n;
|
||||||
}
|
}
|
||||||
avio_flush(out);
|
avio_flush(out);
|
||||||
avio_close(out);
|
ff_format_io_close(s, &out);
|
||||||
avio_close(in);
|
ff_format_io_close(s, &in);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "libavutil/avutil.h"
|
#include "libavutil/avutil.h"
|
||||||
#include "libavutil/avstring.h"
|
#include "libavutil/avstring.h"
|
||||||
#include "libavutil/opt.h"
|
#include "libavutil/opt.h"
|
||||||
|
#include "internal.h"
|
||||||
#include "avformat.h"
|
#include "avformat.h"
|
||||||
#include "avio_internal.h"
|
#include "avio_internal.h"
|
||||||
|
|
||||||
@ -165,6 +166,9 @@ static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto end;
|
goto end;
|
||||||
av_dict_copy(&avf2->metadata, avf->metadata, 0);
|
av_dict_copy(&avf2->metadata, avf->metadata, 0);
|
||||||
|
avf2->opaque = avf->opaque;
|
||||||
|
avf2->io_open = avf->io_open;
|
||||||
|
avf2->io_close = avf->io_close;
|
||||||
|
|
||||||
tee_slave->stream_map = av_calloc(avf->nb_streams, sizeof(*tee_slave->stream_map));
|
tee_slave->stream_map = av_calloc(avf->nb_streams, sizeof(*tee_slave->stream_map));
|
||||||
if (!tee_slave->stream_map) {
|
if (!tee_slave->stream_map) {
|
||||||
@ -227,9 +231,7 @@ static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!(avf2->oformat->flags & AVFMT_NOFILE)) {
|
if (!(avf2->oformat->flags & AVFMT_NOFILE)) {
|
||||||
if ((ret = ffio_open_whitelist(&avf2->pb, filename, AVIO_FLAG_WRITE,
|
if ((ret = avf2->io_open(avf2, &avf2->pb, filename, AVIO_FLAG_WRITE, NULL)) < 0) {
|
||||||
&avf->interrupt_callback, NULL,
|
|
||||||
avf->protocol_whitelist)) < 0) {
|
|
||||||
av_log(avf, AV_LOG_ERROR, "Slave '%s': error opening: %s\n",
|
av_log(avf, AV_LOG_ERROR, "Slave '%s': error opening: %s\n",
|
||||||
slave, av_err2str(ret));
|
slave, av_err2str(ret));
|
||||||
goto end;
|
goto end;
|
||||||
@ -329,7 +331,7 @@ static void close_slaves(AVFormatContext *avf)
|
|||||||
av_freep(&tee->slaves[i].stream_map);
|
av_freep(&tee->slaves[i].stream_map);
|
||||||
av_freep(&tee->slaves[i].bsfs);
|
av_freep(&tee->slaves[i].bsfs);
|
||||||
|
|
||||||
avio_closep(&avf2->pb);
|
ff_format_io_close(avf2, &avf2->pb);
|
||||||
avformat_free_context(avf2);
|
avformat_free_context(avf2);
|
||||||
tee->slaves[i].avf = NULL;
|
tee->slaves[i].avf = NULL;
|
||||||
}
|
}
|
||||||
@ -420,11 +422,8 @@ static int tee_write_trailer(AVFormatContext *avf)
|
|||||||
if ((ret = av_write_trailer(avf2)) < 0)
|
if ((ret = av_write_trailer(avf2)) < 0)
|
||||||
if (!ret_all)
|
if (!ret_all)
|
||||||
ret_all = ret;
|
ret_all = ret;
|
||||||
if (!(avf2->oformat->flags & AVFMT_NOFILE)) {
|
if (!(avf2->oformat->flags & AVFMT_NOFILE))
|
||||||
if ((ret = avio_closep(&avf2->pb)) < 0)
|
ff_format_io_close(avf2, &avf2->pb);
|
||||||
if (!ret_all)
|
|
||||||
ret_all = ret;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
close_slaves(avf);
|
close_slaves(avf);
|
||||||
return ret_all;
|
return ret_all;
|
||||||
|
@ -112,7 +112,11 @@ MAKE_ACCESSORS(AVFormatContext, format, AVCodec *, data_codec)
|
|||||||
MAKE_ACCESSORS(AVFormatContext, format, int, metadata_header_padding)
|
MAKE_ACCESSORS(AVFormatContext, format, int, metadata_header_padding)
|
||||||
MAKE_ACCESSORS(AVFormatContext, format, void *, opaque)
|
MAKE_ACCESSORS(AVFormatContext, format, void *, opaque)
|
||||||
MAKE_ACCESSORS(AVFormatContext, format, av_format_control_message, control_message_cb)
|
MAKE_ACCESSORS(AVFormatContext, format, av_format_control_message, control_message_cb)
|
||||||
|
#if FF_API_OLD_OPEN_CALLBACKS
|
||||||
|
FF_DISABLE_DEPRECATION_WARNINGS
|
||||||
MAKE_ACCESSORS(AVFormatContext, format, AVOpenCallback, open_cb)
|
MAKE_ACCESSORS(AVFormatContext, format, AVOpenCallback, open_cb)
|
||||||
|
FF_ENABLE_DEPRECATION_WARNINGS
|
||||||
|
#endif
|
||||||
|
|
||||||
int64_t av_stream_get_end_pts(const AVStream *st)
|
int64_t av_stream_get_end_pts(const AVStream *st)
|
||||||
{
|
{
|
||||||
@ -356,9 +360,7 @@ static int init_input(AVFormatContext *s, const char *filename,
|
|||||||
(!s->iformat && (s->iformat = av_probe_input_format2(&pd, 0, &score))))
|
(!s->iformat && (s->iformat = av_probe_input_format2(&pd, 0, &score))))
|
||||||
return score;
|
return score;
|
||||||
|
|
||||||
if ((ret = ffio_open_whitelist(&s->pb, filename, AVIO_FLAG_READ | s->avio_flags,
|
if ((ret = s->io_open(s, &s->pb, filename, AVIO_FLAG_READ | s->avio_flags, options)) < 0)
|
||||||
&s->interrupt_callback, options,
|
|
||||||
s->protocol_whitelist)) < 0)
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (s->iformat)
|
if (s->iformat)
|
||||||
@ -4742,3 +4744,10 @@ int av_apply_bitstream_filters(AVCodecContext *codec, AVPacket *pkt,
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ff_format_io_close(AVFormatContext *s, AVIOContext **pb)
|
||||||
|
{
|
||||||
|
if (*pb)
|
||||||
|
s->io_close(s, *pb);
|
||||||
|
*pb = NULL;
|
||||||
|
}
|
||||||
|
@ -30,8 +30,8 @@
|
|||||||
#include "libavutil/version.h"
|
#include "libavutil/version.h"
|
||||||
|
|
||||||
#define LIBAVFORMAT_VERSION_MAJOR 57
|
#define LIBAVFORMAT_VERSION_MAJOR 57
|
||||||
#define LIBAVFORMAT_VERSION_MINOR 24
|
#define LIBAVFORMAT_VERSION_MINOR 25
|
||||||
#define LIBAVFORMAT_VERSION_MICRO 101
|
#define LIBAVFORMAT_VERSION_MICRO 100
|
||||||
|
|
||||||
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
|
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
|
||||||
LIBAVFORMAT_VERSION_MINOR, \
|
LIBAVFORMAT_VERSION_MINOR, \
|
||||||
@ -71,6 +71,9 @@
|
|||||||
#ifndef FF_API_COMPUTE_PKT_FIELDS2
|
#ifndef FF_API_COMPUTE_PKT_FIELDS2
|
||||||
#define FF_API_COMPUTE_PKT_FIELDS2 (LIBAVFORMAT_VERSION_MAJOR < 58)
|
#define FF_API_COMPUTE_PKT_FIELDS2 (LIBAVFORMAT_VERSION_MAJOR < 58)
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef FF_API_OLD_OPEN_CALLBACKS
|
||||||
|
#define FF_API_OLD_OPEN_CALLBACKS (LIBAVFORMAT_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef FF_API_R_FRAME_RATE
|
#ifndef FF_API_R_FRAME_RATE
|
||||||
#define FF_API_R_FRAME_RATE 1
|
#define FF_API_R_FRAME_RATE 1
|
||||||
|
@ -126,8 +126,7 @@ static int webm_chunk_write_header(AVFormatContext *s)
|
|||||||
ret = get_chunk_filename(s, 1, oc->filename);
|
ret = get_chunk_filename(s, 1, oc->filename);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
ret = ffio_open_whitelist(&oc->pb, oc->filename, AVIO_FLAG_WRITE,
|
ret = s->io_open(s, &oc->pb, oc->filename, AVIO_FLAG_WRITE, NULL);
|
||||||
&s->interrupt_callback, NULL, s->protocol_whitelist);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -135,7 +134,7 @@ static int webm_chunk_write_header(AVFormatContext *s)
|
|||||||
ret = oc->oformat->write_header(oc);
|
ret = oc->oformat->write_header(oc);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
avio_close(oc->pb);
|
ff_format_io_close(s, &oc->pb);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,14 +169,11 @@ static int chunk_end(AVFormatContext *s)
|
|||||||
ret = get_chunk_filename(s, 0, filename);
|
ret = get_chunk_filename(s, 0, filename);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
ret = ffio_open_whitelist(&pb, filename, AVIO_FLAG_WRITE,
|
ret = s->io_open(s, &pb, filename, AVIO_FLAG_WRITE, NULL);
|
||||||
&s->interrupt_callback, NULL, s->protocol_whitelist);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
avio_write(pb, buffer, buffer_size);
|
avio_write(pb, buffer, buffer_size);
|
||||||
ret = avio_close(pb);
|
ff_format_io_close(s, &pb);
|
||||||
if (ret < 0)
|
|
||||||
goto fail;
|
|
||||||
oc->pb = NULL;
|
oc->pb = NULL;
|
||||||
fail:
|
fail:
|
||||||
av_free(buffer);
|
av_free(buffer);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user