]> git.webhop.me Git - bs-cst-neutrino-hd.git/commitdiff
cleanup ffmpeg patches
authorMarkham <markham001@gmx.de>
Wed, 3 May 2017 18:33:57 +0000 (20:33 +0200)
committerMarkham <markham001@gmx.de>
Wed, 3 May 2017 18:33:57 +0000 (20:33 +0200)
archive-patches/ffmpeg-0.8.6-dvbsubs.diff [deleted file]
archive-patches/ffmpeg-aac-2.8.x.patch [deleted file]
archive-patches/ffmpeg-dvbsubs.diff [deleted file]
archive-patches/ffmpeg-export-missing-symbol.diff [deleted file]
archive-patches/ffmpeg-fixed-memleak-in-mpegts-demuxer-on-some-malformed-mpegts-files.patch [deleted file]
archive-patches/ffmpeg-hds-libroxml-2.8.x.patch [deleted file]

diff --git a/archive-patches/ffmpeg-0.8.6-dvbsubs.diff b/archive-patches/ffmpeg-0.8.6-dvbsubs.diff
deleted file mode 100644 (file)
index 4e88e75..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
---- ffmpeg-0.8.6/libavcodec/dvbsubdec.c        2011-09-22 02:39:22.000000000 +0200
-+++ ffmpeg-0.8.6/libavcodec/dvbsubdec.c        2011-11-13 13:16:29.000000000 +0100
-@@ -23,7 +23,9 @@
- #include "get_bits.h"
- #include "bytestream.h"
- #include "libavutil/colorspace.h"
-+#include <unistd.h>
-+#define DEBUG
- #define DVBSUB_PAGE_SEGMENT     0x10
- #define DVBSUB_REGION_SEGMENT   0x11
- #define DVBSUB_CLUT_SEGMENT     0x12
-@@ -101,6 +103,10 @@
-     char fname[40], fname2[40];
-     char command[1024];
-+#ifdef DEBUG
-+    av_log(0, AV_LOG_INFO, "SAVE FILE: %s\n", filename);
-+#endif
-+
-     snprintf(fname, sizeof(fname), "%s.ppm", filename);
-     f = fopen(fname, "w");
-@@ -142,11 +148,13 @@
-     }
-     fclose(f);
-+#if 0
-     snprintf(command, sizeof(command), "pnmtopng -alpha %s %s > %s.png 2> /dev/null", fname2, fname, filename);
-     system(command);
-     snprintf(command, sizeof(command), "rm %s %s", fname, fname2);
-     system(command);
-+#endif
- }
- #endif
-@@ -789,8 +797,8 @@
-         y_pos++;
-     while (buf < buf_end) {
--        if (x_pos > region->width || y_pos > region->height) {
--            av_log(avctx, AV_LOG_ERROR, "Invalid object location!\n");
-+        if (x_pos > region->width || y_pos >= region->height) {
-+            av_log(avctx, AV_LOG_ERROR, "Invalid object location: x %d y %d, region %dx%d\n", x_pos, y_pos, region->width, region->height);
-             return;
-         }
-@@ -989,7 +997,9 @@
-         YUV_TO_RGB1_CCIR(cb, cr);
-         YUV_TO_RGB2_CCIR(r, g, b, y);
-+#ifdef DEBUG_CLUT
-         av_dlog(avctx, "clut %d := (%d,%d,%d,%d)\n", entry_id, r, g, b, alpha);
-+#endif
-         if (depth & 0x80)
-             clut->clut4[entry_id] = RGBA(r,g,b,255 - alpha);
-@@ -1332,6 +1342,10 @@
-     int i;
-     int offset_x=0, offset_y=0;
-+#ifdef DEBUG
-+    av_log(avctx, AV_LOG_INFO, "************** dvbsub_display_end_segment ******************\n");
-+#endif
-+
-     sub->end_display_time = ctx->time_out * 1000;
-     if (display_def) {
-@@ -1412,6 +1426,11 @@
-     int segment_type;
-     int page_id;
-     int segment_length;
-+
-+#ifdef DEBUG
-+    av_log(avctx, AV_LOG_INFO, "dvbsub_decode: ctx %x data %x data_size %x (%d) avpkt %x len %d\n", avctx, data, data_size, *data_size, avpkt, buf_size);
-+#endif
-+
-     int i;
-     av_dlog(avctx, "DVB sub packet:\n");
-@@ -1442,28 +1461,50 @@
-         p += 2;
-         if (p_end - p < segment_length) {
--            av_dlog(avctx, "incomplete or broken packet");
--            return -1;
-+            //av_dlog(avctx, "incomplete or broken packet");
-+          av_log(avctx, AV_LOG_INFO, "incomplete or broken packet, size %d, processed %d\n", p_end-p, p_end-buf);
-+            //return -1;
-         }
--        if (page_id == ctx->composition_id || page_id == ctx->ancillary_id ||
--            ctx->composition_id == -1 || ctx->ancillary_id == -1) {
-+        //if (page_id == ctx->composition_id || page_id == ctx->ancillary_id ||
-+            //ctx->composition_id == -1 || ctx->ancillary_id == -1) {
-+          {
-             switch (segment_type) {
-             case DVBSUB_PAGE_SEGMENT:
-+#ifdef DEBUG
-+                av_log(avctx, AV_LOG_INFO, "DVBSUB_PAGE_SEGMENT: page id %d, length %d (composition_id %d ancillary_id %d)\n",
-+                              page_id, segment_length, ctx->composition_id, ctx->ancillary_id);
-+#endif
-                 dvbsub_parse_page_segment(avctx, p, segment_length);
-                 break;
-             case DVBSUB_REGION_SEGMENT:
-+#ifdef DEBUG
-+                 av_log(avctx, AV_LOG_INFO, "DVBSUB_REGION_SEGMENT: page id %d, length %d (composition_id %d ancillary_id %d)\n",
-+                               page_id, segment_length, ctx->composition_id, ctx->ancillary_id);
-+#endif
-                 dvbsub_parse_region_segment(avctx, p, segment_length);
-                 break;
-             case DVBSUB_CLUT_SEGMENT:
-+#ifdef DEBUG
-+                av_log(avctx, AV_LOG_INFO, "DVBSUB_CLUT_SEGMENT: page id %d, length %d (composition_id %d ancillary_id %d)\n",
-+                              page_id, segment_length, ctx->composition_id, ctx->ancillary_id);
-+#endif
-                 dvbsub_parse_clut_segment(avctx, p, segment_length);
-                 break;
-             case DVBSUB_OBJECT_SEGMENT:
-+#ifdef DEBUG
-+                av_log(avctx, AV_LOG_INFO, "DVBSUB_OBJECT_SEGMENT: page id %d, length %d (composition_id %d ancillary_id %d)\n",
-+                              page_id, segment_length, ctx->composition_id, ctx->ancillary_id);
-+#endif
-                 dvbsub_parse_object_segment(avctx, p, segment_length);
-                 break;
-             case DVBSUB_DISPLAYDEFINITION_SEGMENT:
-                 dvbsub_parse_display_definition_segment(avctx, p, segment_length);
-             case DVBSUB_DISPLAY_SEGMENT:
-+#ifdef DEBUG
-+                av_log(avctx, AV_LOG_INFO, "DVBSUB_DISPLAY_SEGMENT: page id %d, length %d (composition_id %d ancillary_id %d)\n",
-+                              page_id, segment_length, ctx->composition_id, ctx->ancillary_id);
-+#endif
-                 *data_size = dvbsub_display_end_segment(avctx, p, segment_length, sub);
-                 break;
-             default:
diff --git a/archive-patches/ffmpeg-aac-2.8.x.patch b/archive-patches/ffmpeg-aac-2.8.x.patch
deleted file mode 100644 (file)
index 9ce3595..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
---- a/libavcodec/aacdec_template.c
-+++ b/libavcodec/aacdec_template.c
-@@ -2347,7 +2347,7 @@
-  * @param   decode  1 if tool is used normally, 0 if tool is used in LTP.
-  * @param   coef    spectral coefficients
-  */
--static void apply_tns(INTFLOAT coef[1024], TemporalNoiseShaping *tns,
-+static __attribute__((optimize(0))) void apply_tns(INTFLOAT coef[1024], TemporalNoiseShaping *tns,
-                       IndividualChannelStream *ics, int decode)
- {
-     const int mmm = FFMIN(ics->tns_max_bands, ics->max_sfb);
---- a/libavcodec/mdct_template.c
-+++ b/libavcodec/mdct_template.c
-@@ -101,7 +101,7 @@ av_cold int ff_mdct_init(FFTContext *s, int nbits, int inverse, double scale)
-  * @param output N/2 samples
-  * @param input N/2 samples
-  */
--void ff_imdct_half_c(FFTContext *s, FFTSample *output, const FFTSample *input)
-+void __attribute__((optimize(0))) ff_imdct_half_c(FFTContext *s, FFTSample *output, const FFTSample *input)
- {
-     int k, n8, n4, n2, n, j;
-     const uint16_t *revtab = s->revtab;
---- a/libavcodec/aacps.c
-+++ b/libavcodec/aacps.c
-@@ -654,7 +654,7 @@
-     par[ 1] = AAC_HALF_SUM(par[ 0], par[ 1]);
- }
--static void decorrelation(PSContext *ps, INTFLOAT (*out)[32][2], const INTFLOAT (*s)[32][2], int is34)
-+static void __attribute__((optimize(0))) decorrelation(PSContext *ps, INTFLOAT (*out)[32][2], const INTFLOAT (*s)[32][2], int is34)
- {
-     LOCAL_ALIGNED_16(INTFLOAT, power, [34], [PS_QMF_TIME_SLOTS]);
-     LOCAL_ALIGNED_16(INTFLOAT, transient_gain, [34], [PS_QMF_TIME_SLOTS]);
---- a/libavcodec/fft_template.c
-+++ b/libavcodec/fft_template.c
-@@ -452,7 +452,7 @@
-     pass(z,FFT_NAME(ff_cos_##n),n4/2);\
- }
--static void fft4(FFTComplex *z)
-+static void __attribute__((optimize(0))) fft4(FFTComplex *z)
- {
-     FFTDouble t1, t2, t3, t4, t5, t6, t7, t8;
-@@ -466,7 +466,7 @@
-     BF(z[2].im, z[0].im, t2, t5);
- }
--static void fft8(FFTComplex *z)
-+static void __attribute__((optimize(0))) fft8(FFTComplex *z)
- {
-     FFTDouble t1, t2, t3, t4, t5, t6;
diff --git a/archive-patches/ffmpeg-dvbsubs.diff b/archive-patches/ffmpeg-dvbsubs.diff
deleted file mode 100644 (file)
index 5a8057e..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
---- ffmpeg-0.7-rc1/libavcodec/dvbsubdec.c      2011-04-27 00:58:23.000000000 +0200
-+++ ffmpeg-0.7-rc1/libavcodec/dvbsubdec.c      2011-05-28 18:38:29.000000000 +0200
-@@ -23,8 +23,10 @@
- #include "get_bits.h"
- #include "bytestream.h"
- #include "libavutil/colorspace.h"
-+#include <unistd.h>
--//#define DEBUG
-+#define DEBUG
-+//#define DEBUG_CLUT
- //#define DEBUG_PACKET_CONTENTS
- //#define DEBUG_SAVE_IMAGES
-@@ -104,12 +106,16 @@
-     char fname[40], fname2[40];
-     char command[1024];
-+#ifdef DEBUG
-+    av_log(0, AV_LOG_INFO, "SAVE FILE: %s\n", filename);
-+#endif
-     snprintf(fname, sizeof(fname), "%s.ppm", filename);
-     f = fopen(fname, "w");
-     if (!f) {
-         perror(fname);
--        exit(1);
-+        //exit(1);
-+        return;
-     }
-     fprintf(f, "P6\n"
-             "%d %d\n"
-@@ -131,7 +137,8 @@
-     f = fopen(fname2, "w");
-     if (!f) {
-         perror(fname2);
--        exit(1);
-+        //exit(1);
-+        return;
-     }
-     fprintf(f, "P5\n"
-             "%d %d\n"
-@@ -145,11 +152,13 @@
-     }
-     fclose(f);
-+#if 0
-     snprintf(command, sizeof(command), "pnmtopng -alpha %s %s > %s.png 2> /dev/null", fname2, fname, filename);
-     system(command);
-     snprintf(command, sizeof(command), "rm %s %s", fname, fname2);
-     system(command);
-+#endif
- }
- #endif
-@@ -777,8 +786,8 @@
-         y_pos++;
-     while (buf < buf_end) {
--        if (x_pos > region->width || y_pos > region->height) {
--            av_log(avctx, AV_LOG_ERROR, "Invalid object location!\n");
-+        if (x_pos > region->width || y_pos >= region->height) {
-+            av_log(avctx, AV_LOG_ERROR, "Invalid object location: x %d y %d, region %dx%d\n", x_pos, y_pos, region->width, region->height);
-             return;
-         }
-@@ -982,7 +991,9 @@
-         YUV_TO_RGB1_CCIR(cb, cr);
-         YUV_TO_RGB2_CCIR(r, g, b, y);
-+#ifdef DEBUG_CLUT
-         av_dlog(avctx, "clut %d := (%d,%d,%d,%d)\n", entry_id, r, g, b, alpha);
-+#endif
-         if (depth & 0x80)
-             clut->clut4[entry_id] = RGBA(r,g,b,255 - alpha);
-@@ -1323,6 +1334,10 @@
-     int i;
-     int offset_x=0, offset_y=0;
-+#ifdef DEBUG
-+    av_log(avctx, AV_LOG_INFO, "************** dvbsub_display_end_segment ******************\n");
-+#endif
-+
-     sub->end_display_time = ctx->time_out * 1000;
-     if (display_def) {
-@@ -1404,6 +1419,10 @@
-     int page_id;
-     int segment_length;
-+#ifdef DEBUG
-+    av_log(avctx, AV_LOG_INFO, "dvbsub_decode: ctx %x data %x data_size %x (%d) avpkt %x len %d\n", avctx, data, data_size, *data_size, avpkt, buf_size);
-+#endif
-+
- #ifdef DEBUG_PACKET_CONTENTS
-     int i;
-@@ -1437,28 +1456,50 @@
-         p += 2;
-         if (p_end - p < segment_length) {
--            av_dlog(avctx, "incomplete or broken packet");
--            return -1;
-+            //av_dlog(avctx, "incomplete or broken packet");
-+          av_log(avctx, AV_LOG_INFO, "incomplete or broken packet, size %d, processed %d\n", p_end-p, p_end-buf);
-+            //return -1;
-         }
--        if (page_id == ctx->composition_id || page_id == ctx->ancillary_id ||
--            ctx->composition_id == -1 || ctx->ancillary_id == -1) {
-+        //if (page_id == ctx->composition_id || page_id == ctx->ancillary_id ||
-+            //ctx->composition_id == -1 || ctx->ancillary_id == -1) {
-+          {
-             switch (segment_type) {
-             case DVBSUB_PAGE_SEGMENT:
-+#ifdef DEBUG
-+                av_log(avctx, AV_LOG_INFO, "DVBSUB_PAGE_SEGMENT: page id %d, length %d (composition_id %d ancillary_id %d)\n",
-+                              page_id, segment_length, ctx->composition_id, ctx->ancillary_id);
-+#endif
-                 dvbsub_parse_page_segment(avctx, p, segment_length);
-                 break;
-             case DVBSUB_REGION_SEGMENT:
-+#ifdef DEBUG
-+                 av_log(avctx, AV_LOG_INFO, "DVBSUB_REGION_SEGMENT: page id %d, length %d (composition_id %d ancillary_id %d)\n",
-+                               page_id, segment_length, ctx->composition_id, ctx->ancillary_id);
-+#endif
-                 dvbsub_parse_region_segment(avctx, p, segment_length);
-                 break;
-             case DVBSUB_CLUT_SEGMENT:
-+#ifdef DEBUG
-+                av_log(avctx, AV_LOG_INFO, "DVBSUB_CLUT_SEGMENT: page id %d, length %d (composition_id %d ancillary_id %d)\n",
-+                              page_id, segment_length, ctx->composition_id, ctx->ancillary_id);
-+#endif
-                 dvbsub_parse_clut_segment(avctx, p, segment_length);
-                 break;
-             case DVBSUB_OBJECT_SEGMENT:
-+#ifdef DEBUG
-+                av_log(avctx, AV_LOG_INFO, "DVBSUB_OBJECT_SEGMENT: page id %d, length %d (composition_id %d ancillary_id %d)\n",
-+                              page_id, segment_length, ctx->composition_id, ctx->ancillary_id);
-+#endif
-                 dvbsub_parse_object_segment(avctx, p, segment_length);
-                 break;
-             case DVBSUB_DISPLAYDEFINITION_SEGMENT:
-                 dvbsub_parse_display_definition_segment(avctx, p, segment_length);
-             case DVBSUB_DISPLAY_SEGMENT:
-+#ifdef DEBUG
-+                av_log(avctx, AV_LOG_INFO, "DVBSUB_DISPLAY_SEGMENT: page id %d, length %d (composition_id %d ancillary_id %d)\n",
-+                              page_id, segment_length, ctx->composition_id, ctx->ancillary_id);
-+#endif
-                 *data_size = dvbsub_display_end_segment(avctx, p, segment_length, sub);
-                 break;
-             default:
diff --git a/archive-patches/ffmpeg-export-missing-symbol.diff b/archive-patches/ffmpeg-export-missing-symbol.diff
deleted file mode 100644 (file)
index 1b9e364..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-Index: b/libavformat/avformat.h
-===================================================================
---- a/libavformat/avformat.h
-+++ b/libavformat/avformat.h
-@@ -206,16 +206,19 @@ int av_dup_packet(AVPacket *pkt);
- /**
-  * Free a packet.
-  *
-  * @param pkt packet to free
-  */
-+void av_free_packet(AVPacket *pkt);
-+#if 0
- static inline void av_free_packet(AVPacket *pkt)
- {
-     if (pkt && pkt->destruct) {
-         pkt->destruct(pkt);
-     }
- }
-+#endif
- /*************************************************/
- /* fractional numbers for exact pts handling */
- /**
-Index: b/libavformat/mmf.c
-===================================================================
---- a/libavformat/mmf.c
-+++ b/libavformat/mmf.c
-@@ -314,5 +314,12 @@ AVOutputFormat mmf_muxer = {
-     mmf_write_header,
-     mmf_write_packet,
-     mmf_write_trailer,
- };
- #endif
-+
-+void av_free_packet(AVPacket *pkt)
-+{
-+    if (pkt && pkt->destruct) {
-+        pkt->destruct(pkt);
-+    }
-+}
diff --git a/archive-patches/ffmpeg-fixed-memleak-in-mpegts-demuxer-on-some-malformed-mpegts-files.patch b/archive-patches/ffmpeg-fixed-memleak-in-mpegts-demuxer-on-some-malformed-mpegts-files.patch
deleted file mode 100644 (file)
index d280124..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-From cb7c19124165508ae5f38a385a14f9c13b096a27 Mon Sep 17 00:00:00 2001
-From: Joakim Plate <elupus@ecce.se>
-Date: Fri, 26 Nov 2010 20:56:48 +0000
-Subject: [PATCH 10/13] fixed: memleak in mpegts demuxer on some malformed (??)
- mpegts files with too large pes packets
-
-at-visions sample file brokenStream.mpg
-
-Patch part of the XBMC patch set for ffmpeg, downloaded from
-https://github.com/xbmc/FFmpeg/.
-
-Signed-off-by: Bernd Kuhls <bernd.kuhls@t-online.de>
-Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
----
- libavformat/mpegts.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
-diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
-index d5a8a45..e070f1f 100644
---- a/libavformat/mpegts.c
-+++ b/libavformat/mpegts.c
-@@ -850,6 +850,10 @@ static void reset_pes_packet_state(PESContext *pes)
- static void new_pes_packet(PESContext *pes, AVPacket *pkt)
- {
-+    if(pkt->data) {
-+      av_log(pes->stream, AV_LOG_ERROR, "ignoring previously allocated packet on stream %d\n", pkt->stream_index);
-+      av_free_packet(pkt);
-+    }
-     av_init_packet(pkt);
-     pkt->buf  = pes->buffer;
-@@ -2644,6 +2649,8 @@ static int mpegts_read_packet(AVFormatContext *s, AVPacket *pkt)
-     pkt->size = -1;
-     ts->pkt = pkt;
-+    ts->pkt->data = NULL;
-+
-     ret = handle_packets(ts, 0);
-     if (ret < 0) {
-         av_free_packet(ts->pkt);
--- 
-2.1.0
-
diff --git a/archive-patches/ffmpeg-hds-libroxml-2.8.x.patch b/archive-patches/ffmpeg-hds-libroxml-2.8.x.patch
deleted file mode 100644 (file)
index 807e1df..0000000
+++ /dev/null
@@ -1,2775 +0,0 @@
-From a311102d78840d25474d0158db478862bef5ae59 Mon Sep 17 00:00:00 2001
-From: Jacek Jendrzej <crashdvb@googlemail.com>
-Date: Thu, 23 Apr 2015 19:57:16 +0200
-Subject: [PATCH 1/4] add HDS ro
-
-Signed-off-by: Jacek Jendrzej <crashdvb@googlemail.com>
----
- configure                 |    5 +
- libavformat/Makefile      |    1 +
- libavformat/allformats.c  |    2 +-
- libavformat/amfmetadata.c |  290 +++++++++++++
- libavformat/amfmetadata.h |   47 ++
- libavformat/f4fbox.c      |  345 +++++++++++++++
- libavformat/f4fbox.h      |  110 +++++
- libavformat/f4mmanifest.c |  256 +++++++++++
- libavformat/f4mmanifest.h |   65 +++
- libavformat/flv.h         |    2 +
- libavformat/flvdec.c      |    5 +
- libavformat/flvtag.c      |  408 ++++++++++++++++++
- libavformat/flvtag.h      |   40 ++
- libavformat/hdsdec.c      | 1036 +++++++++++++++++++++++++++++++++++++++++++++
- 14 files changed, 2611 insertions(+), 1 deletion(-)
- create mode 100644 libavformat/amfmetadata.c
- create mode 100644 libavformat/amfmetadata.h
- create mode 100644 libavformat/f4fbox.c
- create mode 100644 libavformat/f4fbox.h
- create mode 100644 libavformat/f4mmanifest.c
- create mode 100644 libavformat/f4mmanifest.h
- create mode 100644 libavformat/flvtag.c
- create mode 100644 libavformat/flvtag.h
- create mode 100644 libavformat/hdsdec.c
-
-diff --git a/configure b/configure
-index 2eada0e..30f75e0 100755
---- a/configure
-+++ b/configure
-@@ -284,6 +284,7 @@
-   --enable-x11grab         enable X11 grabbing (legacy) [no]
-   --disable-xlib           disable xlib [autodetect]
-   --disable-zlib           disable zlib [autodetect]
-+  --disable-libroxml       disable XML parsing using the C library libroxml [autodetect]
- Toolchain options:
-   --arch=ARCH              select architecture [$arch]
-@@ -1395,6 +1396,7 @@
-     libopus
-     libpulse
-     libquvi
-+    libroxml
-     librtmp
-     libschroedinger
-     libshine
-@@ -2580,6 +2582,7 @@
- eac3_demuxer_select="ac3_parser"
- f4v_muxer_select="mov_muxer"
- flac_demuxer_select="flac_parser"
-+hds_demuxer_select="libroxml"
- hds_muxer_select="flv_muxer"
- hls_muxer_select="mpegts_muxer"
- image2_alias_pix_demuxer_select="image2_demuxer"
-@@ -5193,6 +5196,8 @@
- disabled bzlib || check_lib2 bzlib.h BZ2_bzlibVersion -lbz2 || disable bzlib
- disabled  lzma || check_lib2  lzma.h lzma_version_number -llzma || disable lzma
-+disabled libroxml || check_lib roxml.h roxml_load_buf -lroxml || disable libroxml
-+
- check_lib math.h sin -lm && LIBM="-lm"
- disabled crystalhd || check_lib libcrystalhd/libcrystalhd_if.h DtsCrystalHDVersion -lcrystalhd || disable crystalhd
-diff --git a/libavformat/Makefile b/libavformat/Makefile
-index bca9d5b..e8334c0 100644
---- a/libavformat/Makefile
-+++ b/libavformat/Makefile
-@@ -183,6 +183,7 @@ OBJS-$(CONFIG_H263_DEMUXER)              += h263dec.o rawdec.o
- OBJS-$(CONFIG_H263_MUXER)                += rawenc.o
- OBJS-$(CONFIG_H264_DEMUXER)              += h264dec.o rawdec.o
- OBJS-$(CONFIG_H264_MUXER)                += rawenc.o
-+OBJS-$(CONFIG_HDS_DEMUXER)               += hdsdec.o amfmetadata.o f4mmanifest.o f4fbox.o flvtag.o
- OBJS-$(CONFIG_HDS_MUXER)                 += hdsenc.o
- OBJS-$(CONFIG_HEVC_DEMUXER)              += hevcdec.o rawdec.o
- OBJS-$(CONFIG_HEVC_MUXER)                += rawenc.o
-diff --git a/libavformat/allformats.c b/libavformat/allformats.c
-index 0f53d4c..06652e5 100644
---- a/libavformat/allformats.c
-+++ b/libavformat/allformats.c
-@@ -143,7 +143,7 @@ void av_register_all(void)
-     REGISTER_MUXDEMUX(H261,             h261);
-     REGISTER_MUXDEMUX(H263,             h263);
-     REGISTER_MUXDEMUX(H264,             h264);
--    REGISTER_MUXER   (HDS,              hds);
-+    REGISTER_MUXDEMUX(HDS,              hds);
-     REGISTER_MUXDEMUX(HEVC,             hevc);
-     REGISTER_MUXDEMUX(HLS,              hls);
-     REGISTER_DEMUXER (HNM,              hnm);
-diff --git a/libavformat/amfmetadata.c b/libavformat/amfmetadata.c
-new file mode 100644
-index 0000000..f2fe7ca
---- /dev/null
-+++ b/libavformat/amfmetadata.c
-@@ -0,0 +1,290 @@
-+/*
-+ * Adobe Action Message Format Parser
-+ * Copyright (c) 2013 Cory McCarthy
-+ *
-+ * This file is part of FFmpeg.
-+ *
-+ * 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.
-+ *
-+ * 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 FFmpeg; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-+ */
-+
-+/**
-+ * @file
-+ * @brief Adobe Action Message Format Parser
-+ * @author Cory McCarthy
-+ * @see http://download.macromedia.com/f4v/video_file_format_spec_v10_1.pdf
-+ * @see http://www.adobe.com/content/dam/Adobe/en/devnet/amf/pdf/amf-file-format-spec.pdf
-+ */
-+
-+#include "amfmetadata.h"
-+#include "avio_internal.h"
-+#include "flv.h"
-+#include "libavutil/avstring.h"
-+#include "libavutil/intfloat.h"
-+#include "libavformat/avformat.h"
-+
-+static int amf_metadata_parse_value(AVIOContext *in, AMFMetadata *metadata, const char *name);
-+
-+static int amf_metadata_read_string_value(AVIOContext *in, char *str, int str_size)
-+{
-+    uint8_t type;
-+
-+    type = avio_r8(in);
-+    if(type != 0x02) {
-+      av_log(NULL, AV_LOG_ERROR, "amfmetadata Expected type 2, type = %d \n", type);
-+      return -1;
-+    }
-+
-+    return flv_amf_get_string(in, str, str_size);
-+}
-+
-+static void amf_metadata_assign_property_number(AMFMetadata *metadata,
-+    const char *name, double value)
-+{
-+    if(!av_strcasecmp("width", name)) {
-+      metadata->width = (int)value;
-+    }
-+    else
-+    if(!av_strcasecmp("height", name)) {
-+      metadata->height = (int)value;
-+    }
-+    else
-+    if(!av_strcasecmp("framerate", name)) {
-+      metadata->frame_rate = (int)value;
-+    }
-+    else
-+    if(!av_strcasecmp("videodatarate", name)) {
-+      metadata->video_data_rate = (int)value;
-+    }
-+    else
-+    if(!av_strcasecmp("audiosamplerate", name)) {
-+      metadata->audio_sample_rate = (int)value;
-+    }
-+    else
-+    if(!av_strcasecmp("audiosamplesize", name)) {
-+      metadata->audio_sample_size = (int)value;
-+    }
-+    else
-+    if(!av_strcasecmp("audiochannels", name)) {
-+      metadata->nb_audio_channels = (int)value;
-+    }
-+    else
-+    if(!av_strcasecmp("stereo", name)) {
-+      metadata->nb_audio_channels = ((int)value) ? 2 : 1;
-+    }
-+    else
-+    if(!av_strcasecmp("audiodatarate", name)) {
-+      metadata->audio_data_rate = (int)value;
-+    }
-+    else
-+    if(!av_strcasecmp("audiocodecid", name)) {
-+      switch(FLV_AUDIO_CODECID_MASK & ((int)value << FLV_AUDIO_CODECID_OFFSET)) {
-+      case FLV_CODECID_PCM:
-+          metadata->audio_codec_id = metadata->audio_sample_size == 8
-+                                     ? AV_CODEC_ID_PCM_U8
-+#if HAVE_BIGENDIAN
-+                                     : AV_CODEC_ID_PCM_S16BE;
-+#else
-+                                     : AV_CODEC_ID_PCM_S16LE;
-+#endif
-+          break;
-+      case FLV_CODECID_ADPCM:
-+          metadata->audio_codec_id = AV_CODEC_ID_ADPCM_SWF;
-+          break;
-+      case FLV_CODECID_MP3:
-+          metadata->audio_stream_need_parsing = AVSTREAM_PARSE_FULL;
-+          metadata->audio_codec_id = AV_CODEC_ID_MP3;
-+          break;
-+      case FLV_CODECID_PCM_LE:
-+          metadata->audio_codec_id = metadata->audio_sample_size == 8
-+                                     ? AV_CODEC_ID_PCM_U8
-+                                     : AV_CODEC_ID_PCM_S16LE;
-+          break;
-+      case FLV_CODECID_NELLYMOSER_16KHZ_MONO:
-+          if (!metadata->audio_sample_rate)
-+              metadata->audio_sample_rate = 16000;
-+          metadata->nb_audio_channels = 1;
-+          metadata->audio_codec_id = AV_CODEC_ID_NELLYMOSER;
-+          break;
-+      case FLV_CODECID_NELLYMOSER_8KHZ_MONO:
-+          if (!metadata->audio_sample_rate)
-+              metadata->audio_sample_rate = 8000;
-+          metadata->nb_audio_channels = 1;
-+          metadata->audio_codec_id = AV_CODEC_ID_NELLYMOSER;
-+          break;
-+      case FLV_CODECID_NELLYMOSER:
-+          metadata->audio_codec_id = AV_CODEC_ID_NELLYMOSER;
-+          break;
-+      case FLV_CODECID_PCM_ALAW:
-+          metadata->audio_sample_rate = 8000;
-+          metadata->audio_codec_id = AV_CODEC_ID_PCM_ALAW;
-+          break;
-+      case FLV_CODECID_PCM_MULAW:
-+          metadata->audio_sample_rate = 8000;
-+          metadata->audio_codec_id = AV_CODEC_ID_PCM_MULAW;
-+          break;
-+      case FLV_CODECID_AAC:
-+          metadata->audio_codec_id = AV_CODEC_ID_AAC;
-+          break;
-+      case FLV_CODECID_SPEEX:
-+          metadata->audio_sample_rate = 16000;
-+          metadata->audio_codec_id = AV_CODEC_ID_SPEEX;
-+          break;
-+      default:
-+          break;
-+      }
-+    }
-+    else
-+    if(!av_strcasecmp("videocodecid", name)) {
-+      if((int)value == 7)
-+          metadata->video_codec_id = AV_CODEC_ID_H264;
-+    }
-+}
-+
-+static void amf_metadata_assign_property_string(AMFMetadata *metadata,
-+    const char *name, const char *value)
-+{
-+    if(!av_strcasecmp("audiocodecid", name)) {
-+      if(!av_strcasecmp("mp4a", value))
-+          metadata->audio_codec_id = AV_CODEC_ID_AAC;
-+      else if(!av_strcasecmp(".mp3", value)) {
-+          metadata->audio_stream_need_parsing = AVSTREAM_PARSE_FULL;
-+          metadata->audio_codec_id = AV_CODEC_ID_MP3;
-+      }
-+      else
-+          av_log(NULL, AV_LOG_ERROR, "amfmetadata audiocodecid=%s unhandled\n", value);
-+    }
-+    else
-+    if(!av_strcasecmp("videocodecid", name)) {
-+      if(!av_strcasecmp("avc1", value))
-+          metadata->video_codec_id = AV_CODEC_ID_H264;
-+      else
-+          av_log(NULL, AV_LOG_ERROR, "amfmetadata videocodecid=%s unhandled\n", value);
-+    }
-+}
-+
-+static int amf_metadata_parse_object_property(AVIOContext *in, AMFMetadata *metadata)
-+{
-+    char name[INT16_MAX];
-+    int ret;
-+
-+    if((ret = flv_amf_get_string(in, name, sizeof(name))) < 0)
-+      return ret;
-+
-+    return amf_metadata_parse_value(in, metadata, name);
-+}
-+
-+static int amf_metadata_parse_object(AVIOContext *in, AMFMetadata *metadata)
-+{
-+    int ret;
-+
-+    while(!url_feof(in))
-+      if((ret = amf_metadata_parse_object_property(in, metadata)) < 0)
-+          break;
-+
-+    return 0;
-+}
-+
-+static int amf_metadata_parse_strict_array(AVIOContext *in, AMFMetadata *metadata)
-+{
-+    int length;
-+    int ret;
-+
-+    length = avio_rb32(in);
-+    while(!url_feof(in) && length > 0) {
-+      if((ret = amf_metadata_parse_value(in, metadata, NULL)) < 0)
-+          return ret;
-+      length--;
-+    }
-+
-+    return 0;
-+}
-+
-+static int amf_metadata_parse_value(AVIOContext *in, AMFMetadata *metadata, const char *name)
-+{
-+    uint8_t type;
-+    char value_str[INT16_MAX];
-+    double value_number;
-+    int ret = 0;
-+
-+    type = avio_r8(in);
-+
-+    if(type == AMF_DATA_TYPE_NUMBER) {
-+      value_number = av_int2double(avio_rb64(in));
-+      amf_metadata_assign_property_number(metadata, name, value_number);
-+    }
-+    else if(type == AMF_DATA_TYPE_BOOL) {
-+      value_number = avio_r8(in);
-+      amf_metadata_assign_property_number(metadata, name, value_number);
-+    }
-+    else if(type == AMF_DATA_TYPE_STRING) {
-+      if((ret = flv_amf_get_string(in, value_str, sizeof(value_str))) < 0)
-+          return ret;
-+      amf_metadata_assign_property_string(metadata, name, value_str);
-+    }
-+    else if(type == AMF_DATA_TYPE_OBJECT) {
-+      ret = amf_metadata_parse_object(in, metadata);
-+    }
-+    else if(type == AMF_DATA_TYPE_MIXEDARRAY) {
-+      avio_skip(in, 4);
-+      ret = amf_metadata_parse_object(in, metadata);
-+    }
-+    else if(type == AMF_DATA_TYPE_ARRAY) {
-+      ret = amf_metadata_parse_strict_array(in, metadata);
-+    }
-+    else if(type == AMF_END_OF_OBJECT) {
-+      ret = -1; // EOF
-+    }
-+
-+    return ret;
-+}
-+
-+static int amf_metadata_parse(AVIOContext *in, AMFMetadata *metadata)
-+{
-+    char name[INT16_MAX];
-+    int ret;
-+
-+    if((ret = amf_metadata_read_string_value(in, name, sizeof(name))) < 0) {
-+      av_log(NULL, AV_LOG_ERROR, "amfmetadata Failed to read onMetadata string, ret: %d \n", ret);
-+      return ret;
-+    }
-+
-+    if(av_strcasecmp(name, "onMetaData")) {
-+      av_log(NULL, AV_LOG_ERROR, "amfmetadata Expected onMetadata, str = %s \n", name);
-+      return -1;
-+    }
-+
-+    return amf_metadata_parse_value(in, metadata, name);
-+}
-+
-+int ff_parse_amf_metadata(uint8_t *buffer, int buffer_size, AMFMetadata *metadata)
-+{
-+    AVIOContext *in;
-+    int ret;
-+
-+    if(!buffer)
-+      return 0;
-+    if(buffer_size <= 0)
-+      return 0;
-+
-+    in = avio_alloc_context(buffer, buffer_size,
-+      0, NULL, NULL, NULL, NULL);
-+    if(!in)
-+      return AVERROR(ENOMEM);
-+
-+    ret = amf_metadata_parse(in, metadata);
-+    av_free(in);
-+
-+    return ret;
-+}
-diff --git a/libavformat/amfmetadata.h b/libavformat/amfmetadata.h
-new file mode 100644
-index 0000000..c47cd6e
---- /dev/null
-+++ b/libavformat/amfmetadata.h
-@@ -0,0 +1,47 @@
-+/*
-+ * Adobe Action Message Format Parser
-+ * Copyright (c) 2013 Cory McCarthy
-+ *
-+ * This file is part of FFmpeg.
-+ *
-+ * 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.
-+ *
-+ * 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 FFmpeg; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-+ */
-+
-+/**
-+ * @file
-+ * @brief Adobe Action Message Format Parser
-+ * @author Cory McCarthy
-+ * @see http://download.macromedia.com/f4v/video_file_format_spec_v10_1.pdf
-+ * @see http://www.adobe.com/content/dam/Adobe/en/devnet/amf/pdf/amf-file-format-spec.pdf
-+ */
-+
-+#include "libavcodec/avcodec.h"
-+
-+typedef struct AMFMetadata {
-+    int width;
-+    int height;
-+    int frame_rate;
-+    int audio_sample_rate;
-+    int audio_sample_size;
-+    int nb_audio_channels;
-+    int audio_data_rate;
-+    int video_data_rate;
-+    int audio_stream_need_parsing;
-+
-+    enum AVCodecID audio_codec_id;
-+    enum AVCodecID video_codec_id;
-+} AMFMetadata;
-+
-+int ff_parse_amf_metadata(uint8_t *buffer, int buffer_size, AMFMetadata *metadata);
-diff --git a/libavformat/f4fbox.c b/libavformat/f4fbox.c
-new file mode 100644
-index 0000000..393fbee
---- /dev/null
-+++ b/libavformat/f4fbox.c
-@@ -0,0 +1,345 @@
-+/*
-+ * Adobe Fragmented F4V File (F4F) Parser
-+ * Copyright (c) 2013 Cory McCarthy
-+ *
-+ * This file is part of FFmpeg.
-+ *
-+ * 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.
-+ *
-+ * 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 FFmpeg; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-+ */
-+
-+/**
-+ * @file
-+ * @brief Adobe Fragmented F4V File (F4F) Parser for Adobe HDS
-+ * @author Cory McCarthy
-+ * @see http://download.macromedia.com/f4v/video_file_format_spec_v10_1.pdf
-+ */
-+
-+#include "f4fbox.h"
-+#include "avformat.h"
-+
-+static int f4fbox_parse_single_box(AVIOContext *in, void *opague);
-+
-+static int f4fbox_parse_asrt(AVIOContext *in, int64_t data_size, void *opague)
-+{
-+    F4FBootstrapInfoBox *parent = (F4FBootstrapInfoBox*)opague;
-+    F4FSegmentRunTableBox *asrt;
-+    F4FSegmentRunEntry *entry;
-+    uint32_t segment_run_entry_count;
-+    char url[1024];
-+    int i;
-+
-+    asrt = av_mallocz(sizeof(F4FSegmentRunTableBox));
-+    if(!asrt)
-+        return AVERROR(ENOMEM);
-+
-+    parent->segment_run_table_boxes[parent->nb_segment_run_table_boxes] = asrt;
-+    parent->nb_segment_run_table_boxes++;
-+
-+    asrt->version = avio_r8(in);
-+    asrt->flags = avio_rb24(in);
-+
-+    asrt->nb_quality_entries = avio_r8(in);
-+    if (asrt->nb_quality_entries)
-+      asrt->quality_entries = (char **) av_malloc(asrt->nb_quality_entries * sizeof(char *));
-+    for(i = 0; i < asrt->nb_quality_entries; i++) {
-+        avio_get_str(in, sizeof(url), url, sizeof(url));
-+        av_log(NULL, AV_LOG_DEBUG, "f4fbox asrt quality[%d]=%s\n", i, url);
-+      asrt->quality_entries[i] = av_strdup(url);
-+    }
-+
-+    segment_run_entry_count = avio_rb32(in);
-+    if(segment_run_entry_count > MAX_NB_SEGMENT_RUN_ENTRIES) {
-+        av_log(NULL, AV_LOG_ERROR, "f4fbox segment run entry count exceeds maximum, %d > %d \n",
-+            segment_run_entry_count, MAX_NB_SEGMENT_RUN_ENTRIES);
-+        segment_run_entry_count = MAX_NB_SEGMENT_RUN_ENTRIES;
-+    }
-+
-+    for(i = 0; i < segment_run_entry_count; i++) {
-+        entry = av_mallocz(sizeof(F4FSegmentRunEntry));
-+        if(!entry)
-+            return AVERROR(ENOMEM);
-+
-+        asrt->segment_run_entries[asrt->nb_segment_run_entries] = entry;
-+        asrt->nb_segment_run_entries++;
-+
-+        entry->first_segment = avio_rb32(in);
-+        entry->fragments_per_segment = avio_rb32(in);
-+    }
-+
-+    return 0;
-+}
-+
-+static int f4fbox_parse_afrt(AVIOContext *in, int64_t data_size, void *opague)
-+{
-+    F4FBootstrapInfoBox *parent = (F4FBootstrapInfoBox*)opague;
-+    F4FFragmentRunTableBox *afrt;
-+    F4FFragmentRunEntry *entry;
-+    uint32_t fragment_run_entry_count;
-+    char url[1024];
-+    int i;
-+
-+    afrt = av_mallocz(sizeof(F4FFragmentRunTableBox));
-+    if(!afrt)
-+        return AVERROR(ENOMEM);
-+
-+    parent->fragment_run_table_boxes[parent->nb_fragment_run_table_boxes] = afrt;
-+    parent->nb_fragment_run_table_boxes++;
-+
-+    afrt->version = avio_r8(in);
-+    afrt->flags = avio_rb24(in);
-+
-+    afrt->timescale = avio_rb32(in);
-+
-+    afrt->nb_quality_entries = avio_r8(in);
-+    if (afrt->nb_quality_entries)
-+      afrt->quality_entries = (char **) av_malloc(afrt->nb_quality_entries * sizeof(char *));
-+    for(i = 0; i < afrt->nb_quality_entries; i++) {
-+        avio_get_str(in, sizeof(url), url, sizeof(url));
-+        av_log(NULL, AV_LOG_DEBUG, "f4fbox afrt quality[%d]=%s\n", i, url);
-+      afrt->quality_entries[i] = av_strdup(url);
-+    }
-+
-+    fragment_run_entry_count = avio_rb32(in);
-+    if(fragment_run_entry_count > MAX_NB_FRAGMENT_RUN_ENTRIES) {
-+        av_log(NULL, AV_LOG_ERROR, "f4fbox fragment run entry count exceeds maximum, %d > %d \n",
-+            fragment_run_entry_count, MAX_NB_FRAGMENT_RUN_ENTRIES);
-+        fragment_run_entry_count = MAX_NB_FRAGMENT_RUN_ENTRIES;
-+    }
-+
-+    for(i = 0; i < fragment_run_entry_count; i++) {
-+        entry = av_mallocz(sizeof(F4FFragmentRunEntry));
-+        if(!entry)
-+            return AVERROR(ENOMEM);
-+
-+        afrt->fragment_run_entries[afrt->nb_fragment_run_entries] = entry;
-+        afrt->nb_fragment_run_entries++;
-+
-+        entry->first_fragment = avio_rb32(in);
-+        entry->first_fragment_time_stamp = avio_rb64(in);
-+        entry->fragment_duration = avio_rb32(in);
-+        if(entry->fragment_duration == 0) {
-+            entry->discontinuity_indicator = avio_r8(in);
-+        }
-+    }
-+
-+    return 0;
-+}
-+
-+
-+static int f4fbox_parse_abst(AVIOContext *in, int64_t data_size, void *opague)
-+{
-+    F4FBox *parent = (F4FBox*)opague;
-+    F4FBootstrapInfoBox *abst = &(parent->abst);
-+    uint8_t server_entry_count;
-+    uint8_t segment_run_table_count, fragment_run_table_count;
-+    uint8_t byte;
-+    char url[1024];
-+    int i, ret;
-+
-+    abst->version = avio_r8(in);
-+    abst->flags = avio_rb24(in);
-+    abst->bootstrap_info_version = avio_rb32(in);
-+
-+    byte = avio_r8(in);
-+    abst->profile = (byte >> 6) & 0x03;
-+    abst->is_live = (byte >> 5) & 0x01;
-+    abst->is_update = (byte >> 4) & 0x01;
-+
-+    abst->timescale = avio_rb32(in);
-+    abst->current_media_time = avio_rb64(in);
-+    abst->smpte_time_code_offset = avio_rb64(in);
-+
-+    avio_get_str(in, sizeof(abst->movie_id), abst->movie_id, sizeof(abst->movie_id));
-+
-+    server_entry_count = avio_r8(in);
-+    for(i = 0; i < server_entry_count; i++) {
-+        avio_get_str(in, sizeof(url), url, sizeof(url));
-+    }
-+
-+    abst->nb_quality_entries = avio_r8(in);
-+    if (abst->nb_quality_entries)
-+      abst->quality_entries = (char **) av_malloc(abst->nb_quality_entries * sizeof(char *));
-+    for(i = 0; i < abst->nb_quality_entries; i++) {
-+        avio_get_str(in, sizeof(url), url, sizeof(url));
-+        av_log(NULL, AV_LOG_DEBUG, "f4fbox abst quality[%d]=%s\n", i, url);
-+      abst->quality_entries[i] = av_strdup(url);
-+    }
-+
-+    avio_get_str(in, sizeof(abst->drm_data), abst->drm_data, sizeof(abst->drm_data));
-+    avio_get_str(in, sizeof(abst->metadata), abst->metadata, sizeof(abst->metadata));
-+
-+    segment_run_table_count = avio_r8(in);
-+    for(i = 0; i < segment_run_table_count; i++) {
-+        if((ret = f4fbox_parse_single_box(in, abst)) < 0) {
-+            av_log(NULL, AV_LOG_ERROR, "f4fbox Failed to parse asrt box, ret: %d \n", ret);
-+            return ret;
-+        }
-+    }
-+
-+    fragment_run_table_count = avio_r8(in);
-+    for(i = 0; i < fragment_run_table_count; i++) {
-+        if((ret = f4fbox_parse_single_box(in, abst)) < 0) {
-+            av_log(NULL, AV_LOG_ERROR, "f4fbox Failed to parse afrt box, ret: %d \n", ret);
-+            return ret;
-+        }
-+    }
-+
-+    return 0;
-+}
-+
-+static int f4fbox_parse_mdat(AVIOContext *in, int64_t data_size, void *opague)
-+{
-+    F4FBox *parent = (F4FBox*)opague;
-+    F4FMediaDataBox *mdat = &(parent->mdat);
-+
-+    mdat->data = av_mallocz(sizeof(uint8_t)*data_size);
-+    if(!mdat->data)
-+        return AVERROR(ENOMEM);
-+
-+    mdat->size = data_size;
-+    avio_read(in, mdat->data, mdat->size);
-+
-+    return 0;
-+}
-+
-+static int f4fbox_parse_single_box(AVIOContext *in, void *opague)
-+{
-+    int64_t bytes_read, bytes_left, start_pos, end_pos;
-+    uint64_t size;
-+    uint32_t type;
-+    int ret = 0;
-+
-+    bytes_read = 0;
-+    start_pos = avio_tell(in);
-+
-+    size = avio_rb32(in);
-+    type = avio_rl32(in);
-+    bytes_read += 8;
-+
-+    if(size == 1) {/* 64 bit extended size */
-+        size = avio_rb64(in) - 8;
-+        bytes_read += 8;
-+    }
-+
-+    if(size == 0)
-+        return -1;
-+
-+    if(type == MKTAG('a', 'b', 's', 't')) {
-+        ret = f4fbox_parse_abst(in, size, opague);
-+    }
-+    if(type == MKTAG('a', 's', 'r', 't')) {
-+        ret = f4fbox_parse_asrt(in, size, opague);
-+    }
-+    if(type == MKTAG('a', 'f', 'r', 't')) {
-+        ret = f4fbox_parse_afrt(in, size, opague);
-+    }
-+    if(type == MKTAG('m', 'd', 'a', 't')) {
-+        ret = f4fbox_parse_mdat(in, size, opague);
-+    }
-+
-+    if(ret < 0)
-+        return ret;
-+
-+    end_pos = avio_tell(in);
-+    bytes_left = size - (end_pos - start_pos);
-+    if(bytes_left > 0)
-+        avio_skip(in, bytes_left);
-+
-+    bytes_read += size;
-+
-+    return bytes_read;
-+}
-+
-+static int f4fbox_parse(AVIOContext *in, int64_t data_size, void *opague)
-+{
-+    int64_t bytes_read = 0;
-+    int ret;
-+
-+    while(!url_feof(in) && bytes_read + 8 < data_size) {
-+        if((ret = f4fbox_parse_single_box(in, opague)) < 0) {
-+            av_log(NULL, AV_LOG_ERROR, "f4fbox Failed to parse box, ret: %d \n", ret);
-+            return ret;
-+        }
-+        bytes_read += ret;
-+    }
-+
-+    return 0;
-+}
-+
-+int ff_parse_f4f_box(uint8_t *buffer, int buffer_size, F4FBox *box)
-+{
-+    AVIOContext *in;
-+    int ret;
-+
-+    in = avio_alloc_context(buffer, buffer_size, 0, NULL, NULL, NULL, NULL);
-+    if(!in)
-+        return AVERROR(ENOMEM);
-+
-+    ret = f4fbox_parse(in, buffer_size, box);
-+    av_free(in);
-+
-+    return ret;
-+}
-+
-+int ff_free_f4f_box(F4FBox *box)
-+{
-+    F4FBootstrapInfoBox *abst;
-+    F4FSegmentRunTableBox *asrt;
-+    F4FSegmentRunEntry *sre;
-+    F4FFragmentRunTableBox *afrt;
-+    F4FFragmentRunEntry *fre;
-+    F4FMediaDataBox *mdat;
-+    int i, j;
-+
-+    abst = &(box->abst);
-+    for(j = 0; j < abst->nb_quality_entries; j++)
-+      av_freep(&abst->quality_entries[j]);
-+    if (abst->quality_entries)
-+      av_freep(&abst->quality_entries);
-+
-+    for(i = 0; i < abst->nb_segment_run_table_boxes; i++) {
-+        asrt = abst->segment_run_table_boxes[i];
-+        for(j = 0; j < asrt->nb_quality_entries; j++)
-+          av_freep(&asrt->quality_entries[j]);
-+      if (asrt->quality_entries)
-+          av_freep(&asrt->quality_entries);
-+        for(j = 0; j < asrt->nb_segment_run_entries; j++) {
-+            sre = asrt->segment_run_entries[j];
-+            av_freep(&sre);
-+        }
-+        av_freep(&asrt);
-+    }
-+
-+    for(i = 0; i < abst->nb_fragment_run_table_boxes; i++) {
-+        afrt = abst->fragment_run_table_boxes[i];
-+        for(j = 0; j < afrt->nb_quality_entries; j++)
-+          av_freep(&afrt->quality_entries[j]);
-+      if (afrt->quality_entries)
-+          av_freep(&afrt->quality_entries);
-+        for(j = 0; j < afrt->nb_fragment_run_entries; j++) {
-+            fre = afrt->fragment_run_entries[j];
-+            av_freep(&fre);
-+        }
-+        av_freep(&afrt);
-+    }
-+
-+    mdat = &(box->mdat);
-+    if(mdat->size > 0)
-+        av_freep(&mdat->data);
-+
-+    memset(box, 0x00, sizeof(F4FBox));
-+
-+    return 0;
-+}
-diff --git a/libavformat/f4fbox.h b/libavformat/f4fbox.h
-new file mode 100644
-index 0000000..da3ac24
---- /dev/null
-+++ b/libavformat/f4fbox.h
-@@ -0,0 +1,110 @@
-+/*
-+ * Adobe Fragmented F4V File (F4F) Parser
-+ * Copyright (c) 2013 Cory McCarthy
-+ *
-+ * This file is part of FFmpeg.
-+ *
-+ * 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.
-+ *
-+ * 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 FFmpeg; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-+ */
-+
-+/**
-+ * @file
-+ * @brief Adobe Fragmented F4V File (F4F) Parser for Adobe HDS
-+ * @author Cory McCarthy
-+ * @see http://download.macromedia.com/f4v/video_file_format_spec_v10_1.pdf
-+ */
-+
-+#include "avio_internal.h"
-+
-+#define MAX_NB_SEGMENT_RUN_TABLE_BOXES 256
-+#define MAX_NB_FRAGMENT_RUN_TABLE_BOXES 256
-+
-+#define MAX_NB_SEGMENT_RUN_ENTRIES 1024
-+#define MAX_NB_FRAGMENT_RUN_ENTRIES 1024
-+
-+typedef struct F4FFragmentRunEntry {
-+    uint32_t first_fragment;
-+    uint64_t first_fragment_time_stamp;
-+    uint32_t fragment_duration;
-+    uint8_t discontinuity_indicator;
-+} F4FFragmentRunEntry;
-+
-+typedef struct F4FFragmentRunTableBox {
-+    uint8_t version;
-+    uint32_t flags;
-+    uint32_t timescale;
-+
-+    uint8_t nb_quality_entries;
-+    char **quality_entries;
-+
-+    uint32_t nb_fragment_run_entries;
-+    F4FFragmentRunEntry *fragment_run_entries[MAX_NB_FRAGMENT_RUN_ENTRIES];
-+} F4FFragmentRunTableBox;
-+
-+typedef struct F4FSegmentRunEntry {
-+    uint32_t first_segment;
-+    uint32_t fragments_per_segment;
-+} F4FSegmentRunEntry;
-+
-+typedef struct F4FSegmentRunTableBox {
-+    uint8_t version;
-+    uint32_t flags;
-+
-+    uint8_t nb_quality_entries;
-+    char **quality_entries;
-+
-+    uint32_t nb_segment_run_entries;
-+    F4FSegmentRunEntry *segment_run_entries[MAX_NB_SEGMENT_RUN_ENTRIES];
-+} F4FSegmentRunTableBox;
-+
-+typedef struct F4FBootstrapInfoBox {
-+    uint8_t version;
-+    uint32_t flags;
-+    uint32_t bootstrap_info_version;
-+
-+    uint8_t profile;
-+    uint8_t is_live;
-+    uint8_t is_update;
-+
-+    uint32_t timescale;
-+    uint64_t current_media_time;
-+    uint64_t smpte_time_code_offset;
-+
-+    char movie_id[1024];
-+    char drm_data[1024];
-+    char metadata[1024];
-+
-+    uint8_t nb_quality_entries;
-+    char **quality_entries;
-+
-+    uint8_t nb_segment_run_table_boxes;
-+    F4FSegmentRunTableBox *segment_run_table_boxes[MAX_NB_SEGMENT_RUN_TABLE_BOXES];
-+
-+    uint8_t nb_fragment_run_table_boxes;
-+    F4FFragmentRunTableBox *fragment_run_table_boxes[MAX_NB_FRAGMENT_RUN_TABLE_BOXES];
-+} F4FBootstrapInfoBox;
-+
-+typedef struct F4FMediaDataBox {
-+    uint32_t size;
-+    uint8_t *data;
-+} F4FMediaDataBox;
-+
-+typedef struct F4FBox {
-+    F4FBootstrapInfoBox abst;
-+    F4FMediaDataBox mdat;
-+} F4FBox;
-+
-+int ff_parse_f4f_box(uint8_t *buffer, int buffer_size, F4FBox *box);
-+int ff_free_f4f_box(F4FBox *box);
-diff --git a/libavformat/f4mmanifest.c b/libavformat/f4mmanifest.c
-new file mode 100644
-index 0000000..b33247b
---- /dev/null
-+++ b/libavformat/f4mmanifest.c
-@@ -0,0 +1,256 @@
-+/*
-+ * Adobe Media Manifest (F4M) File Parser
-+ * Copyright (c) 2013 Cory McCarthy
-+ *
-+ * This file is part of FFmpeg.
-+ *
-+ * 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.
-+ *
-+ * 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 FFmpeg; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-+ */
-+
-+/**
-+ * @file
-+ * @brief Adobe Media Manifest (F4M) File Parser
-+ * @author Cory McCarthy
-+ * @see http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/hds/pdfs/adobe-media-manifest-specification.pdf
-+ */
-+
-+#include "f4mmanifest.h"
-+#include "libavutil/avstring.h"
-+#include "libavutil/base64.h"
-+#include <roxml.h>
-+
-+static int f4m_parse_bootstrap_info_node(node_t * node, F4MBootstrapInfo *bootstrap_info)
-+{
-+    const char  *p;
-+    uint8_t *dst;
-+    int ret;
-+    node_t *attr;
-+
-+    attr = roxml_get_attr(node, "id", 0);
-+    p =roxml_get_content(attr,NULL,0,NULL);
-+    if(p) {
-+        av_strlcpy(bootstrap_info->id, p, sizeof(bootstrap_info->id));
-+    }
-+
-+    attr = roxml_get_attr(node, "url", 0);
-+    p =roxml_get_content(attr,NULL,0,NULL);
-+    if(p) {
-+        av_strlcpy(bootstrap_info->url, p, sizeof(bootstrap_info->url));
-+    }
-+
-+    attr = roxml_get_attr(node, "profile", 0);
-+    p =roxml_get_content(attr,NULL,0,NULL);
-+    if(p) {
-+        av_strlcpy(bootstrap_info->profile, p, sizeof(bootstrap_info->profile));
-+    }
-+
-+    p = roxml_get_content(node, NULL, 0, NULL);
-+    if(p) {
-+        dst = av_mallocz(sizeof(uint8_t)*strlen(p));
-+        if(!dst)
-+            return AVERROR(ENOMEM);
-+
-+        if((ret = av_base64_decode(dst, p, strlen(p))) < 0) {
-+            av_log(NULL, AV_LOG_ERROR, "f4mmanifest Failed to decode bootstrap node base64 metadata, ret: %d \n", ret);
-+            av_free(dst);
-+            return ret;
-+        }
-+
-+        bootstrap_info->metadata = av_mallocz(sizeof(uint8_t)*ret);
-+        if(!bootstrap_info->metadata)
-+            return AVERROR(ENOMEM);
-+
-+        bootstrap_info->metadata_size = ret;
-+        memcpy(bootstrap_info->metadata, dst, ret);
-+
-+        av_free(dst);
-+    }
-+
-+    return 0;
-+}
-+
-+static int f4m_parse_metadata_node(node_t * node, F4MMedia *media)
-+{
-+    const char  *p = NULL;
-+    uint8_t *dst;
-+    int ret;
-+
-+    node_t * metadata_node = roxml_get_chld(node, NULL, 0);
-+    while(metadata_node) {
-+        if(!strcmp(roxml_get_name(metadata_node, NULL, 0), "metadata")) {
-+            p = roxml_get_content(metadata_node, NULL, 0, NULL);
-+            break;
-+        }
-+        metadata_node = roxml_get_next_sibling(metadata_node);
-+    }
-+
-+    if(!p)
-+        return 0;
-+
-+    dst = av_mallocz(sizeof(uint8_t)*strlen(p));
-+    if(!dst)
-+        return AVERROR(ENOMEM);
-+
-+    if((ret = av_base64_decode(dst, p, strlen(p))) < 0) {
-+        av_log(NULL, AV_LOG_ERROR, "f4mmanifest Failed to decode base64 metadata, ret: %d \n", ret);
-+        av_free(dst);
-+        return ret;
-+    }
-+
-+    media->metadata = av_mallocz(sizeof(uint8_t)*ret);
-+    if(!media->metadata)
-+        return AVERROR(ENOMEM);
-+
-+    media->metadata_size = ret;
-+    memcpy(media->metadata, dst, ret);
-+
-+    av_free(dst);
-+
-+    return 0;
-+}
-+
-+static int f4m_parse_media_node(node_t * node, F4MMedia *media)
-+{
-+    const char  *p;
-+    int ret;
-+    node_t * attr;
-+
-+    attr = roxml_get_attr(node, "bitrate", 0);
-+    p =roxml_get_content(attr,NULL,0,NULL);
-+    if(p) {
-+        media->bitrate = strtoul(p, NULL, 10);
-+    }
-+
-+    attr = roxml_get_attr(node, "url", 0);
-+    p =roxml_get_content(attr,NULL,0,NULL);
-+    if(p) {
-+        av_strlcpy(media->url, p, sizeof(media->url));
-+    }
-+
-+    attr = roxml_get_attr(node, "bootstrapInfoId", 0);
-+    p =roxml_get_content(attr,NULL,0,NULL);
-+    if(p) {
-+        av_strlcpy(media->bootstrap_info_id, p, sizeof(media->bootstrap_info_id));
-+    }
-+
-+    if((ret = f4m_parse_metadata_node(node, media)) < 0) {
-+        return ret;
-+    }
-+
-+    return 0;
-+}
-+
-+static int f4m_parse_manifest_node(node_t * root_node, F4MManifest *manifest)
-+{
-+    F4MBootstrapInfo *bootstrap_info;
-+    F4MMedia *media;
-+    node_t * node;
-+    const char  *node_content;
-+    int ret = 0,chld_idx=0;
-+
-+    for (chld_idx=0; chld_idx<roxml_get_chld_nb(root_node); chld_idx++){
-+      node = roxml_get_chld(root_node, NULL, chld_idx);
-+      const char * node_name = roxml_get_name(node, NULL, 0);
-+        if(!strcmp(node_name, "text"))
-+            continue;
-+
-+      node_content = roxml_get_content(node, NULL, 0, NULL);
-+
-+        if(!strcmp(node_name, "id") && node_content) {
-+            av_strlcpy(manifest->id, node_content, sizeof(manifest->id));
-+        } else if(!strcmp(node_name, "streamType") && node_content) {
-+            av_strlcpy(manifest->stream_type, node_content, sizeof(manifest->stream_type));
-+        } else if(!strcmp(node_name, "bootstrapInfo")) {
-+            bootstrap_info = av_mallocz(sizeof(F4MBootstrapInfo));
-+            if(!bootstrap_info)
-+                return AVERROR(ENOMEM);
-+            manifest->bootstraps[manifest->nb_bootstraps++] = bootstrap_info;
-+            ret = f4m_parse_bootstrap_info_node(node, bootstrap_info);
-+        } else if(!strcmp(node_name, "media")) {
-+            media = av_mallocz(sizeof(F4MMedia));
-+            if(!media)
-+                return AVERROR(ENOMEM);
-+            manifest->media[manifest->nb_media++] = media;
-+            ret = f4m_parse_media_node(node, media);
-+        } else if (!strcmp(node_name, "duration")) {
-+          double duration = strtod(node_content, NULL);
-+          manifest->duration = duration * AV_TIME_BASE;
-+      }
-+
-+        if(ret < 0)
-+            return ret;
-+    }
-+
-+    return 0;
-+}
-+
-+static int f4m_parse_xml_file(uint8_t *buffer, int size, F4MManifest *manifest)
-+{
-+    node_t * doc;
-+    node_t * root_node;
-+    int ret;
-+
-+    doc = roxml_load_buf(buffer);
-+    if(!doc) {
-+        return -1;
-+    }
-+
-+    doc = roxml_get_root(doc);
-+    root_node = roxml_get_chld(doc, NULL, 0);
-+    if(!root_node) {
-+        av_log(NULL, AV_LOG_ERROR, "f4mmanifest Root element not found \n");
-+        roxml_close(doc);
-+        return -1;
-+    }
-+    const char * root_node_name = roxml_get_name(root_node, NULL, 0);
-+    if(strcmp(root_node_name, "manifest")) {
-+        av_log(NULL, AV_LOG_ERROR, "f4mmanifest Root element is not named manifest, name = %s \n", root_node_name);
-+        roxml_close(doc);
-+        return -1;
-+    }
-+
-+    ret = f4m_parse_manifest_node(root_node, manifest);
-+    roxml_close(doc);
-+
-+    return ret;
-+}
-+
-+int ff_parse_f4m_manifest(uint8_t *buffer, int size, F4MManifest *manifest)
-+{
-+    return f4m_parse_xml_file(buffer, size, manifest);
-+}
-+
-+int ff_free_manifest(F4MManifest *manifest)
-+{
-+    F4MBootstrapInfo *bootstrap_info;
-+    F4MMedia *media;
-+    int i;
-+
-+    for(i = 0; i < manifest->nb_bootstraps; i++) {
-+        bootstrap_info = manifest->bootstraps[i];
-+        av_freep(&bootstrap_info->metadata);
-+        av_freep(&bootstrap_info);
-+    }
-+
-+    for(i = 0; i < manifest->nb_media; i++) {
-+        media = manifest->media[i];
-+        av_freep(&media->metadata);
-+        av_freep(&media);
-+    }
-+
-+    memset(manifest, 0x00, sizeof(F4MManifest));
-+
-+    return 0;
-+}
-diff --git a/libavformat/f4mmanifest.h b/libavformat/f4mmanifest.h
-new file mode 100644
-index 0000000..97a5885
---- /dev/null
-+++ b/libavformat/f4mmanifest.h
-@@ -0,0 +1,65 @@
-+/*
-+ * Adobe Media Manifest (F4M) File Parser
-+ * Copyright (c) 2013 Cory McCarthy
-+ *
-+ * This file is part of FFmpeg.
-+ *
-+ * 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.
-+ *
-+ * 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 FFmpeg; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-+ */
-+
-+/**
-+ * @file
-+ * @brief Adobe Media Manifest (F4M) File Parser
-+ * @author Cory McCarthy
-+ * @see http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/hds/pdfs/adobe-media-manifest-specification.pdf
-+ */
-+
-+#include "internal.h"
-+
-+#define MAX_NB_BOOTSTRAPS 32
-+#define MAX_NB_MEDIA 32
-+
-+typedef struct F4MBootstrapInfo {
-+    char id[MAX_URL_SIZE];
-+    char url[MAX_URL_SIZE];
-+    char profile[MAX_URL_SIZE];
-+
-+    int metadata_size;
-+    uint8_t *metadata;
-+} F4MBootstrapInfo;
-+
-+typedef struct F4MMedia {
-+    int bitrate;
-+    char url[MAX_URL_SIZE];
-+    char bootstrap_info_id[MAX_URL_SIZE];
-+
-+    int metadata_size;
-+    uint8_t *metadata;
-+} F4MMedia;
-+
-+typedef struct F4MManifest {
-+    char id[MAX_URL_SIZE];
-+    char stream_type[MAX_URL_SIZE];
-+    int64_t duration;
-+
-+    int nb_bootstraps;
-+    F4MBootstrapInfo *bootstraps[MAX_NB_BOOTSTRAPS];
-+
-+    int nb_media;
-+    F4MMedia *media[MAX_NB_MEDIA];
-+} F4MManifest;
-+
-+int ff_parse_f4m_manifest(uint8_t *buffer, int size, F4MManifest *manifest);
-+int ff_free_manifest(F4MManifest *manifest);
-diff --git a/libavformat/flv.h b/libavformat/flv.h
-index db9468f..8d97e06 100644
---- a/libavformat/flv.h
-+++ b/libavformat/flv.h
-@@ -135,4 +135,6 @@ typedef enum {
-     AMF_DATA_TYPE_UNSUPPORTED = 0x0d,
- } AMFDataType;
-+int flv_amf_get_string(AVIOContext *ioc, char *buffer, int buffsize);
-+
- #endif /* AVFORMAT_FLV_H */
-diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c
-index 07f7b68..afe7e51 100644
---- a/libavformat/flvdec.c
-+++ b/libavformat/flvdec.c
-@@ -298,6 +298,11 @@ static int amf_get_string(AVIOContext *ioc, char *buffer, int buffsize)
-     return length;
- }
-+int flv_amf_get_string(AVIOContext *ioc, char *buffer, int buffsize)
-+{
-+    return amf_get_string(ioc, buffer, buffsize);
-+}
-+
- static int parse_keyframes_index(AVFormatContext *s, AVIOContext *ioc,
-                                  AVStream *vstream, int64_t max_pos)
- {
-diff --git a/libavformat/flvtag.c b/libavformat/flvtag.c
-new file mode 100644
-index 0000000..a611ea0
---- /dev/null
-+++ b/libavformat/flvtag.c
-@@ -0,0 +1,408 @@
-+/*
-+ * Adobe FLV Tag Parser
-+ * Copyright (c) 2013 Cory McCarthy
-+ * Copyright (c) 2014 martii
-+ *
-+ * This file is part of FFmpeg.
-+ *
-+ * 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.
-+ *
-+ * 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 FFmpeg; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-+ */
-+
-+/**
-+ * @file
-+ * @brief FLV Tag Parser for Adobe HDS F4F Files
-+ * @author Cory McCarthy
-+ * @see http://download.macromedia.com/f4v/video_file_format_spec_v10_1.pdf
-+ */
-+
-+#include "flvtag.h"
-+#include "libavformat/avio.h"
-+#include "libavcodec/get_bits.h"
-+#include "libavutil/channel_layout.h"
-+#include "flv.h"
-+
-+typedef struct FLVTagAudioHeader {
-+    uint8_t sound_format;
-+    uint8_t sound_rate;
-+    uint8_t sound_size;
-+    uint8_t sound_type;
-+
-+    uint8_t aac_packet_type;
-+} FLVTagAudioHeader;
-+
-+typedef struct FLVTagAudioBody {
-+    uint8_t sound_format;
-+    uint8_t sound_rate;
-+    uint8_t sound_size;
-+    uint8_t sound_type;
-+
-+    uint8_t aac_packet_type;
-+} FLVTagAudioBody;
-+
-+typedef struct FLVTagVideoHeader {
-+    uint8_t frame_type;
-+    uint8_t codec_id;
-+
-+    uint8_t avc_packet_type;
-+    int32_t cts;
-+} FLVTagVideoHeader;
-+
-+typedef struct FLVTagVideoBody {
-+    //AVCDecoderConfigurationRecord
-+    uint8_t configuration_version;
-+    uint8_t avc_profile_indication;
-+    uint8_t profile_compatibility;
-+    uint8_t avc_level_indication;
-+
-+    uint8_t length_size_minus_one;
-+
-+    uint8_t *sps_data;
-+    int sps_data_size;
-+
-+    uint8_t *pps_data;
-+    int pps_data_size;
-+} FLVTagVideoBody;
-+
-+static int flv_tag_parse_audio_header(AVIOContext *in,
-+    FLVTagAudioHeader *header)
-+{
-+    int ret = 0;
-+    uint8_t byte;
-+
-+    byte = avio_r8(in);
-+    ret++;
-+
-+    header->sound_format = byte & FLV_AUDIO_CODECID_MASK;
-+    header->sound_rate   = (byte >> FLV_AUDIO_SAMPLERATE_OFFSET) & 0x03;
-+    header->sound_size   = (byte >> FLV_AUDIO_SAMPLESSIZE_OFFSET) & 0x01;
-+    header->sound_type   = byte & 0x01;
-+
-+    if(header->sound_format == FLV_CODECID_AAC) {
-+      header->aac_packet_type = avio_r8(in);
-+      ret++;
-+    }
-+
-+    return ret;
-+}
-+
-+static int flv_tag_parse_audio_body(AVIOContext *in, uint32_t data_size,
-+    FLVTagAudioHeader *header, FLVTagAudioBody *body, FLVMediaSample **sample_out)
-+{
-+    FLVMediaSample *sample;
-+
-+    if(header->sound_format != FLV_CODECID_AAC) {
-+      av_log(NULL, AV_LOG_ERROR, "flvtag Unhandled sound format %d\n", header->sound_format >> FLV_AUDIO_CODECID_OFFSET);
-+      return 0;
-+    }
-+
-+    if(header->aac_packet_type == 0) {
-+      av_log(NULL, AV_LOG_DEBUG, "flvtag skipped aac_packet_type %d\n", header->aac_packet_type);
-+      return 0;
-+    }
-+
-+    if(header->aac_packet_type != 1) {
-+      av_log(NULL, AV_LOG_ERROR, "flvtag Unhandled aac_packet_type %d\n", header->aac_packet_type);
-+      return 0;
-+    }
-+
-+    sample = av_mallocz(sizeof(FLVMediaSample));
-+    if(!sample)
-+      return AVERROR(ENOMEM);
-+
-+    sample->type = AVMEDIA_TYPE_AUDIO;
-+
-+    sample->data = av_mallocz(sizeof(uint8_t) * data_size);
-+    if(!sample->data) {
-+      av_free(sample);
-+      return AVERROR(ENOMEM);
-+    }
-+
-+    sample->data_size = data_size;
-+    avio_read(in, sample->data, sample->data_size);
-+
-+    if(sample_out)
-+      *sample_out = sample;
-+
-+    return data_size;
-+}
-+
-+static int flv_tag_parse_video_header(AVIOContext *in,
-+    FLVTagVideoHeader *header)
-+{
-+    int ret = 0;
-+    uint8_t byte;
-+
-+    byte = avio_r8(in);
-+    ret++;
-+
-+    header->frame_type = byte >> 4;
-+    header->codec_id = byte & 0x0F;
-+
-+    if(header->codec_id == 0x07) {
-+      header->avc_packet_type = avio_r8(in);
-+      header->cts = (avio_rb24(in) + 0xff800000) ^ 0xff800000;
-+      ret += 4;
-+    }
-+
-+    return ret;
-+}
-+
-+static int flv_tag_parse_video_body(AVIOContext *in, uint32_t data_size,
-+    FLVTagVideoHeader *header, FLVTagVideoBody *body, FLVMediaSample **sample_out)
-+{
-+    FLVMediaSample *sample = NULL;
-+    uint8_t *p;
-+    uint8_t nb_sps, nb_pps;
-+    uint16_t sps_length, pps_length;
-+    int i, ret = 0;
-+
-+    if(header->frame_type == 0x05) {
-+      avio_r8(in);
-+      return 1;
-+    }
-+
-+    if(header->codec_id != FLV_CODECID_H264) {
-+      av_log(NULL, AV_LOG_ERROR, "flvtag Unhandled video codec id, id: %d \n", header->codec_id);
-+      return 0;
-+    }
-+
-+    if(header->avc_packet_type == 0x00) {
-+      body->configuration_version = avio_r8(in);
-+      body->avc_profile_indication = avio_r8(in);
-+      body->profile_compatibility = avio_r8(in);
-+      body->avc_level_indication = avio_r8(in);
-+      ret += 4;
-+
-+      body->length_size_minus_one = avio_r8(in) & 0x03;
-+      ret++;
-+
-+      if(body->sps_data_size > 0)
-+          av_freep(&body->sps_data);
-+      if(body->pps_data_size > 0)
-+          av_freep(&body->pps_data);
-+
-+      nb_sps = avio_r8(in) & 0x1F;
-+      ret++;
-+
-+      for(i = 0; i < nb_sps; i++) {
-+          sps_length = avio_rb16(in);
-+          ret += 2;
-+
-+          body->sps_data = av_realloc(body->sps_data,
-+              body->sps_data_size + sps_length + 4);
-+          if(!body->sps_data)
-+              return AVERROR(ENOMEM);
-+
-+          p = body->sps_data + body->sps_data_size;
-+
-+          *p++ = 0x00;
-+          *p++ = 0x00;
-+          *p++ = 0x00;
-+          *p++ = 0x01;
-+          body->sps_data_size += 4;
-+
-+          avio_read(in, p, sps_length);
-+          body->sps_data_size += sps_length;
-+
-+          ret += sps_length;
-+      }
-+
-+      nb_pps = avio_r8(in);
-+      ret++;
-+
-+      for(i = 0; i < nb_pps; i++) {
-+          pps_length = avio_rb16(in);
-+          ret += 2;
-+
-+          body->pps_data = av_realloc(body->pps_data,
-+              body->pps_data_size + pps_length + 4);
-+          if(!body->pps_data)
-+              return AVERROR(ENOMEM);
-+
-+          p = body->pps_data + body->pps_data_size;
-+
-+          *p++ = 0x00;
-+          *p++ = 0x00;
-+          *p++ = 0x00;
-+          *p++ = 0x01;
-+          body->pps_data_size += 4;
-+
-+          avio_read(in, p, pps_length);
-+          body->pps_data_size += pps_length;
-+
-+          ret += pps_length;
-+      }
-+    }
-+    else if(header->avc_packet_type == 0x01) { // AVC NALU
-+      sample = av_mallocz(sizeof(FLVMediaSample));
-+      if(!sample)
-+          return AVERROR(ENOMEM);
-+
-+      sample->type = AVMEDIA_TYPE_VIDEO;
-+
-+      sample->data_size = body->sps_data_size + body->pps_data_size;
-+      sample->data_size += 4 + data_size;
-+
-+      sample->data = av_mallocz(sizeof(uint8_t) * sample->data_size);
-+      if(!sample->data) {
-+          av_free(sample);
-+          return AVERROR(ENOMEM);
-+      }
-+
-+      p = sample->data;
-+
-+      memcpy(p, body->sps_data, body->sps_data_size);
-+      p += body->sps_data_size;
-+
-+      memcpy(p, body->pps_data, body->pps_data_size);
-+      p += body->pps_data_size;
-+
-+      while(ret < data_size) {
-+          int length_size = body->length_size_minus_one + 1;
-+          uint32_t nal_size = 0;
-+          *p++ = 0x00;
-+          *p++ = 0x00;
-+          *p++ = 0x00;
-+          *p++ = 0x01;
-+
-+          while (length_size) {
-+              nal_size <<= 8;
-+              nal_size |= avio_r8(in);
-+              length_size--;
-+              ret++;
-+          }
-+
-+          avio_read(in, p, nal_size);
-+          p += nal_size;
-+          ret += nal_size;
-+      }
-+    }
-+
-+    if(sample_out)
-+      *sample_out = sample;
-+
-+    return ret;
-+}
-+
-+static int flv_tag_decode_body(uint8_t *buffer, int buffer_size,
-+    FLVMediaSample **samples, int *nb_samples_out)
-+{
-+    FLVMediaSample *sample;
-+    AVIOContext *in;
-+    FLVTagAudioHeader audio_header;
-+    FLVTagAudioBody audio_body;
-+    FLVTagVideoHeader video_header;
-+    FLVTagVideoBody video_body;
-+    uint8_t byte, filter, tag_type;
-+    uint32_t data_size, dts, stream_id;
-+    int nb_samples = 0;
-+    int ret;
-+
-+    memset(&audio_header, 0x00, sizeof(FLVTagAudioHeader));
-+    memset(&audio_body, 0x00, sizeof(FLVTagAudioBody));
-+    memset(&video_header, 0x00, sizeof(FLVTagVideoHeader));
-+    memset(&video_body, 0x00, sizeof(FLVTagVideoBody));
-+
-+    in = avio_alloc_context(buffer, buffer_size, 0, NULL, NULL, NULL, NULL);
-+    if(!in)
-+      return AVERROR(ENOMEM);
-+
-+    while(!url_feof(in)) {
-+      byte = avio_r8(in);
-+      filter = byte & 0x20;
-+      tag_type = (byte & 0x01F);
-+
-+      data_size = avio_rb24(in);
-+
-+      dts = avio_rb24(in);
-+      dts |= avio_r8(in) << 24;
-+
-+      stream_id = avio_rb24(in);
-+      if(stream_id != 0) {
-+          av_log(NULL, AV_LOG_ERROR, "flvtag Invalid stream_id %d \n", stream_id);
-+          return -1;
-+      }
-+
-+      if(tag_type == FLV_TAG_TYPE_AUDIO) {
-+          data_size -= flv_tag_parse_audio_header(in, &audio_header);
-+      } else if(tag_type == FLV_TAG_TYPE_VIDEO) {
-+          data_size -= flv_tag_parse_video_header(in, &video_header);
-+      }
-+
-+#if 0
-+      if(filter) {
-+          //EncryptionTagHeader
-+          //FilterParams
-+      }
-+#endif
-+
-+      sample = NULL;
-+
-+      if(tag_type == FLV_TAG_TYPE_AUDIO) {
-+          if((ret = flv_tag_parse_audio_body(in, data_size,
-+                  &audio_header, &audio_body, &sample)) < 0) {
-+
-+              av_free(in);
-+              return ret;
-+          }
-+          data_size -= ret;
-+      } else if(tag_type == FLV_TAG_TYPE_VIDEO) {
-+          if((ret = flv_tag_parse_video_body(in, data_size,
-+                  &video_header, &video_body, &sample)) < 0) {
-+
-+              av_free(in);
-+              return ret;
-+          }
-+          data_size -= ret;
-+      }
-+#if 0
-+      else if(tag_type == 18) {
-+          //ScriptData
-+      }
-+#endif
-+
-+      if(sample) {
-+          sample->dts = dts;
-+          if (tag_type == FLV_TAG_TYPE_VIDEO)
-+                  sample->pts = dts + video_header.cts;
-+          else
-+                  sample->pts = AV_NOPTS_VALUE;
-+          samples[nb_samples++] = sample;
-+      }
-+
-+      if(data_size) {
-+          avio_skip(in, data_size);
-+      }
-+      avio_rb32(in);
-+    }
-+
-+    av_free(in);
-+
-+    if(video_body.sps_data_size > 0)
-+      av_free(video_body.sps_data);
-+    if(video_body.pps_data_size > 0)
-+      av_free(video_body.pps_data);
-+
-+    if(nb_samples_out)
-+      *nb_samples_out = nb_samples;
-+
-+    return 0;
-+}
-+
-+int ff_decode_flv_body(uint8_t *buffer, int buffer_size,
-+    FLVMediaSample **samples, int *nb_samples_out)
-+{
-+    return flv_tag_decode_body(buffer, buffer_size, samples, nb_samples_out);
-+}
-diff --git a/libavformat/flvtag.h b/libavformat/flvtag.h
-new file mode 100644
-index 0000000..51b94b4
---- /dev/null
-+++ b/libavformat/flvtag.h
-@@ -0,0 +1,40 @@
-+/*
-+ * Adobe FLV Tag Parser
-+ * Copyright (c) 2013 Cory McCarthy
-+ *
-+ * This file is part of FFmpeg.
-+ *
-+ * 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.
-+ *
-+ * 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 FFmpeg; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-+ */
-+
-+/**
-+ * @file
-+ * @brief Adobe FLV Tag Parser for Adobe HDS F4F Files
-+ * @author Cory McCarthy
-+ * @see http://download.macromedia.com/f4v/video_file_format_spec_v10_1.pdf
-+ */
-+
-+#include "libavutil/avutil.h"
-+
-+typedef struct FLVMediaSample {
-+    enum AVMediaType type;
-+    uint64_t dts;
-+    uint64_t pts;
-+    int data_size;
-+    uint8_t *data;
-+} FLVMediaSample;
-+
-+int ff_decode_flv_body(uint8_t *buffer, int buffer_size,
-+    FLVMediaSample **samples, int *nb_samples_out);
-diff --git a/libavformat/hdsdec.c b/libavformat/hdsdec.c
-new file mode 100644
-index 0000000..1fadfc8
---- /dev/null
-+++ b/libavformat/hdsdec.c
-@@ -0,0 +1,1036 @@
-+/*
-+ * Adobe HTTP Dynamic Streaming (HDS) demuxer
-+ * Copyright (c) 2013 Cory McCarthy
-+ * Copyright (c) 2014 martii
-+ *
-+ * This file is part of FFmpeg.
-+ *
-+ * 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.
-+ *
-+ * 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 FFmpeg; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-+ */
-+
-+/**
-+ * @file
-+ * @brief Adobe HTTP Dynamic Streaming (HDS) demuxer
-+ * @author Cory McCarthy
-+ * @see http://www.adobe.com/devnet/hds.html
-+ * @see http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/hds/pdfs/adobe-hds-specification.pdf
-+ * @see http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/hds/pdfs/adobe-media-manifest-specification.pdf
-+ * @see http://download.macromedia.com/f4v/video_file_format_spec_v10_1.pdf
-+ *
-+ * @note Link for a HDS test player below:
-+ * @see http://mediapm.edgesuite.net/edgeflash/public/zeri/debug/Main.html
-+ *
-+ * @note Test streams are below:
-+ * @test http://multiplatform-f.akamaihd.net/z/multi/april11/hdworld/hdworld_,512x288_450_b,640x360_700_b,768x432_1000_b,1024x576_1400_m,1280x720_1900_m,1280x720_2500_m,1280x720_3500_m,.mp4.csmil/manifest.f4m?hdcore
-+ * @test http://multiplatform-f.akamaihd.net/z/multi/april11/cctv/cctv_,512x288_450_b,640x360_700_b,768x432_1000_b,1024x576_1400_m,1280x720_1900_m,1280x720_2500_m,1280x720_3500_m,.mp4.csmil/manifest.f4m?hdcore
-+ * @test http://multiplatform-f.akamaihd.net/z/multi/april11/sintel/sintel-hd_,512x288_450_b,640x360_700_b,768x432_1000_b,1024x576_1400_m,1280x720_1900_m,1280x720_2500_m,1280x720_3500_m,.mp4.csmil/manifest.f4m?hdcore
-+ * @test http://multiplatform-f.akamaihd.net/z/multi/akamai10year/Akamai_10_Year_,200,300,600,800,1000,1500,2500,4000,k.mp4.csmil/manifest.f4m?hdcore
-+ * @test http://zerihdndemo-f.akamaihd.net/z/h264/seeker/LegendofSeeker_16x9_24fps_H264_,400K,650K,1Mbps,1.4Mbps,1.8Mbps,2.5Mbps,.mp4.csmil/manifest.f4m?hdcore
-+ * @test http://multiplatform-f.akamaihd.net/z/multi/will/bunny/big_buck_bunny_,640x360_400,640x360_700,640x360_1000,950x540_1500,1280x720_2000,1280x720_3000,.f4v.csmil/manifest.f4m?hdcore
-+ * @test http://multiplatform-f.akamaihd.net/z/multi/companion/nba_game/nba_game.mov_,300,600,800,1000,2500,4000,9000,k.mp4.csmil/manifest.f4m?hdcore
-+ * @test http://multiplatform-f.akamaihd.net/z/multi/companion/big_bang_theory/big_bang_theory.mov_,300,600,800,1000,2500,4000,9000,k.mp4.csmil/manifest.f4m?hdcore
-+ * @test http://multiplatform-f.akamaihd.net/z/multi/shuttle/shuttle_,300,600,800,1000,k.mp4.csmil/manifest.f4m?hdcore
-+ * @test http://multiplatform-f.akamaihd.net/z/multi/up_trailer/up_trailer_720p_,300,600,800,1000,k.mp4.csmil/manifest.f4m?hdcore
-+ * @test http://multiformatlive-f.akamaihd.net/z/demostream_1@2131/manifest.f4m?hdcore
-+ * @test http://zerihdndemo-f.akamaihd.net/z/h264/darkknight/darkknight.smil/manifest.f4m?hdcore
-+ * @test http://zerihdndemo-f.akamaihd.net/z/h264/amours/amours.smil/manifest.f4m?hdcore
-+ * @test http://zerihdndemo-f.akamaihd.net/z/h264/robinhood/robinhood.smil/manifest.f4m?hdcore
-+ * @test http://zerihdndemo-f.akamaihd.net/z/h264/wallstreet/wallstreet.smil/manifest.f4m?hdcore
-+ * @test http://zerihdndemo-f.akamaihd.net/z/h264/rockandroll/rockandroll.smil/manifest.f4m?hdcore
-+ * @test http://184.72.239.149/vod/smil:bigbuckbunny.smil/manifest.f4m
-+ */
-+
-+#include "avformat.h"
-+#include "internal.h"
-+#include "url.h"
-+#include "avio_internal.h"
-+#include "libavutil/avstring.h"
-+#include "libavutil/parseutils.h"
-+#include "libavutil/opt.h"
-+#include "libavutil/dict.h"
-+#include "libavutil/time.h"
-+
-+#include "amfmetadata.h"
-+#include "f4mmanifest.h"
-+#include "f4fbox.h"
-+#include "flvtag.h"
-+
-+#include <unistd.h>
-+#include <pthread.h>
-+#include <semaphore.h>
-+#include <alloca.h>
-+
-+#define MAX_NB_SAMPLES 1024
-+
-+struct HDSDownloadThreadData
-+{
-+    pthread_mutex_t mutex;                    // protects access to this struct
-+    pthread_t thread;                         // download thread id
-+    sem_t *to_thread;                         // send signal to thread
-+    sem_t *to_caller;                         // send signal to caller
-+    sem_t _to_thread;                         // send signal to thread
-+    sem_t _to_caller;                         // send signal to caller
-+    char *cookies;                            // cookies, if any
-+    char *url;                                        // current url
-+    int run;                                  // thread will run until == 0
-+    int abort;                                        // setting this to !=0 aborts download
-+    uint8_t *buffer;                          // set by thread, unset by thread or caller
-+    uint32_t buflen;                          // set by thread, unset by thread or caller
-+    AVIOInterruptCB *interrupt_callback;
-+    AVIOInterruptCB *abort_callback;
-+    AVIOInterruptCB download_abort_callback;
-+};
-+
-+typedef struct HDSBootstrapInfo {
-+    char id[MAX_URL_SIZE];
-+    char url[MAX_URL_SIZE];
-+    char profile[MAX_URL_SIZE];
-+    char *quality;
-+
-+    F4FBox box;
-+} HDSBootstrapInfo;
-+
-+typedef struct HDSMedia {
-+    int media_index;
-+    int bitrate;
-+    char url[MAX_URL_SIZE];
-+    HDSBootstrapInfo *bootstrap_info;
-+
-+    AVStream *audio_stream;
-+    AVStream *video_stream;
-+
-+    int nb_samples;
-+    FLVMediaSample *samples[MAX_NB_SAMPLES];
-+    int sample_index;
-+
-+    unsigned int nb_fragments_read;
-+
-+    struct HDSDownloadThreadData download_data;
-+} HDSMedia;
-+
-+typedef struct HDSContext {
-+    char id[MAX_URL_SIZE];
-+    char base_url[MAX_URL_SIZE];
-+    int is_live;
-+    int last_media_index;
-+
-+    int nb_bootstraps;
-+    HDSBootstrapInfo *bootstrap_info[MAX_NB_BOOTSTRAPS];
-+
-+    int nb_media;
-+    HDSMedia *media[MAX_NB_MEDIA];
-+
-+    int64_t seek_timestamp;
-+    char *cookies;
-+} HDSContext;
-+
-+static void construct_bootstrap_url(const char *base_url, const char *bootstrap_url,
-+    const char *suffix, char *url_out, size_t url_size)
-+{
-+    char *p;
-+
-+    p = url_out;
-+    p += av_strlcat(p, base_url, url_size);
-+    p += av_strlcat(p, bootstrap_url, url_size);
-+    p += av_strlcat(p, suffix, url_size);
-+}
-+
-+static int download_bootstrap(AVFormatContext *s, HDSBootstrapInfo *bootstrap,
-+    uint8_t **buffer_out, int *buffer_size_out)
-+{
-+    HDSContext *c = s->priv_data;
-+    URLContext *puc = NULL;
-+    AVDictionary *opts = NULL;
-+    char url[MAX_URL_SIZE];
-+    uint8_t *buffer;
-+    int buffer_size;
-+    int ret;
-+
-+    memset(url, 0x00, sizeof(url));
-+
-+    if(!av_stristr(bootstrap->url, "?") && av_stristr(s->filename, "?")) {
-+      construct_bootstrap_url(c->base_url, bootstrap->url, av_stristr(s->filename, "?"), url, MAX_URL_SIZE);
-+    } else {
-+      construct_bootstrap_url(c->base_url, bootstrap->url, "", url, MAX_URL_SIZE);
-+    }
-+
-+    av_dict_set(&opts, "cookies", c->cookies, 0);
-+    ret = ffurl_open(&puc, url, AVIO_FLAG_READ, &s->interrupt_callback, &opts);
-+    av_dict_free(&opts);
-+
-+    if(ret < 0) {
-+      av_log(NULL, AV_LOG_ERROR, "hds Failed to start downloading bootstrap, ret: %d\n", ret);
-+      return ret;
-+    }
-+
-+    buffer_size = ffurl_size(puc);
-+    buffer = av_mallocz(buffer_size+FF_INPUT_BUFFER_PADDING_SIZE);
-+    if(!buffer)
-+      return AVERROR(ENOMEM);
-+
-+    if((ret = ffurl_read_complete(puc, buffer, buffer_size)) < 0) {
-+      av_log(NULL, AV_LOG_ERROR, "hds Failed to download bootstrap, ret: %d\n", ret);
-+      av_free(buffer);
-+      return ret;
-+    }
-+
-+    if (c->cookies)
-+      av_freep(&c->cookies);
-+    av_opt_get(puc->priv_data, "cookies", 0, (uint8_t **) &c->cookies);
-+    if (c->cookies && !strlen(c->cookies))
-+      av_freep(&c->cookies);
-+
-+    if((ret = ffurl_close(puc)) < 0) {
-+      av_log(NULL, AV_LOG_ERROR, "hds Failed to finish downloading bootstrap, ret: %d\n", ret);
-+      av_free(buffer);
-+      return ret;
-+    }
-+
-+    if(buffer_out)
-+      *buffer_out = buffer;
-+    else
-+      av_free(buffer);
-+
-+    if(buffer_size_out)
-+      *buffer_size_out = buffer_size;
-+
-+    return 0;
-+}
-+
-+static int create_bootstrap_info(AVFormatContext *s, F4MBootstrapInfo *f4m_bootstrap_info)
-+{
-+    HDSContext *c = s->priv_data;
-+    HDSBootstrapInfo *bootstrap_info;
-+    uint8_t *buffer;
-+    int buffer_size, ret;
-+
-+    bootstrap_info = av_mallocz(sizeof(HDSBootstrapInfo));
-+    if(!bootstrap_info)
-+      return AVERROR(ENOMEM);
-+
-+    c->bootstrap_info[c->nb_bootstraps++] = bootstrap_info;
-+
-+    memcpy(bootstrap_info->id, f4m_bootstrap_info->id, sizeof(bootstrap_info->id));
-+    memcpy(bootstrap_info->url, f4m_bootstrap_info->url, sizeof(bootstrap_info->url));
-+    memcpy(bootstrap_info->profile, f4m_bootstrap_info->profile, sizeof(bootstrap_info->profile));
-+
-+    buffer = f4m_bootstrap_info->metadata;
-+    buffer_size = f4m_bootstrap_info->metadata_size;
-+
-+    if(buffer_size > 0) {
-+      if((ret = ff_parse_f4f_box(buffer, buffer_size, &(bootstrap_info->box))) < 0) {
-+          av_log(NULL, AV_LOG_ERROR, "hds Failed to parse metadata bootstrap box, ret: %d\n", ret);
-+          return ret;
-+      }
-+    } else {
-+      if((ret = download_bootstrap(s, bootstrap_info, &buffer, &buffer_size)) < 0) {
-+          av_log(NULL, AV_LOG_ERROR, "hds Failed to download bootstrap, ret: %d\n", ret);
-+          return ret;
-+      }
-+
-+      if((ret = ff_parse_f4f_box(buffer, buffer_size, &(bootstrap_info->box))) < 0) {
-+          av_log(NULL, AV_LOG_ERROR, "hds Failed to parse downloaded bootstrap box, ret: %d\n", ret);
-+          return ret;
-+      }
-+    }
-+
-+    return 0;
-+}
-+
-+static int create_streams(AVFormatContext *s, HDSMedia *media, AMFMetadata *metadata, int i)
-+{
-+    if (metadata->video_codec_id) {
-+      AVStream *st = avformat_new_stream(s, NULL);
-+      if(!st)
-+          return AVERROR(ENOMEM);
-+
-+      media->video_stream = st;
-+      avpriv_set_pts_info(st, 32, 1, 1000);
-+      st->discard = AVDISCARD_ALL;
-+      st->id = 0 + 2 * i;
-+      st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-+      st->codec->codec_id = metadata->video_codec_id;
-+      st->codec->width = metadata->width;
-+      st->codec->height = metadata->height;
-+      st->codec->bit_rate = metadata->video_data_rate * 1000;
-+    }
-+
-+    if (metadata->audio_codec_id) {
-+      AVStream *st = avformat_new_stream(s, NULL);
-+      if(!st)
-+          return AVERROR(ENOMEM);
-+
-+      media->audio_stream = st;
-+      avpriv_set_pts_info(st, 32, 1, 1000);
-+      st->discard = AVDISCARD_ALL;
-+      st->id = 1 + 2 * i;
-+      st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-+      st->codec->codec_id = metadata->audio_codec_id;
-+      st->codec->channels = metadata->nb_audio_channels;
-+      st->codec->channel_layout = (st->codec->channels == 2) ?  AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO;
-+      st->codec->sample_rate = metadata->audio_sample_rate;
-+      st->codec->sample_fmt = AV_SAMPLE_FMT_S16;
-+      st->codec->bit_rate = metadata->audio_data_rate * 1000;
-+      st->need_parsing = metadata->audio_stream_need_parsing;
-+    }
-+
-+    return 0;
-+}
-+
-+static int create_media(AVFormatContext *s, F4MMedia *f4m_media, int i)
-+{
-+    HDSContext *c = s->priv_data;
-+    HDSMedia *media;
-+    AMFMetadata metadata;
-+    int ret, j;
-+
-+    media = av_mallocz(sizeof(HDSMedia));
-+    if(!media)
-+      return AVERROR(ENOMEM);
-+
-+    c->media[c->nb_media++] = media;
-+
-+    media->media_index = i;
-+    media->bitrate = f4m_media->bitrate;
-+    memcpy(media->url, f4m_media->url, sizeof(media->url));
-+
-+    for(j = 0; j < c->nb_bootstraps; j++) {
-+      if(!av_strcasecmp(f4m_media->bootstrap_info_id, c->bootstrap_info[j]->id))
-+          continue;
-+      media->bootstrap_info = c->bootstrap_info[j];
-+      break;
-+    }
-+
-+    memset(&metadata, 0x00, sizeof(AMFMetadata));
-+    metadata.nb_audio_channels = 1;
-+    if((ret = ff_parse_amf_metadata(f4m_media->metadata, f4m_media->metadata_size, &metadata)) < 0) {
-+      av_log(NULL, AV_LOG_ERROR, "hds Failed to parse metadata, ret: %d\n", ret);
-+      return ret;
-+    }
-+
-+    return create_streams(s, media, &metadata, i);
-+}
-+
-+static int create_pmt(AVFormatContext *s)
-+{
-+    HDSContext *c = s->priv_data;
-+    HDSMedia *media;
-+    AVProgram *p;
-+    int i, j;
-+
-+    j = 0;
-+    for(i = 0; i < c->nb_media; i++) {
-+      media = c->media[i];
-+
-+      p = av_new_program(s, j++);
-+      if(!p)
-+          return AVERROR(ENOMEM);
-+
-+      av_dict_set(&p->metadata,"name",
-+          av_asprintf("%d kbit/s", media->bitrate), 0);
-+
-+      if (media->video_stream)
-+          ff_program_add_stream_index(s, p->id, media->video_stream->index);
-+      if (media->audio_stream)
-+          ff_program_add_stream_index(s, p->id, media->audio_stream->index);
-+    }
-+
-+    return 0;
-+}
-+
-+static void download_thread_start(AVFormatContext *s, HDSMedia *media);
-+
-+static int initialize_context(AVFormatContext *s, F4MManifest *manifest)
-+{
-+    HDSContext *c = s->priv_data;
-+    F4MBootstrapInfo *f4m_bootstrap_info;
-+    F4MMedia *f4m_media;
-+    int i, ret;
-+
-+    for(i = 0; i < manifest->nb_bootstraps; i++) {
-+      f4m_bootstrap_info = manifest->bootstraps[i];
-+      if((ret = create_bootstrap_info(s, f4m_bootstrap_info)) < 0) {
-+          av_log(NULL, AV_LOG_ERROR, "hds Failed to create bootstrap_info, ret: %d\n", ret);
-+          return ret;
-+      }
-+    }
-+
-+    for(i = 0; i < manifest->nb_media; i++) {
-+      f4m_media = manifest->media[i];
-+      if((ret = create_media(s, f4m_media, i)) < 0) {
-+          av_log(NULL, AV_LOG_ERROR, "hds Failed to create media, ret: %d\n", ret);
-+          return ret;
-+      }
-+    }
-+
-+    if((ret = create_pmt(s)) < 0) {
-+      av_log(NULL, AV_LOG_ERROR, "hds Failed to create PMT, ret: %d\n", ret);
-+      return ret;
-+    }
-+
-+    if(!av_strcasecmp(manifest->stream_type, "live"))
-+      c->is_live = 1;
-+
-+    s->duration = manifest->duration;
-+    c->seek_timestamp = AV_NOPTS_VALUE;
-+
-+    for(i = 0; i < c->nb_media; i++)
-+      download_thread_start(s, c->media[i]);
-+
-+    return 0;
-+}
-+
-+//#define HDS_ENABLE_LOG_CALLBACK
-+#ifdef HDS_ENABLE_LOG_CALLBACK
-+static void log_callback(void *ptr __attribute__ ((unused)), int lvl __attribute__ ((unused)), const char *format, va_list ap)
-+{
-+    vfprintf(stderr, format, ap);
-+}
-+#endif
-+
-+static int hds_read_header(AVFormatContext *s)
-+{
-+    HDSContext *c = s->priv_data;
-+    AVIOContext *in = s->pb;
-+    F4MManifest manifest;
-+    int64_t filesize;
-+    uint8_t *buf;
-+    char *p;
-+    int ret;
-+#ifdef HDS_ENABLE_LOG_CALLBACK
-+    av_log_set_callback(log_callback);
-+#endif
-+
-+    p = av_stristr(s->filename, "manifest.f4m");
-+    if(!p) {
-+      av_log(NULL, AV_LOG_ERROR, "hds \"manifest.f4m\" is not a substring of \"%s\"\n", s->filename);
-+      return -1;
-+    }
-+    av_strlcpy(c->base_url, s->filename, p - s->filename + 1);
-+
-+    filesize = avio_size(in);
-+    if(filesize <= 0)
-+      return -1;
-+
-+    buf = av_mallocz(filesize*sizeof(uint8_t));
-+    if(!buf)
-+      return AVERROR(ENOMEM);
-+
-+    avio_read(in, buf, filesize);
-+
-+    memset(&manifest, 0x00, sizeof(F4MManifest));
-+    ret = ff_parse_f4m_manifest(buf, filesize, &manifest);
-+
-+    av_free(buf);
-+
-+    if (ret > -1)
-+      ret = initialize_context(s, &manifest);
-+
-+    ff_free_manifest(&manifest);
-+
-+    return ret;
-+}
-+
-+static void construct_fragment_url(const char *base_url, const char *media_url,
-+    unsigned int segment, unsigned int fragment, const char *suffix, char *url_out, size_t url_size)
-+{
-+    char *p;
-+    char *fragment_str;
-+
-+    p = url_out;
-+    p += av_strlcat(p, base_url, url_size);
-+    p += av_strlcat(p, media_url, url_size);
-+
-+    fragment_str = av_asprintf("Seg%u-Frag%u", segment, fragment);
-+    p += av_strlcat(p, fragment_str, url_size);
-+    av_free(fragment_str);
-+
-+    p += av_strlcat(p, suffix, url_size);
-+}
-+
-+static int get_fragment_offset(HDSMedia *media, int64_t timestamp)
-+{
-+    F4FBootstrapInfoBox *abst = &(media->bootstrap_info->box.abst);
-+    int fragments_max = 0;
-+    int i, j;
-+
-+    for(i = 0; i < abst->nb_segment_run_table_boxes; i++) {
-+      F4FSegmentRunTableBox *asrt = abst->segment_run_table_boxes[i];
-+      int found = 0;
-+      if (asrt->nb_quality_entries && media->bootstrap_info->quality)
-+          for(j = 0; !found && j < asrt->nb_quality_entries; j++)
-+              found = !strcmp(asrt->quality_entries[j], media->bootstrap_info->quality);
-+      else
-+          found = 1;
-+
-+      if (found) {
-+          F4FSegmentRunEntry *segment_entry = asrt->segment_run_entries[asrt->nb_segment_run_entries - 1];
-+          fragments_max = segment_entry->fragments_per_segment;
-+          break;
-+      }
-+    }
-+
-+    for(i = 0; i < abst->nb_fragment_run_table_boxes; i++) {
-+      int found = 0;
-+      F4FFragmentRunTableBox *afrt = abst->fragment_run_table_boxes[i];
-+      if (afrt->nb_quality_entries && media->bootstrap_info->quality)
-+          for(j = 0; !found && j < afrt->nb_quality_entries; j++)
-+              found = !strcmp(afrt->quality_entries[j], media->bootstrap_info->quality);
-+      else
-+          found = 1;
-+
-+      if (found) {
-+          for(j = 0; j < afrt->nb_fragment_run_entries; j++) {
-+              F4FFragmentRunEntry *fre = afrt->fragment_run_entries[j];
-+              int fragcount;
-+              if (j + 1 < afrt->nb_fragment_run_entries) {
-+                  fragcount = afrt->fragment_run_entries[j + 1]->first_fragment - fre->first_fragment;
-+                  fragments_max -= fragcount;
-+              } else
-+                  fragcount = fragments_max;
-+
-+              if (timestamp >= fre->first_fragment_time_stamp && timestamp <= fre->first_fragment_time_stamp + fragcount * fre->fragment_duration)
-+                  return fre->first_fragment + (timestamp - fre->first_fragment_time_stamp)/fre->fragment_duration;
-+          }
-+          break;
-+      }
-+    }
-+    return 0;
-+}
-+
-+static int get_segment_fragment(int is_live, HDSMedia *media, unsigned int *segment_out, unsigned int *fragment_out)
-+{
-+    F4FBootstrapInfoBox *abst = &(media->bootstrap_info->box.abst);
-+    unsigned int segment = ~0, fragment = ~0, fragments_max = 0;
-+    int i, j, skip;
-+
-+    if (is_live) {
-+      // FIXME. This is a crude hack.
-+      *segment_out = 1;
-+      *fragment_out = media->nb_fragments_read;
-+      return 0;
-+    }
-+
-+    skip = media->nb_fragments_read;
-+    for(i = 0; segment == ~0 && i < abst->nb_segment_run_table_boxes; i++) {
-+      F4FSegmentRunTableBox *asrt = abst->segment_run_table_boxes[i];
-+      int found = 0;
-+      if (asrt->nb_quality_entries && media->bootstrap_info->quality)
-+          for(j = 0; !found && j < asrt->nb_quality_entries; j++)
-+              found = !strcmp(asrt->quality_entries[j], media->bootstrap_info->quality);
-+      else
-+          found = 1;
-+
-+      if (found) {
-+          for (j = 0; segment == ~0 && j < asrt->nb_segment_run_entries; j++) {
-+              F4FSegmentRunEntry *segment_entry = asrt->segment_run_entries[j];
-+
-+              if (segment_entry->fragments_per_segment < skip) {
-+                  skip -= segment_entry->fragments_per_segment;
-+                  fragments_max = segment_entry->fragments_per_segment;
-+              } else
-+                  segment = segment_entry->first_segment;
-+          }
-+          break;
-+      }
-+    }
-+
-+    if(segment == ~0) {
-+      av_log(NULL, AV_LOG_ERROR, "hds segment entry for next fragment (%u) not found, skip: %d\n", media->nb_fragments_read, skip);
-+      return 0;
-+    }
-+
-+    skip = media->nb_fragments_read;
-+    for(i = 0; fragment == ~0 && i < abst->nb_fragment_run_table_boxes; i++) {
-+      int found = 0;
-+      F4FFragmentRunTableBox *afrt = abst->fragment_run_table_boxes[i];
-+      if (afrt->nb_quality_entries && media->bootstrap_info->quality)
-+          for(j = 0; !found && j < afrt->nb_quality_entries; j++)
-+              found = !strcmp(afrt->quality_entries[j], media->bootstrap_info->quality);
-+      else
-+          found = 1;
-+
-+      if (found) {
-+          for(j = 0; fragment == ~0 && j < afrt->nb_fragment_run_entries; j++) {
-+              int fragcount;
-+              F4FFragmentRunEntry *fre = afrt->fragment_run_entries[j];
-+              if (j + 1 < afrt->nb_fragment_run_entries) {
-+                  fragcount = afrt->fragment_run_entries[j + 1]->first_fragment - fre->first_fragment;
-+                  fragments_max -= fragcount;
-+              } else
-+                  fragcount = fragments_max;
-+
-+              if (fragcount < skip)
-+                  fragcount -= skip;
-+              else {
-+                  fragment = fre->first_fragment + skip;
-+                  skip = 0;
-+              }
-+          }
-+          break;
-+      }
-+    }
-+
-+    if (!is_live && skip > 0) {
-+      av_log(NULL, AV_LOG_ERROR, "hds fragment %d fragments beyond EOF\n", skip);
-+      return AVERROR_EOF;
-+    }
-+
-+    if(fragment == ~0) {
-+      av_log(NULL, AV_LOG_ERROR, "hds fragment entry not found\n");
-+      return -1;
-+    }
-+
-+    if(segment_out)
-+      *segment_out = segment;
-+    if(fragment_out)
-+      *fragment_out = fragment;
-+
-+    return 0;
-+}
-+
-+static int download_abort_callback_function(void *opaque)
-+{
-+    HDSMedia *media = (HDSMedia *) opaque;
-+    return media->download_data.abort || ff_check_interrupt(media->download_data.interrupt_callback);
-+}
-+
-+static void *download_thread(void *opaque)
-+{
-+    HDSMedia *media = (HDSMedia *) opaque;
-+
-+    while (media->download_data.run && !download_abort_callback_function(media)) {
-+      AVDictionary *opts = NULL;
-+      URLContext *puc = NULL;
-+      uint8_t *buffer = NULL;
-+      int buffer_size = 0, ret;
-+      char *url = NULL;
-+      int url_len;
-+      int tries_left = 15;
-+
-+      if (sem_wait(media->download_data.to_thread))
-+          break;
-+      if (!media->download_data.run)
-+          continue;
-+
-+      pthread_mutex_lock(&media->download_data.mutex);
-+      media->download_data.abort = 0;
-+      if (media->download_data.buffer)
-+          av_freep(&media->download_data.buffer);
-+      media->download_data.buflen = 0;
-+      // generate local copies from HDSDownloadThreadData
-+      if (media->download_data.cookies)
-+          av_dict_set(&opts, "cookies", media->download_data.cookies, 0);
-+      url_len = strlen(media->download_data.url) + 1;
-+      url = alloca(url_len);
-+      strncpy(url, media->download_data.url, url_len);
-+      pthread_mutex_unlock(&media->download_data.mutex);
-+      //av_log(NULL, AV_LOG_DEBUG, "%s %d: downloading %s\n", __FILE__,__LINE__, url);
-+
-+      // initiate download
-+      do {
-+          ret = ffurl_open(&puc, url, AVIO_FLAG_READ, &media->download_data.download_abort_callback, &opts);
-+          if (ret < 0) {
-+              sleep(1);
-+              if (download_abort_callback_function(media))
-+                  break;
-+              sleep(1);
-+              tries_left--;
-+          }
-+      } while (ret < 0 && media->download_data.run && !download_abort_callback_function(media) && tries_left > 0);
-+
-+      if (opts)
-+          av_dict_free(&opts);
-+
-+      if(ret < 0) {
-+          av_log(NULL, AV_LOG_ERROR, "hds Failed to start downloading url:%s, ret:%d\n", url, ret);
-+      } else {
-+          buffer_size = ffurl_size(puc);
-+          if (buffer_size > -1)
-+              buffer = av_mallocz(buffer_size+FF_INPUT_BUFFER_PADDING_SIZE);
-+          if(!buffer)
-+              av_log(NULL, AV_LOG_DEBUG, "hds Failed to allocate %d bytes buffer\n", buffer_size);
-+      }
-+
-+      if(buffer && (ret = ffurl_read_complete(puc, buffer, buffer_size)) < 0) {
-+          av_log(NULL, AV_LOG_ERROR, "hds Failed to download fragment, ret: %d\n", ret);
-+          av_freep(&buffer);
-+      }
-+
-+      pthread_mutex_lock(&media->download_data.mutex);
-+      if (media->download_data.abort || !buffer) {
-+          media->download_data.abort = 0;
-+      } else {
-+          //av_log(NULL, AV_LOG_DEBUG, "%s %d: downloaded  %s\n", __FILE__,__LINE__, media->download_data.url);
-+          if (media->download_data.cookies)
-+              av_freep(&media->download_data.cookies);
-+          av_opt_get(puc->priv_data, "cookies", 0, (uint8_t **) &media->download_data.cookies);
-+          if (media->download_data.cookies && !strlen(media->download_data.cookies))
-+              av_freep(&media->download_data.cookies);
-+          media->download_data.buffer = buffer;
-+          media->download_data.buflen = buffer_size;
-+      }
-+      sem_post(media->download_data.to_caller);       // confirm download
-+      pthread_mutex_unlock(&media->download_data.mutex);
-+      if (puc)
-+          ffurl_close(puc);
-+    }
-+    pthread_exit(NULL);
-+}
-+
-+static void download_thread_start(AVFormatContext *s, HDSMedia *media)
-+{
-+#if defined(__APPLE__)
-+    char buf[40];
-+#endif
-+    pthread_mutex_init(&media->download_data.mutex, NULL);
-+#if defined(__APPLE__) // no unnamed semaphores on darwin
-+    snprintf(buf, sizeof(buf), "sem_to_thread%d", media->media_index);
-+    media->download_data.to_thread = sem_open(buf, O_CREAT, 0644, 0);
-+    snprintf(buf, sizeof(buf), "sem_to_caller%d", media->media_index);
-+    media->download_data.to_caller = sem_open(buf, O_CREAT, 0644, 0);
-+#else
-+    sem_init(&media->download_data._to_thread, 0, 0);
-+    sem_init(&media->download_data._to_caller, 0, 0);
-+    media->download_data.to_thread = &media->download_data._to_thread;
-+    media->download_data.to_caller = &media->download_data._to_caller;
-+#endif
-+    media->download_data.thread = 0;
-+    media->download_data.run = 1;
-+    media->download_data.abort = 0;
-+    media->download_data.url = NULL;
-+    media->download_data.buffer = NULL;
-+    media->download_data.buflen = 0;
-+    media->download_data.cookies = NULL;
-+    media->download_data.interrupt_callback = &s->interrupt_callback;
-+    media->download_data.download_abort_callback.callback = download_abort_callback_function;
-+    media->download_data.download_abort_callback.opaque = media;
-+    media->download_data.abort_callback = &media->download_data.download_abort_callback;
-+    if (pthread_create(&media->download_data.thread, NULL, download_thread, media))
-+      av_log(NULL, AV_LOG_ERROR, "hds: creating download thread failed\n");
-+}
-+
-+static void download_thread_stop(HDSMedia *media)
-+{
-+    if (media->download_data.thread) {
-+#if defined(__APPLE__)
-+      char buf[40];
-+#endif
-+      media->download_data.run = 0;
-+      media->download_data.abort = 1;
-+      sem_post(media->download_data.to_thread);
-+      pthread_join(media->download_data.thread, NULL);
-+      media->download_data.thread = 0;
-+      if (media->download_data.url)
-+              av_freep(&media->download_data.url);
-+      if (media->download_data.cookies)
-+              av_freep(&media->download_data.cookies);
-+      if (media->download_data.buffer)
-+              av_freep(&media->download_data.buffer);
-+      media->download_data.buflen = 0;
-+#if defined(__APPLE__)
-+      sem_close(media->download_data.to_thread);
-+      sem_close(media->download_data.to_caller);
-+      snprintf(buf, sizeof(buf), "sem_to_thread%d", media->media_index);
-+      sem_unlink(buf);
-+      snprintf(buf, sizeof(buf), "sem_to_caller%d", media->media_index);
-+      sem_unlink(buf);
-+#else
-+      sem_destroy(&media->download_data._to_thread);
-+      sem_destroy(&media->download_data._to_caller);
-+#endif
-+      pthread_mutex_destroy(&media->download_data.mutex);
-+    }
-+}
-+
-+static int download_fragment(AVFormatContext *s, HDSMedia *media, uint8_t **buffer_out, int *buffer_size_out)
-+{
-+    HDSContext *c = s->priv_data;
-+    char url[MAX_URL_SIZE];
-+    unsigned int segment, fragment;
-+    int ret;
-+
-+    if((ret = get_segment_fragment(c->is_live, media, &segment, &fragment)) < 0)
-+      return ret;
-+    memset(url, 0x00, sizeof(url));
-+    if(!av_stristr(media->url, "?") && av_stristr(s->filename, "?"))
-+      construct_fragment_url(c->base_url, media->url, segment, fragment, av_stristr(s->filename, "?"), url, MAX_URL_SIZE);
-+    else
-+      construct_fragment_url(c->base_url, media->url, segment, fragment, "", url, MAX_URL_SIZE);
-+
-+    pthread_mutex_lock(&media->download_data.mutex);
-+
-+    if (!media->download_data.cookies)
-+      media->download_data.cookies = av_strdup(c->cookies);
-+    if (media->download_data.url && strcmp(media->download_data.url, url)) {
-+      // download in progress or finished, but not the wanted one. abort it.
-+      media->download_data.abort = 1; // initiate abort
-+      pthread_mutex_unlock(&media->download_data.mutex);
-+      sem_wait(media->download_data.to_caller); // wait until current transfer has finished
-+      pthread_mutex_lock(&media->download_data.mutex);
-+      av_freep(&media->download_data.url);
-+    }
-+    if (!media->download_data.url) {
-+      // queue retrieval of wanted url
-+      media->download_data.url = av_strdup(url);
-+      sem_post(media->download_data.to_thread);       // initiate download
-+    }
-+    if (media->download_data.url && !strcmp(media->download_data.url, url)) {
-+      // download matches what we want
-+      pthread_mutex_unlock(&media->download_data.mutex);
-+      sem_wait(media->download_data.to_caller); // wait until finished
-+      pthread_mutex_lock(&media->download_data.mutex);
-+      av_freep(&media->download_data.url);
-+      if (media->download_data.buffer) {
-+          *buffer_out = media->download_data.buffer;
-+          *buffer_size_out = media->download_data.buflen;
-+          media->download_data.buffer = NULL;
-+          media->download_data.buflen = 0;
-+          ret = 0;
-+          media->nb_fragments_read++;
-+          //initiate retrieval of next url
-+          if(!get_segment_fragment(c->is_live, media, &segment, &fragment))
-+              memset(url, 0x00, sizeof(url));
-+              if(!av_stristr(media->url, "?") && av_stristr(s->filename, "?"))
-+                  construct_fragment_url(c->base_url, media->url, segment, fragment, av_stristr(s->filename, "?"), url, MAX_URL_SIZE);
-+              else
-+                  construct_fragment_url(c->base_url, media->url, segment, fragment, "", url, MAX_URL_SIZE);
-+              media->download_data.url = av_strdup(url);
-+              sem_post(media->download_data.to_thread);       // initiate download
-+      } else {
-+          // finished but failed
-+          ret = AVERROR(EIO);
-+      }
-+    }
-+    pthread_mutex_unlock(&media->download_data.mutex);
-+    return ret;
-+}
-+
-+static int get_next_fragment(AVFormatContext *s, HDSMedia *media)
-+{
-+    F4FBox box;
-+    uint8_t *buffer = NULL;
-+    int buffer_size = 0, ret;
-+
-+    if (ff_check_interrupt(media->download_data.interrupt_callback))
-+      return AVERROR(EIO);
-+
-+    if((ret = download_fragment(s, media, &buffer, &buffer_size)) < 0)
-+      return ret;
-+
-+    memset(&box, 0x00, sizeof(F4FBox));
-+    if((ret = ff_parse_f4f_box(buffer, buffer_size, &box)) < 0) {
-+      av_log(NULL, AV_LOG_ERROR, "hds Failed to parse bootstrap box, ret: %d\n", ret);
-+      av_free(buffer);
-+      ff_free_f4f_box(&box);
-+      return ret;
-+    }
-+    av_free(buffer);
-+
-+    if((ret = ff_decode_flv_body(box.mdat.data, box.mdat.size, media->samples, &media->nb_samples)) < 0) {
-+      av_log(NULL, AV_LOG_ERROR, "hds Failed to decode FLV body, ret: %d\n", ret);
-+      ff_free_f4f_box(&box);
-+      return ret;
-+    }
-+
-+    ff_free_f4f_box(&box);
-+
-+    return 0;
-+}
-+
-+static void read_next_sample(HDSMedia *media, AVPacket *pkt)
-+{
-+    FLVMediaSample *sample;
-+
-+    sample = media->samples[media->sample_index];
-+    media->sample_index++;
-+
-+    av_new_packet(pkt, sample->data_size);
-+    memcpy(pkt->data, sample->data, sample->data_size);
-+
-+    pkt->dts = sample->dts;
-+    pkt->pts = sample->pts;
-+
-+    if(sample->type == AVMEDIA_TYPE_VIDEO && media->video_stream)
-+      pkt->stream_index = media->video_stream->index;
-+    else if(sample->type == AVMEDIA_TYPE_AUDIO && media->audio_stream)
-+      pkt->stream_index = media->audio_stream->index;
-+}
-+
-+static void clear_samples(HDSMedia *media)
-+{
-+    FLVMediaSample *sample;
-+    int i;
-+
-+    for(i = 0; i < media->nb_samples; i++) {
-+      sample = media->samples[i];
-+      av_freep(&sample->data);
-+      av_freep(&sample);
-+      media->samples[i] = NULL;
-+    }
-+
-+    media->nb_samples = 0;
-+    media->sample_index = 0;
-+}
-+
-+static int get_next_packet(AVFormatContext *s, HDSMedia *media, AVPacket *pkt)
-+{
-+    HDSContext *c = s->priv_data;
-+    int ret;
-+
-+    if (c->is_live && !media->nb_fragments_read) {
-+      int64_t ts = media->bootstrap_info->box.abst.current_media_time;
-+      media->nb_fragments_read = get_fragment_offset(media, ts);
-+      if (media->nb_fragments_read > 1)
-+              media->nb_fragments_read--;
-+    }
-+
-+    if (c->seek_timestamp != AV_NOPTS_VALUE) {
-+      int64_t ts = c->seek_timestamp;
-+      c->seek_timestamp = AV_NOPTS_VALUE;
-+      media->nb_fragments_read = get_fragment_offset(media, ts);
-+      clear_samples(media);
-+    }
-+
-+    if(media->nb_samples == 0) {
-+      if((ret = get_next_fragment(s, media)) < 0) {
-+          return ret;
-+      }
-+    }
-+
-+    if(media->nb_samples > 0) {
-+      read_next_sample(media, pkt);
-+    }
-+
-+    if(media->sample_index >= media->nb_samples) {
-+      clear_samples(media);
-+    }
-+
-+    return 0;
-+}
-+
-+static int hds_read_packet(AVFormatContext *s, AVPacket *pkt)
-+{
-+    HDSContext *c = s->priv_data;
-+    HDSMedia *media = NULL;
-+    int i, ret;
-+
-+    for (i = c->last_media_index + 1; !media && i < c->nb_media; i++) {
-+      media = c->media[i];
-+      if ((!media->video_stream || (media->video_stream->discard == AVDISCARD_ALL))
-+       && (!media->audio_stream || (media->audio_stream->discard == AVDISCARD_ALL)))
-+          media = NULL;
-+    }
-+    for (i = 0; !media && i < c->nb_media; i++) {
-+      media = c->media[i];
-+      if ((!media->video_stream || (media->video_stream->discard == AVDISCARD_ALL))
-+       && (!media->audio_stream || (media->audio_stream->discard == AVDISCARD_ALL)))
-+          media = NULL;
-+    }
-+    c->last_media_index = i;
-+
-+    if (media && !media->bootstrap_info && c->nb_bootstraps)
-+        media->bootstrap_info = c->bootstrap_info[0];
-+
-+    if (!media || !media->bootstrap_info) {
-+      av_log(NULL, AV_LOG_ERROR, "hds Failed to find valid stream\n");
-+      return AVERROR(EIO);
-+    }
-+
-+    if((ret = get_next_packet(s, media, pkt)) < 0) {
-+      if(ret != AVERROR_EOF)
-+          av_log(NULL, AV_LOG_ERROR, "hds Failed to get next packet, ret: %d\n", ret);
-+      return ret;
-+    }
-+
-+    return 0;
-+}
-+
-+static int hds_close(AVFormatContext *s)
-+{
-+    HDSContext *c = s->priv_data;
-+    HDSBootstrapInfo *bootstrap_info;
-+    HDSMedia *media;
-+    int i;
-+
-+    for(i = 0; i < c->nb_media; i++)
-+      download_thread_stop(c->media[i]);
-+
-+    for(i = 0; i < c->nb_bootstraps; i++) {
-+      bootstrap_info = c->bootstrap_info[i];
-+
-+      ff_free_f4f_box(&bootstrap_info->box);
-+      av_freep(&bootstrap_info);
-+    }
-+
-+    for(i = 0; i < c->nb_media; i++) {
-+      media = c->media[i];
-+
-+      if (media->download_data.buffer)
-+          av_freep(&media->download_data.buffer);
-+
-+      clear_samples(media);
-+      av_freep(&media);
-+    }
-+
-+    if(c->cookies)
-+      av_freep(&c->cookies);
-+
-+    memset(c, 0x00, sizeof(HDSContext));
-+
-+    return 0;
-+}
-+
-+static int hds_probe(AVProbeData *p)
-+{
-+    if(p->filename && av_stristr(p->filename, ".f4m"))
-+      return AVPROBE_SCORE_MAX;
-+    return 0;
-+}
-+
-+static int hds_read_seek(AVFormatContext *s, int stream_index,
-+                             int64_t timestamp, int flags)
-+{
-+    HDSContext *c = s->priv_data;
-+
-+    if (flags & AVSEEK_FLAG_BYTE)
-+      return AVERROR(ENOSYS);
-+    if (s->duration < c->seek_timestamp) {
-+      c->seek_timestamp = AV_NOPTS_VALUE;
-+      return AVERROR(EIO);
-+    }
-+    c->seek_timestamp = timestamp;
-+
-+    if (c->is_live) {
-+      int i;
-+      for(i = 0; i < c->nb_media; i++)
-+          c->media[i]->nb_fragments_read = 0;
-+      c->seek_timestamp = AV_NOPTS_VALUE;
-+      return 0;
-+    }
-+
-+    return 0;
-+}
-+
-+AVInputFormat ff_hds_demuxer = {
-+    .name        = "hds",
-+    .long_name      = NULL_IF_CONFIG_SMALL("Adobe HTTP Dynamic Streaming Demuxer"),
-+    .priv_data_size = sizeof(HDSContext),
-+    .read_probe     = hds_probe,
-+    .read_header    = hds_read_header,
-+    .read_packet    = hds_read_packet,
-+    .read_close     = hds_close,
-+    .read_seek      = hds_read_seek,
-+};
--- 
-2.4.0
-