aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2011-06-18 04:40:18 +0200
committerMichael Niedermayer <michaelni@gmx.at>2011-06-18 05:10:38 +0200
commit2905e3ff6462431d55f89614b24e2a407707c82a (patch)
treed482d458a449228c8475942117c7eb81ec8934c6
parent44d1b4088f2959912a27ffbffc5884db1b35a645 (diff)
parent78440c007cd310bb27ac2af5fb7ea5b7555efc84 (diff)
downloadffmpeg-2905e3ff6462431d55f89614b24e2a407707c82a.tar.gz
Merge remote-tracking branch 'qatar/master'
* qatar/master: lavc: add opt_find to AVCodecContext class. h264: Complexify frame num gap shortening code intreadwrite.h: fix AV_RL32/AV_RB32 signedness. Fix decoding of mpegts streams with h264 video that does *NOT* have b frames Add minor bumps and APIChanges entries for lavf private options. ffmpeg: deprecate -vc and -tvstd ffmpeg: use new avformat_open_* API. ffserver: use new avformat_open_* API. ffprobe: use new avformat_open_* API. ffplay: use new avformat_open_* API. cmdutils: add opt_default2(). dict: add AV_DICT_APPEND flag. lavf: add avformat_write_header() as a replacement for av_write_header(). Deprecate av_open_input_* and remove their uses. lavf: add avformat_open_input() as a replacement for av_open_input_* AVOptions: add av_opt_find() as a replacement for av_find_opt. AVOptions: add av_opt_set_dict() mapping a dictionary struct to a context. ffmpeg: don't abuse a global for passing frame size from input to output ffmpeg: don't abuse a global for passing pixel format from input to output ffmpeg: initialise encoders earlier. Conflicts: cmdutils.c doc/APIchanges ffmpeg.c ffplay.c ffprobe.c libavcodec/h264.c libavformat/avformat.h libavformat/utils.c libavformat/version.h libavutil/avutil.h Merged-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r--cmdutils.c84
-rw-r--r--cmdutils.h1
-rw-r--r--doc/APIchanges10
-rw-r--r--ffmpeg.c38
-rw-r--r--ffprobe.c16
-rw-r--r--ffserver.c39
-rw-r--r--libavcodec/h264.c4
-rw-r--r--libavcodec/options.c21
-rw-r--r--libavfilter/vsrc_movie.c4
-rw-r--r--libavformat/applehttp.c9
-rw-r--r--libavformat/avformat.h64
-rw-r--r--libavformat/avidec.c8
-rw-r--r--libavformat/options.c28
-rw-r--r--libavformat/rdt.c4
-rw-r--r--libavformat/rtpdec_asf.c7
-rw-r--r--libavformat/rtpenc_chain.c2
-rw-r--r--libavformat/sapdec.c7
-rw-r--r--libavformat/utils.c304
-rw-r--r--libavformat/version.h4
-rw-r--r--libavutil/avutil.h5
-rw-r--r--libavutil/dict.c13
-rw-r--r--libavutil/dict.h2
-rw-r--r--libavutil/intreadwrite.h20
-rw-r--r--libavutil/log.h7
-rw-r--r--libavutil/opt.c52
-rw-r--r--libavutil/opt.h48
26 files changed, 607 insertions, 194 deletions
diff --git a/cmdutils.c b/cmdutils.c
index 1f7ecc4887..3b9cfaa3d9 100644
--- a/cmdutils.c
+++ b/cmdutils.c
@@ -38,6 +38,7 @@
#include "libavutil/parseutils.h"
#include "libavutil/pixdesc.h"
#include "libavutil/eval.h"
+#include "libavutil/dict.h"
#include "libavutil/opt.h"
#include "cmdutils.h"
#include "version.h"
@@ -54,6 +55,7 @@ static int opt_name_count;
AVCodecContext *avcodec_opts[AVMEDIA_TYPE_NB];
AVFormatContext *avformat_opts;
struct SwsContext *sws_opts;
+AVDictionary *format_opts, *video_opts, *audio_opts, *sub_opts;
static const int this_year = 2011;
@@ -86,6 +88,10 @@ void uninit_opts(void)
av_freep(&opt_names);
av_freep(&opt_values);
opt_name_count = 0;
+ av_dict_free(&format_opts);
+ av_dict_free(&video_opts);
+ av_dict_free(&audio_opts);
+ av_dict_free(&sub_opts);
}
void log_callback_help(void* ptr, int level, const char* fmt, va_list vl)
@@ -290,6 +296,43 @@ unknown_opt:
}
}
+#define FLAGS (o->type == FF_OPT_TYPE_FLAGS) ? AV_DICT_APPEND : 0
+#define SET_PREFIXED_OPTS(ch, flag, output) \
+ if (opt[0] == ch && avcodec_opts[0] && (o = av_opt_find(avcodec_opts[0], opt+1, NULL, flag, 0)))\
+ av_dict_set(&output, opt+1, arg, FLAGS);
+static int opt_default2(const char *opt, const char *arg)
+{
+ const AVOption *o;
+ if ((o = av_opt_find(avcodec_opts[0], opt, NULL, 0, AV_OPT_SEARCH_CHILDREN))) {
+ if (o->flags & AV_OPT_FLAG_VIDEO_PARAM)
+ av_dict_set(&video_opts, opt, arg, FLAGS);
+ if (o->flags & AV_OPT_FLAG_AUDIO_PARAM)
+ av_dict_set(&audio_opts, opt, arg, FLAGS);
+ if (o->flags & AV_OPT_FLAG_SUBTITLE_PARAM)
+ av_dict_set(&sub_opts, opt, arg, FLAGS);
+ } else if ((o = av_opt_find(avformat_opts, opt, NULL, 0, AV_OPT_SEARCH_CHILDREN)))
+ av_dict_set(&format_opts, opt, arg, FLAGS);
+ else if ((o = av_opt_find(sws_opts, opt, NULL, 0, AV_OPT_SEARCH_CHILDREN))) {
+ // XXX we only support sws_flags, not arbitrary sws options
+ int ret = av_set_string3(sws_opts, opt, arg, 1, NULL);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "Error setting option %s.\n", opt);
+ return ret;
+ }
+ }
+
+ if (!o) {
+ SET_PREFIXED_OPTS('v', AV_OPT_FLAG_VIDEO_PARAM, video_opts)
+ SET_PREFIXED_OPTS('a', AV_OPT_FLAG_AUDIO_PARAM, audio_opts)
+ SET_PREFIXED_OPTS('s', AV_OPT_FLAG_SUBTITLE_PARAM, sub_opts)
+ }
+
+ if (o)
+ return 0;
+ fprintf(stderr, "Unrecognized option '%s'\n", opt);
+ return AVERROR_OPTION_NOT_FOUND;
+}
+
int opt_default(const char *opt, const char *arg){
int type;
int ret= 0;
@@ -322,7 +365,7 @@ int opt_default(const char *opt, const char *arg){
goto out;
for(type=0; *avcodec_opts && type<AVMEDIA_TYPE_NB && ret>= 0; type++){
- const AVOption *o2 = av_find_opt(avcodec_opts[0], opt, NULL, opt_types[type], opt_types[type]);
+ const AVOption *o2 = av_opt_find(avcodec_opts[0], opt, NULL, opt_types[type], 0);
if(o2)
ret = av_set_string3(avcodec_opts[type], opt, arg, 1, &o);
}
@@ -345,11 +388,50 @@ int opt_default(const char *opt, const char *arg){
exit(1);
}
if (!o) {
+//<<<<<<< HEAD
fprintf(stderr, "Unrecognized option '%s'\n", opt);
exit(1);
+/*||||||| merged common ancestors
+ AVCodec *p = NULL;
+ AVOutputFormat *oformat = NULL;
+ while ((p=av_codec_next(p))){
+ const AVClass *c = p->priv_class;
+ if(c && av_find_opt(&c, opt, NULL, 0, 0))
+ break;
+ }
+ if (!p) {
+ while ((oformat = av_oformat_next(oformat))) {
+ const AVClass *c = oformat->priv_class;
+ if (c && av_find_opt(&c, opt, NULL, 0, 0))
+ break;
+ }
+ }
+ if(!p && !oformat){
+ fprintf(stderr, "Unrecognized option '%s'\n", opt);
+ exit(1);
+ }
+=======
+ AVCodec *p = NULL;
+ AVOutputFormat *oformat = NULL;
+ while ((p=av_codec_next(p))){
+ const AVClass *c = p->priv_class;
+ if(c && av_opt_find(&c, opt, NULL, 0, 0))
+ break;
+ }
+ if (!p) {
+ while ((oformat = av_oformat_next(oformat))) {
+ const AVClass *c = oformat->priv_class;
+ if (c && av_opt_find(&c, opt, NULL, 0, 0))
+ break;
+ }
+ }
+>>>>>>> qatar/master*/
}
out:
+ if ((ret = opt_default2(opt, arg)) < 0)
+ return ret;
+
// av_log(NULL, AV_LOG_ERROR, "%s:%s: %f 0x%0X\n", opt, arg, av_get_double(avcodec_opts, opt, NULL), (int)av_get_int(avcodec_opts, opt, NULL));
opt_values= av_realloc(opt_values, sizeof(void*)*(opt_name_count+1));
diff --git a/cmdutils.h b/cmdutils.h
index 5fd398d054..c0c3ce07d9 100644
--- a/cmdutils.h
+++ b/cmdutils.h
@@ -47,6 +47,7 @@ extern const char **opt_names;
extern AVCodecContext *avcodec_opts[AVMEDIA_TYPE_NB];
extern AVFormatContext *avformat_opts;
extern struct SwsContext *sws_opts;
+extern AVDictionary *format_opts, *video_opts, *audio_opts, *sub_opts;
/**
* Initialize the cmdutils option system, in particular
diff --git a/doc/APIchanges b/doc/APIchanges
index e8dc0642fa..e07951fe05 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -23,6 +23,16 @@ API changes, most recent first:
2011-06-12 - xxxxxxx - lavfi 2.16.0 - avfilter_graph_parse()
Change avfilter_graph_parse() signature.
+2011-06-xx - xxxxxxx - lavf 53.2.0 - avformat.h
+ Add avformat_open_input and avformat_write_header().
+ Deprecate av_open_input_stream, av_open_input_file,
+ AVFormatParameters and av_write_header.
+
+2011-06-xx - xxxxxxx - lavu 51.7.0 - opt.h
+ Add av_opt_set_dict() and av_opt_find().
+ Deprecate av_find_opt().
+ Add AV_DICT_APPEND flag.
+
2011-06-xx - xxxxxxx - lavu 51.6.0 - opt.h
Add av_opt_flag_is_set().
diff --git a/ffmpeg.c b/ffmpeg.c
index 6ce127e903..4e8ac200da 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -2261,6 +2261,8 @@ static int transcode(AVFormatContext **output_files,
abort();
}
} else {
+ if (!ost->enc)
+ ost->enc = avcodec_find_encoder(ost->st->codec->codec_id);
switch(codec->codec_type) {
case AVMEDIA_TYPE_AUDIO:
ost->fifo= av_fifo_alloc(1024);
@@ -2272,7 +2274,7 @@ static int transcode(AVFormatContext **output_files,
if (icodec->lowres)
codec->sample_rate >>= icodec->lowres;
}
- choose_sample_rate(ost->st, codec->codec);
+ choose_sample_rate(ost->st, ost->enc);
codec->time_base = (AVRational){1, codec->sample_rate};
if (!codec->channels)
codec->channels = icodec->channels;
@@ -2287,6 +2289,10 @@ static int transcode(AVFormatContext **output_files,
ost->resample_channels = icodec->channels;
break;
case AVMEDIA_TYPE_VIDEO:
+ if (codec->pix_fmt == PIX_FMT_NONE)
+ codec->pix_fmt = icodec->pix_fmt;
+ choose_pixel_fmt(ost->st, ost->enc);
+
if (ost->st->codec->pix_fmt == PIX_FMT_NONE) {
fprintf(stderr, "Video pixel format is unknown, stream cannot be encoded\n");
ffmpeg_exit(1);
@@ -2297,6 +2303,10 @@ static int transcode(AVFormatContext **output_files,
if (ost->video_resample) {
codec->bits_per_raw_sample= frame_bits_per_raw_sample;
}
+ if (!codec->width || !codec->height) {
+ codec->width = icodec->width;
+ codec->height = icodec->height;
+ }
ost->resample_height = icodec->height;
ost->resample_width = icodec->width;
ost->resample_pix_fmt= icodec->pix_fmt;
@@ -2305,9 +2315,9 @@ static int transcode(AVFormatContext **output_files,
if (!ost->frame_rate.num)
ost->frame_rate = ist->st->r_frame_rate.num ? ist->st->r_frame_rate : (AVRational){25,1};
- if (codec->codec && codec->codec->supported_framerates && !force_fps) {
- int idx = av_find_nearest_q_idx(ost->frame_rate, codec->codec->supported_framerates);
- ost->frame_rate = codec->codec->supported_framerates[idx];
+ if (ost->enc && ost->enc->supported_framerates && !force_fps) {
+ int idx = av_find_nearest_q_idx(ost->frame_rate, ost->enc->supported_framerates);
+ ost->frame_rate = ost->enc->supported_framerates[idx];
}
codec->time_base = (AVRational){ost->frame_rate.den, ost->frame_rate.num};
@@ -2375,8 +2385,6 @@ static int transcode(AVFormatContext **output_files,
if (ost->encoding_needed) {
AVCodec *codec = ost->enc;
AVCodecContext *dec = input_streams[ost->source_index].st->codec;
- if (!codec)
- codec = avcodec_find_encoder(ost->st->codec->codec_id);
if (!codec) {
snprintf(error, sizeof(error), "Encoder (codec id %d) not found for output stream #%d.%d",
ost->st->codec->codec_id, ost->file_index, ost->index);
@@ -3397,17 +3405,12 @@ static int opt_input_file(const char *opt, const char *filename)
if(!input_codecs[nb_input_codecs-1])
input_codecs[nb_input_codecs-1] = avcodec_find_decoder(dec->codec_id);
set_context_opts(dec, avcodec_opts[AVMEDIA_TYPE_VIDEO], AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM, input_codecs[nb_input_codecs-1]);
- frame_height = dec->height;
- frame_width = dec->width;
- frame_pix_fmt = dec->pix_fmt;
rfps = ic->streams[i]->r_frame_rate.num;
rfps_base = ic->streams[i]->r_frame_rate.den;
if (dec->lowres) {
dec->flags |= CODEC_FLAG_EMU_EDGE;
- frame_height >>= dec->lowres;
- frame_width >>= dec->lowres;
- dec->height = frame_height;
- dec->width = frame_width;
+ dec->height >>= dec->lowres;
+ dec->width >>= dec->lowres;
}
if(me_threshold)
dec->debug |= FF_DEBUG_MV;
@@ -3452,9 +3455,12 @@ static int opt_input_file(const char *opt, const char *filename)
input_files[nb_input_files - 1].ctx = ic;
input_files[nb_input_files - 1].ist_index = nb_input_streams - ic->nb_streams;
- video_channel = 0;
top_field_first = -1;
+ video_channel = 0;
frame_rate = (AVRational){0, 0};
+ frame_pix_fmt = PIX_FMT_NONE;
+ frame_height = 0;
+ frame_width = 0;
audio_sample_rate = 0;
audio_channels = 0;
@@ -3578,8 +3584,6 @@ static void new_video_stream(AVFormatContext *oc, int file_idx)
video_enc->bits_per_raw_sample = frame_bits_per_raw_sample;
st->sample_aspect_ratio = video_enc->sample_aspect_ratio;
- choose_pixel_fmt(st, codec);
-
if (intra_only)
video_enc->gop_size = 0;
if (video_qscale || same_quality) {
@@ -3985,6 +3989,8 @@ static int opt_output_file(const char *opt, const char *filename)
set_context_opts(oc, avformat_opts, AV_OPT_FLAG_ENCODING_PARAM, NULL);
frame_rate = (AVRational){0, 0};
+ frame_width = 0;
+ frame_height = 0;
audio_sample_rate = 0;
audio_channels = 0;
diff --git a/ffprobe.c b/ffprobe.c
index e945a9a54d..f0ec9e4739 100644
--- a/ffprobe.c
+++ b/ffprobe.c
@@ -262,18 +262,18 @@ static void show_format(AVFormatContext *fmt_ctx)
static int open_input_file(AVFormatContext **fmt_ctx_ptr, const char *filename)
{
int err, i;
- AVFormatParameters fmt_params;
- AVFormatContext *fmt_ctx;
-
- memset(&fmt_params, 0, sizeof(fmt_params));
- fmt_params.prealloced_context = 1;
- fmt_ctx = avformat_alloc_context();
- set_context_opts(fmt_ctx, avformat_opts, AV_OPT_FLAG_DECODING_PARAM, NULL);
+ AVFormatContext *fmt_ctx = NULL;
+ AVDictionaryEntry *t;
- if ((err = av_open_input_file(&fmt_ctx, filename, iformat, 0, &fmt_params)) < 0) {
+ if ((err = avformat_open_input(&fmt_ctx, filename, iformat, &format_opts)) < 0) {
print_error(filename, err);
return err;
}
+ if ((t = av_dict_get(format_opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
+ av_log(NULL, AV_LOG_ERROR, "Option %s not found.\n", t->key);
+ return AVERROR_OPTION_NOT_FOUND;
+ }
+
/* fill the streams in the format context */
if ((err = av_find_stream_info(fmt_ctx)) < 0) {
diff --git a/ffserver.c b/ffserver.c
index e222887c65..15ea00f4f8 100644
--- a/ffserver.c
+++ b/ffserver.c
@@ -205,7 +205,7 @@ typedef struct FFStream {
char filename[1024]; /* stream filename */
struct FFStream *feed; /* feed we are using (can be null if
coming from file) */
- AVFormatParameters *ap_in; /* input parameters */
+ AVDictionary *in_opts; /* input parameters */
AVInputFormat *ifmt; /* if non NULL, force input format */
AVOutputFormat *fmt;
IPAddressACL *acl;
@@ -2126,7 +2126,7 @@ static int open_input_stream(HTTPContext *c, const char *info)
{
char buf[128];
char input_filename[1024];
- AVFormatContext *s;
+ AVFormatContext *s = NULL;
int buf_size, i, ret;
int64_t stream_pos;
@@ -2157,8 +2157,7 @@ static int open_input_stream(HTTPContext *c, const char *info)
return -1;
/* open stream */
- if ((ret = av_open_input_file(&s, input_filename, c->stream->ifmt,
- buf_size, c->stream->ap_in)) < 0) {
+ if ((ret = avformat_open_input(&s, input_filename, c->stream->ifmt, &c->stream->in_opts)) < 0) {
http_log("could not open %s: %d\n", input_filename, ret);
return -1;
}
@@ -2268,8 +2267,7 @@ static int http_prepare_data(HTTPContext *c)
c->fmt_ctx.preload = (int)(0.5*AV_TIME_BASE);
c->fmt_ctx.max_delay = (int)(0.7*AV_TIME_BASE);
- av_set_parameters(&c->fmt_ctx, NULL);
- if (av_write_header(&c->fmt_ctx) < 0) {
+ if (avformat_write_header(&c->fmt_ctx, NULL) < 0) {
http_log("Error writing output header\n");
return -1;
}
@@ -2709,11 +2707,14 @@ static int http_receive_data(HTTPContext *c)
}
} else {
/* We have a header in our hands that contains useful data */
- AVFormatContext *s = NULL;
+ AVFormatContext *s = avformat_alloc_context();
AVIOContext *pb;
AVInputFormat *fmt_in;
int i;
+ if (!s)
+ goto fail;
+
/* use feed output format name to find corresponding input format */
fmt_in = av_find_input_format(feed->fmt->name);
if (!fmt_in)
@@ -2723,7 +2724,8 @@ static int http_receive_data(HTTPContext *c)
0, NULL, NULL, NULL, NULL);
pb->seekable = 0;
- if (av_open_input_stream(&s, pb, c->stream->feed_filename, fmt_in, NULL) < 0) {
+ s->pb = pb;
+ if (avformat_open_input(&s, c->stream->feed_filename, fmt_in, NULL) < 0) {
av_free(pb);
goto fail;
}
@@ -3442,8 +3444,7 @@ static int rtp_new_av_stream(HTTPContext *c,
/* XXX: close stream */
goto fail;
}
- av_set_parameters(ctx, NULL);
- if (av_write_header(ctx) < 0) {
+ if (avformat_write_header(ctx, NULL) < 0) {
fail:
if (h)
url_close(h);
@@ -3597,28 +3598,25 @@ static void extract_mpeg4_header(AVFormatContext *infile)
static void build_file_streams(void)
{
FFStream *stream, *stream_next;
- AVFormatContext *infile;
int i, ret;
/* gather all streams */
for(stream = first_stream; stream != NULL; stream = stream_next) {
+ AVFormatContext *infile = NULL;
stream_next = stream->next;
if (stream->stream_type == STREAM_TYPE_LIVE &&
!stream->feed) {
/* the stream comes from a file */
/* try to open the file */
/* open stream */
- stream->ap_in = av_mallocz(sizeof(AVFormatParameters));
if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
/* specific case : if transport stream output to RTP,
we use a raw transport stream reader */
- stream->ap_in->mpeg2ts_raw = 1;
- stream->ap_in->mpeg2ts_compute_pcr = 1;
+ av_dict_set(&stream->in_opts, "mpeg2ts_compute_pcr", "1", 0);
}
http_log("Opening file '%s'\n", stream->feed_filename);
- if ((ret = av_open_input_file(&infile, stream->feed_filename,
- stream->ifmt, 0, stream->ap_in)) < 0) {
+ if ((ret = avformat_open_input(&infile, stream->feed_filename, stream->ifmt, &stream->in_opts)) < 0) {
http_log("Could not open '%s': %d\n", stream->feed_filename, ret);
/* remove stream (no need to spend more time on it) */
fail:
@@ -3678,10 +3676,10 @@ static void build_feed_streams(void)
if (avio_check(feed->feed_filename, AVIO_FLAG_READ) > 0) {
/* See if it matches */
- AVFormatContext *s;
+ AVFormatContext *s = NULL;
int matches = 0;
- if (av_open_input_file(&s, feed->feed_filename, NULL, FFM_PACKET_SIZE, NULL) >= 0) {
+ if (avformat_open_input(&s, feed->feed_filename, NULL, NULL) >= 0) {
/* Now see if it matches */
if (s->nb_streams == feed->nb_streams) {
matches = 1;
@@ -3767,8 +3765,7 @@ static void build_feed_streams(void)
s->oformat = feed->fmt;
s->nb_streams = feed->nb_streams;
s->streams = feed->streams;
- av_set_parameters(s, NULL);
- if (av_write_header(s) < 0) {
+ if (avformat_write_header(s, NULL) < 0) {
http_log("Container doesn't supports the required parameters\n");
exit(1);
}
@@ -3944,7 +3941,7 @@ static int ffserver_opt_default(const char *opt, const char *arg,
AVCodecContext *avctx, int type)
{
int ret = 0;
- const AVOption *o = av_find_opt(avctx, opt, NULL, type, type);
+ const AVOption *o = av_opt_find(avctx, opt, NULL, type, 0);
if(o)
ret = av_set_string3(avctx, opt, arg, 1, NULL);
return ret;
diff --git a/libavcodec/h264.c b/libavcodec/h264.c
index 0919c12b92..b88622d432 100644
--- a/libavcodec/h264.c
+++ b/libavcodec/h264.c
@@ -3784,8 +3784,8 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size){
init_get_bits(&s->gb, ptr, bit_length);
ff_h264_decode_seq_parameter_set(h);
- if(s->flags& CODEC_FLAG_LOW_DELAY ||
- (h->sps.bitstream_restriction_flag && !h->sps.num_reorder_frames))
+ if (s->flags& CODEC_FLAG_LOW_DELAY ||
+ (h->sps.bitstream_restriction_flag && !h->sps.num_reorder_frames))
s->low_delay=1;
if(avctx->has_b_frames < 2)
diff --git a/libavcodec/options.c b/libavcodec/options.c
index 78a7bc8a40..b6ad5d8763 100644
--- a/libavcodec/options.c
+++ b/libavcodec/options.c
@@ -37,6 +37,25 @@ static const char* context_to_name(void* ptr) {
return "NULL";
}
+static const AVOption *opt_find(void *obj, const char *name, const char *unit, int opt_flags, int search_flags)
+{
+ AVCodecContext *s = obj;
+ AVCodec *c = NULL;
+
+ if (s->priv_data) {
+ if (s->codec->priv_class)
+ return av_opt_find(s->priv_data, name, unit, opt_flags, search_flags);
+ return NULL;
+ }
+
+ while ((c = av_codec_next(c))) {
+ const AVOption *o;
+ if (c->priv_class && (o = av_opt_find(&c->priv_class, name, unit, opt_flags, search_flags)))
+ return o;
+ }
+ return NULL;
+}
+
#define OFFSET(x) offsetof(AVCodecContext,x)
#define DEFAULT 0 //should be NAN but it does not work as it is not a constant in glibc as required by ANSI/ISO C
//these names are too long to be readable
@@ -457,7 +476,7 @@ static const AVOption options[]={
#undef D
#undef DEFAULT
-static const AVClass av_codec_context_class = { "AVCodecContext", context_to_name, options, LIBAVUTIL_VERSION_INT, OFFSET(log_level_offset) };
+static const AVClass av_codec_context_class = { "AVCodecContext", context_to_name, options, LIBAVUTIL_VERSION_INT, OFFSET(log_level_offset), .opt_find = opt_find};
void avcodec_get_context_defaults2(AVCodecContext *s, enum AVMediaType codec_type){
int flags=0;
diff --git a/libavfilter/vsrc_movie.c b/libavfilter/vsrc_movie.c
index 6c5c831fed..7a3babbec8 100644
--- a/libavfilter/vsrc_movie.c
+++ b/libavfilter/vsrc_movie.c
@@ -92,9 +92,9 @@ static int movie_init(AVFilterContext *ctx)
iformat = movie->format_name ? av_find_input_format(movie->format_name) : NULL;
movie->format_ctx = NULL;
- if ((ret = av_open_input_file(&movie->format_ctx, movie->file_name, iformat, 0, NULL)) < 0) {
+ if ((ret = avformat_open_input(&movie->format_ctx, movie->file_name, iformat, NULL)) < 0) {
av_log(ctx, AV_LOG_ERROR,
- "Failed to av_open_input_file '%s'\n", movie->file_name);
+ "Failed to avformat_open_input '%s'\n", movie->file_name);
return ret;
}
if ((ret = av_find_stream_info(movie->format_ctx)) < 0)
diff --git a/libavformat/applehttp.c b/libavformat/applehttp.c
index 050d99c6d7..ddf97e9d31 100644
--- a/libavformat/applehttp.c
+++ b/libavformat/applehttp.c
@@ -473,6 +473,11 @@ static int applehttp_read_header(AVFormatContext *s, AVFormatParameters *ap)
if (v->n_segments == 0)
continue;
+ if (!(v->ctx = avformat_alloc_context())) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
v->index = i;
v->needed = 1;
v->parent = s;
@@ -491,8 +496,8 @@ static int applehttp_read_header(AVFormatContext *s, AVFormatParameters *ap)
NULL, 0, 0);
if (ret < 0)
goto fail;
- ret = av_open_input_stream(&v->ctx, &v->pb, v->segments[0]->url,
- in_fmt, NULL);
+ v->ctx->pb = &v->pb;
+ ret = avformat_open_input(&v->ctx, v->segments[0]->url, in_fmt, NULL);
if (ret < 0)
goto fail;
v->stream_offset = stream_offset;
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index f00fce4a38..1734649a95 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -247,8 +247,8 @@ typedef struct AVFormatParameters {
attribute_deprecated unsigned int mpeg2ts_compute_pcr:1;
attribute_deprecated unsigned int initial_pause:1; /**< Do not begin to play the stream
immediately (RTSP only). */
+ attribute_deprecated unsigned int prealloced_context:1;
#endif
- unsigned int prealloced_context:1;
} AVFormatParameters;
//! Demuxer will use avio_open, no opened file should be provided by the caller.
@@ -751,10 +751,12 @@ typedef struct AVFormatContext {
#if FF_API_FLAG_RTP_HINT
#define AVFMT_FLAG_RTP_HINT 0x0040 ///< Deprecated, use the -movflags rtphint muxer specific AVOption instead
#endif
-#define AVFMT_FLAG_MP4A_LATM 0x0080 ///< Enable RTP MP4A-LATM payload
+#define AVFMT_FLAG_CUSTOM_IO 0x0080 ///< The caller has supplied a custom AVIOContext, don't avio_close() it.
+#define AVFMT_FLAG_MP4A_LATM 0x8000 ///< Enable RTP MP4A-LATM payload
#define AVFMT_FLAG_SORT_DTS 0x10000 ///< try to interleave outputted packets by dts (using this flag can slow demuxing down)
#define AVFMT_FLAG_PRIV_OPT 0x20000 ///< Enable use of private options by delaying codec open (this could be made default once all code is converted)
#define AVFMT_FLAG_KEEP_SIDE_DATA 0x40000 ///< Dont merge side data but keep it seperate.
+
int loop_input;
/**
@@ -1054,11 +1056,13 @@ int av_probe_input_buffer(AVIOContext *pb, AVInputFormat **fmt,
const char *filename, void *logctx,
unsigned int offset, unsigned int max_probe_size);
+#if FF_API_FORMAT_PARAMETERS
/**
* Allocate all the structures needed to read an input stream.
* This does not open the needed codecs for decoding the stream[s].
+ * @deprecated use avformat_open_input instead.
*/
-int av_open_input_stream(AVFormatContext **ic_ptr,
+attribute_deprecated int av_open_input_stream(AVFormatContext **ic_ptr,
AVIOContext *pb, const char *filename,
AVInputFormat *fmt, AVFormatParameters *ap);
@@ -1073,11 +1077,35 @@ int av_open_input_stream(AVFormatContext **ic_ptr,
* @param ap Additional parameters needed when opening the file
* (NULL if default).
* @return 0 if OK, AVERROR_xxx otherwise
+ *
+ * @deprecated use avformat_open_input instead.
*/
-int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
+attribute_deprecated int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
AVInputFormat *fmt,
int buf_size,
AVFormatParameters *ap);
+#endif
+
+/**
+ * Open an input stream and read the header. The codecs are not opened.
+ * The stream must be closed with av_close_input_file().
+ *
+ * @param ps Pointer to user-supplied AVFormatContext (allocated by avformat_alloc_context).
+ * May be a pointer to NULL, in which case an AVFormatContext is allocated by this
+ * function and written into ps.
+ * Note that a user-supplied AVFormatContext will be freed on failure.
+ * @param filename Name of the stream to open.
+ * @param fmt If non-NULL, this parameter forces a specific input format.
+ * Otherwise the format is autodetected.
+ * @param options A dictionary filled with AVFormatContext and demuxer-private options.
+ * On return this parameter will be destroyed and replaced with a dict containing
+ * options that were not found. May be NULL.
+ *
+ * @return 0 on success, a negative AVERROR on failure.
+ *
+ * @note If you want to use custom IO, preallocate the format context and set its pb field.
+ */
+int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options);
int av_demuxer_open(AVFormatContext *ic, AVFormatParameters *ap);
@@ -1365,7 +1393,12 @@ int64_t av_gen_search(AVFormatContext *s, int stream_index,
/**
* media file output
*/
+#if FF_API_FORMAT_PARAMETERS
+/**
+ * @deprecated pass the options to avformat_write_header directly.
+ */
attribute_deprecated int av_set_parameters(AVFormatContext *s, AVFormatParameters *ap);
+#endif
/**
* Split a URL string into components.
@@ -1394,6 +1427,24 @@ void av_url_split(char *proto, int proto_size,
const char *url);
/**
+ * Allocate the stream private data and write the stream header to
+ * an output media file.
+ *
+ * @param s Media file handle, must be allocated with avformat_alloc_context().
+ * Its oformat field must be set to the desired output format;
+ * Its pb field must be set to an already openened AVIOContext.
+ * @param options An AVDictionary filled with AVFormatContext and muxer-private options.
+ * On return this parameter will be destroyed and replaced with a dict containing
+ * options that were not found. May be NULL.
+ *
+ * @return 0 on success, negative AVERROR on failure.
+ *
+ * @see av_opt_find, av_dict_set, avio_open, av_oformat_next.
+ */
+int avformat_write_header(AVFormatContext *s, AVDictionary **options);
+
+#if FF_API_FORMAT_PARAMETERS
+/**
* Allocate the stream private data and write the stream header to an
* output media file.
* @note: this sets stream time-bases, if possible to stream->codec->time_base
@@ -1401,8 +1452,11 @@ void av_url_split(char *proto, int proto_size,
*
* @param s media file handle
* @return 0 if OK, AVERROR_xxx on error
+ *
+ * @deprecated use avformat_write_header.
*/
-int av_write_header(AVFormatContext *s);
+attribute_deprecated int av_write_header(AVFormatContext *s);
+#endif
/**
* Write a packet to an output media file.
diff --git a/libavformat/avidec.c b/libavformat/avidec.c
index b7d09d799e..0bcdd3fdec 100644
--- a/libavformat/avidec.c
+++ b/libavformat/avidec.c
@@ -800,7 +800,11 @@ static int read_gab2_sub(AVStream *st, AVPacket *pkt) {
if (!(sub_demuxer = av_probe_input_format2(&pd, 1, &score)))
goto error;
- if (!av_open_input_stream(&ast->sub_ctx, pb, "", sub_demuxer, NULL)) {
+ if (!(ast->sub_ctx = avformat_alloc_context()))
+ goto error;
+
+ ast->sub_ctx->pb = pb;
+ if (!avformat_open_input(&ast->sub_ctx, "", sub_demuxer, NULL)) {
av_read_packet(ast->sub_ctx, &ast->sub_pkt);
*st->codec = *ast->sub_ctx->streams[0]->codec;
ast->sub_ctx->streams[0]->codec->extradata = NULL;
@@ -1393,7 +1397,7 @@ static int avi_read_close(AVFormatContext *s)
if (ast) {
if (ast->sub_ctx) {
av_freep(&ast->sub_ctx->pb);
- av_close_input_stream(ast->sub_ctx);
+ av_close_input_file(ast->sub_ctx);
}
av_free(ast->sub_buffer);
av_free_packet(&ast->sub_pkt);
diff --git a/libavformat/options.c b/libavformat/options.c
index ed06ea0e44..e09fc97a25 100644
--- a/libavformat/options.c
+++ b/libavformat/options.c
@@ -33,6 +33,33 @@ static const char* format_to_name(void* ptr)
else return "NULL";
}
+static const AVOption *opt_find(void *obj, const char *name, const char *unit, int opt_flags, int search_flags)
+{
+ AVFormatContext *s = obj;
+ AVInputFormat *ifmt = NULL;
+ AVOutputFormat *ofmt = NULL;
+ if (s->priv_data) {
+ if ((s->iformat && !s->iformat->priv_class) ||
+ (s->oformat && !s->oformat->priv_class))
+ return NULL;
+ return av_opt_find(s->priv_data, name, unit, opt_flags, search_flags);
+ }
+
+ while ((ifmt = av_iformat_next(ifmt))) {
+ const AVOption *o;
+
+ if (ifmt->priv_class && (o = av_opt_find(&ifmt->priv_class, name, unit, opt_flags, search_flags)))
+ return o;
+ }
+ while ((ofmt = av_oformat_next(ofmt))) {
+ const AVOption *o;
+
+ if (ofmt->priv_class && (o = av_opt_find(&ofmt->priv_class, name, unit, opt_flags, search_flags)))
+ return o;
+ }
+ return NULL;
+}
+
#define OFFSET(x) offsetof(AVFormatContext,x)
#define DEFAULT 0 //should be NAN but it does not work as it is not a constant in glibc as required by ANSI/ISO C
//these names are too long to be readable
@@ -75,6 +102,7 @@ static const AVClass av_format_context_class = {
.item_name = format_to_name,
.option = options,
.version = LIBAVUTIL_VERSION_INT,
+ .opt_find = opt_find,
};
static void avformat_get_context_defaults(AVFormatContext *s)
diff --git a/libavformat/rdt.c b/libavformat/rdt.c
index 5c35b7453b..bbdb899578 100644
--- a/libavformat/rdt.c
+++ b/libavformat/rdt.c
@@ -523,7 +523,7 @@ rdt_new_context (void)
{
PayloadContext *rdt = av_mallocz(sizeof(PayloadContext));
- av_open_input_stream(&rdt->rmctx, NULL, "", &ff_rdt_demuxer, NULL);
+ avformat_open_input(&rdt->rmctx, "", &ff_rdt_demuxer, NULL);
return rdt;
}
@@ -539,7 +539,7 @@ rdt_free_context (PayloadContext *rdt)
av_freep(&rdt->rmst[i]);
}
if (rdt->rmctx)
- av_close_input_stream(rdt->rmctx);
+ av_close_input_file(rdt->rmctx);
av_freep(&rdt->mlti_data);
av_freep(&rdt->rmst);
av_free(rdt);
diff --git a/libavformat/rtpdec_asf.c b/libavformat/rtpdec_asf.c
index 58c9068a87..4f776453d7 100644
--- a/libavformat/rtpdec_asf.c
+++ b/libavformat/rtpdec_asf.c
@@ -107,10 +107,13 @@ int ff_wms_parse_sdp_a_line(AVFormatContext *s, const char *p)
"Failed to fix invalid RTSP-MS/ASF min_pktsize\n");
init_packetizer(&pb, buf, len);
if (rt->asf_ctx) {
- av_close_input_stream(rt->asf_ctx);
+ av_close_input_file(rt->asf_ctx);
rt->asf_ctx = NULL;
}
- ret = av_open_input_stream(&rt->asf_ctx, &pb, "", &ff_asf_demuxer, NULL);
+ if (!(rt->asf_ctx = avformat_alloc_context()))
+ return AVERROR(ENOMEM);
+ rt->asf_ctx->pb = &pb;
+ ret = avformat_open_input(&rt->asf_ctx, "", &ff_asf_demuxer, NULL);
if (ret < 0)
return ret;
av_dict_copy(&s->metadata, rt->asf_ctx->metadata, 0);
diff --git a/libavformat/rtpenc_chain.c b/libavformat/rtpenc_chain.c
index 7f1a8868eb..ed96d72f62 100644
--- a/libavformat/rtpenc_chain.c
+++ b/libavformat/rtpenc_chain.c
@@ -67,7 +67,7 @@ AVFormatContext *ff_rtp_chain_mux_open(AVFormatContext *s, AVStream *st,
ffio_fdopen(&rtpctx->pb, handle);
} else
ffio_open_dyn_packet_buf(&rtpctx->pb, packet_size);
- ret = av_write_header(rtpctx);
+ ret = avformat_write_header(rtpctx, NULL);
if (ret) {
if (handle) {
diff --git a/libavformat/sapdec.c b/libavformat/sapdec.c
index ea4b982041..f6897fbb0b 100644
--- a/libavformat/sapdec.c
+++ b/libavformat/sapdec.c
@@ -52,7 +52,7 @@ static int sap_read_close(AVFormatContext *s)
{
struct SAPState *sap = s->priv_data;
if (sap->sdp_ctx)
- av_close_input_stream(sap->sdp_ctx);
+ av_close_input_file(sap->sdp_ctx);
if (sap->ann_fd)
ffurl_close(sap->ann_fd);
av_freep(&sap->sdp);
@@ -156,9 +156,8 @@ static int sap_read_header(AVFormatContext *s,
goto fail;
}
sap->sdp_ctx->max_delay = s->max_delay;
- ap->prealloced_context = 1;
- ret = av_open_input_stream(&sap->sdp_ctx, &sap->sdp_pb, "temp.sdp",
- infmt, ap);
+ sap->sdp_ctx->pb = &sap->sdp_pb;
+ ret = avformat_open_input(&sap->sdp_ctx, "temp.sdp", infmt, NULL);
if (ret < 0)
goto fail;
if (sap->sdp_ctx->ctx_flags & AVFMTCTX_NOHEADER)
diff --git a/libavformat/utils.c b/libavformat/utils.c
index 1a10887029..3be8706d87 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -28,6 +28,7 @@
#include "libavcodec/raw.h"
#include "libavutil/opt.h"
#include "libavutil/dict.h"
+#include "libavutil/pixdesc.h"
#include "metadata.h"
#include "id3v2.h"
#include "libavutil/avstring.h"
@@ -393,6 +394,47 @@ static int set_codec_from_probe_data(AVFormatContext *s, AVStream *st, AVProbeDa
/************************************************************/
/* input media file */
+#if FF_API_FORMAT_PARAMETERS
+static AVDictionary *convert_format_parameters(AVFormatParameters *ap)
+{
+ char buf[1024];
+ AVDictionary *opts = NULL;
+
+ if (ap->time_base.num) {
+ snprintf(buf, sizeof(buf), "%d/%d", ap->time_base.den, ap->time_base.num);
+ av_dict_set(&opts, "framerate", buf, 0);
+ }
+ if (ap->sample_rate) {
+ snprintf(buf, sizeof(buf), "%d", ap->sample_rate);
+ av_dict_set(&opts, "sample_rate", buf, 0);
+ }
+ if (ap->channels) {
+ snprintf(buf, sizeof(buf), "%d", ap->channels);
+ av_dict_set(&opts, "channels", buf, 0);
+ }
+ if (ap->width || ap->height) {
+ snprintf(buf, sizeof(buf), "%dx%d", ap->width, ap->height);
+ av_dict_set(&opts, "video_size", buf, 0);
+ }
+ if (ap->pix_fmt != PIX_FMT_NONE) {
+ av_dict_set(&opts, "pixel_format", av_get_pix_fmt_name(ap->pix_fmt), 0);
+ }
+ if (ap->channel) {
+ snprintf(buf, sizeof(buf), "%d", ap->channel);
+ av_dict_set(&opts, "channel", buf, 0);
+ }
+ if (ap->standard) {
+ av_dict_set(&opts, "standard", ap->standard, 0);
+ }
+ if (ap->mpeg2ts_compute_pcr) {
+ av_dict_set(&opts, "mpeg2ts_compute_pcr", "1", 0);
+ }
+ if (ap->initial_pause) {
+ av_dict_set(&opts, "initial_pause", "1", 0);
+ }
+ return opts;
+}
+
/**
* Open a media file from an IO stream. 'fmt' must be specified.
*/
@@ -401,6 +443,7 @@ int av_open_input_stream(AVFormatContext **ic_ptr,
AVInputFormat *fmt, AVFormatParameters *ap)
{
int err;
+ AVDictionary *opts;
AVFormatContext *ic;
AVFormatParameters default_ap;
@@ -408,6 +451,7 @@ int av_open_input_stream(AVFormatContext **ic_ptr,
ap=&default_ap;
memset(ap, 0, sizeof(default_ap));
}
+ opts = convert_format_parameters(ap);
if(!ap->prealloced_context)
ic = avformat_alloc_context();
@@ -417,63 +461,15 @@ int av_open_input_stream(AVFormatContext **ic_ptr,
err = AVERROR(ENOMEM);
goto fail;
}
- ic->iformat = fmt;
ic->pb = pb;
- ic->duration = AV_NOPTS_VALUE;
- ic->start_time = AV_NOPTS_VALUE;
- av_strlcpy(ic->filename, filename, sizeof(ic->filename));
-
- /* allocate private data */
- if (fmt->priv_data_size > 0) {
- ic->priv_data = av_mallocz(fmt->priv_data_size);
- if (!ic->priv_data) {
- err = AVERROR(ENOMEM);
- goto fail;
- }
- if (fmt->priv_class) {
- *(const AVClass**)ic->priv_data= fmt->priv_class;
- av_opt_set_defaults(ic->priv_data);
- }
- } else {
- ic->priv_data = NULL;
- }
-
- // e.g. AVFMT_NOFILE formats will not have a AVIOContext
- if (ic->pb)
- ff_id3v2_read(ic, ID3v2_DEFAULT_MAGIC);
-
- if (!(ic->flags&AVFMT_FLAG_PRIV_OPT) && ic->iformat->read_header) {
- err = ic->iformat->read_header(ic, ap);
- if (err < 0)
- goto fail;
- }
-
- if (!(ic->flags&AVFMT_FLAG_PRIV_OPT) && pb && !ic->data_offset)
- ic->data_offset = avio_tell(ic->pb);
- ic->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE;
+ err = avformat_open_input(ic_ptr, filename, fmt, &opts);
- *ic_ptr = ic;
- return 0;
- fail:
- if (ic) {
- int i;
- av_freep(&ic->priv_data);
- for(i=0;i<ic->nb_streams;i++) {
- AVStream *st = ic->streams[i];
- if (st) {
- av_free(st->priv_data);
- av_free(st->codec->extradata);
- av_free(st->codec);
- av_free(st->info);
- }
- av_free(st);
- }
- }
- av_free(ic);
- *ic_ptr = NULL;
+fail:
+ av_dict_free(&opts);
return err;
}
+#endif
int av_demuxer_open(AVFormatContext *ic, AVFormatParameters *ap){
int err;
@@ -562,68 +558,124 @@ int av_probe_input_buffer(AVIOContext *pb, AVInputFormat **fmt,
return ret;
}
+#if FF_API_FORMAT_PARAMETERS
int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
AVInputFormat *fmt,
int buf_size,
AVFormatParameters *ap)
{
int err;
- AVProbeData probe_data, *pd = &probe_data;
- AVIOContext *pb = NULL;
- void *logctx= ap && ap->prealloced_context ? *ic_ptr : NULL;
+ AVDictionary *opts = convert_format_parameters(ap);
- pd->filename = "";
- if (filename)
- pd->filename = filename;
- pd->buf = NULL;
- pd->buf_size = 0;
+ if (!ap->prealloced_context)
+ *ic_ptr = NULL;
+
+ err = avformat_open_input(ic_ptr, filename, fmt, &opts);
- if (!fmt) {
- /* guess format if no file can be opened */
- fmt = av_probe_input_format(pd, 0);
+ av_dict_free(&opts);
+ return err;
+}
+#endif
+
+/* open input file and probe the format if necessary */
+static int init_input(AVFormatContext *s, const char *filename)
+{
+ int ret;
+ AVProbeData pd = {filename, NULL, 0};
+
+ if (s->pb) {
+ s->flags |= AVFMT_FLAG_CUSTOM_IO;
+ if (!s->iformat)
+ return av_probe_input_buffer(s->pb, &s->iformat, filename, s, 0, 0);
+ else if (s->iformat->flags & AVFMT_NOFILE)
+ return AVERROR(EINVAL);
+ return 0;
}
- /* Do not open file if the format does not need it. XXX: specific
- hack needed to handle RTSP/TCP */
- if (!fmt || !(fmt->flags & AVFMT_NOFILE)) {
- /* if no file needed do not try to open one */
- if ((err=avio_open(&pb, filename, AVIO_FLAG_READ)) < 0) {
+ if ( (s->iformat && s->iformat->flags & AVFMT_NOFILE) ||
+ (!s->iformat && (s->iformat = av_probe_input_format(&pd, 0))))
+ return 0;
+
+ if ((ret = avio_open(&s->pb, filename, AVIO_FLAG_READ)) < 0)
+ return ret;
+ if (s->iformat)
+ return 0;
+ return av_probe_input_buffer(s->pb, &s->iformat, filename, s, 0, 0);
+}
+
+int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options)
+{
+ AVFormatContext *s = *ps;
+ int ret = 0;
+ AVFormatParameters ap = { 0 };
+ AVDictionary *tmp = NULL;
+
+ if (!s && !(s = avformat_alloc_context()))
+ return AVERROR(ENOMEM);
+ if (fmt)
+ s->iformat = fmt;
+
+ if (options)
+ av_dict_copy(&tmp, *options, 0);
+
+ if ((ret = av_opt_set_dict(s, &tmp)) < 0)
+ goto fail;
+
+ if ((ret = init_input(s, filename)) < 0)
+ goto fail;
+
+ /* check filename in case an image number is expected */
+ if (s->iformat->flags & AVFMT_NEEDNUMBER) {
+ if (!av_filename_number_test(filename)) {
+ ret = AVERROR(EINVAL);
goto fail;
}
- if (buf_size > 0) {
- ffio_set_buf_size(pb, buf_size);
- }
- if (!fmt && (err = av_probe_input_buffer(pb, &fmt, filename, logctx, 0, logctx ? (*ic_ptr)->probesize : 0)) < 0) {
+ }
+
+ s->duration = s->start_time = AV_NOPTS_VALUE;
+ av_strlcpy(s->filename, filename, sizeof(s->filename));
+
+ /* allocate private data */
+ if (s->iformat->priv_data_size > 0) {
+ if (!(s->priv_data = av_mallocz(s->iformat->priv_data_size))) {
+ ret = AVERROR(ENOMEM);
goto fail;
}
+ if (s->iformat->priv_class) {
+ *(const AVClass**)s->priv_data = s->iformat->priv_class;
+ av_opt_set_defaults(s->priv_data);
+ if ((ret = av_opt_set_dict(s->priv_data, &tmp)) < 0)
+ goto fail;
+ }
}
- /* if still no format found, error */
- if (!fmt) {
- err = AVERROR_INVALIDDATA;
- goto fail;
- }
+ /* e.g. AVFMT_NOFILE formats will not have a AVIOContext */
+ if (s->pb)
+ ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC);
- /* check filename in case an image number is expected */
- if (fmt->flags & AVFMT_NEEDNUMBER) {
- if (!av_filename_number_test(filename)) {
- err = AVERROR(EINVAL);
+ if (!(s->flags&AVFMT_FLAG_PRIV_OPT) && s->iformat->read_header)
+ if ((ret = s->iformat->read_header(s, &ap)) < 0)
goto fail;
- }
+
+ if (!(s->flags&AVFMT_FLAG_PRIV_OPT) && s->pb && !s->data_offset)
+ s->data_offset = avio_tell(s->pb);
+
+ s->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE;
+
+ if (options) {
+ av_dict_free(options);
+ *options = tmp;
}
- err = av_open_input_stream(ic_ptr, pb, filename, fmt, ap);
- if (err)
- goto fail;
+ *ps = s;
return 0;
- fail:
- av_freep(&pd->buf);
- if (pb)
- avio_close(pb);
- if (ap && ap->prealloced_context)
- av_free(*ic_ptr);
- *ic_ptr = NULL;
- return err;
+fail:
+ av_dict_free(&tmp);
+ if (s->pb && !(s->flags & AVFMT_FLAG_CUSTOM_IO))
+ avio_close(s->pb);
+ avformat_free_context(s);
+ *ps = NULL;
+ return ret;
}
/*******************************************************/
@@ -2615,7 +2667,8 @@ void avformat_free_context(AVFormatContext *s)
void av_close_input_file(AVFormatContext *s)
{
- AVIOContext *pb = s->iformat->flags & AVFMT_NOFILE ? NULL : s->pb;
+ AVIOContext *pb = (s->iformat->flags & AVFMT_NOFILE) || (s->flags & AVFMT_FLAG_CUSTOM_IO) ?
+ NULL : s->pb;
av_close_input_stream(s);
if (pb)
avio_close(pb);
@@ -2722,6 +2775,7 @@ AVChapter *ff_new_chapter(AVFormatContext *s, int id, AVRational time_base, int6
/************************************************************/
/* output media file */
+#if FF_API_FORMAT_PARAMETERS
int av_set_parameters(AVFormatContext *s, AVFormatParameters *ap)
{
if (s->oformat->priv_data_size > 0) {
@@ -2737,6 +2791,7 @@ int av_set_parameters(AVFormatContext *s, AVFormatParameters *ap)
return 0;
}
+#endif
int avformat_alloc_output_context2(AVFormatContext **avctx, AVOutputFormat *oformat,
const char *format, const char *filename)
@@ -2834,15 +2889,29 @@ static int validate_codec_tag(AVFormatContext *s, AVStream *st)
return 1;
}
+#if FF_API_FORMAT_PARAMETERS
int av_write_header(AVFormatContext *s)
{
- int ret, i;
+ return avformat_write_header(s, NULL);
+}
+#endif
+
+int avformat_write_header(AVFormatContext *s, AVDictionary **options)
+{
+ int ret = 0, i;
AVStream *st;
+ AVDictionary *tmp = NULL;
+
+ if (options)
+ av_dict_copy(&tmp, *options, 0);
+ if ((ret = av_opt_set_dict(s, &tmp)) < 0)
+ goto fail;
// some sanity checks
if (s->nb_streams == 0 && !(s->oformat->flags & AVFMT_NOSTREAMS)) {
av_log(s, AV_LOG_ERROR, "no streams\n");
- return AVERROR(EINVAL);
+ ret = AVERROR(EINVAL);
+ goto fail;
}
for(i=0;i<s->nb_streams;i++) {
@@ -2852,7 +2921,8 @@ int av_write_header(AVFormatContext *s)
case AVMEDIA_TYPE_AUDIO:
if(st->codec->sample_rate<=0){
av_log(s, AV_LOG_ERROR, "sample rate not set\n");
- return AVERROR(EINVAL);
+ ret = AVERROR(EINVAL);
+ goto fail;
}
if(!st->codec->block_align)
st->codec->block_align = st->codec->channels *
@@ -2861,15 +2931,18 @@ int av_write_header(AVFormatContext *s)
case AVMEDIA_TYPE_VIDEO:
if(st->codec->time_base.num<=0 || st->codec->time_base.den<=0){ //FIXME audio too?
av_log(s, AV_LOG_ERROR, "time base not set\n");
- return AVERROR(EINVAL);
+ ret = AVERROR(EINVAL);
+ goto fail;
}
if((st->codec->width<=0 || st->codec->height<=0) && !(s->oformat->flags & AVFMT_NODIMENSIONS)){
av_log(s, AV_LOG_ERROR, "dimensions not set\n");
- return AVERROR(EINVAL);
+ ret = AVERROR(EINVAL);
+ goto fail;
}
if(av_cmp_q(st->sample_aspect_ratio, st->codec->sample_aspect_ratio)){
av_log(s, AV_LOG_ERROR, "Aspect ratio mismatch between encoder and muxer layer\n");
- return AVERROR(EINVAL);
+ ret = AVERROR(EINVAL);
+ goto fail;
}
break;
}
@@ -2886,7 +2959,8 @@ int av_write_header(AVFormatContext *s)
av_log(s, AV_LOG_ERROR,
"Tag %s/0x%08x incompatible with output codec id '%d'\n",
tagbuf, st->codec->codec_tag, st->codec->codec_id);
- return AVERROR_INVALIDDATA;
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
}
}else
st->codec->codec_tag= av_codec_get_tag(s->oformat->codec_tag, st->codec->codec_id);
@@ -2899,8 +2973,16 @@ int av_write_header(AVFormatContext *s)
if (!s->priv_data && s->oformat->priv_data_size > 0) {
s->priv_data = av_mallocz(s->oformat->priv_data_size);
- if (!s->priv_data)
- return AVERROR(ENOMEM);
+ if (!s->priv_data) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+ if (s->oformat->priv_class) {
+ *(const AVClass**)s->priv_data= s->oformat->priv_class;
+ av_opt_set_defaults(s->priv_data);
+ if ((ret = av_opt_set_dict(s->priv_data, &tmp)) < 0)
+ goto fail;
+ }
}
/* set muxer identification string */
@@ -2911,7 +2993,7 @@ int av_write_header(AVFormatContext *s)
if(s->oformat->write_header){
ret = s->oformat->write_header(s);
if (ret < 0)
- return ret;
+ goto fail;
}
/* init PTS generation */
@@ -2930,12 +3012,22 @@ int av_write_header(AVFormatContext *s)
break;
}
if (den != AV_NOPTS_VALUE) {
- if (den <= 0)
- return AVERROR_INVALIDDATA;
+ if (den <= 0) {
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
av_frac_init(&st->pts, 0, 0, den);
}
}
+
+ if (options) {
+ av_dict_free(options);
+ *options = tmp;
+ }
return 0;
+fail:
+ av_dict_free(&tmp);
+ return ret;
}
//FIXME merge with compute_pkt_fields
diff --git a/libavformat/version.h b/libavformat/version.h
index 48224f8506..691f9c0569 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -24,8 +24,8 @@
#include "libavutil/avutil.h"
#define LIBAVFORMAT_VERSION_MAJOR 53
-#define LIBAVFORMAT_VERSION_MINOR 3
-#define LIBAVFORMAT_VERSION_MICRO 1
+#define LIBAVFORMAT_VERSION_MINOR 4
+#define LIBAVFORMAT_VERSION_MICRO 0
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
LIBAVFORMAT_VERSION_MINOR, \
diff --git a/libavutil/avutil.h b/libavutil/avutil.h
index 500c700851..36dcf8f718 100644
--- a/libavutil/avutil.h
+++ b/libavutil/avutil.h
@@ -40,7 +40,7 @@
#define AV_VERSION(a, b, c) AV_VERSION_DOT(a, b, c)
#define LIBAVUTIL_VERSION_MAJOR 51
-#define LIBAVUTIL_VERSION_MINOR 8
+#define LIBAVUTIL_VERSION_MINOR 9
#define LIBAVUTIL_VERSION_MICRO 0
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
@@ -63,6 +63,9 @@
#ifndef FF_API_GET_BITS_PER_SAMPLE_FMT
#define FF_API_GET_BITS_PER_SAMPLE_FMT (LIBAVUTIL_VERSION_MAJOR < 52)
#endif
+#ifndef FF_API_FIND_OPT
+#define FF_API_FIND_OPT (LIBAVUTIL_VERSION_MAJOR < 52)
+#endif
/**
* Return the LIBAVUTIL_VERSION_INT constant.
diff --git a/libavutil/dict.c b/libavutil/dict.c
index 332eccd679..74301fbf11 100644
--- a/libavutil/dict.c
+++ b/libavutil/dict.c
@@ -19,6 +19,7 @@
*/
#include <strings.h>
+#include "avstring.h"
#include "dict.h"
#include "internal.h"
#include "mem.h"
@@ -51,6 +52,7 @@ int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags
{
AVDictionary *m = *pm;
AVDictionaryEntry *tag = av_dict_get(m, key, NULL, flags);
+ char *oldval = NULL;
if(!m)
m = *pm = av_mallocz(sizeof(*m));
@@ -58,7 +60,10 @@ int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags
if(tag) {
if (flags & AV_DICT_DONT_OVERWRITE)
return 0;
- av_free(tag->value);
+ if (flags & AV_DICT_APPEND)
+ oldval = tag->value;
+ else
+ av_free(tag->value);
av_free(tag->key);
*tag = m->elems[--m->count];
} else {
@@ -75,6 +80,12 @@ int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags
m->elems[m->count].key = av_strdup(key );
if (flags & AV_DICT_DONT_STRDUP_VAL) {
m->elems[m->count].value = value;
+ } else if (oldval && flags & AV_DICT_APPEND) {
+ int len = strlen(oldval) + strlen(value) + 1;
+ if (!(oldval = av_realloc(oldval, len)))
+ return AVERROR(ENOMEM);
+ av_strlcat(oldval, value, len);
+ m->elems[m->count].value = oldval;
} else
m->elems[m->count].value = av_strdup(value);
m->count++;
diff --git a/libavutil/dict.h b/libavutil/dict.h
index 19cc0915d8..421be32244 100644
--- a/libavutil/dict.h
+++ b/libavutil/dict.h
@@ -29,6 +29,8 @@
#define AV_DICT_DONT_STRDUP_KEY 4
#define AV_DICT_DONT_STRDUP_VAL 8
#define AV_DICT_DONT_OVERWRITE 16 ///< Don't overwrite existing entries.
+#define AV_DICT_APPEND 32 /**< If the entry already exists, append to it. Note that no
+ delimiter is added, the strings are simply concatenated. */
typedef struct {
char *key;
diff --git a/libavutil/intreadwrite.h b/libavutil/intreadwrite.h
index 1849a64661..09d796c8b8 100644
--- a/libavutil/intreadwrite.h
+++ b/libavutil/intreadwrite.h
@@ -229,11 +229,11 @@ union unaligned_16 { uint16_t l; } __attribute__((packed)) av_alias;
#endif
#ifndef AV_RB32
-# define AV_RB32(x) \
- ((((const uint8_t*)(x))[0] << 24) | \
- (((const uint8_t*)(x))[1] << 16) | \
- (((const uint8_t*)(x))[2] << 8) | \
- ((const uint8_t*)(x))[3])
+# define AV_RB32(x) \
+ (((uint32_t)((const uint8_t*)(x))[0] << 24) | \
+ (((const uint8_t*)(x))[1] << 16) | \
+ (((const uint8_t*)(x))[2] << 8) | \
+ ((const uint8_t*)(x))[3])
#endif
#ifndef AV_WB32
# define AV_WB32(p, d) do { \
@@ -245,11 +245,11 @@ union unaligned_16 { uint16_t l; } __attribute__((packed)) av_alias;
#endif
#ifndef AV_RL32
-# define AV_RL32(x) \
- ((((const uint8_t*)(x))[3] << 24) | \
- (((const uint8_t*)(x))[2] << 16) | \
- (((const uint8_t*)(x))[1] << 8) | \
- ((const uint8_t*)(x))[0])
+# define AV_RL32(x) \
+ (((uint32_t)((const uint8_t*)(x))[3] << 24) | \
+ (((const uint8_t*)(x))[2] << 16) | \
+ (((const uint8_t*)(x))[1] << 8) | \
+ ((const uint8_t*)(x))[0])
#endif
#ifndef AV_WL32
# define AV_WL32(p, d) do { \
diff --git a/libavutil/log.h b/libavutil/log.h
index c87125d2d5..149225dadf 100644
--- a/libavutil/log.h
+++ b/libavutil/log.h
@@ -70,6 +70,13 @@ typedef struct {
* can be NULL of course
*/
int parent_log_context_offset;
+
+ /**
+ * A function for extended searching, e.g. in possible
+ * children objects.
+ */
+ const struct AVOption* (*opt_find)(void *obj, const char *name, const char *unit,
+ int opt_flags, int search_flags);
} AVClass;
/* av_log API */
diff --git a/libavutil/opt.c b/libavutil/opt.c
index d57a547377..8c351488a8 100644
--- a/libavutil/opt.c
+++ b/libavutil/opt.c
@@ -29,7 +29,9 @@
#include "avstring.h"
#include "opt.h"
#include "eval.h"
+#include "dict.h"
+#if FF_API_FIND_OPT
//FIXME order them and do a bin search
const AVOption *av_find_opt(void *v, const char *name, const char *unit, int mask, int flags)
{
@@ -41,6 +43,7 @@ const AVOption *av_find_opt(void *v, const char *name, const char *unit, int mas
}
return NULL;
}
+#endif
const AVOption *av_next_option(void *obj, const AVOption *last)
{
@@ -51,7 +54,7 @@ const AVOption *av_next_option(void *obj, const AVOption *last)
static int av_set_number2(void *obj, const char *name, double num, int den, int64_t intnum, const AVOption **o_out)
{
- const AVOption *o= av_find_opt(obj, name, NULL, 0, 0);
+ const AVOption *o = av_opt_find(obj, name, NULL, 0, 0);
void *dst;
if (o_out)
*o_out= o;
@@ -114,7 +117,7 @@ static int hexchar2int(char c) {
int av_set_string3(void *obj, const char *name, const char *val, int alloc, const AVOption **o_out)
{
int ret;
- const AVOption *o= av_find_opt(obj, name, NULL, 0, 0);
+ const AVOption *o = av_opt_find(obj, name, NULL, 0, 0);
if (o_out)
*o_out = o;
if (!o)
@@ -161,7 +164,7 @@ int av_set_string3(void *obj, const char *name, const char *val, int alloc, cons
buf[i]=0;
{
- const AVOption *o_named= av_find_opt(obj, buf, o->unit, 0, 0);
+ const AVOption *o_named = av_opt_find(obj, buf, o->unit, 0, 0);
if (o_named && o_named->type == FF_OPT_TYPE_CONST)
d= o_named->default_val.dbl;
else if (!strcmp(buf, "default")) d= o->default_val.dbl;
@@ -226,7 +229,7 @@ const AVOption *av_set_int(void *obj, const char *name, int64_t n)
*/
const char *av_get_string(void *obj, const char *name, const AVOption **o_out, char *buf, int buf_len)
{
- const AVOption *o= av_find_opt(obj, name, NULL, 0, 0);
+ const AVOption *o = av_opt_find(obj, name, NULL, 0, 0);
void *dst;
uint8_t *bin;
int len, i;
@@ -259,7 +262,7 @@ const char *av_get_string(void *obj, const char *name, const AVOption **o_out, c
static int av_get_number(void *obj, const char *name, const AVOption **o_out, double *num, int *den, int64_t *intnum)
{
- const AVOption *o= av_find_opt(obj, name, NULL, 0, 0);
+ const AVOption *o = av_opt_find(obj, name, NULL, 0, 0);
void *dst;
if (!o || (o->offset<=0 && o->type != FF_OPT_TYPE_CONST))
goto error;
@@ -538,6 +541,45 @@ void av_opt_free(void *obj)
av_freep((uint8_t *)obj + o->offset);
}
+int av_opt_set_dict(void *obj, AVDictionary **options)
+{
+ AVDictionaryEntry *t = NULL;
+ AVDictionary *tmp = NULL;
+ int ret = 0;
+
+ while ((t = av_dict_get(*options, "", t, AV_DICT_IGNORE_SUFFIX))) {
+ ret = av_set_string3(obj, t->key, t->value, 1, NULL);
+ if (ret == AVERROR_OPTION_NOT_FOUND)
+ av_dict_set(&tmp, t->key, t->value, 0);
+ else if (ret < 0) {
+ av_log(obj, AV_LOG_ERROR, "Error setting option %s to value %s.\n", t->key, t->value);
+ break;
+ }
+ ret = 0;
+ }
+ av_dict_free(options);
+ *options = tmp;
+ return ret;
+}
+
+const AVOption *av_opt_find(void *obj, const char *name, const char *unit,
+ int opt_flags, int search_flags)
+{
+ AVClass *c = *(AVClass**)obj;
+ const AVOption *o = NULL;
+
+ if (c->opt_find && search_flags & AV_OPT_SEARCH_CHILDREN &&
+ (o = c->opt_find(obj, name, unit, opt_flags, search_flags)))
+ return o;
+
+ while (o = av_next_option(obj, o)) {
+ if (!strcmp(o->name, name) && (!unit || (o->unit && !strcmp(o->unit, unit))) &&
+ (o->flags & opt_flags) == opt_flags)
+ return o;
+ }
+ return NULL;
+}
+
#ifdef TEST
#undef printf
diff --git a/libavutil/opt.h b/libavutil/opt.h
index 872b5547c1..97a1cb5774 100644
--- a/libavutil/opt.h
+++ b/libavutil/opt.h
@@ -29,6 +29,7 @@
#include "rational.h"
#include "avutil.h"
+#include "dict.h"
enum AVOptionType{
FF_OPT_TYPE_FLAGS,
@@ -91,6 +92,7 @@ typedef struct AVOption {
const char *unit;
} AVOption;
+#if FF_API_FIND_OPT
/**
* Look for an option in obj. Look only for the options which
* have the flags set as specified in mask and flags (that is,
@@ -102,8 +104,12 @@ typedef struct AVOption {
* @param[in] unit the unit of the option to look for, or any if NULL
* @return a pointer to the option found, or NULL if no option
* has been found
+ *
+ * @deprecated use av_opt_find.
*/
+attribute_deprecated
const AVOption *av_find_opt(void *obj, const char *name, const char *unit, int mask, int flags);
+#endif
/**
* Set the field of obj with the given name to value.
@@ -191,4 +197,46 @@ void av_opt_free(void *obj);
*/
int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name);
+/*
+ * Set all the options from a given dictionary on an object.
+ *
+ * @param obj a struct whose first element is a pointer to AVClass
+ * @param options options to process. This dictionary will be freed and replaced
+ * by a new one containing all options not found in obj.
+ * Of course this new dictionary needs to be freed by caller
+ * with av_dict_free().
+ *
+ * @return 0 on success, a negative AVERROR if some option was found in obj,
+ * but could not be set.
+ *
+ * @see av_dict_copy()
+ */
+int av_opt_set_dict(void *obj, struct AVDictionary **options);
+
+#define AV_OPT_SEARCH_CHILDREN 0x0001 /**< Search in possible children of the
+ given object first. */
+
+/**
+ * Look for an option in an object. Consider only options which
+ * have all the specified flags set.
+ *
+ * @param[in] obj A pointer to a struct whose first element is a
+ * pointer to an AVClass.
+ * @param[in] name The name of the option to look for.
+ * @param[in] unit When searching for named constants, name of the unit
+ * it belongs to.
+ * @param opt_flags Find only options with all the specified flags set (AV_OPT_FLAG).
+ * @param search_flags A combination of AV_OPT_SEARCH_*.
+ *
+ * @return A pointer to the option found, or NULL if no option
+ * was found.
+ *
+ * @note Options found with AV_OPT_SEARCH_CHILDREN flag may not be settable
+ * directly with av_set_string3(). Use special calls which take an options
+ * AVDictionary (e.g. avformat_open_input()) to set options found with this
+ * flag.
+ */
+const AVOption *av_opt_find(void *obj, const char *name, const char *unit,
+ int opt_flags, int search_flags);
+
#endif /* AVUTIL_OPT_H */