diff --git a/ffmpeg.c b/ffmpeg.c
index 4d12f80..c48aec7 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -202,13 +202,14 @@ static void sub2video_push_ref(InputStream *ist, int64_t pts)
                              AV_BUFFERSRC_FLAG_PUSH);
 }
 
-static void sub2video_update(InputStream *ist, AVSubtitle *sub, int64_t pts)
+static void sub2video_update(InputStream *ist, AVSubtitle *sub)
 {
     int w = ist->sub2video.w, h = ist->sub2video.h;
     AVFilterBufferRef *ref = ist->sub2video.ref;
     int8_t *dst;
     int     dst_linesize;
     int i;
+    int64_t pts = av_rescale_q(sub->pts, AV_TIME_BASE_Q, ist->st->time_base);
 
     if (!ref)
         return;
@@ -693,15 +694,15 @@ static void pre_process_video_frame(InputStream *ist, AVPicture *picture, void *
 static void do_subtitle_out(AVFormatContext *s,
                             OutputStream *ost,
                             InputStream *ist,
-                            AVSubtitle *sub,
-                            int64_t pts)
+                            AVSubtitle *sub)
 {
     int subtitle_out_max_size = 1024 * 1024;
     int subtitle_out_size, nb, i;
     AVCodecContext *enc;
     AVPacket pkt;
+    int64_t pts;
 
-    if (pts == AV_NOPTS_VALUE) {
+    if (sub->pts == AV_NOPTS_VALUE) {
         av_log(NULL, AV_LOG_ERROR, "Subtitle packets must have a pts\n");
         if (exit_on_error)
             exit_program(1);
@@ -723,8 +724,7 @@ static void do_subtitle_out(AVFormatContext *s,
         nb = 1;
 
     /* shift timestamp to honor -ss and make check_recording_time() work with -t */
-    pts = av_rescale_q(pts, ist->st->time_base, AV_TIME_BASE_Q)
-        - output_files[ost->file_index]->start_time;
+    pts = sub->pts - output_files[ost->file_index]->start_time;
     for (i = 0; i < nb; i++) {
         ost->sync_opts = av_rescale_q(pts, AV_TIME_BASE_Q, enc->time_base);
         if (!check_recording_time(ost))
@@ -1657,7 +1657,6 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output)
 static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output)
 {
     AVSubtitle subtitle;
-    int64_t pts = pkt->pts;
     int i, ret = avcodec_decode_subtitle2(ist->st->codec,
                                           &subtitle, got_output, pkt);
     if (ret < 0 || !*got_output) {
@@ -1668,8 +1667,8 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output)
 
     if (ist->fix_sub_duration) {
         if (ist->prev_sub.got_output) {
-            int end = av_rescale_q(pts - ist->prev_sub.pts, ist->st->time_base,
-                                   (AVRational){ 1, 1000 });
+            int end = av_rescale(subtitle.pts - ist->prev_sub.subtitle.pts,
+                                 1000, AV_TIME_BASE);
             if (end < ist->prev_sub.subtitle.end_display_time) {
                 av_log(ist->st->codec, AV_LOG_DEBUG,
                        "Subtitle duration reduced from %d to %d\n",
@@ -1677,26 +1676,25 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output)
                 ist->prev_sub.subtitle.end_display_time = end;
             }
         }
-        FFSWAP(int64_t,    pts,         ist->prev_sub.pts);
         FFSWAP(int,        *got_output, ist->prev_sub.got_output);
         FFSWAP(int,        ret,         ist->prev_sub.ret);
         FFSWAP(AVSubtitle, subtitle,    ist->prev_sub.subtitle);
     }
 
+    sub2video_update(ist, &subtitle);
+
     if (!*got_output || !subtitle.num_rects)
         return ret;
 
     rate_emu_sleep(ist);
 
-    sub2video_update(ist, &subtitle, pkt->pts);
-
     for (i = 0; i < nb_output_streams; i++) {
         OutputStream *ost = output_streams[i];
 
         if (!check_output_constraints(ist, ost) || !ost->encoding_needed)
             continue;
 
-        do_subtitle_out(output_files[ost->file_index]->ctx, ost, ist, &subtitle, pts);
+        do_subtitle_out(output_files[ost->file_index]->ctx, ost, ist, &subtitle);
     }
 
     avsubtitle_free(&subtitle);
diff --git a/ffmpeg.h b/ffmpeg.h
index cd849c9..85a11a0 100644
--- a/ffmpeg.h
+++ b/ffmpeg.h
@@ -232,7 +232,6 @@ typedef struct InputStream {
 
     int fix_sub_duration;
     struct { /* previous decoded subtitle and related variables */
-        int64_t pts;
         int got_output;
         int ret;
         AVSubtitle subtitle;
diff --git a/ffplay.c b/ffplay.c
index 42f03b8..408c82c 100644
--- a/ffplay.c
+++ b/ffplay.c
@@ -1840,6 +1840,8 @@ static int subtitle_thread(void *arg)
 
         avcodec_decode_subtitle2(is->subtitle_st->codec, &sp->sub,
                                  &got_subtitle, pkt);
+        if (sp->sub.pts != AV_NOPTS_VALUE)
+            pts = sp->sub.pts / (double)AV_TIME_BASE;
 
         if (got_subtitle && sp->sub.format == 0) {
             sp->pts = pts;
diff --git a/libavcodec/pgssubdec.c b/libavcodec/pgssubdec.c
index 79ebb55..64d20df 100644
--- a/libavcodec/pgssubdec.c
+++ b/libavcodec/pgssubdec.c
@@ -67,6 +67,7 @@ typedef struct PGSSubContext {
     PGSSubPresentation presentation;
     uint32_t           clut[256];
     PGSSubPicture      pictures[UINT16_MAX];
+    int64_t            pts;
     int forced_subs_only;
 } PGSSubContext;
 
@@ -387,7 +388,11 @@ static int display_end_segment(AVCodecContext *avctx, void *data,
      *      not been cleared by a subsequent empty display command.
      */
 
+    if (ctx->pts == AV_NOPTS_VALUE) /* if no presentation segment to set it */
+        ctx->pts = sub->pts;
     memset(sub, 0, sizeof(*sub));
+    sub->pts = ctx->pts;
+    ctx->pts = AV_NOPTS_VALUE;
 
     // Blank if last object_count was 0.
     if (!ctx->presentation.object_count)
@@ -436,8 +441,10 @@ static int display_end_segment(AVCodecContext *avctx, void *data,
 static int decode(AVCodecContext *avctx, void *data, int *data_size,
                   AVPacket *avpkt)
 {
+    PGSSubContext *ctx = avctx->priv_data;
     const uint8_t *buf = avpkt->data;
     int buf_size       = avpkt->size;
+    AVSubtitle *sub    = data;
 
     const uint8_t *buf_end;
     uint8_t       segment_type;
@@ -482,6 +489,7 @@ static int decode(AVCodecContext *avctx, void *data, int *data_size,
             break;
         case PRESENTATION_SEGMENT:
             parse_presentation_segment(avctx, buf, segment_length);
+            ctx->pts = sub->pts;
             break;
         case WINDOW_SEGMENT:
             /*
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index 99e012a..30b0d21 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -1701,6 +1701,9 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub,
     avctx->pkt = avpkt;
     *got_sub_ptr = 0;
     avcodec_get_subtitle_defaults(sub);
+    if (avctx->pkt_timebase.den && avpkt->pts != AV_NOPTS_VALUE)
+        sub->pts = av_rescale_q(avpkt->pts,
+                                avctx->pkt_timebase, AV_TIME_BASE_Q);
     ret = avctx->codec->decode(avctx, sub, got_sub_ptr, avpkt);
     if (*got_sub_ptr)
         avctx->frame_number++;
