Current code segfaults since the deprecation of AVSubtitleRect.pict because it
freed/realloced AVSubtitleRect.pict.data by itself.

The new code stores the generated YUVA AVSubtitle rectangles in their own
struct and keeps the original AVSubtitle structure untouched, because
overwriting it is considered invalid API usage.

Signed-off-by: Marton Balint <c...@passwd.hu>
---
 ffplay.c | 48 ++++++++++++++++++++++++++----------------------
 1 file changed, 26 insertions(+), 22 deletions(-)

diff --git a/ffplay.c b/ffplay.c
index 4a084b4..7c1cb4f 100644
--- a/ffplay.c
+++ b/ffplay.c
@@ -151,6 +151,7 @@ typedef struct Clock {
 typedef struct Frame {
     AVFrame *frame;
     AVSubtitle sub;
+    AVSubtitleRect **subrects;  /* rescaled subtitle rectangles in yuva */
     int serial;
     double pts;           /* presentation timestamp for the frame */
     double duration;      /* estimated duration of the frame */
@@ -649,6 +650,12 @@ static void decoder_destroy(Decoder *d) {
 
 static void frame_queue_unref_item(Frame *vp)
 {
+    int i;
+    for (i = 0; i < vp->sub.num_rects; i++) {
+        av_freep(&vp->subrects[i]->data[0]);
+        av_freep(&vp->subrects[i]);
+    }
+    av_freep(&vp->subrects);
     av_frame_unref(vp->frame);
     avsubtitle_free(&vp->sub);
 }
@@ -860,7 +867,7 @@ static void blend_subrect(AVPicture *dst, const 
AVSubtitleRect *rect, int imgw,
     int x, y, Y, U, V, A;
     uint8_t *lum, *cb, *cr;
     int dstx, dsty, dstw, dsth;
-    const AVPicture *src = &rect->pict;
+    const AVSubtitleRect *src = rect;
 
     dstw = av_clip(rect->w, 0, imgw);
     dsth = av_clip(rect->h, 0, imgh);
@@ -963,7 +970,7 @@ static void video_image_display(VideoState *is)
                     pict.linesize[2] = vp->bmp->pitches[1];
 
                     for (i = 0; i < sp->sub.num_rects; i++)
-                        blend_subrect(&pict, sp->sub.rects[i],
+                        blend_subrect(&pict, sp->subrects[i],
                                       vp->bmp->w, vp->bmp->h);
 
                     SDL_UnlockYUVOverlay (vp->bmp);
@@ -2295,6 +2302,10 @@ static int subtitle_thread(void *arg)
                 pts = sp->sub.pts / (double)AV_TIME_BASE;
             sp->pts = pts;
             sp->serial = is->subdec.pkt_serial;
+            if (!(sp->subrects = av_mallocz_array(sp->sub.num_rects, 
sizeof(AVSubtitleRect*)))) {
+                av_log(NULL, AV_LOG_FATAL, "Cannot allocate subrects\n");
+                exit(1);
+            }
 
             for (i = 0; i < sp->sub.num_rects; i++)
             {
@@ -2304,35 +2315,28 @@ static int subtitle_thread(void *arg)
                 int subh = is->subdec.avctx->height ? is->subdec.avctx->height 
: is->viddec_height;
                 int out_w = is->viddec_width  ? in_w * is->viddec_width  / 
subw : in_w;
                 int out_h = is->viddec_height ? in_h * is->viddec_height / 
subh : in_h;
-                AVPicture newpic;
 
-                //can not use avpicture_alloc as it is not compatible with 
avsubtitle_free()
-                av_image_fill_linesizes(newpic.linesize, AV_PIX_FMT_YUVA420P, 
out_w);
-                newpic.data[0] = av_malloc(newpic.linesize[0] * out_h);
-                newpic.data[3] = av_malloc(newpic.linesize[3] * out_h);
-                newpic.data[1] = av_malloc(newpic.linesize[1] * ((out_h+1)/2));
-                newpic.data[2] = av_malloc(newpic.linesize[2] * ((out_h+1)/2));
+                if (!(sp->subrects[i] = av_mallocz(sizeof(AVSubtitleRect))) || 
+                    av_image_alloc(sp->subrects[i]->data, 
sp->subrects[i]->linesize, out_w, out_h, AV_PIX_FMT_YUVA420P, 16) < 0) {
+                    av_log(NULL, AV_LOG_FATAL, "Cannot allocate subtitle 
data\n");
+                    exit(1);
+                }
 
                 is->sub_convert_ctx = sws_getCachedContext(is->sub_convert_ctx,
                     in_w, in_h, AV_PIX_FMT_PAL8, out_w, out_h,
                     AV_PIX_FMT_YUVA420P, sws_flags, NULL, NULL, NULL);
-                if (!is->sub_convert_ctx || !newpic.data[0] || !newpic.data[3] 
||
-                    !newpic.data[1] || !newpic.data[2]
-                ) {
+                if (!is->sub_convert_ctx) {
                     av_log(NULL, AV_LOG_FATAL, "Cannot initialize the sub 
conversion context\n");
                     exit(1);
                 }
                 sws_scale(is->sub_convert_ctx,
-                          (void*)sp->sub.rects[i]->pict.data, 
sp->sub.rects[i]->pict.linesize,
-                          0, in_h, newpic.data, newpic.linesize);
-
-                av_free(sp->sub.rects[i]->pict.data[0]);
-                av_free(sp->sub.rects[i]->pict.data[1]);
-                sp->sub.rects[i]->pict = newpic;
-                sp->sub.rects[i]->w = out_w;
-                sp->sub.rects[i]->h = out_h;
-                sp->sub.rects[i]->x = sp->sub.rects[i]->x * out_w / in_w;
-                sp->sub.rects[i]->y = sp->sub.rects[i]->y * out_h / in_h;
+                          (void*)sp->sub.rects[i]->data, 
sp->sub.rects[i]->linesize,
+                          0, in_h, sp->subrects[i]->data, 
sp->subrects[i]->linesize);
+
+                sp->subrects[i]->w = out_w;
+                sp->subrects[i]->h = out_h;
+                sp->subrects[i]->x = sp->sub.rects[i]->x * out_w / in_w;
+                sp->subrects[i]->y = sp->sub.rects[i]->y * out_h / in_h;
             }
 
             /* now we can update the picture count */
-- 
2.1.4

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to