diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2011-06-18 04:40:18 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2011-06-18 05:10:38 +0200 |
commit | 2905e3ff6462431d55f89614b24e2a407707c82a (patch) | |
tree | d482d458a449228c8475942117c7eb81ec8934c6 /libavformat | |
parent | 44d1b4088f2959912a27ffbffc5884db1b35a645 (diff) | |
parent | 78440c007cd310bb27ac2af5fb7ea5b7555efc84 (diff) | |
download | ffmpeg-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>
Diffstat (limited to 'libavformat')
-rw-r--r-- | libavformat/applehttp.c | 9 | ||||
-rw-r--r-- | libavformat/avformat.h | 64 | ||||
-rw-r--r-- | libavformat/avidec.c | 8 | ||||
-rw-r--r-- | libavformat/options.c | 28 | ||||
-rw-r--r-- | libavformat/rdt.c | 4 | ||||
-rw-r--r-- | libavformat/rtpdec_asf.c | 7 | ||||
-rw-r--r-- | libavformat/rtpenc_chain.c | 2 | ||||
-rw-r--r-- | libavformat/sapdec.c | 7 | ||||
-rw-r--r-- | libavformat/utils.c | 304 | ||||
-rw-r--r-- | libavformat/version.h | 4 |
10 files changed, 311 insertions, 126 deletions
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, \ |