Skip to content

Commit

Permalink
Merge commit '9f61abc8111c7c43f49ca012e957a108b9cc7610'
Browse files Browse the repository at this point in the history
This also deprecates our old duplicated callbacks.

* commit '9f61abc8111c7c43f49ca012e957a108b9cc7610':
  lavf: allow custom IO for all files

Merged-by: Derek Buitenhuis <derek.buitenhuis@gmail.com>
  • Loading branch information
dwbuiten committed Feb 10, 2016
2 parents d94b11a + 9f61abc commit bc9a596
Show file tree
Hide file tree
Showing 19 changed files with 177 additions and 132 deletions.
3 changes: 3 additions & 0 deletions doc/APIchanges
Expand Up @@ -15,6 +15,9 @@ libavutil: 2015-08-28

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
Add protocol_whitelist to AVFormatContext, AVIOContext

Expand Down
40 changes: 37 additions & 3 deletions libavformat/avformat.h
Expand Up @@ -1780,7 +1780,6 @@ typedef struct AVFormatContext {
/**
* User data.
* 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;

Expand Down Expand Up @@ -1811,6 +1810,7 @@ typedef struct AVFormatContext {
*/
enum AVCodecID data_codec_id;

#if FF_API_OLD_OPEN_CALLBACKS
/**
* Called to open further IO contexts when needed for demuxing.
*
Expand All @@ -1825,15 +1825,47 @@ typedef struct AVFormatContext {
* @See av_format_set_open_cb()
*
* 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);
#endif

/**
* ',' separated list of allowed protocols.
* - encoding: unused
* - decoding: set by user through AVOptions (NO direct access)
*/
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;

int av_format_get_probe_score(const AVFormatContext *s);
Expand All @@ -1851,8 +1883,10 @@ void * av_format_get_opaque(const AVFormatContext *s);
void av_format_set_opaque(AVFormatContext *s, void *opaque);
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);
AVOpenCallback av_format_get_open_cb(const AVFormatContext *s);
void av_format_set_open_cb(AVFormatContext *s, AVOpenCallback callback);
#if FF_API_OLD_OPEN_CALLBACKS
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
Expand Down
8 changes: 5 additions & 3 deletions libavformat/dashenc.c
Expand Up @@ -448,8 +448,7 @@ static int write_manifest(AVFormatContext *s, int final)
AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0);

snprintf(temp_filename, sizeof(temp_filename), "%s.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) {
av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename);
return ret;
Expand Down Expand Up @@ -549,7 +548,7 @@ static int write_manifest(AVFormatContext *s, int final)
avio_printf(out, "\t</Period>\n");
avio_printf(out, "</MPD>\n");
avio_flush(out);
avio_close(out);
ff_format_io_close(s, &out);
return ff_rename(temp_filename, s->filename, s);
}

Expand Down Expand Up @@ -624,6 +623,9 @@ static int dash_write_header(AVFormatContext *s)
os->ctx = ctx;
ctx->oformat = oformat;
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))) {
ret = AVERROR(ENOMEM);
Expand Down
24 changes: 11 additions & 13 deletions libavformat/hdsenc.c
Expand Up @@ -140,7 +140,8 @@ static void hds_free(AVFormatContext *s)
return;
for (i = 0; i < s->nb_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)
av_write_trailer(os->ctx);
if (os->ctx)
Expand Down Expand Up @@ -170,8 +171,7 @@ static int write_manifest(AVFormatContext *s, int final)

snprintf(filename, sizeof(filename), "%s/index.f4m", s->filename);
snprintf(temp_filename, sizeof(temp_filename), "%s/index.f4m.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) {
av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename);
return ret;
Expand All @@ -189,7 +189,7 @@ static int write_manifest(AVFormatContext *s, int final)
int b64_size = AV_BASE64_SIZE(os->metadata_size);
char *base64 = av_malloc(b64_size);
if (!base64) {
avio_close(out);
ff_format_io_close(s, &out);
return AVERROR(ENOMEM);
}
av_base64_encode(base64, b64_size, os->metadata, os->metadata_size);
Expand All @@ -202,7 +202,7 @@ static int write_manifest(AVFormatContext *s, int final)
}
avio_printf(out, "</manifest>\n");
avio_flush(out);
avio_close(out);
ff_format_io_close(s, &out);
return ff_rename(temp_filename, filename, s);
}

Expand Down Expand Up @@ -239,8 +239,7 @@ static int write_abst(AVFormatContext *s, OutputStream *os, int final)
"%s/stream%d.abst", s->filename, index);
snprintf(temp_filename, sizeof(temp_filename),
"%s/stream%d.abst.tmp", s->filename, index);
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) {
av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename);
return ret;
Expand Down Expand Up @@ -283,15 +282,14 @@ static int write_abst(AVFormatContext *s, OutputStream *os, int final)
}
update_size(out, afrt_pos);
update_size(out, 0);
avio_close(out);
ff_format_io_close(s, &out);
return ff_rename(temp_filename, filename, s);
}

static int init_file(AVFormatContext *s, OutputStream *os, int64_t start_ts)
{
int ret, i;
ret = ffio_open_whitelist(&os->out, os->temp_filename, AVIO_FLAG_WRITE,
&s->interrupt_callback, NULL, s->protocol_whitelist);
ret = s->io_open(s, &os->out, os->temp_filename, AVIO_FLAG_WRITE, NULL);
if (ret < 0)
return ret;
avio_wb32(os->out, 0);
Expand All @@ -304,13 +302,13 @@ static int init_file(AVFormatContext *s, OutputStream *os, int64_t start_ts)
return 0;
}

static void close_file(OutputStream *os)
static void close_file(AVFormatContext *s, OutputStream *os)
{
int64_t pos = avio_tell(os->out);
avio_seek(os->out, 0, SEEK_SET);
avio_wb32(os->out, pos);
avio_flush(os->out);
avio_closep(&os->out);
ff_format_io_close(s, &os->out);
}

static int hds_write_header(AVFormatContext *s)
Expand Down Expand Up @@ -475,7 +473,7 @@ static int hds_flush(AVFormatContext *s, OutputStream *os, int final,

avio_flush(os->ctx->pb);
os->packets_written = 0;
close_file(os);
close_file(s, os);

snprintf(target_filename, sizeof(target_filename),
"%s/stream%dSeg1-Frag%d", s->filename, index, os->fragment_index);
Expand Down
11 changes: 5 additions & 6 deletions libavformat/hls.c
Expand Up @@ -180,7 +180,7 @@ struct variant {

typedef struct HLSContext {
AVClass *class;
AVFormatContext *avfmt;
AVFormatContext *ctx;
int n_variants;
struct variant **variants;
int n_playlists;
Expand Down Expand Up @@ -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, 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) {
// update cookies on http response with setcookies.
URLContext *u = *uc;
Expand Down Expand Up @@ -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, "http_proxy", c->http_proxy, 0);

ret = ffio_open_whitelist(&in, url, AVIO_FLAG_READ,
c->interrupt_callback, &opts, c->avfmt->protocol_whitelist);
ret = c->ctx->io_open(c->ctx, &in, url, AVIO_FLAG_READ, &opts);
av_dict_free(&opts);
if (ret < 0)
return ret;
Expand Down Expand Up @@ -849,7 +848,7 @@ static int parse_playlist(HLSContext *c, const char *url,
fail:
av_free(new_url);
if (close_in)
avio_close(in);
ff_format_io_close(c->ctx, &in);
return ret;
}

Expand Down Expand Up @@ -1518,7 +1517,7 @@ static int hls_read_header(AVFormatContext *s)
HLSContext *c = s->priv_data;
int ret = 0, i, j, stream_offset = 0;

c->avfmt = s;
c->ctx = s;
c->interrupt_callback = &s->interrupt_callback;
c->strict_std_compliance = s->strict_std_compliance;

Expand Down
40 changes: 18 additions & 22 deletions libavformat/hlsenc.c
Expand Up @@ -210,8 +210,7 @@ static int hls_encryption_start(AVFormatContext *s)
AVIOContext *pb;
uint8_t key[KEYSIZE];

if ((ret = ffio_open_whitelist(&pb, hls->key_info_file, AVIO_FLAG_READ,
&s->interrupt_callback, NULL, s->protocol_whitelist)) < 0) {
if ((ret = s->io_open(s, &pb, hls->key_info_file, AVIO_FLAG_READ, NULL)) < 0) {
av_log(hls, AV_LOG_ERROR,
"error opening key info file %s\n", hls->key_info_file);
return ret;
Expand All @@ -226,7 +225,7 @@ static int hls_encryption_start(AVFormatContext *s)
ff_get_line(pb, hls->iv_string, sizeof(hls->iv_string));
hls->iv_string[strcspn(hls->iv_string, "\r\n")] = '\0';

avio_close(pb);
ff_format_io_close(s, &pb);

if (!*hls->key_uri) {
av_log(hls, AV_LOG_ERROR, "no key URI specified in key info file\n");
Expand All @@ -238,14 +237,13 @@ static int hls_encryption_start(AVFormatContext *s)
return AVERROR(EINVAL);
}

if ((ret = ffio_open_whitelist(&pb, hls->key_file, AVIO_FLAG_READ,
&s->interrupt_callback, NULL, s->protocol_whitelist)) < 0) {
if ((ret = s->io_open(s, &pb, hls->key_file, AVIO_FLAG_READ, NULL)) < 0) {
av_log(hls, AV_LOG_ERROR, "error opening key file %s\n", hls->key_file);
return ret;
}

ret = avio_read(pb, key, sizeof(key));
avio_close(pb);
ff_format_io_close(s, &pb);
if (ret != sizeof(key)) {
av_log(hls, AV_LOG_ERROR, "error reading key file %s\n", hls->key_file);
if (ret >= 0 || ret == AVERROR_EOF)
Expand All @@ -272,6 +270,9 @@ static int hls_mux_init(AVFormatContext *s)
oc->oformat = hls->oformat;
oc->interrupt_callback = s->interrupt_callback;
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);

if(hls->vtt_oformat) {
Expand Down Expand Up @@ -395,8 +396,7 @@ static int hls_window(AVFormatContext *s, int last)

set_http_options(&options, hls);
snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", s->filename);
if ((ret = ffio_open_whitelist(&out, temp_filename, AVIO_FLAG_WRITE,
&s->interrupt_callback, &options, s->protocol_whitelist)) < 0)
if ((ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, NULL)) < 0)
goto fail;

for (en = hls->segments; en; en = en->next) {
Expand Down Expand Up @@ -446,8 +446,7 @@ static int hls_window(AVFormatContext *s, int last)
avio_printf(out, "#EXT-X-ENDLIST\n");

if( hls->vtt_m3u8_name ) {
if ((ret = ffio_open_whitelist(&sub_out, hls->vtt_m3u8_name, AVIO_FLAG_WRITE,
&s->interrupt_callback, &options, s->protocol_whitelist)) < 0)
if ((ret = s->io_open(s, &sub_out, hls->vtt_m3u8_name, AVIO_FLAG_WRITE, &options)) < 0)
goto fail;
avio_printf(sub_out, "#EXTM3U\n");
avio_printf(sub_out, "#EXT-X-VERSION:%d\n", version);
Expand Down Expand Up @@ -477,8 +476,8 @@ static int hls_window(AVFormatContext *s, int last)

fail:
av_dict_free(&options);
avio_closep(&out);
avio_closep(&sub_out);
ff_format_io_close(s, &out);
ff_format_io_close(s, &sub_out);
if (ret >= 0 && use_rename)
ff_rename(temp_filename, s->filename, s);
return ret;
Expand Down Expand Up @@ -543,20 +542,17 @@ static int hls_start(AVFormatContext *s)
err = AVERROR(ENOMEM);
goto fail;
}
err = ffio_open_whitelist(&oc->pb, filename, AVIO_FLAG_WRITE,
&s->interrupt_callback, &options, s->protocol_whitelist);
err = s->io_open(s, &oc->pb, oc->filename, AVIO_FLAG_WRITE, NULL);
av_free(filename);
av_dict_free(&options);
if (err < 0)
return err;
} else
if ((err = ffio_open_whitelist(&oc->pb, oc->filename, AVIO_FLAG_WRITE,
&s->interrupt_callback, &options, s->protocol_whitelist)) < 0)
if ((err = s->io_open(s, &oc->pb, oc->filename, AVIO_FLAG_WRITE, &options)) < 0)
goto fail;
if (c->vtt_basename) {
set_http_options(&options, c);
if ((err = ffio_open_whitelist(&vtt_oc->pb, vtt_oc->filename, AVIO_FLAG_WRITE,
&s->interrupt_callback, &options, s->protocol_whitelist)) < 0)
if ((err = s->io_open(s, &vtt_oc->pb, vtt_oc->filename, AVIO_FLAG_WRITE, &options)) < 0)
goto fail;
}
av_dict_free(&options);
Expand Down Expand Up @@ -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);
hls->number++;
} else {
avio_closep(&oc->pb);
ff_format_io_close(s, &oc->pb);
if (hls->vtt_avf)
avio_close(hls->vtt_avf->pb);
ff_format_io_close(s, &hls->vtt_avf->pb);

ret = hls_start(s);
}
Expand Down Expand Up @@ -828,15 +824,15 @@ static int hls_write_trailer(struct AVFormatContext *s)
av_write_trailer(oc);
if (oc->pb) {
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);
}

if (vtt_oc) {
if (vtt_oc->pb)
av_write_trailer(vtt_oc);
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);
avformat_free_context(oc);
Expand Down

0 comments on commit bc9a596

Please sign in to comment.