diff mbox

[v9,03/18] package/ffmpeg: Add Kodi patchset

Message ID 1419356801-31525-4-git-send-email-bernd.kuhls@t-online.de
State Accepted
Headers show

Commit Message

Bernd Kuhls Dec. 23, 2014, 5:46 p.m. UTC
In the past xbmc delivered its own ffmpeg source code with specific patches to
address bugs found during the use of xbmc. For Helix the ffmpeg source code was
removed, Helix uses a vanilla ffmpeg source tarball and applies this patchset
on top of it.

Downloaded from
https://github.com/xbmc/FFmpeg/compare/FFmpeg:release/2.5...release/2.5-xbmc.patch

Signed-off-by: Bernd Kuhls <bernd.kuhls@t-online.de>
---
 package/ffmpeg/0001-kodi.patch |  610 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 610 insertions(+)
 create mode 100644 package/ffmpeg/0001-kodi.patch

Comments

Thomas Petazzoni Dec. 26, 2014, 5:22 p.m. UTC | #1
Dear Bernd Kuhls,

On Tue, 23 Dec 2014 18:46:26 +0100, Bernd Kuhls wrote:
> In the past xbmc delivered its own ffmpeg source code with specific patches to
> address bugs found during the use of xbmc. For Helix the ffmpeg source code was
> removed, Helix uses a vanilla ffmpeg source tarball and applies this patchset
> on top of it.
> 
> Downloaded from
> https://github.com/xbmc/FFmpeg/compare/FFmpeg:release/2.5...release/2.5-xbmc.patch
> 
> Signed-off-by: Bernd Kuhls <bernd.kuhls@t-online.de>

I am wondering, wouldn't it be easier to have the individual patches,
instead of one big patch that combines all the XBMC patches?

Also, have those patches been submitted upstream? Why is there an XBMC
patch set, instead of patches submitted to upstream ffmpeg? Can we
expect this patch series to reduce in size over time?

Thomas
Bernd Kuhls Jan. 4, 2015, 11:45 a.m. UTC | #2
[posted and mailed]

Hi Thomas,

(digging through mail backlog after holiday...)

Thomas Petazzoni
<thomas.petazzoni@free-electrons.com> wrote
in news:20141226182251.79d06670@free-electrons.com: 

> I am wondering, wouldn't it be easier to have the individual patches,
> instead of one big patch that combines all the XBMC patches?

Ok.

> Also, have those patches been submitted upstream? Why is there an XBMC
> patch set, instead of patches submitted to upstream ffmpeg?

Quoting FernetMenta (http://forum.kodi.tv/showthread.php?tid=177474&pid=
1653966#pid1653966):
"We have not accepted any ffmpeg patches not accepted upstream for more than 
a year. Instead we do work with the ffmpeg devs and fix bugs upstream first. 
Nevertheless XBMC has a different release cycle than ffmpeg it it is 
necessary to backport patches."

> Can we expect this patch series to reduce in size over time?

Yes.

Regards, Bernd
diff mbox

Patch

diff --git a/package/ffmpeg/0001-kodi.patch b/package/ffmpeg/0001-kodi.patch
new file mode 100644
index 0000000..dba5dc4
--- /dev/null
+++ b/package/ffmpeg/0001-kodi.patch
@@ -0,0 +1,610 @@ 
+In the past xbmc delivered its own ffmpeg source code with specific patches to
+address bugs found during the use of xbmc. For Kodi Helix the ffmpeg source code
+was removed, Helix uses a vanilla ffmpeg source tarball and applies this patchset
+on top of it.
+
+Downloaded from
+https://github.com/xbmc/FFmpeg/compare/FFmpeg:release/2.5...release/2.5-xbmc.patch
+
+Signed-off-by: Bernd Kuhls <bernd.kuhls@t-online.de>
+
+From 74f1c9b43b191a9d6b494e90a4a11677fca33c13 Mon Sep 17 00:00:00 2001
+From: Joakim Plate <elupus@ecce.se>
+Date: Sun, 11 Sep 2011 19:04:51 +0200
+Subject: [PATCH 01/13] Support raw dvdsub palette as stored on normal dvd's
+
+This is how the palette is stored on dvd's. Currently
+only xbmc passes the palette information to libavcodec
+this way.
+---
+ libavcodec/dvdsubdec.c | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+diff --git a/libavcodec/dvdsubdec.c b/libavcodec/dvdsubdec.c
+index 39604f3..a711e16 100644
+--- a/libavcodec/dvdsubdec.c
++++ b/libavcodec/dvdsubdec.c
+@@ -64,6 +64,24 @@ static void yuv_a_to_rgba(const uint8_t *ycbcr, const uint8_t *alpha, uint32_t *
+     }
+ }
+ 
++static void ayvu_to_argb(const uint8_t *ayvu, uint32_t *argb, int num_values)
++{
++    uint8_t *cm = ff_crop_tab + MAX_NEG_CROP;
++    uint8_t r, g, b;
++    int i, y, cb, cr, a;
++    int r_add, g_add, b_add;
++
++    for (i = num_values; i > 0; i--) {
++        a = *ayvu++;
++        y = *ayvu++;
++        cr = *ayvu++;
++        cb = *ayvu++;
++        YUV_TO_RGB1_CCIR(cb, cr);
++        YUV_TO_RGB2_CCIR(r, g, b, y);
++        *argb++ = (a << 24) | (r << 16) | (g << 8) | b;
++    }
++}
++
+ static int decode_run_2bit(GetBitContext *gb, int *color)
+ {
+     unsigned int v, t;
+@@ -697,6 +715,12 @@ static av_cold int dvdsub_init(AVCodecContext *avctx)
+         parse_ifo_palette(ctx, ctx->ifo_str);
+     if (ctx->palette_str)
+         parse_palette(ctx, ctx->palette_str);
++
++    if (!ctx->has_palette && avctx->extradata_size == 64) {
++        ayvu_to_argb((uint8_t*)avctx->extradata, ctx->palette, 16);
++        ctx->has_palette = 1;
++    }
++
+     if (ctx->has_palette) {
+         int i;
+         av_log(avctx, AV_LOG_DEBUG, "palette:");
+
+From fbd0b8b0239d3786b941adc89322b8e49e4c768e Mon Sep 17 00:00:00 2001
+From: Joakim Plate <elupus@ecce.se>
+Date: Mon, 12 Sep 2011 21:37:17 +0200
+Subject: [PATCH 02/13] asf hacks
+
+---
+ libavformat/asfdec.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/libavformat/asfdec.c b/libavformat/asfdec.c
+index 7f7bb4d..8911987 100644
+--- a/libavformat/asfdec.c
++++ b/libavformat/asfdec.c
+@@ -1549,9 +1549,20 @@ static int asf_read_seek(AVFormatContext *s, int stream_index,
+     AVStream *st    = s->streams[stream_index];
+     int ret = 0;
+ 
++    if (pts == 0) {
++      // this is a hack since av_gen_search searches the entire file in this case
++      av_log(s, AV_LOG_DEBUG, "SEEKTO: %"PRId64"\n", s->data_offset);
++      if (avio_seek(s->pb, s->data_offset, SEEK_SET) < 0)
++          return -1;
++      return 0;
++    }
++
+     if (s->packet_size <= 0)
+         return -1;
+ 
++    if (st->codec->codec_type != AVMEDIA_TYPE_VIDEO)
++        return -1;
++
+     /* Try using the protocol's read_seek if available */
+     if (s->pb) {
+         int ret = avio_seek_time(s->pb, stream_index, pts, flags);
+
+From 54200b3e6009c6870e33c02c8bbcf023fcd92cac Mon Sep 17 00:00:00 2001
+From: Cory Fields <theuni-nospam-@xbmc.org>
+Date: Mon, 28 Jun 2010 01:55:31 -0400
+Subject: [PATCH 03/13] if av_read_packet returns AVERROR_IO, we are done.
+ ffmpeg's codecs might or might not handle returning any completed demuxed
+ packets correctly
+
+---
+ libavformat/utils.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/libavformat/utils.c b/libavformat/utils.c
+index ae6347a..3e8af50 100644
+--- a/libavformat/utils.c
++++ b/libavformat/utils.c
+@@ -1304,6 +1304,8 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt)
+         if (ret < 0) {
+             if (ret == AVERROR(EAGAIN))
+                 return ret;
++            if (ret == AVERROR(EIO))
++                return ret;
+             /* flush the parsers */
+             for (i = 0; i < s->nb_streams; i++) {
+                 st = s->streams[i];
+
+From e9236f6fe3fae1ad4a3a2b6b63db493b083f0b21 Mon Sep 17 00:00:00 2001
+From: Cory Fields <theuni-nospam-@xbmc.org>
+Date: Mon, 28 Jun 2010 02:10:50 -0400
+Subject: [PATCH 04/13] added: Ticket #7187, TV Teletext support for DVB EBU
+ Teletext streams
+
+---
+ libavcodec/avcodec.h | 4 ++++
+ libavformat/mpegts.c | 2 ++
+ 2 files changed, 6 insertions(+)
+
+diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
+index dabae1b..dd6ef3f 100644
+--- a/libavcodec/avcodec.h
++++ b/libavcodec/avcodec.h
+@@ -520,6 +520,10 @@ enum AVCodecID {
+     AV_CODEC_ID_PJS        = MKBETAG('P','h','J','S'),
+     AV_CODEC_ID_ASS        = MKBETAG('A','S','S',' '),  ///< ASS as defined in Matroska
+ 
++    /* data codecs */
++    AV_CODEC_ID_VBI_DATA= 0x17500,
++    AV_CODEC_ID_VBI_TELETEXT,
++
+     /* other specific kind of codecs (generally used for attachments) */
+     AV_CODEC_ID_FIRST_UNKNOWN = 0x18000,           ///< A dummy ID pointing at the start of various fake codecs.
+     AV_CODEC_ID_TTF = 0x18000,
+diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
+index 97da0a3..5dd28f1 100644
+--- a/libavformat/mpegts.c
++++ b/libavformat/mpegts.c
+@@ -729,6 +729,8 @@ static const StreamType DESC_types[] = {
+     { 0x7b, AVMEDIA_TYPE_AUDIO,    AV_CODEC_ID_DTS          },
+     { 0x56, AVMEDIA_TYPE_SUBTITLE, AV_CODEC_ID_DVB_TELETEXT },
+     { 0x59, AVMEDIA_TYPE_SUBTITLE, AV_CODEC_ID_DVB_SUBTITLE }, /* subtitling descriptor */
++    { 0x45, AVMEDIA_TYPE_DATA,         AV_CODEC_ID_VBI_DATA }, /* VBI Data descriptor */
++    { 0x46, AVMEDIA_TYPE_DATA,     AV_CODEC_ID_VBI_TELETEXT }, /* VBI Teletext descriptor */
+     { 0 },
+ };
+ 
+
+From 1f48ee2290e9041b0371eb9a9cb742e9568930a1 Mon Sep 17 00:00:00 2001
+From: Joakim Plate <elupus@ecce.se>
+Date: Sun, 18 Sep 2011 19:16:34 +0200
+Subject: [PATCH 05/13] Don't accept mpegts PMT that isn't current
+
+---
+ libavformat/mpegts.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
+index 5dd28f1..9f85aed 100644
+--- a/libavformat/mpegts.c
++++ b/libavformat/mpegts.c
+@@ -572,6 +572,7 @@ typedef struct SectionHeader {
+     uint8_t tid;
+     uint16_t id;
+     uint8_t version;
++    uint8_t current;
+     uint8_t sec_num;
+     uint8_t last_sec_num;
+ } SectionHeader;
+@@ -643,6 +644,7 @@ static int parse_section_header(SectionHeader *h,
+     val = get8(pp, p_end);
+     if (val < 0)
+         return val;
++    h->current = val & 0x1;
+     h->version = (val >> 1) & 0x1f;
+     val = get8(pp, p_end);
+     if (val < 0)
+@@ -1968,6 +1970,8 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
+         return;
+     if (ts->skip_changes)
+         return;
++    if (!h->current)
++        return;
+ 
+     ts->stream->ts_id = h->id;
+ 
+
+From db98fbe37f2f7175ff03b8d582e940518ddf3642 Mon Sep 17 00:00:00 2001
+From: Joakim Plate <elupus@ecce.se>
+Date: Sun, 18 Sep 2011 19:17:23 +0200
+Subject: [PATCH 06/13] Don't reparse PMT unless it's version has changed
+
+---
+ libavformat/mpegts.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
+index 9f85aed..25007a6 100644
+--- a/libavformat/mpegts.c
++++ b/libavformat/mpegts.c
+@@ -88,6 +88,7 @@ struct MpegTSFilter {
+     int es_id;
+     int last_cc; /* last cc code (-1 if first packet) */
+     int64_t last_pcr;
++    int last_version; /* last version of data on this pid */
+     enum MpegTSFilterType type;
+     union {
+         MpegTSPESFilter pes_filter;
+@@ -450,6 +451,7 @@ static MpegTSFilter *mpegts_open_filter(MpegTSContext *ts, unsigned int pid,
+     filter->es_id   = -1;
+     filter->last_cc = -1;
+     filter->last_pcr= -1;
++    filter->last_version = -1;
+ 
+     return filter;
+ }
+@@ -1972,6 +1974,10 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
+         return;
+     if (!h->current)
+         return;
++    if (h->version == filter->last_version)
++        return;
++    filter->last_version = h->version;
++    av_dlog(ts->stream, "version=%d\n", filter->last_version);
+ 
+     ts->stream->ts_id = h->id;
+ 
+
+From fdd8caea6535434a877587f5325e914ba50ed17f Mon Sep 17 00:00:00 2001
+From: Cory Fields <theuni-nospam-@xbmc.org>
+Date: Fri, 9 Jul 2010 16:43:31 -0400
+Subject: [PATCH 07/13] Read PID timestamps as well as PCR timestamps to find
+ location in mpegts stream
+
+---
+ libavformat/mpegts.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 46 insertions(+), 2 deletions(-)
+
+diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
+index 25007a6..d5a8a45 100644
+--- a/libavformat/mpegts.c
++++ b/libavformat/mpegts.c
+@@ -2459,6 +2459,44 @@ static void seek_back(AVFormatContext *s, AVIOContext *pb, int64_t pos) {
+         av_log(s, pb->seekable ? AV_LOG_ERROR : AV_LOG_INFO, "Unable to seek back to the start\n");
+ }
+ 
++static int parse_timestamp(int64_t *ts, const uint8_t *buf)
++{
++    int afc, flags;
++    const uint8_t *p;
++
++    if(!(buf[1] & 0x40)) /* must be a start packet */
++        return -1;
++
++    afc = (buf[3] >> 4) & 3;
++    p = buf + 4;
++    if (afc == 0 || afc == 2) /* invalid or only adaption field */
++        return -1;
++    if (afc == 3)
++        p += p[0] + 1;
++    if (p >= buf + TS_PACKET_SIZE)
++        return -1;
++
++    if (p[0] != 0x00 || p[1] != 0x00 || p[2] != 0x01)  /* packet_start_code_prefix */
++        return -1;
++
++    flags = p[3] | 0x100; /* stream type */
++    if (!((flags >= 0x1c0 && flags <= 0x1df) ||
++          (flags >= 0x1e0 && flags <= 0x1ef) ||
++          (flags == 0x1bd) || (flags == 0x1fd)))
++        return -1;
++
++    flags = p[7];
++    if ((flags & 0xc0) == 0x80) {
++        *ts = ff_parse_pes_pts(p+9);
++        return 0;
++    } else if ((flags & 0xc0) == 0xc0) {
++        *ts = ff_parse_pes_pts(p+9+5);
++        return 0;
++    }
++    return -1;
++}
++
++
+ static int mpegts_read_header(AVFormatContext *s)
+ {
+     MpegTSContext *ts = s->priv_data;
+@@ -2658,6 +2696,7 @@ static av_unused int64_t mpegts_get_pcr(AVFormatContext *s, int stream_index,
+     uint8_t buf[TS_PACKET_SIZE];
+     int pcr_l, pcr_pid =
+         ((PESContext *)s->streams[stream_index]->priv_data)->pcr_pid;
++    int pid = ((PESContext*)s->streams[stream_index]->priv_data)->pid;
+     int pos47 = ts->pos47_full % ts->raw_packet_size;
+     pos =
+         ((*ppos + ts->raw_packet_size - 1 - pos47) / ts->raw_packet_size) *
+@@ -2679,6 +2718,11 @@ static av_unused int64_t mpegts_get_pcr(AVFormatContext *s, int stream_index,
+             *ppos = pos;
+             return timestamp;
+         }
++        if ((pid < 0 || (AV_RB16(buf + 1) & 0x1fff) == pid) &&
++            parse_timestamp(&timestamp, buf) == 0) {
++            *ppos = pos;
++            return timestamp;
++        }
+         pos += ts->raw_packet_size;
+     }
+ 
+@@ -2778,7 +2822,7 @@ AVInputFormat ff_mpegts_demuxer = {
+     .read_header    = mpegts_read_header,
+     .read_packet    = mpegts_read_packet,
+     .read_close     = mpegts_read_close,
+-    .read_timestamp = mpegts_get_dts,
++    .read_timestamp = mpegts_get_pcr,
+     .flags          = AVFMT_SHOW_IDS | AVFMT_TS_DISCONT,
+     .priv_class     = &mpegts_class,
+ };
+@@ -2790,7 +2834,7 @@ AVInputFormat ff_mpegtsraw_demuxer = {
+     .read_header    = mpegts_read_header,
+     .read_packet    = mpegts_raw_read_packet,
+     .read_close     = mpegts_read_close,
+-    .read_timestamp = mpegts_get_dts,
++    .read_timestamp = mpegts_get_pcr,
+     .flags          = AVFMT_SHOW_IDS | AVFMT_TS_DISCONT,
+     .priv_class     = &mpegtsraw_class,
+ };
+
+From c57e5b8154f5fe1457f4c64e04885a2cdfb37f51 Mon Sep 17 00:00:00 2001
+From: Joakim Plate <elupus@ecce.se>
+Date: Sat, 22 Oct 2011 19:01:38 +0200
+Subject: [PATCH 08/13] Get stream durations using read_timestamp
+
+---
+ libavformat/utils.c | 39 +++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 39 insertions(+)
+
+diff --git a/libavformat/utils.c b/libavformat/utils.c
+index 3e8af50..f4fb172 100644
+--- a/libavformat/utils.c
++++ b/libavformat/utils.c
+@@ -2356,6 +2356,41 @@ static void estimate_timings_from_bit_rate(AVFormatContext *ic)
+ #define DURATION_MAX_READ_SIZE 250000LL
+ #define DURATION_MAX_RETRY 4
+ 
++static void av_estimate_timings_from_pts2(AVFormatContext *ic, int64_t old_offset)
++{
++    AVStream *st;
++    int i, step= 1024;
++    int64_t ts, pos;
++
++    for(i=0;i<ic->nb_streams;i++) {
++        st = ic->streams[i];
++
++        pos = 0;
++        ts = ic->iformat->read_timestamp(ic, i, &pos, DURATION_MAX_READ_SIZE);
++        if (ts == AV_NOPTS_VALUE)
++            continue;
++        if (st->start_time > ts || st->start_time == AV_NOPTS_VALUE)
++            st->start_time = ts;
++
++        pos = avio_size(ic->pb) - 1;
++        do {
++            pos -= step;
++            ts = ic->iformat->read_timestamp(ic, i, &pos, pos + step);
++            step += step;
++        } while (ts == AV_NOPTS_VALUE && pos >= step && step < DURATION_MAX_READ_SIZE);
++
++        if (ts == AV_NOPTS_VALUE)
++            continue;
++
++        if (st->duration < ts - st->start_time || st->duration == AV_NOPTS_VALUE)
++            st->duration = ts - st->start_time;
++    }
++
++    fill_all_stream_timings(ic);
++
++    avio_seek(ic->pb, old_offset, SEEK_SET);
++}
++
+ /* only usable for MPEG-PS streams */
+ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
+ {
+@@ -2506,6 +2541,10 @@ static void estimate_timings(AVFormatContext *ic, int64_t old_offset)
+          * the components */
+         fill_all_stream_timings(ic);
+         ic->duration_estimation_method = AVFMT_DURATION_FROM_STREAM;
++    } else if (ic->iformat->read_timestamp && 
++        file_size && ic->pb->seekable) {
++        /* get accurate estimate from the PTSes */
++        av_estimate_timings_from_pts2(ic, old_offset);
+     } else {
+         /* less precise: use bitrate info */
+         estimate_timings_from_bit_rate(ic);
+
+From 4bcec3ef0042244b0ade00d132368d0872f73c72 Mon Sep 17 00:00:00 2001
+From: Joakim Plate <elupus@ecce.se>
+Date: Wed, 8 Dec 2010 14:03:43 +0000
+Subject: [PATCH 09/13] changed: allow 4 second skew between streams in mov
+ before attempting to seek
+
+---
+ libavformat/mov.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/libavformat/mov.c b/libavformat/mov.c
+index 8d66c0a..127ffd9 100644
+--- a/libavformat/mov.c
++++ b/libavformat/mov.c
+@@ -4028,8 +4028,8 @@ static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st)
+             if (!sample || (!s->pb->seekable && current_sample->pos < sample->pos) ||
+                 (s->pb->seekable &&
+                  ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb &&
+-                 ((FFABS(best_dts - dts) <= AV_TIME_BASE && current_sample->pos < sample->pos) ||
+-                  (FFABS(best_dts - dts) > AV_TIME_BASE && dts < best_dts)))))) {
++                 ((FFABS(best_dts - dts) <= 4*AV_TIME_BASE && current_sample->pos < sample->pos) ||
++                  (FFABS(best_dts - dts) > 4*AV_TIME_BASE && dts < best_dts)))))) {
+                 sample = current_sample;
+                 best_dts = dts;
+                 *st = avst;
+
+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
+---
+ 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
+@@ -832,6 +832,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;
+@@ -2649,6 +2653,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);
+
+From c315a758a292200c22925603682e259849d6d558 Mon Sep 17 00:00:00 2001
+From: Joakim Plate <elupus@ecce.se>
+Date: Mon, 28 Jun 2010 21:26:54 +0000
+Subject: [PATCH 11/13] Speed up mpegts av_find_stream_info
+
+---
+ libavformat/mpegts.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
+index e070f1f..dd9e129 100644
+--- a/libavformat/mpegts.c
++++ b/libavformat/mpegts.c
+@@ -994,7 +994,7 @@ static int mpegts_push_data(MpegTSFilter *filter,
+                         goto skip;
+ 
+                     /* stream not present in PMT */
+-                    if (!pes->st) {
++                    if (ts->auto_guess && !pes->st) {
+                         if (ts->skip_changes)
+                             goto skip;
+ 
+
+From 939ebbbc46ca9995637415594f1815633587104f Mon Sep 17 00:00:00 2001
+From: marc <mhocking@ubuntu-desktop.(none)>
+Date: Mon, 18 Feb 2013 17:18:18 +0000
+Subject: [PATCH 12/13] dxva-h264 Fix dxva playback of streams that don't start
+ with an I-Frame.
+
+---
+ libavcodec/dxva2_h264.c | 8 ++++++++
+ libavcodec/h264.c       | 1 +
+ libavcodec/h264.h       | 2 ++
+ libavcodec/h264_slice.c | 1 +
+ 4 files changed, 12 insertions(+)
+
+diff --git a/libavcodec/dxva2_h264.c b/libavcodec/dxva2_h264.c
+index 6deccc3..85b25fd 100644
+--- a/libavcodec/dxva2_h264.c
++++ b/libavcodec/dxva2_h264.c
+@@ -451,6 +451,14 @@ static int dxva2_h264_end_frame(AVCodecContext *avctx)
+ 
+     if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0)
+         return -1;
++
++    // Wait for an I-frame before start decoding. Workaround for ATI UVD and UVD+ GPUs
++    if (!h->got_first_iframe) {
++        if (!(ctx_pic->pp.wBitFields & (1 << 15)))
++            return -1;
++        h->got_first_iframe = 1;
++    }
++
+     ret = ff_dxva2_common_end_frame(avctx, &h->cur_pic_ptr->f,
+                                     &ctx_pic->pp, sizeof(ctx_pic->pp),
+                                     &ctx_pic->qm, sizeof(ctx_pic->qm),
+diff --git a/libavcodec/h264.c b/libavcodec/h264.c
+index 222bf58..ea2ec17 100644
+--- a/libavcodec/h264.c
++++ b/libavcodec/h264.c
+@@ -1085,6 +1085,7 @@ void ff_h264_flush_change(H264Context *h)
+     h->list_count = 0;
+     h->current_slice = 0;
+     h->mmco_reset = 1;
++    h->got_first_iframe = 0;
+ }
+ 
+ /* forget old pics after a seek */
+diff --git a/libavcodec/h264.h b/libavcodec/h264.h
+index b94f06b..bc9458b 100644
+--- a/libavcodec/h264.h
++++ b/libavcodec/h264.h
+@@ -741,6 +741,8 @@ typedef struct H264Context {
+     int luma_weight_flag[2];    ///< 7.4.3.2 luma_weight_lX_flag
+     int chroma_weight_flag[2];  ///< 7.4.3.2 chroma_weight_lX_flag
+ 
++    int got_first_iframe;
++
+     // Timestamp stuff
+     int sei_buffering_period_present;   ///< Buffering period SEI flag
+     int initial_cpb_removal_delay[32];  ///< Initial timestamps for CPBs
+diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
+index 53f61ca..b171d78 100644
+--- a/libavcodec/h264_slice.c
++++ b/libavcodec/h264_slice.c
+@@ -1189,6 +1189,7 @@ static int h264_slice_header_init(H264Context *h, int reinit)
+         ff_h264_free_tables(h, 0);
+     h->first_field           = 0;
+     h->prev_interlaced_frame = 1;
++    h->got_first_iframe = 0;
+ 
+     init_scan_tables(h);
+     ret = ff_h264_alloc_tables(h);
+
+From 7d7ce18ff0d24b586634fa6e631fa0eec7865aae Mon Sep 17 00:00:00 2001
+From: elupus <elupus@xbmc.org>
+Date: Tue, 1 Nov 2011 20:18:35 +0100
+Subject: [PATCH 13/13] add public version of ff_read_frame_flush
+
+We need this since we sometimes seek on the
+input stream behind ffmpeg's back. After this
+all data need to be flushed completely.
+---
+ libavformat/avformat.h | 5 +++++
+ libavformat/utils.c    | 5 +++++
+ 2 files changed, 10 insertions(+)
+
+diff --git a/libavformat/avformat.h b/libavformat/avformat.h
+index 2e54ed1..3a9f292 100644
+--- a/libavformat/avformat.h
++++ b/libavformat/avformat.h
+@@ -2121,6 +2121,11 @@ int av_find_best_stream(AVFormatContext *ic,
+ int av_read_frame(AVFormatContext *s, AVPacket *pkt);
+ 
+ /**
++ * Clear out any buffered data in context
++ */
++void av_read_frame_flush(AVFormatContext *s);
++
++/**
+  * Seek to the keyframe at timestamp.
+  * 'timestamp' in 'stream_index'.
+  *
+diff --git a/libavformat/utils.c b/libavformat/utils.c
+index f4fb172..10dda18 100644
+--- a/libavformat/utils.c
++++ b/libavformat/utils.c
+@@ -1624,6 +1624,11 @@ void ff_read_frame_flush(AVFormatContext *s)
+     }
+ }
+ 
++void av_read_frame_flush(AVFormatContext *s)
++{
++  ff_read_frame_flush(s);
++}
++
+ void ff_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp)
+ {
+     int i;