diff --git a/configure b/configure
index faea887..f933fd8 100755
--- a/configure
+++ b/configure
@@ -232,6 +232,7 @@ External library support:
                            native MPEG-4/Xvid encoder exists [no]
   --enable-openal          enable OpenAL 1.1 capture support [no]
   --enable-openssl         enable openssl [no]
+  --enable-teletext-zvbi   enable teletext support via libzvbi [no]
   --enable-zlib            enable zlib [autodetect]
 
 Advanced options (experts only):
@@ -1206,6 +1207,7 @@ CONFIG_LIST="
     sram
     static
     swscale_alpha
+    teletext_zvbi
     thumb
     vaapi
     vda
@@ -1775,6 +1777,7 @@ zlib_decoder_select="zlib"
 zlib_encoder_select="zlib"
 zmbv_decoder_select="zlib"
 zmbv_encoder_select="zlib"
+#teletext_decoder_select="teletext_zvbi"
 
 # hardware accelerators
 crystalhd_deps="libcrystalhd_libcrystalhd_if_h"
@@ -1858,6 +1861,7 @@ libxavs_encoder_deps="libxavs"
 libxvid_encoder_deps="libxvid"
 libutvideo_decoder_deps="libutvideo"
 libutvideo_encoder_deps="libutvideo"
+teletext_decoder_deps="teletext_zvbi"
 
 # demuxers / muxers
 ac3_demuxer_select="ac3_parser"
@@ -3872,6 +3876,7 @@ enabled openssl    && { check_lib openssl/ssl.h SSL_library_init -lssl -lcrypto
                         check_lib openssl/ssl.h SSL_library_init -lssl32 -leay32 ||
                         check_lib openssl/ssl.h SSL_library_init -lssl -lcrypto -lws2_32 -lgdi32 ||
                         die "ERROR: openssl not found"; }
+enabled teletext_zvbi && require libzvbi libzvbi.h vbi_decoder_new -lzvbi
 
 if enabled gnutls; then
     { check_lib nettle/bignum.h nettle_mpz_get_str_256 -lnettle -lhogweed -lgmp && enable nettle; } ||
@@ -4273,6 +4278,7 @@ echo "libxavs enabled           ${libxavs-no}"
 echo "libxvid enabled           ${libxvid-no}"
 echo "openal enabled            ${openal-no}"
 echo "openssl enabled           ${openssl-no}"
+echo "teletext_zvbi enabled     ${teletext_zvbi-no}"
 echo "zlib enabled              ${zlib-no}"
 echo "bzlib enabled             ${bzlib-no}"
 echo "texi2html enabled         ${texi2html-no}"
diff --git a/ffmpeg.c b/ffmpeg.c
index 977218f..5b05549 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -117,6 +117,9 @@ static int64_t video_size = 0;
 static int64_t audio_size = 0;
 static int64_t subtitle_size = 0;
 static int64_t extra_size = 0;
+static int64_t video_iframe_count = 0;
+static int64_t video_iframe_last;
+static int64_t video_iframe_delta_sum = 0;
 static int nb_frames_dup = 0;
 static int nb_frames_drop = 0;
 
@@ -145,6 +148,9 @@ int         nb_output_files   = 0;
 FilterGraph **filtergraphs;
 int        nb_filtergraphs;
 
+static double vdelta_sum;
+static long   vdelta_n;
+
 #if HAVE_TERMIOS_H
 
 /* init terminal so that we can grab keys */
@@ -573,6 +579,15 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost)
     }
 
     pkt->stream_index = ost->index;
+    if (avctx->codec_type == AVMEDIA_TYPE_VIDEO &&
+	pkt->flags & AV_PKT_FLAG_KEY && pkt->pts != AV_NOPTS_VALUE) {
+	int64_t pts = av_rescale_q(pkt->pts,
+				   s->streams[pkt->stream_index]->time_base,
+				   AV_TIME_BASE_Q);
+	if (video_iframe_count++ > 0)
+	    video_iframe_delta_sum += pts - video_iframe_last;
+	video_iframe_last = pts;
+    }
 
     if (debug_ts) {
         av_log(NULL, AV_LOG_INFO, "muxer <- type:%s "
@@ -796,6 +811,8 @@ static void do_video_out(AVFormatContext *s,
 
     sync_ipts = in_picture->pts;
     delta = sync_ipts - ost->sync_opts + duration;
+    vdelta_sum += delta;
+    ++vdelta_n;
 
     /* by default, we output a single frame */
     nb_frames = 1;
@@ -1245,6 +1262,10 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti
         if(video_size + audio_size + subtitle_size + extra_size == 0){
             av_log(NULL, AV_LOG_WARNING, "Output file is empty, nothing was encoded (check -ss / -t / -frames parameters if used)\n");
         }
+        if (vdelta_n > 0)
+            av_log(NULL, AV_LOG_VERBOSE, "vdelta_avg:%f\n", vdelta_sum/(double)vdelta_n);
+        if (video_iframe_count > 0)
+            av_log(NULL, AV_LOG_VERBOSE, "iframes_delta_avg:%f sec\n", (double)video_iframe_delta_sum/(video_iframe_count*AV_TIME_BASE));
     }
 }
 
@@ -1353,8 +1374,16 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p
     av_init_packet(&opkt);
 
     if ((!ost->frame_number && !(pkt->flags & AV_PKT_FLAG_KEY)) &&
-        !ost->copy_initial_nonkeyframes)
+        !ost->copy_initial_nonkeyframes) {
+	int64_t d = ist->next_pts - of->start_time;
+	fprintf(stderr, "ist:%d dropping non-keyframe %"PRId64"\n",
+		ist->st->index, d);
+	av_interleaved_discard(of->ctx, d);
+	// input context start_time is effectively increased by d
+	if (!copy_ts)
+	    input_files[ist->file_index]->ts_offset -= d;
         return;
+    }
 
     if (!ost->frame_number && ist->pts < of->start_time &&
         !ost->copy_prior_start)
@@ -2788,6 +2817,13 @@ static int process_input(int file_index)
                av_ts2timestr(input_files[ist->file_index]->ts_offset, &AV_TIME_BASE_Q));
     }
 
+    // Teletext streams are often shared between programs
+    // and their absolute timestamps are meaningless
+    if (ist->st->codec->codec_id == CODEC_ID_DVB_TELETEXT && !copy_ts) {
+        pkt.dts = pkt.pts = av_rescale_q(av_get_cur_dts(is, -1), AV_TIME_BASE_Q, ist->st->time_base);
+        //fprintf(stderr, "teletext %d ts set to %f -> %"PRId64"\n", ist_index, ipts_min, pkt.dts/90);
+    }
+
     if(!ist->wrap_correction_done && is->start_time != AV_NOPTS_VALUE && ist->st->pts_wrap_bits < 64){
         int64_t stime, stime2;
         // Correcting starttime based on the enabled streams
@@ -2844,8 +2880,8 @@ static int process_input(int file_index)
             pkt_dts+1<ist->pts){
             ifile->ts_offset -= delta;
             av_log(NULL, AV_LOG_DEBUG,
-                   "timestamp discontinuity %"PRId64", new offset= %"PRId64"\n",
-                   delta, ifile->ts_offset);
+                   "ist_index:%d timestamp discontinuity %"PRId64", new offset= %"PRId64"\n",
+                   ifile->ist_index + pkt.stream_index, delta, ifile->ts_offset);
             pkt.dts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base);
             if (pkt.pts != AV_NOPTS_VALUE)
                 pkt.pts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base);
diff --git a/ffmpeg_opt.c b/ffmpeg_opt.c
index fcd6048..e2b63da 100644
--- a/ffmpeg_opt.c
+++ b/ffmpeg_opt.c
@@ -628,6 +628,9 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
         case AVMEDIA_TYPE_SUBTITLE:
             if(!ist->dec)
                 ist->dec = avcodec_find_decoder(dec->codec_id);
+	    if (dec->codec_id == CODEC_ID_DVB_SUBTITLE ||
+		dec->codec_id == CODEC_ID_DVB_TELETEXT)
+		ist->fix_sub_duration = 1;
             MATCH_PER_STREAM_OPT(fix_sub_duration, i, ist->fix_sub_duration, ic, st);
             break;
         case AVMEDIA_TYPE_ATTACHMENT:
@@ -810,6 +813,20 @@ static int open_input_file(OptionsContext *o, const char *filename)
             av_log(NULL, AV_LOG_WARNING, "%s: could not seek to position %0.3f\n",
                    filename, (double)timestamp / AV_TIME_BASE);
         }
+	if (av_get_cur_dts(ic, -1) != AV_NOPTS_VALUE) {
+	    av_log(NULL, AV_LOG_INFO, "*** seek timestamp=%"PRId64"\n", timestamp);
+	    timestamp = av_get_cur_dts(ic, -1);
+	    av_log(NULL, AV_LOG_INFO, "*** after seek timestamp=%"PRId64"\n", timestamp);
+	}
+	/* reload stream parameters */
+	if (ic->nb_streams > orig_nb_streams)
+	    opts = grow_array(opts, sizeof *opts, &orig_nb_streams, ic->nb_streams);
+	ret = avformat_find_stream_info(ic, opts);
+	if (ret < 0) {
+	    av_log(NULL, AV_LOG_FATAL, "%s: could not find codec parameters\n", filename);
+	    avformat_close_input(&ic);
+	    exit(1);
+	}
     }
 
     /* update the current parameters so that they match the one of the input stream */
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 27c9a11..9bd17d9 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -702,6 +702,7 @@ OBJS-$(CONFIG_LIBVPX_ENCODER)             += libvpxenc.o
 OBJS-$(CONFIG_LIBX264_ENCODER)            += libx264.o
 OBJS-$(CONFIG_LIBXAVS_ENCODER)            += libxavs.o
 OBJS-$(CONFIG_LIBXVID_ENCODER)            += libxvid.o
+OBJS-$(CONFIG_TELETEXT_DECODER)           += teletextdec.o pes_parser.o
 
 # parsers
 OBJS-$(CONFIG_AAC_PARSER)              += aac_parser.o aac_ac3_parser.o \
@@ -738,6 +739,7 @@ OBJS-$(CONFIG_MPEGAUDIO_PARSER)        += mpegaudio_parser.o \
                                           mpegaudiodecheader.o mpegaudiodata.o
 OBJS-$(CONFIG_MPEGVIDEO_PARSER)        += mpegvideo_parser.o    \
                                           mpeg12.o mpeg12data.o
+OBJS-$(CONFIG_PES_PARSER)              += pes_parser.o
 OBJS-$(CONFIG_PNM_PARSER)              += pnm_parser.o pnm.o
 OBJS-$(CONFIG_RV30_PARSER)             += rv34_parser.o
 OBJS-$(CONFIG_RV40_PARSER)             += rv34_parser.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 987b877..91ccc5e 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -457,6 +457,7 @@ void avcodec_register_all(void)
     REGISTER_ENCDEC (SUBRIP,            subrip);
     REGISTER_DECODER(SUBVIEWER,         subviewer);
     REGISTER_DECODER(SUBVIEWER1,        subviewer1);
+    REGISTER_DECODER(TELETEXT,          teletext);
     REGISTER_DECODER(TEXT,              text);
     REGISTER_DECODER(VPLAYER,           vplayer);
     REGISTER_DECODER(WEBVTT,            webvtt);
@@ -518,6 +519,7 @@ void avcodec_register_all(void)
     REGISTER_PARSER(MPEG4VIDEO,         mpeg4video);
     REGISTER_PARSER(MPEGAUDIO,          mpegaudio);
     REGISTER_PARSER(MPEGVIDEO,          mpegvideo);
+    REGISTER_PARSER(PES,                pes);
     REGISTER_PARSER(PNG,                png);
     REGISTER_PARSER(PNM,                pnm);
     REGISTER_PARSER(RV30,               rv30);
diff --git a/libavcodec/dvbsub_parser.c b/libavcodec/dvbsub_parser.c
index 5274fd6..478e897 100644
--- a/libavcodec/dvbsub_parser.c
+++ b/libavcodec/dvbsub_parser.c
@@ -30,7 +30,7 @@
 /* parser definition */
 typedef struct DVBSubParseContext {
     uint8_t *packet_buf;
-    int packet_start;
+    int cursor;
     int packet_index;
     int in_packet;
 } DVBSubParseContext;
@@ -49,8 +49,7 @@ static int dvbsub_parse(AVCodecParserContext *s,
                         const uint8_t *buf, int buf_size)
 {
     DVBSubParseContext *pc = s->priv_data;
-    uint8_t *p, *p_end;
-    int i, len, buf_pos = 0;
+    int i;
 
     av_dlog(avctx, "DVB parse packet pts=%"PRIx64", lpts=%"PRIx64", cpts=%"PRIx64":\n",
             s->pts, s->last_pts, s->cur_frame_pts[s->cur_frame_start_index]);
@@ -68,100 +67,54 @@ static int dvbsub_parse(AVCodecParserContext *s,
     *poutbuf = NULL;
     *poutbuf_size = 0;
 
-    s->fetch_timestamp = 1;
-
-    if (s->last_pts != s->pts && s->pts != AV_NOPTS_VALUE) /* Start of a new packet */
-    {
-        if (pc->packet_index != pc->packet_start)
-        {
-            av_dlog(avctx, "Discarding %d bytes\n",
-                    pc->packet_index - pc->packet_start);
-        }
-
-        pc->packet_start = 0;
-        pc->packet_index = 0;
-
+    if (!pc->in_packet) {
         if (buf_size < 2 || buf[0] != 0x20 || buf[1] != 0x00) {
             av_dlog(avctx, "Bad packet header\n");
-            return -1;
+            return buf_size; /* discard data */
         }
-
-        buf_pos = 2;
-
+        if (buf_size-2 > PARSE_BUF_SIZE)
+            return -1;
+        memcpy(pc->packet_buf, buf+2, buf_size-2);
+        pc->cursor = 0;
+        pc->packet_index = buf_size-2;
         pc->in_packet = 1;
     } else {
-        if (pc->packet_start != 0)
-        {
-            if (pc->packet_index != pc->packet_start)
-            {
-                memmove(pc->packet_buf, pc->packet_buf + pc->packet_start,
-                            pc->packet_index - pc->packet_start);
-
-                pc->packet_index -= pc->packet_start;
-                pc->packet_start = 0;
-            } else {
-                pc->packet_start = 0;
-                pc->packet_index = 0;
-            }
-        }
+        if (buf_size + pc->packet_index > PARSE_BUF_SIZE)
+            return -1;
+        memcpy(pc->packet_buf + pc->packet_index, buf, buf_size);
+        pc->packet_index += buf_size;
     }
 
-    if (buf_size - buf_pos + pc->packet_index > PARSE_BUF_SIZE)
-        return -1;
-
-/* if not currently in a packet, discard data */
-    if (pc->in_packet == 0)
-        return buf_size;
-
-    memcpy(pc->packet_buf + pc->packet_index, buf + buf_pos, buf_size - buf_pos);
-    pc->packet_index += buf_size - buf_pos;
-
-    p = pc->packet_buf;
-    p_end = pc->packet_buf + pc->packet_index;
-
-    while (p < p_end)
-    {
-        if (*p == 0x0f)
-        {
-            if (p + 6 <= p_end)
-            {
-                len = AV_RB16(p + 4);
+    /* parse newly obtained segments */
+    while (pc->cursor < pc->packet_index) {
+        if (pc->packet_buf[pc->cursor] == 0x0f) {
+            if (pc->cursor + 6 <= pc->packet_index) {
+                int len = AV_RB16(pc->packet_buf + pc->cursor + 4);
 
-                if (p + len + 6 <= p_end)
-                {
-                    *poutbuf_size += len + 6;
-
-                    p += len + 6;
+                if (pc->cursor + len + 6 <= pc->packet_index) {
+                    pc->cursor += len + 6;
                 } else
                     break;
             } else
                 break;
-        } else if (*p == 0xff) {
-            if (p + 1 < p_end)
-            {
+        } else if (pc->packet_buf[pc->cursor] == 0xff) {
+            if (pc->cursor + 1 < pc->packet_index) {
                 av_dlog(avctx, "Junk at end of packet\n");
             }
-            pc->packet_index = p - pc->packet_buf;
+            *poutbuf = pc->packet_buf;
+            *poutbuf_size = pc->cursor;
+            pc->packet_index = 0;
             pc->in_packet = 0;
+            av_dlog(avctx, "parse packet sz:%d\n", *poutbuf_size);
             break;
         } else {
             av_log(avctx, AV_LOG_ERROR, "Junk in packet\n");
 
-            pc->packet_index = p - pc->packet_buf;
             pc->in_packet = 0;
             break;
         }
     }
 
-    if (*poutbuf_size > 0)
-    {
-        *poutbuf = pc->packet_buf;
-        pc->packet_start = *poutbuf_size;
-    }
-
-    if (s->pts == AV_NOPTS_VALUE)
-        s->pts = s->last_pts;
-
     return buf_size;
 }
 
diff --git a/libavcodec/pes_parser.c b/libavcodec/pes_parser.c
new file mode 100644
index 0000000..074b3ad
--- /dev/null
+++ b/libavcodec/pes_parser.c
@@ -0,0 +1,95 @@
+/*
+ * PES parsing for ffmpeg
+ * Copyright (c) 2008, 2011 Wolfram Gloger.
+ *
+ * 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
+ */
+#include "avcodec.h"
+#include "get_bits.h"
+
+/* parser definition */
+typedef struct PESParseContext {
+    uint8_t *packet;
+    int packet_len;
+    int packet_index;
+} PESParseContext;
+
+static int pes_parse_init(AVCodecParserContext *s)
+{
+    return 0;
+}
+
+static int pes_parse(AVCodecParserContext *s,
+                     AVCodecContext *avctx,
+                     const uint8_t **poutbuf, int *poutbuf_size,
+                     const uint8_t *buf, int buf_size)
+{
+    int old_len;
+    PESParseContext *pc = s->priv_data;
+
+    if (pc->packet_index == 0) {
+        if (buf_size < 6 || buf[0]!=0x00 || buf[1]!=0x00 || buf[2]!=0x01) {
+            av_log(avctx, AV_LOG_DEBUG, "PES wrong header\n");
+            *poutbuf = NULL;
+            *poutbuf_size = 0;
+            return buf_size;
+        }
+        old_len = pc->packet_len;
+        pc->packet_len = AV_RB16(buf + 4);
+        if (pc->packet_len == 0) /* unbounded */
+            pc->packet_len = buf_size;
+        else
+            pc->packet_len += 6;
+        //av_log(avctx, AV_LOG_DEBUG, "PES len:%d\n", pc->packet_len);
+        if (pc->packet_len > old_len) {
+            av_freep(&pc->packet);
+            pc->packet = av_malloc(pc->packet_len);
+        }
+    }
+    if (pc->packet) {
+        if (pc->packet_index + buf_size <= pc->packet_len) {
+            memcpy(pc->packet + pc->packet_index, buf, buf_size);
+            pc->packet_index += buf_size;
+            if (pc->packet_index >= pc->packet_len) {
+                *poutbuf = pc->packet;
+                *poutbuf_size = pc->packet_len;
+                pc->packet_index = 0;
+                return buf_size;
+            }
+        } else {
+            /* erroneous size */
+            pc->packet_index = 0;
+        }
+    }
+    *poutbuf = NULL;
+    *poutbuf_size = 0;
+    return buf_size;
+}
+
+static void pes_parse_close(AVCodecParserContext *s)
+{
+    PESParseContext *pc = s->priv_data;
+    av_freep(&pc->packet);
+}
+
+AVCodecParser ff_pes_parser = {
+    { CODEC_ID_DVB_TELETEXT },
+    sizeof(PESParseContext),
+    pes_parse_init,
+    pes_parse,
+    pes_parse_close,
+};
diff --git a/libavcodec/srtenc.c b/libavcodec/srtenc.c
index 3036a7f..33e9d8d 100644
--- a/libavcodec/srtenc.c
+++ b/libavcodec/srtenc.c
@@ -137,6 +137,8 @@ static av_cold int srt_encode_init(AVCodecContext *avctx)
 {
     SRTContext *s = avctx->priv_data;
     s->avctx = avctx;
+    if (!avctx->subtitle_header)
+        return 0;
     s->ass_ctx = ff_ass_split(avctx->subtitle_header);
     return s->ass_ctx ? 0 : AVERROR_INVALIDDATA;
 }
@@ -225,6 +227,21 @@ static void srt_end_cb(void *priv)
         srt_print(priv, "\r\n\r\n");
 }
 
+static void srt_print_timing(SRTContext *s, int sc, int ec)
+{
+    int sh, sm, ss;
+    int eh, em, es;
+
+    sh = sc/3600000;  sc -= 3600000*sh;
+    sm = sc/  60000;  sc -=   60000*sm;
+    ss = sc/   1000;  sc -=    1000*ss;
+    eh = ec/3600000;  ec -= 3600000*eh;
+    em = ec/  60000;  ec -=   60000*em;
+    es = ec/   1000;  ec -=    1000*es;
+    srt_print(s,"%d\r\n%02d:%02d:%02d,%03d --> %02d:%02d:%02d,%03d\r\n",
+              ++s->count, sh, sm, ss, sc, eh, em, es, ec);
+}
+
 static const ASSCodesCallbacks srt_callbacks = {
     .text             = srt_text_cb,
     .new_line         = srt_new_line_cb,
@@ -250,31 +267,39 @@ static int srt_encode_frame(AVCodecContext *avctx,
 
     for (i=0; i<sub->num_rects; i++) {
 
-        if (sub->rects[i]->type != SUBTITLE_ASS) {
-            av_log(avctx, AV_LOG_ERROR, "Only SUBTITLE_ASS type supported.\n");
-            return AVERROR(ENOSYS);
-        }
+        switch (sub->rects[i]->type) {
+        case SUBTITLE_TEXT: {
+            int sc0 = av_rescale(sub->pts, 1000, AV_TIME_BASE);
 
+            if (avctx->codec->id == CODEC_ID_SRT)
+                srt_print_timing(s,
+                                 sc0 + sub->start_display_time,
+                                 sc0 + sub->end_display_time);
+            srt_print(s, sub->rects[i]->text);
+            break;
+        }
+        case SUBTITLE_ASS:
+            if (!s->ass_ctx) {
+                av_log(avctx, AV_LOG_ERROR, "Got SUBTITLE_ASS but no header.\n");
+                return AVERROR_INVALIDDATA;
+            }
         dialog = ff_ass_split_dialog(s->ass_ctx, sub->rects[i]->ass, 0, &num);
         for (; dialog && num--; dialog++) {
             if (avctx->codec->id == AV_CODEC_ID_SRT) {
-                int sh, sm, ss, sc = 10 * dialog->start;
-                int eh, em, es, ec = 10 * dialog->end;
-                sh = sc/3600000;  sc -= 3600000*sh;
-                sm = sc/  60000;  sc -=   60000*sm;
-                ss = sc/   1000;  sc -=    1000*ss;
-                eh = ec/3600000;  ec -= 3600000*eh;
-                em = ec/  60000;  ec -=   60000*em;
-                es = ec/   1000;  ec -=    1000*es;
-                srt_print(s,"%d\r\n%02d:%02d:%02d,%03d --> %02d:%02d:%02d,%03d\r\n",
-                          ++s->count, sh, sm, ss, sc, eh, em, es, ec);
+                srt_print_timing(s, 10 * dialog->start, 10 * dialog->end);
                 s->dialog_start = s->ptr - 2;
             }
             s->alignment_applied = 0;
             srt_style_apply(s, dialog->style);
             ff_ass_split_override_codes(&srt_callbacks, s, dialog->text);
         }
-    }
+        break;
+        default:
+            av_log(avctx, AV_LOG_ERROR, "Only SUBTITLE_TEXT, SUBTITLE_ASS types supported.\n");
+            return AVERROR(ENOSYS);
+        }
+
+     }
 
     if (s->ptr == s->buffer)
         return 0;
diff --git a/libavcodec/teletextdec.c b/libavcodec/teletextdec.c
new file mode 100644
index 0000000..a415a1d
--- /dev/null
+++ b/libavcodec/teletextdec.c
@@ -0,0 +1,423 @@
+/*
+ * Teletext decoding for ffmpeg
+ * Copyright (c) 2005-2010, 2012 Wolfram Gloger.
+ *
+ * This library 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 of the License, or (at your option) any later version.
+ *
+ * This library 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 this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "avcodec.h"
+#include "libavutil/opt.h"
+
+#include <libzvbi.h>
+
+//#define DEBUG         1
+
+#define TEXT_MAXSZ    2044
+#define BINARIZE      0
+#define PALETTE_MAX   40
+#define RGBA(r,g,b,a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
+#define VBI_R(rgba)   (((rgba) >> 0) & 0xFF)
+#define VBI_G(rgba)   (((rgba) >> 8) & 0xFF)
+#define VBI_B(rgba)   (((rgba) >> 16) & 0xFF)
+#define VBI_A(rgba)   (((rgba) >> 24) & 0xFF)
+
+/* main data structure */
+typedef struct TeletextContext
+{
+    AVClass        *class;
+    char           *pgno;
+    int             y_offset;
+    int             ci_clip;
+    int             gen_bitmap;
+    int             force_chop_top;
+    int             sub_display_time; /* in msec */
+
+    int             lines_processed;
+    int             last_rows, last_cols;
+    AVSubtitleRect *sub_rect;
+
+    vbi_decoder *   vbi;
+    vbi_dvb_demux * dx;
+#ifdef DEBUG
+    vbi_export *    ex;
+#endif
+    /* Don't even _think_ about making sliced stack-local! */
+    vbi_sliced      sliced[64];
+} TeletextContext;
+
+/************************************************************************/
+
+static int
+teletext_decode_frame(AVCodecContext *avctx,
+                      void *data, int *data_size,
+                      AVPacket *pkt)
+{
+    TeletextContext *ctx = avctx->priv_data;
+    AVSubtitle      *sub = data;
+    const uint8_t   *buf = pkt->data;
+    unsigned int    left = pkt->size;
+
+    while (left > 0) {
+        int64_t pts = 0;
+        unsigned int lines = vbi_dvb_demux_cor(ctx->dx, ctx->sliced, 64, &pts, &buf, &left);
+#ifdef DEBUG
+        av_log(avctx, AV_LOG_INFO,
+               " Teletext: ctx=%p buf_size=%d left=%u lines=%u pts=%f\n",
+               ctx, pkt->size, left, lines, (double)pts/90000.0);
+#endif
+        if (lines > 0) {
+#ifdef DEBUGx
+            int i;
+            for(i=0; i<lines; ++i)
+                if (ctx->sliced[i].id >= 0)
+                    av_log(avctx, AV_LOG_INFO,
+                           " Teletext: lines=%d id=%x\n", i, ctx->sliced[i].id);
+#endif
+            vbi_decode(ctx->vbi, ctx->sliced, lines, (double)pts/90000.0);
+            ctx->lines_processed += lines;
+        }
+    }
+
+    // is there a subtitle to pass?
+    if (ctx->sub_rect) {
+        sub->format = 0;
+        sub->start_display_time = 0;
+        sub->end_display_time = ctx->sub_display_time;
+        sub->num_rects = 0;
+
+        if (ctx->sub_rect->type != SUBTITLE_NONE) {
+            sub->rects = av_malloc(sizeof(*sub->rects) * 1);
+            if (sub->rects) {
+                sub->num_rects = 1;
+                sub->rects[0] = ctx->sub_rect;
+            }
+        } else {
+            av_log(avctx, AV_LOG_DEBUG, " Teletext: sending empty sub\n");
+            sub->rects = 0;
+        }
+        if (!sub->rects) // no rect was passed
+            av_free(ctx->sub_rect);
+        ctx->sub_rect = 0;
+
+        *data_size = 1;
+    } else
+        *data_size = 0;
+
+    return pkt->size;
+}
+
+static int
+chop_spaces_utf8(const unsigned char* t, int len)
+{
+    t += len;
+    while (len > 0) {
+        if (*--t != ' ' || (len-1 > 0 && *(t-1) & 0x80))
+            break;
+        --len;
+    }
+    return len;
+}
+
+// draw a page as text
+static int
+gen_sub_text(TeletextContext *ctx, vbi_page *page, int chop_top)
+{
+    AVSubtitleRect *sub_rect = ctx->sub_rect;
+    char *text;
+    const char *in;
+    char *out;
+    char *vbi_text = av_malloc(TEXT_MAXSZ);
+    int sz = vbi_print_page_region(page, vbi_text, TEXT_MAXSZ-1, "UTF-8",
+                                   /*table mode*/ TRUE, FALSE,
+                                   0,             chop_top,
+                                   page->columns, page->rows-chop_top);
+    if (sz <= 0) {
+        av_log(0, AV_LOG_ERROR, "vbi_print error\n");
+        av_free(vbi_text);
+        return -1;
+    }
+    vbi_text[sz] = '\0';
+    in  = vbi_text;
+    out = text = av_malloc(TEXT_MAXSZ);
+    for (;;) {
+        int nl, sz;
+
+        // skip leading spaces and newlines
+        in += strspn(in, " \n");
+        // compute end of row
+        for (nl = 0; in[nl]; ++nl)
+            if (in[nl] == '\n' && (nl==0 || !(in[nl-1] & 0x80)))
+                break;
+        if (!in[nl])
+            break;
+        // skip trailing spaces
+        sz = chop_spaces_utf8(in, nl);
+        memcpy(out, in, sz);
+        out += sz;
+        *out++ = '\n';
+        in  += nl;
+    }
+    av_free(vbi_text);
+    *out = '\0';
+    if (out > text) {
+        sub_rect->type = SUBTITLE_TEXT;
+        sub_rect->text = text;
+        av_log(0, AV_LOG_DEBUG, "subtext:%s:txetbus\n", text);
+    } else {
+        sub_rect->type = SUBTITLE_NONE;
+        av_free(text);
+    }
+    return 0;
+}
+
+static int
+find_ci_in_page(const vbi_rgba *pix, const vbi_page *page)
+{
+    static int last_i = 0; // cache for performance
+
+    if (*pix == page->color_map[last_i])
+        return last_i;
+    for (last_i=0;
+         last_i<(sizeof page->color_map)/(sizeof page->color_map[0]);
+         ++last_i) {
+        if (*pix == page->color_map[last_i])
+            return last_i;
+    }
+    return -1;
+}
+
+// draw a page as bitmap
+static int
+gen_sub_bitmap(TeletextContext *ctx, vbi_page *page, int chop_top)
+{
+    AVSubtitleRect *sub_rect = ctx->sub_rect;
+    int resx = page->columns*12, resy = page->rows*10;
+    int ix, iy, ci, ci_max = 0, ci_max_count = 0;
+    const vbi_rgba* vptr;
+    uint8_t *bptr;
+    char *canvas = av_malloc(resx*resy*sizeof(vbi_rgba));
+
+    if (!canvas)
+        return -1;
+
+    /* only VBI_PIXFMT_RGBA32_LE is supported in libzvbi */
+    vbi_draw_vt_page(page, VBI_PIXFMT_RGBA32_LE, canvas,
+                     /*reveal*/ 1, /*flash*/ 1);
+
+    if (chop_top) {
+        resy -= 10;
+        av_log(0, AV_LOG_DEBUG, " Teletext: chopping top line\n");
+    }
+    //avpicture_alloc(&sub_rect->pict, PIX_FMT_PAL8, resx, resy);
+    sub_rect->pict.data[0] = av_mallocz(resx*resy);
+
+    vptr = (const vbi_rgba *)canvas + (chop_top*10*resx);
+    bptr = sub_rect->pict.data[0];
+
+    for (iy=0; iy<resy; ++iy) {
+        for (ix=0; ix<resx; ++ix, ++vptr, ++bptr) {
+            ci = find_ci_in_page(vptr, page);
+            if (ci < 0)
+                av_log(0, AV_LOG_ERROR,
+                       " Teletext: can't find pixel in LUT!\n");
+            else {
+                if (ci >= ctx->ci_clip)
+                    ci = ci % ctx->ci_clip;
+                if (ci > ci_max)
+                    ci_max = ci;
+                if (ci == ci_max)
+                    ++ci_max_count;
+                *bptr = BINARIZE ? (!!ci) : (uint8_t)ci;
+            }
+        }
+    }
+    av_free(canvas);
+
+    if (ci_max_count == resx*resy) {
+        av_log(0, AV_LOG_DEBUG, " Teletext: dropping empty page\n");
+        // send empty subtitle
+        //avpicture_free(&sub_rect->pict);
+        av_freep(&sub_rect->pict.data[0]);
+        sub_rect->type = SUBTITLE_NONE;
+    } else {
+        sub_rect->x = resx<720 ? (720 - resx)/2 : 0;
+        sub_rect->y = resy<576 ? (576 - resy) : 0;
+        if (sub_rect->y > ctx->y_offset)
+            sub_rect->y -= ctx->y_offset;
+        sub_rect->w = resx;
+        sub_rect->h = resy;
+        sub_rect->nb_colors = ci_max+1;
+        sub_rect->pict.linesize[0] = resx;
+        sub_rect->pict.data[1] = av_malloc(sub_rect->nb_colors * sizeof(uint32_t));
+        //sub_rect->rgba_palette =
+        //    av_malloc(sizeof(*sub_rect->rgba_palette)*
+        //              sub_rect->nb_colors);
+        for (ci=0; ci<sub_rect->nb_colors; ++ci) {
+            int r, g, b, a;
+
+            r = VBI_R(page->color_map[ci]);
+            g = VBI_G(page->color_map[ci]);
+            b = VBI_B(page->color_map[ci]);
+            a = (r+g+b == 0) ? 0 : VBI_A(page->color_map[ci]);
+            ((uint32_t *)sub_rect->pict.data[1])[ci] =
+                RGBA(r, g, b, a);
+#ifdef DEBUG
+            av_log(0, AV_LOG_DEBUG, " Teletext: palette %0x\n",
+                   ((uint32_t *)sub_rect->pict.data[1])[ci]);
+#endif
+        }
+        sub_rect->type = SUBTITLE_BITMAP;
+    }
+#ifdef DEBUG
+    fprintf(stderr, "ci_max=%d...\n", ci_max);
+#endif
+    return 0;
+}
+
+static void
+handler(vbi_event *ev, void *user_data)
+{
+    TeletextContext *ctx = user_data;
+    vbi_page page;
+    int res;
+    char pgno_str[12];
+
+    snprintf(pgno_str, sizeof pgno_str, "%03x", ev->ev.ttx_page.pgno);
+    av_log(0, AV_LOG_DEBUG, "Page %s.%02x %s\n",
+           pgno_str, ev->ev.ttx_page.subno & 0xFF, ctx->pgno);
+
+    if (strcmp(ctx->pgno, "*") && !strstr(ctx->pgno, pgno_str)) {
+        return;
+    }
+
+    /* Fetch the page.  */
+    res = vbi_fetch_vt_page(ctx->vbi, &page,
+                            ev->ev.ttx_page.pgno,
+                            ev->ev.ttx_page.subno,
+                            VBI_WST_LEVEL_3p5, 25, TRUE);
+
+#ifdef DEBUG
+    fprintf(stderr, "\nSaving res=%d dy0=%d dy1=%d...\n",
+            res, page.dirty.y0, page.dirty.y1);
+    fflush(stderr);
+
+    if (!vbi_export_stdio(ctx->ex, stderr, &page)) {
+        fprintf(stderr, "failed: %s\n", vbi_export_errstr(ctx->ex));
+        //exit(EXIT_FAILURE);
+    }
+#endif
+
+    // TODO: check if page changed
+    if (page.columns!=ctx->last_cols || page.rows!=ctx->last_rows || 1) {
+        vbi_subno subno;
+        char *lang;
+        vbi_page_type vpt = vbi_classify_page(ctx->vbi,
+                                              ev->ev.ttx_page.pgno,
+                                              &subno, &lang);
+        int chop_top = ctx->force_chop_top ||
+            ((page.rows > 1) && (vpt == VBI_SUBTITLE_PAGE));
+
+        av_log(0, AV_LOG_DEBUG, "%d x %d page chop:%d\n",
+               page.columns, page.rows, chop_top);
+
+        ctx->sub_rect = av_mallocz(sizeof(*ctx->sub_rect));
+        res = ctx->gen_bitmap ?
+            gen_sub_bitmap(ctx, &page, chop_top) :
+            gen_sub_text  (ctx, &page, chop_top);
+        if (res)
+            av_freep(&ctx->sub_rect);
+
+        ctx->last_cols = page.columns;
+        ctx->last_rows = page.rows;
+    }
+    vbi_unref_page(&page);
+}
+
+static int teletext_init_decoder(AVCodecContext *avctx)
+{
+    TeletextContext *ctx = avctx->priv_data;
+    const char* p_env;
+
+    ctx->sub_rect = 0;
+
+    ctx->vbi = vbi_decoder_new();
+    assert(NULL != ctx->vbi);
+    vbi_event_handler_add(ctx->vbi, VBI_EVENT_TTX_PAGE, handler, ctx);
+    ctx->dx = vbi_dvb_pes_demux_new (/* callback */ NULL, NULL);
+    assert(NULL != ctx->dx);
+#ifdef DEBUG
+    {
+        char *t;
+        ctx->ex = vbi_export_new("text", &t);
+    }
+#endif
+    av_log(avctx, AV_LOG_INFO, "teletext pgno:%s\n", ctx->pgno);
+    p_env = getenv("TELETEXT_Y_OFFSET");
+    if (p_env)
+        ctx->y_offset = strtol(p_env, 0, 10);
+    ctx->sub_display_time = 10000;
+    ctx->ci_clip = 256; /* dvdsub encoder cannot take more than 16.. */
+    return 0;
+}
+
+static int teletext_close_decoder(AVCodecContext *avctx)
+{
+    TeletextContext *ctx = avctx->priv_data;
+
+#ifdef DEBUG
+    av_log(avctx, AV_LOG_INFO,
+           " Teletext: lines_total=%u\n", ctx->lines_processed);
+#endif
+    av_free(ctx->sub_rect);
+
+    vbi_dvb_demux_delete(ctx->dx);
+    vbi_decoder_delete(ctx->vbi);
+    return 0;
+}
+
+#define OFFSET(x) offsetof(TeletextContext, x)
+#define SD AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_DECODING_PARAM
+static const AVOption options[] = {
+    {"teletext_page", "Number(s) of teletext page(s) to decode", OFFSET(pgno), AV_OPT_TYPE_STRING, {.str = "100"}, 0, 0, SD},
+    {"teletext_chop_top", "Force discarding the top teletext line", OFFSET(force_chop_top), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, SD},
+    {"teletext_bitmap", "Generate bitmap rather than text subtitles", OFFSET(gen_bitmap), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, SD},
+    {"teletext_y_offset", "y offset of generated bitmaps", OFFSET(y_offset), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1080, SD},
+    { NULL },
+};
+
+static const AVClass teletext_class = {
+    .class_name = "teletext",
+    .item_name  = av_default_item_name,
+    .option     = options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+AVCodec ff_teletext_decoder = {
+    .name      = "teletext",
+    .type      = AVMEDIA_TYPE_SUBTITLE,
+    .id        = CODEC_ID_DVB_TELETEXT,
+    .priv_data_size = sizeof(TeletextContext),
+    .init      = teletext_init_decoder,
+    .close     = teletext_close_decoder,
+    .decode    = teletext_decode_frame,
+    .long_name = NULL_IF_CONFIG_SMALL("Teletext subtitles"),
+    .priv_class= &teletext_class,
+};
+
+/* Local Variables: */
+/* indent-tabs-mode:nil */
+/* tab-width:4 */
+/* c-basic-offset:4 */
+/* End: */
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index c907d4e..fd5f504 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -1382,6 +1382,8 @@ AVFormatContext *avformat_alloc_output_context(const char *format,
                                                const char *filename);
 #endif
 
+void av_interleaved_discard(AVFormatContext *s, int64_t dts_min);
+
 /**
  * Allocate an AVFormatContext for an output format.
  * avformat_free_context() can be used to free the context and
@@ -1441,6 +1443,9 @@ AVInputFormat *av_probe_input_format2(AVProbeData *pd, int is_opened, int *score
  */
 AVInputFormat *av_probe_input_format3(AVProbeData *pd, int is_opened, int *score_ret);
 
+/* current dts in AV_TIME_BASE units */
+int64_t av_get_cur_dts(AVFormatContext *s, int stream_index);
+
 /**
  * Probe a bytestream to determine the input format. Each time a probe returns
  * with a score that is too low, the probe buffer size is increased and another
diff --git a/libavformat/avidec.c b/libavformat/avidec.c
index 7436b63..68b60d0 100644
--- a/libavformat/avidec.c
+++ b/libavformat/avidec.c
@@ -1534,7 +1534,7 @@ static int avi_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp
             index=0;
         while(!avi->non_interleaved && index>0 && st2->index_entries[index-1].pos >= pos_min)
             index--;
-        ast2->frame_offset = st2->index_entries[index].timestamp;
+        st2->cur_dts = ast2->frame_offset = st2->index_entries[index].timestamp;
     }
 
     /* do the seek */
diff --git a/libavformat/mpegenc.c b/libavformat/mpegenc.c
index e2a96bc..1a1d6a5 100644
--- a/libavformat/mpegenc.c
+++ b/libavformat/mpegenc.c
@@ -38,7 +38,7 @@ typedef struct PacketDesc {
     int64_t dts;
     int size;
     int unwritten_size;
-    int flags;
+  //int flags;
     struct PacketDesc *next;
 } PacketDesc;
 
@@ -55,7 +55,6 @@ typedef struct {
     int lpcm_align;
     int bytes_to_iframe;
     int align_iframe;
-    int64_t vobu_start_pts;
 } StreamInfo;
 
 typedef struct {
@@ -80,6 +79,7 @@ typedef struct {
     int64_t vcd_padding_bytes_written;
 
     int preload;
+    int64_t vobu_start_pts;
 } MpegMuxContext;
 
 extern AVOutputFormat ff_mpeg1vcd_muxer;
@@ -267,6 +267,7 @@ static int put_system_header(AVFormatContext *ctx, uint8_t *buf,int only_for_str
     buf[4] = (size - 6) >> 8;
     buf[5] = (size - 6) & 0xff;
 
+    //av_log(ctx, AV_LOG_DEBUG, "system header size:%d\n", size);
     return size;
 }
 
@@ -425,6 +426,7 @@ static int mpeg_mux_init(AVFormatContext *ctx)
         bitrate += 10000;
         s->mux_rate = (bitrate + (8 * 50) - 1) / (8 * 50);
     }
+    av_log(ctx, AV_LOG_DEBUG, "mux_rate=%d bytes/sec\n", s->mux_rate*50);
 
     if (s->is_vcd) {
         double overhead_rate;
@@ -483,6 +485,7 @@ static int mpeg_mux_init(AVFormatContext *ctx)
     }
     s->system_header_size = get_system_header_size(ctx);
     s->last_scr = 0;
+    s->vobu_start_pts = AV_NOPTS_VALUE;
     return 0;
  fail:
     for(i=0;i<ctx->nb_streams;i++) {
@@ -607,6 +610,7 @@ static int flush_packet(AVFormatContext *ctx, int stream_index,
                 }
 
                 if (stream->bytes_to_iframe == 0 || s->packet_number == 0) {
+		    //av_log(ctx, AV_LOG_DEBUG, "DVD ALIGN2 pack_num:%d pts:%f\n", s->packet_number, pts/90000.0);
                     size = put_system_header(ctx, buf_ptr, 0);
                     buf_ptr += size;
                     size = buf_ptr - buffer;
@@ -1052,8 +1056,8 @@ static int mpeg_mux_write_packet(AVFormatContext *ctx, AVPacket *pkt)
     AVStream *st = ctx->streams[stream_index];
     StreamInfo *stream = st->priv_data;
     int64_t pts, dts;
-    PacketDesc *pkt_desc;
-    int preload;
+    PacketDesc *pkt_desc, *dec_next;
+    int preload, requeue = 0;
     const int is_iframe = st->codec->codec_type == AVMEDIA_TYPE_VIDEO && (pkt->flags & AV_PKT_FLAG_KEY);
 
     preload = av_rescale(s->preload, 90000, AV_TIME_BASE);
@@ -1071,26 +1075,38 @@ static int mpeg_mux_write_packet(AVFormatContext *ctx, AVPacket *pkt)
     av_dlog(ctx, "dts:%f pts:%f flags:%d stream:%d nopts:%d\n",
             dts / 90000.0, pts / 90000.0, pkt->flags,
             pkt->stream_index, pts != AV_NOPTS_VALUE);
-    if (!stream->premux_packet)
+    if (!stream->premux_packet) {
         stream->next_packet = &stream->premux_packet;
+	requeue = 1;
+    }
     *stream->next_packet=
-    pkt_desc= av_mallocz(sizeof(PacketDesc));
+    pkt_desc= av_malloc(sizeof(PacketDesc));
     pkt_desc->pts= pts;
     pkt_desc->dts= dts;
     pkt_desc->unwritten_size=
     pkt_desc->size= size;
+    pkt_desc->next= NULL;
     if(!stream->predecode_packet)
         stream->predecode_packet= pkt_desc;
+    else if (requeue) {
+        for (dec_next= stream->predecode_packet; dec_next->next; dec_next= dec_next->next);
+        dec_next->next = pkt_desc;
+    }
+
     stream->next_packet= &pkt_desc->next;
 
     if (av_fifo_realloc2(stream->fifo, av_fifo_size(stream->fifo) + size) < 0)
         return -1;
 
     if (s->is_dvd){
-        if (is_iframe && (s->packet_number == 0 || (pts - stream->vobu_start_pts >= 36000))) { // min VOBU length 0.4 seconds (mpucoder)
+        if (is_iframe && s->packet_number>0 && pts != AV_NOPTS_VALUE &&
+            s->vobu_start_pts != AV_NOPTS_VALUE && pts - s->vobu_start_pts >= 36000) { // min VOBU length 0.4 seconds (mpucoder)
             stream->bytes_to_iframe = av_fifo_size(stream->fifo);
             stream->align_iframe = 1;
-            stream->vobu_start_pts = pts;
+            s->vobu_start_pts = pts;
+        } else {
+            if (s->vobu_start_pts == AV_NOPTS_VALUE)
+                s->vobu_start_pts = pts;
         }
     }
 
diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
index a6e07fa..b5780c4 100644
--- a/libavformat/mpegts.c
+++ b/libavformat/mpegts.c
@@ -699,6 +699,17 @@ static int mpegts_set_stream_info(AVStream *st, PESContext *pes,
 
 static void new_pes_packet(PESContext *pes, AVPacket *pkt)
 {
+    /* For a teletext stream, output the complete packet,
+       including header. */
+    if (pes->st->codec->codec_id == CODEC_ID_DVB_TELETEXT) {
+      if (av_new_packet(pkt, pes->pes_header_size+pes->data_index) == 0) {
+	memcpy(pkt->data, pes->header, pes->pes_header_size);
+	memcpy(pkt->data+pes->pes_header_size, pes->buffer, pes->data_index);
+	av_freep(&pes->buffer);
+      } else
+	av_init_packet(pkt);
+    } else {
+
     av_init_packet(pkt);
 
     pkt->destruct = av_destruct_packet;
@@ -712,6 +723,8 @@ static void new_pes_packet(PESContext *pes, AVPacket *pkt)
     }
     memset(pkt->data+pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
 
+    }
+
     // Separate out the AC3 substream from an HDMV combined TrueHD/AC3 PID
     if (pes->sub_st && pes->stream_type == 0x83 && pes->extended_stream_id == 0x76)
         pkt->stream_index = pes->sub_st->index;
diff --git a/libavformat/mpegts.h b/libavformat/mpegts.h
index 98c4b93..98c89a3 100644
--- a/libavformat/mpegts.h
+++ b/libavformat/mpegts.h
@@ -57,6 +57,7 @@
 
 #define STREAM_TYPE_AUDIO_AC3       0x81
 #define STREAM_TYPE_AUDIO_DTS       0x8a
+//#define STREAM_TYPE_TELETEXT        0x101
 
 typedef struct MpegTSContext MpegTSContext;
 
diff --git a/libavformat/mux.c b/libavformat/mux.c
index c7e176a..470ccf5 100644
--- a/libavformat/mux.c
+++ b/libavformat/mux.c
@@ -763,6 +763,45 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt)
     }
 }
 
+void av_interleaved_discard(AVFormatContext *s, int64_t dts_min)
+{
+    AVPacketList *pktl= s->packet_buffer, **prev= &s->packet_buffer, *next;
+    int i;
+
+    av_log(s, AV_LOG_DEBUG, "av_interleaved_discard dts_min:%"PRId64"\n", dts_min);
+    while(pktl) {
+	const AVStream *st= s->streams[pktl->pkt.stream_index];
+	next = pktl->next;
+        if(dts_min == AV_NOPTS_VALUE ||
+	   pktl->pkt.dts*st->time_base.num*AV_TIME_BASE < dts_min*st->time_base.den) {
+av_log(s, AV_LOG_DEBUG, "av_interleaved_discard %"PRId64"\n", pktl->pkt.dts);
+            if(s->streams[pktl->pkt.stream_index]->last_in_packet_buffer == pktl)
+                s->streams[pktl->pkt.stream_index]->last_in_packet_buffer= NULL;
+	    av_free_packet(&pktl->pkt);
+	    *prev = next;
+	    av_freep(&pktl);
+	} else {
+	  int64_t ts_diff= av_rescale_q(dts_min, AV_TIME_BASE_Q, st->time_base);
+	  if (pktl->pkt.pts != AV_NOPTS_VALUE)
+	    pktl->pkt.pts -= ts_diff;
+	  if (pktl->pkt.dts != AV_NOPTS_VALUE)
+	    pktl->pkt.dts -= ts_diff;
+	  prev = &pktl->next;
+	}
+	pktl= next;
+    }
+    for(i = 0; i < s->nb_streams; i++) {
+      AVStream *st = s->streams[i];
+
+      if (st->cur_dts != AV_NOPTS_VALUE) {
+	if (!st->last_in_packet_buffer) // all packets have been deleted
+	  st->cur_dts = 0;
+	else // some packets remain
+	  st->cur_dts -= av_rescale_q(dts_min, AV_TIME_BASE_Q, st->time_base);
+      }
+    }
+}
+
 int av_write_trailer(AVFormatContext *s)
 {
     int ret, i;
diff --git a/libavformat/seek.c b/libavformat/seek.c
index 0ae99eb..3e655f2 100644
--- a/libavformat/seek.c
+++ b/libavformat/seek.c
@@ -60,6 +60,7 @@ typedef struct {
  * @param tb_lo low timestamp time base
  * @return representation of distance between high and low timestamps
  */
+#if 0
 static int64_t ts_distance(int64_t ts_hi,
                            AVRational tb_hi,
                            int64_t ts_lo,
@@ -72,6 +73,7 @@ static int64_t ts_distance(int64_t ts_hi,
 
     return hi - lo;
 }
+#endif
 
 /**
  * Partial search for keyframes in multiple streams.
@@ -94,7 +96,7 @@ static int64_t ts_distance(int64_t ts_hi,
  * @param found_hi          ptr to the count of already found high timestamp keyframes
  * @param first_iter        flag for first iteration
  */
-static void search_hi_lo_keyframes(AVFormatContext *s,
+static int search_hi_lo_keyframes(AVFormatContext *s,
                                    int64_t timestamp,
                                    AVRational timebase,
                                    int flags,
@@ -102,7 +104,8 @@ static void search_hi_lo_keyframes(AVFormatContext *s,
                                    int keyframes_to_find,
                                    int *found_lo,
                                    int *found_hi,
-                                   int first_iter)
+				   int first_iter,
+				  int64_t delta_max)
 {
     AVPacket pkt;
     AVSyncPoint *sp;
@@ -114,6 +117,7 @@ static void search_hi_lo_keyframes(AVFormatContext *s,
     int64_t pts, dts;   // PTS/DTS from stream
     int64_t ts;         // PTS in stream-local time base or position for byte seeking
     AVRational ts_tb;   // Time base of the stream or 1:1 for byte seeking
+    int ret = 0;
 
     for (;;) {
         if (av_read_frame(s, &pkt) < 0) {
@@ -171,8 +175,14 @@ static void search_hi_lo_keyframes(AVFormatContext *s,
                 ts_tb.den = 1;
             } else {
                 // otherwise, get stream time_base
+                int64_t delta;
                 ts    = pts;
                 ts_tb = st->time_base;
+                delta = timestamp - av_rescale_q(ts, ts_tb, timebase);
+                if (FFABS(delta) > delta_max) {
+                    ret = -1;
+                    break;
+                }
             }
 
             if (sp->first_ts == AV_NOPTS_VALUE) {
@@ -239,6 +249,7 @@ static void search_hi_lo_keyframes(AVFormatContext *s,
 
     // Clean up the parser.
     ff_read_frame_flush(s);
+    return ret;
 }
 
 int64_t ff_gen_syncpoint_search(AVFormatContext *s,
@@ -257,9 +268,10 @@ int64_t ff_gen_syncpoint_search(AVFormatContext *s,
     int64_t step;
     int found_lo = 0, found_hi = 0;
     int64_t min_distance, distance;
-    int64_t min_pos = 0;
+    int64_t min_distance2;
     int first_iter = 1;
     AVRational time_base;
+    int64_t delta_max = INT64_MAX;
 
     if (flags & AVSEEK_FLAG_BYTE) {
         // for byte seeking, we have exact 1:1 "timestamps" - positions
@@ -275,6 +287,7 @@ int64_t ff_gen_syncpoint_search(AVFormatContext *s,
             time_base.num = 1;
             time_base.den = AV_TIME_BASE;
         }
+	delta_max = av_rescale_q(20*AV_TIME_BASE, AV_TIME_BASE_Q, time_base);
     }
 
     // Initialize syncpoint structures for each stream.
@@ -315,13 +328,16 @@ int64_t ff_gen_syncpoint_search(AVFormatContext *s,
     curpos = FFMAX(pos - step / 2, 0);
     for (;;) {
         avio_seek(s->pb, curpos, SEEK_SET);
-        search_hi_lo_keyframes(s,
-                               ts, time_base,
-                               flags,
-                               sync,
-                               keyframes_to_find,
-                               &found_lo, &found_hi,
-                               first_iter);
+        i = search_hi_lo_keyframes(s,
+				   ts, time_base,
+				   flags,
+				   sync,
+				   keyframes_to_find,
+				   &found_lo, &found_hi,
+				   first_iter,
+				   delta_max);
+	av_log(s, AV_LOG_ERROR, "search_hi_lo=%d flo:%d fhi:%d ktf:%d delta_max=%lld\n",
+	       i, found_lo, found_hi, keyframes_to_find, delta_max);
         if (found_lo == keyframes_to_find && found_hi == keyframes_to_find)
             break;  // have all keyframes we wanted
         if (!curpos)
@@ -351,11 +367,16 @@ int64_t ff_gen_syncpoint_search(AVFormatContext *s,
 
     // Find actual position to start decoding so that decoder synchronizes
     // closest to ts and between ts_min and ts_max.
-    pos = INT64_MAX;
+    min_distance2 = INT64_MAX;
 
     for (i = 0; i < s->nb_streams; ++i) {
         st = s->streams[i];
         if (st->discard < AVDISCARD_ALL) {
+	    int64_t cur_dts;
+	    int64_t min_pos = 0;
+	    int64_t ts_num = st->time_base.num*time_base.den;
+	    int64_t ts_den = st->time_base.den*time_base.num;
+
             sp = &sync[i];
             min_distance = INT64_MAX;
             // Find timestamp closest to requested timestamp within min/max limits.
@@ -363,31 +384,38 @@ int64_t ff_gen_syncpoint_search(AVFormatContext *s,
                 && av_compare_ts(ts_min, time_base, sp->ts_lo, st->time_base) <= 0
                 && av_compare_ts(sp->ts_lo, st->time_base, ts_max, time_base) <= 0) {
                 // low timestamp is in range
-                min_distance = ts_distance(ts, time_base, sp->ts_lo, st->time_base);
+                min_distance = ts - av_rescale(sp->ts_lo, ts_num, ts_den); //ts_distance(ts, time_base, sp->ts_lo, st->time_base);
                 min_pos = sp->pos_lo;
+		cur_dts = sp->ts_lo;
             }
             if (sp->pos_hi != INT64_MAX
                 && av_compare_ts(ts_min, time_base, sp->ts_hi, st->time_base) <= 0
                 && av_compare_ts(sp->ts_hi, st->time_base, ts_max, time_base) <= 0) {
                 // high timestamp is in range, check distance
-                distance = ts_distance(sp->ts_hi, st->time_base, ts, time_base);
+                distance = av_rescale(sp->ts_hi, ts_num, ts_den) - ts;
                 if (distance < min_distance) {
                     min_distance = distance;
                     min_pos = sp->pos_hi;
+		    cur_dts = sp->ts_hi;
                 }
             }
+            av_log(s, AV_LOG_DEBUG, "seek2 st:%d dist=%lld pos=%lld dts=%lld\n", i, min_distance, min_pos, cur_dts);
             if (min_distance == INT64_MAX) {
                 // no timestamp is in range, cannot seek
                 av_free(sync);
                 return -1;
             }
-            if (min_pos < pos)
+            if (min_distance < min_distance2) {
+                min_distance2 = min_distance;
                 pos = min_pos;
+		st->cur_dts = cur_dts;
+	    }
         }
     }
 
     avio_seek(s->pb, pos, SEEK_SET);
     av_free(sync);
+    av_log(s, AV_LOG_DEBUG, "seek2 pos=%lld\n", pos);
     return pos;
 }
 
diff --git a/libavformat/utils.c b/libavformat/utils.c
index a78da36..2d8ff75 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -1409,7 +1409,7 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt)
                    cur_pkt.duration,
                    cur_pkt.flags);
 
-        if (st->need_parsing && !st->parser && !(s->flags & AVFMT_FLAG_NOPARSE)) {
+        if (st->need_parsing && !st->parser && !(s->flags & AVFMT_FLAG_NOPARSE)&& st->codec->codec_id != CODEC_ID_PROBE) {
             st->parser = av_parser_init(st->codec->codec_id);
             if (!st->parser) {
                 av_log(s, AV_LOG_VERBOSE, "parser not found for codec "
@@ -1846,21 +1846,56 @@ int64_t ff_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts,
     }
 
     if(ts_max == AV_NOPTS_VALUE){
-        int step= 1024;
+        int64_t step= 1024;
         filesize = avio_size(s->pb);
         pos_max = filesize - 1;
         do{
             pos_max -= step;
             ts_max = ff_read_timestamp(s, stream_index, &pos_max, pos_max + step, read_timestamp);
-            step += step;
-        }while(ts_max == AV_NOPTS_VALUE && pos_max >= step);
+#ifdef DEBUG_SEEK
+            av_log(s, AV_LOG_DEBUG, "ts_min=0x%llx ts_max=0x%llx\n",
+                   ts_min, ts_max);
+#endif
+
+            if (ts_max == AV_NOPTS_VALUE || ts_max < target_ts)
+                step += step;
+            else {
+		if (ts_max < ts_min) { /* wraparound */
+#ifdef DEBUG_SEEK
+		    av_log(s, AV_LOG_DEBUG, "wraparound: target=%lld ts_min=%lld ts_max=%lld\n",
+			   target_ts, ts_min, ts_max);
+#endif
+		    /* try to adjust pos_min until ts_min<=target_ts */
+		    step = pos_max - pos_min;
+		    while (step > 0) {
+			step >>= 1;
+			pos= pos_min + step;
+			ts= ff_read_timestamp(s, stream_index, &pos, pos_max, read_timestamp);
+#ifdef DEBUG_SEEK
+			av_log(s, AV_LOG_DEBUG, "wraparound2: pos=%lld step=%lld ts=%lld\n", pos, step, ts);
+#endif
+			if (ts != AV_NOPTS_VALUE) {
+			    if (ts <= target_ts ) {
+				pos_min = pos;
+				ts_min = ts;
+				break;
+			    } else if (ts_max < ts) {
+				pos_min = pos;
+				step = pos_max - pos_min;
+			    }
+			}
+		    }
+		}
+                break;
+            }
+        } while (pos_max >= step);
         if (ts_max == AV_NOPTS_VALUE)
             return -1;
 
         for(;;){
             int64_t tmp_pos= pos_max + 1;
             int64_t tmp_ts= ff_read_timestamp(s, stream_index, &tmp_pos, INT64_MAX, read_timestamp);
-            if(tmp_ts == AV_NOPTS_VALUE)
+            if(tmp_ts == AV_NOPTS_VALUE || tmp_ts < ts_max)
                 break;
             ts_max= tmp_ts;
             pos_max= tmp_pos;
@@ -1881,6 +1916,11 @@ int64_t ff_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts,
         pos_limit= pos_min;
     }
 
+#ifdef DEBUG_SEEK
+    av_log(s, AV_LOG_DEBUG, "ts_min=0x%llx ts_max=0x%llx pos_limit=%lld\n",
+           ts_min, ts_max, pos_limit);
+#endif
+
     no_change=0;
     while (pos_min < pos_limit) {
         av_dlog(s, "pos_min=0x%"PRIx64" pos_max=0x%"PRIx64" dts_min=%s dts_max=%s\n",
@@ -2026,7 +2066,7 @@ static int seek_frame_generic(AVFormatContext *s,
 static int seek_frame_internal(AVFormatContext *s, int stream_index,
                                int64_t timestamp, int flags)
 {
-    int ret;
+    int i, ret;
     AVStream *st;
 
     if (flags & AVSEEK_FLAG_BYTE) {
@@ -2052,19 +2092,25 @@ static int seek_frame_internal(AVFormatContext *s, int stream_index,
         ret = s->iformat->read_seek(s, stream_index, timestamp, flags);
     } else
         ret = -1;
-    if (ret >= 0) {
-        return 0;
-    }
-
-    if (s->iformat->read_timestamp && !(s->iformat->flags & AVFMT_NOBINSEARCH)) {
+    if (ret >= 0)
+        ;
+    else if (s->iformat->read_timestamp && !(s->iformat->flags & AVFMT_NOBINSEARCH)) {
         ff_read_frame_flush(s);
-        return ff_seek_frame_binary(s, stream_index, timestamp, flags);
+        ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
     } else if (!(s->iformat->flags & AVFMT_NOGENSEARCH)) {
         ff_read_frame_flush(s);
-        return seek_frame_generic(s, stream_index, timestamp, flags);
+        ret = seek_frame_generic(s, stream_index, timestamp, flags);
+    } else
+        ret = -1;
+    if (ret >= 0) {
+	for(i=0; i<s->nb_streams; i++) {
+	    st = s->streams[i];
+	    st->first_dts = st->cur_dts;
+            av_log(s, AV_LOG_DEBUG, "after seek st:%d cur:%lld\n", i, st->cur_dts);
+        }
+        return 0;
     }
-    else
-        return -1;
+    return ret;
 }
 
 int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
@@ -2112,6 +2158,27 @@ int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int
     // try some generic seek like seek_frame_generic() but with new ts semantics
 }
 
+/**
+ * Obtain the current dts in AV_TIME_BASE units.
+ * @param stream_index If stream_index is (-1), a default
+ * stream is selected.
+ */
+int64_t av_get_cur_dts(AVFormatContext *s, int stream_index)
+{
+    AVStream *st;
+
+    if (stream_index < 0){
+        stream_index= av_find_default_stream_index(s);
+        if(stream_index < 0)
+            return AV_NOPTS_VALUE;
+    }
+    st= s->streams[stream_index];
+    if (st->cur_dts == AV_NOPTS_VALUE || is_relative(st->cur_dts))
+        return AV_NOPTS_VALUE;
+    return av_rescale(st->cur_dts, AV_TIME_BASE * (int64_t)st->time_base.num,
+                      st->time_base.den);
+}
+
 /*******************************************************/
 
 /**
@@ -2405,6 +2472,9 @@ static int has_codec_parameters(AVStream *st, const char **errmsg_ptr)
             FAIL("no decodable DTS frames");
         break;
     case AVMEDIA_TYPE_VIDEO:
+	if (avctx->codec_id == CODEC_ID_MPEG2VIDEO &&
+	    avctx->sample_aspect_ratio.num == 0)
+	    FAIL("mpeg2v unspecified aspect");
         if (!avctx->width)
             FAIL("unspecified size");
         if (st->info->found_decoder >= 0 && avctx->pix_fmt == AV_PIX_FMT_NONE)
@@ -2658,6 +2728,9 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
                 st->time_base= */
             if(!st->codec->time_base.num)
                 st->codec->time_base= st->time_base;
+	    if (st->codec->codec_id == CODEC_ID_MPEG2VIDEO)
+		// aspect ratio may change; re-probe it
+		st->codec->sample_aspect_ratio = (AVRational){0,1};
         }
         //only for the split stuff
         if (!st->parser && !(ic->flags & AVFMT_FLAG_NOPARSE)) {
@@ -3042,7 +3115,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
     for (i=0; i < ic->nb_streams; i++) {
         if (ic->streams[i]->codec)
             ic->streams[i]->codec->thread_count = 0;
-        av_freep(&ic->streams[i]->info);
+        memset(ic->streams[i]->info, 0, sizeof *ic->streams[i]->info);
     }
     if(ic->pb)
         av_log(ic, AV_LOG_DEBUG, "File position after avformat_find_stream_info() is %"PRId64"\n", avio_tell(ic->pb));
