avformat: introduce AVFormatContext io_close2 which returns an int

Otherwise there is no way to detect an error returned by avio_close() because
ff_format_io_close cannot get the return value.

Checking the return value of the close function is important in order to check
if all data was successfully written and the underlying close() operation was
successful.

It can also be useful even for read mode because it can return any pending
AVIOContext error, so the user don't have to manually check AVIOContext->error.

In order to still support if the user overrides io_close, the generic code only
uses io_close2 if io_close is either NULL or the default io_close callback.

Signed-off-by: Marton Balint <cus@passwd.hu>
pull/376/head
Marton Balint 3 years ago
parent 8d66a07d65
commit 64834bb86a
  1. 3
      doc/APIchanges
  2. 13
      libavformat/avformat.h
  3. 1
      libavformat/dashenc.c
  4. 1
      libavformat/fifo.c
  5. 1
      libavformat/hlsenc.c
  6. 10
      libavformat/internal.h
  7. 7
      libavformat/options.c
  8. 1
      libavformat/segment.c
  9. 1
      libavformat/tee.c
  10. 17
      libavformat/utils.c
  11. 4
      libavformat/version.h

@ -14,6 +14,9 @@ libavutil: 2021-04-27
API changes, most recent first:
2021-12-xx - xxxxxxxxxx - lavf 59.10.100 - avformat.h
Add AVFormatContext io_close2 which returns an int
2021-11-10 - xxxxxxxxxx - lavu 57.11.100 - hwcontext_vulkan.h
Add AVVkFrame.offset and AVVulkanFramesContext.flags.

@ -1786,6 +1786,19 @@ typedef struct AVFormatContext {
* - decoding: set by user
*/
int max_probe_packets;
/**
* A callback for closing the streams opened with AVFormatContext.io_open().
*
* Using this is preferred over io_close, because this can return an error.
* Therefore this callback is used instead of io_close by the generic
* libavformat code if io_close is NULL or the default.
*
* @param s the format context
* @param pb IO context to be closed and freed
* @return 0 on success, a negative AVERROR code on failure
*/
int (*io_close2)(struct AVFormatContext *s, AVIOContext *pb);
} AVFormatContext;
/**

@ -1546,6 +1546,7 @@ static int dash_init(AVFormatContext *s)
ctx->interrupt_callback = s->interrupt_callback;
ctx->opaque = s->opaque;
ctx->io_close = s->io_close;
ctx->io_close2 = s->io_close2;
ctx->io_open = s->io_open;
ctx->strict_std_compliance = s->strict_std_compliance;

@ -499,6 +499,7 @@ static int fifo_mux_init(AVFormatContext *avf, const AVOutputFormat *oformat,
return ret;
avf2->opaque = avf->opaque;
avf2->io_close = avf->io_close;
avf2->io_close2 = avf->io_close2;
avf2->io_open = avf->io_open;
avf2->flags = avf->flags;

@ -866,6 +866,7 @@ static int hls_mux_init(AVFormatContext *s, VariantStream *vs)
oc->opaque = s->opaque;
oc->io_open = s->io_open;
oc->io_close = s->io_close;
oc->io_close2 = s->io_close2;
oc->strict_std_compliance = s->strict_std_compliance;
av_dict_copy(&oc->metadata, s->metadata, 0);

@ -916,8 +916,16 @@ int ff_format_output_open(AVFormatContext *s, const char *url, AVDictionary **op
/*
* A wrapper around AVFormatContext.io_close that should be used
* instead of calling the pointer directly.
*
* @param s AVFormatContext
* @param *pb the AVIOContext to be closed and freed. Can be NULL.
* @return >=0 on success, negative AVERROR in case of failure
*/
void ff_format_io_close(AVFormatContext *s, AVIOContext **pb);
int ff_format_io_close(AVFormatContext *s, AVIOContext **pb);
/* Default io_close callback, not to be used directly, use ff_format_io_close
* instead. */
void ff_format_io_close_default(AVFormatContext *s, AVIOContext *pb);
/**
* Utility function to check if the file uses http or https protocol

@ -146,9 +146,9 @@ static int io_open_default(AVFormatContext *s, AVIOContext **pb,
return ffio_open_whitelist(pb, url, flags, &s->interrupt_callback, options, s->protocol_whitelist, s->protocol_blacklist);
}
static void io_close_default(AVFormatContext *s, AVIOContext *pb)
static int io_close2_default(AVFormatContext *s, AVIOContext *pb)
{
avio_close(pb);
return avio_close(pb);
}
AVFormatContext *avformat_alloc_context(void)
@ -162,7 +162,8 @@ AVFormatContext *avformat_alloc_context(void)
s = &si->pub;
s->av_class = &av_format_context_class;
s->io_open = io_open_default;
s->io_close = io_close_default;
s->io_close = ff_format_io_close_default;
s->io_close2= io_close2_default;
av_opt_set_defaults(s);

@ -158,6 +158,7 @@ static int segment_mux_init(AVFormatContext *s)
av_dict_copy(&oc->metadata, s->metadata, 0);
oc->opaque = s->opaque;
oc->io_close = s->io_close;
oc->io_close2 = s->io_close2;
oc->io_open = s->io_open;
oc->flags = s->flags;

@ -237,6 +237,7 @@ static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave)
avf2->opaque = avf->opaque;
avf2->io_open = avf->io_open;
avf2->io_close = avf->io_close;
avf2->io_close2 = avf->io_close2;
avf2->interrupt_callback = avf->interrupt_callback;
avf2->flags = avf->flags;
avf2->strict_std_compliance = avf->strict_std_compliance;

@ -1831,11 +1831,22 @@ int ff_format_output_open(AVFormatContext *s, const char *url, AVDictionary **op
return 0;
}
void ff_format_io_close(AVFormatContext *s, AVIOContext **pb)
void ff_format_io_close_default(AVFormatContext *s, AVIOContext *pb)
{
if (*pb)
s->io_close(s, *pb);
avio_close(pb);
}
int ff_format_io_close(AVFormatContext *s, AVIOContext **pb)
{
int ret = 0;
if (*pb) {
if (s->io_close == ff_format_io_close_default || s->io_close == NULL)
ret = s->io_close2(s, *pb);
else
s->io_close(s, *pb);
}
*pb = NULL;
return ret;
}
int ff_is_http_proto(const char *filename) {

@ -32,8 +32,8 @@
// Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium)
// Also please add any ticket numbers that you believe might be affected here
#define LIBAVFORMAT_VERSION_MAJOR 59
#define LIBAVFORMAT_VERSION_MINOR 9
#define LIBAVFORMAT_VERSION_MICRO 102
#define LIBAVFORMAT_VERSION_MINOR 10
#define LIBAVFORMAT_VERSION_MICRO 100
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
LIBAVFORMAT_VERSION_MINOR, \

Loading…
Cancel
Save