Merge commit '9f61abc8111c7c43f49ca012e957a108b9cc7610'
authorDerek Buitenhuis <derek.buitenhuis@gmail.com>
Wed, 10 Feb 2016 14:40:32 +0000 (14:40 +0000)
committerDerek Buitenhuis <derek.buitenhuis@gmail.com>
Wed, 10 Feb 2016 14:42:41 +0000 (14:42 +0000)
This also deprecates our old duplicated callbacks.

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

Merged-by: Derek Buitenhuis <derek.buitenhuis@gmail.com>
19 files changed:
1  2 
doc/APIchanges
libavformat/avformat.h
libavformat/dashenc.c
libavformat/hdsenc.c
libavformat/hls.c
libavformat/hlsenc.c
libavformat/img2dec.c
libavformat/img2enc.c
libavformat/internal.h
libavformat/mlvdec.c
libavformat/mov.c
libavformat/movenc.c
libavformat/options.c
libavformat/segment.c
libavformat/smoothstreamingenc.c
libavformat/tee.c
libavformat/utils.c
libavformat/version.h
libavformat/webm_chunk.c

diff --combined doc/APIchanges
@@@ -1,5 -1,5 +1,5 @@@
  Never assume the API of libav* to be stable unless at least 1 month has passed
 -since the last major version increase.
 +since the last major version increase or the API was added.
  
  The last version increases were:
  libavcodec:    2015-08-28
@@@ -7,60 -7,47 +7,63 @@@ libavdevice:   2015-08-2
  libavfilter:   2015-08-28
  libavformat:   2015-08-28
  libavresample: 2015-08-28
 +libpostproc:   2015-08-28
 +libswresample: 2015-08-28
  libswscale:    2015-08-28
  libavutil:     2015-08-28
  
  
  API changes, most recent first:
  
 -2016-xx-xx - xxxxxxx - lavf 57.3.0 - avformat.h
++2016-xx-xx - xxxxxxx - lavf 57.25.0 - avformat.h
+   Add AVFormatContext.opaque, io_open and io_close, allowing custom IO
 -  for muxers and demuxers that open additional files.
 -2015-xx-xx - xxxxxxx - lavc 57.12.0 - avcodec.h
 +2016-02-01 - xxxxxxx - lavf 57.24.100
 +  Add protocol_whitelist to AVFormatContext, AVIOContext
 +
 +2016-01-31 - xxxxxxx - lavu 55.17.100
 +  Add AV_FRAME_DATA_GOP_TIMECODE for exporting MPEG1/2 GOP timecodes.
 +
 +2016-01-01 - xxxxxxx - lavc 57.21.100 / 57.12.0 - avcodec.h
    Add AVCodecDescriptor.profiles and avcodec_profile_name().
  
 -2015-xx-xx - xxxxxxx - lavc 57.11.0 - avcodec.h dirac.h
 +2015-12-28 - xxxxxxx - lavf 57.21.100 - avformat.h
 +  Add automatic bitstream filtering; add av_apply_bitstream_filters()
 +
 +2015-12-22 - xxxxxxx - lavfi 6.21.101 - avfilter.h
 +  Deprecate avfilter_link_set_closed().
 +  Applications are not supposed to mess with links,
 +  they should close the sinks.
 +
 +2015-12-17 - lavc 57.18.100 / 57.11.0 - avcodec.h dirac.h
    xxxxxxx - Add av_packet_add_side_data().
    xxxxxxx - Add AVCodecContext.coded_side_data.
    xxxxxxx - Add AVCPBProperties API.
    xxxxxxx - Add a new public header dirac.h containing
              av_dirac_parse_sequence_header()
  
 -2015-xx-xx - xxxxxxx - lavc 57.9.1 - avcodec.h
 +2015-12-11 - xxxxxxx - lavf 57.20.100 - avformat.h
 +  Add av_program_add_stream_index()
 +
 +2015-11-29 - xxxxxxx - lavc 57.16.101 - avcodec.h
    Deprecate rtp_callback without replacement, i.e. it won't be possible to
    get image slices before the full frame is encoded any more. The libavformat
    rtpenc muxer can still be used for RFC-2190 packetization.
  
 -2015-11-xx - xxxxxxx - lavc 57.9.0 - avcodec.h
 +2015-11-xx - xxxxxxx - lavc 57.16.0 - avcodec.h
    Add AV_PKT_DATA_FALLBACK_TRACK for making fallback associations between
    streams.
  
 -2015-11-xx - xxxxxxx - lavf 57.1.0 - avformat.h
 +2015-11-xx - xxxxxxx - lavf 57.19.100 - avformat.h
    Add av_stream_new_side_data().
  
 -2015-11-xx - xxxxxxx - lavu 55.3.0 - xtea.h
 +2015-11-xx - xxxxxxx - lavu 55.8.100 - xtea.h
      Add av_xtea_le_init and av_xtea_le_crypt
  
 -2015-11-xx - xxxxxxx - lavfi 6.1.0 - avfilter.h
 -    Add a frame_rate field to AVFilterLink
 +2015-11-18 - lavu 55.7.100 - mem.h
 +  Add av_fast_mallocz()
  
 -2015-xx-xx - xxxxxxx - lavc 57.6.0 - avcodec.h
 -
 -2015-xx-xx - lavc 57.7.0 - avcodec.h
 +2015-10-29 - lavc 57.12.100 / 57.8.0 - avcodec.h
    xxxxxx - Deprecate av_free_packet(). Use av_packet_unref() as replacement,
             it resets the packet in a more consistent way.
    xxxxxx - Deprecate av_dup_packet(), it is a no-op for most cases.
    xxxxxx - Add av_packet_alloc(), av_packet_clone(), av_packet_free().
             They match the AVFrame functions with the same name.
  
 -2015-xx-xx - xxxxxxx - lavc 57.5.0 - avcodec.h
 +2015-10-27 - xxxxxxx - lavu 55.5.100 - cpu.h
 +  Add AV_CPU_FLAG_AESNI.
 +
 +2015-10-22 - xxxxxxx - lavc 57.9.100 / lavc 57.5.0 - avcodec.h
    Add data and linesize array to AVSubtitleRect, to be used instead of
    the ones from the embedded AVPicture.
  
 -2015-xx-xx - xxxxxxx - lavc 57.0.0 - qsv.h
 +2015-10-22 - xxxxxxx - lavc 57.8.100 / lavc 57.0.0 - qsv.h
    Add an API for allocating opaque surfaces.
  
 -2015-xx-xx - xxxxxxx - lavu 55.2.0 - dict.h
 +2015-10-15 - xxxxxxx - lavf 57.4.100
 +  Remove the latm demuxer that was a duplicate of the loas demuxer.
 +
 +2015-10-14 - xxxxxxx - lavu 55.4.100 / lavu 55.2.0 - dict.h
    Change return type of av_dict_copy() from void to int, so that a proper
    error code can be reported.
  
 -2015-09-29 - 948f3c1 - lavc 57.0.0 - avcodec.h
 +2015-09-29 - b01891a / 948f3c1 - lavc 57.3.100 / lavc 57.2.0 - avcodec.h
    Change type of AVPacket.duration from int to int64_t.
  
 -2015-09-18 - e3d4784 - lavc 57.2.0 - d3d11va.h
 +2015-09-17 - 7c46f24 / e3d4784 - lavc 57.3.100 / lavc 57.2.0 - d3d11va.h
    Add av_d3d11va_alloc_context(). This function must from now on be used for
    allocating AVD3D11VAContext.
  
 -2015-09-07 - lavu 55.0.0
 -  b8b5d82 - Change type of AVPixFmtDescriptor.flags from uint8_t to uint64_t.
 -  6b3ef7f - Change type of AVComponentDescriptor fields from uint16_t to int
 +2015-09-15 - lavf 57.2.100 - avformat.h
 +  probesize and max_analyze_duration switched to 64bit, both
 +  are only accessible through AVOptions
 +
 +2015-09-15 - lavf 57.1.100 - avformat.h
 +  bit_rate was changed to 64bit, make sure you update any
 +  printf() or other type sensitive code
 +
 +2015-09-15 - lavc 57.2.100 - avcodec.h
 +  bit_rate/rc_max_rate/rc_min_rate were changed to 64bit, make sure you update
 +  any printf() or other type sensitive code
 +
 +2015-09-07 - lavu 55.0.100 / lavu 55.0.0
 +  c734b34 / b8b5d82 - Change type of AVPixFmtDescriptor.flags from uint8_t to uint64_t.
 +  f53569a / 6b3ef7f - Change type of AVComponentDescriptor fields from uint16_t to int
              and drop bit packing.
 -  2268db2 - Add step, offset, and depth to AVComponentDescriptor to replace
 +  151aa2e / 2268db2 - Add step, offset, and depth to AVComponentDescriptor to replace
              the deprecated step_minus1, offset_plus1, and depth_minus1.
  
 -2015-07-31 - lavu 54.17.0
 -  7a7df34 - Add av_blowfish_alloc().
 -  ae36545 - Add av_rc4_alloc().
 -  5d8bea3 - Add av_xtea_alloc().
 -  d9e8b47 - Add av_des_alloc().
 +-------- 8< --------- FFmpeg 2.8 was cut here -------- 8< ---------
 +
 +2015-08-27 - 1dd854e1 - lavc 56.58.100 - vaapi.h
 +  Deprecate old VA-API context (vaapi_context) fields that were only
 +  set and used by libavcodec. They are all managed internally now.
 +
 +2015-08-19 - 9f8e57ef - lavu 54.31.100 - pixfmt.h
 +  Add a unique pixel format for VA-API (AV_PIX_FMT_VAAPI) that
 +  indicates the nature of the underlying storage: a VA surface. This
 +  yields the same value as AV_PIX_FMT_VAAPI_VLD.
 +  Deprecate old VA-API related pixel formats: AV_PIX_FMT_VAAPI_MOCO,
 +  AV_PIX_FMT_VAAPI_IDCT, AV_PIX_FMT_VAAPI_VLD.
  
 -2015-07-29 - 7e38340 - lavu 54.16.0 - hmac.h
 -  Add AV_HMAC_SHA224 and AV_HMAC_SHA256.
 +2015-08-02 - lavu 54.30.100 / 54.17.0
 +  9ed59f1 / 7a7df34c -  Add av_blowfish_alloc().
 +  a130ec9 / ae365453 -  Add av_rc4_alloc().
 +  9ca1997 / 5d8bea3b -  Add av_xtea_alloc().
 +  3cf08e9 / d9e8b47e -  Add av_des_alloc().
  
 -2015-07-27 - lavc 56.35.0 - avcodec.h
 -  7c6eb0a - Rename CODEC_FLAG* defines to AV_CODEC_FLAG*.
 -  def9785 - Rename CODEC_CAP_* defines to AV_CODEC_CAP_*.
 -  059a934 - Rename FF_INPUT_BUFFER_PADDING_SIZE and FF_MIN_BUFFER_SIZE
 -            to AV_INPUT_BUFFER_PADDING_SIZE and AV_INPUT_BUFFER_MIN_SIZE.
 +2015-07-27 - lavc 56.56.100 / 56.35.0 - avcodec.h
 +  94d68a4 / 7c6eb0a1 - Rename CODEC_FLAG* defines to AV_CODEC_FLAG*.
 +  444e987 / def97856 - Rename CODEC_CAP_* defines to AV_CODEC_CAP_*.
 +  29d147c / 059a9348 - Rename FF_INPUT_BUFFER_PADDING_SIZE and FF_MIN_BUFFER_SIZE
 +              to AV_INPUT_BUFFER_PADDING_SIZE and AV_INPUT_BUFFER_MIN_SIZE.
  
 -2015-07-20 - 5d3addb - lavc 56.33.0 - avcodec.h
 -  Add AV_PKT_DATA_QUALITY_FACTOR to export the quality value of an AVPacket.
 +2015-07-22 - c40ecff - lavc 56.51.100 - avcodec.h
 +  Add AV_PKT_DATA_QUALITY_STATS to export the quality value, PSNR, and pict_type
 +  of an AVPacket.
  
 -2015-07-02 - 1316df7 - lavu 56.15.0
 +2015-07-16 - 8dad213 - lavc 56.49.100
 +  Add av_codec_get_codec_properties(), FF_CODEC_PROPERTY_LOSSLESS
 +  and FF_CODEC_PROPERTY_CLOSED_CAPTIONS
 +
 +2015-07-03 - d563e13 / 83212943 - lavu 54.28.100 / 56.15.0
    Add av_version_info().
  
 -2015-07-01 - 0d449c8 - lavfi 5.1.0 - version.h
 -             0f87f9b - lavd 55.2.0 - version.h
 -  Add library identification symbols, LIBAVFILTER_IDENT and LIBAVDEVICE_IDENT.
 +-------- 8< --------- FFmpeg 2.7 was cut here -------- 8< ---------
  
 -2015-06-07 - 252d620 - lavf 56.20.0 - avio.h
 -  Add avio_put_str16be.
 +2015-06-04 - cc17b43 - lswr  1.2.100
 +  Add swr_get_out_samples()
  
 -2015-05-13 - f7cafb5 - lavu 54.14.0 - cpu.h
 +2015-05-27 - c312bfa - lavu 54.26.100 - cpu.h
    Add AV_CPU_FLAG_AVXSLOW.
  
 -2015-05-13 - e7c5e17 - lavc 56.23.0
 +2015-05-26 - 1fb9b2a - lavu 54.25.100 - rational.h
 +  Add av_q2intfloat().
 +
 +2015-05-13 - cc48409 / e7c5e17 - lavc 56.39.100 / 56.23.0
    Add av_vda_default_init2.
  
 -2015-04-19 - c253340 - lavu 54.12.0
 +2015-05-11 - 541d75f - lavf 56.33.100 - avformat.h
 +  Add AVOpenCallback AVFormatContext.open_cb
 +
 +2015-05-07 - a7dd933 - 56.38.100 - avcodec.h
 +  Add av_packet_side_data_name().
 +
 +2015-05-07 - 01e59d4 - 56.37.102 - avcodec.h
 +  Add FF_PROFILE_VP9_2 and FF_PROFILE_VP9_3.
 +
 +2015-05-04 - 079b7f6 - 56.37.100 - avcodec.h
 +  Add FF_PROFILE_VP9_0 and FF_PROFILE_VP9_1.
 +
 +2015-04-22 - 748d481 - lavf 56.31.100 - avformat.h
 +  Add AVFMT_FLAG_FAST_SEEK flag. Some formats (initially mp3) use it to enable
 +  fast, but inaccurate seeking.
 +
 +2015-04-20 - 8e8219e / c253340 - lavu 54.23.100 / 54.12.0 - log.h
    Add AV_LOG_TRACE for extremely verbose debugging.
  
 -2015-04-07 - 27f2746 - lavu 54.11.0
 -  Add av_small_strptime().
 +2015-04-02 - 26e0e393 - lavf 56.29.100 - avio.h
 +  Add AVIODirEntryType.AVIO_ENTRY_SERVER.
 +  Add AVIODirEntryType.AVIO_ENTRY_SHARE.
 +  Add AVIODirEntryType.AVIO_ENTRY_WORKGROUP.
  
 -2015-03-29 - 6fe2641 - lavc 56.22.0
 -  Add FF_PROFILE_DTS_EXPRESS.
 +2015-03-31 - 3188696 - lavu 54.22.100 - avstring.h
 +  Add av_append_path_component()
  
 -2015-03-29 - c484561 - lavu 54.10.0
 +2015-03-27 - 184084c - lavf 56.27.100 - avio.h url.h
 +  New directory listing API.
 +
 +  Add AVIODirEntryType enum.
 +  Add AVIODirEntry, AVIODirContext structures.
 +  Add avio_open_dir(), avio_read_dir(), avio_close_dir(), avio_free_directory_entry().
 +  Add ff_alloc_dir_entry().
 +  Extend URLProtocol with url_open_dir(), url_read_dir(), url_close_dir().
 +
 +2015-03-29 - 268ff17 / c484561 - lavu 54.21.100 / 54.10.0 - pixfmt.h
    Add AV_PIX_FMT_MMAL for MMAL hardware acceleration.
  
 -2015-02-19 - 31d2039 - lavc 56.13
 +2015-03-19 - 11fe56c - 56.29.100 / lavc 56.22.0
 +  Add FF_PROFILE_DTS_EXPRESS.
 +
 +-------- 8< --------- FFmpeg 2.6 was cut here -------- 8< ---------
 +
 +2015-03-04 - cca4476 - lavf 56.25.100
 +  Add avformat_flush()
 +
 +2015-03-03 - 81a9126 - lavf 56.24.100
 +  Add avio_put_str16be()
 +
 +2015-02-19 - 560eb71 / 31d2039 - lavc 56.23.100 / 56.13.0
    Add width, height, coded_width, coded_height and format to
    AVCodecParserContext.
  
 -2015-02-19 - 5b1d9ce - lavu 54.9.0
 +2015-02-19 - e375511 / 5b1d9ce - lavu 54.19.100 / 54.9.0
    Add AV_PIX_FMT_QSV for QSV hardware acceleration.
  
 -2015-01-27 - 728685f - lavc 56.12.0, lavu 54.8.0 - avcodec.h, frame.h
 +2015-02-14 - ba22295 - lavc 56.21.102
 +  Deprecate VIMA decoder.
 +
 +2015-01-27 - 62a82c6 / 728685f - lavc 56.21.100 / 56.12.0, lavu 54.18.100 / 54.8.0 - avcodec.h, frame.h
    Add AV_PKT_DATA_AUDIO_SERVICE_TYPE and AV_FRAME_DATA_AUDIO_SERVICE_TYPE for
    storing the audio service type as side data.
  
 -2015-01-14 - e2ad0b6 - lavu 54.6.0 - imgutils.h
 -  Add utility functions for image manipulation: av_image_get_buffer_size()
 -  av_image_fill_arrays() and av_image_copy_to_buffer().
 +2015-01-16 - a47c933 - lavf 56.19.100 - avformat.h
 +  Add data_codec and data_codec_id for storing codec of data stream
  
 -2014-12-25 - c220a60 - lavc 56.10.0 - vdpau.h
 +2015-01-11 - 007c33d - lavd 56.4.100 - avdevice.h
 +  Add avdevice_list_input_sources().
 +  Add avdevice_list_output_sinks().
 +
 +2014-12-25 - d7aaeea / c220a60 - lavc 56.19.100 / 56.10.0 - vdpau.h
    Add av_vdpau_get_surface_parameters().
  
 -2014-12-25 - 6c99c92 - lavc 56.9.0 - avcodec.h
 +2014-12-25 - ddb9a24 / 6c99c92 - lavc 56.18.100 / 56.9.0 - avcodec.h
    Add AV_HWACCEL_FLAG_ALLOW_HIGH_DEPTH flag to av_vdpau_bind_context().
  
 -2014-12-25 - 57b6704 - lavc 56.8.0 - avcodec.h
 +2014-12-25 - d16079a / 57b6704 - lavc 56.17.100 / 56.8.0 - avcodec.h
    Add AVCodecContext.sw_pix_fmt.
  
 -2014-11-07 - 1384df6 - lavf 56.06.3 - avformat.h
 -  Add AVFormatContext.avoid_negative_ts.
 +2014-12-04 - 6e9ac02 - lavc 56.14.100 - dv_profile.h
 +  Add av_dv_codec_profile2().
  
 -2014-11-06 - 5e80fb7 - lavc 56.6.0 - vorbis_parser.h
 -  Add a public API for parsing vorbis packets.
 +-------- 8< --------- FFmpeg 2.5 was cut here -------- 8< ---------
 +
 +2014-11-21 - ab922f9 - lavu 54.15.100 - dict.h
 +   Add av_dict_get_string().
  
 -2014-10-24 - 1bd0bdc - lavu 54.5.0 - time.h
 -  Add av_gettime_relative().
 +2014-11-18 - a54a51c - lavu 54.14.100 - float_dsp.h
 +  Add avpriv_float_dsp_alloc().
  
 -2014-10-15 - 7ea1b34 - lavc 56.5.0 - avcodec.h
 +2014-11-16 - 6690d4c3 - lavf 56.13.100 - avformat.h
 +  Add AVStream.recommended_encoder_configuration with accessors.
 +
 +2014-11-16 - bee5844d - lavu 54.13.100 - opt.h
 +  Add av_opt_serialize().
 +
 +2014-11-16 - eec69332 - lavu 54.12.100 - opt.h
 +  Add av_opt_is_set_to_default().
 +
 +2014-11-06 - 44fa267 / 5e80fb7 - lavc 56.11.100 / 56.6.0 - vorbis_parser.h
 +  Add a public API for parsing vorbis packets.
 +
 +2014-10-15 - 17085a0 / 7ea1b34 - lavc 56.7.100 / 56.5.0 - avcodec.h
    Replace AVCodecContext.time_base used for decoding
    with AVCodecContext.framerate.
  
 -2014-10-15 - d565fef1- lavc 56.4.0 - avcodec.h
 +2014-10-15 - 51c810e / d565fef1 - lavc 56.6.100 / 56.4.0 - avcodec.h
    Add AV_HWACCEL_FLAG_IGNORE_LEVEL flag to av_vdpau_bind_context().
  
 -2014-10-13 - 2df0c32 - lavc 56.03.0 - avcodec.h
 +2014-10-13 - da21895 / 2df0c32e - lavc 56.5.100 / 56.3.0 - avcodec.h
    Add AVCodecContext.initial_padding. Deprecate the use of AVCodecContext.delay
    for audio encoding.
  
 -2014-10-08 - 5a419b2 - lavu 54.04.0 - pixdesc.h
 +2014-10-08 - bb44f7d / 5a419b2 - lavu 54.10.100 / 54.4.0 - pixdesc.h
    Add API to return the name of frame and context color properties.
  
 -2014-10-06 - e3e158e - lavc 56.2.0 - vdpau.h
 +2014-10-06 - a61899a / e3e158e - lavc 56.3.100 / 56.2.0 - vdpau.h
    Add av_vdpau_bind_context(). This function should now be used for creating
    (or resetting) a AVVDPAUContext instead of av_vdpau_alloc_context().
  
 -2014-08-25 - b263f8f - lavf 56.03.0 - avformat.h
 -  Add AVFormatContext.max_ts_probe.
 +2014-10-02 - cdd6f05 - lavc 56.2.100 - avcodec.h
 +2014-10-02 - cdd6f05 - lavu 54.9.100 - frame.h
 +  Add AV_FRAME_DATA_SKIP_SAMPLES. Add lavc CODEC_FLAG2_SKIP_MANUAL and
 +  AVOption "skip_manual", which makes lavc export skip information via
 +  AV_FRAME_DATA_SKIP_SAMPLES AVFrame side data, instead of skipping and
 +  discarding samples automatically.
 +
 +2014-10-02 - 0d92b0d - lavu 54.8.100 - avstring.h
 +  Add av_match_list()
 +
 +2014-09-24 - ac68295 - libpostproc 53.1.100
 +  Add visualization support
 +
 +2014-09-19 - 6edd6a4 - lavc 56.1.101 - dv_profile.h
 +  deprecate avpriv_dv_frame_profile2(), which was made public by accident.
  
 -------------------------------8<-------------------------------------
 -                   11 branch was cut here
 ------------------------------>8--------------------------------------
  
 -2014-08-28 - 9301486 - lavc 56.1.0 - avcodec.h
 +-------- 8< --------- FFmpeg 2.4 was cut here -------- 8< ---------
 +
 +2014-08-25 - 215db29 / b263f8f - lavf 56.3.100 / 56.3.0 - avformat.h
 +  Add AVFormatContext.max_ts_probe.
 +
 +2014-08-28 - f30a815 / 9301486 - lavc 56.1.100 / 56.1.0 - avcodec.h
    Add AV_PKT_DATA_STEREO3D to export container-level stereo3d information.
  
 -2014-08-13 - 8ddc326 - lavu 54.03.0 - mem.h
 +2014-08-23 - 8fc9bd0 - lavu 54.7.100 - dict.h
 +  AV_DICT_DONT_STRDUP_KEY and AV_DICT_DONT_STRDUP_VAL arguments are now
 +  freed even on error. This is consistent with the behaviour all users
 +  of it we could find expect.
 +
 +2014-08-21 - 980a5b0 - lavu 54.6.100 - frame.h motion_vector.h
 +  Add AV_FRAME_DATA_MOTION_VECTORS side data and AVMotionVector structure
 +
 +2014-08-16 - b7d5e01 - lswr 1.1.100 - swresample.h
 +  Add AVFrame based API
 +
 +2014-08-16 - c2829dc - lavu 54.4.100 - dict.h
 +  Add av_dict_set_int helper function.
 +
 +2014-08-13 - c8571c6 / 8ddc326 - lavu 54.3.100 / 54.3.0 - mem.h
    Add av_strndup().
  
 -2014-08-13 - a8c104a - lavu 54.02.0 - opt.h
 +2014-08-13 - 2ba4577 / a8c104a - lavu 54.2.100 / 54.2.0 - opt.h
    Add av_opt_get_dict_val/set_dict_val with AV_OPT_TYPE_DICT to support
    dictionary types being set as options.
  
    Add AVFormatContext.event_flags and AVStream.event_flags for signaling to
    the user when events happen in the file/stream.
  
 -2014-08-10 - fb1ddcd - lavr 2.1.0 - avresample.h
 +2014-08-10 - 78eaaa8 / fb1ddcd - lavr 2.1.0 - avresample.h
    Add avresample_convert_frame() and avresample_config().
  
 -2014-08-10 - fb1ddcd - lavu 54.1.0 - error.h
 +2014-08-10 - 78eaaa8 / fb1ddcd - lavu 54.1.100 / 54.1.0 - error.h
    Add AVERROR_INPUT_CHANGED and AVERROR_OUTPUT_CHANGED.
  
 -2014-08-08 - d35b94f - lavc 55.57.4 - avcodec.h
 +2014-08-08 - 3841f2a / d35b94f - lavc 55.73.102 / 55.57.4 - avcodec.h
    Deprecate FF_IDCT_XVIDMMX define and xvidmmx idct option.
    Replaced by FF_IDCT_XVID and xvid respectively.
  
 +2014-08-08 - 5c3c671 - lavf 55.53.100 - avio.h
 +  Add avio_feof() and deprecate url_feof().
 +
  2014-08-07 - bb78903 - lsws 2.1.3 - swscale.h
 -  sws_getCachedContext is not going to be removed in the future.
 +  sws_getContext is not going to be removed in the future.
  
 -2014-08-07 - ad1ee5f - lavc 55.57.3 - avcodec.h
 +2014-08-07 - a561662 / ad1ee5f - lavc 55.73.101 / 55.57.3 - avcodec.h
    reordered_opaque is not going to be removed in the future.
  
 -2014-08-04 - e9abafc - lavu 53.22.0 - pixfmt.h
 +2014-08-02 - 28a2107 - lavu 52.98.100 - pixelutils.h
 +  Add pixelutils API with SAD functions
 +
 +2014-08-04 - 6017c98 / e9abafc - lavu 52.97.100 / 53.22.0 - pixfmt.h
    Add AV_PIX_FMT_YA16 pixel format for 16 bit packed gray with alpha.
  
 -2014-08-04 - e96c3b8 - lavu 53.21.1 - avstring.h
 +2014-08-04 - 4c8bc6f / e96c3b8 - lavu 52.96.101 / 53.21.1 - avstring.h
    Rename AV_PIX_FMT_Y400A to AV_PIX_FMT_YA8 to better identify the format.
    An alias pixel format and color space name are provided for compatibility.
  
 -2014-08-04 - d2962e9 - lavu 53.21.0 - pixdesc.h
 +2014-08-04 - 073c074 / d2962e9 - lavu 52.96.100 / 53.21.0 - pixdesc.h
    Support name aliases for pixel formats.
  
 -2014-08-03 - 1ef9e83 - lavc 55.57.2 - avcodec.h
 -2014-08-03 - 1ef9e83 - lavu 53.20.0 - frame.h
 +2014-08-03 - 71d008e / 1ef9e83 - lavc 55.72.101 / 55.57.2 - avcodec.h
 +2014-08-03 - 71d008e / 1ef9e83 - lavu 52.95.100 / 53.20.0 - frame.h
    Deprecate AVCodecContext.dtg_active_format and use side-data instead.
  
 -2014-08-03 - 9f17685 - lavc 55.57.1 - avcodec.h
 +2014-08-03 - e680c73 - lavc 55.72.100 - avcodec.h
 +  Add get_pixels() to AVDCT
 +
 +2014-08-03 - 9400603 / 9f17685 - lavc 55.71.101 / 55.57.1 - avcodec.h
    Deprecate unused FF_IDCT_IPP define and ipp avcodec option.
    Deprecate unused FF_DEBUG_PTS define and pts avcodec option.
    Deprecate unused FF_CODER_TYPE_DEFLATE define and deflate avcodec option.
    Deprecate unused FF_DCT_INT define and int avcodec option.
    Deprecate unused avcodec option scenechange_factor.
  
 -2014-07-29 - 69e7336 - lavu 53.19.0 - avstring.h
 +2014-07-30 - ba3e331 - lavu 52.94.100 - frame.h
 +  Add av_frame_side_data_name()
 +
 +2014-07-29 - 80a3a66 / 3a19405 - lavf 56.01.100 / 56.01.0 - avformat.h
 +  Add mime_type field to AVProbeData, which now MUST be initialized in
 +  order to avoid uninitialized reads of the mime_type pointer, likely
 +  leading to crashes.
 +  Typically, this means you will do 'AVProbeData pd = { 0 };' instead of
 +  'AVProbeData pd;'.
 +
 +2014-07-29 - 31e0b5d / 69e7336 - lavu 52.92.100 / 53.19.0 - avstring.h
    Make name matching function from lavf public as av_match_name().
  
 -2014-07-28 - c5fca01 - lavc 55.57.0 - avcodec.h
 +2014-07-28 - 2e5c8b0 / c5fca01 - lavc 55.71.100 / 55.57.0 - avcodec.h
    Add AV_CODEC_PROP_REORDER to mark codecs supporting frame reordering.
  
 -2014-07-09 - a54f03b - lavu 53.18.0 - display.h
 +2014-07-27 - ff9a154 - lavf 55.50.100 - avformat.h
 +  New field int64_t probesize2 instead of deprecated
 +  field int probesize.
 +
 +2014-07-27 - 932ff70 - lavc 55.70.100 - avdct.h
 +  Add AVDCT / avcodec_dct_alloc() / avcodec_dct_init().
 +
 +2014-07-23 - 8a4c086 - lavf 55.49.100 - avio.h
 +  Add avio_read_to_bprint()
 +
 +
 +-------- 8< --------- FFmpeg 2.3 was cut here -------- 8< ---------
 +
 +2014-07-14 - 62227a7 - lavf 55.47.100 - avformat.h
 +  Add av_stream_get_parser()
 +
 +2014-07-09 - c67690f / a54f03b - lavu 52.92.100 / 53.18.0 - display.h
    Add av_display_matrix_flip() to flip the transformation matrix.
  
 -2014-07-09 - f6ee61f - lavc 55.56.0 - dv_profile.h
 +2014-07-09 - 1b58f13 / f6ee61f - lavc 55.69.100 / 55.56.0 - dv_profile.h
    Add a public API for DV profile handling.
  
 -2014-06-20 - 9e500ef - lavu 53.17.0 - imgutils.h
 +2014-06-20 - 0dceefc / 9e500ef - lavu 52.90.100 / 53.17.0 - imgutils.h
    Add av_image_check_sar().
  
 -2014-06-20 - 874390e - lavc 55.55.0 - avcodec.h
 +2014-06-20 - 4a99333 / 874390e - lavc 55.68.100 / 55.55.0 - avcodec.h
    Add av_packet_rescale_ts() to simplify timestamp conversion.
  
 -2014-06-18 - 194be1f - lavf 55.20.0 - avformat.h
 +2014-06-18 - ac293b6 / 194be1f - lavf 55.44.100 / 55.20.0 - avformat.h
    The proper way for providing a hint about the desired timebase to the muxers
    is now setting AVStream.time_base, instead of AVStream.codec.time_base as was
    done previously. The old method is now deprecated.
  
 -2014-06-01 - 0957b27 - lavc 55.54.0 - avcodec.h
 +2014-06-11 - 67d29da - lavc 55.66.101 - avcodec.h
 +  Increase FF_INPUT_BUFFER_PADDING_SIZE to 32 due to some corner cases needing
 +  it
 +
 +2014-06-10 - 5482780 - lavf 55.43.100 - avformat.h
 +  New field int64_t max_analyze_duration2 instead of deprecated
 +  int max_analyze_duration.
 +
 +2014-05-30 - 00759d7 - lavu 52.89.100 - opt.h
 +  Add av_opt_copy()
 +
 +2014-06-01 - 03bb99a / 0957b27 - lavc 55.66.100 / 55.54.0 - avcodec.h
    Add AVCodecContext.side_data_only_packets to allow encoders to output packets
    with only side data. This option may become mandatory in the future, so all
    users are recommended to update their code and enable this option.
  
 -2014-06-01 - 8c02adc - lavu 53.16.0 - frame.h, pixfmt.h
 +2014-06-01 - 6e8e9f1 / 8c02adc - lavu 52.88.100 / 53.16.0 - frame.h, pixfmt.h
    Move all color-related enums (AVColorPrimaries, AVColorSpace, AVColorRange,
    AVColorTransferCharacteristic, and AVChromaLocation) inside lavu.
 -  Add AVFrame fields for them on the next lavu major bump.
 +  And add AVFrame fields for them.
  
 -2014-05-28 - b2d4565 - lavr 1.3.0 - avresample.h
 +2014-05-29 - bdb2e80 / b2d4565 - lavr 1.3.0 - avresample.h
    Add avresample_max_output_samples
  
 -2014-05-28 - 6d21259 - lavf 55.19.0 - avformat.h
 +2014-05-28 - d858ee7 / 6d21259 - lavf 55.42.100 / 55.19.0 - avformat.h
    Add strict_std_compliance and related AVOptions to support experimental
    muxing.
  
 -2014-05-20 - c23c96b - lavf 55.18.0 - avformat.h
 +2014-05-26 - 55cc60c - lavu 52.87.100 - threadmessage.h
 +  Add thread message queue API.
 +
 +2014-05-26 - c37d179 - lavf 55.41.100 - avformat.h
 +  Add format_probesize to AVFormatContext.
 +
 +2014-05-20 - 7d25af1 / c23c96b - lavf 55.39.100 / 55.18.0 - avformat.h
    Add av_stream_get_side_data() to access stream-level side data
    in the same way as av_packet_get_side_data().
  
 -2014-05-19 - bddd8cb - lavu 53.15.0 - frame.h, display.h
 +2014-05-20 - 7336e39 - lavu 52.86.100 - fifo.h
 +  Add av_fifo_alloc_array() function.
 +
 +2014-05-19 - ef1d4ee / bddd8cb - lavu 52.85.100 / 53.15.0 - frame.h, display.h
    Add AV_FRAME_DATA_DISPLAYMATRIX for exporting frame-level
    spatial rendering on video frames for proper display.
  
 -2014-05-19 - bddd8cb - lavc 55.53.0 - avcodec.h
 +2014-05-19 - ef1d4ee / bddd8cb - lavc 55.64.100 / 55.53.0 - avcodec.h
    Add AV_PKT_DATA_DISPLAYMATRIX for exporting packet-level
    spatial rendering on video frames for proper display.
  
 -2014-05-19 - a312f71 - lavf 55.17.1 - avformat.h
 +2014-05-19 - 999a99c / a312f71 - lavf 55.38.101 / 55.17.1 - avformat.h
    Deprecate AVStream.pts and the AVFrac struct, which was its only use case.
 -  Those fields were poorly defined and not meant to be public, so there is
 -  no replacement for them.
 +  See use av_stream_get_end_pts()
  
 -2014-05-18 - fd05602 - lavc 55.52.0 - avcodec.h
 +2014-05-18 - 68c0518 / fd05602 - lavc 55.63.100 / 55.52.0 - avcodec.h
    Add avcodec_free_context(). From now on it should be used for freeing
    AVCodecContext.
  
 -2014-05-15 - 0c1959b - lavf 55.17.0 - avformat.h
 +2014-05-17 - 0eec06e / 1bd0bdc - lavu 52.84.100 / 54.5.0 - time.h
 +  Add av_gettime_relative() av_gettime_relative_is_monotonic()
 +
 +2014-05-15 - eacf7d6 / 0c1959b - lavf 55.38.100 / 55.17.0 - avformat.h
    Add AVFMT_FLAG_BITEXACT flag. Muxers now use it instead of checking
    CODEC_FLAG_BITEXACT on the first stream.
  
 -2014-05-11 - 66e6c8a - lavu 53.14.0 - pixfmt.h
 +2014-05-15 - 96cb4c8 - lswr 0.19.100 - swresample.h
 +  Add swr_close()
 +
 +2014-05-11 - 14aef38 / 66e6c8a - lavu 52.83.100 / 53.14.0 - pixfmt.h
    Add AV_PIX_FMT_VDA for new-style VDA acceleration.
  
 -2014-05-01 - a2941c8 - lavc 55.50.3 - avcodec.h
 +2014-05-07 - 351f611 - lavu 52.82.100 - fifo.h
 +  Add av_fifo_freep() function.
 +
 +2014-05-02 - ba52fb11 - lavu 52.81.100 - opt.h
 +  Add av_opt_set_dict2() function.
 +
 +2014-05-01 - e77b985 / a2941c8 - lavc 55.60.103 / 55.50.3 - avcodec.h
    Deprecate CODEC_FLAG_MV0. It is replaced by the flag "mv0" in the
    "mpv_flags" private option of the mpegvideo encoders.
  
 -2014-05-01 - 6484149 - lavc 55.50.2 - avcodec.h
 +2014-05-01 - e40ae8c / 6484149 - lavc 55.60.102 / 55.50.2 - avcodec.h
    Deprecate CODEC_FLAG_GMC. It is replaced by the "gmc" private option of the
    libxvid encoder.
  
 -2014-05-01 - b2c3171 - lavc 55.50.1 - avcodec.h
 +2014-05-01 - 1851643 / b2c3171 - lavc 55.60.101 / 55.50.1 - avcodec.h
    Deprecate CODEC_FLAG_NORMALIZE_AQP. It is replaced by the flag "naq" in the
    "mpv_flags" private option of the mpegvideo encoders.
  
 -2014-05-01 - 5fcceda - avcodec.h
 +2014-05-01 - cac07d0 / 5fcceda - avcodec.h
    Deprecate CODEC_FLAG_INPUT_PRESERVED. Its functionality is replaced by passing
    reference-counted frames to encoders.
  
 -2014-04-28 - ed4b757 - lavc 55.50.0 - dxva2.h
 +2014-04-30 - 617e866 - lavu 52.81.100 - pixdesc.h
 +  Add av_find_best_pix_fmt_of_2(), av_get_pix_fmt_loss()
 +  Deprecate avcodec_get_pix_fmt_loss(), avcodec_find_best_pix_fmt_of_2()
 +
 +2014-04-29 - 1bf6396 - lavc 55.60.100 - avcodec.h
 +  Add AVCodecDescriptor.mime_types field.
 +
 +2014-04-29 - b804eb4 - lavu 52.80.100 - hash.h
 +  Add av_hash_final_bin(), av_hash_final_hex() and av_hash_final_b64().
 +
 +2014-03-07 - 8b2a130 - lavc 55.50.0 / 55.53.100 - dxva2.h
    Add FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO for old Intel GPUs.
  
 -2014-04-22 - 502512e - lavu 53.13.0 - avutil.h
 +2014-04-22 - 502512e /dac7e8a - lavu 53.13.0 / 52.78.100 - avutil.h
    Add av_get_time_base_q().
  
 -2014-04-17 - 0983d48 - lavu 53.12.0 - crc.h
 +2014-04-17 - a8d01a7 / 0983d48 - lavu 53.12.0 / 52.77.100 - crc.h
    Add AV_CRC_16_ANSI_LE crc variant.
  
 -2014-04-07 - 8b17243 - lavu 53.11.0 - pixfmt.h
 +2014-04-15 - ef818d8 - lavf 55.37.101 - avformat.h
 +  Add av_format_inject_global_side_data()
 +
 +2014-04-12 - 4f698be - lavu 52.76.100 - log.h
 +  Add av_log_get_flags()
 +
 +2014-04-11 - 6db42a2b - lavd 55.12.100 - avdevice.h
 +  Add avdevice_capabilities_create() function.
 +  Add avdevice_capabilities_free() function.
 +
 +2014-04-07 - 0a1cc04 / 8b17243 - lavu 52.75.100 / 53.11.0 - pixfmt.h
    Add AV_PIX_FMT_YVYU422 pixel format.
  
 -2014-04-04 - 8542f9c - lavu 53.10.0 - replaygain.h
 +2014-04-04 - c1d0536 / 8542f9c - lavu 52.74.100 / 53.10.0 - replaygain.h
    Full scale for peak values is now 100000 (instead of UINT32_MAX) and values
    may overflow.
  
 -2014-04-03 - 7763118 - lavu 53.09.0 - log.h
 +2014-04-03 - c16e006 / 7763118 - lavu 52.73.100 / 53.9.0 - log.h
    Add AV_LOG(c) macro to have 256 color debug messages.
  
 -2014-03-24 - d161ae0 - lavu 53.08.0 - frame.h
 +2014-04-03 - eaed4da9 - lavu 52.72.100 - opt.h
 +  Add AV_OPT_MULTI_COMPONENT_RANGE define to allow return
 +  multi-component option ranges.
 +
 +2014-03-29 - cd50a44b - lavu 52.70.100 - mem.h
 +  Add av_dynarray_add_nofree() function.
 +
 +2014-02-24 - 3e1f241 / d161ae0 - lavu 52.69.100 / 53.8.0 - frame.h
    Add av_frame_remove_side_data() for removing a single side data
    instance from a frame.
  
 -2014-03-24 - 5a7e35d - lavu 53.07.0 - frame.h, replaygain.h
 +2014-03-24 - 83e8978 / 5a7e35d - lavu 52.68.100 / 53.7.0 - frame.h, replaygain.h
    Add AV_FRAME_DATA_REPLAYGAIN for exporting replaygain tags.
    Add a new header replaygain.h with the AVReplayGain struct.
  
 -2014-03-24 - 5a7e35d - lavc 55.36.0 - avcodec.h
 +2014-03-24 - 83e8978 / 5a7e35d - lavc 55.54.100 / 55.36.0 - avcodec.h
    Add AV_PKT_DATA_REPLAYGAIN for exporting replaygain tags.
  
 -2014-03-24 - 25b3258 - lavf 55.13.0 - avformat.h
 +2014-03-24 - 595ba3b / 25b3258 - lavf 55.35.100 / 55.13.0 - avformat.h
    Add AVStream.side_data and AVStream.nb_side_data for exporting stream-global
    side data (e.g. replaygain tags, video rotation)
  
 -2014-03-24 - 0e2c3ee - lavc 55.35.0 - avcodec.h
 +2014-03-24 - bd34e26 / 0e2c3ee - lavc 55.53.100 / 55.35.0 - avcodec.h
    Give the name AVPacketSideData to the previously anonymous struct used for
    AVPacket.side_data.
  
 -2014-03-16 - 1481d24 - lavu 53.06.0 - pixfmt.h
 -  Add RGBA64 pixel format and variants.
  
 -2014-02-24 - 1155fd0 - lavu 53.05.0 - frame.h
 +-------- 8< --------- FFmpeg 2.2 was cut here -------- 8< ---------
 +
 +2014-03-18 - 37c07d4 - lsws 2.5.102
 +  Make gray16 full-scale.
 +
 +2014-03-16 - 6b1ca17 / 1481d24 - lavu 52.67.100 / 53.6.0 - pixfmt.h
 +  Add RGBA64_LIBAV pixel format and variants for compatibility
 +
 +2014-03-11 - 3f3229c - lavf 55.34.101 - avformat.h
 +  Set AVFormatContext.start_time_realtime when demuxing.
 +
 +2014-03-03 - 06fed440 - lavd 55.11.100 - avdevice.h
 +  Add av_input_audio_device_next().
 +  Add av_input_video_device_next().
 +  Add av_output_audio_device_next().
 +  Add av_output_video_device_next().
 +
 +2014-02-24 - fff5262 / 1155fd0 - lavu 52.66.100 / 53.5.0 - frame.h
    Add av_frame_copy() for copying the frame data.
  
 -2014-02-22 - 7e86c27 - lavr 1.2.0 - avresample.h
 +2014-02-24 - a66be60 - lswr 0.18.100 - swresample.h
 +  Add swr_is_initialized() for checking whether a resample context is initialized.
 +
 +2014-02-22 - 5367c0b / 7e86c27 - lavr 1.2.0 - avresample.h
    Add avresample_is_open() for checking whether a resample context is open.
  
 -2014-02-19 - c3ecd96 - lavu 53.04.0  - opt.h
 +2014-02-19 - 6a24d77 / c3ecd96 - lavu 52.65.100 / 53.4.0  - opt.h
    Add AV_OPT_FLAG_EXPORT and AV_OPT_FLAG_READONLY to mark options meant (only)
    for reading.
  
 -2014-02-19 - 6bb8720 - lavu 53.03.01 - opt.h
 +2014-02-19 - f4c8d00 / 6bb8720 - lavu 52.64.101 / 53.3.1 - opt.h
    Deprecate unused AV_OPT_FLAG_METADATA.
  
 -------------------------------8<-------------------------------------
 -                   10 branch was cut here
 ------------------------------>8--------------------------------------
 +2014-02-16 - 81c3f81 - lavd 55.10.100 - avdevice.h
 +  Add avdevice_list_devices() and avdevice_free_list_devices()
 +
 +2014-02-16 - db3c970 - lavf 55.33.100 - avio.h
 +  Add avio_find_protocol_name() to find out the name of the protocol that would
 +  be selected for a given URL.
  
 -2014-02-15 - c98f316 - lavu 53.3.0 - frame.h
 +2014-02-15 - a2bc6c1 / c98f316 - lavu 52.64.100 / 53.3.0 - frame.h
    Add AV_FRAME_DATA_DOWNMIX_INFO value to the AVFrameSideDataType enum and
    downmix_info.h API, which identify downmix-related metadata.
  
 -2014-02-04 - d9ae103 - lavf 55.11.0 - avformat.h
 +2014-02-11 - 1b05ac2 - lavf 55.32.100 - avformat.h
 +  Add av_write_uncoded_frame() and av_interleaved_write_uncoded_frame().
 +
 +2014-02-04 - 3adb5f8 / d9ae103 - lavf 55.30.100 / 55.11.0 - avformat.h
    Add AVFormatContext.max_interleave_delta for controlling amount of buffering
    when interleaving.
  
 -2014-01-20 - 93c553c - lavc 55.32.1 - avcodec.h
 +2014-02-02 - 5871ee5 - lavf 55.29.100 - avformat.h
 +  Add output_ts_offset muxing option to AVFormatContext.
 +
 +2014-01-27 - 102bd64 - lavd 55.7.100 - avdevice.h
 +                       lavf 55.28.100 - avformat.h
 +  Add avdevice_dev_to_app_control_message() function.
 +
 +2014-01-27 - 7151411 - lavd 55.6.100 - avdevice.h
 +                       lavf 55.27.100 - avformat.h
 +  Add avdevice_app_to_dev_control_message() function.
 +
 +2014-01-24 - 86bee79 - lavf 55.26.100 - avformat.h
 +  Add AVFormatContext option metadata_header_padding to allow control over the
 +  amount of padding added.
 +
 +2014-01-20 - eef74b2 / 93c553c - lavc 55.48.102 / 55.32.1 - avcodec.h
    Edges are not required anymore on video buffers allocated by get_buffer2()
    (i.e. as if the CODEC_FLAG_EMU_EDGE flag was always on). Deprecate
    CODEC_FLAG_EMU_EDGE and avcodec_get_edge_width().
  
 -2014-01-05 - 5b4797a - lavu 53.2.0 - frame.h
 +2014-01-19 - 1a193c4 - lavf 55.25.100 - avformat.h
 +  Add avformat_get_mov_video_tags() and avformat_get_mov_audio_tags().
 +
 +2014-01-19 - 3532dd5 - lavu 52.63.100 - rational.h
 +  Add av_make_q() function.
 +
 +2014-01-05 - 4cf4da9 / 5b4797a - lavu 52.62.100 / 53.2.0 - frame.h
    Add AV_FRAME_DATA_MATRIXENCODING value to the AVFrameSideDataType enum, which
    identifies AVMatrixEncoding data.
  
 -2014-01-05 - 5c437fb - lavu 53.1.0 - channel_layout.h
 +2014-01-05 - 751385f / 5c437fb - lavu 52.61.100 / 53.1.0 - channel_layout.h
    Add values for various Dolby flags to the AVMatrixEncoding enum.
  
 -2013-12-20 - 2a41826 - lavc 55.30.0 - avcodec.h
 -  Add HEVC profiles
 +2014-01-04 - b317f94 - lavu 52.60.100 - mathematics.h
 +  Add av_add_stable() function.
 +
 +2013-12-22 - 911676c - lavu 52.59.100 - avstring.h
 +  Add av_strnlen() function.
 +
 +2013-12-09 - 64f73ac - lavu 52.57.100 - opencl.h
 +  Add av_opencl_benchmark() function.
  
 -2013-12-11 - b9fb59d,9431356,d7b3ee9 - lavc 55.28.1 - avcodec.h
 +2013-11-30 - 82b2e9c - lavu 52.56.100 - ffversion.h
 +  Moves version.h to libavutil/ffversion.h.
 +  Install ffversion.h and make it public.
 +
 +2013-12-11 - 29c83d2 / b9fb59d,409a143 / 9431356,44967ab / d7b3ee9 - lavc 55.45.101 / 55.28.1 - avcodec.h
    av_frame_alloc(), av_frame_unref() and av_frame_free() now can and should be
    used instead of avcodec_alloc_frame(), avcodec_get_frame_defaults() and
    avcodec_free_frame() respectively. The latter three functions are deprecated.
  
 -2013-12-09 - 7e244c6- - lavu 52.20.0 - frame.h
 +2013-12-09 - 7a60348 / 7e244c6- - lavu 52.58.100 / 52.20.0 - frame.h
    Add AV_FRAME_DATA_STEREO3D value to the AVFrameSideDataType enum and
    stereo3d.h API, that identify codec-independent stereo3d information.
  
 -2013-11-26 - 1eaac1d- - lavu 52.19.0 - frame.h
 +2013-11-26 - 625b290 / 1eaac1d- - lavu 52.55.100 / 52.19.0 - frame.h
    Add AV_FRAME_DATA_A53_CC value to the AVFrameSideDataType enum, which
    identifies ATSC A53 Part 4 Closed Captions data.
  
 -2013-11-14 - cce3e0a - lavu 52.18.0 - mem.h
 +2013-11-22 - 6859065 - lavu 52.54.100 - avstring.h
 +  Add av_utf8_decode() function.
 +
 +2013-11-22 - fb7d70c - lavc 55.44.100 - avcodec.h
 +  Add HEVC profiles
 +
 +2013-11-20 - c28b61c - lavc 55.44.100 - avcodec.h
 +  Add av_packet_{un,}pack_dictionary()
 +  Add AV_PKT_METADATA_UPDATE side data type, used to transmit key/value
 +  strings between a stream and the application.
 +
 +2013-11-14 - 7c888ae / cce3e0a - lavu 52.53.100 / 52.18.0 - mem.h
    Move av_fast_malloc() and av_fast_realloc() for libavcodec to libavutil.
  
 -2013-11-14 - 8941971 - lavc 55.27.0 - avcodec.h
 +2013-11-14 - b71e4d8 / 8941971 - lavc 55.43.100 / 55.27.0 - avcodec.h
    Deprecate AVCodecContext.error_rate, it is replaced by the 'error_rate'
    private option of the mpegvideo encoder family.
  
 -2013-11-14 - 728c465 - lavc 55.26.0 - vdpau.h
 +2013-11-14 - 31c09b7 / 728c465 - lavc 55.42.100 / 55.26.0 - vdpau.h
    Add av_vdpau_get_profile().
    Add av_vdpau_alloc_context(). This function must from now on be
    used for allocating AVVDPAUContext.
  
 -2013-11-04 - cd8f772 - lavc 55.25.0 - avcodec.h
 +2013-11-04 - be41f21 / cd8f772 - lavc 55.41.100 / 55.25.0 - avcodec.h
 +                       lavu 52.51.100 - frame.h
    Add ITU-R BT.2020 and other not yet included values to color primaries,
    transfer characteristics and colorspaces.
  
 -2013-10-31 - 28096e0 - lavu 52.17.0 - frame.h
 +2013-11-04 - 85cabf1 - lavu 52.50.100 - avutil.h
 +  Add av_fopen_utf8()
 +
 +2013-10-31 - 78265fc / 28096e0 - lavu 52.49.100 / 52.17.0 - frame.h
    Add AVFrame.flags and AV_FRAME_FLAG_CORRUPT.
  
 -2013-09-28 - 0767bfd - lavfi 3.11.0 - avfilter.h
 +
 +-------- 8< --------- FFmpeg 2.1 was cut here -------- 8< ---------
 +
 +2013-10-27 - dbe6f9f - lavc 55.39.100 - avcodec.h
 +  Add CODEC_CAP_DELAY support to avcodec_decode_subtitle2.
 +
 +2013-10-27 - d61617a - lavu 52.48.100 - parseutils.h
 +  Add av_get_known_color_name().
 +
 +2013-10-17 - 8696e51 - lavu 52.47.100 - opt.h
 +  Add AV_OPT_TYPE_CHANNEL_LAYOUT and channel layout option handlers
 +  av_opt_get_channel_layout() and av_opt_set_channel_layout().
 +
 +2013-10-06 - ccf96f8 -libswscale 2.5.101 - options.c
 +  Change default scaler to bicubic
 +
 +2013-10-03 - e57dba0 - lavc 55.34.100 - avcodec.h
 +  Add av_codec_get_max_lowres()
 +
 +2013-10-02 - 5082fcc - lavf 55.19.100 - avformat.h
 +  Add audio/video/subtitle AVCodec fields to AVFormatContext to force specific
 +  decoders
 +
 +2013-09-28 - 7381d31 / 0767bfd - lavfi 3.88.100 / 3.11.0 - avfilter.h
    Add AVFilterGraph.execute and AVFilterGraph.opaque for custom slice threading
    implementations.
  
 -2013-09-21 - e208e6d - lavu 52.16.0 - pixfmt.h
 +2013-09-21 - 85f8a3c / e208e6d - lavu 52.46.100 / 52.16.0 - pixfmt.h
    Add interleaved 4:2:2 8/10-bit formats AV_PIX_FMT_NV16 and
    AV_PIX_FMT_NV20.
  
 -2013-09-16 - 3feb3d6 - lavu 52.15.0 - mem.h
 +2013-09-16 - c74c3fb / 3feb3d6 - lavu 52.44.100 / 52.15.0 - mem.h
    Add av_reallocp.
  
 -2013-08-10 - 5a9a9d4 - lavc 55.16.0 - avcodec.h
 +2013-09-04 - 3e1f507 - lavc 55.31.101 - avcodec.h
 +  avcodec_close() argument can be NULL.
 +
 +2013-09-04 - 36cd017a - lavf 55.16.101 - avformat.h
 +  avformat_close_input() argument can be NULL and point on NULL.
 +
 +2013-08-29 - e31db62 - lavf 55.15.100 - avformat.h
 +  Add av_format_get_probe_score().
 +
 +2013-08-15 - 1e0e193 - lsws 2.5.100 -
 +  Add a sws_dither AVOption, allowing to set the dither algorithm used
 +
 +2013-08-11 - d404fe35 - lavc 55.27.100 - vdpau.h
 +  Add a render2 alternative to the render callback function.
 +
 +2013-08-11 - af05edc - lavc 55.26.100 - vdpau.h
 +  Add allocation function for AVVDPAUContext, allowing
 +  to extend it in the future without breaking ABI/API.
 +
 +2013-08-10 - 67a580f / 5a9a9d4 - lavc 55.25.100 / 55.16.0 - avcodec.h
    Extend AVPacket API with av_packet_unref, av_packet_ref,
    av_packet_move_ref, av_packet_copy_props, av_packet_free_side_data.
  
 -2013-08-05 - f824535 - lavc 55.13.0 - avcodec.h
 +2013-08-05 - 9547e3e / f824535 - lavc 55.22.100 / 55.13.0 - avcodec.h
    Deprecate the bitstream-related members from struct AVVDPAUContext.
 -  The bistream buffers no longer need to be explicitly freed.
 +  The bitstream buffers no longer need to be explicitly freed.
  
 -2013-08-05 - 549294f - lavc 55.12.0 - avcodec.h
 +2013-08-05 - 3b805dc / 549294f - lavc 55.21.100 / 55.12.0 - avcodec.h
    Deprecate the CODEC_CAP_HWACCEL_VDPAU codec capability. Use CODEC_CAP_HWACCEL
    and select the AV_PIX_FMT_VDPAU format with get_format() instead.
  
 -2013-08-05 - a0ad5d0 - lavu 52.14.0 - pixfmt.h
 +2013-08-05 - 4ee0984 / a0ad5d0 - lavu 52.41.100 / 52.14.0 - pixfmt.h
    Deprecate AV_PIX_FMT_VDPAU_*. Use AV_PIX_FMT_VDPAU instead.
  
 -2013-08-02 - a8b1927 - lavc 55.11.0 - avcodec.h
 +2013-08-02 - 82fdfe8 / a8b1927 - lavc 55.20.100 / 55.11.0 - avcodec.h
    Add output_picture_number to AVCodecParserContext.
  
 -2013-06-24 - 95d5246 - lavc 55.10.0 - avcodec.h
 +2013-07-23 - abc8110 - lavc 55.19.100 - avcodec.h
 +  Add avcodec_chroma_pos_to_enum()
 +  Add avcodec_enum_to_chroma_pos()
 +
 +
 +-------- 8< --------- FFmpeg 2.0 was cut here -------- 8< ---------
 +
 +2013-07-03 - 838bd73 - lavfi 3.78.100 - avfilter.h
 +  Deprecate avfilter_graph_parse() in favor of the equivalent
 +  avfilter_graph_parse_ptr().
 +
 +2013-06-24 - af5f9c0 / 95d5246 - lavc 55.17.100 / 55.10.0 - avcodec.h
    Add MPEG-2 AAC profiles
  
 -2013-06-04 - fc962d4 - lavu 52.13.0 - mem.h
 +2013-06-25 - af5f9c0 / 95d5246 - lavf 55.10.100 - avformat.h
 +  Add AV_DISPOSITION_* flags to indicate text track kind.
 +
 +2013-06-15 - 99b8cd0 - lavu 52.36.100
 +  Add AVRIPEMD:
 +   av_ripemd_alloc()
 +   av_ripemd_init()
 +   av_ripemd_update()
 +   av_ripemd_final()
 +
 +2013-06-10 - 82ef670 - lavu 52.35.101 - hmac.h
 +  Add AV_HMAC_SHA224, AV_HMAC_SHA256, AV_HMAC_SHA384, AV_HMAC_SHA512
 +
 +2013-06-04 - 30b491f / fc962d4 - lavu 52.35.100 / 52.13.0 - mem.h
    Add av_realloc_array and av_reallocp_array
  
 -2013-05-24 - 129bb23 - lavfi 3.10.0 - avfilter.h
 +2013-05-30 - 682b227 - lavu 52.35.100
 +  Add AVSHA512:
 +   av_sha512_alloc()
 +   av_sha512_init()
 +   av_sha512_update()
 +   av_sha512_final()
 +
 +2013-05-24 - 8d4e969 / 129bb23 - lavfi 3.10.0 / 3.70.100 - avfilter.h
    Add support for slice multithreading to lavfi. Filters supporting threading
    are marked with AVFILTER_FLAG_SLICE_THREADS.
    New fields AVFilterContext.thread_type, AVFilterGraph.thread_type and
    AVFilterGraph.nb_threads (accessible directly or through AVOptions) may be
    used to configure multithreading.
  
 -2013-05-24 - 2a6eaea - lavu 52.12.0 - cpu.h
 +2013-05-24 - fe40a9f / 2a6eaea - lavu 52.12.0 / 52.34.100 - cpu.h
    Add av_cpu_count() function for getting the number of logical CPUs.
  
 -2013-05-24 - b493847 - lavc 55.7.0 - avcodec.h
 +2013-05-24 - 0c25c39 / b493847 - lavc 55.7.0 / 55.12.100 - avcodec.h
    Add picture_structure to AVCodecParserContext.
  
 -2013-05-15 - e6c4ac7 - lavu 52.11.0 - pixdesc.h
 +2013-05-17 - 3a751ea - lavu 52.33.100 - opt.h
 +  Add AV_OPT_TYPE_COLOR value to AVOptionType enum.
 +
 +2013-05-13 - e398416 - lavu 52.31.100 - mem.h
 +  Add av_dynarray2_add().
 +
 +2013-05-12 - 1776177 - lavfi 3.65.100
 +  Add AVFILTER_FLAG_SUPPORT_TIMELINE* filter flags.
 +
 +2013-04-19 - 380cfce - lavc 55.4.100
 +  Add AV_CODEC_PROP_TEXT_SUB property for text based subtitles codec.
 +
 +2013-04-18 - 7c1a002 - lavf 55.3.100
 +  The matroska demuxer can now output proper verbatim ASS packets. It will
 +  become the default starting lavf 56.0.100.
 +
 +2013-04-10 - af0d270 - lavu 25.26.100 - avutil.h,opt.h
 +  Add av_int_list_length()
 +  and av_opt_set_int_list().
 +
 +2013-03-30 - 5c73645 - lavu 52.24.100 - samplefmt.h
 +  Add av_samples_alloc_array_and_samples().
 +
 +2013-03-29 - ef7b6b4 - lavf 55.1.100 - avformat.h
 +  Add av_guess_frame_rate()
 +
 +2013-03-20 - 8d928a9 - lavu 52.22.100 - opt.h
 +  Add AV_OPT_TYPE_DURATION value to AVOptionType enum.
 +
 +2013-03-17 - 7aa9af5 - lavu 52.20.100 - opt.h
 +  Add AV_OPT_TYPE_VIDEO_RATE value to AVOptionType enum.
 +
 +
 +-------- 8< --------- FFmpeg 1.2 was cut here -------- 8< ---------
 +
 +2013-03-07 - 9767ec6 - lavu 52.18.100 - avstring.h,bprint.h
 +  Add av_escape() and av_bprint_escape() API.
 +
 +2013-02-24 - b59cd08 - lavfi 3.41.100 - buffersink.h
 +  Add sample_rates field to AVABufferSinkParams.
 +
 +2013-01-17 - a1a707f - lavf 54.61.100
 +  Add av_codec_get_tag2().
 +
 +2013-01-01 - 2eb2e17 - lavfi 3.34.100
 +  Add avfilter_get_audio_buffer_ref_from_arrays_channels.
 +
 +
 +-------- 8< --------- FFmpeg 1.1 was cut here -------- 8< ---------
 +
 +2012-12-20 - 34de47aa - lavfi 3.29.100 - avfilter.h
 +  Add AVFilterLink.channels, avfilter_link_get_channels()
 +  and avfilter_ref_get_channels().
 +
 +2012-12-15 - 96d815fc - lavc 54.80.100 - avcodec.h
 +  Add pkt_size field to AVFrame.
 +
 +2012-11-25 - c70ec631 - lavu 52.9.100 - opt.h
 +  Add the following convenience functions to opt.h:
 +   av_opt_get_image_size
 +   av_opt_get_pixel_fmt
 +   av_opt_get_sample_fmt
 +   av_opt_set_image_size
 +   av_opt_set_pixel_fmt
 +   av_opt_set_sample_fmt
 +
 +2012-11-17 - 4cd74c81 - lavu 52.8.100 - bprint.h
 +  Add av_bprint_strftime().
 +
 +2012-11-15 - 92648107 - lavu 52.7.100 - opt.h
 +  Add av_opt_get_key_value().
 +
 +2012-11-13 - 79456652 - lavfi 3.23.100 - avfilter.h
 +  Add channels field to AVFilterBufferRefAudioProps.
 +
 +2012-11-03 - 481fdeee - lavu 52.3.100 - opt.h
 +  Add AV_OPT_TYPE_SAMPLE_FMT value to AVOptionType enum.
 +
 +2012-10-21 - 6fb2fd8 - lavc  54.68.100 - avcodec.h
 +                       lavfi  3.20.100 - avfilter.h
 +  Add AV_PKT_DATA_STRINGS_METADATA side data type, used to transmit key/value
 +  strings between AVPacket and AVFrame, and add metadata field to
 +  AVCodecContext (which shall not be accessed by users; see AVFrame metadata
 +  instead).
 +
 +2012-09-27 - a70b493 - lavd 54.3.100 - version.h
 +  Add LIBAVDEVICE_IDENT symbol.
 +
 +2012-09-27 - a70b493 - lavfi 3.18.100 - version.h
 +  Add LIBAVFILTER_IDENT symbol.
 +
 +2012-09-27 - a70b493 - libswr 0.16.100 - version.h
 +  Add LIBSWRESAMPLE_VERSION, LIBSWRESAMPLE_BUILD
 +  and LIBSWRESAMPLE_IDENT symbols.
 +
 +
 +-------- 8< --------- FFmpeg 1.0 was cut here -------- 8< ---------
 +
 +2012-09-06 - 29e972f - lavu 51.72.100 - parseutils.h
 +  Add av_small_strptime() time parsing function.
 +
 +  Can be used as a stripped-down replacement for strptime(), on
 +  systems which do not support it.
 +
 +2012-08-25 - 2626cc4 - lavf 54.28.100
 +  Matroska demuxer now identifies SRT subtitles as AV_CODEC_ID_SUBRIP instead
 +  of AV_CODEC_ID_TEXT.
 +
 +2012-08-13 - 5c0d8bc - lavfi 3.8.100 - avfilter.h
 +  Add avfilter_get_class() function, and priv_class field to AVFilter
 +  struct.
 +
 +2012-08-12 - a25346e - lavu 51.69.100 - opt.h
 +  Add AV_OPT_FLAG_FILTERING_PARAM symbol in opt.h.
 +
 +2012-07-31 - 23fc4dd - lavc 54.46.100
 +  Add channels field to AVFrame.
 +
 +2012-07-30 - f893904 - lavu 51.66.100
 +  Add av_get_channel_description()
 +  and av_get_standard_channel_layout() functions.
 +
 +2012-07-21 - 016a472 - lavc 54.43.100
 +  Add decode_error_flags field to AVFrame.
 +
 +2012-07-20 - b062936 - lavf 54.18.100
 +  Add avformat_match_stream_specifier() function.
 +
 +2012-07-14 - f49ec1b - lavc 54.38.100 - avcodec.h
 +  Add metadata to AVFrame, and the accessor functions
 +  av_frame_get_metadata() and av_frame_set_metadata().
 +
 +2012-07-10 - 0e003d8 - lavc 54.33.100
 +  Add av_fast_padded_mallocz().
 +
 +2012-07-10 - 21d5609 - lavfi 3.2.0 - avfilter.h
 +  Add init_opaque() callback to AVFilter struct.
 +
 +2012-06-26 - e6674e4 - lavu 51.63.100 - imgutils.h
 +  Add functions to libavutil/imgutils.h:
 +  av_image_get_buffer_size()
 +  av_image_fill_arrays()
 +  av_image_copy_to_buffer()
 +
 +2012-06-24 - c41899a - lavu 51.62.100 - version.h
 +  version moved from avutil.h to version.h
 +
 +2012-04-11 - 359abb1 - lavu 51.58.100 - error.h
 +  Add av_make_error_string() and av_err2str() utilities to
 +  libavutil/error.h.
 +
 +2012-06-05 - 62b39d4 - lavc 54.24.100
 +  Add pkt_duration field to AVFrame.
 +
 +2012-05-24 - f2ee065 - lavu 51.54.100
 +  Move AVPALETTE_SIZE and AVPALETTE_COUNT macros from
 +  libavcodec/avcodec.h to libavutil/pixfmt.h.
 +
 +2012-05-14 - 94a9ac1 - lavf 54.5.100
 +  Add av_guess_sample_aspect_ratio() function.
 +
 +2012-04-20 - 65fa7bc - lavfi 2.70.100
 +  Add avfilter_unref_bufferp() to avfilter.h.
 +
 +2012-04-13 - 162e400 - lavfi 2.68.100
 +  Install libavfilter/asrc_abuffer.h public header.
 +
 +2012-03-26 - a67d9cf - lavfi 2.66.100
 +  Add avfilter_fill_frame_from_{audio_,}buffer_ref() functions.
 +
 +2013-05-15 - ff46809 / e6c4ac7 - lavu 52.32.100 / 52.11.0 - pixdesc.h
    Replace PIX_FMT_* flags with AV_PIX_FMT_FLAG_*.
  
 -2013-04-03 - 507b1e4 - lavc 55.4.0 - avcodec.h
 +2013-04-03 - 6fc58a8 / 507b1e4 - lavc 55.7.100 / 55.4.0 - avcodec.h
    Add field_order to AVCodecParserContext.
  
 -2013-04-19 - 5e83d9a - lavc 55.2.0 - avcodec.h
 +2013-04-19 - f4b05cd / 5e83d9a - lavc 55.5.100 / 55.2.0 - avcodec.h
    Add CODEC_FLAG_UNALIGNED to allow decoders to produce unaligned output.
  
 -2013-04-11 - lavfi 3.8.0
 -  38f0c07 - Move all content from avfiltergraph.h to avfilter.h. Deprecate
 +2013-04-11 - lavfi 3.53.100 / 3.8.0
 +  231fd44 / 38f0c07 - Move all content from avfiltergraph.h to avfilter.h. Deprecate
              avfilterhraph.h, user applications should include just avfilter.h
 -  bc1a985 - Add avfilter_graph_alloc_filter(), deprecate avfilter_open() and
 +  86070b8 / bc1a985 - Add avfilter_graph_alloc_filter(), deprecate avfilter_open() and
              avfilter_graph_add_filter().
 -  1113672 - Add AVFilterContext.graph pointing to the AVFilterGraph that contains the
 +  4fde705 / 1113672 - Add AVFilterContext.graph pointing to the AVFilterGraph that contains the
              filter.
 -  48a5ada - Add avfilter_init_str(), deprecate avfilter_init_filter().
 -  1ba95a9 - Add avfilter_init_dict().
 -  7cdd737 - Add AVFilter.flags field and AVFILTER_FLAG_DYNAMIC_{INPUTS,OUTPUTS} flags.
 -  7e8fe4b - Add avfilter_pad_count() for counting filter inputs/outputs.
 -  fa2a34c - Add avfilter_next(), deprecate av_filter_next().
 +  710b0aa / 48a5ada - Add avfilter_init_str(), deprecate avfilter_init_filter().
 +  46de9ba / 1ba95a9 - Add avfilter_init_dict().
 +  16fc24b / 7cdd737 - Add AVFilter.flags field and AVFILTER_FLAG_DYNAMIC_{INPUTS,OUTPUTS} flags.
 +  f4db6bf / 7e8fe4b - Add avfilter_pad_count() for counting filter inputs/outputs.
 +  835cc0f / fa2a34c - Add avfilter_next(), deprecate av_filter_next().
              Deprecate avfilter_uninit().
  
 -2013-04-09 - lavfi 3.7.0 - avfilter.h
 -  b439c99 - Add AVFilter.priv_class for exporting filter options through the
 +2013-04-09 - lavfi 3.51.100 / 3.7.0 - avfilter.h
 +  0594ef0 / b439c99 - Add AVFilter.priv_class for exporting filter options through the
              AVOptions API in the similar way private options work in lavc and lavf.
 -  8114c10 - Add avfilter_get_class().
 +  44d4488 / 8114c10 - Add avfilter_get_class().
    Switch all filters to use AVOptions.
  
 -2013-03-19 - 2c328a9 - lavu 52.9.0 - pixdesc.h
 +2013-03-19 - 17ebef2 / 2c328a9 - lavu 52.20.100 / 52.9.0 - pixdesc.h
    Add av_pix_fmt_count_planes() function for counting planes in a pixel format.
  
 -2013-03-16 - 42c7c61 - lavfi 3.6.0
 +2013-03-16 - ecade98 / 42c7c61 - lavfi 3.47.100 / 3.6.0
    Add AVFilterGraph.nb_filters, deprecate AVFilterGraph.filter_count.
  
 -2013-03-08 - Reference counted buffers - lavu 52.8.0, lavc 55.0.0, lavf 55.0.0,
 -lavd 54.0.0, lavfi 3.5.0
 -  8e401db, 1cec062 - add a new API for reference counted buffers and buffer
 +2013-03-08 - Reference counted buffers - lavu 52.8.0, lavc 55.0.100 / 55.0.0, lavf 55.0.100 / 55.0.0,
 +lavd 54.4.100 / 54.0.0, lavfi 3.5.0
 +  36099df / 8e401db, 532f31a / 1cec062 - add a new API for reference counted buffers and buffer
                       pools (new header libavutil/buffer.h).
 -  1afddbe - add AVPacket.buf to allow reference counting for the AVPacket data.
 +  2653e12 / 1afddbe - add AVPacket.buf to allow reference counting for the AVPacket data.
              Add av_packet_from_data() function for constructing packets from
              av_malloc()ed data.
 -  7ecc2d4 - move AVFrame from lavc to lavu (new header libavutil/frame.h), add
 +  c4e8821 / 7ecc2d4 - move AVFrame from lavc to lavu (new header libavutil/frame.h), add
              AVFrame.buf/extended_buf to allow reference counting for the AVFrame
              data. Add new API for working with reference-counted AVFrames.
 -  759001c - add the refcounted_frames field to AVCodecContext to make audio and
 +  80e9e63 / 759001c - add the refcounted_frames field to AVCodecContext to make audio and
              video decoders return reference-counted frames. Add get_buffer2()
              callback to AVCodecContext which allocates reference-counted frames.
              Add avcodec_default_get_buffer2() as the default get_buffer2()
                  * qscale_table, qstride, qscale_type, mbskip_table, motion_val,
                    mb_type, dct_coeff, ref_index -- mpegvideo-specific tables,
                    which are not exported anymore.
 -  7e35037 - switch libavfilter to use AVFrame instead of AVFilterBufferRef. Add
 +  a05a44e / 7e35037 - switch libavfilter to use AVFrame instead of AVFilterBufferRef. Add
              av_buffersrc_add_frame(), deprecate av_buffersrc_buffer().
              Add av_buffersink_get_frame() and av_buffersink_get_samples(),
              deprecate av_buffersink_read() and av_buffersink_read_samples().
              Deprecate AVFilterBufferRef and all functions for working with it.
  
 -2013-03-17 - 12c5c1d - lavu 52.8.0 - avstring.h
 +2013-03-17 - 6c17ff8 / 12c5c1d - lavu 52.19.100 / 52.8.0 - avstring.h
    Add av_isdigit, av_isgraph, av_isspace, av_isxdigit.
  
 -2013-02-23 - 9f12235 - lavfi 3.4.0 - avfiltergraph.h
 +2013-02-23 - 71cf094 / 9f12235 - lavfi 3.40.100 / 3.4.0 - avfiltergraph.h
    Add resample_lavr_opts to AVFilterGraph for setting libavresample options
    for auto-inserted resample filters.
  
 -2013-01-25 - 38c1466 - lavu 52.7.0 - dict.h
 +2013-01-25 - e7e14bc / 38c1466 - lavu 52.17.100 / 52.7.0 - dict.h
    Add av_dict_parse_string() to set multiple key/value pairs at once from a
    string.
  
 -2013-01-25 - b85a5e8 - lavu 52.6.0 - avstring.h
 +2013-01-25 - 25be630 / b85a5e8 - lavu 52.16.100 / 52.6.0 - avstring.h
    Add av_strnstr()
  
 -2013-01-15 - 8ee288d - lavu 52.5.0 - hmac.h
 +2013-01-15 - e7e0186 / 8ee288d - lavu 52.15.100 / 52.5.0 - hmac.h
    Add AVHMAC.
  
 -2013-01-13 - 44e065d - lavc 54.36.0 - vdpau.h
 +2013-01-13 - 8ee7b38 / 44e065d - lavc 54.87.100 / 54.36.0 - vdpau.h
    Add AVVDPAUContext struct for VDPAU hardware-accelerated decoding.
  
 -2013-01-12 - 169fb94 - lavu 52.4.0 - pixdesc.h
 +2013-01-12 - dae382b / 169fb94 - lavu 52.14.100 / 52.4.0 - pixdesc.h
    Add AV_PIX_FMT_VDPAU flag.
  
 -2013-01-07 - 074a00d - lavr 1.1.0
 +2013-01-07 - 249fca3 / 074a00d - lavr 1.1.0
    Add avresample_set_channel_mapping() for input channel reordering,
    duplication, and silencing.
  
 -------------------------------8<-------------------------------------
 -                   9 branch was cut here
 ------------------------------>8--------------------------------------
 -
 -2012-12-29 - lavu 52.3.0
 -  d8fd06c - Add av_basename() and av_dirname().
 -  c1a02e8 - Add av_pix_fmt_get_chroma_sub_sample and deprecate
 -            avcodec_get_chroma_sub_sample.
 +2012-12-29 - lavu 52.13.100 / 52.3.0 - avstring.h
 +  2ce43b3 / d8fd06c - Add av_basename() and av_dirname().
 +  e13d5e9 / c1a02e8 - Add av_pix_fmt_get_chroma_sub_sample and deprecate
 +                      avcodec_get_chroma_sub_sample.
  
 -2012-11-11 - 5980f5d - lavu 52.2.0 - audioconvert.h
 +2012-11-11 - 03b0787 / 5980f5d - lavu 52.6.100 / 52.2.0 - audioconvert.h
    Rename audioconvert.h to channel_layout.h. audioconvert.h is now deprecated.
  
 -2012-11-05 - dfde8a3 - lavu 52.1.0 - intmath.h
 -  Add av_ctz() for trailing zero bit count
 -
 -2012-10-21 - a893655 - lavu 51.45.0 - error.h
 +2012-10-21 - e3a91c5 / a893655 - lavu 51.77.100 / 51.45.0 - error.h
    Add AVERROR_EXPERIMENTAL
  
 -2012-10-12 - d2fcb35 - lavu 51.44.0 - pixdesc.h
 +2012-10-12 - a33ed6b / d2fcb35 - lavu 51.76.100 / 51.44.0 - pixdesc.h
    Add functions for accessing pixel format descriptors.
    Accessing the av_pix_fmt_descriptors array directly is now
    deprecated.
  
 -2012-10-11 - 9a92aea - lavu 51.43.0 - aes.h, md5.h, sha.h, tree.h
 +2012-10-11 - f391e40 / 9a92aea - lavu 51.75.100 / 51.43.0 - aes.h, md5.h, sha.h, tree.h
    Add functions for allocating the opaque contexts for the algorithms,
 -  deprecate the context size variables.
  
 -2012-10-10 - b522000 - lavf 54.18.0 - avio.h
 +2012-10-10 - de31814 / b522000 - lavf 54.32.100 / 54.18.0 - avio.h
    Add avio_closep to complement avio_close.
  
 -2012-10-08 - 78071a1 - lavu 51.42.0 - pixfmt.h
 +2012-10-08 - ae77266 / 78071a1 - lavu 51.74.100 / 51.42.0 - pixfmt.h
    Rename PixelFormat to AVPixelFormat and all PIX_FMT_* to AV_PIX_FMT_*.
    To provide backwards compatibility, PixelFormat is now #defined as
    AVPixelFormat.
    'PixelFormat' identifier. Such code should either #undef PixelFormat
    or stop using the PixelFormat name.
  
 -2012-10-05 - e7ba5b1 - lavr 1.0.0 - avresample.h
 +2012-10-05 - 55c49af / e7ba5b1 - lavr 1.0.0 - avresample.h
    Data planes parameters to avresample_convert() and
    avresample_read() are now uint8_t** instead of void**.
    Libavresample is now stable.
  
 -2012-09-24 - a42aada - lavc 54.28.0 - avcodec.h
 +2012-09-26 - 3ba0dab7 / 1384df64 - lavf 54.29.101 / 56.06.3 - avformat.h
 +  Add AVFormatContext.avoid_negative_ts.
 +
 +2012-09-24 - 46a3595 / a42aada - lavc 54.59.100 / 54.28.0 - avcodec.h
    Add avcodec_free_frame(). This function must now
    be used for freeing an AVFrame.
  
 -2012-09-12 - 8919fee - lavu 51.41.0 - audioconvert.h
 +2012-09-12 - e3e09f2 / 8919fee - lavu 51.73.100 / 51.41.0 - audioconvert.h
    Added AV_CH_LOW_FREQUENCY_2 channel mask value.
  
 -2012-09-04 - 686a329 - lavu 51.40.0 - opt.h
 +2012-09-04 - b21b5b0 / 686a329 - lavu 51.71.100 / 51.40.0 - opt.h
    Reordered the fields in default_val in AVOption, changed which
    default_val field is used for which AVOptionType.
  
 -2012-08-30 - a231832 - lavc 54.26.1 - avcodec.h
 +2012-08-30 - 98298eb / a231832 - lavc 54.54.101 / 54.26.1 - avcodec.h
    Add codec descriptor properties AV_CODEC_PROP_LOSSY and
    AV_CODEC_PROP_LOSSLESS.
  
    Add codec descriptors for accessing codec properties without having
    to refer to a specific decoder or encoder.
  
 -  c223d79 - Add an AVCodecDescriptor struct and functions
 +  f5f3684 / c223d79 - Add an AVCodecDescriptor struct and functions
              avcodec_descriptor_get() and avcodec_descriptor_next().
 -  51efed1 - Add AVCodecDescriptor.props and AV_CODEC_PROP_INTRA_ONLY.
 -  91e59fe - Add avcodec_descriptor_get_by_name().
 -
 +  f5f3684 / 51efed1 - Add AVCodecDescriptor.props and AV_CODEC_PROP_INTRA_ONLY.
 +  6c180b3 / 91e59fe - Add avcodec_descriptor_get_by_name().
  
 -2012-08-08 - 1d9c2dc - lavu 51.39 - avutil.h
 -  Don't implicitly include libavutil/common.h in avutil.h
 -
 -2012-08-08 - 987170c - lavu 51.38 - dict.h
 +2012-08-08 - f5f3684 / 987170c - lavu 51.68.100 / 51.38.0 - dict.h
    Add av_dict_count().
  
 -2012-08-07 - 104e10f - lavc 54.25 - avcodec.h
 +2012-08-07 - 7a72695 / 104e10f - lavc 54.51.100 / 54.25.0 - avcodec.h
    Rename CodecID to AVCodecID and all CODEC_ID_* to AV_CODEC_ID_*.
    To provide backwards compatibility, CodecID is now #defined as AVCodecID.
    Note that this can break user code that includes avcodec.h and uses the
    'CodecID' identifier. Such code should either #undef CodecID or stop using the
    CodecID name.
  
 -2012-08-03 - 239fdf1 - lavu 51.37.1 - cpu.h
 +2012-08-03 - e776ee8 / 239fdf1 - lavu 51.66.101 / 51.37.1 - cpu.h
                         lsws 2.1.1   - swscale.h
    Rename AV_CPU_FLAG_MMX2  ---> AV_CPU_FLAG_MMXEXT.
    Rename SWS_CPU_CAPS_MMX2 ---> SWS_CPU_CAPS_MMXEXT.
  
 -2012-07-29 - 681ed00 - lavf 54.13.0 - avformat.h
 +2012-07-29 - 7c26761 / 681ed00 - lavf 54.22.100 / 54.13.0 - avformat.h
    Add AVFMT_FLAG_NOBUFFER for low latency use cases.
  
 -2012-07-20 - b70d89a - lavfi 3.0.0 - avfilter.h
 -  Add avfilter_unref_bufferp().
 -
 -2012-07-10 - 5fade8a - lavu 51.37.0
 +2012-07-10 - fbe0245 / f3e5e6f - lavu 51.65.100 / 51.37.0
    Add av_malloc_array() and av_mallocz_array()
  
 -2012-06-22 - d3d3a32 - lavu 51.34.0
 +2012-06-22 - e847f41 / d3d3a32 - lavu 51.61.100 / 51.34.0
    Add av_usleep()
  
 -2012-06-20 - ae0a301 - lavu 51.33.0
 +2012-06-20 - 4da42eb / ae0a301 - lavu 51.60.100 / 51.33.0
    Move av_gettime() to libavutil, add libavutil/time.h
  
 -2012-06-09 - 3971be0 - lavr 0.0.3
 +2012-06-09 - 82edf67 / 3971be0 - lavr 0.0.3
    Add a parameter to avresample_build_matrix() for Dolby/DPLII downmixing.
  
 -2012-06-12 - 9baeff9 - lavfi 2.23.0 - avfilter.h
 +2012-06-12 - c7b9eab / 9baeff9 - lavfi 2.79.100 / 2.23.0 - avfilter.h
    Add AVFilterContext.nb_inputs/outputs. Deprecate
    AVFilterContext.input/output_count.
  
 -2012-06-12 - 84b9fbe - lavfi 2.22.0 - avfilter.h
 +2012-06-12 - c7b9eab / 84b9fbe - lavfi 2.79.100 / 2.22.0 - avfilter.h
    Add avfilter_pad_get_type() and avfilter_pad_get_name(). Those
    should now be used instead of accessing AVFilterPad members
    directly.
  
 -2012-06-12 - b0f0dfc - lavu 51.32.0 - audioconvert.h
 +2012-06-12 - 3630a07 / b0f0dfc - lavu 51.57.100 / 51.32.0 - audioconvert.h
    Add av_get_channel_layout_channel_index(), av_get_channel_name()
    and av_channel_layout_extract_channel().
  
 -2012-05-25 - 154486f - lavu 51.31.0 - opt.h
 +2012-05-25 - 53ce990 / 154486f - lavu 51.55.100 / 51.31.0 - opt.h
    Add av_opt_set_bin()
  
 -2012-05-26 - e9cef89 - lavf 54.3.0
 -  Add AVFMT_TS_NONSTRICT format flag to indicate that a muxer supports
 -  non-increasing monotone timestamps.
 -
 -2012-05-15 - lavfi 2.17.0
 +2012-05-15 - lavfi 2.74.100 / 2.17.0
    Add support for audio filters
 -  ac71230/a2cd9be - add video/audio buffer sink in a new installed
 +  61930bd / ac71230, 1cbf7fb / a2cd9be - add video/audio buffer sink in a new installed
                      header buffersink.h
 -  720c6b7 - add av_buffersrc_write_frame(), deprecate
 +  1cbf7fb / 720c6b7 - add av_buffersrc_write_frame(), deprecate
              av_vsrc_buffer_add_frame()
 -  ab16504 - add avfilter_copy_buf_props()
 -  9453c9e - add extended_data to AVFilterBuffer
 -  1b8c927 - add avfilter_get_audio_buffer_ref_from_arrays()
 +  61930bd / ab16504 - add avfilter_copy_buf_props()
 +  61930bd / 9453c9e - add extended_data to AVFilterBuffer
 +  61930bd / 1b8c927 - add avfilter_get_audio_buffer_ref_from_arrays()
  
 -2012-05-09 - lavu 51.30.0 - samplefmt.h
 -  142e740 - add av_samples_copy()
 -  6d7f617 - add av_samples_set_silence()
 +2012-05-09 - lavu 51.53.100 / 51.30.0 - samplefmt.h
 +  61930bd / 142e740 - add av_samples_copy()
 +  61930bd / 6d7f617 - add av_samples_set_silence()
  
 -2012-05-09 - a5117a2 - lavc 54.13.1
 +2012-05-09 - 61930bd / a5117a2 - lavc 54.21.101 / 54.13.1
    For audio formats with fixed frame size, the last frame
    no longer needs to be padded with silence, libavcodec
    will handle this internally (effectively all encoders
    behave as if they had CODEC_CAP_SMALL_LAST_FRAME set).
  
 -2012-05-07 - 828bd08 - lavc 54.13.0 - avcodec.h
 +2012-05-07 - 653d117 / 828bd08 - lavc 54.20.100 / 54.13.0 - avcodec.h
    Add sample_rate and channel_layout fields to AVFrame.
  
 -2012-05-01 - 4010d72 - lavr 0.0.1
 +2012-05-01 - 2330eb1 / 4010d72 - lavr 0.0.1
    Change AV_MIX_COEFF_TYPE_Q6 to AV_MIX_COEFF_TYPE_Q8.
  
 -2012-04-25 - 3527a73 - lavu 51.29.0 - cpu.h
 +2012-04-25 - e890b68 / 3527a73 - lavu 51.48.100 / 51.29.0 - cpu.h
    Add av_parse_cpu_flags()
  
 -2012-04-24 - c8af852 - lavr 0.0.0
 +2012-04-24 - 3ead79e / c8af852 - lavr 0.0.0
    Add libavresample audio conversion library
  
 -2012-04-20 - 0c0d1bc - lavu 51.28.0 - audio_fifo.h
 +2012-04-20 - 3194ab7 / 0c0d1bc - lavu 51.47.100 / 51.28.0 - audio_fifo.h
    Add audio FIFO functions:
      av_audio_fifo_free()
      av_audio_fifo_alloc()
      av_audio_fifo_size()
      av_audio_fifo_space()
  
 -2012-04-14 - lavfi 2.16.0 - avfiltergraph.h
 -  d7bcc71 Add avfilter_graph_parse2().
 -  91d3cbe Add avfilter_inout_alloc() and avfilter_inout_free().
 +2012-04-14 - lavfi 2.70.100 / 2.16.0 - avfiltergraph.h
 +  7432bcf / d7bcc71 Add avfilter_graph_parse2().
  
 -2012-04-08 - 4d693b0 - lavu 51.27.0 - samplefmt.h
 +2012-04-08 - 6bfb304 / 4d693b0 - lavu 51.46.100 / 51.27.0 - samplefmt.h
    Add av_get_packed_sample_fmt() and av_get_planar_sample_fmt()
  
 -2012-04-05 - 5cc51a5 - lavu 51.26.0 - audioconvert.h
 -  Add av_get_default_channel_layout()
 +2012-03-21 - b75c67d - lavu 51.43.100
 +  Add bprint.h for bprint API.
 +
 +2012-02-21 - 9cbf17e - lavc 54.4.100
 +  Add av_get_pcm_codec() function.
 +
 +2012-02-16 - 560b224 - libswr 0.7.100
 +  Add swr_set_matrix() function.
 +
 +2012-02-09 - c28e7af - lavu 51.39.100
 +  Add a new installed header libavutil/timestamp.h with timestamp
 +  utilities.
 +
 +2012-02-06 - 70ffda3 - lavu 51.38.100
 +  Add av_parse_ratio() function to parseutils.h.
 +
 +2012-02-06 - 70ffda3 - lavu 51.38.100
 +  Add AV_LOG_MAX_OFFSET macro to log.h.
  
 -2012-03-20 - 3c90cc2 - lavfo 54.2.0
 +2012-02-02 - 0eaa123 - lavu 51.37.100
 +  Add public timecode helpers.
 +
 +2012-01-24 - 0c3577b - lavfi 2.60.100
 +  Add avfilter_graph_dump.
 +
 +2012-03-20 - 0ebd836 / 3c90cc2 - lavfo 54.2.0
    Deprecate av_read_packet(), use av_read_frame() with
    AVFMT_FLAG_NOPARSE | AVFMT_FLAG_NOFILLIN in AVFormatContext.flags
  
 -2012-03-06 - 4d851f8 - lavu 51.25.0 - cpu.h
 -  Add av_set_cpu_flags_mask().
 +2012-03-05 - lavc 54.10.100 / 54.8.0
 +  f095391 / 6699d07 Add av_get_exact_bits_per_sample()
 +  f095391 / 9524cf7 Add av_get_audio_frame_duration()
  
 -2012-03-05 - lavc 54.8.0
 -  6699d07 Add av_get_exact_bits_per_sample()
 -  9524cf7 Add av_get_audio_frame_duration()
 -
 -2012-03-04 - 44fe77b - lavc 54.7.0 - avcodec.h
 +2012-03-04 - 2af8f2c / 44fe77b - lavc 54.8.100 / 54.7.0 - avcodec.h
    Add av_codec_is_encoder/decoder().
  
 -2012-03-01 - 442c132 - lavc 54.3.0 - avcodec.h
 +2012-03-01 - 1eb7f39 / 442c132 - lavc 54.5.100 / 54.3.0 - avcodec.h
    Add av_packet_shrink_side_data.
  
 -2012-02-29 - dd2a4bc - lavf 54.2.0 - avformat.h
 +2012-02-29 - 79ae084 / dd2a4bc - lavf 54.2.100 / 54.2.0 - avformat.h
    Add AVStream.attached_pic and AV_DISPOSITION_ATTACHED_PIC,
    used for dealing with attached pictures/cover art.
  
 -2012-02-25 - c9bca80 - lavu 51.24.0 - error.h
 +2012-02-25 - 305e4b3 / c9bca80 - lavu 51.41.100 / 51.24.0 - error.h
    Add AVERROR_UNKNOWN
    NOTE: this was backported to 0.8
  
 -2012-02-20 - e9cda85 - lavc 54.2.0
 +2012-02-20 - eadd426 / e9cda85 - lavc 54.2.100 / 54.2.0
    Add duration field to AVCodecParserContext
  
 -2012-02-20 - 0b42a93 - lavu 51.23.1 - mathematics.h
 +2012-02-20 - eadd426 / 0b42a93 - lavu 51.40.100 / 51.23.1 - mathematics.h
    Add av_rescale_q_rnd()
  
 -2012-02-08 - 38d5533 - lavu 51.22.1 - pixdesc.h
 +2012-02-08 - f2b20b7 / 38d5533 - lavu 51.38.101 / 51.22.1 - pixdesc.h
    Add PIX_FMT_PSEUDOPAL flag.
  
 -2012-02-08 - 52f82a1 - lavc 54.01.0
 +2012-02-08 - f2b20b7 / 52f82a1 - lavc 54.2.100 / 54.1.0
    Add avcodec_encode_video2() and deprecate avcodec_encode_video().
  
 -2012-02-01 - 316fc74 - lavc 54.01.0
 +2012-02-01 - 4c677df / 316fc74 - lavc 54.1.0
    Add av_fast_padded_malloc() as alternative for av_realloc() when aligned
    memory is required. The buffer will always have FF_INPUT_BUFFER_PADDING_SIZE
    zero-padded bytes at the end.
  
 -2012-01-31 - dd6d3b0 - lavf 54.01.0
 +2012-01-31 - a369a6b / dd6d3b0 - lavf 54.1.0
    Add avformat_get_riff_video_tags() and avformat_get_riff_audio_tags().
    NOTE: this was backported to 0.8
  
 -2012-01-31 - af08d9a - lavc 54.01.0
 +2012-01-31 - a369a6b / af08d9a - lavc 54.1.0
    Add avcodec_is_open() function.
    NOTE: this was backported to 0.8
  
 -2012-01-30 - 8b93312 - lavu 51.22.0 - intfloat.h
 +2012-01-30 - 151ecc2 / 8b93312 - lavu 51.36.100 / 51.22.0 - intfloat.h
    Add a new installed header libavutil/intfloat.h with int/float punning
    functions.
    NOTE: this was backported to 0.8
  
 -2012-01-25 - lavf 53.22.0
 -  f1caf01 Allow doing av_write_frame(ctx, NULL) for flushing possible
 +2012-01-25 - lavf 53.31.100 / 53.22.0
 +  3c5fe5b / f1caf01 Allow doing av_write_frame(ctx, NULL) for flushing possible
            buffered data within a muxer. Added AVFMT_ALLOW_FLUSH for
            muxers supporting it (av_write_frame makes sure it is called
            only for muxers with this flag).
  
 -------------------------------8<-------------------------------------
 -                   0.8 branch was cut here
 ------------------------------>8--------------------------------------
 -
 -2012-01-15 - lavc 53.34.0
 +2012-01-15 - lavc 53.56.105 / 53.34.0
    New audio encoding API:
 -  b2c75b6 Add CODEC_CAP_VARIABLE_FRAME_SIZE capability for use by audio
 +  67f5650 / b2c75b6 Add CODEC_CAP_VARIABLE_FRAME_SIZE capability for use by audio
            encoders.
 -  5ee5fa0 Add avcodec_fill_audio_frame() as a convenience function.
 -  b2c75b6 Add avcodec_encode_audio2() and deprecate avcodec_encode_audio().
 +  67f5650 / 5ee5fa0 Add avcodec_fill_audio_frame() as a convenience function.
 +  67f5650 / b2c75b6 Add avcodec_encode_audio2() and deprecate avcodec_encode_audio().
            Add AVCodec.encode2().
  
 -2012-01-12 - 3167dc9 - lavfi 2.15.0
 +2012-01-12 - b18e17e / 3167dc9 - lavfi 2.59.100 / 2.15.0
    Add a new installed header -- libavfilter/version.h -- with version macros.
  
 -2011-01-03 - b73ec05 - lavu 51.21.0
 +
 +-------- 8< --------- FFmpeg 0.9 was cut here -------- 8< ---------
 +
 +2011-12-08 - a502939 - lavfi 2.52.0
 +  Add av_buffersink_poll_frame() to buffersink.h.
 +
 +2011-12-08 - 26c6fec - lavu 51.31.0
 +  Add av_log_format_line.
 +
 +2011-12-03 - 976b095 - lavu 51.30.0
 +  Add AVERROR_BUG.
 +
 +2011-11-24 - 573ffbb - lavu 51.28.1
 +  Add av_get_alt_sample_fmt() to samplefmt.h.
 +
 +2011-11-03 - 96949da - lavu 51.23.0
 +  Add av_strcasecmp() and av_strncasecmp() to avstring.h.
 +
 +2011-10-20 - b35e9e1 - lavu 51.22.0
 +  Add av_strtok() to avstring.h.
 +
 +2012-01-03 - ad1c8dd / b73ec05 - lavu 51.34.100 / 51.21.0
    Add av_popcount64
  
 -2011-12-25 - lavfi 2.14.0
 -  e1d9dbf Add a new installed header - buffersrc.h
 -  It contains a new function av_buffersrc_buffer() that allows passing
 -  frames to the 'buffer' filter, but unlike av_vsrc_buffer_add_frame()
 -  it allows for direct rendering.
 -  1c9e340 Add avfilter_copy_frame_props() for copying properties from
 -  AVFrame to AVFilterBufferRef.
 -
 -2011-12-25 - lavc 53.31.0
 -  Add the following new fields to AVFrame:
 -    b58dbb5 sample_aspect_ratio
 -    3a2ddf7 width, height
 -    8a4a5f6 format
 -
 -2011-12-18 - 8400b12 - lavc 53.28.1
 +2011-12-18 - 7c29313 / 8400b12 - lavc 53.46.1 / 53.28.1
    Deprecate AVFrame.age. The field is unused.
  
 -2011-12-12 - 5266045 - lavf 53.17.0
 +2011-12-12 - 8bc7fe4 / 5266045 - lavf 53.25.0 / 53.17.0
    Add avformat_close_input().
    Deprecate av_close_input_file() and av_close_input_stream().
  
 -2011-12-09 - b2890f5 - lavu 51.20.0 - audioconvert.h
 +2011-12-09 - c59b80c / b2890f5 - lavu 51.32.0 / 51.20.0 - audioconvert.h
    Expand the channel layout list.
  
 -2011-12-02 - 0eea212 - lavc 53.25.0
 +2011-12-02 - e4de716 / 0eea212 - lavc 53.40.0 / 53.25.0
    Add nb_samples and extended_data fields to AVFrame.
    Deprecate AVCODEC_MAX_AUDIO_FRAME_SIZE.
    Deprecate avcodec_decode_audio3() in favor of avcodec_decode_audio4().
    avcodec_decode_audio4() writes output samples to an AVFrame, which allows
    audio decoders to use get_buffer().
  
 -2011-12-04 - 560f773 - lavc 53.24.0
 +2011-12-04 - e4de716 / 560f773 - lavc 53.40.0 / 53.24.0
    Change AVFrame.data[4]/base[4]/linesize[4]/error[4] to [8] at next major bump.
    Change AVPicture.data[4]/linesize[4] to [8] at next major bump.
    Change AVCodecContext.error[4] to [8] at next major bump.
    Add AV_NUM_DATA_POINTERS to simplify the bump transition.
  
 -2011-11-24 - lavu 51.19.0
 -  bd97b2e - add planar RGB pixel formats
 -  6b0768e - add PIX_FMT_PLANAR and PIX_FMT_RGB pixel descriptions
 +2011-11-24 - lavu 51.29.0 / 51.19.0
 +  92afb43 / bd97b2e - add planar RGB pixel formats
 +  92afb43 / 6b0768e - add PIX_FMT_PLANAR and PIX_FMT_RGB pixel descriptions
  
 -2011-11-23 - bbb46f3 - lavu 51.18.0
 +2011-11-23 - 8e576d5 / bbb46f3 - lavu 51.27.0 / 51.18.0
    Add av_samples_get_buffer_size(), av_samples_fill_arrays(), and
    av_samples_alloc(), to samplefmt.h.
  
 -2011-11-23 - 8889cc4 - lavu 51.17.0
 +2011-11-23 - 8e576d5 / 8889cc4 - lavu 51.27.0 / 51.17.0
    Add planar sample formats and av_sample_fmt_is_planar() to samplefmt.h.
  
 -2011-11-19 - f3a29b7 - lavc 53.21.0
 +2011-11-19 - dbb38bc / f3a29b7 - lavc 53.36.0 / 53.21.0
    Move some AVCodecContext fields to a new private struct, AVCodecInternal,
    which is accessed from a new field, AVCodecContext.internal.
    - fields moved:
        AVCodecContext.internal_buffer_count --> AVCodecInternal.buffer_count
        AVCodecContext.is_copy               --> AVCodecInternal.is_copy
  
 -2011-11-16 - 6270671 - lavu 51.16.0
 +2011-11-16 - 8709ba9 / 6270671 - lavu 51.26.0 / 51.16.0
    Add av_timegm()
  
 -2011-11-13 - lavf 53.15.0
 +2011-11-13 - lavf 53.21.0 / 53.15.0
    New interrupt callback API, allowing per-AVFormatContext/AVIOContext
    interrupt callbacks.
 -  6aa0b98 Add AVIOInterruptCB struct and the interrupt_callback field to
 +  5f268ca / 6aa0b98 Add AVIOInterruptCB struct and the interrupt_callback field to
            AVFormatContext.
 -  1dee0ac Add avio_open2() with additional parameters. Those are
 +  5f268ca / 1dee0ac Add avio_open2() with additional parameters. Those are
            an interrupt callback and an options AVDictionary.
            This will allow passing AVOptions to protocols after lavf
            54.0.
  
 -2011-11-06 - ba04ecf - lavu 51.14.0
 +2011-11-06 - 13b7781 / ba04ecf - lavu 51.24.0 / 51.14.0
    Add av_strcasecmp() and av_strncasecmp() to avstring.h.
  
 -2011-11-06 - 07b172f - lavu 51.13.0
 +2011-11-06 - 13b7781 / 07b172f - lavu 51.24.0 / 51.13.0
    Add av_toupper()/av_tolower()
  
 -2011-11-05 - b6d08f4 - lavf 53.13.0
 +2011-11-05 - d8cab5c / b6d08f4 - lavf 53.19.0 / 53.13.0
    Add avformat_network_init()/avformat_network_deinit()
  
 -2011-10-27 - 512557b - lavc 53.15.0
 +2011-10-27 - 6faf0a2 / 512557b - lavc 53.24.0 / 53.15.0
    Remove avcodec_parse_frame.
    Deprecate AVCodecContext.parse_only and CODEC_CAP_PARSE_ONLY.
  
 -2011-10-19 - 569129a - lavf 53.10.0
 +2011-10-19 - d049257 / 569129a - lavf 53.17.0 / 53.10.0
    Add avformat_new_stream(). Deprecate av_new_stream().
  
 -2011-10-13 - b631fba - lavf 53.9.0
 +2011-10-13 - 91eb1b1 / b631fba - lavf 53.16.0 / 53.9.0
    Add AVFMT_NO_BYTE_SEEK AVInputFormat flag.
  
 -2011-10-12 - lavu 51.12.0
 +2011-10-12 - lavu 51.21.0 / 51.12.0
    AVOptions API rewrite.
  
 -  - 145f741 FF_OPT_TYPE* renamed to AV_OPT_TYPE_*
 +  - f884ef0 / 145f741 FF_OPT_TYPE* renamed to AV_OPT_TYPE_*
    - new setting/getting functions with slightly different semantics:
 -        dac66da av_set_string3 -> av_opt_set
 +        f884ef0 / dac66da av_set_string3 -> av_opt_set
                  av_set_double  -> av_opt_set_double
                  av_set_q       -> av_opt_set_q
                  av_set_int     -> av_opt_set_int
  
 -        41d9d51 av_get_string  -> av_opt_get
 +        f884ef0 / 41d9d51 av_get_string  -> av_opt_get
                  av_get_double  -> av_opt_get_double
                  av_get_q       -> av_opt_get_q
                  av_get_int     -> av_opt_get_int
  
 -  - 8c5dcaa trivial rename av_next_option -> av_opt_next
 -  - 641c7af new functions - av_opt_child_next, av_opt_child_class_next
 +  - f884ef0 / 8c5dcaa trivial rename av_next_option -> av_opt_next
 +  - f884ef0 / 641c7af new functions - av_opt_child_next, av_opt_child_class_next
      and av_opt_find2()
  
 -2011-09-03 - fb4ca26 - lavc 53.10.0
 -                       lavf 53.6.0
 +2011-09-22 - a70e787 - lavu 51.17.0
 +  Add av_x_if_null().
 +
 +2011-09-18 - 645cebb - lavc 53.16.0
 +  Add showall flag2
 +
 +2011-09-16 - ea8de10 - lavfi 2.42.0
 +  Add avfilter_all_channel_layouts.
 +
 +2011-09-16 - 9899037 - lavfi 2.41.0
 +  Rename avfilter_all_* function names to avfilter_make_all_*.
 +
 +  In particular, apply the renames:
 +  avfilter_all_formats         -> avfilter_make_all_formats
 +  avfilter_all_channel_layouts -> avfilter_make_all_channel_layouts
 +  avfilter_all_packing_formats -> avfilter_make_all_packing_formats
 +
 +2011-09-12 - 4381bdd - lavfi 2.40.0
 +  Change AVFilterBufferRefAudioProps.sample_rate type from uint32_t to int.
 +
 +2011-09-12 - 2c03174 - lavfi 2.40.0
 +  Simplify signature for avfilter_get_audio_buffer(), make it
 +  consistent with avfilter_get_video_buffer().
 +
 +2011-09-06 - 4f7dfe1 - lavfi 2.39.0
 +  Rename libavfilter/vsink_buffer.h to libavfilter/buffersink.h.
 +
 +2011-09-06 - c4415f6 - lavfi 2.38.0
 +  Unify video and audio sink API.
 +
 +  In particular, add av_buffersink_get_buffer_ref(), deprecate
 +  av_vsink_buffer_get_video_buffer_ref() and change the value for the
 +  opaque field passed to the abuffersink init function.
 +
 +2011-09-04 - 61e2e29 - lavu 51.16.0
 +  Add av_asprintf().
 +
 +2011-08-22 - dacd827 - lavf 53.10.0
 +  Add av_find_program_from_stream().
 +
 +2011-08-20 - 69e2c1a - lavu 51.13.0
 +  Add av_get_media_type_string().
 +
 +2011-09-03 - 1889c67 / fb4ca26 - lavc 53.13.0
 +                       lavf 53.11.0
                         lsws  2.1.0
    Add {avcodec,avformat,sws}_get_class().
  
 -2011-09-03 - c11fb82 - lavu 51.10.0
 +2011-08-03 - 1889c67 / c11fb82 - lavu 51.15.0
    Add AV_OPT_SEARCH_FAKE_OBJ flag for av_opt_find() function.
  
 -2011-08-26 - lavu 51.9.0
 -  - f2011ed Add av_fifo_peek2(), deprecate av_fifo_peek().
 -  - add41de..abc78a5 Do not include intfloat_readwrite.h,
 +2011-08-14 - 323b930 - lavu 51.12.0
 +  Add av_fifo_peek2(), deprecate av_fifo_peek().
 +
 +2011-08-26 - lavu 51.14.0 / 51.9.0
 +  - 976a8b2 / add41de..976a8b2 / abc78a5 Do not include intfloat_readwrite.h,
      mathematics.h, rational.h, pixfmt.h, or log.h from avutil.h.
  
 -2011-08-16 - 48f9e45 - lavf 53.4.0
 +2011-08-16 - 27fbe31 / 48f9e45 - lavf 53.11.0 / 53.8.0
    Add avformat_query_codec().
  
 -2011-08-16 - bca06e7 - lavc 53.8.0
 +2011-08-16 - 27fbe31 / bca06e7 - lavc 53.11.0
    Add avcodec_get_type().
  
 -2011-08-06 - 2f63440 - lavf 53.4.0
 +2011-08-06 - 0cb233c / 2f63440 - lavf 53.7.0
    Add error_recognition to AVFormatContext.
  
 -2011-08-02 - 9d39cbf - lavc 53.7.1
 +2011-08-02 - 1d186e9 / 9d39cbf - lavc 53.9.1
    Add AV_PKT_FLAG_CORRUPT AVPacket flag.
  
 -2011-07-10 - a67c061 - lavf 53.3.0
 +2011-07-16 - b57df29 - lavfi 2.27.0
 +  Add audio packing negotiation fields and helper functions.
 +
 +  In particular, add AVFilterPacking enum, planar, in_packings and
 +  out_packings fields to AVFilterLink, and the functions:
 +  avfilter_set_common_packing_formats()
 +  avfilter_all_packing_formats()
 +
 +2011-07-10 - 3602ad7 / a67c061 - lavf 53.6.0
    Add avformat_find_stream_info(), deprecate av_find_stream_info().
    NOTE: this was backported to 0.7
  
 -2011-07-10 - 0b950fe - lavc 53.6.0
 +2011-07-10 - 3602ad7 / 0b950fe - lavc 53.8.0
    Add avcodec_open2(), deprecate avcodec_open().
    NOTE: this was backported to 0.7
  
    Add avcodec_alloc_context3. Deprecate avcodec_alloc_context() and
    avcodec_alloc_context2().
  
 -2011-06-23 - 67e9ae1 - lavu 51.8.0 - attributes.h
 -  Add av_printf_format().
 +2011-07-01 - b442ca6 - lavf 53.5.0 - avformat.h
 +  Add function av_get_output_timestamp().
 +
 +2011-06-28 - 5129336 - lavu 51.11.0 - avutil.h
 +  Define the AV_PICTURE_TYPE_NONE value in AVPictureType enum.
 +
 +
 +-------- 8< --------- FFmpeg 0.7 was cut here -------- 8< ---------
 +
 +
 +
 +-------- 8< --------- FFmpeg 0.8 was cut here -------- 8< ---------
 +
 +2011-06-19 - fd2c0a5 - lavfi 2.23.0 - avfilter.h
 +  Add layout negotiation fields and helper functions.
 +
 +  In particular, add in_chlayouts and out_chlayouts to AVFilterLink,
 +  and the functions:
 +  avfilter_set_common_sample_formats()
 +  avfilter_set_common_channel_layouts()
 +  avfilter_all_channel_layouts()
 +
 +2011-06-19 - 527ca39 - lavfi 2.22.0 - AVFilterFormats
 +  Change type of AVFilterFormats.formats from int * to int64_t *,
 +  and update formats handling API accordingly.
 +
 +  avfilter_make_format_list() still takes a int32_t array and converts
 +  it to int64_t. A new function, avfilter_make_format64_list(), that
 +  takes int64_t arrays has been added.
 +
 +2011-06-19 - 44f669e - lavfi 2.21.0 - vsink_buffer.h
 +  Add video sink buffer and vsink_buffer.h public header.
  
 -------------------------------8<-------------------------------------
 -                   0.7 branch was cut here
 ------------------------------>8--------------------------------------
 +2011-06-12 - 9fdf772 - lavfi 2.18.0 - avcodec.h
 +  Add avfilter_get_video_buffer_ref_from_frame() function in
 +  libavfilter/avcodec.h.
  
 -2011-06-16 - 05e84c9, 25de595 - lavf 53.2.0 - avformat.h
 +2011-06-12 - c535494 - lavfi 2.17.0 - avfiltergraph.h
 +  Add avfilter_inout_alloc() and avfilter_inout_free() functions.
 +
 +2011-06-12 - 6119b23 - lavfi 2.16.0 - avfilter_graph_parse()
 +  Change avfilter_graph_parse() signature.
 +
 +2011-06-23 - 686959e / 67e9ae1 - lavu 51.10.0 / 51.8.0 - attributes.h
 +  Add av_printf_format().
 +
 +2011-06-16 - 2905e3f / 05e84c9, 2905e3f / 25de595 - lavf 53.4.0 / 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-16 - 7e83e1c, dc59ec5 - lavu 51.7.0 - opt.h
 +2011-06-16 - 2905e3f / 7e83e1c, 2905e3f / dc59ec5 - lavu 51.9.0 / 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-10 - cb7c11c - lavu 51.6.0 - opt.h
 +2011-06-10 - 45fb647 / cb7c11c - lavu 51.6.0 - opt.h
    Add av_opt_flag_is_set().
  
 -2011-06-08 - d9f80ea - lavu 51.5.0 - AVMetadata
 +2011-06-10 - c381960 - lavfi 2.15.0 - avfilter_get_audio_buffer_ref_from_arrays
 +  Add avfilter_get_audio_buffer_ref_from_arrays() to avfilter.h.
 +
 +2011-06-09 - f9ecb84 / d9f80ea - lavu 51.8.0 - AVMetadata
    Move AVMetadata from lavf to lavu and rename it to
    AVDictionary -- new installed header dict.h.
    All av_metadata_* functions renamed to av_dict_*.
  
 -2011-06-07 - a6703fa - lavu 51.4.0 - av_get_bytes_per_sample()
 +2011-06-07 - d552f61 / a6703fa - lavu 51.8.0 - av_get_bytes_per_sample()
    Add av_get_bytes_per_sample() in libavutil/samplefmt.h.
    Deprecate av_get_bits_per_sample_fmt().
  
 -2011-06-05 - b39b062 - lavu 51.3.0 - opt.h
 +2011-06-05 - f956924 / b39b062 - lavu 51.8.0 - opt.h
    Add av_opt_free convenience function.
  
 -2011-05-28 - 0420bd7 - lavu 51.2.0 - pixdesc.h
 +2011-06-06 - 95a0242 - lavfi 2.14.0 - AVFilterBufferRefAudioProps
 +  Remove AVFilterBufferRefAudioProps.size, and use nb_samples in
 +  avfilter_get_audio_buffer() and avfilter_default_get_audio_buffer() in
 +  place of size.
 +
 +2011-06-06 - 0bc2cca - lavu 51.6.0 - av_samples_alloc()
 +  Switch nb_channels and nb_samples parameters order in
 +  av_samples_alloc().
 +
 +2011-06-06 - e1c7414 - lavu 51.5.0 - av_samples_*
 +  Change the data layout created by av_samples_fill_arrays() and
 +  av_samples_alloc().
 +
 +2011-06-06 - 27bcf55 - lavfi 2.13.0 - vsrc_buffer.h
 +  Make av_vsrc_buffer_add_video_buffer_ref() accepts an additional
 +  flags parameter in input.
 +
 +2011-06-03 - e977ca2 - lavfi 2.12.0 - avfilter_link_free()
 +  Add avfilter_link_free() function.
 +
 +2011-06-02 - 5ad38d9 - lavu 51.4.0 - av_force_cpu_flags()
 +  Add av_cpu_flags() in libavutil/cpu.h.
 +
 +2011-05-28 - e71f260 - lavu 51.3.0 - pixdesc.h
    Add av_get_pix_fmt_name() in libavutil/pixdesc.h, and deprecate
    avcodec_get_pix_fmt_name() in libavcodec/avcodec.h in its favor.
  
 -2011-05-25 - 30315a8 - lavf 53.1.0 - avformat.h
 +2011-05-25 - 39e4206 / 30315a8 - lavf 53.3.0 - avformat.h
    Add fps_probe_size to AVFormatContext.
  
 -2011-05-18 - 64150ff - lavc 53.4.0 - AVCodecContext.request_sample_fmt
 +2011-05-22 - 5ecdfd0 - lavf 53.2.0 - avformat.h
 +  Introduce avformat_alloc_output_context2() and deprecate
 +  avformat_alloc_output_context().
 +
 +2011-05-22 - 83db719 - lavfi 2.10.0 - vsrc_buffer.h
 +  Make libavfilter/vsrc_buffer.h public.
 +
 +2011-05-19 - c000a9f - lavfi 2.8.0 - avcodec.h
 +  Add av_vsrc_buffer_add_frame() to libavfilter/avcodec.h.
 +
 +2011-05-14 - 9fdf772 - lavfi 2.6.0 - avcodec.h
 +  Add avfilter_get_video_buffer_ref_from_frame() to libavfilter/avcodec.h.
 +
 +2011-05-18 - 75a37b5 / 64150ff - lavc 53.7.0 - AVCodecContext.request_sample_fmt
    Add request_sample_fmt field to AVCodecContext.
  
 -2011-05-10 - 188dea1 - lavc 53.3.0 - avcodec.h
 +2011-05-10 - 59eb12f / 188dea1 - lavc 53.6.0 - avcodec.h
    Deprecate AVLPCType and the following fields in
    AVCodecContext: lpc_coeff_precision, prediction_order_method,
    min_partition_order, max_partition_order, lpc_type, lpc_passes.
    Corresponding FLAC encoder options should be used instead.
  
 -2011-04-26 - bebe72f - lavu 51.1.0 - avutil.h
 +2011-05-07 - 9fdf772 - lavfi 2.5.0 - avcodec.h
 +  Add libavfilter/avcodec.h header and avfilter_copy_frame_props()
 +  function.
 +
 +2011-05-07 - 18ded93 - lavc 53.5.0 - AVFrame
 +  Add format field to AVFrame.
 +
 +2011-05-07 - 22333a6 - lavc 53.4.0 - AVFrame
 +  Add width and height fields to AVFrame.
 +
 +2011-05-01 - 35fe66a - lavfi 2.4.0 - avfilter.h
 +  Rename AVFilterBufferRefVideoProps.pixel_aspect to
 +  sample_aspect_ratio.
 +
 +2011-05-01 - 77e9dee - lavc 53.3.0 - AVFrame
 +  Add a sample_aspect_ratio field to AVFrame.
 +
 +2011-05-01 - 1ba5727 - lavc 53.2.0 - AVFrame
 +  Add a pkt_pos field to AVFrame.
 +
 +2011-04-29 - 35ceaa7 - lavu 51.2.0 - mem.h
 +  Add av_dynarray_add function for adding
 +  an element to a dynamic array.
 +
 +2011-04-26 - d7e5aeb / bebe72f - lavu 51.1.0 - avutil.h
    Add AVPictureType enum and av_get_picture_type_char(), deprecate
    FF_*_TYPE defines and av_get_pict_type_char() defined in
    libavcodec/avcodec.h.
  
 -2011-04-26 - 10d3940 - lavfi 2.3.0 - avfilter.h
 +2011-04-26 - d7e5aeb / 10d3940 - lavfi 2.3.0 - avfilter.h
    Add pict_type and key_frame fields to AVFilterBufferRefVideo.
  
 -2011-04-26 - 7a11c82 - lavfi 2.2.0 - vsrc_buffer
 +2011-04-26 - d7e5aeb / 7a11c82 - lavfi 2.2.0 - vsrc_buffer
    Add sample_aspect_ratio fields to vsrc_buffer arguments
  
 -2011-04-21 - 94f7451 - lavc 53.1.0 - avcodec.h
 +2011-04-21 - 8772156 / 94f7451 - lavc 53.1.0 - avcodec.h
    Add CODEC_CAP_SLICE_THREADS for codecs supporting sliced threading.
  
  2011-04-15 - lavc 52.120.0 - avcodec.h
    AVPacket structure got additional members for passing side information:
 -    4de339e introduce side information for AVPacket
 -    2d8591c make containers pass palette change in AVPacket
 +    c407984 / 4de339e introduce side information for AVPacket
 +    c407984 / 2d8591c make containers pass palette change in AVPacket
  
  2011-04-12 - lavf 52.107.0 - avio.h
    Avio cleanup, part II - deprecate the entire URLContext API:
 -    175389c add avio_check as a replacement for url_exist
 -    ff1ec0c add avio_pause and avio_seek_time as replacements
 +    c55780d / 175389c add avio_check as a replacement for url_exist
 +    9891004 / ff1ec0c add avio_pause and avio_seek_time as replacements
              for _av_url_read_fseek/fpause
 -    cdc6a87 deprecate av_protocol_next(), avio_enum_protocols
 +    d4d0932 / cdc6a87 deprecate av_protocol_next(), avio_enum_protocols
              should be used instead.
 -    80c6e23 rename url_set_interrupt_cb->avio_set_interrupt_cb.
 -    f87b1b3 rename open flags: URL_* -> AVIO_*
 -    f8270bb add avio_enum_protocols.
 -    5593f03 deprecate URLProtocol.
 -    c486dad deprecate URLContext.
 -    026e175 deprecate the typedef for URLInterruptCB
 -    8e76a19 deprecate av_register_protocol2.
 -    b840484 deprecate URL_PROTOCOL_FLAG_NESTED_SCHEME
 -    1305d93 deprecate av_url_read_seek
 -    fa104e1 deprecate av_url_read_pause
 -    727c7aa deprecate url_get_filename().
 -    5958df3 deprecate url_max_packet_size().
 -    1869ea0 deprecate url_get_file_handle().
 -    32a97d4 deprecate url_filesize().
 -    e52a914 deprecate url_close().
 -    58a48c6 deprecate url_seek().
 -    925e908 deprecate url_write().
 -    dce3756 deprecate url_read_complete().
 -    bc371ac deprecate url_read().
 -    0589da0 deprecate url_open().
 -    62eaaea deprecate url_connect.
 -    5652bb9 deprecate url_alloc.
 -    333e894 deprecate url_open_protocol
 -    e230705 deprecate url_poll and URLPollEntry
 -
 -2011-04-10 - lavu  50.40.0 - pixfmt.h
 -  Add PIX_FMT_BGR48LE and PIX_FMT_BGR48BE pixel formats
 +    c88caa5 / 80c6e23 rename url_set_interrupt_cb->avio_set_interrupt_cb.
 +    c88caa5 / f87b1b3 rename open flags: URL_* -> AVIO_*
 +    d4d0932 / f8270bb add avio_enum_protocols.
 +    d4d0932 / 5593f03 deprecate URLProtocol.
 +    d4d0932 / c486dad deprecate URLContext.
 +    d4d0932 / 026e175 deprecate the typedef for URLInterruptCB
 +    c88caa5 / 8e76a19 deprecate av_register_protocol2.
 +    11d7841 / b840484 deprecate URL_PROTOCOL_FLAG_NESTED_SCHEME
 +    11d7841 / 1305d93 deprecate av_url_read_seek
 +    11d7841 / fa104e1 deprecate av_url_read_pause
 +    434f248 / 727c7aa deprecate url_get_filename().
 +    434f248 / 5958df3 deprecate url_max_packet_size().
 +    434f248 / 1869ea0 deprecate url_get_file_handle().
 +    434f248 / 32a97d4 deprecate url_filesize().
 +    434f248 / e52a914 deprecate url_close().
 +    434f248 / 58a48c6 deprecate url_seek().
 +    434f248 / 925e908 deprecate url_write().
 +    434f248 / dce3756 deprecate url_read_complete().
 +    434f248 / bc371ac deprecate url_read().
 +    434f248 / 0589da0 deprecate url_open().
 +    434f248 / 62eaaea deprecate url_connect.
 +    434f248 / 5652bb9 deprecate url_alloc.
 +    434f248 / 333e894 deprecate url_open_protocol
 +    434f248 / e230705 deprecate url_poll and URLPollEntry
  
  2011-04-08 - lavf 52.106.0 - avformat.h
    Minor avformat.h cleanup:
 -    a9bf9d8 deprecate av_guess_image2_codec
 -    c3675df rename avf_sdp_create->av_sdp_create
 +    d4d0932 / a9bf9d8 deprecate av_guess_image2_codec
 +    d4d0932 / c3675df rename avf_sdp_create->av_sdp_create
  
  2011-04-03 - lavf 52.105.0 - avio.h
    Large-scale renaming/deprecating of AVIOContext-related functions:
 -    724f6a0 deprecate url_fdopen
 -    403ee83 deprecate url_open_dyn_packet_buf
 -    6dc7d80 rename url_close_dyn_buf       -> avio_close_dyn_buf
 -    b92c545 rename url_open_dyn_buf        -> avio_open_dyn_buf
 -    8978fed introduce an AVIOContext.seekable field as a replacement for
 +    2cae980 / 724f6a0 deprecate url_fdopen
 +    2cae980 / 403ee83 deprecate url_open_dyn_packet_buf
 +    2cae980 / 6dc7d80 rename url_close_dyn_buf       -> avio_close_dyn_buf
 +    2cae980 / b92c545 rename url_open_dyn_buf        -> avio_open_dyn_buf
 +    2cae980 / 8978fed introduce an AVIOContext.seekable field as a replacement for
              AVIOContext.is_streamed and url_is_streamed()
 -    b64030f deprecate get_checksum()
 -    4c4427a deprecate init_checksum()
 -    4ec153b deprecate udp_set_remote_url/get_local_port
 -    933e90a deprecate av_url_read_fseek/fpause
 -    8d9769a deprecate url_fileno
 -    b7f2fdd rename put_flush_packet -> avio_flush
 -    35f1023 deprecate url_close_buf
 -    83fddae deprecate url_open_buf
 -    d9d86e0 rename url_fprintf -> avio_printf
 -    59f65d9 deprecate url_setbufsize
 -    3e68b3b deprecate url_ferror
 -    66e5b1d deprecate url_feof
 +    1caa412 / b64030f deprecate get_checksum()
 +    1caa412 / 4c4427a deprecate init_checksum()
 +    2fd41c9 / 4ec153b deprecate udp_set_remote_url/get_local_port
 +    4fa0e24 / 933e90a deprecate av_url_read_fseek/fpause
 +    4fa0e24 / 8d9769a deprecate url_fileno
 +    0fecf26 / b7f2fdd rename put_flush_packet -> avio_flush
 +    0fecf26 / 35f1023 deprecate url_close_buf
 +    0fecf26 / 83fddae deprecate url_open_buf
 +    0fecf26 / d9d86e0 rename url_fprintf -> avio_printf
 +    0fecf26 / 59f65d9 deprecate url_setbufsize
 +    6947b0c / 3e68b3b deprecate url_ferror
      e8bb2e2 deprecate url_fget_max_packet_size
      76aa876 rename url_fsize -> avio_size
      e519753 deprecate url_fgetc
      b3db9ce deprecate get_partial_buffer
      8d9ac96 rename av_alloc_put_byte -> avio_alloc_context
  
 -2011-03-25 - 34b47d7 - lavc 52.115.0 - AVCodecContext.audio_service_type
 +2011-03-25 - 27ef7b1 / 34b47d7 - lavc 52.115.0 - AVCodecContext.audio_service_type
    Add audio_service_type field to AVCodecContext.
  
 +2011-03-17 - e309fdc - lavu 50.40.0 - pixfmt.h
 +  Add PIX_FMT_BGR48LE and PIX_FMT_BGR48BE pixel formats
 +
  2011-03-02 - 863c471 - lavf  52.103.0 - av_pkt_dump2, av_pkt_dump_log2
    Add new functions av_pkt_dump2, av_pkt_dump_log2 that uses the
    source stream timebase for outputting timestamps. Deprecate
  2011-02-10 - 12c14cd - lavf 52.99.0 - AVStream.disposition
    Add AV_DISPOSITION_HEARING_IMPAIRED and AV_DISPOSITION_VISUAL_IMPAIRED.
  
 -2011-02-09 - 5592734 - lavc 52.112.0 - avcodec_thread_init()
 +2011-02-09 - c0b102c - lavc 52.112.0 - avcodec_thread_init()
    Deprecate avcodec_thread_init()/avcodec_thread_free() use; instead
    set thread_count before calling avcodec_open.
  
 -2011-02-09 - 778b08a - lavc 52.111.0 - threading API
 +2011-02-09 - 37b00b4 - lavc 52.111.0 - threading API
    Add CODEC_CAP_FRAME_THREADS with new restrictions on get_buffer()/
    release_buffer()/draw_horiz_band() callbacks for appropriate codecs.
    Add thread_type and active_thread_type fields to AVCodecContext.
  2011-02-02 - dfd2a00 - lavu 50.37.0 - log.h
    Make av_dlog public.
  
 +2011-01-31 - 7b3ea55 - lavfi 1.76.0 - vsrc_buffer
 +  Add sample_aspect_ratio fields to vsrc_buffer arguments
 +
 +2011-01-31 - 910b5b8 - lavfi 1.75.0 - AVFilterLink sample_aspect_ratio
 +  Add sample_aspect_ratio field to AVFilterLink.
 +
  2011-01-15 - a242ac3 - lavfi 1.74.0 - AVFilterBufferRefAudioProps
    Rename AVFilterBufferRefAudioProps.samples_nb to nb_samples.
  
  2010-06-02 - 7e566bb - lavc 52.73.0 - av_get_codec_tag_string()
    Add av_get_codec_tag_string().
  
 +
 +-------- 8< --------- FFmpeg 0.6 was cut here -------- 8< ---------
 +
  2010-06-01 - 2b99142 - lsws 0.11.0 - convertPalette API
    Add sws_convertPalette8ToPacked32() and sws_convertPalette8ToPacked24().
  
  2010-05-09 - b6bc205 - lavfi 1.20.0 - AVFilterPicRef
    Add interlaced and top_field_first fields to AVFilterPicRef.
  
 -------------------------------8<-------------------------------------
 -                   0.6 branch was cut here
 ------------------------------>8--------------------------------------
 -
  2010-05-01 - 8e2ee18 - lavf 52.62.0 - probe function
    Add av_probe_input_format2 to API, it allows ignoring probe
    results below given score and returns the actual probe score.
diff --combined libavformat/avformat.h
@@@ -1,20 -1,20 +1,20 @@@
  /*
   * copyright (c) 2001 Fabrice Bellard
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -50,7 -50,7 +50,7 @@@
   *
   * Main lavf structure used for both muxing and demuxing is AVFormatContext,
   * which exports all information about the file being read or written. As with
 - * most Libav structures, its size is not part of public ABI, so it cannot be
 + * most Libavformat structures, its size is not part of public ABI, so it cannot be
   * allocated on stack or directly with av_malloc(). To create an
   * AVFormatContext, use avformat_alloc_context() (some functions, like
   * avformat_open_input() might do that for you).
@@@ -67,7 -67,7 +67,7 @@@
   * with an AVFMT_NOFILE format).
   *
   * @section lavf_options Passing options to (de)muxers
 - * Lavf allows to configure muxers and demuxers using the @ref avoptions
 + * It is possible to configure lavf muxers and demuxers using the @ref avoptions
   * mechanism. Generic (format-independent) libavformat options are provided by
   * AVFormatContext, they can be examined from a user program by calling
   * av_opt_next() / av_opt_find() on an allocated AVFormatContext (or its AVClass
   * if its AVClass is non-NULL, and the protocols layer. See the discussion on
   * nesting in @ref avoptions documentation to learn how to access those.
   *
 + * @section urls
 + * URL strings in libavformat are made of a scheme/protocol, a ':', and a
 + * scheme specific string. URLs without a scheme and ':' used for local files
 + * are supported but deprecated. "file:" should be used for local files.
 + *
 + * It is important that the scheme string is not taken from untrusted
 + * sources without checks.
 + *
 + * Note that some schemes/protocols are quite powerful, allowing access to
 + * both local and remote files, parts of them, concatenations of them, local
 + * audio and video devices and so on.
 + *
   * @defgroup lavf_decoding Demuxing
   * @{
   * Demuxers read a media file and split it into chunks of data (@em packets). A
   * cleanup.
   *
   * @section lavf_decoding_open Opening a media file
 - * The minimum information required to open a file is its URL or filename, which
 + * The minimum information required to open a file is its URL, which
   * is passed to avformat_open_input(), as in the following code:
   * @code
 - * const char    *url = "in.mp3";
 + * const char    *url = "file:in.mp3";
   * AVFormatContext *s = NULL;
   * int ret = avformat_open_input(&s, url, NULL, NULL);
   * if (ret < 0)
   *
   * @defgroup lavf_io I/O Read/Write
   * @{
 + * @section lavf_io_dirlist Directory listing
 + * The directory listing API makes it possible to list files on remote servers.
 + *
 + * Some of possible use cases:
 + * - an "open file" dialog to choose files from a remote location,
 + * - a recursive media finder providing a player with an ability to play all
 + * files from a given directory.
 + *
 + * @subsection lavf_io_dirlist_open Opening a directory
 + * At first, a directory needs to be opened by calling avio_open_dir()
 + * supplied with a URL and, optionally, ::AVDictionary containing
 + * protocol-specific parameters. The function returns zero or positive
 + * integer and allocates AVIODirContext on success.
 + *
 + * @code
 + * AVIODirContext *ctx = NULL;
 + * if (avio_open_dir(&ctx, "smb://example.com/some_dir", NULL) < 0) {
 + *     fprintf(stderr, "Cannot open directory.\n");
 + *     abort();
 + * }
 + * @endcode
 + *
 + * This code tries to open a sample directory using smb protocol without
 + * any additional parameters.
 + *
 + * @subsection lavf_io_dirlist_read Reading entries
 + * Each directory's entry (i.e. file, another directory, anything else
 + * within ::AVIODirEntryType) is represented by AVIODirEntry.
 + * Reading consecutive entries from an opened AVIODirContext is done by
 + * repeatedly calling avio_read_dir() on it. Each call returns zero or
 + * positive integer if successful. Reading can be stopped right after the
 + * NULL entry has been read -- it means there are no entries left to be
 + * read. The following code reads all entries from a directory associated
 + * with ctx and prints their names to standard output.
 + * @code
 + * AVIODirEntry *entry = NULL;
 + * for (;;) {
 + *     if (avio_read_dir(ctx, &entry) < 0) {
 + *         fprintf(stderr, "Cannot list directory.\n");
 + *         abort();
 + *     }
 + *     if (!entry)
 + *         break;
 + *     printf("%s\n", entry->name);
 + *     avio_free_directory_entry(&entry);
 + * }
 + * @endcode
   * @}
   *
   * @defgroup lavf_codec Demuxers
  
  struct AVFormatContext;
  
 +struct AVDeviceInfoList;
 +struct AVDeviceCapabilitiesQuery;
  
  /**
   * @defgroup metadata_api Public Metadata API
   *
   * Metadata is exported or set as pairs of key/value strings in the 'metadata'
   * fields of the AVFormatContext, AVStream, AVChapter and AVProgram structs
 - * using the @ref lavu_dict "AVDictionary" API. Like all strings in Libav,
 + * using the @ref lavu_dict "AVDictionary" API. Like all strings in FFmpeg,
   * metadata is assumed to be UTF-8 encoded Unicode. Note that metadata
   * exported by demuxers isn't checked to be valid UTF-8 in most cases.
   *
@@@ -464,9 -403,6 +464,9 @@@ typedef struct AVProbeData 
      const char *mime_type; /**< mime_type, when known. */
  } AVProbeData;
  
 +#define AVPROBE_SCORE_RETRY (AVPROBE_SCORE_MAX/4)
 +#define AVPROBE_SCORE_STREAM_RETRY (AVPROBE_SCORE_MAX/4-1)
 +
  #define AVPROBE_SCORE_EXTENSION  50 ///< score for file extension
  #define AVPROBE_SCORE_MIME       75 ///< score for file mime type
  #define AVPROBE_SCORE_MAX       100 ///< maximum score
                                          timestamps. If not set the timestamp
                                          will be shifted in av_write_frame and
                                          av_interleaved_write_frame so they
 -                                        start from 0. */
 +                                        start from 0.
 +                                        The user or muxer can override this through
 +                                        AVFormatContext.avoid_negative_ts
 +                                        */
 +
 +#define AVFMT_SEEK_TO_PTS   0x4000000 /**< Seeking is based on PTS */
  
  /**
   * @addtogroup lavf_encoding
@@@ -574,67 -505,8 +574,67 @@@ typedef struct AVOutputFormat 
       *
       * @return 1 if the codec is supported, 0 if it is not.
       *         A negative number if unknown.
 +     *         MKTAG('A', 'P', 'I', 'C') if the codec is only supported as AV_DISPOSITION_ATTACHED_PIC
       */
      int (*query_codec)(enum AVCodecID id, int std_compliance);
 +
 +    void (*get_output_timestamp)(struct AVFormatContext *s, int stream,
 +                                 int64_t *dts, int64_t *wall);
 +    /**
 +     * Allows sending messages from application to device.
 +     */
 +    int (*control_message)(struct AVFormatContext *s, int type,
 +                           void *data, size_t data_size);
 +
 +    /**
 +     * Write an uncoded AVFrame.
 +     *
 +     * See av_write_uncoded_frame() for details.
 +     *
 +     * The library will free *frame afterwards, but the muxer can prevent it
 +     * by setting the pointer to NULL.
 +     */
 +    int (*write_uncoded_frame)(struct AVFormatContext *, int stream_index,
 +                               AVFrame **frame, unsigned flags);
 +    /**
 +     * Returns device list with it properties.
 +     * @see avdevice_list_devices() for more details.
 +     */
 +    int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list);
 +    /**
 +     * Initialize device capabilities submodule.
 +     * @see avdevice_capabilities_create() for more details.
 +     */
 +    int (*create_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
 +    /**
 +     * Free device capabilities submodule.
 +     * @see avdevice_capabilities_free() for more details.
 +     */
 +    int (*free_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
 +    enum AVCodecID data_codec; /**< default data codec */
 +    /**
 +     * Initialize format. May allocate data here, and set any AVFormatContext or
 +     * AVStream parameters that need to be set before packets are sent.
 +     * This method must not write output.
 +     *
 +     * Any allocations made here must be freed in deinit().
 +     */
 +    int (*init)(struct AVFormatContext *);
 +    /**
 +     * Deinitialize format. If present, this is called whenever the muxer is being
 +     * destroyed, regardless of whether or not the header has been written.
 +     *
 +     * If a trailer is being written, this is called after write_trailer().
 +     *
 +     * This is called if init() fails as well.
 +     */
 +    void (*deinit)(struct AVFormatContext *);
 +    /**
 +     * Set up any necessary bitstream filtering and extract any extra data needed
 +     * for the global header.
 +     * Return 0 if more packets from this stream must be checked; 1 if not.
 +     */
 +    int (*check_bitstream)(struct AVFormatContext *, const AVPacket *pkt);
  } AVOutputFormat;
  /**
   * @}
@@@ -661,7 -533,7 +661,7 @@@ typedef struct AVInputFormat 
      /**
       * Can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_SHOW_IDS,
       * AVFMT_GENERIC_INDEX, AVFMT_TS_DISCONT, AVFMT_NOBINSEARCH,
 -     * AVFMT_NOGENSEARCH, AVFMT_NO_BYTE_SEEK.
 +     * AVFMT_NOGENSEARCH, AVFMT_NO_BYTE_SEEK, AVFMT_SEEK_TO_PTS.
       */
      int flags;
  
       * Active streams are all streams that have AVStream.discard < AVDISCARD_ALL.
       */
      int (*read_seek2)(struct AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags);
 +
 +    /**
 +     * Returns device list with it properties.
 +     * @see avdevice_list_devices() for more details.
 +     */
 +    int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list);
 +
 +    /**
 +     * Initialize device capabilities submodule.
 +     * @see avdevice_capabilities_create() for more details.
 +     */
 +    int (*create_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
 +
 +    /**
 +     * Free device capabilities submodule.
 +     * @see avdevice_capabilities_free() for more details.
 +     */
 +    int (*free_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
  } AVInputFormat;
  /**
   * @}
@@@ -799,19 -653,11 +799,19 @@@ enum AVStreamParseType 
      AVSTREAM_PARSE_HEADERS,    /**< Only parse headers, do not repack. */
      AVSTREAM_PARSE_TIMESTAMPS, /**< full parsing and interpolation of timestamps for frames not starting on a packet boundary */
      AVSTREAM_PARSE_FULL_ONCE,  /**< full parsing and repack of the first frame only, only implemented for H.264 currently */
 +    AVSTREAM_PARSE_FULL_RAW=MKTAG(0,'R','A','W'),       /**< full parsing and repack with timestamp and position generation by parser for raw
 +                                                             this assumes that each packet in the file contains no demuxer level headers and
 +                                                             just codec level data, otherwise position generation would fail */
  };
  
  typedef struct AVIndexEntry {
      int64_t pos;
 -    int64_t timestamp;
 +    int64_t timestamp;        /**<
 +                               * Timestamp in AVStream.time_base units, preferably the time from which on correctly decoded frames are available
 +                               * when seeking to this entry. That means preferable PTS on keyframe based formats.
 +                               * But demuxers can choose to store a different timestamp, if it is more convenient for the implementation or nothing better
 +                               * is known
 +                               */
  #define AVINDEX_KEYFRAME 0x0001
      int flags:2;
      int size:30; //Yeah, trying to keep the size of this small to reduce memory requirements (it is 24 vs. 32 bytes due to possible 8-byte alignment).
  typedef struct AVStreamInternal AVStreamInternal;
  
  /**
 + * To specify text track kind (different from subtitles default).
 + */
 +#define AV_DISPOSITION_CAPTIONS     0x10000
 +#define AV_DISPOSITION_DESCRIPTIONS 0x20000
 +#define AV_DISPOSITION_METADATA     0x40000
 +
 +/**
 + * Options for behavior on timestamp wrap detection.
 + */
 +#define AV_PTS_WRAP_IGNORE      0   ///< ignore the wrap
 +#define AV_PTS_WRAP_ADD_OFFSET  1   ///< add the format specific offset on wrap detection
 +#define AV_PTS_WRAP_SUB_OFFSET  -1  ///< subtract the format specific offset on wrap detection
 +
 +/**
   * Stream structure.
   * New fields can be added to the end with minor version bumps.
   * Removal, reordering and changes to existing fields require a major
@@@ -910,12 -742,10 +910,12 @@@ typedef struct AVStream 
      AVRational time_base;
  
      /**
 -     * Decoding: pts of the first frame of the stream, in stream time base.
 +     * Decoding: pts of the first frame of the stream in presentation order, in stream time base.
       * Only set this if you are absolutely 100% sure that the value you set
       * it to really is the pts of the first frame.
       * This may be undefined (AV_NOPTS_VALUE).
 +     * @note The ASF header does NOT contain a correct start_time the ASF
 +     * demuxer must NOT set this.
       */
      int64_t start_time;
  
       * - muxing: May be set by the caller before avformat_write_header().
       *
       * Freed by libavformat in avformat_free_context().
 +     *
 +     * @see av_format_inject_global_side_data()
       */
      AVPacketSideData *side_data;
      /**
      /**
       * Stream information used internally by av_find_stream_info()
       */
 -#define MAX_STD_TIMEBASES (60*12+5)
 +#define MAX_STD_TIMEBASES (30*12+30+3+6)
      struct {
 -        int nb_decoded_frames;
 +        int64_t last_dts;
 +        int64_t duration_gcd;
 +        int duration_count;
 +        int64_t rfps_duration_sum;
 +        double (*duration_error)[2][MAX_STD_TIMEBASES];
 +        int64_t codec_info_duration;
 +        int64_t codec_info_duration_fields;
 +
 +        /**
 +         * 0  -> decoder has not been searched for yet.
 +         * >0 -> decoder found
 +         * <0 -> decoder with codec_id == -found_decoder has not been found
 +         */
          int found_decoder;
  
 +        int64_t last_duration;
 +
          /**
           * Those are used for average framerate estimation.
           */
      int pts_wrap_bits; /**< number of bits in pts (used for wrapping control) */
  
      // Timestamp generation support:
 +    /**
 +     * Timestamp corresponding to the last dts sync point.
 +     *
 +     * Initialized when AVCodecParserContext.dts_sync_point >= 0 and
 +     * a DTS is received from the underlying container. Otherwise set to
 +     * AV_NOPTS_VALUE by default.
 +     */
      int64_t first_dts;
      int64_t cur_dts;
      int64_t last_IP_pts;
      /**
       * Number of packets to buffer for codec probing
       */
 -#define MAX_PROBE_PACKETS 2500
      int probe_packets;
  
      /**
      unsigned int index_entries_allocated_size;
  
      /**
 +     * Real base framerate of the stream.
 +     * This is the lowest framerate with which all timestamps can be
 +     * represented accurately (it is the least common multiple of all
 +     * framerates in the stream). Note, this value is just a guess!
 +     * For example, if the time base is 1/90000 and all frames have either
 +     * approximately 3600 or 1800 timer ticks, then r_frame_rate will be 50/1.
 +     *
 +     * Code outside avformat should access this field using:
 +     * av_stream_get/set_r_frame_rate(stream)
 +     */
 +    AVRational r_frame_rate;
 +
 +    /**
 +     * Stream Identifier
 +     * This is the MPEG-TS stream identifier +1
 +     * 0 means unknown
 +     */
 +    int stream_identifier;
 +
 +    int64_t interleaver_chunk_size;
 +    int64_t interleaver_chunk_duration;
 +
 +    /**
 +     * stream probing state
 +     * -1   -> probing finished
 +     *  0   -> no probing requested
 +     * rest -> perform probing with request_probe being the minimum score to accept.
 +     * NOT PART OF PUBLIC API
 +     */
 +    int request_probe;
 +    /**
 +     * Indicates that everything up to the next keyframe
 +     * should be discarded.
 +     */
 +    int skip_to_keyframe;
 +
 +    /**
 +     * Number of samples to skip at the start of the frame decoded from the next packet.
 +     */
 +    int skip_samples;
 +
 +    /**
 +     * If not 0, the number of samples that should be skipped from the start of
 +     * the stream (the samples are removed from packets with pts==0, which also
 +     * assumes negative timestamps do not happen).
 +     * Intended for use with formats such as mp3 with ad-hoc gapless audio
 +     * support.
 +     */
 +    int64_t start_skip_samples;
 +
 +    /**
 +     * If not 0, the first audio sample that should be discarded from the stream.
 +     * This is broken by design (needs global sample count), but can't be
 +     * avoided for broken by design formats such as mp3 with ad-hoc gapless
 +     * audio support.
 +     */
 +    int64_t first_discard_sample;
 +
 +    /**
 +     * The sample after last sample that is intended to be discarded after
 +     * first_discard_sample. Works on frame boundaries only. Used to prevent
 +     * early EOF if the gapless info is broken (considered concatenated mp3s).
 +     */
 +    int64_t last_discard_sample;
 +
 +    /**
 +     * Number of internally decoded frames, used internally in libavformat, do not access
 +     * its lifetime differs from info which is why it is not in that structure.
 +     */
 +    int nb_decoded_frames;
 +
 +    /**
 +     * Timestamp offset added to timestamps before muxing
 +     * NOT PART OF PUBLIC API
 +     */
 +    int64_t mux_ts_offset;
 +
 +    /**
 +     * Internal data to check for wrapping of the time stamp
 +     */
 +    int64_t pts_wrap_reference;
 +
 +    /**
 +     * Options for behavior, when a wrap is detected.
 +     *
 +     * Defined by AV_PTS_WRAP_ values.
 +     *
 +     * If correction is enabled, there are two possibilities:
 +     * If the first time stamp is near the wrap point, the wrap offset
 +     * will be subtracted, which will create negative time stamps.
 +     * Otherwise the offset will be added.
 +     */
 +    int pts_wrap_behavior;
 +
 +    /**
 +     * Internal data to prevent doing update_initial_durations() twice
 +     */
 +    int update_initial_durations_done;
 +
 +    /**
 +     * Internal data to generate dts from pts
 +     */
 +    int64_t pts_reorder_error[MAX_REORDER_DELAY+1];
 +    uint8_t pts_reorder_error_count[MAX_REORDER_DELAY+1];
 +
 +    /**
 +     * Internal data to analyze DTS and detect faulty mpeg streams
 +     */
 +    int64_t last_dts_for_order_check;
 +    uint8_t dts_ordered;
 +    uint8_t dts_misordered;
 +
 +    /**
 +     * Internal data to inject global side data
 +     */
 +    int inject_global_side_data;
 +
 +    /**
 +     * String containing paris of key and values describing recommended encoder configuration.
 +     * Paris are separated by ','.
 +     * Keys are separated from values by '='.
 +     */
 +    char *recommended_encoder_configuration;
 +
 +    /**
 +     * display aspect ratio (0 if unknown)
 +     * - encoding: unused
 +     * - decoding: Set by libavformat to calculate sample_aspect_ratio internally
 +     */
 +    AVRational display_aspect_ratio;
 +
 +    struct FFFrac *priv_pts;
 +
 +    /**
       * An opaque field for libavformat internal usage.
       * Must not be accessed in any way by callers.
       */
      AVStreamInternal *internal;
  } AVStream;
  
 +AVRational av_stream_get_r_frame_rate(const AVStream *s);
 +void       av_stream_set_r_frame_rate(AVStream *s, AVRational r);
 +struct AVCodecParserContext *av_stream_get_parser(const AVStream *s);
 +char* av_stream_get_recommended_encoder_configuration(const AVStream *s);
 +void  av_stream_set_recommended_encoder_configuration(AVStream *s, char *configuration);
 +
 +/**
 + * Returns the pts of the last muxed packet + its duration
 + *
 + * the retuned value is undefined when used with a demuxer.
 + */
 +int64_t    av_stream_get_end_pts(const AVStream *st);
 +
  #define AV_PROGRAM_RUNNING 1
  
  /**
@@@ -1242,23 -903,6 +1242,23 @@@ typedef struct AVProgram 
      unsigned int   *stream_index;
      unsigned int   nb_stream_indexes;
      AVDictionary *metadata;
 +
 +    int program_num;
 +    int pmt_pid;
 +    int pcr_pid;
 +
 +    /*****************************************************************
 +     * All fields below this line are not part of the public API. They
 +     * may not be used outside of libavformat and can be changed and
 +     * removed at will.
 +     * New public fields should be added right above.
 +     *****************************************************************
 +     */
 +    int64_t start_time;
 +    int64_t end_time;
 +
 +    int64_t pts_wrap_reference;    ///< reference dts for wrap detection
 +    int pts_wrap_behavior;         ///< behavior on wrap detection
  } AVProgram;
  
  #define AVFMTCTX_NOHEADER      0x0001 /**< signal that no header is present
@@@ -1271,26 -915,6 +1271,26 @@@ typedef struct AVChapter 
      AVDictionary *metadata;
  } AVChapter;
  
 +
 +/**
 + * Callback used by devices to communicate with application.
 + */
 +typedef int (*av_format_control_message)(struct AVFormatContext *s, int type,
 +                                         void *data, size_t data_size);
 +
 +typedef int (*AVOpenCallback)(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags,
 +                              const AVIOInterruptCB *int_cb, AVDictionary **options);
 +
 +/**
 + * The duration of a video can be estimated through various ways, and this enum can be used
 + * to know how the duration was estimated.
 + */
 +enum AVDurationEstimationMethod {
 +    AVFMT_DURATION_FROM_PTS,    ///< Duration accurately estimated from PTSes
 +    AVFMT_DURATION_FROM_STREAM, ///< Duration estimated from a stream with a known duration
 +    AVFMT_DURATION_FROM_BITRATE ///< Duration estimated from bitrate (less accurate)
 +};
 +
  typedef struct AVFormatInternal AVFormatInternal;
  
  /**
@@@ -1401,9 -1025,9 +1401,9 @@@ typedef struct AVFormatContext 
      /**
       * Total stream bitrate in bit/s, 0 if not
       * available. Never set it directly if the file_size and the
 -     * duration are known as Libav can compute it automatically.
 +     * duration are known as FFmpeg can compute it automatically.
       */
 -    int bit_rate;
 +    int64_t bit_rate;
  
      unsigned int packet_size;
      int max_delay;
   * This flag is mainly intended for testing.
   */
  #define AVFMT_FLAG_BITEXACT         0x0400
 +#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 ///< Don't merge side data but keep it separate.
 +#define AVFMT_FLAG_FAST_SEEK   0x80000 ///< Enable fast, but inaccurate seeks for some formats
  
      /**
       * Maximum size of the data read from input for determining
       * the input container format.
       * Demuxing only, set by the caller before avformat_open_input().
       */
 -    unsigned int probesize;
 +    int64_t probesize;
  
      /**
       * Maximum duration (in AV_TIME_BASE units) of the data read
       * from input in avformat_find_stream_info().
       * Demuxing only, set by the caller before avformat_find_stream_info().
 +     * Can be set to 0 to let avformat choose using a heuristic.
       */
 -    int max_analyze_duration;
 +    int64_t max_analyze_duration;
  
      const uint8_t *key;
      int keylen;
       * Start time of the stream in real world time, in microseconds
       * since the Unix epoch (00:00 1st January 1970). That is, pts=0 in the
       * stream was captured at this real world time.
 -     * Muxing only, set by the caller before avformat_write_header().
 +     * - muxing: Set by the caller before avformat_write_header(). If set to
 +     *           either 0 or AV_NOPTS_VALUE, then the current wall-time will
 +     *           be used.
 +     * - demuxing: Set by libavformat. AV_NOPTS_VALUE if unknown. Note that
 +     *             the value may become known after some number of frames
 +     *             have been received.
       */
      int64_t start_time_realtime;
  
      /**
       * Avoid negative timestamps during muxing.
       * Any value of the AVFMT_AVOID_NEG_TS_* constants.
 -     * Note, this only works when using av_interleaved_write_frame.
 +     * Note, this only works when using av_interleaved_write_frame. (interleave_packet_per_dts is in use)
       * - muxing: Set by user
       * - demuxing: unused
       */
  #define AVFMT_AVOID_NEG_TS_MAKE_ZERO         2 ///< Shift timestamps so that they start at 0
  
      /**
 +     * Transport stream id.
 +     * This will be moved into demuxer private options. Thus no API/ABI compatibility
 +     */
 +    int ts_id;
 +
 +    /**
 +     * Audio preload in microseconds.
 +     * Note, not all formats support this and unpredictable things may happen if it is used when not supported.
 +     * - encoding: Set by user via AVOptions (NO direct access)
 +     * - decoding: unused
 +     */
 +    int audio_preload;
 +
 +    /**
 +     * Max chunk time in microseconds.
 +     * Note, not all formats support this and unpredictable things may happen if it is used when not supported.
 +     * - encoding: Set by user via AVOptions (NO direct access)
 +     * - decoding: unused
 +     */
 +    int max_chunk_duration;
 +
 +    /**
 +     * Max chunk size in bytes
 +     * Note, not all formats support this and unpredictable things may happen if it is used when not supported.
 +     * - encoding: Set by user via AVOptions (NO direct access)
 +     * - decoding: unused
 +     */
 +    int max_chunk_size;
 +
 +    /**
 +     * forces the use of wallclock timestamps as pts/dts of packets
 +     * This has undefined results in the presence of B frames.
 +     * - encoding: unused
 +     * - decoding: Set by user via AVOptions (NO direct access)
 +     */
 +    int use_wallclock_as_timestamps;
 +
 +    /**
 +     * avio flags, used to force AVIO_FLAG_DIRECT.
 +     * - encoding: unused
 +     * - decoding: Set by user via AVOptions (NO direct access)
 +     */
 +    int avio_flags;
 +
 +    /**
 +     * The duration field can be estimated through various ways, and this field can be used
 +     * to know how the duration was estimated.
 +     * - encoding: unused
 +     * - decoding: Read by user via AVOptions (NO direct access)
 +     */
 +    enum AVDurationEstimationMethod duration_estimation_method;
 +
 +    /**
 +     * Skip initial bytes when opening stream
 +     * - encoding: unused
 +     * - decoding: Set by user via AVOptions (NO direct access)
 +     */
 +    int64_t skip_initial_bytes;
 +
 +    /**
 +     * Correct single timestamp overflows
 +     * - encoding: unused
 +     * - decoding: Set by user via AVOptions (NO direct access)
 +     */
 +    unsigned int correct_ts_overflow;
 +
 +    /**
 +     * Force seeking to any (also non key) frames.
 +     * - encoding: unused
 +     * - decoding: Set by user via AVOptions (NO direct access)
 +     */
 +    int seek2any;
 +
 +    /**
 +     * Flush the I/O context after each packet.
 +     * - encoding: Set by user via AVOptions (NO direct access)
 +     * - decoding: unused
 +     */
 +    int flush_packets;
 +
 +    /**
 +     * format probing score.
 +     * The maximal score is AVPROBE_SCORE_MAX, its set when the demuxer probes
 +     * the format.
 +     * - encoding: unused
 +     * - decoding: set by avformat, read by user via av_format_get_probe_score() (NO direct access)
 +     */
 +    int probe_score;
 +
 +    /**
 +     * number of bytes to read maximally to identify format.
 +     * - encoding: unused
 +     * - decoding: set by user through AVOPtions (NO direct access)
 +     */
 +    int format_probesize;
 +
 +    /**
 +     * ',' separated list of allowed decoders.
 +     * If NULL then all are allowed
 +     * - encoding: unused
 +     * - decoding: set by user through AVOptions (NO direct access)
 +     */
 +    char *codec_whitelist;
 +
 +    /**
 +     * ',' separated list of allowed demuxers.
 +     * If NULL then all are allowed
 +     * - encoding: unused
 +     * - decoding: set by user through AVOptions (NO direct access)
 +     */
 +    char *format_whitelist;
 +
 +    /**
       * An opaque field for libavformat internal usage.
       * Must not be accessed in any way by callers.
       */
      AVFormatInternal *internal;
  
      /**
 -     * Arbitrary user data set by the caller.
 +     * IO repositioned flag.
 +     * This is set by avformat when the underlaying IO context read pointer
 +     * is repositioned, for example when doing byte based seeking.
 +     * Demuxers can use the flag to detect such changes.
 +     */
 +    int io_repositioned;
 +
 +    /**
 +     * Forced video codec.
 +     * This allows forcing a specific decoder, even when there are multiple with
 +     * the same codec_id.
 +     * Demuxing: Set by user via av_format_set_video_codec (NO direct access).
 +     */
 +    AVCodec *video_codec;
 +
 +    /**
 +     * Forced audio codec.
 +     * This allows forcing a specific decoder, even when there are multiple with
 +     * the same codec_id.
 +     * Demuxing: Set by user via av_format_set_audio_codec (NO direct access).
 +     */
 +    AVCodec *audio_codec;
 +
 +    /**
 +     * Forced subtitle codec.
 +     * This allows forcing a specific decoder, even when there are multiple with
 +     * the same codec_id.
 +     * Demuxing: Set by user via av_format_set_subtitle_codec (NO direct access).
 +     */
 +    AVCodec *subtitle_codec;
 +
 +    /**
 +     * Forced data codec.
 +     * This allows forcing a specific decoder, even when there are multiple with
 +     * the same codec_id.
 +     * Demuxing: Set by user via av_format_set_data_codec (NO direct access).
 +     */
 +    AVCodec *data_codec;
 +
 +    /**
 +     * Number of bytes to be written as padding in a metadata header.
 +     * Demuxing: Unused.
 +     * Muxing: Set by user via av_format_set_metadata_header_padding.
 +     */
 +    int metadata_header_padding;
 +
 +    /**
 +     * 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;
  
      /**
 +     * Callback used by devices to communicate with application.
 +     */
 +    av_format_control_message control_message_cb;
 +
 +    /**
 +     * Output timestamp offset, in microseconds.
 +     * Muxing: set by user via AVOptions (NO direct access)
 +     */
 +    int64_t output_ts_offset;
 +
 +    /**
 +     * dump format separator.
 +     * can be ", " or "\n      " or anything else
 +     * Code outside libavformat should access this field using AVOptions
 +     * (NO direct access).
 +     * - muxing: Set by user.
 +     * - demuxing: Set by user.
 +     */
 +    uint8_t *dump_separator;
 +
 +    /**
 +     * Forced Data codec_id.
 +     * Demuxing: Set by user.
 +     */
 +    enum AVCodecID data_codec_id;
 +
++#if FF_API_OLD_OPEN_CALLBACKS
 +    /**
 +     * Called to open further IO contexts when needed for demuxing.
 +     *
 +     * This can be set by the user application to perform security checks on
 +     * the URLs before opening them.
 +     * The function should behave like avio_open2(), AVFormatContext is provided
 +     * as contextual information and to reach AVFormatContext.opaque.
 +     *
 +     * If NULL then some simple checks are used together with avio_open2().
 +     *
 +     * Must not be accessed directly from outside avformat.
 +     * @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;
  
- AVOpenCallback av_format_get_open_cb(const AVFormatContext *s);
- void      av_format_set_open_cb(AVFormatContext *s, AVOpenCallback callback);
 +int av_format_get_probe_score(const AVFormatContext *s);
 +AVCodec * av_format_get_video_codec(const AVFormatContext *s);
 +void      av_format_set_video_codec(AVFormatContext *s, AVCodec *c);
 +AVCodec * av_format_get_audio_codec(const AVFormatContext *s);
 +void      av_format_set_audio_codec(AVFormatContext *s, AVCodec *c);
 +AVCodec * av_format_get_subtitle_codec(const AVFormatContext *s);
 +void      av_format_set_subtitle_codec(AVFormatContext *s, AVCodec *c);
 +AVCodec * av_format_get_data_codec(const AVFormatContext *s);
 +void      av_format_set_data_codec(AVFormatContext *s, AVCodec *c);
 +int       av_format_get_metadata_header_padding(const AVFormatContext *s);
 +void      av_format_set_metadata_header_padding(AVFormatContext *s, int c);
 +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);
++#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
 + * of each stream as well as after any subsequent seek.
 + */
 +void av_format_inject_global_side_data(AVFormatContext *s);
 +
 +/**
 + * Returns the method used to set ctx->duration.
 + *
 + * @return AVFMT_DURATION_FROM_PTS, AVFMT_DURATION_FROM_STREAM, or AVFMT_DURATION_FROM_BITRATE.
 + */
 +enum AVDurationEstimationMethod av_fmt_ctx_get_duration_estimation_method(const AVFormatContext* ctx);
 +
  typedef struct AVPacketList {
      AVPacket pkt;
      struct AVPacketList *next;
@@@ -1904,6 -1301,7 +1938,6 @@@ const char *avformat_license(void)
   *
   * @see av_register_input_format()
   * @see av_register_output_format()
 - * @see av_register_protocol()
   */
  void av_register_all(void);
  
@@@ -1969,9 -1367,6 +2003,9 @@@ const AVClass *avformat_get_class(void)
   *
   * When muxing, should be called by the user before avformat_write_header().
   *
 + * User is required to call avcodec_close() and avformat_free_context() to
 + * clean up the allocation by avformat_new_stream().
 + *
   * @param s media file handle
   * @param c If non-NULL, the AVCodecContext corresponding to the new stream
   * will be initialized to use this codec. This is needed for e.g. codec-specific
@@@ -2010,25 -1405,6 +2044,25 @@@ AVProgram *av_new_program(AVFormatConte
  
  
  /**
 + * Allocate an AVFormatContext for an output format.
 + * avformat_free_context() can be used to free the context and
 + * everything allocated by the framework within it.
 + *
 + * @param *ctx is set to the created format context, or to NULL in
 + * case of failure
 + * @param oformat format to use for allocating the context, if NULL
 + * format_name and filename are used instead
 + * @param format_name the name of output format to use for allocating the
 + * context, if NULL filename is used instead
 + * @param filename the name of the filename to use for allocating the
 + * context, may be NULL
 + * @return >= 0 in case of success, a negative AVERROR code in case of
 + * failure
 + */
 +int avformat_alloc_output_context2(AVFormatContext **ctx, AVOutputFormat *oformat,
 +                                   const char *format_name, const char *filename);
 +
 +/**
   * @addtogroup lavf_decoding
   * @{
   */
@@@ -2062,15 -1438,6 +2096,15 @@@ AVInputFormat *av_probe_input_format(AV
  AVInputFormat *av_probe_input_format2(AVProbeData *pd, int is_opened, int *score_max);
  
  /**
 + * Guess the file format.
 + *
 + * @param is_opened Whether the file is already opened; determines whether
 + *                  demuxers with or without AVFMT_NOFILE are probed.
 + * @param score_ret The score of the best detection.
 + */
 +AVInputFormat *av_probe_input_format3(AVProbeData *pd, int is_opened, int *score_ret);
 +
 +/**
   * Probe a bytestream to determine the input format. Each time a probe returns
   * with a score that is too low, the probe buffer size is increased and another
   * attempt is made. When the maximum probe size is reached, the input format
   *
   * @param pb the bytestream to probe
   * @param fmt the input format is put here
 - * @param filename the filename of the stream
 + * @param url the url of the stream
   * @param logctx the log context
   * @param offset the offset within the bytestream to probe from
   * @param max_probe_size the maximum probe buffer size (zero for default)
 - * @return 0 in case of success, a negative value corresponding to an
 + * @return the score in case of success, a negative value corresponding to an
 + *         the maximal score is AVPROBE_SCORE_MAX
   * AVERROR code otherwise
   */
 +int av_probe_input_buffer2(AVIOContext *pb, AVInputFormat **fmt,
 +                           const char *url, void *logctx,
 +                           unsigned int offset, unsigned int max_probe_size);
 +
 +/**
 + * Like av_probe_input_buffer2() but returns 0 on success
 + */
  int av_probe_input_buffer(AVIOContext *pb, AVInputFormat **fmt,
 -                          const char *filename, void *logctx,
 +                          const char *url, void *logctx,
                            unsigned int offset, unsigned int max_probe_size);
  
  /**
   *           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 url URL 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.
   *
   * @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 avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options);
 +
 +attribute_deprecated
 +int av_demuxer_open(AVFormatContext *ic);
  
  /**
   * Read packets of a media file to get stream information. This
  int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);
  
  /**
 + * Find the programs which belong to a given stream.
 + *
 + * @param ic    media file handle
 + * @param last  the last found program, the search will start after this
 + *              program, or from the beginning if it is NULL
 + * @param s     stream index
 + * @return the next program which belongs to s, NULL if no program is found or
 + *         the last program is not among the programs of ic.
 + */
 +AVProgram *av_find_program_from_stream(AVFormatContext *ic, AVProgram *last, int s);
 +
 +void av_program_add_stream_index(AVFormatContext *ac, int progid, unsigned int idx);
 +
 +/**
   * Find the "best" stream in the file.
   * The best stream is determined according to various heuristics as the most
   * likely to be what the user expects.
@@@ -2245,7 -1587,6 +2279,7 @@@ int av_seek_frame(AVFormatContext *s, i
   * or if stream_index is -1, in AV_TIME_BASE units.
   * If flags contain AVSEEK_FLAG_ANY, then non-keyframes are treated as
   * keyframes (this may not be supported by all demuxers).
 + * If flags contain AVSEEK_FLAG_BACKWARD, it is ignored.
   *
   * @param s media file handle
   * @param stream_index index of the stream which is used as time base reference
  int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags);
  
  /**
 + * Discard all internally buffered data. This can be useful when dealing with
 + * discontinuities in the byte stream. Generally works only with formats that
 + * can resync. This includes headerless formats like MPEG-TS/TS but should also
 + * work with NUT, Ogg and in a limited way AVI for example.
 + *
 + * The set of streams, the detected duration, stream parameters and codecs do
 + * not change when calling this function. If you want a complete reset, it's
 + * better to open a new AVFormatContext.
 + *
 + * This does not flush the AVIOContext (s->pb). If necessary, call
 + * avio_flush(s->pb) before calling this function.
 + *
 + * @param s media file handle
 + * @return >=0 on success, error code otherwise
 + */
 +int avformat_flush(AVFormatContext *s);
 +
 +/**
   * Start playing a network-based stream (e.g. RTSP stream) at the
   * current position.
   */
@@@ -2325,7 -1648,6 +2359,7 @@@ void avformat_close_input(AVFormatConte
   *
   * @see av_opt_find, av_dict_set, avio_open, av_oformat_next.
   */
 +av_warn_unused_result
  int avformat_write_header(AVFormatContext *s, AVDictionary **options);
  
  /**
@@@ -2409,44 -1731,6 +2443,44 @@@ int av_write_frame(AVFormatContext *s, 
  int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt);
  
  /**
 + * Write a uncoded frame to an output media file.
 + *
 + * The frame must be correctly interleaved according to the container
 + * specification; if not, then av_interleaved_write_frame() must be used.
 + *
 + * See av_interleaved_write_frame() for details.
 + */
 +int av_write_uncoded_frame(AVFormatContext *s, int stream_index,
 +                           AVFrame *frame);
 +
 +/**
 + * Write a uncoded frame to an output media file.
 + *
 + * If the muxer supports it, this function makes it possible to write an AVFrame
 + * structure directly, without encoding it into a packet.
 + * It is mostly useful for devices and similar special muxers that use raw
 + * video or PCM data and will not serialize it into a byte stream.
 + *
 + * To test whether it is possible to use it with a given muxer and stream,
 + * use av_write_uncoded_frame_query().
 + *
 + * The caller gives up ownership of the frame and must not access it
 + * afterwards.
 + *
 + * @return  >=0 for success, a negative code on error
 + */
 +int av_interleaved_write_uncoded_frame(AVFormatContext *s, int stream_index,
 +                                       AVFrame *frame);
 +
 +/**
 + * Test whether a muxer supports uncoded frame.
 + *
 + * @return  >=0 if an uncoded frame can be written to that muxer and stream,
 + *          <0 if not
 + */
 +int av_write_uncoded_frame_query(AVFormatContext *s, int stream_index);
 +
 +/**
   * Write the stream trailer to an output media file and free the
   * file private data.
   *
@@@ -2481,25 -1765,6 +2515,25 @@@ enum AVCodecID av_guess_codec(AVOutputF
                              enum AVMediaType type);
  
  /**
 + * Get timing information for the data currently output.
 + * The exact meaning of "currently output" depends on the format.
 + * It is mostly relevant for devices that have an internal buffer and/or
 + * work in real time.
 + * @param s          media file handle
 + * @param stream     stream in the media file
 + * @param[out] dts   DTS of the last packet output for the stream, in stream
 + *                   time_base units
 + * @param[out] wall  absolute time when that packet whas output,
 + *                   in microsecond
 + * @return  0 if OK, AVERROR(ENOSYS) if the format does not support it
 + * Note: some formats or devices may not allow to measure dts and wall
 + * atomically.
 + */
 +int av_get_output_timestamp(struct AVFormatContext *s, int stream,
 +                            int64_t *dts, int64_t *wall);
 +
 +
 +/**
   * @}
   */
  
@@@ -2546,7 -1811,7 +2580,7 @@@ void av_hex_dump_log(void *avcl, int le
   * @param dump_payload True if the payload must be displayed, too.
   * @param st AVStream that the packet belongs to
   */
 -void av_pkt_dump2(FILE *f, AVPacket *pkt, int dump_payload, AVStream *st);
 +void av_pkt_dump2(FILE *f, const AVPacket *pkt, int dump_payload, const AVStream *st);
  
  
  /**
   * @param dump_payload True if the payload must be displayed, too.
   * @param st AVStream that the packet belongs to
   */
 -void av_pkt_dump_log2(void *avcl, int level, AVPacket *pkt, int dump_payload,
 -                      AVStream *st);
 +void av_pkt_dump_log2(void *avcl, int level, const AVPacket *pkt, int dump_payload,
 +                      const AVStream *st);
  
  /**
   * Get the AVCodecID for the given codec tag tag.
@@@ -2583,18 -1848,6 +2617,18 @@@ enum AVCodecID av_codec_get_id(const st
   */
  unsigned int av_codec_get_tag(const struct AVCodecTag * const *tags, enum AVCodecID id);
  
 +/**
 + * Get the codec tag for the given codec id.
 + *
 + * @param tags list of supported codec_id - codec_tag pairs, as stored
 + * in AVInputFormat.codec_tag and AVOutputFormat.codec_tag
 + * @param id codec id that should be searched for in the list
 + * @param tag A pointer to the found tag
 + * @return 0 if id was not found in tags, > 0 if it was found
 + */
 +int av_codec_get_tag2(const struct AVCodecTag * const *tags, enum AVCodecID id,
 +                      unsigned int *tag);
 +
  int av_find_default_stream_index(AVFormatContext *s);
  
  /**
@@@ -2653,9 -1906,9 +2687,9 @@@ void av_url_split(char *proto,         
   * codec and time base.
   *
   * @param ic        the context to analyze
 - * @param index     the index to print, if you have multiple inputs or outputs
 + * @param index     index of the stream to dump information about
   * @param url       the URL to print, such as source or destination file
 - * @param is_output whether the context is input or ouput
 + * @param is_output Select whether the specified context is an input(0) or output(1)
   */
  void av_dump_format(AVFormatContext *ic,
                      int index,
@@@ -2747,78 -2000,10 +2781,78 @@@ const struct AVCodecTag *avformat_get_r
   */
  const struct AVCodecTag *avformat_get_riff_audio_tags(void);
  /**
 + * @return the table mapping MOV FourCCs for video to libavcodec AVCodecID.
 + */
 +const struct AVCodecTag *avformat_get_mov_video_tags(void);
 +/**
 + * @return the table mapping MOV FourCCs for audio to AVCodecID.
 + */
 +const struct AVCodecTag *avformat_get_mov_audio_tags(void);
 +
 +/**
   * @}
   */
  
  /**
 + * Guess the sample aspect ratio of a frame, based on both the stream and the
 + * frame aspect ratio.
 + *
 + * Since the frame aspect ratio is set by the codec but the stream aspect ratio
 + * is set by the demuxer, these two may not be equal. This function tries to
 + * return the value that you should use if you would like to display the frame.
 + *
 + * Basic logic is to use the stream aspect ratio if it is set to something sane
 + * otherwise use the frame aspect ratio. This way a container setting, which is
 + * usually easy to modify can override the coded value in the frames.
 + *
 + * @param format the format context which the stream is part of
 + * @param stream the stream which the frame is part of
 + * @param frame the frame with the aspect ratio to be determined
 + * @return the guessed (valid) sample_aspect_ratio, 0/1 if no idea
 + */
 +AVRational av_guess_sample_aspect_ratio(AVFormatContext *format, AVStream *stream, AVFrame *frame);
 +
 +/**
 + * Guess the frame rate, based on both the container and codec information.
 + *
 + * @param ctx the format context which the stream is part of
 + * @param stream the stream which the frame is part of
 + * @param frame the frame for which the frame rate should be determined, may be NULL
 + * @return the guessed (valid) frame rate, 0/1 if no idea
 + */
 +AVRational av_guess_frame_rate(AVFormatContext *ctx, AVStream *stream, AVFrame *frame);
 +
 +/**
 + * Check if the stream st contained in s is matched by the stream specifier
 + * spec.
 + *
 + * See the "stream specifiers" chapter in the documentation for the syntax
 + * of spec.
 + *
 + * @return  >0 if st is matched by spec;
 + *          0  if st is not matched by spec;
 + *          AVERROR code if spec is invalid
 + *
 + * @note  A stream specifier can match several streams in the format.
 + */
 +int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st,
 +                                    const char *spec);
 +
 +int avformat_queue_attached_pictures(AVFormatContext *s);
 +
 +/**
 + * Apply a list of bitstream filters to a packet.
 + *
 + * @param codec AVCodecContext, usually from an AVStream
 + * @param pkt the packet to apply filters to
 + * @param bsfc a NULL-terminated list of filters to apply
 + * @return  >=0 on success;
 + *          AVERROR code on failure
 + */
 +int av_apply_bitstream_filters(AVCodecContext *codec, AVPacket *pkt,
 +                               AVBitStreamFilterContext *bsfc);
 +
 +/**
   * @}
   */
  
diff --combined libavformat/dashenc.c
@@@ -2,20 -2,20 +2,20 @@@
   * MPEG-DASH ISO BMFF segmenter
   * Copyright (c) 2014 Martin Storsjo
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
  #include <unistd.h>
  #endif
  
 +#include "libavutil/avassert.h"
  #include "libavutil/avstring.h"
  #include "libavutil/intreadwrite.h"
  #include "libavutil/mathematics.h"
  #include "libavutil/opt.h"
 +#include "libavutil/rational.h"
  #include "libavutil/time_internal.h"
  
  #include "avc.h"
@@@ -96,8 -94,6 +96,8 @@@ typedef struct DASHContext 
      const char *single_file_name;
      const char *init_seg_name;
      const char *media_seg_name;
 +    AVRational min_frame_rate, max_frame_rate;
 +    int ambiguous_frame_rate;
  } DASHContext;
  
  static int dash_write(void *opaque, uint8_t *buf, int buf_size)
@@@ -448,8 -444,7 +448,7 @@@ static int write_manifest(AVFormatConte
      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;
      }
  
      if (c->has_video) {
 -        avio_printf(out, "\t\t<AdaptationSet contentType=\"video\" segmentAlignment=\"true\" bitstreamSwitching=\"true\">\n");
 +        avio_printf(out, "\t\t<AdaptationSet contentType=\"video\" segmentAlignment=\"true\" bitstreamSwitching=\"true\"");
 +        if (c->max_frame_rate.num && !c->ambiguous_frame_rate)
 +            avio_printf(out, " %s=\"%d/%d\"", (av_cmp_q(c->min_frame_rate, c->max_frame_rate) < 0) ? "maxFrameRate" : "frameRate", c->max_frame_rate.num, c->max_frame_rate.den);
 +        avio_printf(out, ">\n");
 +
          for (i = 0; i < s->nb_streams; i++) {
              AVStream *st = s->streams[i];
              OutputStream *os = &c->streams[i];
 +
              if (st->codec->codec_type != AVMEDIA_TYPE_VIDEO)
                  continue;
 -            avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"video/mp4\" codecs=\"%s\"%s width=\"%d\" height=\"%d\">\n", i, os->codec_str, os->bandwidth_str, st->codec->width, st->codec->height);
 +
 +            avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"video/mp4\" codecs=\"%s\"%s width=\"%d\" height=\"%d\"", i, os->codec_str, os->bandwidth_str, st->codec->width, st->codec->height);
 +            if (st->avg_frame_rate.num)
 +                avio_printf(out, " frameRate=\"%d/%d\"", st->avg_frame_rate.num, st->avg_frame_rate.den);
 +            avio_printf(out, ">\n");
 +
              output_segment_list(&c->streams[i], out, c);
              avio_printf(out, "\t\t\t</Representation>\n");
          }
          for (i = 0; i < s->nb_streams; i++) {
              AVStream *st = s->streams[i];
              OutputStream *os = &c->streams[i];
 +
              if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO)
                  continue;
 +
              avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"audio/mp4\" codecs=\"%s\"%s audioSamplingRate=\"%d\">\n", i, os->codec_str, os->bandwidth_str, st->codec->sample_rate);
              avio_printf(out, "\t\t\t\t<AudioChannelConfiguration schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\" value=\"%d\" />\n", st->codec->channels);
              output_segment_list(&c->streams[i], out, c);
      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);
 +    return ff_rename(temp_filename, s->filename, s);
  }
  
  static int dash_write_header(AVFormatContext *s)
          c->single_file = 1;
      if (c->single_file)
          c->use_template = 0;
 +    c->ambiguous_frame_rate = 0;
  
      av_strlcpy(c->dirname, s->filename, sizeof(c->dirname));
      ptr = strrchr(c->dirname, '/');
          AVDictionary *opts = NULL;
          char filename[1024];
  
 -        os->bit_rate = s->streams[i]->codec->bit_rate;
 +        os->bit_rate = s->streams[i]->codec->bit_rate ?
 +                       s->streams[i]->codec->bit_rate :
 +                       s->streams[i]->codec->rc_max_rate;
          if (os->bit_rate) {
              snprintf(os->bandwidth_str, sizeof(os->bandwidth_str),
                       " bandwidth=\"%d\"", os->bit_rate);
          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);
              dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), c->init_seg_name, i, 0, os->bit_rate, 0);
          }
          snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->initfile);
 -        ret = ffurl_open(&os->out, filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL);
 +        ret = ffurl_open_whitelist(&os->out, filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL, s->protocol_whitelist);
          if (ret < 0)
              goto fail;
          os->init_start_pos = 0;
          // already before being handed to this muxer, so we don't have mismatches
          // between the MPD and the actual segments.
          s->avoid_negative_ts = ctx->avoid_negative_ts;
 -        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
 +        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
 +            AVRational avg_frame_rate = s->streams[i]->avg_frame_rate;
 +            if (avg_frame_rate.num > 0) {
 +                if (av_cmp_q(avg_frame_rate, c->min_frame_rate) < 0)
 +                    c->min_frame_rate = avg_frame_rate;
 +                if (av_cmp_q(c->max_frame_rate, avg_frame_rate) < 0)
 +                    c->max_frame_rate = avg_frame_rate;
 +            } else {
 +                c->ambiguous_frame_rate = 1;
 +            }
              c->has_video = 1;
 -        else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
 +        } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
              c->has_audio = 1;
 +        }
  
          set_codec_str(s, st->codec, os->codec_str, sizeof(os->codec_str));
          os->first_pts = AV_NOPTS_VALUE;
@@@ -756,7 -729,7 +758,7 @@@ static void find_index_range(AVFormatCo
      URLContext *fd;
      int ret;
  
 -    ret = ffurl_open(&fd, full_path, AVIO_FLAG_READ, &s->interrupt_callback, NULL);
 +    ret = ffurl_open_whitelist(&fd, full_path, AVIO_FLAG_READ, &s->interrupt_callback, NULL, s->protocol_whitelist);
      if (ret < 0)
          return;
      if (ffurl_seek(fd, pos, SEEK_SET) != pos) {
@@@ -839,7 -812,7 +841,7 @@@ static int dash_flush(AVFormatContext *
              dash_fill_tmpl_params(filename, sizeof(filename), c->media_seg_name, i, os->segment_index, os->bit_rate, os->start_pts);
              snprintf(full_path, sizeof(full_path), "%s%s", c->dirname, filename);
              snprintf(temp_path, sizeof(temp_path), "%s.tmp", full_path);
 -            ret = ffurl_open(&os->out, temp_path, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL);
 +            ret = ffurl_open_whitelist(&os->out, temp_path, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL, s->protocol_whitelist);
              if (ret < 0)
                  break;
              write_styp(os->ctx->pb);
          } else {
              ffurl_close(os->out);
              os->out = NULL;
 -            ret = ff_rename(temp_path, full_path);
 +            ret = ff_rename(temp_path, full_path, s);
              if (ret < 0)
                  break;
          }
@@@ -963,7 -936,7 +965,7 @@@ static int dash_write_packet(AVFormatCo
      else
          os->max_pts = FFMAX(os->max_pts, pkt->pts + pkt->duration);
      os->packets_written++;
 -    return ff_write_chained(os->ctx, 0, pkt, s);
 +    return ff_write_chained(os->ctx, 0, pkt, s, 0);
  }
  
  static int dash_write_trailer(AVFormatContext *s)
@@@ -1005,10 -978,10 +1007,10 @@@ static const AVOption options[] = 
      { "window_size", "number of segments kept in the manifest", OFFSET(window_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, E },
      { "extra_window_size", "number of segments kept outside of the manifest before removing from disk", OFFSET(extra_window_size), AV_OPT_TYPE_INT, { .i64 = 5 }, 0, INT_MAX, E },
      { "min_seg_duration", "minimum segment duration (in microseconds)", OFFSET(min_seg_duration), AV_OPT_TYPE_INT64, { .i64 = 5000000 }, 0, INT_MAX, E },
 -    { "remove_at_exit", "remove all segments when finished", OFFSET(remove_at_exit), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, E },
 -    { "use_template", "Use SegmentTemplate instead of SegmentList", OFFSET(use_template), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, E },
 -    { "use_timeline", "Use SegmentTimeline in SegmentTemplate", OFFSET(use_timeline), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, E },
 -    { "single_file", "Store all segments in one file, accessed using byte ranges", OFFSET(single_file), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, E },
 +    { "remove_at_exit", "remove all segments when finished", OFFSET(remove_at_exit), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
 +    { "use_template", "Use SegmentTemplate instead of SegmentList", OFFSET(use_template), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, E },
 +    { "use_timeline", "Use SegmentTimeline in SegmentTemplate", OFFSET(use_timeline), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, E },
 +    { "single_file", "Store all segments in one file, accessed using byte ranges", OFFSET(single_file), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
      { "single_file_name", "DASH-templated name to be used for baseURL. Implies storing all segments in one file, accessed using byte ranges", OFFSET(single_file_name), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E },
      { "init_seg_name", "DASH-templated name to used for the initialization segment", OFFSET(init_seg_name), AV_OPT_TYPE_STRING, {.str = "init-stream$RepresentationID$.m4s"}, 0, 0, E },
      { "media_seg_name", "DASH-templated name to used for the media segments", OFFSET(media_seg_name), AV_OPT_TYPE_STRING, {.str = "chunk-stream$RepresentationID$-$Number%05d$.m4s"}, 0, 0, E },
diff --combined libavformat/hdsenc.c
@@@ -2,20 -2,20 +2,20 @@@
   * Live HDS fragmenter
   * Copyright (c) 2013 Martin Storsjo
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -26,7 -26,6 +26,7 @@@
  #endif
  
  #include "avformat.h"
 +#include "avio_internal.h"
  #include "internal.h"
  #include "os_support.h"
  
@@@ -140,19 -139,20 +140,20 @@@ 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 && os->ctx->pb)
 -            av_free(os->ctx->pb);
 +        if (os->ctx)
 +            av_freep(&os->ctx->pb);
          if (os->ctx)
              avformat_free_context(os->ctx);
 -        av_free(os->metadata);
 +        av_freep(&os->metadata);
          for (j = 0; j < os->nb_extra_packets; j++)
 -            av_free(os->extra_packets[j]);
 +            av_freep(&os->extra_packets[j]);
          for (j = 0; j < os->nb_fragments; j++)
 -            av_free(os->fragments[j]);
 -        av_free(os->fragments);
 +            av_freep(&os->fragments[j]);
 +        av_freep(&os->fragments);
      }
      av_freep(&c->streams);
  }
@@@ -163,15 -163,14 +164,14 @@@ static int write_manifest(AVFormatConte
      AVIOContext *out;
      char filename[1024], temp_filename[1024];
      int ret, i;
 -    float duration = 0;
 +    double duration = 0;
  
      if (c->nb_streams > 0)
          duration = c->streams[0].last_ts * av_q2d(s->streams[0]->time_base);
  
      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;
          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);
      }
      avio_printf(out, "</manifest>\n");
      avio_flush(out);
-     avio_close(out);
+     ff_format_io_close(s, &out);
 -    return ff_rename(temp_filename, filename);
 +    return ff_rename(temp_filename, filename, s);
  }
  
  static void update_size(AVIOContext *out, int64_t pos)
@@@ -239,8 -238,7 +239,7 @@@ static int write_abst(AVFormatContext *
               "%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;
      }
      update_size(out, afrt_pos);
      update_size(out, 0);
-     avio_close(out);
+     ff_format_io_close(s, &out);
 -    return ff_rename(temp_filename, filename);
 +    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);
      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)
  
      if (mkdir(s->filename, 0777) == -1 && errno != EEXIST) {
          ret = AVERROR(errno);
 +        av_log(s, AV_LOG_ERROR , "Failed to create directory %s\n", s->filename);
          goto fail;
      }
  
          goto fail;
      }
  
 -    c->streams = av_mallocz(sizeof(*c->streams) * s->nb_streams);
 +    c->streams = av_mallocz_array(s->nb_streams, sizeof(*c->streams));
      if (!c->streams) {
          ret = AVERROR(ENOMEM);
          goto fail;
@@@ -475,11 -471,11 +473,11 @@@ static int hds_flush(AVFormatContext *s
  
      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);
 -    ret = ff_rename(os->temp_filename, target_filename);
 +    ret = ff_rename(os->temp_filename, target_filename, s);
      if (ret < 0)
          return ret;
      add_fragment(os, target_filename, os->frag_start_ts, end_ts - os->frag_start_ts);
          if (remove > 0) {
              for (i = 0; i < remove; i++) {
                  unlink(os->fragments[i]->file);
 -                av_free(os->fragments[i]);
 +                av_freep(&os->fragments[i]);
              }
              os->nb_fragments -= remove;
              memmove(os->fragments, os->fragments + remove,
@@@ -515,7 -511,7 +513,7 @@@ static int hds_write_packet(AVFormatCon
      HDSContext *c = s->priv_data;
      AVStream *st = s->streams[pkt->stream_index];
      OutputStream *os = &c->streams[s->streams[pkt->stream_index]->id];
 -    int64_t end_dts = os->fragment_index * (int64_t) c->min_frag_duration;
 +    int64_t end_dts = os->fragment_index * (int64_t)c->min_frag_duration;
      int ret;
  
      if (st->first_dts == AV_NOPTS_VALUE)
      os->last_ts = pkt->dts;
  
      os->packets_written++;
 -    return ff_write_chained(os->ctx, pkt->stream_index - os->first_stream, pkt, s);
 +    return ff_write_chained(os->ctx, pkt->stream_index - os->first_stream, pkt, s, 0);
  }
  
  static int hds_write_trailer(AVFormatContext *s)
@@@ -570,7 -566,7 +568,7 @@@ static const AVOption options[] = 
      { "window_size", "number of fragments kept in the manifest", OFFSET(window_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, E },
      { "extra_window_size", "number of fragments kept outside of the manifest before removing from disk", OFFSET(extra_window_size), AV_OPT_TYPE_INT, { .i64 = 5 }, 0, INT_MAX, E },
      { "min_frag_duration", "minimum fragment duration (in microseconds)", OFFSET(min_frag_duration), AV_OPT_TYPE_INT64, { .i64 = 10000000 }, 0, INT_MAX, E },
 -    { "remove_at_exit", "remove all fragments when finished", OFFSET(remove_at_exit), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, E },
 +    { "remove_at_exit", "remove all fragments when finished", OFFSET(remove_at_exit), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
      { NULL },
  };
  
diff --combined libavformat/hls.c
@@@ -1,22 -1,21 +1,22 @@@
  /*
   * Apple HTTP Live Streaming demuxer
   * Copyright (c) 2010 Martin Storsjo
 + * Copyright (c) 2013 Anssi Hannula
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -27,7 -26,6 +27,7 @@@
   */
  
  #include "libavutil/avstring.h"
 +#include "libavutil/avassert.h"
  #include "libavutil/intreadwrite.h"
  #include "libavutil/mathematics.h"
  #include "libavutil/opt.h"
  #include "internal.h"
  #include "avio_internal.h"
  #include "url.h"
 +#include "id3v2.h"
  
  #define INITIAL_BUFFER_SIZE 32768
  
 +#define MAX_FIELD_LEN 64
 +#define MAX_CHARACTERISTICS_LEN 512
 +
 +#define MPEG_TIME_BASE 90000
 +#define MPEG_TIME_BASE_Q (AVRational){1, MPEG_TIME_BASE}
 +
  /*
   * An apple http stream consists of a playlist with media segment files,
   * played sequentially. There may be several playlists with the same
  enum KeyType {
      KEY_NONE,
      KEY_AES_128,
 +    KEY_SAMPLE_AES
  };
  
  struct segment {
      int64_t duration;
 -    char url[MAX_URL_SIZE];
 -    char key[MAX_URL_SIZE];
 +    int64_t url_offset;
 +    int64_t size;
 +    char *url;
 +    char *key;
      enum KeyType key_type;
      uint8_t iv[16];
 +    /* associated Media Initialization Section, treated as a segment */
 +    struct segment *init_section;
 +};
 +
 +struct rendition;
 +
 +enum PlaylistType {
 +    PLS_TYPE_UNSPECIFIED,
 +    PLS_TYPE_EVENT,
 +    PLS_TYPE_VOD
  };
  
  /*
 - * Each variant has its own demuxer. If it currently is active,
 + * Each playlist has its own demuxer. If it currently is active,
   * it has an open AVIOContext too, and potentially an AVPacket
   * containing the next packet from this stream.
   */
 -struct variant {
 -    int bandwidth;
 +struct playlist {
      char url[MAX_URL_SIZE];
      AVIOContext pb;
      uint8_t* read_buffer;
      int stream_offset;
  
      int finished;
 +    enum PlaylistType type;
      int64_t target_duration;
      int start_seq_no;
      int n_segments;
      struct segment **segments;
      int needed, cur_needed;
      int cur_seq_no;
 +    int64_t cur_seg_offset;
      int64_t last_load_time;
  
 +    /* Currently active Media Initialization Section */
 +    struct segment *cur_init_section;
 +    uint8_t *init_sec_buf;
 +    unsigned int init_sec_buf_size;
 +    unsigned int init_sec_data_len;
 +    unsigned int init_sec_buf_read_offset;
 +
      char key_url[MAX_URL_SIZE];
      uint8_t key[16];
 +
 +    /* ID3 timestamp handling (elementary audio streams have ID3 timestamps
 +     * (and possibly other ID3 tags) in the beginning of each segment) */
 +    int is_id3_timestamped; /* -1: not yet known */
 +    int64_t id3_mpegts_timestamp; /* in mpegts tb */
 +    int64_t id3_offset; /* in stream original tb */
 +    uint8_t* id3_buf; /* temp buffer for id3 parsing */
 +    unsigned int id3_buf_size;
 +    AVDictionary *id3_initial; /* data from first id3 tag */
 +    int id3_found; /* ID3 tag found at some point */
 +    int id3_changed; /* ID3 tag data has changed at some point */
 +    ID3v2ExtraMeta *id3_deferred_extra; /* stored here until subdemuxer is opened */
 +
 +    int64_t seek_timestamp;
 +    int seek_flags;
 +    int seek_stream_index; /* into subdemuxer stream array */
 +
 +    /* Renditions associated with this playlist, if any.
 +     * Alternative rendition playlists have a single rendition associated
 +     * with them, and variant main Media Playlists may have
 +     * multiple (playlist-less) renditions associated with them. */
 +    int n_renditions;
 +    struct rendition **renditions;
 +
 +    /* Media Initialization Sections (EXT-X-MAP) associated with this
 +     * playlist, if any. */
 +    int n_init_sections;
 +    struct segment **init_sections;
 +};
 +
 +/*
 + * Renditions are e.g. alternative subtitle or audio streams.
 + * The rendition may either be an external playlist or it may be
 + * contained in the main Media Playlist of the variant (in which case
 + * playlist is NULL).
 + */
 +struct rendition {
 +    enum AVMediaType type;
 +    struct playlist *playlist;
 +    char group_id[MAX_FIELD_LEN];
 +    char language[MAX_FIELD_LEN];
 +    char name[MAX_FIELD_LEN];
 +    int disposition;
 +};
 +
 +struct variant {
 +    int bandwidth;
 +
 +    /* every variant contains at least the main Media Playlist in index 0 */
 +    int n_playlists;
 +    struct playlist **playlists;
 +
 +    char audio_group[MAX_FIELD_LEN];
 +    char video_group[MAX_FIELD_LEN];
 +    char subtitles_group[MAX_FIELD_LEN];
  };
  
  typedef struct HLSContext {
-     AVFormatContext *avfmt;
 +    AVClass *class;
+     AVFormatContext *ctx;
      int n_variants;
      struct variant **variants;
 +    int n_playlists;
 +    struct playlist **playlists;
 +    int n_renditions;
 +    struct rendition **renditions;
 +
      int cur_seq_no;
 -    int end_of_segment;
 +    int live_start_index;
      int first_packet;
      int64_t first_timestamp;
 -    int64_t seek_timestamp;
 -    int seek_flags;
 +    int64_t cur_timestamp;
      AVIOInterruptCB *interrupt_callback;
 +    char *user_agent;                    ///< holds HTTP user agent set as an AVOption to the HTTP protocol context
 +    char *cookies;                       ///< holds HTTP cookie values set in either the initial response or as an AVOption to the HTTP protocol context
 +    char *headers;                       ///< holds HTTP headers set as an AVOption to the HTTP protocol context
 +    char *http_proxy;                    ///< holds the address of the HTTP proxy server
      AVDictionary *avio_opts;
 +    int strict_std_compliance;
  } HLSContext;
  
  static int read_chomp_line(AVIOContext *s, char *buf, int maxlen)
      return len;
  }
  
 -static void free_segment_list(struct variant *var)
 +static void free_segment_list(struct playlist *pls)
 +{
 +    int i;
 +    for (i = 0; i < pls->n_segments; i++) {
 +        av_freep(&pls->segments[i]->key);
 +        av_freep(&pls->segments[i]->url);
 +        av_freep(&pls->segments[i]);
 +    }
 +    av_freep(&pls->segments);
 +    pls->n_segments = 0;
 +}
 +
 +static void free_init_section_list(struct playlist *pls)
  {
      int i;
 -    for (i = 0; i < var->n_segments; i++)
 -        av_free(var->segments[i]);
 -    av_freep(&var->segments);
 -    var->n_segments = 0;
 +    for (i = 0; i < pls->n_init_sections; i++) {
 +        av_freep(&pls->init_sections[i]->url);
 +        av_freep(&pls->init_sections[i]);
 +    }
 +    av_freep(&pls->init_sections);
 +    pls->n_init_sections = 0;
 +}
 +
 +static void free_playlist_list(HLSContext *c)
 +{
 +    int i;
 +    for (i = 0; i < c->n_playlists; i++) {
 +        struct playlist *pls = c->playlists[i];
 +        free_segment_list(pls);
 +        free_init_section_list(pls);
 +        av_freep(&pls->renditions);
 +        av_freep(&pls->id3_buf);
 +        av_dict_free(&pls->id3_initial);
 +        ff_id3v2_free_extra_meta(&pls->id3_deferred_extra);
 +        av_freep(&pls->init_sec_buf);
 +        av_packet_unref(&pls->pkt);
 +        av_freep(&pls->pb.buffer);
 +        if (pls->input)
 +            ffurl_close(pls->input);
 +        if (pls->ctx) {
 +            pls->ctx->pb = NULL;
 +            avformat_close_input(&pls->ctx);
 +        }
 +        av_free(pls);
 +    }
 +    av_freep(&c->playlists);
 +    av_freep(&c->cookies);
 +    av_freep(&c->user_agent);
 +    av_freep(&c->headers);
 +    av_freep(&c->http_proxy);
 +    c->n_playlists = 0;
  }
  
  static void free_variant_list(HLSContext *c)
      int i;
      for (i = 0; i < c->n_variants; i++) {
          struct variant *var = c->variants[i];
 -        free_segment_list(var);
 -        av_packet_unref(&var->pkt);
 -        av_free(var->pb.buffer);
 -        if (var->input)
 -            ffurl_close(var->input);
 -        if (var->ctx) {
 -            var->ctx->pb = NULL;
 -            avformat_close_input(&var->ctx);
 -        }
 +        av_freep(&var->playlists);
          av_free(var);
      }
      av_freep(&c->variants);
      c->n_variants = 0;
  }
  
 +static void free_rendition_list(HLSContext *c)
 +{
 +    int i;
 +    for (i = 0; i < c->n_renditions; i++)
 +        av_freep(&c->renditions[i]);
 +    av_freep(&c->renditions);
 +    c->n_renditions = 0;
 +}
 +
  /*
   * Used to reset a statically allocated AVPacket to a clean slate,
   * containing no data.
@@@ -294,78 -154,35 +294,78 @@@ static void reset_packet(AVPacket *pkt
      pkt->data = NULL;
  }
  
 -static struct variant *new_variant(HLSContext *c, int bandwidth,
 -                                   const char *url, const char *base)
 +static struct playlist *new_playlist(HLSContext *c, const char *url,
 +                                     const char *base)
  {
 -    struct variant *var = av_mallocz(sizeof(struct variant));
 -    if (!var)
 +    struct playlist *pls = av_mallocz(sizeof(struct playlist));
 +    if (!pls)
          return NULL;
 -    reset_packet(&var->pkt);
 -    var->bandwidth = bandwidth;
 -    ff_make_absolute_url(var->url, sizeof(var->url), base, url);
 -    dynarray_add(&c->variants, &c->n_variants, var);
 -    return var;
 +    reset_packet(&pls->pkt);
 +    ff_make_absolute_url(pls->url, sizeof(pls->url), base, url);
 +    pls->seek_timestamp = AV_NOPTS_VALUE;
 +
 +    pls->is_id3_timestamped = -1;
 +    pls->id3_mpegts_timestamp = AV_NOPTS_VALUE;
 +
 +    dynarray_add(&c->playlists, &c->n_playlists, pls);
 +    return pls;
  }
  
  struct variant_info {
      char bandwidth[20];
 +    /* variant group ids: */
 +    char audio[MAX_FIELD_LEN];
 +    char video[MAX_FIELD_LEN];
 +    char subtitles[MAX_FIELD_LEN];
  };
  
 +static struct variant *new_variant(HLSContext *c, struct variant_info *info,
 +                                   const char *url, const char *base)
 +{
 +    struct variant *var;
 +    struct playlist *pls;
 +
 +    pls = new_playlist(c, url, base);
 +    if (!pls)
 +        return NULL;
 +
 +    var = av_mallocz(sizeof(struct variant));
 +    if (!var)
 +        return NULL;
 +
 +    if (info) {
 +        var->bandwidth = atoi(info->bandwidth);
 +        strcpy(var->audio_group, info->audio);
 +        strcpy(var->video_group, info->video);
 +        strcpy(var->subtitles_group, info->subtitles);
 +    }
 +
 +    dynarray_add(&c->variants, &c->n_variants, var);
 +    dynarray_add(&var->playlists, &var->n_playlists, pls);
 +    return var;
 +}
 +
  static void handle_variant_args(struct variant_info *info, const char *key,
                                  int key_len, char **dest, int *dest_len)
  {
      if (!strncmp(key, "BANDWIDTH=", key_len)) {
          *dest     =        info->bandwidth;
          *dest_len = sizeof(info->bandwidth);
 +    } else if (!strncmp(key, "AUDIO=", key_len)) {
 +        *dest     =        info->audio;
 +        *dest_len = sizeof(info->audio);
 +    } else if (!strncmp(key, "VIDEO=", key_len)) {
 +        *dest     =        info->video;
 +        *dest_len = sizeof(info->video);
 +    } else if (!strncmp(key, "SUBTITLES=", key_len)) {
 +        *dest     =        info->subtitles;
 +        *dest_len = sizeof(info->subtitles);
      }
  }
  
  struct key_info {
       char uri[MAX_URL_SIZE];
 -     char method[10];
 +     char method[11];
       char iv[35];
  };
  
@@@ -384,264 -201,44 +384,264 @@@ static void handle_key_args(struct key_
      }
  }
  
 -static int open_in(HLSContext *c, AVIOContext **in, const char *url)
 +struct init_section_info {
 +    char uri[MAX_URL_SIZE];
 +    char byterange[32];
 +};
 +
 +static struct segment *new_init_section(struct playlist *pls,
 +                                        struct init_section_info *info,
 +                                        const char *url_base)
  {
 -    AVDictionary *tmp = NULL;
 -    int ret;
 +    struct segment *sec;
 +    char *ptr;
 +    char tmp_str[MAX_URL_SIZE];
  
 -    av_dict_copy(&tmp, c->avio_opts, 0);
 +    if (!info->uri[0])
 +        return NULL;
  
 -    ret = c->ctx->io_open(c->ctx, in, url, AVIO_FLAG_READ, &tmp);
 +    sec = av_mallocz(sizeof(*sec));
 +    if (!sec)
 +        return NULL;
  
 -    av_dict_free(&tmp);
 -    return ret;
 +    ff_make_absolute_url(tmp_str, sizeof(tmp_str), url_base, info->uri);
 +    sec->url = av_strdup(tmp_str);
 +    if (!sec->url) {
 +        av_free(sec);
 +        return NULL;
 +    }
 +
 +    if (info->byterange[0]) {
 +        sec->size = atoi(info->byterange);
 +        ptr = strchr(info->byterange, '@');
 +        if (ptr)
 +            sec->url_offset = atoi(ptr+1);
 +    } else {
 +        /* the entire file is the init section */
 +        sec->size = -1;
 +    }
 +
 +    dynarray_add(&pls->init_sections, &pls->n_init_sections, sec);
 +
 +    return sec;
 +}
 +
 +static void handle_init_section_args(struct init_section_info *info, const char *key,
 +                                           int key_len, char **dest, int *dest_len)
 +{
 +    if (!strncmp(key, "URI=", key_len)) {
 +        *dest     =        info->uri;
 +        *dest_len = sizeof(info->uri);
 +    } else if (!strncmp(key, "BYTERANGE=", key_len)) {
 +        *dest     =        info->byterange;
 +        *dest_len = sizeof(info->byterange);
 +    }
 +}
 +
 +struct rendition_info {
 +    char type[16];
 +    char uri[MAX_URL_SIZE];
 +    char group_id[MAX_FIELD_LEN];
 +    char language[MAX_FIELD_LEN];
 +    char assoc_language[MAX_FIELD_LEN];
 +    char name[MAX_FIELD_LEN];
 +    char defaultr[4];
 +    char forced[4];
 +    char characteristics[MAX_CHARACTERISTICS_LEN];
 +};
 +
 +static struct rendition *new_rendition(HLSContext *c, struct rendition_info *info,
 +                                      const char *url_base)
 +{
 +    struct rendition *rend;
 +    enum AVMediaType type = AVMEDIA_TYPE_UNKNOWN;
 +    char *characteristic;
 +    char *chr_ptr;
 +    char *saveptr;
 +
 +    if (!strcmp(info->type, "AUDIO"))
 +        type = AVMEDIA_TYPE_AUDIO;
 +    else if (!strcmp(info->type, "VIDEO"))
 +        type = AVMEDIA_TYPE_VIDEO;
 +    else if (!strcmp(info->type, "SUBTITLES"))
 +        type = AVMEDIA_TYPE_SUBTITLE;
 +    else if (!strcmp(info->type, "CLOSED-CAPTIONS"))
 +        /* CLOSED-CAPTIONS is ignored since we do not support CEA-608 CC in
 +         * AVC SEI RBSP anyway */
 +        return NULL;
 +
 +    if (type == AVMEDIA_TYPE_UNKNOWN)
 +        return NULL;
 +
 +    /* URI is mandatory for subtitles as per spec */
 +    if (type == AVMEDIA_TYPE_SUBTITLE && !info->uri[0])
 +        return NULL;
 +
 +    /* TODO: handle subtitles (each segment has to parsed separately) */
 +    if (c->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL)
 +        if (type == AVMEDIA_TYPE_SUBTITLE)
 +            return NULL;
 +
 +    rend = av_mallocz(sizeof(struct rendition));
 +    if (!rend)
 +        return NULL;
 +
 +    dynarray_add(&c->renditions, &c->n_renditions, rend);
 +
 +    rend->type = type;
 +    strcpy(rend->group_id, info->group_id);
 +    strcpy(rend->language, info->language);
 +    strcpy(rend->name, info->name);
 +
 +    /* add the playlist if this is an external rendition */
 +    if (info->uri[0]) {
 +        rend->playlist = new_playlist(c, info->uri, url_base);
 +        if (rend->playlist)
 +            dynarray_add(&rend->playlist->renditions,
 +                         &rend->playlist->n_renditions, rend);
 +    }
 +
 +    if (info->assoc_language[0]) {
 +        int langlen = strlen(rend->language);
 +        if (langlen < sizeof(rend->language) - 3) {
 +            rend->language[langlen] = ',';
 +            strncpy(rend->language + langlen + 1, info->assoc_language,
 +                    sizeof(rend->language) - langlen - 2);
 +        }
 +    }
 +
 +    if (!strcmp(info->defaultr, "YES"))
 +        rend->disposition |= AV_DISPOSITION_DEFAULT;
 +    if (!strcmp(info->forced, "YES"))
 +        rend->disposition |= AV_DISPOSITION_FORCED;
 +
 +    chr_ptr = info->characteristics;
 +    while ((characteristic = av_strtok(chr_ptr, ",", &saveptr))) {
 +        if (!strcmp(characteristic, "public.accessibility.describes-music-and-sound"))
 +            rend->disposition |= AV_DISPOSITION_HEARING_IMPAIRED;
 +        else if (!strcmp(characteristic, "public.accessibility.describes-video"))
 +            rend->disposition |= AV_DISPOSITION_VISUAL_IMPAIRED;
 +
 +        chr_ptr = NULL;
 +    }
 +
 +    return rend;
 +}
 +
 +static void handle_rendition_args(struct rendition_info *info, const char *key,
 +                                  int key_len, char **dest, int *dest_len)
 +{
 +    if (!strncmp(key, "TYPE=", key_len)) {
 +        *dest     =        info->type;
 +        *dest_len = sizeof(info->type);
 +    } else if (!strncmp(key, "URI=", key_len)) {
 +        *dest     =        info->uri;
 +        *dest_len = sizeof(info->uri);
 +    } else if (!strncmp(key, "GROUP-ID=", key_len)) {
 +        *dest     =        info->group_id;
 +        *dest_len = sizeof(info->group_id);
 +    } else if (!strncmp(key, "LANGUAGE=", key_len)) {
 +        *dest     =        info->language;
 +        *dest_len = sizeof(info->language);
 +    } else if (!strncmp(key, "ASSOC-LANGUAGE=", key_len)) {
 +        *dest     =        info->assoc_language;
 +        *dest_len = sizeof(info->assoc_language);
 +    } else if (!strncmp(key, "NAME=", key_len)) {
 +        *dest     =        info->name;
 +        *dest_len = sizeof(info->name);
 +    } else if (!strncmp(key, "DEFAULT=", key_len)) {
 +        *dest     =        info->defaultr;
 +        *dest_len = sizeof(info->defaultr);
 +    } else if (!strncmp(key, "FORCED=", key_len)) {
 +        *dest     =        info->forced;
 +        *dest_len = sizeof(info->forced);
 +    } else if (!strncmp(key, "CHARACTERISTICS=", key_len)) {
 +        *dest     =        info->characteristics;
 +        *dest_len = sizeof(info->characteristics);
 +    }
 +    /*
 +     * ignored:
 +     * - AUTOSELECT: client may autoselect based on e.g. system language
 +     * - INSTREAM-ID: EIA-608 closed caption number ("CC1".."CC4")
 +     */
  }
  
 -static int url_connect(struct variant *var, AVDictionary *opts)
 +/* used by parse_playlist to allocate a new variant+playlist when the
 + * playlist is detected to be a Media Playlist (not Master Playlist)
 + * and we have no parent Master Playlist (parsing of which would have
 + * allocated the variant and playlist already)
 + * *pls == NULL  => Master Playlist or parentless Media Playlist
 + * *pls != NULL => parented Media Playlist, playlist+variant allocated */
 +static int ensure_playlist(HLSContext *c, struct playlist **pls, const char *url)
 +{
 +    if (*pls)
 +        return 0;
 +    if (!new_variant(c, NULL, url, NULL))
 +        return AVERROR(ENOMEM);
 +    *pls = c->playlists[c->n_playlists - 1];
 +    return 0;
 +}
 +
 +static int url_connect(struct playlist *pls, AVDictionary *opts, AVDictionary *opts2)
  {
      AVDictionary *tmp = NULL;
      int ret;
  
      av_dict_copy(&tmp, opts, 0);
 +    av_dict_copy(&tmp, opts2, 0);
 +
 +    if (pls->parent->protocol_whitelist) {
 +        pls->input->protocol_whitelist =  av_strdup(pls->parent->protocol_whitelist);
 +        if (!pls->input->protocol_whitelist) {
 +            av_dict_free(&tmp);
 +            return AVERROR(ENOMEM);
 +        }
 +    }
  
 -    if ((ret = av_opt_set_dict(var->input, &tmp)) < 0 ||
 -        (ret = ffurl_connect(var->input, NULL)) < 0) {
 -        ffurl_close(var->input);
 -        var->input = NULL;
 +    if ((ret = ffurl_connect(pls->input, &tmp)) < 0) {
 +        ffurl_close(pls->input);
 +        pls->input = NULL;
      }
  
      av_dict_free(&tmp);
      return ret;
  }
  
 -static int open_url(HLSContext *c, URLContext **uc, const char *url)
 +static void update_options(char **dest, const char *name, void *src)
 +{
 +    av_freep(dest);
 +    av_opt_get(src, name, 0, (uint8_t**)dest);
 +    if (*dest && !strlen(*dest))
 +        av_freep(dest);
 +}
 +
 +static int open_url(HLSContext *c, URLContext **uc, const char *url, AVDictionary *opts)
  {
      AVDictionary *tmp = NULL;
      int ret;
 +    const char *proto_name = avio_find_protocol_name(url);
 +
 +    if (!proto_name)
 +        return AVERROR_INVALIDDATA;
 +
 +    // only http(s) & file are allowed
 +    if (!av_strstart(proto_name, "http", NULL) && !av_strstart(proto_name, "file", NULL))
 +        return AVERROR_INVALIDDATA;
 +    if (!strncmp(proto_name, url, strlen(proto_name)) && url[strlen(proto_name)] == ':')
 +        ;
 +    else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5))
 +        return AVERROR_INVALIDDATA;
  
      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(uc, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp);
++    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;
 +        update_options(&c->cookies, "cookies", u->priv_data);
 +        av_dict_set(&opts, "cookies", c->cookies, 0);
 +    }
  
      av_dict_free(&tmp);
  
  }
  
  static int parse_playlist(HLSContext *c, const char *url,
 -                          struct variant *var, AVIOContext *in)
 +                          struct playlist *pls, AVIOContext *in)
  {
 -    int ret = 0, is_segment = 0, is_variant = 0, bandwidth = 0;
 +    int ret = 0, is_segment = 0, is_variant = 0;
      int64_t duration = 0;
      enum KeyType key_type = KEY_NONE;
      uint8_t iv[16] = "";
      int has_iv = 0;
      char key[MAX_URL_SIZE] = "";
 -    char line[1024];
 +    char line[MAX_URL_SIZE];
      const char *ptr;
      int close_in = 0;
 +    int64_t seg_offset = 0;
 +    int64_t seg_size = -1;
      uint8_t *new_url = NULL;
 +    struct variant_info variant_info;
 +    char tmp_str[MAX_URL_SIZE];
 +    struct segment *cur_init_section = NULL;
  
      if (!in) {
-         ret = ffio_open_whitelist(&in, url, AVIO_FLAG_READ,
-                          c->interrupt_callback, &opts, c->avfmt->protocol_whitelist);
 +#if 1
 +        AVDictionary *opts = NULL;
 +        close_in = 1;
 +        /* Some HLS servers don't like being sent the range header */
 +        av_dict_set(&opts, "seekable", "0", 0);
 +
 +        // broker prior HTTP options that should be consistent across requests
 +        av_dict_set(&opts, "user-agent", c->user_agent, 0);
 +        av_dict_set(&opts, "cookies", c->cookies, 0);
 +        av_dict_set(&opts, "headers", c->headers, 0);
 +        av_dict_set(&opts, "http_proxy", c->http_proxy, 0);
 +
++        ret = c->ctx->io_open(c->ctx, &in, url, AVIO_FLAG_READ, &opts);
 +        av_dict_free(&opts);
 +        if (ret < 0)
 +            return ret;
 +#else
          ret = open_in(c, &in, url);
          if (ret < 0)
              return ret;
          close_in = 1;
 +#endif
      }
  
      if (av_opt_get(in, "location", AV_OPT_SEARCH_CHILDREN, &new_url) >= 0)
          goto fail;
      }
  
 -    if (var) {
 -        free_segment_list(var);
 -        var->finished = 0;
 +    if (pls) {
 +        free_segment_list(pls);
 +        pls->finished = 0;
 +        pls->type = PLS_TYPE_UNSPECIFIED;
      }
 -    while (!in->eof_reached) {
 +    while (!avio_feof(in)) {
          read_chomp_line(in, line, sizeof(line));
          if (av_strstart(line, "#EXT-X-STREAM-INF:", &ptr)) {
 -            struct variant_info info = {{0}};
              is_variant = 1;
 +            memset(&variant_info, 0, sizeof(variant_info));
              ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_variant_args,
 -                               &info);
 -            bandwidth = atoi(info.bandwidth);
 +                               &variant_info);
          } else if (av_strstart(line, "#EXT-X-KEY:", &ptr)) {
              struct key_info info = {{0}};
              ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_key_args,
              has_iv = 0;
              if (!strcmp(info.method, "AES-128"))
                  key_type = KEY_AES_128;
 +            if (!strcmp(info.method, "SAMPLE-AES"))
 +                key_type = KEY_SAMPLE_AES;
              if (!strncmp(info.iv, "0x", 2) || !strncmp(info.iv, "0X", 2)) {
                  ff_hex_to_data(iv, info.iv + 2);
                  has_iv = 1;
              }
              av_strlcpy(key, info.uri, sizeof(key));
 +        } else if (av_strstart(line, "#EXT-X-MEDIA:", &ptr)) {
 +            struct rendition_info info = {{0}};
 +            ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_rendition_args,
 +                               &info);
 +            new_rendition(c, &info, url);
          } else if (av_strstart(line, "#EXT-X-TARGETDURATION:", &ptr)) {
 -            if (!var) {
 -                var = new_variant(c, 0, url, NULL);
 -                if (!var) {
 -                    ret = AVERROR(ENOMEM);
 -                    goto fail;
 -                }
 -            }
 -            var->target_duration = atoi(ptr) * AV_TIME_BASE;
 +            ret = ensure_playlist(c, &pls, url);
 +            if (ret < 0)
 +                goto fail;
 +            pls->target_duration = atoi(ptr) * AV_TIME_BASE;
          } else if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) {
 -            if (!var) {
 -                var = new_variant(c, 0, url, NULL);
 -                if (!var) {
 -                    ret = AVERROR(ENOMEM);
 -                    goto fail;
 -                }
 -            }
 -            var->start_seq_no = atoi(ptr);
 +            ret = ensure_playlist(c, &pls, url);
 +            if (ret < 0)
 +                goto fail;
 +            pls->start_seq_no = atoi(ptr);
 +        } else if (av_strstart(line, "#EXT-X-PLAYLIST-TYPE:", &ptr)) {
 +            ret = ensure_playlist(c, &pls, url);
 +            if (ret < 0)
 +                goto fail;
 +            if (!strcmp(ptr, "EVENT"))
 +                pls->type = PLS_TYPE_EVENT;
 +            else if (!strcmp(ptr, "VOD"))
 +                pls->type = PLS_TYPE_VOD;
 +        } else if (av_strstart(line, "#EXT-X-MAP:", &ptr)) {
 +            struct init_section_info info = {{0}};
 +            ret = ensure_playlist(c, &pls, url);
 +            if (ret < 0)
 +                goto fail;
 +            ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_init_section_args,
 +                               &info);
 +            cur_init_section = new_init_section(pls, &info, url);
          } else if (av_strstart(line, "#EXT-X-ENDLIST", &ptr)) {
 -            if (var)
 -                var->finished = 1;
 +            if (pls)
 +                pls->finished = 1;
          } else if (av_strstart(line, "#EXTINF:", &ptr)) {
              is_segment = 1;
              duration   = atof(ptr) * AV_TIME_BASE;
 +        } else if (av_strstart(line, "#EXT-X-BYTERANGE:", &ptr)) {
 +            seg_size = atoi(ptr);
 +            ptr = strchr(ptr, '@');
 +            if (ptr)
 +                seg_offset = atoi(ptr+1);
          } else if (av_strstart(line, "#", NULL)) {
              continue;
          } else if (line[0]) {
              if (is_variant) {
 -                if (!new_variant(c, bandwidth, line, url)) {
 +                if (!new_variant(c, &variant_info, line, url)) {
                      ret = AVERROR(ENOMEM);
                      goto fail;
                  }
                  is_variant = 0;
 -                bandwidth  = 0;
              }
              if (is_segment) {
                  struct segment *seg;
 -                if (!var) {
 -                    var = new_variant(c, 0, url, NULL);
 -                    if (!var) {
 +                if (!pls) {
 +                    if (!new_variant(c, 0, url, NULL)) {
                          ret = AVERROR(ENOMEM);
                          goto fail;
                      }
 +                    pls = c->playlists[c->n_playlists - 1];
                  }
                  seg = av_malloc(sizeof(struct segment));
                  if (!seg) {
                  if (has_iv) {
                      memcpy(seg->iv, iv, sizeof(iv));
                  } else {
 -                    int seq = var->start_seq_no + var->n_segments;
 +                    int seq = pls->start_seq_no + pls->n_segments;
                      memset(seg->iv, 0, sizeof(seg->iv));
                      AV_WB32(seg->iv + 12, seq);
                  }
 -                ff_make_absolute_url(seg->key, sizeof(seg->key), url, key);
 -                ff_make_absolute_url(seg->url, sizeof(seg->url), url, line);
 -                dynarray_add(&var->segments, &var->n_segments, seg);
 +
 +                if (key_type != KEY_NONE) {
 +                    ff_make_absolute_url(tmp_str, sizeof(tmp_str), url, key);
 +                    seg->key = av_strdup(tmp_str);
 +                    if (!seg->key) {
 +                        av_free(seg);
 +                        ret = AVERROR(ENOMEM);
 +                        goto fail;
 +                    }
 +                } else {
 +                    seg->key = NULL;
 +                }
 +
 +                ff_make_absolute_url(tmp_str, sizeof(tmp_str), url, line);
 +                seg->url = av_strdup(tmp_str);
 +                if (!seg->url) {
 +                    av_free(seg->key);
 +                    av_free(seg);
 +                    ret = AVERROR(ENOMEM);
 +                    goto fail;
 +                }
 +
 +                dynarray_add(&pls->segments, &pls->n_segments, seg);
                  is_segment = 0;
 +
 +                seg->size = seg_size;
 +                if (seg_size >= 0) {
 +                    seg->url_offset = seg_offset;
 +                    seg_offset += seg_size;
 +                    seg_size = -1;
 +                } else {
 +                    seg->url_offset = 0;
 +                    seg_offset = 0;
 +                }
 +
 +                seg->init_section = cur_init_section;
              }
          }
      }
 -    if (var)
 -        var->last_load_time = av_gettime_relative();
 +    if (pls)
 +        pls->last_load_time = av_gettime_relative();
  
  fail:
      av_free(new_url);
      if (close_in)
-         avio_close(in);
+         ff_format_io_close(c->ctx, &in);
      return ret;
  }
  
 -static int open_input(struct variant *var)
 +static struct segment *current_segment(struct playlist *pls)
  {
 -    struct segment *seg = var->segments[var->cur_seq_no - var->start_seq_no];
 +    return pls->segments[pls->cur_seq_no - pls->start_seq_no];
 +}
 +
 +enum ReadFromURLMode {
 +    READ_NORMAL,
 +    READ_COMPLETE,
 +};
 +
 +/* read from URLContext, limiting read to current segment */
 +static int read_from_url(struct playlist *pls, struct segment *seg,
 +                         uint8_t *buf, int buf_size,
 +                         enum ReadFromURLMode mode)
 +{
 +    int ret;
 +
 +     /* limit read if the segment was only a part of a file */
 +    if (seg->size >= 0)
 +        buf_size = FFMIN(buf_size, seg->size - pls->cur_seg_offset);
 +
 +    if (mode == READ_COMPLETE)
 +        ret = ffurl_read_complete(pls->input, buf, buf_size);
 +    else
 +        ret = ffurl_read(pls->input, buf, buf_size);
 +
 +    if (ret > 0)
 +        pls->cur_seg_offset += ret;
 +
 +    return ret;
 +}
 +
 +/* Parse the raw ID3 data and pass contents to caller */
 +static void parse_id3(AVFormatContext *s, AVIOContext *pb,
 +                      AVDictionary **metadata, int64_t *dts,
 +                      ID3v2ExtraMetaAPIC **apic, ID3v2ExtraMeta **extra_meta)
 +{
 +    static const char id3_priv_owner_ts[] = "com.apple.streaming.transportStreamTimestamp";
 +    ID3v2ExtraMeta *meta;
 +
 +    ff_id3v2_read_dict(pb, metadata, ID3v2_DEFAULT_MAGIC, extra_meta);
 +    for (meta = *extra_meta; meta; meta = meta->next) {
 +        if (!strcmp(meta->tag, "PRIV")) {
 +            ID3v2ExtraMetaPRIV *priv = meta->data;
 +            if (priv->datasize == 8 && !strcmp(priv->owner, id3_priv_owner_ts)) {
 +                /* 33-bit MPEG timestamp */
 +                int64_t ts = AV_RB64(priv->data);
 +                av_log(s, AV_LOG_DEBUG, "HLS ID3 audio timestamp %"PRId64"\n", ts);
 +                if ((ts & ~((1ULL << 33) - 1)) == 0)
 +                    *dts = ts;
 +                else
 +                    av_log(s, AV_LOG_ERROR, "Invalid HLS ID3 audio timestamp %"PRId64"\n", ts);
 +            }
 +        } else if (!strcmp(meta->tag, "APIC") && apic)
 +            *apic = meta->data;
 +    }
 +}
 +
 +/* Check if the ID3 metadata contents have changed */
 +static int id3_has_changed_values(struct playlist *pls, AVDictionary *metadata,
 +                                  ID3v2ExtraMetaAPIC *apic)
 +{
 +    AVDictionaryEntry *entry = NULL;
 +    AVDictionaryEntry *oldentry;
 +    /* check that no keys have changed values */
 +    while ((entry = av_dict_get(metadata, "", entry, AV_DICT_IGNORE_SUFFIX))) {
 +        oldentry = av_dict_get(pls->id3_initial, entry->key, NULL, AV_DICT_MATCH_CASE);
 +        if (!oldentry || strcmp(oldentry->value, entry->value) != 0)
 +            return 1;
 +    }
 +
 +    /* check if apic appeared */
 +    if (apic && (pls->ctx->nb_streams != 2 || !pls->ctx->streams[1]->attached_pic.data))
 +        return 1;
 +
 +    if (apic) {
 +        int size = pls->ctx->streams[1]->attached_pic.size;
 +        if (size != apic->buf->size - AV_INPUT_BUFFER_PADDING_SIZE)
 +            return 1;
 +
 +        if (memcmp(apic->buf->data, pls->ctx->streams[1]->attached_pic.data, size) != 0)
 +            return 1;
 +    }
 +
 +    return 0;
 +}
 +
 +/* Parse ID3 data and handle the found data */
 +static void handle_id3(AVIOContext *pb, struct playlist *pls)
 +{
 +    AVDictionary *metadata = NULL;
 +    ID3v2ExtraMetaAPIC *apic = NULL;
 +    ID3v2ExtraMeta *extra_meta = NULL;
 +    int64_t timestamp = AV_NOPTS_VALUE;
 +
 +    parse_id3(pls->ctx, pb, &metadata, &timestamp, &apic, &extra_meta);
 +
 +    if (timestamp != AV_NOPTS_VALUE) {
 +        pls->id3_mpegts_timestamp = timestamp;
 +        pls->id3_offset = 0;
 +    }
 +
 +    if (!pls->id3_found) {
 +        /* initial ID3 tags */
 +        av_assert0(!pls->id3_deferred_extra);
 +        pls->id3_found = 1;
 +
 +        /* get picture attachment and set text metadata */
 +        if (pls->ctx->nb_streams)
 +            ff_id3v2_parse_apic(pls->ctx, &extra_meta);
 +        else
 +            /* demuxer not yet opened, defer picture attachment */
 +            pls->id3_deferred_extra = extra_meta;
 +
 +        av_dict_copy(&pls->ctx->metadata, metadata, 0);
 +        pls->id3_initial = metadata;
 +
 +    } else {
 +        if (!pls->id3_changed && id3_has_changed_values(pls, metadata, apic)) {
 +            avpriv_report_missing_feature(pls->ctx, "Changing ID3 metadata in HLS audio elementary stream");
 +            pls->id3_changed = 1;
 +        }
 +        av_dict_free(&metadata);
 +    }
 +
 +    if (!pls->id3_deferred_extra)
 +        ff_id3v2_free_extra_meta(&extra_meta);
 +}
 +
 +/* Intercept and handle ID3 tags between URLContext and AVIOContext */
 +static void intercept_id3(struct playlist *pls, uint8_t *buf,
 +                         int buf_size, int *len)
 +{
 +    /* intercept id3 tags, we do not want to pass them to the raw
 +     * demuxer on all segment switches */
 +    int bytes;
 +    int id3_buf_pos = 0;
 +    int fill_buf = 0;
 +    struct segment *seg = current_segment(pls);
 +
 +    /* gather all the id3 tags */
 +    while (1) {
 +        /* see if we can retrieve enough data for ID3 header */
 +        if (*len < ID3v2_HEADER_SIZE && buf_size >= ID3v2_HEADER_SIZE) {
 +            bytes = read_from_url(pls, seg, buf + *len, ID3v2_HEADER_SIZE - *len, READ_COMPLETE);
 +            if (bytes > 0) {
 +
 +                if (bytes == ID3v2_HEADER_SIZE - *len)
 +                    /* no EOF yet, so fill the caller buffer again after
 +                     * we have stripped the ID3 tags */
 +                    fill_buf = 1;
 +
 +                *len += bytes;
 +
 +            } else if (*len <= 0) {
 +                /* error/EOF */
 +                *len = bytes;
 +                fill_buf = 0;
 +            }
 +        }
 +
 +        if (*len < ID3v2_HEADER_SIZE)
 +            break;
 +
 +        if (ff_id3v2_match(buf, ID3v2_DEFAULT_MAGIC)) {
 +            int64_t maxsize = seg->size >= 0 ? seg->size : 1024*1024;
 +            int taglen = ff_id3v2_tag_len(buf);
 +            int tag_got_bytes = FFMIN(taglen, *len);
 +            int remaining = taglen - tag_got_bytes;
 +
 +            if (taglen > maxsize) {
 +                av_log(pls->ctx, AV_LOG_ERROR, "Too large HLS ID3 tag (%d > %"PRId64" bytes)\n",
 +                       taglen, maxsize);
 +                break;
 +            }
 +
 +            /*
 +             * Copy the id3 tag to our temporary id3 buffer.
 +             * We could read a small id3 tag directly without memcpy, but
 +             * we would still need to copy the large tags, and handling
 +             * both of those cases together with the possibility for multiple
 +             * tags would make the handling a bit complex.
 +             */
 +            pls->id3_buf = av_fast_realloc(pls->id3_buf, &pls->id3_buf_size, id3_buf_pos + taglen);
 +            if (!pls->id3_buf)
 +                break;
 +            memcpy(pls->id3_buf + id3_buf_pos, buf, tag_got_bytes);
 +            id3_buf_pos += tag_got_bytes;
 +
 +            /* strip the intercepted bytes */
 +            *len -= tag_got_bytes;
 +            memmove(buf, buf + tag_got_bytes, *len);
 +            av_log(pls->ctx, AV_LOG_DEBUG, "Stripped %d HLS ID3 bytes\n", tag_got_bytes);
 +
 +            if (remaining > 0) {
 +                /* read the rest of the tag in */
 +                if (read_from_url(pls, seg, pls->id3_buf + id3_buf_pos, remaining, READ_COMPLETE) != remaining)
 +                    break;
 +                id3_buf_pos += remaining;
 +                av_log(pls->ctx, AV_LOG_DEBUG, "Stripped additional %d HLS ID3 bytes\n", remaining);
 +            }
 +
 +        } else {
 +            /* no more ID3 tags */
 +            break;
 +        }
 +    }
 +
 +    /* re-fill buffer for the caller unless EOF */
 +    if (*len >= 0 && (fill_buf || *len == 0)) {
 +        bytes = read_from_url(pls, seg, buf + *len, buf_size - *len, READ_NORMAL);
 +
 +        /* ignore error if we already had some data */
 +        if (bytes >= 0)
 +            *len += bytes;
 +        else if (*len == 0)
 +            *len = bytes;
 +    }
 +
 +    if (pls->id3_buf) {
 +        /* Now parse all the ID3 tags */
 +        AVIOContext id3ioctx;
 +        ffio_init_context(&id3ioctx, pls->id3_buf, id3_buf_pos, 0, NULL, NULL, NULL, NULL);
 +        handle_id3(&id3ioctx, pls);
 +    }
 +
 +    if (pls->is_id3_timestamped == -1)
 +        pls->is_id3_timestamped = (pls->id3_mpegts_timestamp != AV_NOPTS_VALUE);
 +}
 +
 +static int open_input(HLSContext *c, struct playlist *pls, struct segment *seg)
 +{
 +    AVDictionary *opts = NULL;
 +    int ret;
 +
 +    // broker prior HTTP options that should be consistent across requests
 +    av_dict_set(&opts, "user-agent", c->user_agent, 0);
 +    av_dict_set(&opts, "cookies", c->cookies, 0);
 +    av_dict_set(&opts, "headers", c->headers, 0);
 +    av_dict_set(&opts, "http_proxy", c->http_proxy, 0);
 +    av_dict_set(&opts, "seekable", "0", 0);
 +
 +    if (seg->size >= 0) {
 +        /* try to restrict the HTTP request to the part we want
 +         * (if this is in fact a HTTP request) */
 +        av_dict_set_int(&opts, "offset", seg->url_offset, 0);
 +        av_dict_set_int(&opts, "end_offset", seg->url_offset + seg->size, 0);
 +    }
 +
 +    av_log(pls->parent, AV_LOG_VERBOSE, "HLS request for url '%s', offset %"PRId64", playlist %d\n",
 +           seg->url, seg->url_offset, pls->index);
 +
      if (seg->key_type == KEY_NONE) {
 -        return  open_url(var->parent->priv_data, &var->input, seg->url);
 +        ret = open_url(pls->parent->priv_data, &pls->input, seg->url, opts);
      } else if (seg->key_type == KEY_AES_128) {
 -        HLSContext *c = var->parent->priv_data;
 +//         HLSContext *c = var->parent->priv_data;
          char iv[33], key[33], url[MAX_URL_SIZE];
 -        int ret;
 -        if (strcmp(seg->key, var->key_url)) {
 +        if (strcmp(seg->key, pls->key_url)) {
              URLContext *uc;
 -            if (open_url(var->parent->priv_data, &uc, seg->key) == 0) {
 -                if (ffurl_read_complete(uc, var->key, sizeof(var->key))
 -                    != sizeof(var->key)) {
 +            if (open_url(pls->parent->priv_data, &uc, seg->key, opts) == 0) {
 +                if (ffurl_read_complete(uc, pls->key, sizeof(pls->key))
 +                    != sizeof(pls->key)) {
                      av_log(NULL, AV_LOG_ERROR, "Unable to read key file %s\n",
                             seg->key);
                  }
                  av_log(NULL, AV_LOG_ERROR, "Unable to open key file %s\n",
                         seg->key);
              }
 -            av_strlcpy(var->key_url, seg->key, sizeof(var->key_url));
 +            av_strlcpy(pls->key_url, seg->key, sizeof(pls->key_url));
          }
          ff_data_to_hex(iv, seg->iv, sizeof(seg->iv), 0);
 -        ff_data_to_hex(key, var->key, sizeof(var->key), 0);
 +        ff_data_to_hex(key, pls->key, sizeof(pls->key), 0);
          iv[32] = key[32] = '\0';
          if (strstr(seg->url, "://"))
              snprintf(url, sizeof(url), "crypto+%s", seg->url);
          else
              snprintf(url, sizeof(url), "crypto:%s", seg->url);
 -        if ((ret = ffurl_alloc(&var->input, url, AVIO_FLAG_READ,
 -                               &var->parent->interrupt_callback)) < 0)
 -            return ret;
 -        av_opt_set(var->input->priv_data, "key", key, 0);
 -        av_opt_set(var->input->priv_data, "iv", iv, 0);
  
 -        return url_connect(var, c->avio_opts);
 +        if ((ret = ffurl_alloc(&pls->input, url, AVIO_FLAG_READ,
 +                               &pls->parent->interrupt_callback)) < 0)
 +            goto cleanup;
 +        av_opt_set(pls->input->priv_data, "key", key, 0);
 +        av_opt_set(pls->input->priv_data, "iv", iv, 0);
 +
 +        if ((ret = url_connect(pls, c->avio_opts, opts)) < 0) {
 +            goto cleanup;
 +        }
 +        ret = 0;
 +    } else if (seg->key_type == KEY_SAMPLE_AES) {
 +        av_log(pls->parent, AV_LOG_ERROR,
 +               "SAMPLE-AES encryption is not supported yet\n");
 +        ret = AVERROR_PATCHWELCOME;
 +    }
 +    else
 +      ret = AVERROR(ENOSYS);
 +
 +    /* Seek to the requested position. If this was a HTTP request, the offset
 +     * should already be where want it to, but this allows e.g. local testing
 +     * without a HTTP server. */
 +    if (ret == 0 && seg->key_type == KEY_NONE && seg->url_offset) {
 +        int seekret = ffurl_seek(pls->input, seg->url_offset, SEEK_SET);
 +        if (seekret < 0) {
 +            av_log(pls->parent, AV_LOG_ERROR, "Unable to seek to offset %"PRId64" of HLS segment '%s'\n", seg->url_offset, seg->url);
 +            ret = seekret;
 +            ffurl_close(pls->input);
 +            pls->input = NULL;
 +        }
 +    }
 +
 +cleanup:
 +    av_dict_free(&opts);
 +    pls->cur_seg_offset = 0;
 +    return ret;
 +}
 +
 +static int update_init_section(struct playlist *pls, struct segment *seg)
 +{
 +    static const int max_init_section_size = 1024*1024;
 +    HLSContext *c = pls->parent->priv_data;
 +    int64_t sec_size;
 +    int64_t urlsize;
 +    int ret;
 +
 +    if (seg->init_section == pls->cur_init_section)
 +        return 0;
 +
 +    pls->cur_init_section = NULL;
 +
 +    if (!seg->init_section)
 +        return 0;
 +
 +    /* this will clobber playlist URLContext stuff, so this should be
 +     * called between segments only */
 +    ret = open_input(c, pls, seg->init_section);
 +    if (ret < 0) {
 +        av_log(pls->parent, AV_LOG_WARNING,
 +               "Failed to open an initialization section in playlist %d\n",
 +               pls->index);
 +        return ret;
      }
 -    return AVERROR(ENOSYS);
 +
 +    if (seg->init_section->size >= 0)
 +        sec_size = seg->init_section->size;
 +    else if ((urlsize = ffurl_size(pls->input)) >= 0)
 +        sec_size = urlsize;
 +    else
 +        sec_size = max_init_section_size;
 +
 +    av_log(pls->parent, AV_LOG_DEBUG,
 +           "Downloading an initialization section of size %"PRId64"\n",
 +           sec_size);
 +
 +    sec_size = FFMIN(sec_size, max_init_section_size);
 +
 +    av_fast_malloc(&pls->init_sec_buf, &pls->init_sec_buf_size, sec_size);
 +
 +    ret = read_from_url(pls, seg->init_section, pls->init_sec_buf,
 +                        pls->init_sec_buf_size, READ_COMPLETE);
 +    ffurl_close(pls->input);
 +    pls->input = NULL;
 +
 +    if (ret < 0)
 +        return ret;
 +
 +    pls->cur_init_section = seg->init_section;
 +    pls->init_sec_data_len = ret;
 +    pls->init_sec_buf_read_offset = 0;
 +
 +    /* spec says audio elementary streams do not have media initialization
 +     * sections, so there should be no ID3 timestamps */
 +    pls->is_id3_timestamped = 0;
 +
 +    return 0;
 +}
 +
 +static int64_t default_reload_interval(struct playlist *pls)
 +{
 +    return pls->n_segments > 0 ?
 +                          pls->segments[pls->n_segments - 1]->duration :
 +                          pls->target_duration;
  }
  
  static int read_data(void *opaque, uint8_t *buf, int buf_size)
  {
 -    struct variant *v = opaque;
 +    struct playlist *v = opaque;
      HLSContext *c = v->parent->priv_data;
      int ret, i;
 +    int just_opened = 0;
  
  restart:
 +    if (!v->needed)
 +        return AVERROR_EOF;
 +
      if (!v->input) {
 +        int64_t reload_interval;
 +        struct segment *seg;
 +
 +        /* Check that the playlist is still needed before opening a new
 +         * segment. */
 +        if (v->ctx && v->ctx->nb_streams &&
 +            v->parent->nb_streams >= v->stream_offset + v->ctx->nb_streams) {
 +            v->needed = 0;
 +            for (i = v->stream_offset; i < v->stream_offset + v->ctx->nb_streams;
 +                i++) {
 +                if (v->parent->streams[i]->discard < AVDISCARD_ALL)
 +                    v->needed = 1;
 +            }
 +        }
 +        if (!v->needed) {
 +            av_log(v->parent, AV_LOG_INFO, "No longer receiving playlist %d\n",
 +                v->index);
 +            return AVERROR_EOF;
 +        }
 +
          /* If this is a live stream and the reload interval has elapsed since
 -         * the last playlist reload, reload the variant playlists now. */
 -        int64_t reload_interval = v->n_segments > 0 ?
 -                                  v->segments[v->n_segments - 1]->duration :
 -                                  v->target_duration;
 +         * the last playlist reload, reload the playlists now. */
 +        reload_interval = default_reload_interval(v);
  
  reload:
          if (!v->finished &&
              av_gettime_relative() - v->last_load_time >= reload_interval) {
 -            if ((ret = parse_playlist(c, v->url, v, NULL)) < 0)
 +            if ((ret = parse_playlist(c, v->url, v, NULL)) < 0) {
 +                av_log(v->parent, AV_LOG_WARNING, "Failed to reload playlist %d\n",
 +                       v->index);
                  return ret;
 +            }
              /* If we need to reload the playlist again below (if
               * there's still no more segments), switch to a reload
               * interval of half the target duration. */
              goto reload;
          }
  
 -        ret = open_input(v);
 -        if (ret < 0)
 +        seg = current_segment(v);
 +
 +        /* load/update Media Initialization Section, if any */
 +        ret = update_init_section(v, seg);
 +        if (ret)
              return ret;
 +
 +        ret = open_input(c, v, seg);
 +        if (ret < 0) {
 +            if (ff_check_interrupt(c->interrupt_callback))
 +                return AVERROR_EXIT;
 +            av_log(v->parent, AV_LOG_WARNING, "Failed to open segment of playlist %d\n",
 +                   v->index);
 +            v->cur_seq_no += 1;
 +            goto reload;
 +        }
 +        just_opened = 1;
      }
 -    ret = ffurl_read(v->input, buf, buf_size);
 -    if (ret > 0)
 +
 +    if (v->init_sec_buf_read_offset < v->init_sec_data_len) {
 +        /* Push init section out first before first actual segment */
 +        int copy_size = FFMIN(v->init_sec_data_len - v->init_sec_buf_read_offset, buf_size);
 +        memcpy(buf, v->init_sec_buf, copy_size);
 +        v->init_sec_buf_read_offset += copy_size;
 +        return copy_size;
 +    }
 +
 +    ret = read_from_url(v, current_segment(v), buf, buf_size, READ_NORMAL);
 +    if (ret > 0) {
 +        if (just_opened && v->is_id3_timestamped != 0) {
 +            /* Intercept ID3 tags here, elementary audio streams are required
 +             * to convey timestamps using them in the beginning of each segment. */
 +            intercept_id3(v, buf, buf_size, &ret);
 +        }
 +
          return ret;
 +    }
      ffurl_close(v->input);
      v->input = NULL;
      v->cur_seq_no++;
  
 -    c->end_of_segment = 1;
      c->cur_seq_no = v->cur_seq_no;
  
 -    if (v->ctx && v->ctx->nb_streams &&
 -        v->parent->nb_streams >= v->stream_offset + v->ctx->nb_streams) {
 -        v->needed = 0;
 -        for (i = v->stream_offset; i < v->stream_offset + v->ctx->nb_streams;
 -             i++) {
 -            if (v->parent->streams[i]->discard < AVDISCARD_ALL)
 -                v->needed = 1;
 +    goto restart;
 +}
 +
 +static int playlist_in_multiple_variants(HLSContext *c, struct playlist *pls)
 +{
 +    int variant_count = 0;
 +    int i, j;
 +
 +    for (i = 0; i < c->n_variants && variant_count < 2; i++) {
 +        struct variant *v = c->variants[i];
 +
 +        for (j = 0; j < v->n_playlists; j++) {
 +            if (v->playlists[j] == pls) {
 +                variant_count++;
 +                break;
 +            }
          }
      }
 -    if (!v->needed) {
 -        av_log(v->parent, AV_LOG_INFO, "No longer receiving variant %d\n",
 -               v->index);
 -        return AVERROR_EOF;
 +
 +    return variant_count >= 2;
 +}
 +
 +static void add_renditions_to_variant(HLSContext *c, struct variant *var,
 +                                      enum AVMediaType type, const char *group_id)
 +{
 +    int i;
 +
 +    for (i = 0; i < c->n_renditions; i++) {
 +        struct rendition *rend = c->renditions[i];
 +
 +        if (rend->type == type && !strcmp(rend->group_id, group_id)) {
 +
 +            if (rend->playlist)
 +                /* rendition is an external playlist
 +                 * => add the playlist to the variant */
 +                dynarray_add(&var->playlists, &var->n_playlists, rend->playlist);
 +            else
 +                /* rendition is part of the variant main Media Playlist
 +                 * => add the rendition to the main Media Playlist */
 +                dynarray_add(&var->playlists[0]->renditions,
 +                             &var->playlists[0]->n_renditions,
 +                             rend);
 +        }
      }
 -    goto restart;
 +}
 +
 +static void add_metadata_from_renditions(AVFormatContext *s, struct playlist *pls,
 +                                         enum AVMediaType type)
 +{
 +    int rend_idx = 0;
 +    int i;
 +
 +    for (i = 0; i < pls->ctx->nb_streams; i++) {
 +        AVStream *st = s->streams[pls->stream_offset + i];
 +
 +        if (st->codec->codec_type != type)
 +            continue;
 +
 +        for (; rend_idx < pls->n_renditions; rend_idx++) {
 +            struct rendition *rend = pls->renditions[rend_idx];
 +
 +            if (rend->type != type)
 +                continue;
 +
 +            if (rend->language[0])
 +                av_dict_set(&st->metadata, "language", rend->language, 0);
 +            if (rend->name[0])
 +                av_dict_set(&st->metadata, "comment", rend->name, 0);
 +
 +            st->disposition |= rend->disposition;
 +        }
 +        if (rend_idx >=pls->n_renditions)
 +            break;
 +    }
 +}
 +
 +/* if timestamp was in valid range: returns 1 and sets seq_no
 + * if not: returns 0 and sets seq_no to closest segment */
 +static int find_timestamp_in_playlist(HLSContext *c, struct playlist *pls,
 +                                      int64_t timestamp, int *seq_no)
 +{
 +    int i;
 +    int64_t pos = c->first_timestamp == AV_NOPTS_VALUE ?
 +                  0 : c->first_timestamp;
 +
 +    if (timestamp < pos) {
 +        *seq_no = pls->start_seq_no;
 +        return 0;
 +    }
 +
 +    for (i = 0; i < pls->n_segments; i++) {
 +        int64_t diff = pos + pls->segments[i]->duration - timestamp;
 +        if (diff > 0) {
 +            *seq_no = pls->start_seq_no + i;
 +            return 1;
 +        }
 +        pos += pls->segments[i]->duration;
 +    }
 +
 +    *seq_no = pls->start_seq_no + pls->n_segments - 1;
 +
 +    return 0;
 +}
 +
 +static int select_cur_seq_no(HLSContext *c, struct playlist *pls)
 +{
 +    int seq_no;
 +
 +    if (!pls->finished && !c->first_packet &&
 +        av_gettime_relative() - pls->last_load_time >= default_reload_interval(pls))
 +        /* reload the playlist since it was suspended */
 +        parse_playlist(c, pls->url, pls, NULL);
 +
 +    /* If playback is already in progress (we are just selecting a new
 +     * playlist) and this is a complete file, find the matching segment
 +     * by counting durations. */
 +    if (pls->finished && c->cur_timestamp != AV_NOPTS_VALUE) {
 +        find_timestamp_in_playlist(c, pls, c->cur_timestamp, &seq_no);
 +        return seq_no;
 +    }
 +
 +    if (!pls->finished) {
 +        if (!c->first_packet && /* we are doing a segment selection during playback */
 +            c->cur_seq_no >= pls->start_seq_no &&
 +            c->cur_seq_no < pls->start_seq_no + pls->n_segments)
 +            /* While spec 3.4.3 says that we cannot assume anything about the
 +             * content at the same sequence number on different playlists,
 +             * in practice this seems to work and doing it otherwise would
 +             * require us to download a segment to inspect its timestamps. */
 +            return c->cur_seq_no;
 +
 +        /* If this is a live stream, start live_start_index segments from the
 +         * start or end */
 +        if (c->live_start_index < 0)
 +            return pls->start_seq_no + FFMAX(pls->n_segments + c->live_start_index, 0);
 +        else
 +            return pls->start_seq_no + FFMIN(c->live_start_index, pls->n_segments - 1);
 +    }
 +
 +    /* Otherwise just start on the first segment. */
 +    return pls->start_seq_no;
  }
  
  static int save_avio_options(AVFormatContext *s)
  {
      HLSContext *c = s->priv_data;
 -    const char *opts[] = { "headers", "user_agent", NULL }, **opt = opts;
 +    const char *opts[] = {
 +        "headers", "http_proxy", "user_agent", "user-agent", "cookies", NULL };
 +    const char **opt = opts;
      uint8_t *buf;
      int ret = 0;
  
      while (*opt) {
 -        if (av_opt_get(s->pb, *opt, AV_OPT_SEARCH_CHILDREN, &buf) >= 0) {
 +        if (av_opt_get(s->pb, *opt, AV_OPT_SEARCH_CHILDREN | AV_OPT_ALLOW_NULL, &buf) >= 0) {
              ret = av_dict_set(&c->avio_opts, *opt, buf,
                                AV_DICT_DONT_STRDUP_VAL);
              if (ret < 0)
  
  static int hls_read_header(AVFormatContext *s)
  {
 +    URLContext *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb->opaque;
      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;
 +
 +    c->first_packet = 1;
 +    c->first_timestamp = AV_NOPTS_VALUE;
 +    c->cur_timestamp = AV_NOPTS_VALUE;
 +
 +    // if the URL context is good, read important options we must broker later
 +    if (u && u->prot->priv_data_class) {
 +        // get the previous user agent & set back to null if string size is zero
 +        update_options(&c->user_agent, "user-agent", u->priv_data);
 +
 +        // get the previous cookies & set back to null if string size is zero
 +        update_options(&c->cookies, "cookies", u->priv_data);
 +
 +        // get the previous headers & set back to null if string size is zero
 +        update_options(&c->headers, "headers", u->priv_data);
 +
 +        // get the previous http proxt & set back to null if string size is zero
 +        update_options(&c->http_proxy, "http_proxy", u->priv_data);
 +    }
  
      if ((ret = parse_playlist(c, s->filename, NULL, s->pb)) < 0)
          goto fail;
      if ((ret = save_avio_options(s)) < 0)
          goto fail;
  
 +    /* Some HLS servers don't like being sent the range header */
 +    av_dict_set(&c->avio_opts, "seekable", "0", 0);
 +
      if (c->n_variants == 0) {
          av_log(NULL, AV_LOG_WARNING, "Empty playlist\n");
          ret = AVERROR_EOF;
          goto fail;
      }
 -    /* If the playlist only contained variants, parse each individual
 -     * variant playlist. */
 -    if (c->n_variants > 1 || c->variants[0]->n_segments == 0) {
 -        for (i = 0; i < c->n_variants; i++) {
 -            struct variant *v = c->variants[i];
 -            if ((ret = parse_playlist(c, v->url, v, NULL)) < 0)
 +    /* If the playlist only contained playlists (Master Playlist),
 +     * parse each individual playlist. */
 +    if (c->n_playlists > 1 || c->playlists[0]->n_segments == 0) {
 +        for (i = 0; i < c->n_playlists; i++) {
 +            struct playlist *pls = c->playlists[i];
 +            if ((ret = parse_playlist(c, pls->url, pls, NULL)) < 0)
                  goto fail;
          }
      }
  
 -    if (c->variants[0]->n_segments == 0) {
 +    if (c->variants[0]->playlists[0]->n_segments == 0) {
          av_log(NULL, AV_LOG_WARNING, "Empty playlist\n");
          ret = AVERROR_EOF;
          goto fail;
  
      /* If this isn't a live stream, calculate the total duration of the
       * stream. */
 -    if (c->variants[0]->finished) {
 +    if (c->variants[0]->playlists[0]->finished) {
          int64_t duration = 0;
 -        for (i = 0; i < c->variants[0]->n_segments; i++)
 -            duration += c->variants[0]->segments[i]->duration;
 +        for (i = 0; i < c->variants[0]->playlists[0]->n_segments; i++)
 +            duration += c->variants[0]->playlists[0]->segments[i]->duration;
          s->duration = duration;
      }
  
 -    /* Open the demuxer for each variant */
 +    /* Associate renditions with variants */
      for (i = 0; i < c->n_variants; i++) {
 -        struct variant *v = c->variants[i];
 -        AVInputFormat *in_fmt = NULL;
 -        char bitrate_str[20];
 -        AVProgram *program;
 +        struct variant *var = c->variants[i];
  
 -        if (v->n_segments == 0)
 -            continue;
 +        if (var->audio_group[0])
 +            add_renditions_to_variant(c, var, AVMEDIA_TYPE_AUDIO, var->audio_group);
 +        if (var->video_group[0])
 +            add_renditions_to_variant(c, var, AVMEDIA_TYPE_VIDEO, var->video_group);
 +        if (var->subtitles_group[0])
 +            add_renditions_to_variant(c, var, AVMEDIA_TYPE_SUBTITLE, var->subtitles_group);
 +    }
 +
 +    /* Open the demuxer for each playlist */
 +    for (i = 0; i < c->n_playlists; i++) {
 +        struct playlist *pls = c->playlists[i];
 +        AVInputFormat *in_fmt = NULL;
  
 -        if (!(v->ctx = avformat_alloc_context())) {
 +        if (!(pls->ctx = avformat_alloc_context())) {
              ret = AVERROR(ENOMEM);
              goto fail;
          }
  
 -        v->index  = i;
 -        v->needed = 1;
 -        v->parent = s;
 +        if (pls->n_segments == 0)
 +            continue;
  
 -        /* If this is a live stream with more than 3 segments, start at the
 -         * third last segment. */
 -        v->cur_seq_no = v->start_seq_no;
 -        if (!v->finished && v->n_segments > 3)
 -            v->cur_seq_no = v->start_seq_no + v->n_segments - 3;
 +        pls->index  = i;
 +        pls->needed = 1;
 +        pls->parent = s;
 +        pls->cur_seq_no = select_cur_seq_no(c, pls);
  
 -        v->read_buffer = av_malloc(INITIAL_BUFFER_SIZE);
 -        ffio_init_context(&v->pb, v->read_buffer, INITIAL_BUFFER_SIZE, 0, v,
 +        pls->read_buffer = av_malloc(INITIAL_BUFFER_SIZE);
 +        if (!pls->read_buffer){
 +            ret = AVERROR(ENOMEM);
 +            avformat_free_context(pls->ctx);
 +            pls->ctx = NULL;
 +            goto fail;
 +        }
 +        ffio_init_context(&pls->pb, pls->read_buffer, INITIAL_BUFFER_SIZE, 0, pls,
                            read_data, NULL, NULL);
 -        v->pb.seekable = 0;
 -        ret = av_probe_input_buffer(&v->pb, &in_fmt, v->segments[0]->url,
 +        pls->pb.seekable = 0;
 +        ret = av_probe_input_buffer(&pls->pb, &in_fmt, pls->segments[0]->url,
                                      NULL, 0, 0);
          if (ret < 0) {
              /* Free the ctx - it isn't initialized properly at this point,
               * so avformat_close_input shouldn't be called. If
               * avformat_open_input fails below, it frees and zeros the
               * context, so it doesn't need any special treatment like this. */
 -            avformat_free_context(v->ctx);
 -            v->ctx = NULL;
 +            av_log(s, AV_LOG_ERROR, "Error when loading first segment '%s'\n", pls->segments[0]->url);
 +            avformat_free_context(pls->ctx);
 +            pls->ctx = NULL;
              goto fail;
          }
 -        v->ctx->pb       = &v->pb;
 -        v->stream_offset = stream_offset;
 -        ret = avformat_open_input(&v->ctx, v->segments[0]->url, in_fmt, NULL);
 -        if (ret < 0)
 +        pls->ctx->pb       = &pls->pb;
 +        pls->stream_offset = stream_offset;
 +
 +        if ((ret = ff_copy_whitelists(pls->ctx, s)) < 0)
              goto fail;
  
 -        v->ctx->ctx_flags &= ~AVFMTCTX_NOHEADER;
 -        ret = avformat_find_stream_info(v->ctx, NULL);
 +        ret = avformat_open_input(&pls->ctx, pls->segments[0]->url, in_fmt, NULL);
          if (ret < 0)
              goto fail;
 -        snprintf(bitrate_str, sizeof(bitrate_str), "%d", v->bandwidth);
  
 -        program = av_new_program(s, i);
 -        if (!program)
 +        if (pls->id3_deferred_extra && pls->ctx->nb_streams == 1) {
 +            ff_id3v2_parse_apic(pls->ctx, &pls->id3_deferred_extra);
 +            avformat_queue_attached_pictures(pls->ctx);
 +            ff_id3v2_free_extra_meta(&pls->id3_deferred_extra);
 +            pls->id3_deferred_extra = NULL;
 +        }
 +
 +        pls->ctx->ctx_flags &= ~AVFMTCTX_NOHEADER;
 +        ret = avformat_find_stream_info(pls->ctx, NULL);
 +        if (ret < 0)
              goto fail;
 -        av_dict_set(&program->metadata, "variant_bitrate", bitrate_str, 0);
  
 -        /* Create new AVStreams for each stream in this variant */
 -        for (j = 0; j < v->ctx->nb_streams; j++) {
 +        if (pls->is_id3_timestamped == -1)
 +            av_log(s, AV_LOG_WARNING, "No expected HTTP requests have been made\n");
 +
 +        /* Create new AVStreams for each stream in this playlist */
 +        for (j = 0; j < pls->ctx->nb_streams; j++) {
              AVStream *st = avformat_new_stream(s, NULL);
 -            AVStream *ist = v->ctx->streams[j];
 +            AVStream *ist = pls->ctx->streams[j];
              if (!st) {
                  ret = AVERROR(ENOMEM);
                  goto fail;
              }
 -            ff_program_add_stream_index(s, i, stream_offset + j);
              st->id = i;
 -            avpriv_set_pts_info(st, ist->pts_wrap_bits, ist->time_base.num, ist->time_base.den);
 -            avcodec_copy_context(st->codec, v->ctx->streams[j]->codec);
 -            if (v->bandwidth)
 -                av_dict_set(&st->metadata, "variant_bitrate", bitrate_str,
 -                                 0);
 +
 +            avcodec_copy_context(st->codec, pls->ctx->streams[j]->codec);
 +
 +            if (pls->is_id3_timestamped) /* custom timestamps via id3 */
 +                avpriv_set_pts_info(st, 33, 1, MPEG_TIME_BASE);
 +            else
 +                avpriv_set_pts_info(st, ist->pts_wrap_bits, ist->time_base.num, ist->time_base.den);
          }
 -        stream_offset += v->ctx->nb_streams;
 +
 +        add_metadata_from_renditions(s, pls, AVMEDIA_TYPE_AUDIO);
 +        add_metadata_from_renditions(s, pls, AVMEDIA_TYPE_VIDEO);
 +        add_metadata_from_renditions(s, pls, AVMEDIA_TYPE_SUBTITLE);
 +
 +        stream_offset += pls->ctx->nb_streams;
      }
  
 -    c->first_packet = 1;
 -    c->first_timestamp = AV_NOPTS_VALUE;
 -    c->seek_timestamp  = AV_NOPTS_VALUE;
 +    /* Create a program for each variant */
 +    for (i = 0; i < c->n_variants; i++) {
 +        struct variant *v = c->variants[i];
 +        AVProgram *program;
 +
 +        program = av_new_program(s, i);
 +        if (!program)
 +            goto fail;
 +        av_dict_set_int(&program->metadata, "variant_bitrate", v->bandwidth, 0);
 +
 +        for (j = 0; j < v->n_playlists; j++) {
 +            struct playlist *pls = v->playlists[j];
 +            int is_shared = playlist_in_multiple_variants(c, pls);
 +            int k;
 +
 +            for (k = 0; k < pls->ctx->nb_streams; k++) {
 +                struct AVStream *st = s->streams[pls->stream_offset + k];
 +
 +                av_program_add_stream_index(s, i, pls->stream_offset + k);
 +
 +                /* Set variant_bitrate for streams unique to this variant */
 +                if (!is_shared && v->bandwidth)
 +                    av_dict_set_int(&st->metadata, "variant_bitrate", v->bandwidth, 0);
 +            }
 +        }
 +    }
  
      return 0;
  fail:
 +    free_playlist_list(c);
      free_variant_list(c);
 +    free_rendition_list(c);
      return ret;
  }
  
@@@ -1723,172 -646,127 +1722,172 @@@ static int recheck_discard_flags(AVForm
      int i, changed = 0;
  
      /* Check if any new streams are needed */
 -    for (i = 0; i < c->n_variants; i++)
 -        c->variants[i]->cur_needed = 0;;
 +    for (i = 0; i < c->n_playlists; i++)
 +        c->playlists[i]->cur_needed = 0;
  
      for (i = 0; i < s->nb_streams; i++) {
          AVStream *st = s->streams[i];
 -        struct variant *var = c->variants[s->streams[i]->id];
 +        struct playlist *pls = c->playlists[s->streams[i]->id];
          if (st->discard < AVDISCARD_ALL)
 -            var->cur_needed = 1;
 +            pls->cur_needed = 1;
      }
 -    for (i = 0; i < c->n_variants; i++) {
 -        struct variant *v = c->variants[i];
 -        if (v->cur_needed && !v->needed) {
 -            v->needed = 1;
 +    for (i = 0; i < c->n_playlists; i++) {
 +        struct playlist *pls = c->playlists[i];
 +        if (pls->cur_needed && !pls->needed) {
 +            pls->needed = 1;
              changed = 1;
 -            v->cur_seq_no = c->cur_seq_no;
 -            v->pb.eof_reached = 0;
 -            av_log(s, AV_LOG_INFO, "Now receiving variant %d\n", i);
 -        } else if (first && !v->cur_needed && v->needed) {
 -            if (v->input)
 -                ffurl_close(v->input);
 -            v->input = NULL;
 -            v->needed = 0;
 +            pls->cur_seq_no = select_cur_seq_no(c, pls);
 +            pls->pb.eof_reached = 0;
 +            if (c->cur_timestamp != AV_NOPTS_VALUE) {
 +                /* catch up */
 +                pls->seek_timestamp = c->cur_timestamp;
 +                pls->seek_flags = AVSEEK_FLAG_ANY;
 +                pls->seek_stream_index = -1;
 +            }
 +            av_log(s, AV_LOG_INFO, "Now receiving playlist %d, segment %d\n", i, pls->cur_seq_no);
 +        } else if (first && !pls->cur_needed && pls->needed) {
 +            if (pls->input)
 +                ffurl_close(pls->input);
 +            pls->input = NULL;
 +            pls->needed = 0;
              changed = 1;
 -            av_log(s, AV_LOG_INFO, "No longer receiving variant %d\n", i);
 +            av_log(s, AV_LOG_INFO, "No longer receiving playlist %d\n", i);
          }
      }
      return changed;
  }
  
 +static void fill_timing_for_id3_timestamped_stream(struct playlist *pls)
 +{
 +    if (pls->id3_offset >= 0) {
 +        pls->pkt.dts = pls->id3_mpegts_timestamp +
 +                                 av_rescale_q(pls->id3_offset,
 +                                              pls->ctx->streams[pls->pkt.stream_index]->time_base,
 +                                              MPEG_TIME_BASE_Q);
 +        if (pls->pkt.duration)
 +            pls->id3_offset += pls->pkt.duration;
 +        else
 +            pls->id3_offset = -1;
 +    } else {
 +        /* there have been packets with unknown duration
 +         * since the last id3 tag, should not normally happen */
 +        pls->pkt.dts = AV_NOPTS_VALUE;
 +    }
 +
 +    if (pls->pkt.duration)
 +        pls->pkt.duration = av_rescale_q(pls->pkt.duration,
 +                                         pls->ctx->streams[pls->pkt.stream_index]->time_base,
 +                                         MPEG_TIME_BASE_Q);
 +
 +    pls->pkt.pts = AV_NOPTS_VALUE;
 +}
 +
 +static AVRational get_timebase(struct playlist *pls)
 +{
 +    if (pls->is_id3_timestamped)
 +        return MPEG_TIME_BASE_Q;
 +
 +    return pls->ctx->streams[pls->pkt.stream_index]->time_base;
 +}
 +
 +static int compare_ts_with_wrapdetect(int64_t ts_a, struct playlist *pls_a,
 +                                      int64_t ts_b, struct playlist *pls_b)
 +{
 +    int64_t scaled_ts_a = av_rescale_q(ts_a, get_timebase(pls_a), MPEG_TIME_BASE_Q);
 +    int64_t scaled_ts_b = av_rescale_q(ts_b, get_timebase(pls_b), MPEG_TIME_BASE_Q);
 +
 +    return av_compare_mod(scaled_ts_a, scaled_ts_b, 1LL << 33);
 +}
 +
  static int hls_read_packet(AVFormatContext *s, AVPacket *pkt)
  {
      HLSContext *c = s->priv_data;
 -    int ret, i, minvariant = -1;
 +    int ret, i, minplaylist = -1;
  
 -    if (c->first_packet) {
 -        recheck_discard_flags(s, 1);
 -        c->first_packet = 0;
 -    }
 +    recheck_discard_flags(s, c->first_packet);
 +    c->first_packet = 0;
  
 -start:
 -    c->end_of_segment = 0;
 -    for (i = 0; i < c->n_variants; i++) {
 -        struct variant *var = c->variants[i];
 -        /* Make sure we've got one buffered packet from each open variant
 +    for (i = 0; i < c->n_playlists; i++) {
 +        struct playlist *pls = c->playlists[i];
 +        /* Make sure we've got one buffered packet from each open playlist
           * stream */
 -        if (var->needed && !var->pkt.data) {
 +        if (pls->needed && !pls->pkt.data) {
              while (1) {
                  int64_t ts_diff;
 -                AVStream *st;
 -                ret = av_read_frame(var->ctx, &var->pkt);
 +                AVRational tb;
 +                ret = av_read_frame(pls->ctx, &pls->pkt);
                  if (ret < 0) {
 -                    if (!var->pb.eof_reached)
 +                    if (!avio_feof(&pls->pb) && ret != AVERROR_EOF)
                          return ret;
 -                    reset_packet(&var->pkt);
 +                    reset_packet(&pls->pkt);
                      break;
                  } else {
 +                    /* stream_index check prevents matching picture attachments etc. */
 +                    if (pls->is_id3_timestamped && pls->pkt.stream_index == 0) {
 +                        /* audio elementary streams are id3 timestamped */
 +                        fill_timing_for_id3_timestamped_stream(pls);
 +                    }
 +
                      if (c->first_timestamp == AV_NOPTS_VALUE &&
 -                        var->pkt.dts       != AV_NOPTS_VALUE)
 -                        c->first_timestamp = av_rescale_q(var->pkt.dts,
 -                            var->ctx->streams[var->pkt.stream_index]->time_base,
 -                            AV_TIME_BASE_Q);
 +                        pls->pkt.dts       != AV_NOPTS_VALUE)
 +                        c->first_timestamp = av_rescale_q(pls->pkt.dts,
 +                            get_timebase(pls), AV_TIME_BASE_Q);
                  }
  
 -                if (c->seek_timestamp == AV_NOPTS_VALUE)
 +                if (pls->seek_timestamp == AV_NOPTS_VALUE)
                      break;
  
 -                if (var->pkt.dts == AV_NOPTS_VALUE) {
 -                    c->seek_timestamp = AV_NOPTS_VALUE;
 -                    break;
 -                }
 +                if (pls->seek_stream_index < 0 ||
 +                    pls->seek_stream_index == pls->pkt.stream_index) {
  
 -                st = var->ctx->streams[var->pkt.stream_index];
 -                ts_diff = av_rescale_rnd(var->pkt.dts, AV_TIME_BASE,
 -                                         st->time_base.den, AV_ROUND_DOWN) -
 -                          c->seek_timestamp;
 -                if (ts_diff >= 0 && (c->seek_flags  & AVSEEK_FLAG_ANY ||
 -                                     var->pkt.flags & AV_PKT_FLAG_KEY)) {
 -                    c->seek_timestamp = AV_NOPTS_VALUE;
 -                    break;
 +                    if (pls->pkt.dts == AV_NOPTS_VALUE) {
 +                        pls->seek_timestamp = AV_NOPTS_VALUE;
 +                        break;
 +                    }
 +
 +                    tb = get_timebase(pls);
 +                    ts_diff = av_rescale_rnd(pls->pkt.dts, AV_TIME_BASE,
 +                                            tb.den, AV_ROUND_DOWN) -
 +                            pls->seek_timestamp;
 +                    if (ts_diff >= 0 && (pls->seek_flags  & AVSEEK_FLAG_ANY ||
 +                                        pls->pkt.flags & AV_PKT_FLAG_KEY)) {
 +                        pls->seek_timestamp = AV_NOPTS_VALUE;
 +                        break;
 +                    }
                  }
 -                av_packet_unref(&var->pkt);
 -                reset_packet(&var->pkt);
 +                av_packet_unref(&pls->pkt);
 +                reset_packet(&pls->pkt);
              }
          }
 -        /* Check if this stream still is on an earlier segment number, or
 -         * has the packet with the lowest dts */
 -        if (var->pkt.data) {
 -            struct variant *minvar = minvariant < 0 ?
 -                                     NULL : c->variants[minvariant];
 -            if (minvariant < 0 || var->cur_seq_no < minvar->cur_seq_no) {
 -                minvariant = i;
 -            } else if (var->cur_seq_no == minvar->cur_seq_no) {
 -                int64_t dts     =    var->pkt.dts;
 -                int64_t mindts  = minvar->pkt.dts;
 -                AVStream *st    =    var->ctx->streams[var->pkt.stream_index];
 -                AVStream *minst = minvar->ctx->streams[minvar->pkt.stream_index];
 -
 -                if (dts == AV_NOPTS_VALUE) {
 -                    minvariant = i;
 -                } else if (mindts != AV_NOPTS_VALUE) {
 -                    if (st->start_time    != AV_NOPTS_VALUE)
 -                        dts    -= st->start_time;
 -                    if (minst->start_time != AV_NOPTS_VALUE)
 -                        mindts -= minst->start_time;
 -
 -                    if (av_compare_ts(dts, st->time_base,
 -                                      mindts, minst->time_base) < 0)
 -                        minvariant = i;
 -                }
 +        /* Check if this stream has the packet with the lowest dts */
 +        if (pls->pkt.data) {
 +            struct playlist *minpls = minplaylist < 0 ?
 +                                     NULL : c->playlists[minplaylist];
 +            if (minplaylist < 0) {
 +                minplaylist = i;
 +            } else {
 +                int64_t dts     =    pls->pkt.dts;
 +                int64_t mindts  = minpls->pkt.dts;
 +
 +                if (dts == AV_NOPTS_VALUE ||
 +                    (mindts != AV_NOPTS_VALUE && compare_ts_with_wrapdetect(dts, pls, mindts, minpls) < 0))
 +                    minplaylist = i;
              }
          }
      }
 -    if (c->end_of_segment) {
 -        if (recheck_discard_flags(s, 0))
 -            goto start;
 -    }
 +
      /* If we got a packet, return it */
 -    if (minvariant >= 0) {
 -        *pkt = c->variants[minvariant]->pkt;
 -        pkt->stream_index += c->variants[minvariant]->stream_offset;
 -        reset_packet(&c->variants[minvariant]->pkt);
 +    if (minplaylist >= 0) {
 +        struct playlist *pls = c->playlists[minplaylist];
 +        *pkt = pls->pkt;
 +        pkt->stream_index += pls->stream_offset;
 +        reset_packet(&c->playlists[minplaylist]->pkt);
 +
 +        if (pkt->dts != AV_NOPTS_VALUE)
 +            c->cur_timestamp = av_rescale_q(pkt->dts,
 +                                            pls->ctx->streams[pls->pkt.stream_index]->time_base,
 +                                            AV_TIME_BASE_Q);
 +
          return 0;
      }
      return AVERROR_EOF;
@@@ -1898,9 -776,7 +1897,9 @@@ static int hls_close(AVFormatContext *s
  {
      HLSContext *c = s->priv_data;
  
 +    free_playlist_list(c);
      free_variant_list(c);
 +    free_rendition_list(c);
  
      av_dict_free(&c->avio_opts);
  
@@@ -1911,80 -787,58 +1910,80 @@@ static int hls_read_seek(AVFormatContex
                                 int64_t timestamp, int flags)
  {
      HLSContext *c = s->priv_data;
 -    int i, j, ret;
 +    struct playlist *seek_pls = NULL;
 +    int i, seq_no;
 +    int64_t first_timestamp, seek_timestamp, duration;
  
 -    if ((flags & AVSEEK_FLAG_BYTE) || !c->variants[0]->finished)
 +    if ((flags & AVSEEK_FLAG_BYTE) ||
 +        !(c->variants[0]->playlists[0]->finished || c->variants[0]->playlists[0]->type == PLS_TYPE_EVENT))
          return AVERROR(ENOSYS);
  
 -    c->seek_flags     = flags;
 -    c->seek_timestamp = stream_index < 0 ? timestamp :
 -                        av_rescale_rnd(timestamp, AV_TIME_BASE,
 -                                       s->streams[stream_index]->time_base.den,
 -                                       flags & AVSEEK_FLAG_BACKWARD ?
 -                                       AV_ROUND_DOWN : AV_ROUND_UP);
 -    timestamp = av_rescale_rnd(timestamp, AV_TIME_BASE, stream_index >= 0 ?
 -                               s->streams[stream_index]->time_base.den :
 -                               AV_TIME_BASE, flags & AVSEEK_FLAG_BACKWARD ?
 -                               AV_ROUND_DOWN : AV_ROUND_UP);
 -    if (s->duration < c->seek_timestamp) {
 -        c->seek_timestamp = AV_NOPTS_VALUE;
 +    first_timestamp = c->first_timestamp == AV_NOPTS_VALUE ?
 +                      0 : c->first_timestamp;
 +
 +    seek_timestamp = av_rescale_rnd(timestamp, AV_TIME_BASE,
 +                                    s->streams[stream_index]->time_base.den,
 +                                    flags & AVSEEK_FLAG_BACKWARD ?
 +                                    AV_ROUND_DOWN : AV_ROUND_UP);
 +
 +    duration = s->duration == AV_NOPTS_VALUE ?
 +               0 : s->duration;
 +
 +    if (0 < duration && duration < seek_timestamp - first_timestamp)
          return AVERROR(EIO);
 +
 +    /* find the playlist with the specified stream */
 +    for (i = 0; i < c->n_playlists; i++) {
 +        struct playlist *pls = c->playlists[i];
 +        if (stream_index >= pls->stream_offset &&
 +            stream_index - pls->stream_offset < pls->ctx->nb_streams) {
 +            seek_pls = pls;
 +            break;
 +        }
      }
 +    /* check if the timestamp is valid for the playlist with the
 +     * specified stream index */
 +    if (!seek_pls || !find_timestamp_in_playlist(c, seek_pls, seek_timestamp, &seq_no))
 +        return AVERROR(EIO);
  
 -    ret = AVERROR(EIO);
 -    for (i = 0; i < c->n_variants; i++) {
 +    /* set segment now so we do not need to search again below */
 +    seek_pls->cur_seq_no = seq_no;
 +    seek_pls->seek_stream_index = stream_index - seek_pls->stream_offset;
 +
 +    for (i = 0; i < c->n_playlists; i++) {
          /* Reset reading */
 -        struct variant *var = c->variants[i];
 -        int64_t pos = c->first_timestamp == AV_NOPTS_VALUE ?
 -                      0 : c->first_timestamp;
 -        if (var->input) {
 -            ffurl_close(var->input);
 -            var->input = NULL;
 +        struct playlist *pls = c->playlists[i];
 +        if (pls->input) {
 +            ffurl_close(pls->input);
 +            pls->input = NULL;
          }
 -        av_packet_unref(&var->pkt);
 -        reset_packet(&var->pkt);
 -        var->pb.eof_reached = 0;
 +        av_packet_unref(&pls->pkt);
 +        reset_packet(&pls->pkt);
 +        pls->pb.eof_reached = 0;
          /* Clear any buffered data */
 -        var->pb.buf_end = var->pb.buf_ptr = var->pb.buffer;
 +        pls->pb.buf_end = pls->pb.buf_ptr = pls->pb.buffer;
          /* Reset the pos, to let the mpegts demuxer know we've seeked. */
 -        var->pb.pos = 0;
 -
 -        /* Locate the segment that contains the target timestamp */
 -        for (j = 0; j < var->n_segments; j++) {
 -            if (timestamp >= pos &&
 -                timestamp < pos + var->segments[j]->duration) {
 -                var->cur_seq_no = var->start_seq_no + j;
 -                ret = 0;
 -                break;
 -            }
 -            pos += var->segments[j]->duration;
 +        pls->pb.pos = 0;
 +        /* Flush the packet queue of the subdemuxer. */
 +        ff_read_frame_flush(pls->ctx);
 +
 +        pls->seek_timestamp = seek_timestamp;
 +        pls->seek_flags = flags;
 +
 +        if (pls != seek_pls) {
 +            /* set closest segment seq_no for playlists not handled above */
 +            find_timestamp_in_playlist(c, pls, seek_timestamp, &pls->cur_seq_no);
 +            /* seek the playlist to the given position without taking
 +             * keyframes into account since this playlist does not have the
 +             * specified stream where we should look for the keyframes */
 +            pls->seek_stream_index = -1;
 +            pls->seek_flags |= AVSEEK_FLAG_ANY;
          }
 -        if (ret)
 -            c->seek_timestamp = AV_NOPTS_VALUE;
      }
 -    return ret;
 +
 +    c->cur_timestamp = seek_timestamp;
 +
 +    return 0;
  }
  
  static int hls_probe(AVProbeData *p)
       * somewhere for a proper match. */
      if (strncmp(p->buf, "#EXTM3U", 7))
          return 0;
 +
      if (strstr(p->buf, "#EXT-X-STREAM-INF:")     ||
          strstr(p->buf, "#EXT-X-TARGETDURATION:") ||
          strstr(p->buf, "#EXT-X-MEDIA-SEQUENCE:"))
      return 0;
  }
  
 +#define OFFSET(x) offsetof(HLSContext, x)
 +#define FLAGS AV_OPT_FLAG_DECODING_PARAM
 +static const AVOption hls_options[] = {
 +    {"live_start_index", "segment index to start live streams at (negative values are from the end)",
 +        OFFSET(live_start_index), AV_OPT_TYPE_INT, {.i64 = -3}, INT_MIN, INT_MAX, FLAGS},
 +    {NULL}
 +};
 +
 +static const AVClass hls_class = {
 +    .class_name = "hls,applehttp",
 +    .item_name  = av_default_item_name,
 +    .option     = hls_options,
 +    .version    = LIBAVUTIL_VERSION_INT,
 +};
 +
  AVInputFormat ff_hls_demuxer = {
      .name           = "hls,applehttp",
      .long_name      = NULL_IF_CONFIG_SMALL("Apple HTTP Live Streaming"),
 +    .priv_class     = &hls_class,
      .priv_data_size = sizeof(HLSContext),
      .read_probe     = hls_probe,
      .read_header    = hls_read_header,
diff --combined libavformat/hlsenc.c
@@@ -2,67 -2,40 +2,67 @@@
   * Apple HTTP Live Streaming segmenter
   * Copyright (c) 2012, Luca Barbato
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
 +#include "config.h"
  #include <float.h>
  #include <stdint.h>
 +#if HAVE_UNISTD_H
 +#include <unistd.h>
 +#endif
  
 +#include "libavutil/avassert.h"
  #include "libavutil/mathematics.h"
  #include "libavutil/parseutils.h"
  #include "libavutil/avstring.h"
  #include "libavutil/opt.h"
  #include "libavutil/log.h"
 +#include "libavutil/time_internal.h"
  
  #include "avformat.h"
 +#include "avio_internal.h"
  #include "internal.h"
 +#include "os_support.h"
  
 -typedef struct ListEntry {
 -    char  name[1024];
 -    int64_t duration;     // segment duration in AV_TIME_BASE units
 -    struct ListEntry *next;
 -} ListEntry;
 +#define KEYSIZE 16
 +#define LINE_BUFFER_SIZE 1024
 +
 +typedef struct HLSSegment {
 +    char filename[1024];
 +    char sub_filename[1024];
 +    double duration; /* in seconds */
 +    int64_t pos;
 +    int64_t size;
 +
 +    char key_uri[LINE_BUFFER_SIZE + 1];
 +    char iv_string[KEYSIZE*2 + 1];
 +
 +    struct HLSSegment *next;
 +} HLSSegment;
 +
 +typedef enum HLSFlags {
 +    // Generate a single media file and use byte ranges in the playlist.
 +    HLS_SINGLE_FILE = (1 << 0),
 +    HLS_DELETE_SEGMENTS = (1 << 1),
 +    HLS_ROUND_DURATIONS = (1 << 2),
 +    HLS_DISCONT_START = (1 << 3),
 +    HLS_OMIT_ENDLIST = (1 << 4),
 +} HLSFlags;
  
  typedef struct HLSContext {
      const AVClass *class;  // Class for private options.
      int64_t sequence;
      int64_t start_sequence;
      AVOutputFormat *oformat;
 +    AVOutputFormat *vtt_oformat;
 +
      AVFormatContext *avf;
 +    AVFormatContext *vtt_avf;
 +
      float time;            // Set by a private option.
 -    int  size;             // Set by a private option.
 +    int max_nb_segments;   // Set by a private option.
      int  wrap;             // Set by a private option.
 -    int  version;          // Set by a private option.
 -    int  allowcache;
 +    uint32_t flags;        // enum HLSFlags
 +    char *segment_filename;
 +
 +    int use_localtime;      ///< flag to expand filename with localtime
 +    int allowcache;
      int64_t recording_time;
      int has_video;
 -    // The following timestamps are in AV_TIME_BASE units.
 +    int has_subtitle;
      int64_t start_pts;
      int64_t end_pts;
 -    int64_t duration;      // last segment duration computed so far.
 +    double duration;      // last segment duration computed so far, in seconds
 +    int64_t start_pos;    // last segment starting position
 +    int64_t size;         // last segment size
      int nb_entries;
 -    ListEntry *list;
 -    ListEntry *end_list;
 +    int discontinuity_set;
 +
 +    HLSSegment *segments;
 +    HLSSegment *last_segment;
 +    HLSSegment *old_segments;
 +
      char *basename;
 +    char *vtt_basename;
 +    char *vtt_m3u8_name;
      char *baseurl;
 +    char *format_options_str;
 +    char *vtt_format_options_str;
 +    char *subtitle_filename;
 +    AVDictionary *format_options;
 +
 +    char *key_info_file;
 +    char key_file[LINE_BUFFER_SIZE + 1];
 +    char key_uri[LINE_BUFFER_SIZE + 1];
 +    char key_string[KEYSIZE*2 + 1];
 +    char iv_string[KEYSIZE*2 + 1];
 +    AVDictionary *vtt_format_options;
 +
 +    char *method;
 +
  } HLSContext;
  
-     if ((ret = ffio_open_whitelist(&pb, hls->key_info_file, AVIO_FLAG_READ,
-                            &s->interrupt_callback, NULL, s->protocol_whitelist)) < 0) {
 +static int hls_delete_old_segments(HLSContext *hls) {
 +
 +    HLSSegment *segment, *previous_segment = NULL;
 +    float playlist_duration = 0.0f;
 +    int ret = 0, path_size, sub_path_size;
 +    char *dirname = NULL, *p, *sub_path;
 +    char *path = NULL;
 +
 +    segment = hls->segments;
 +    while (segment) {
 +        playlist_duration += segment->duration;
 +        segment = segment->next;
 +    }
 +
 +    segment = hls->old_segments;
 +    while (segment) {
 +        playlist_duration -= segment->duration;
 +        previous_segment = segment;
 +        segment = previous_segment->next;
 +        if (playlist_duration <= -previous_segment->duration) {
 +            previous_segment->next = NULL;
 +            break;
 +        }
 +    }
 +
 +    if (segment) {
 +        if (hls->segment_filename) {
 +            dirname = av_strdup(hls->segment_filename);
 +        } else {
 +            dirname = av_strdup(hls->avf->filename);
 +        }
 +        if (!dirname) {
 +            ret = AVERROR(ENOMEM);
 +            goto fail;
 +        }
 +        p = (char *)av_basename(dirname);
 +        *p = '\0';
 +    }
 +
 +    while (segment) {
 +        av_log(hls, AV_LOG_DEBUG, "deleting old segment %s\n",
 +                                  segment->filename);
 +        path_size = strlen(dirname) + strlen(segment->filename) + 1;
 +        path = av_malloc(path_size);
 +        if (!path) {
 +            ret = AVERROR(ENOMEM);
 +            goto fail;
 +        }
 +
 +        av_strlcpy(path, dirname, path_size);
 +        av_strlcat(path, segment->filename, path_size);
 +        if (unlink(path) < 0) {
 +            av_log(hls, AV_LOG_ERROR, "failed to delete old segment %s: %s\n",
 +                                     path, strerror(errno));
 +        }
 +
 +        if (segment->sub_filename[0] != '\0') {
 +            sub_path_size = strlen(dirname) + strlen(segment->sub_filename) + 1;
 +            sub_path = av_malloc(sub_path_size);
 +            if (!sub_path) {
 +                ret = AVERROR(ENOMEM);
 +                goto fail;
 +            }
 +
 +            av_strlcpy(sub_path, dirname, sub_path_size);
 +            av_strlcat(sub_path, segment->sub_filename, sub_path_size);
 +            if (unlink(sub_path) < 0) {
 +                av_log(hls, AV_LOG_ERROR, "failed to delete old segment %s: %s\n",
 +                                         sub_path, strerror(errno));
 +            }
 +            av_free(sub_path);
 +        }
 +        av_freep(&path);
 +        previous_segment = segment;
 +        segment = previous_segment->next;
 +        av_free(previous_segment);
 +    }
 +
 +fail:
 +    av_free(path);
 +    av_free(dirname);
 +
 +    return ret;
 +}
 +
 +static int hls_encryption_start(AVFormatContext *s)
 +{
 +    HLSContext *hls = s->priv_data;
 +    int ret;
 +    AVIOContext *pb;
 +    uint8_t key[KEYSIZE];
 +
-     avio_close(pb);
++    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;
 +    }
 +
 +    ff_get_line(pb, hls->key_uri, sizeof(hls->key_uri));
 +    hls->key_uri[strcspn(hls->key_uri, "\r\n")] = '\0';
 +
 +    ff_get_line(pb, hls->key_file, sizeof(hls->key_file));
 +    hls->key_file[strcspn(hls->key_file, "\r\n")] = '\0';
 +
 +    ff_get_line(pb, hls->iv_string, sizeof(hls->iv_string));
 +    hls->iv_string[strcspn(hls->iv_string, "\r\n")] = '\0';
 +
-     if ((ret = ffio_open_whitelist(&pb, hls->key_file, AVIO_FLAG_READ,
-                            &s->interrupt_callback, NULL, s->protocol_whitelist)) < 0) {
++    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");
 +        return AVERROR(EINVAL);
 +    }
 +
 +    if (!*hls->key_file) {
 +        av_log(hls, AV_LOG_ERROR, "no key file specified in key info file\n");
 +        return AVERROR(EINVAL);
 +    }
 +
-     avio_close(pb);
++    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));
++    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)
 +            ret = AVERROR(EINVAL);
 +        return ret;
 +    }
 +    ff_data_to_hex(hls->key_string, key, sizeof(key), 0);
 +
 +    return 0;
 +}
 +
  static int hls_mux_init(AVFormatContext *s)
  {
      HLSContext *hls = s->priv_data;
      AVFormatContext *oc;
 -    int i;
 +    AVFormatContext *vtt_oc = NULL;
 +    int i, ret;
  
 -    hls->avf = oc = avformat_alloc_context();
 -    if (!oc)
 -        return AVERROR(ENOMEM);
 +    ret = avformat_alloc_output_context2(&hls->avf, hls->oformat, NULL, NULL);
 +    if (ret < 0)
 +        return ret;
 +    oc = hls->avf;
  
      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) {
 +        ret = avformat_alloc_output_context2(&hls->vtt_avf, hls->vtt_oformat, NULL, NULL);
 +        if (ret < 0)
 +            return ret;
 +        vtt_oc          = hls->vtt_avf;
 +        vtt_oc->oformat = hls->vtt_oformat;
 +        av_dict_copy(&vtt_oc->metadata, s->metadata, 0);
 +    }
  
      for (i = 0; i < s->nb_streams; i++) {
          AVStream *st;
 -        if (!(st = avformat_new_stream(oc, NULL)))
 +        AVFormatContext *loc;
 +        if (s->streams[i]->codec->codec_type == AVMEDIA_TYPE_SUBTITLE)
 +            loc = vtt_oc;
 +        else
 +            loc = oc;
 +
 +        if (!(st = avformat_new_stream(loc, NULL)))
              return AVERROR(ENOMEM);
          avcodec_copy_context(st->codec, s->streams[i]->codec);
          st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio;
          st->time_base = s->streams[i]->time_base;
      }
 +    hls->start_pos = 0;
  
      return 0;
  }
  
 -static int append_entry(HLSContext *hls, int64_t duration)
 +/* Create a new segment and append it to the segment list */
 +static int hls_append_segment(HLSContext *hls, double duration, int64_t pos,
 +                              int64_t size)
  {
 -    ListEntry *en = av_malloc(sizeof(*en));
 +    HLSSegment *en = av_malloc(sizeof(*en));
 +    int ret;
  
      if (!en)
          return AVERROR(ENOMEM);
  
 -    av_strlcpy(en->name, av_basename(hls->avf->filename), sizeof(en->name));
 +    av_strlcpy(en->filename, av_basename(hls->avf->filename), sizeof(en->filename));
 +
 +    if(hls->has_subtitle)
 +        av_strlcpy(en->sub_filename, av_basename(hls->vtt_avf->filename), sizeof(en->sub_filename));
 +    else
 +        en->sub_filename[0] = '\0';
  
      en->duration = duration;
 +    en->pos      = pos;
 +    en->size     = size;
      en->next     = NULL;
  
 -    if (!hls->list)
 -        hls->list = en;
 -    else
 -        hls->end_list->next = en;
 -
 -    hls->end_list = en;
 +    if (hls->key_info_file) {
 +        av_strlcpy(en->key_uri, hls->key_uri, sizeof(en->key_uri));
 +        av_strlcpy(en->iv_string, hls->iv_string, sizeof(en->iv_string));
 +    }
  
 -    if (hls->nb_entries >= hls->size) {
 -        en = hls->list;
 -        hls->list = en->next;
 -        av_free(en);
 +    if (!hls->segments)
 +        hls->segments = en;
 +    else
 +        hls->last_segment->next = en;
 +
 +    hls->last_segment = en;
 +
 +    if (hls->max_nb_segments && hls->nb_entries >= hls->max_nb_segments) {
 +        en = hls->segments;
 +        hls->segments = en->next;
 +        if (en && hls->flags & HLS_DELETE_SEGMENTS &&
 +                !(hls->flags & HLS_SINGLE_FILE || hls->wrap)) {
 +            en->next = hls->old_segments;
 +            hls->old_segments = en;
 +            if ((ret = hls_delete_old_segments(hls)) < 0)
 +                return ret;
 +        } else
 +            av_free(en);
      } else
          hls->nb_entries++;
  
      return 0;
  }
  
 -static void free_entries(HLSContext *hls)
 +static void hls_free_segments(HLSSegment *p)
  {
 -    ListEntry *p = hls->list, *en;
 +    HLSSegment *en;
  
      while(p) {
          en = p;
      }
  }
  
 +static void set_http_options(AVDictionary **options, HLSContext *c)
 +{
 +    if (c->method)
 +        av_dict_set(options, "method", c->method, 0);
 +}
 +
  static int hls_window(AVFormatContext *s, int last)
  {
      HLSContext *hls = s->priv_data;
 -    ListEntry *en;
 -    int64_t target_duration = 0;
 +    HLSSegment *en;
 +    int target_duration = 0;
      int ret = 0;
      AVIOContext *out = NULL;
 +    AVIOContext *sub_out = NULL;
      char temp_filename[1024];
 -    int64_t sequence = FFMAX(hls->start_sequence, hls->sequence - hls->size);
 -
 -    snprintf(temp_filename, sizeof(temp_filename), "%s.tmp", s->filename);
 +    int64_t sequence = FFMAX(hls->start_sequence, hls->sequence - hls->nb_entries);
 +    int version = hls->flags & HLS_SINGLE_FILE ? 4 : 3;
 +    const char *proto = avio_find_protocol_name(s->filename);
 +    int use_rename = proto && !strcmp(proto, "file");
 +    static unsigned warned_non_file;
 +    char *key_uri = NULL;
 +    char *iv_string = NULL;
 +    AVDictionary *options = NULL;
 +
 +    if (!use_rename && !warned_non_file++)
 +        av_log(s, AV_LOG_ERROR, "Cannot use rename on non file protocol, this may lead to races and temporarly partial files\n");
 +
 +    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->list; en; en = en->next) {
 +    for (en = hls->segments; en; en = en->next) {
          if (target_duration < en->duration)
 -            target_duration = en->duration;
 +            target_duration = ceil(en->duration);
      }
  
 +    hls->discontinuity_set = 0;
      avio_printf(out, "#EXTM3U\n");
 -    avio_printf(out, "#EXT-X-VERSION:%d\n", hls->version);
 +    avio_printf(out, "#EXT-X-VERSION:%d\n", version);
      if (hls->allowcache == 0 || hls->allowcache == 1) {
          avio_printf(out, "#EXT-X-ALLOW-CACHE:%s\n", hls->allowcache == 0 ? "NO" : "YES");
      }
 -    avio_printf(out, "#EXT-X-TARGETDURATION:%"PRId64"\n",
 -                av_rescale_rnd(target_duration, 1, AV_TIME_BASE,
 -                               AV_ROUND_UP));
 +    avio_printf(out, "#EXT-X-TARGETDURATION:%d\n", target_duration);
      avio_printf(out, "#EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence);
  
      av_log(s, AV_LOG_VERBOSE, "EXT-X-MEDIA-SEQUENCE:%"PRId64"\n",
             sequence);
 -
 -    for (en = hls->list; en; en = en->next) {
 -        if (hls->version > 2)
 -            avio_printf(out, "#EXTINF:%f\n",
 -                        (double)en->duration / AV_TIME_BASE);
 +    if((hls->flags & HLS_DISCONT_START) && sequence==hls->start_sequence && hls->discontinuity_set==0 ){
 +        avio_printf(out, "#EXT-X-DISCONTINUITY\n");
 +        hls->discontinuity_set = 1;
 +    }
 +    for (en = hls->segments; en; en = en->next) {
 +        if (hls->key_info_file && (!key_uri || strcmp(en->key_uri, key_uri) ||
 +                                    av_strcasecmp(en->iv_string, iv_string))) {
 +            avio_printf(out, "#EXT-X-KEY:METHOD=AES-128,URI=\"%s\"", en->key_uri);
 +            if (*en->iv_string)
 +                avio_printf(out, ",IV=0x%s", en->iv_string);
 +            avio_printf(out, "\n");
 +            key_uri = en->key_uri;
 +            iv_string = en->iv_string;
 +        }
 +
 +        if (hls->flags & HLS_ROUND_DURATIONS)
 +            avio_printf(out, "#EXTINF:%ld,\n",  lrint(en->duration));
          else
 -            avio_printf(out, "#EXTINF:%"PRId64",\n",
 -                        av_rescale(en->duration, 1, AV_TIME_BASE));
 +            avio_printf(out, "#EXTINF:%f,\n", en->duration);
 +        if (hls->flags & HLS_SINGLE_FILE)
 +             avio_printf(out, "#EXT-X-BYTERANGE:%"PRIi64"@%"PRIi64"\n",
 +                         en->size, en->pos);
          if (hls->baseurl)
              avio_printf(out, "%s", hls->baseurl);
 -        avio_printf(out, "%s\n", en->name);
 +        avio_printf(out, "%s\n", en->filename);
      }
  
 -    if (last)
 +    if (last && (hls->flags & HLS_OMIT_ENDLIST)==0)
          avio_printf(out, "#EXT-X-ENDLIST\n");
  
-         if ((ret = ffio_open_whitelist(&sub_out, hls->vtt_m3u8_name, AVIO_FLAG_WRITE,
-                           &s->interrupt_callback, &options, s->protocol_whitelist)) < 0)
 +    if( hls->vtt_m3u8_name ) {
++        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);
 +        if (hls->allowcache == 0 || hls->allowcache == 1) {
 +            avio_printf(sub_out, "#EXT-X-ALLOW-CACHE:%s\n", hls->allowcache == 0 ? "NO" : "YES");
 +        }
 +        avio_printf(sub_out, "#EXT-X-TARGETDURATION:%d\n", target_duration);
 +        avio_printf(sub_out, "#EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence);
 +
 +        av_log(s, AV_LOG_VERBOSE, "EXT-X-MEDIA-SEQUENCE:%"PRId64"\n",
 +               sequence);
 +
 +        for (en = hls->segments; en; en = en->next) {
 +            avio_printf(sub_out, "#EXTINF:%f,\n", en->duration);
 +            if (hls->flags & HLS_SINGLE_FILE)
 +                 avio_printf(sub_out, "#EXT-X-BYTERANGE:%"PRIi64"@%"PRIi64"\n",
 +                         en->size, en->pos);
 +            if (hls->baseurl)
 +                avio_printf(sub_out, "%s", hls->baseurl);
 +            avio_printf(sub_out, "%s\n", en->sub_filename);
 +        }
 +
 +        if (last)
 +            avio_printf(sub_out, "#EXT-X-ENDLIST\n");
 +
 +    }
 +
  fail:
-     avio_closep(&out);
-     avio_closep(&sub_out);
 +    av_dict_free(&options);
 -    if (ret >= 0)
 -        ff_rename(temp_filename, s->filename);
+     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;
  }
  
@@@ -488,101 -190,20 +487,98 @@@ static int hls_start(AVFormatContext *s
  {
      HLSContext *c = s->priv_data;
      AVFormatContext *oc = c->avf;
 +    AVFormatContext *vtt_oc = c->vtt_avf;
 +    AVDictionary *options = NULL;
 +    char *filename, iv_string[KEYSIZE*2 + 1];
      int err = 0;
  
 -    if (av_get_frame_filename(oc->filename, sizeof(oc->filename),
 -                              c->basename, c->wrap ? c->sequence % c->wrap : c->sequence) < 0)
 -        return AVERROR(EINVAL);
 +    if (c->flags & HLS_SINGLE_FILE) {
 +        av_strlcpy(oc->filename, c->basename,
 +                   sizeof(oc->filename));
 +        if (c->vtt_basename)
 +            av_strlcpy(vtt_oc->filename, c->vtt_basename,
 +                  sizeof(vtt_oc->filename));
 +    } else {
 +        if (c->use_localtime) {
 +            time_t now0;
 +            struct tm *tm, tmpbuf;
 +            time(&now0);
 +            tm = localtime_r(&now0, &tmpbuf);
 +            if (!strftime(oc->filename, sizeof(oc->filename), c->basename, tm)) {
 +                av_log(oc, AV_LOG_ERROR, "Could not get segment filename with use_localtime\n");
 +                return AVERROR(EINVAL);
 +            }
 +       } else if (av_get_frame_filename(oc->filename, sizeof(oc->filename),
 +                                  c->basename, c->wrap ? c->sequence % c->wrap : c->sequence) < 0) {
 +            av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s' you can try use -use_localtime 1 with it\n", c->basename);
 +            return AVERROR(EINVAL);
 +        }
 +        if( c->vtt_basename) {
 +            if (av_get_frame_filename(vtt_oc->filename, sizeof(vtt_oc->filename),
 +                              c->vtt_basename, c->wrap ? c->sequence % c->wrap : c->sequence) < 0) {
 +                av_log(vtt_oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", c->vtt_basename);
 +                return AVERROR(EINVAL);
 +            }
 +       }
 +    }
      c->number++;
  
 -    if ((err = s->io_open(s, &oc->pb, oc->filename, AVIO_FLAG_WRITE, NULL)) < 0)
 -        return err;
 +    set_http_options(&options, c);
 +
 +    if (c->key_info_file) {
 +        if ((err = hls_encryption_start(s)) < 0)
 +            goto fail;
 +        if ((err = av_dict_set(&options, "encryption_key", c->key_string, 0))
 +                < 0)
 +            goto fail;
 +        err = av_strlcpy(iv_string, c->iv_string, sizeof(iv_string));
 +        if (!err)
 +            snprintf(iv_string, sizeof(iv_string), "%032"PRIx64, c->sequence);
 +        if ((err = av_dict_set(&options, "encryption_iv", iv_string, 0)) < 0)
 +           goto fail;
 +
 +        filename = av_asprintf("crypto:%s", oc->filename);
 +        if (!filename) {
 +            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);
 +
 +    /* We only require one PAT/PMT per segment. */
 +    if (oc->oformat->priv_class && oc->priv_data) {
 +        char period[21];
 +
 +        snprintf(period, sizeof(period), "%d", (INT_MAX / 2) - 1);
  
 -    if (oc->oformat->priv_class && oc->priv_data)
          av_opt_set(oc->priv_data, "mpegts_flags", "resend_headers", 0);
 +        av_opt_set(oc->priv_data, "sdt_period", period, 0);
 +        av_opt_set(oc->priv_data, "pat_period", period, 0);
 +    }
 +
 +    if (c->vtt_basename) {
 +        err = avformat_write_header(vtt_oc,NULL);
 +        if (err < 0)
 +            return err;
 +    }
  
      return 0;
 +fail:
 +    av_dict_free(&options);
 +
 +    return err;
  }
  
  static int hls_write_header(AVFormatContext *s)
      int ret, i;
      char *p;
      const char *pattern = "%d.ts";
 -    int basename_size = strlen(s->filename) + strlen(pattern) + 1;
 +    const char *pattern_localtime_fmt = "-%s.ts";
 +    const char *vtt_pattern = "%d.vtt";
 +    AVDictionary *options = NULL;
 +    int basename_size;
 +    int vtt_basename_size;
  
      hls->sequence       = hls->start_sequence;
      hls->recording_time = hls->time * AV_TIME_BASE;
      hls->start_pts      = AV_NOPTS_VALUE;
  
 -    for (i = 0; i < s->nb_streams; i++)
 +    if (hls->format_options_str) {
 +        ret = av_dict_parse_string(&hls->format_options, hls->format_options_str, "=", ":", 0);
 +        if (ret < 0) {
 +            av_log(s, AV_LOG_ERROR, "Could not parse format options list '%s'\n", hls->format_options_str);
 +            goto fail;
 +        }
 +    }
 +
 +    for (i = 0; i < s->nb_streams; i++) {
          hls->has_video +=
              s->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO;
 +        hls->has_subtitle +=
 +            s->streams[i]->codec->codec_type == AVMEDIA_TYPE_SUBTITLE;
 +    }
  
      if (hls->has_video > 1)
          av_log(s, AV_LOG_WARNING,
          goto fail;
      }
  
 -    hls->basename = av_malloc(basename_size);
 -
 -    if (!hls->basename) {
 -        ret = AVERROR(ENOMEM);
 -        goto fail;
 +    if(hls->has_subtitle) {
 +        hls->vtt_oformat = av_guess_format("webvtt", NULL, NULL);
 +        if (!hls->oformat) {
 +            ret = AVERROR_MUXER_NOT_FOUND;
 +            goto fail;
 +        }
      }
  
 -    strcpy(hls->basename, s->filename);
 -
 -    p = strrchr(hls->basename, '.');
 -
 -    if (p)
 -        *p = '\0';
 +    if (hls->segment_filename) {
 +        hls->basename = av_strdup(hls->segment_filename);
 +        if (!hls->basename) {
 +            ret = AVERROR(ENOMEM);
 +            goto fail;
 +        }
 +    } else {
 +        if (hls->flags & HLS_SINGLE_FILE)
 +            pattern = ".ts";
 +
 +        if (hls->use_localtime) {
 +            basename_size = strlen(s->filename) + strlen(pattern_localtime_fmt) + 1;
 +        } else {
 +            basename_size = strlen(s->filename) + strlen(pattern) + 1;
 +        }
 +        hls->basename = av_malloc(basename_size);
 +        if (!hls->basename) {
 +            ret = AVERROR(ENOMEM);
 +            goto fail;
 +        }
 +
 +        av_strlcpy(hls->basename, s->filename, basename_size);
 +
 +        p = strrchr(hls->basename, '.');
 +        if (p)
 +            *p = '\0';
 +        if (hls->use_localtime) {
 +            av_strlcat(hls->basename, pattern_localtime_fmt, basename_size);
 +        } else {
 +            av_strlcat(hls->basename, pattern, basename_size);
 +        }
 +    }
  
 -    av_strlcat(hls->basename, pattern, basename_size);
 +    if(hls->has_subtitle) {
 +
 +        if (hls->flags & HLS_SINGLE_FILE)
 +            vtt_pattern = ".vtt";
 +        vtt_basename_size = strlen(s->filename) + strlen(vtt_pattern) + 1;
 +        hls->vtt_basename = av_malloc(vtt_basename_size);
 +        if (!hls->vtt_basename) {
 +            ret = AVERROR(ENOMEM);
 +            goto fail;
 +        }
 +        hls->vtt_m3u8_name = av_malloc(vtt_basename_size);
 +        if (!hls->vtt_m3u8_name ) {
 +            ret = AVERROR(ENOMEM);
 +            goto fail;
 +        }
 +        av_strlcpy(hls->vtt_basename, s->filename, vtt_basename_size);
 +        p = strrchr(hls->vtt_basename, '.');
 +        if (p)
 +            *p = '\0';
 +
 +        if( hls->subtitle_filename ) {
 +            strcpy(hls->vtt_m3u8_name, hls->subtitle_filename);
 +        } else {
 +            strcpy(hls->vtt_m3u8_name, hls->vtt_basename);
 +            av_strlcat(hls->vtt_m3u8_name, "_vtt.m3u8", vtt_basename_size);
 +        }
 +        av_strlcat(hls->vtt_basename, vtt_pattern, vtt_basename_size);
 +    }
  
      if ((ret = hls_mux_init(s)) < 0)
          goto fail;
      if ((ret = hls_start(s)) < 0)
          goto fail;
  
 -    if ((ret = avformat_write_header(hls->avf, NULL)) < 0)
 -        return ret;
 -
 -
 +    av_dict_copy(&options, hls->format_options, 0);
 +    ret = avformat_write_header(hls->avf, &options);
 +    if (av_dict_count(options)) {
 +        av_log(s, AV_LOG_ERROR, "Some of provided format options in '%s' are not recognized\n", hls->format_options_str);
 +        ret = AVERROR(EINVAL);
 +        goto fail;
 +    }
 +    //av_assert0(s->nb_streams == hls->avf->nb_streams);
 +    for (i = 0; i < s->nb_streams; i++) {
 +        AVStream *inner_st;
 +        AVStream *outer_st = s->streams[i];
 +        if (outer_st->codec->codec_type != AVMEDIA_TYPE_SUBTITLE)
 +            inner_st = hls->avf->streams[i];
 +        else if (hls->vtt_avf)
 +            inner_st = hls->vtt_avf->streams[0];
 +        else {
 +            /* We have a subtitle stream, when the user does not want one */
 +            inner_st = NULL;
 +            continue;
 +        }
 +        avpriv_set_pts_info(outer_st, inner_st->pts_wrap_bits, inner_st->time_base.num, inner_st->time_base.den);
 +    }
  fail:
 -    if (ret) {
 -        av_free(hls->basename);
 +
 +    av_dict_free(&options);
 +    if (ret < 0) {
 +        av_freep(&hls->basename);
 +        av_freep(&hls->vtt_basename);
          if (hls->avf)
              avformat_free_context(hls->avf);
 +        if (hls->vtt_avf)
 +            avformat_free_context(hls->vtt_avf);
 +
      }
      return ret;
  }
  static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
  {
      HLSContext *hls = s->priv_data;
 -    AVFormatContext *oc = hls->avf;
 +    AVFormatContext *oc = NULL;
      AVStream *st = s->streams[pkt->stream_index];
      int64_t end_pts = hls->recording_time * hls->number;
 -    int64_t pts     = av_rescale_q(pkt->pts, st->time_base, AV_TIME_BASE_Q);
 +    int is_ref_pkt = 1;
      int ret, can_split = 1;
 +    int stream_index = 0;
  
 +    if( st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE ) {
 +        oc = hls->vtt_avf;
 +        stream_index = 0;
 +    } else {
 +        oc = hls->avf;
 +        stream_index = pkt->stream_index;
 +    }
      if (hls->start_pts == AV_NOPTS_VALUE) {
 -        hls->start_pts = pts;
 -        hls->end_pts   = pts;
 +        hls->start_pts = pkt->pts;
 +        hls->end_pts   = pkt->pts;
      }
  
      if (hls->has_video) {
          can_split = st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
                      pkt->flags & AV_PKT_FLAG_KEY;
 +        is_ref_pkt = st->codec->codec_type == AVMEDIA_TYPE_VIDEO;
      }
      if (pkt->pts == AV_NOPTS_VALUE)
 -        can_split = 0;
 -    else
 -        hls->duration = pts - hls->end_pts;
 +        is_ref_pkt = can_split = 0;
 +
 +    if (is_ref_pkt)
 +        hls->duration = (double)(pkt->pts - hls->end_pts)
 +                                   * st->time_base.num / st->time_base.den;
 +
 +    if (can_split && av_compare_ts(pkt->pts - hls->start_pts, st->time_base,
 +                                   end_pts, AV_TIME_BASE_Q) >= 0) {
 +        int64_t new_start_pos;
 +        av_write_frame(oc, NULL); /* Flush any buffered data */
  
 -    if (can_split && pts - hls->start_pts >= end_pts) {
 -        ret = append_entry(hls, hls->duration);
 -        if (ret)
 +        new_start_pos = avio_tell(hls->avf->pb);
 +        hls->size = new_start_pos - hls->start_pos;
 +        ret = hls_append_segment(hls, hls->duration, hls->start_pos, hls->size);
 +        hls->start_pos = new_start_pos;
 +        if (ret < 0)
              return ret;
  
 -        hls->end_pts = pts;
 +        hls->end_pts = pkt->pts;
          hls->duration = 0;
  
 -        av_write_frame(oc, NULL); /* Flush any buffered data */
 -        ff_format_io_close(s, &oc->pb);
 +        if (hls->flags & HLS_SINGLE_FILE) {
 +            if (hls->avf->oformat->priv_class && hls->avf->priv_data)
 +                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);
 +            ret = hls_start(s);
 +        }
  
 -        if (ret)
 +        if (ret < 0)
              return ret;
  
 +        if( st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE )
 +            oc = hls->vtt_avf;
 +        else
          oc = hls->avf;
  
          if ((ret = hls_window(s, 0)) < 0)
              return ret;
      }
  
 -    ret = ff_write_chained(oc, pkt->stream_index, pkt, s);
 +    ret = ff_write_chained(oc, stream_index, pkt, s, 0);
  
      return ret;
  }
@@@ -823,61 -323,28 +819,61 @@@ static int hls_write_trailer(struct AVF
  {
      HLSContext *hls = s->priv_data;
      AVFormatContext *oc = hls->avf;
 +    AVFormatContext *vtt_oc = hls->vtt_avf;
  
      av_write_trailer(oc);
 -    ff_format_io_close(s, &oc->pb);
 +    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);
 -    av_free(hls->basename);
 -    append_entry(hls, hls->duration);
 +
 +    if (vtt_oc) {
 +        av_freep(&hls->vtt_basename);
 +        av_freep(&hls->vtt_m3u8_name);
 +        avformat_free_context(vtt_oc);
 +    }
 +
 +    hls->avf = NULL;
      hls_window(s, 1);
  
 -    free_entries(hls);
 +    hls_free_segments(hls->segments);
 +    hls_free_segments(hls->old_segments);
      return 0;
  }
  
  #define OFFSET(x) offsetof(HLSContext, x)
  #define E AV_OPT_FLAG_ENCODING_PARAM
  static const AVOption options[] = {
 -    {"start_number",  "first number in the sequence",            OFFSET(start_sequence),AV_OPT_TYPE_INT64,  {.i64 = 0},     0, INT64_MAX, E},
 -    {"hls_time",      "segment length in seconds",               OFFSET(time),    AV_OPT_TYPE_FLOAT,  {.dbl = 2},     0, FLT_MAX, E},
 -    {"hls_list_size", "maximum number of playlist entries",      OFFSET(size),    AV_OPT_TYPE_INT,    {.i64 = 5},     0, INT_MAX, E},
 -    {"hls_wrap",      "number after which the index wraps",      OFFSET(wrap),    AV_OPT_TYPE_INT,    {.i64 = 0},     0, INT_MAX, E},
 +    {"start_number",  "set first number in the sequence",        OFFSET(start_sequence),AV_OPT_TYPE_INT64,  {.i64 = 0},     0, INT64_MAX, E},
 +    {"hls_time",      "set segment length in seconds",           OFFSET(time),    AV_OPT_TYPE_FLOAT,  {.dbl = 2},     0, FLT_MAX, E},
 +    {"hls_list_size", "set maximum number of playlist entries",  OFFSET(max_nb_segments),    AV_OPT_TYPE_INT,    {.i64 = 5},     0, INT_MAX, E},
 +    {"hls_ts_options","set hls mpegts list of options for the container format used for hls", OFFSET(format_options_str), AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,    E},
 +    {"hls_vtt_options","set hls vtt list of options for the container format used for hls", OFFSET(vtt_format_options_str), AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,    E},
 +    {"hls_wrap",      "set number after which the index wraps",  OFFSET(wrap),    AV_OPT_TYPE_INT,    {.i64 = 0},     0, INT_MAX, E},
      {"hls_allow_cache", "explicitly set whether the client MAY (1) or MUST NOT (0) cache media segments", OFFSET(allowcache), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, E},
      {"hls_base_url",  "url to prepend to each playlist entry",   OFFSET(baseurl), AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,       E},
 -    {"hls_version",   "protocol version",                        OFFSET(version), AV_OPT_TYPE_INT,    {.i64 = 3},     2, 3, E},
 +    {"hls_segment_filename", "filename template for segment files", OFFSET(segment_filename),   AV_OPT_TYPE_STRING, {.str = NULL},            0,       0,         E},
 +    {"hls_key_info_file",    "file with key URI and key file path", OFFSET(key_info_file),      AV_OPT_TYPE_STRING, {.str = NULL},            0,       0,         E},
 +    {"hls_subtitle_path",     "set path of hls subtitles", OFFSET(subtitle_filename), AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,    E},
 +    {"hls_flags",     "set flags affecting HLS playlist and media file generation", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = 0 }, 0, UINT_MAX, E, "flags"},
 +    {"single_file",   "generate a single media file indexed with byte ranges", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SINGLE_FILE }, 0, UINT_MAX,   E, "flags"},
 +    {"delete_segments", "delete segment files that are no longer part of the playlist", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_DELETE_SEGMENTS }, 0, UINT_MAX,   E, "flags"},
 +    {"round_durations", "round durations in m3u8 to whole numbers", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_ROUND_DURATIONS }, 0, UINT_MAX,   E, "flags"},
 +    {"discont_start", "start the playlist with a discontinuity tag", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_DISCONT_START }, 0, UINT_MAX,   E, "flags"},
 +    {"omit_endlist", "Do not append an endlist when ending stream", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_OMIT_ENDLIST }, 0, UINT_MAX,   E, "flags"},
 +    { "use_localtime", "set filename expansion with strftime at segment creation", OFFSET(use_localtime), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
 +    {"method", "set the HTTP method", OFFSET(method), AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,    E},
 +
      { NULL },
  };
  
@@@ -896,7 -363,6 +892,7 @@@ AVOutputFormat ff_hls_muxer = 
      .priv_data_size = sizeof(HLSContext),
      .audio_codec    = AV_CODEC_ID_AAC,
      .video_codec    = AV_CODEC_ID_H264,
 +    .subtitle_codec = AV_CODEC_ID_WEBVTT,
      .flags          = AVFMT_NOFILE | AVFMT_ALLOW_FLUSH,
      .write_header   = hls_write_header,
      .write_packet   = hls_write_packet,
diff --combined libavformat/img2dec.c
@@@ -3,48 -3,45 +3,48 @@@
   * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
   * Copyright (c) 2004 Michael Niedermayer
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
 +#define _DEFAULT_SOURCE
 +#define _BSD_SOURCE
 +#include <sys/stat.h>
  #include "libavutil/avstring.h"
  #include "libavutil/log.h"
  #include "libavutil/opt.h"
  #include "libavutil/pixdesc.h"
  #include "libavutil/parseutils.h"
 +#include "libavutil/intreadwrite.h"
  #include "avformat.h"
 +#include "avio_internal.h"
  #include "internal.h"
 +#include "img2.h"
  
 -typedef struct VideoDemuxData {
 -    const AVClass *class;  /**< Class for private options. */
 -    int img_first;
 -    int img_last;
 -    int img_number;
 -    int img_count;
 -    int is_pipe;
 -    char path[1024];
 -    char *pixel_format;     /**< Set by a private option. */
 -    char *video_size;       /**< Set by a private option. */
 -    char *framerate;        /**< Set by a private option. */
 -    int loop;
 -    int start_number;
 -} VideoDemuxData;
 +#if HAVE_GLOB
 +/* Locally define as 0 (bitwise-OR no-op) any missing glob options that
 +   are non-posix glibc/bsd extensions. */
 +#ifndef GLOB_NOMAGIC
 +#define GLOB_NOMAGIC 0
 +#endif
 +#ifndef GLOB_BRACE
 +#define GLOB_BRACE 0
 +#endif
 +
 +#endif /* HAVE_GLOB */
  
  static const int sizes[][2] = {
      { 640, 480 },
@@@ -73,55 -70,26 +73,55 @@@ static int infer_size(int *width_ptr, i
      return -1;
  }
  
 -/* return -1 if no image found */
 -static int find_image_range(int *pfirst_index, int *plast_index,
 -                            const char *path, int max_start)
 +static int is_glob(const char *path)
 +{
 +#if HAVE_GLOB
 +    size_t span = 0;
 +    const char *p = path;
 +
 +    while (p = strchr(p, '%')) {
 +        if (*(++p) == '%') {
 +            ++p;
 +            continue;
 +        }
 +        if (span = strspn(p, "*?[]{}"))
 +            break;
 +    }
 +    /* Did we hit a glob char or get to the end? */
 +    return span != 0;
 +#else
 +    return 0;
 +#endif
 +}
 +
 +/**
 + * Get index range of image files matched by path.
 + *
 + * @param pfirst_index pointer to index updated with the first number in the range
 + * @param plast_index  pointer to index updated with the last number in the range
 + * @param path         path which has to be matched by the image files in the range
 + * @param start_index  minimum accepted value for the first index in the range
 + * @return -1 if no image file could be found
 + */
 +static int find_image_range(AVIOContext *pb, int *pfirst_index, int *plast_index,
 +                            const char *path, int start_index, int start_index_range)
  {
      char buf[1024];
      int range, last_index, range1, first_index;
  
      /* find the first image */
 -    for (first_index = 0; first_index < max_start; first_index++) {
 +    for (first_index = start_index; first_index < start_index + start_index_range; first_index++) {
          if (av_get_frame_filename(buf, sizeof(buf), path, first_index) < 0) {
              *pfirst_index =
              *plast_index  = 1;
 -            if (avio_check(buf, AVIO_FLAG_READ) > 0)
 +            if (pb || avio_check(buf, AVIO_FLAG_READ) > 0)
                  return 0;
              return -1;
          }
          if (avio_check(buf, AVIO_FLAG_READ) > 0)
              break;
      }
 -    if (first_index == 5)
 +    if (first_index == start_index + start_index_range)
          goto fail;
  
      /* find the last image */
@@@ -161,26 -129,20 +161,26 @@@ static int img_read_probe(AVProbeData *
      if (p->filename && ff_guess_image2_codec(p->filename)) {
          if (av_filename_number_test(p->filename))
              return AVPROBE_SCORE_MAX;
 +        else if (is_glob(p->filename))
 +            return AVPROBE_SCORE_MAX;
 +        else if (p->filename[strcspn(p->filename, "*?{")]) // probably PT_GLOB
 +            return AVPROBE_SCORE_EXTENSION + 2; // score chosen to be a tad above the image pipes
 +        else if (p->buf_size == 0)
 +            return 0;
 +        else if (av_match_ext(p->filename, "raw") || av_match_ext(p->filename, "gif"))
 +            return 5;
          else
              return AVPROBE_SCORE_EXTENSION;
      }
      return 0;
  }
  
 -static int img_read_header(AVFormatContext *s1)
 +int ff_img_read_header(AVFormatContext *s1)
  {
      VideoDemuxData *s = s1->priv_data;
 -    int first_index, last_index, ret = 0;
 -    int width = 0, height = 0;
 +    int first_index = 1, last_index = 1;
      AVStream *st;
      enum AVPixelFormat pix_fmt = AV_PIX_FMT_NONE;
 -    AVRational framerate;
  
      s1->ctx_flags |= AVFMTCTX_NOHEADER;
  
                 s->pixel_format);
          return AVERROR(EINVAL);
      }
 -    if (s->video_size &&
 -        (ret = av_parse_video_size(&width, &height, s->video_size)) < 0) {
 -        av_log(s, AV_LOG_ERROR,
 -               "Could not parse video size: %s.\n", s->video_size);
 -        return ret;
 -    }
 -    if ((ret = av_parse_video_rate(&framerate, s->framerate)) < 0) {
 -        av_log(s, AV_LOG_ERROR,
 -               "Could not parse framerate: %s.\n", s->framerate);
 -        return ret;
 -    }
  
      av_strlcpy(s->path, s1->filename, sizeof(s->path));
      s->img_number = 0;
          st->need_parsing = AVSTREAM_PARSE_FULL;
      }
  
 -    avpriv_set_pts_info(st, 60, framerate.den, framerate.num);
 +    if (s->ts_from_file == 2) {
 +#if !HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
 +        av_log(s1, AV_LOG_ERROR, "POSIX.1-2008 not supported, nanosecond file timestamps unavailable\n");
 +        return AVERROR(ENOSYS);
 +#endif
 +        avpriv_set_pts_info(st, 64, 1, 1000000000);
 +    } else if (s->ts_from_file)
 +        avpriv_set_pts_info(st, 64, 1, 1);
 +    else
 +        avpriv_set_pts_info(st, 64, s->framerate.den, s->framerate.num);
  
 -    if (width && height) {
 -        st->codec->width  = width;
 -        st->codec->height = height;
 +    if (s->width && s->height) {
 +        st->codec->width  = s->width;
 +        st->codec->height = s->height;
      }
  
      if (!s->is_pipe) {
 -        if (find_image_range(&first_index, &last_index, s->path,
 -                             FFMAX(s->start_number, 5)) < 0)
 -            return AVERROR(ENOENT);
 +        if (s->pattern_type == PT_DEFAULT) {
 +            if (s1->pb) {
 +                s->pattern_type = PT_NONE;
 +            } else
 +                s->pattern_type = PT_GLOB_SEQUENCE;
 +        }
 +
 +        if (s->pattern_type == PT_GLOB_SEQUENCE) {
 +        s->use_glob = is_glob(s->path);
 +        if (s->use_glob) {
 +#if HAVE_GLOB
 +            char *p = s->path, *q, *dup;
 +            int gerr;
 +#endif
 +
 +            av_log(s1, AV_LOG_WARNING, "Pattern type 'glob_sequence' is deprecated: "
 +                   "use pattern_type 'glob' instead\n");
 +#if HAVE_GLOB
 +            dup = q = av_strdup(p);
 +            while (*q) {
 +                /* Do we have room for the next char and a \ insertion? */
 +                if ((p - s->path) >= (sizeof(s->path) - 2))
 +                  break;
 +                if (*q == '%' && strspn(q + 1, "%*?[]{}"))
 +                    ++q;
 +                else if (strspn(q, "\\*?[]{}"))
 +                    *p++ = '\\';
 +                *p++ = *q++;
 +            }
 +            *p = 0;
 +            av_free(dup);
 +
 +            gerr = glob(s->path, GLOB_NOCHECK|GLOB_BRACE|GLOB_NOMAGIC, NULL, &s->globstate);
 +            if (gerr != 0) {
 +                return AVERROR(ENOENT);
 +            }
 +            first_index = 0;
 +            last_index = s->globstate.gl_pathc - 1;
 +#endif
 +        }
 +        }
 +        if ((s->pattern_type == PT_GLOB_SEQUENCE && !s->use_glob) || s->pattern_type == PT_SEQUENCE) {
 +            if (find_image_range(s1->pb, &first_index, &last_index, s->path,
 +                                 s->start_number, s->start_number_range) < 0) {
 +                av_log(s1, AV_LOG_ERROR,
 +                       "Could find no file with path '%s' and index in the range %d-%d\n",
 +                       s->path, s->start_number, s->start_number + s->start_number_range - 1);
 +                return AVERROR(ENOENT);
 +            }
 +        } else if (s->pattern_type == PT_GLOB) {
 +#if HAVE_GLOB
 +            int gerr;
 +            gerr = glob(s->path, GLOB_NOCHECK|GLOB_BRACE|GLOB_NOMAGIC, NULL, &s->globstate);
 +            if (gerr != 0) {
 +                return AVERROR(ENOENT);
 +            }
 +            first_index = 0;
 +            last_index = s->globstate.gl_pathc - 1;
 +            s->use_glob = 1;
 +#else
 +            av_log(s1, AV_LOG_ERROR,
 +                   "Pattern type 'glob' was selected but globbing "
 +                   "is not supported by this libavformat build\n");
 +            return AVERROR(ENOSYS);
 +#endif
 +        } else if (s->pattern_type != PT_GLOB_SEQUENCE && s->pattern_type != PT_NONE) {
 +            av_log(s1, AV_LOG_ERROR,
 +                   "Unknown value '%d' for pattern_type option\n", s->pattern_type);
 +            return AVERROR(EINVAL);
 +        }
          s->img_first  = first_index;
          s->img_last   = last_index;
 -        s->img_number = s->start_number != 1 ? s->start_number : first_index;
 +        s->img_number = first_index;
          /* compute duration */
 -        st->start_time = 0;
 -        st->duration   = last_index - first_index + 1;
 +        if (!s->ts_from_file) {
 +            st->start_time = 0;
 +            st->duration   = last_index - first_index + 1;
 +        }
      }
  
      if (s1->video_codec_id) {
      } else if (s1->audio_codec_id) {
          st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
          st->codec->codec_id   = s1->audio_codec_id;
 +    } else if (s1->iformat->raw_codec_id) {
 +        st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
 +        st->codec->codec_id   = s1->iformat->raw_codec_id;
      } else {
 +        const char *str = strrchr(s->path, '.');
 +        s->split_planes       = str && !av_strcasecmp(str + 1, "y");
          st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
 -        st->codec->codec_id   = ff_guess_image2_codec(s->path);
 +        if (s1->pb) {
 +            int probe_buffer_size = 2048;
 +            uint8_t *probe_buffer = av_realloc(NULL, probe_buffer_size + AVPROBE_PADDING_SIZE);
 +            AVInputFormat *fmt = NULL;
 +            AVProbeData pd = { 0 };
 +
 +            if (!probe_buffer)
 +                return AVERROR(ENOMEM);
 +
 +            probe_buffer_size = avio_read(s1->pb, probe_buffer, probe_buffer_size);
 +            if (probe_buffer_size < 0) {
 +                av_free(probe_buffer);
 +                return probe_buffer_size;
 +            }
 +            memset(probe_buffer + probe_buffer_size, 0, AVPROBE_PADDING_SIZE);
 +
 +            pd.buf = probe_buffer;
 +            pd.buf_size = probe_buffer_size;
 +            pd.filename = s1->filename;
 +
 +            while ((fmt = av_iformat_next(fmt))) {
 +                if (fmt->read_header != ff_img_read_header ||
 +                    !fmt->read_probe ||
 +                    (fmt->flags & AVFMT_NOFILE) ||
 +                    !fmt->raw_codec_id)
 +                    continue;
 +                if (fmt->read_probe(&pd) > 0) {
 +                    st->codec->codec_id = fmt->raw_codec_id;
 +                    break;
 +                }
 +            }
 +            if (s1->flags & AVFMT_FLAG_CUSTOM_IO) {
 +                avio_seek(s1->pb, 0, SEEK_SET);
 +            } else
 +                ffio_rewind_with_probe_data(s1->pb, &probe_buffer, probe_buffer_size);
 +        }
 +        if (st->codec->codec_id == AV_CODEC_ID_NONE)
 +            st->codec->codec_id = ff_guess_image2_codec(s->path);
 +        if (st->codec->codec_id == AV_CODEC_ID_LJPEG)
 +            st->codec->codec_id = AV_CODEC_ID_MJPEG;
 +        if (st->codec->codec_id == AV_CODEC_ID_ALIAS_PIX) // we cannot distingiush this from BRENDER_PIX
 +            st->codec->codec_id = AV_CODEC_ID_NONE;
      }
      if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
          pix_fmt != AV_PIX_FMT_NONE)
      return 0;
  }
  
 -static int img_read_packet(AVFormatContext *s1, AVPacket *pkt)
 +int ff_img_read_packet(AVFormatContext *s1, AVPacket *pkt)
  {
      VideoDemuxData *s = s1->priv_data;
 -    char filename[1024];
 +    char filename_bytes[1024];
 +    char *filename = filename_bytes;
      int i, res;
      int size[3]           = { 0 }, ret[3] = { 0 };
      AVIOContext *f[3]     = { NULL };
      AVCodecContext *codec = s1->streams[0]->codec;
-     AVOpenCallback open_func = s1->open_cb;
-     if (!open_func)
-         open_func = ffio_open2_wrapper;
  
      if (!s->is_pipe) {
          /* loop over input */
          }
          if (s->img_number > s->img_last)
              return AVERROR_EOF;
 -        if (av_get_frame_filename(filename, sizeof(filename),
 +        if (s->pattern_type == PT_NONE) {
 +            av_strlcpy(filename_bytes, s->path, sizeof(filename_bytes));
 +        } else if (s->use_glob) {
 +#if HAVE_GLOB
 +            filename = s->globstate.gl_pathv[s->img_number];
 +#endif
 +        } else {
 +        if (av_get_frame_filename(filename_bytes, sizeof(filename_bytes),
                                    s->path,
                                    s->img_number) < 0 && s->img_number > 1)
              return AVERROR(EIO);
 +        }
          for (i = 0; i < 3; i++) {
 -            if (s1->io_open(s1, &f[i], filename, AVIO_FLAG_READ, NULL) < 0) {
 +            if (s1->pb &&
 +                !strcmp(filename_bytes, s->path) &&
 +                !s->loop &&
 +                !s->split_planes) {
 +                f[i] = s1->pb;
-             } else if (open_func(s1, &f[i], filename, AVIO_FLAG_READ,
-                            &s1->interrupt_callback, NULL) < 0) {
++            } else if (s1->io_open(s1, &f[i], filename, AVIO_FLAG_READ, NULL) < 0) {
                  if (i >= 1)
                      break;
                  av_log(s1, AV_LOG_ERROR, "Could not open file : %s\n",
              }
              size[i] = avio_size(f[i]);
  
 -            if (codec->codec_id != AV_CODEC_ID_RAWVIDEO)
 +            if (!s->split_planes)
                  break;
              filename[strlen(filename) - 1] = 'U' + i;
          }
  
 +        if (codec->codec_id == AV_CODEC_ID_NONE) {
 +            AVProbeData pd = { 0 };
 +            AVInputFormat *ifmt;
 +            uint8_t header[PROBE_BUF_MIN + AVPROBE_PADDING_SIZE];
 +            int ret;
 +            int score = 0;
 +
 +            ret = avio_read(f[0], header, PROBE_BUF_MIN);
 +            if (ret < 0)
 +                return ret;
 +            memset(header + ret, 0, sizeof(header) - ret);
 +            avio_skip(f[0], -ret);
 +            pd.buf = header;
 +            pd.buf_size = ret;
 +            pd.filename = filename;
 +
 +            ifmt = av_probe_input_format3(&pd, 1, &score);
 +            if (ifmt && ifmt->read_packet == ff_img_read_packet && ifmt->raw_codec_id)
 +                codec->codec_id = ifmt->raw_codec_id;
 +        }
 +
          if (codec->codec_id == AV_CODEC_ID_RAWVIDEO && !codec->width)
              infer_size(&codec->width, &codec->height, size[0]);
      } else {
          f[0] = s1->pb;
 -        if (f[0]->eof_reached)
 -            return AVERROR(EIO);
 -        size[0] = 4096;
 +        if (avio_feof(f[0]) && s->loop && s->is_pipe)
 +            avio_seek(f[0], 0, SEEK_SET);
 +        if (avio_feof(f[0]))
 +            return AVERROR_EOF;
 +        if (s->frame_size > 0) {
 +            size[0] = s->frame_size;
 +        } else if (!s1->streams[0]->parser) {
 +            size[0] = avio_size(s1->pb);
 +        } else {
 +            size[0] = 4096;
 +        }
      }
  
      res = av_new_packet(pkt, size[0] + size[1] + size[2]);
 -    if (res < 0)
 -        return res;
 +    if (res < 0) {
 +        goto fail;
 +    }
      pkt->stream_index = 0;
      pkt->flags       |= AV_PKT_FLAG_KEY;
 +    if (s->ts_from_file) {
 +        struct stat img_stat;
 +        if (stat(filename, &img_stat)) {
 +            res = AVERROR(EIO);
 +            goto fail;
 +        }
 +        pkt->pts = (int64_t)img_stat.st_mtime;
 +#if HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
 +        if (s->ts_from_file == 2)
 +            pkt->pts = 1000000000*pkt->pts + img_stat.st_mtim.tv_nsec;
 +#endif
 +        av_add_index_entry(s1->streams[0], s->img_number, pkt->pts, 0, 0, AVINDEX_KEYFRAME);
 +    } else if (!s->is_pipe) {
 +        pkt->pts      = s->pts;
 +    }
 +
 +    if (s->is_pipe)
 +        pkt->pos = avio_tell(f[0]);
  
      pkt->size = 0;
      for (i = 0; i < 3; i++) {
          if (f[i]) {
              ret[i] = avio_read(f[i], pkt->data + pkt->size, size[i]);
 -            if (!s->is_pipe)
 +            if (s->loop && s->is_pipe && ret[i] == AVERROR_EOF) {
 +                if (avio_seek(f[i], 0, SEEK_SET) >= 0) {
 +                    pkt->pos = 0;
 +                    ret[i] = avio_read(f[i], pkt->data + pkt->size, size[i]);
 +                }
 +            }
 +            if (!s->is_pipe && f[i] != s1->pb)
-                 avio_closep(&f[i]);
+                 ff_format_io_close(s1, &f[i]);
              if (ret[i] > 0)
                  pkt->size += ret[i];
          }
  
      if (ret[0] <= 0 || ret[1] < 0 || ret[2] < 0) {
          av_packet_unref(pkt);
 -        return AVERROR(EIO); /* signal EOF */
 +        if (ret[0] < 0) {
 +            res = ret[0];
 +        } else if (ret[1] < 0) {
 +            res = ret[1];
 +        } else if (ret[2] < 0) {
 +            res = ret[2];
 +        } else {
 +            res = AVERROR_EOF;
 +        }
 +        goto fail;
      } else {
          s->img_count++;
          s->img_number++;
 +        s->pts++;
          return 0;
      }
-                 avio_closep(&f[i]);
 +
 +fail:
 +    if (!s->is_pipe) {
 +        for (i = 0; i < 3; i++) {
 +            if (f[i] != s1->pb)
++                ff_format_io_close(s1, &f[i]);
 +        }
 +    }
 +    return res;
 +}
 +
 +static int img_read_close(struct AVFormatContext* s1)
 +{
 +#if HAVE_GLOB
 +    VideoDemuxData *s = s1->priv_data;
 +    if (s->use_glob) {
 +        globfree(&s->globstate);
 +    }
 +#endif
 +    return 0;
 +}
 +
 +static int img_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
 +{
 +    VideoDemuxData *s1 = s->priv_data;
 +    AVStream *st = s->streams[0];
 +
 +    if (s1->ts_from_file) {
 +        int index = av_index_search_timestamp(st, timestamp, flags);
 +        if(index < 0)
 +            return -1;
 +        s1->img_number = st->index_entries[index].pos;
 +        return 0;
 +    }
 +
 +    if (timestamp < 0 || !s1->loop && timestamp > s1->img_last - s1->img_first)
 +        return -1;
 +    s1->img_number = timestamp%(s1->img_last - s1->img_first + 1) + s1->img_first;
 +    s1->pts = timestamp;
 +    return 0;
  }
  
  #define OFFSET(x) offsetof(VideoDemuxData, x)
  #define DEC AV_OPT_FLAG_DECODING_PARAM
 -static const AVOption options[] = {
 -    { "pixel_format", "",                             OFFSET(pixel_format), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0,       DEC },
 -    { "video_size",   "",                             OFFSET(video_size),   AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0,       DEC },
 -    { "framerate",    "",                             OFFSET(framerate),    AV_OPT_TYPE_STRING, { .str = "25" }, 0, 0,       DEC },
 -    { "loop",         "",                             OFFSET(loop),         AV_OPT_TYPE_INT,    { .i64 = 0    }, 0, 1,       DEC },
 -    { "start_number", "first number in the sequence", OFFSET(start_number), AV_OPT_TYPE_INT,    { .i64 = 1    }, 1, INT_MAX, DEC },
 +const AVOption ff_img_options[] = {
 +    { "framerate",    "set the video framerate",             OFFSET(framerate),    AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, 0,   DEC },
 +    { "loop",         "force loop over input file sequence", OFFSET(loop),         AV_OPT_TYPE_BOOL,   {.i64 = 0   }, 0, 1,       DEC },
 +
 +    { "pattern_type", "set pattern type",                    OFFSET(pattern_type), AV_OPT_TYPE_INT,    {.i64=PT_DEFAULT}, 0,       INT_MAX, DEC, "pattern_type"},
 +    { "glob_sequence","select glob/sequence pattern type",   0, AV_OPT_TYPE_CONST,  {.i64=PT_GLOB_SEQUENCE}, INT_MIN, INT_MAX, DEC, "pattern_type" },
 +    { "glob",         "select glob pattern type",            0, AV_OPT_TYPE_CONST,  {.i64=PT_GLOB         }, INT_MIN, INT_MAX, DEC, "pattern_type" },
 +    { "sequence",     "select sequence pattern type",        0, AV_OPT_TYPE_CONST,  {.i64=PT_SEQUENCE     }, INT_MIN, INT_MAX, DEC, "pattern_type" },
 +    { "none",         "disable pattern matching",            0, AV_OPT_TYPE_CONST,  {.i64=PT_NONE         }, INT_MIN, INT_MAX, DEC, "pattern_type" },
 +
 +    { "pixel_format", "set video pixel format",              OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0,       DEC },
 +    { "start_number", "set first number in the sequence",    OFFSET(start_number), AV_OPT_TYPE_INT,    {.i64 = 0   }, INT_MIN, INT_MAX, DEC },
 +    { "start_number_range", "set range for looking at the first sequence number", OFFSET(start_number_range), AV_OPT_TYPE_INT, {.i64 = 5}, 1, INT_MAX, DEC },
 +    { "video_size",   "set video size",                      OFFSET(width),        AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0,   DEC },
 +    { "frame_size",   "force frame size in bytes",           OFFSET(frame_size),   AV_OPT_TYPE_INT,    {.i64 = 0   }, 0, INT_MAX, DEC },
 +    { "ts_from_file", "set frame timestamp from file's one", OFFSET(ts_from_file), AV_OPT_TYPE_INT,    {.i64 = 0   }, 0, 2,       DEC, "ts_type" },
 +    { "none", "none",                   0, AV_OPT_TYPE_CONST,    {.i64 = 0   }, 0, 2,       DEC, "ts_type" },
 +    { "sec",  "second precision",       0, AV_OPT_TYPE_CONST,    {.i64 = 1   }, 0, 2,       DEC, "ts_type" },
 +    { "ns",   "nano second precision",  0, AV_OPT_TYPE_CONST,    {.i64 = 2   }, 0, 2,       DEC, "ts_type" },
      { NULL },
  };
  
  static const AVClass img2_class = {
      .class_name = "image2 demuxer",
      .item_name  = av_default_item_name,
 -    .option     = options,
 +    .option     = ff_img_options,
      .version    = LIBAVUTIL_VERSION_INT,
  };
  AVInputFormat ff_image2_demuxer = {
      .long_name      = NULL_IF_CONFIG_SMALL("image2 sequence"),
      .priv_data_size = sizeof(VideoDemuxData),
      .read_probe     = img_read_probe,
 -    .read_header    = img_read_header,
 -    .read_packet    = img_read_packet,
 +    .read_header    = ff_img_read_header,
 +    .read_packet    = ff_img_read_packet,
 +    .read_close     = img_read_close,
 +    .read_seek      = img_read_seek,
      .flags          = AVFMT_NOFILE,
      .priv_class     = &img2_class,
  };
  static const AVClass img2pipe_class = {
      .class_name = "image2pipe demuxer",
      .item_name  = av_default_item_name,
 -    .option     = options,
 +    .option     = ff_img_options,
      .version    = LIBAVUTIL_VERSION_INT,
  };
  AVInputFormat ff_image2pipe_demuxer = {
      .name           = "image2pipe",
      .long_name      = NULL_IF_CONFIG_SMALL("piped image2 sequence"),
      .priv_data_size = sizeof(VideoDemuxData),
 -    .read_header    = img_read_header,
 -    .read_packet    = img_read_packet,
 +    .read_header    = ff_img_read_header,
 +    .read_packet    = ff_img_read_packet,
      .priv_class     = &img2pipe_class,
  };
  #endif
 +
 +static int bmp_probe(AVProbeData *p)
 +{
 +    const uint8_t *b = p->buf;
 +    int ihsize;
 +
 +    if (AV_RB16(b) != 0x424d)
 +        return 0;
 +
 +    ihsize = AV_RL32(b+14);
 +    if (ihsize < 12 || ihsize > 255)
 +        return 0;
 +
 +    if (!AV_RN32(b + 6)) {
 +        return AVPROBE_SCORE_EXTENSION + 1;
 +    }
 +    return AVPROBE_SCORE_EXTENSION / 4;
 +}
 +
 +static int dds_probe(AVProbeData *p)
 +{
 +    const uint8_t *b = p->buf;
 +
 +    if (   AV_RB64(b) == 0x444453207c000000
 +        && AV_RL32(b +  8)
 +        && AV_RL32(b + 12))
 +        return AVPROBE_SCORE_MAX - 1;
 +    return 0;
 +}
 +
 +static int dpx_probe(AVProbeData *p)
 +{
 +    const uint8_t *b = p->buf;
 +    int w, h;
 +    int is_big = (AV_RN32(b) == AV_RN32("SDPX"));
 +
 +    if (p->buf_size < 0x304+8)
 +        return 0;
 +    w = is_big ? AV_RB32(p->buf + 0x304) : AV_RL32(p->buf + 0x304);
 +    h = is_big ? AV_RB32(p->buf + 0x308) : AV_RL32(p->buf + 0x308);
 +    if (w <= 0 || h <= 0)
 +        return 0;
 +
 +    if (is_big || AV_RN32(b) == AV_RN32("XPDS"))
 +        return AVPROBE_SCORE_EXTENSION + 1;
 +    return 0;
 +}
 +
 +static int exr_probe(AVProbeData *p)
 +{
 +    const uint8_t *b = p->buf;