Revision 72ce053b

View differences:

ffplay.c
57 57

  
58 58
#define MAX_VIDEOQ_SIZE (5 * 256 * 1024)
59 59
#define MAX_AUDIOQ_SIZE (5 * 16 * 1024)
60
#define MAX_SUBTITLEQ_SIZE (5 * 16 * 1024)
60 61

  
61 62
/* SDL audio buffer size, in samples. Should be small to have precise
62 63
   A/V sync as SDL does not have hardware buffer fullness info. */
......
86 87
} PacketQueue;
87 88

  
88 89
#define VIDEO_PICTURE_QUEUE_SIZE 1
90
#define SUBPICTURE_QUEUE_SIZE 4
89 91

  
90 92
typedef struct VideoPicture {
91 93
    double pts; /* presentation time stamp for this picture */
......
94 96
    int allocated;
95 97
} VideoPicture;
96 98

  
99
typedef struct SubPicture {
100
    double pts; /* presentation time stamp for this picture */
101
    AVSubtitle sub;
102
} SubPicture;
103

  
97 104
enum {
98 105
    AV_SYNC_AUDIO_MASTER, /* default choice */
99 106
    AV_SYNC_VIDEO_MASTER,
......
142 149
    int sample_array_index;
143 150
    int last_i_start;
144 151
    
152
    SDL_Thread *subtitle_tid;
153
    int subtitle_stream;
154
    int subtitle_stream_changed;
155
    AVStream *subtitle_st;
156
    PacketQueue subtitleq;
157
    SubPicture subpq[SUBPICTURE_QUEUE_SIZE];
158
    int subpq_size, subpq_rindex, subpq_windex;
159
    SDL_mutex *subpq_mutex;
160
    SDL_cond *subpq_cond;
161
        
145 162
    double frame_timer;
146 163
    double frame_last_pts;
147 164
    double frame_last_delay;
......
163 180
    
164 181
    SDL_mutex *video_decoder_mutex;
165 182
    SDL_mutex *audio_decoder_mutex;
183
    SDL_mutex *subtitle_decoder_mutex;
166 184

  
167 185
    //    QETimer *video_timer;
168 186
    char filename[1024];
......
371 389
}
372 390
#endif
373 391

  
392

  
393

  
394
#define SCALEBITS 10
395
#define ONE_HALF  (1 << (SCALEBITS - 1))
396
#define FIX(x)    ((int) ((x) * (1<<SCALEBITS) + 0.5))
397

  
398
#define RGB_TO_Y_CCIR(r, g, b) \
399
((FIX(0.29900*219.0/255.0) * (r) + FIX(0.58700*219.0/255.0) * (g) + \
400
  FIX(0.11400*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS)
401

  
402
#define RGB_TO_U_CCIR(r1, g1, b1, shift)\
403
(((- FIX(0.16874*224.0/255.0) * r1 - FIX(0.33126*224.0/255.0) * g1 +         \
404
     FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
405

  
406
#define RGB_TO_V_CCIR(r1, g1, b1, shift)\
407
(((FIX(0.50000*224.0/255.0) * r1 - FIX(0.41869*224.0/255.0) * g1 -           \
408
   FIX(0.08131*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
409

  
410
#define ALPHA_BLEND(a, oldp, newp, s)\
411
((((oldp << s) * (255 - (a))) + (newp * (a))) / (255 << s))
412

  
413
#define RGBA_IN(r, g, b, a, s)\
414
{\
415
    unsigned int v = ((const uint32_t *)(s))[0];\
416
    a = (v >> 24) & 0xff;\
417
    r = (v >> 16) & 0xff;\
418
    g = (v >> 8) & 0xff;\
419
    b = v & 0xff;\
420
}
421

  
422
#define YUVA_IN(y, u, v, a, s, pal)\
423
{\
424
    unsigned int val = ((const uint32_t *)(pal))[*(const uint8_t*)s];\
425
    a = (val >> 24) & 0xff;\
426
    y = (val >> 16) & 0xff;\
427
    u = (val >> 8) & 0xff;\
428
    v = val & 0xff;\
429
}
430

  
431
#define YUVA_OUT(d, y, u, v, a)\
432
{\
433
    ((uint32_t *)(d))[0] = (a << 24) | (y << 16) | (u << 8) | v;\
434
}
435

  
436

  
437
#define BPP 1
438

  
439
static void blend_subrect(AVPicture *dst, const AVSubtitleRect *rect)
440
{
441
    int wrap, wrap3, width2, skip2;
442
    int y, u, v, a, u1, v1, a1, w, h;
443
    uint8_t *lum, *cb, *cr;
444
    const uint8_t *p;
445
    const uint32_t *pal;
446

  
447
    lum = dst->data[0] + rect->y * dst->linesize[0];
448
    cb = dst->data[1] + (rect->y >> 1) * dst->linesize[1];
449
    cr = dst->data[2] + (rect->y >> 1) * dst->linesize[2];
450

  
451
    width2 = (rect->w + 1) >> 1;
452
    skip2 = rect->x >> 1;
453
    wrap = dst->linesize[0];
454
    wrap3 = rect->linesize;
455
    p = rect->bitmap;
456
    pal = rect->rgba_palette;  /* Now in YCrCb! */
457
    
458
    if (rect->y & 1) {
459
        lum += rect->x;
460
        cb += skip2;
461
        cr += skip2;
462
    
463
        if (rect->x & 1) {
464
            YUVA_IN(y, u, v, a, p, pal);
465
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
466
            cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
467
            cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
468
            cb++;
469
            cr++;
470
            lum++;
471
            p += BPP;
472
        }
473
        for(w = rect->w - (rect->x & 1); w >= 2; w -= 2) {
474
            YUVA_IN(y, u, v, a, p, pal);
475
            u1 = u;
476
            v1 = v;
477
            a1 = a;
478
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
479

  
480
            YUVA_IN(y, u, v, a, p + BPP, pal);
481
            u1 += u;
482
            v1 += v;
483
            a1 += a;
484
            lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
485
            cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
486
            cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
487
            cb++;
488
            cr++;
489
            p += 2 * BPP;
490
            lum += 2;
491
        }
492
        if (w) {
493
            YUVA_IN(y, u, v, a, p, pal);
494
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
495
            cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
496
            cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
497
        }
498
        p += wrap3 + (wrap3 - rect->w * BPP);
499
        lum += wrap + (wrap - rect->w - rect->x);
500
        cb += dst->linesize[1] - width2 - skip2;
501
        cr += dst->linesize[2] - width2 - skip2;
502
    }
503
    for(h = rect->h - (rect->y & 1); h >= 2; h -= 2) {
504
        lum += rect->x;
505
        cb += skip2;
506
        cr += skip2;
507
    
508
        if (rect->x & 1) {
509
            YUVA_IN(y, u, v, a, p, pal);
510
            u1 = u;
511
            v1 = v;
512
            a1 = a;
513
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
514
            p += wrap3;
515
            lum += wrap;
516
            YUVA_IN(y, u, v, a, p, pal);
517
            u1 += u;
518
            v1 += v;
519
            a1 += a;
520
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
521
            cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
522
            cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
523
            cb++;
524
            cr++;
525
            p += -wrap3 + BPP;
526
            lum += -wrap + 1;
527
        }
528
        for(w = rect->w - (rect->x & 1); w >= 2; w -= 2) {
529
            YUVA_IN(y, u, v, a, p, pal);
530
            u1 = u;
531
            v1 = v;
532
            a1 = a;
533
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
534

  
535
            YUVA_IN(y, u, v, a, p, pal);
536
            u1 += u;
537
            v1 += v;
538
            a1 += a;
539
            lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
540
            p += wrap3;
541
            lum += wrap;
542

  
543
            YUVA_IN(y, u, v, a, p, pal);
544
            u1 += u;
545
            v1 += v;
546
            a1 += a;
547
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
548

  
549
            YUVA_IN(y, u, v, a, p, pal);
550
            u1 += u;
551
            v1 += v;
552
            a1 += a;
553
            lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
554

  
555
            cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 2);
556
            cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 2);
557

  
558
            cb++;
559
            cr++;
560
            p += -wrap3 + 2 * BPP;
561
            lum += -wrap + 2;
562
        }
563
        if (w) {
564
            YUVA_IN(y, u, v, a, p, pal);
565
            u1 = u;
566
            v1 = v;
567
            a1 = a;
568
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
569
            p += wrap3;
570
            lum += wrap;
571
            YUVA_IN(y, u, v, a, p, pal);
572
            u1 += u;
573
            v1 += v;
574
            a1 += a;
575
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
576
            cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
577
            cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
578
            cb++;
579
            cr++;
580
            p += -wrap3 + BPP;
581
            lum += -wrap + 1;
582
        }
583
        p += wrap3 + (wrap3 - rect->w * BPP);
584
        lum += wrap + (wrap - rect->w - rect->x);
585
        cb += dst->linesize[1] - width2 - skip2;
586
        cr += dst->linesize[2] - width2 - skip2;
587
    }
588
    /* handle odd height */
589
    if (h) {
590
        lum += rect->x;
591
        cb += skip2;
592
        cr += skip2;
593
    
594
        if (rect->x & 1) {
595
            YUVA_IN(y, u, v, a, p, pal);
596
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
597
            cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
598
            cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
599
            cb++;
600
            cr++;
601
            lum++;
602
            p += BPP;
603
        }
604
        for(w = rect->w - (rect->x & 1); w >= 2; w -= 2) {
605
            YUVA_IN(y, u, v, a, p, pal);
606
            u1 = u;
607
            v1 = v;
608
            a1 = a;
609
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
610

  
611
            YUVA_IN(y, u, v, a, p + BPP, pal);
612
            u1 += u;
613
            v1 += v;
614
            a1 += a;
615
            lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
616
            cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u, 1);
617
            cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v, 1);
618
            cb++;
619
            cr++;
620
            p += 2 * BPP;
621
            lum += 2;
622
        }
623
        if (w) {
624
            YUVA_IN(y, u, v, a, p, pal);
625
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
626
            cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
627
            cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
628
        }
629
    }
630
}
631

  
632
static void free_subpicture(SubPicture *sp)
633
{
634
    int i;
635
    
636
    for (i = 0; i < sp->sub.num_rects; i++)
637
    {
638
        av_free(sp->sub.rects[i].bitmap);
639
        av_free(sp->sub.rects[i].rgba_palette);
640
    }
641
    
642
    av_free(sp->sub.rects);
643
    
644
    memset(&sp->sub, 0, sizeof(AVSubtitle));
645
}
646

  
374 647
static void video_image_display(VideoState *is)
375 648
{
376 649
    VideoPicture *vp;
650
    SubPicture *sp;
651
    AVPicture pict;
377 652
    float aspect_ratio;
378 653
    int width, height, x, y;
379 654
    SDL_Rect rect;
655
    int i;
380 656

  
381 657
    vp = &is->pictq[is->pictq_rindex];
382 658
    if (vp->bmp) {
......
424 700
        }
425 701
#endif
426 702

  
703
        if (is->subtitle_st)
704
        {
705
            if (is->subpq_size > 0)
706
            {
707
                sp = &is->subpq[is->subpq_rindex];
708

  
709
                if (vp->pts >= sp->pts + ((float) sp->sub.start_display_time / 1000))
710
                {
711
                    SDL_LockYUVOverlay (vp->bmp);
712

  
713
                    pict.data[0] = vp->bmp->pixels[0];
714
                    pict.data[1] = vp->bmp->pixels[2];
715
                    pict.data[2] = vp->bmp->pixels[1];
716

  
717
                    pict.linesize[0] = vp->bmp->pitches[0];
718
                    pict.linesize[1] = vp->bmp->pitches[2];
719
                    pict.linesize[2] = vp->bmp->pitches[1];
720

  
721
                    for (i = 0; i < sp->sub.num_rects; i++)
722
                        blend_subrect(&pict, &sp->sub.rects[i]);
723

  
724
                    SDL_UnlockYUVOverlay (vp->bmp);
725
                }
726
            }
727
        }
728

  
729

  
427 730
        /* XXX: we suppose the screen has a 1.0 pixel ratio */
428 731
        height = is->height;
429 732
        width = ((int)rint(height * aspect_ratio)) & -3;
......
642 945
    VideoPicture *vp;
643 946
    double actual_delay, delay, sync_threshold, ref_clock, diff;
644 947

  
948
    SubPicture *sp, *sp2;
645 949

  
646 950
    if (is->video_st) {
647 951
        if (is->pictq_size == 0) {
......
702 1006
                   delay, actual_delay, vp->pts, -diff);
703 1007
#endif
704 1008

  
1009
            if(is->subtitle_st) {
1010
                if (is->subtitle_stream_changed) {
1011
                    SDL_LockMutex(is->subpq_mutex);
1012
                    
1013
                    while (is->subpq_size) {
1014
                        free_subpicture(&is->subpq[is->subpq_rindex]);
1015
                    
1016
                        /* update queue size and signal for next picture */
1017
                        if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
1018
                            is->subpq_rindex = 0;
1019
                                
1020
                        is->subpq_size--;
1021
                    }
1022
                    is->subtitle_stream_changed = 0;
1023

  
1024
                    SDL_CondSignal(is->subpq_cond);
1025
                    SDL_UnlockMutex(is->subpq_mutex);
1026
                } else {
1027
                    if (is->subpq_size > 0) {
1028
                        sp = &is->subpq[is->subpq_rindex];
1029

  
1030
                        if (is->subpq_size > 1)
1031
                            sp2 = &is->subpq[(is->subpq_rindex + 1) % SUBPICTURE_QUEUE_SIZE];
1032
                        else
1033
                            sp2 = NULL;
1034

  
1035
                        if ((is->video_current_pts > (sp->pts + ((float) sp->sub.end_display_time / 1000)))
1036
                                || (sp2 && is->video_current_pts > (sp2->pts + ((float) sp2->sub.start_display_time / 1000))))
1037
                        {
1038
                            free_subpicture(sp);
1039

  
1040
                            /* update queue size and signal for next picture */
1041
                            if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
1042
                                is->subpq_rindex = 0;
1043

  
1044
                            SDL_LockMutex(is->subpq_mutex);
1045
                            is->subpq_size--;
1046
                            SDL_CondSignal(is->subpq_cond);
1047
                            SDL_UnlockMutex(is->subpq_mutex);
1048
                        }
1049
                    }
1050
                }
1051
            }
1052

  
705 1053
            /* display picture */
706 1054
            video_display(is);
707 1055
            
......
730 1078
    if (show_status) {
731 1079
        static int64_t last_time;
732 1080
        int64_t cur_time;
733
        int aqsize, vqsize;
1081
        int aqsize, vqsize, sqsize;
734 1082
        double av_diff;
735 1083
        
736 1084
        cur_time = av_gettime();
737 1085
        if (!last_time || (cur_time - last_time) >= 500 * 1000) {
738 1086
            aqsize = 0;
739 1087
            vqsize = 0;
1088
            sqsize = 0;
740 1089
            if (is->audio_st)
741 1090
                aqsize = is->audioq.size;
742 1091
            if (is->video_st)
743 1092
                vqsize = is->videoq.size;
1093
            if (is->subtitle_st)
1094
                sqsize = is->subtitleq.size;
744 1095
            av_diff = 0;
745 1096
            if (is->audio_st && is->video_st)
746 1097
                av_diff = get_audio_clock(is) - get_video_clock(is);
747
            printf("%7.2f A-V:%7.3f aq=%5dKB vq=%5dKB    \r", 
748
                   get_master_clock(is), av_diff, aqsize / 1024, vqsize / 1024);
1098
            printf("%7.2f A-V:%7.3f aq=%5dKB vq=%5dKB sq=%5dB    \r", 
1099
                   get_master_clock(is), av_diff, aqsize / 1024, vqsize / 1024, sqsize);
749 1100
            fflush(stdout);
750 1101
            last_time = cur_time;
751 1102
        }
......
948 1299
    return 0;
949 1300
}
950 1301

  
1302
static int subtitle_thread(void *arg)
1303
{
1304
    VideoState *is = arg;
1305
    SubPicture *sp;
1306
    AVPacket pkt1, *pkt = &pkt1;
1307
    int len1, got_subtitle;
1308
    double pts;
1309
    int i, j;
1310
    int r, g, b, y, u, v, a;
1311

  
1312
    for(;;) {
1313
        while (is->paused && !is->subtitleq.abort_request) {
1314
            SDL_Delay(10);
1315
        }
1316
        if (packet_queue_get(&is->subtitleq, pkt, 1) < 0)
1317
            break;
1318
            
1319
        SDL_LockMutex(is->subpq_mutex);
1320
        while (is->subpq_size >= SUBPICTURE_QUEUE_SIZE &&
1321
               !is->subtitleq.abort_request) {
1322
            SDL_CondWait(is->subpq_cond, is->subpq_mutex);
1323
        }
1324
        SDL_UnlockMutex(is->subpq_mutex);
1325
        
1326
        if (is->subtitleq.abort_request)
1327
            goto the_end;
1328
            
1329
        sp = &is->subpq[is->subpq_windex];
1330

  
1331
       /* NOTE: ipts is the PTS of the _first_ picture beginning in
1332
           this packet, if any */
1333
        pts = 0;
1334
        if (pkt->pts != AV_NOPTS_VALUE)
1335
            pts = av_q2d(is->subtitle_st->time_base)*pkt->pts;
1336

  
1337
        SDL_LockMutex(is->subtitle_decoder_mutex);
1338
        len1 = avcodec_decode_subtitle(is->subtitle_st->codec, 
1339
                                    &sp->sub, &got_subtitle, 
1340
                                    pkt->data, pkt->size);
1341
        SDL_UnlockMutex(is->subtitle_decoder_mutex);
1342
//            if (len1 < 0)
1343
//                break;
1344
        if (got_subtitle && sp->sub.format == 0) {
1345
            sp->pts = pts;
1346
            
1347
            for (i = 0; i < sp->sub.num_rects; i++)
1348
            {
1349
                for (j = 0; j < sp->sub.rects[i].nb_colors; j++)
1350
                {
1351
                    RGBA_IN(r, g, b, a, sp->sub.rects[i].rgba_palette + j);
1352
                    y = RGB_TO_Y_CCIR(r, g, b);
1353
                    u = RGB_TO_U_CCIR(r, g, b, 0);
1354
                    v = RGB_TO_V_CCIR(r, g, b, 0);
1355
                    YUVA_OUT(sp->sub.rects[i].rgba_palette + j, y, u, v, a);
1356
                }
1357
            }
1358

  
1359
            /* now we can update the picture count */
1360
            if (++is->subpq_windex == SUBPICTURE_QUEUE_SIZE)
1361
                is->subpq_windex = 0;
1362
            SDL_LockMutex(is->subpq_mutex);
1363
            is->subpq_size++;
1364
            SDL_UnlockMutex(is->subpq_mutex);
1365
        }
1366
        av_free_packet(pkt);
1367
//        if (step) 
1368
//            if (cur_stream)
1369
//                stream_pause(cur_stream);
1370
    }
1371
 the_end:
1372
    return 0;
1373
}
1374

  
951 1375
/* copy samples for viewing in editor window */
952 1376
static void update_sample_display(VideoState *is, short *samples, int samples_size)
953 1377
{
......
1237 1661
        packet_queue_init(&is->videoq);
1238 1662
        is->video_tid = SDL_CreateThread(video_thread, is);
1239 1663
        break;
1664
    case CODEC_TYPE_SUBTITLE:
1665
        is->subtitle_stream = stream_index;
1666
        is->subtitle_st = ic->streams[stream_index];
1667
        packet_queue_init(&is->subtitleq);
1668
        
1669
        is->subtitle_tid = SDL_CreateThread(subtitle_thread, is);
1670
        break;
1240 1671
    default:
1241 1672
        break;
1242 1673
    }
......
1248 1679
    AVFormatContext *ic = is->ic;
1249 1680
    AVCodecContext *enc;
1250 1681
    
1682
    if (stream_index < 0 || stream_index >= ic->nb_streams)
1683
        return;
1251 1684
    enc = ic->streams[stream_index]->codec;
1252 1685

  
1253 1686
    switch(enc->codec_type) {
......
1271 1704

  
1272 1705
        packet_queue_end(&is->videoq);
1273 1706
        break;
1707
    case CODEC_TYPE_SUBTITLE:
1708
        packet_queue_abort(&is->subtitleq);
1709
        
1710
        /* note: we also signal this mutex to make sure we deblock the
1711
           video thread in all cases */
1712
        SDL_LockMutex(is->subpq_mutex);
1713
        is->subtitle_stream_changed = 1;
1714
    
1715
        SDL_CondSignal(is->subpq_cond);
1716
        SDL_UnlockMutex(is->subpq_mutex);
1717

  
1718
        SDL_WaitThread(is->subtitle_tid, NULL);
1719

  
1720
        packet_queue_end(&is->subtitleq);
1721
        break;
1274 1722
    default:
1275 1723
        break;
1276 1724
    }
......
1285 1733
        is->video_st = NULL;
1286 1734
        is->video_stream = -1;
1287 1735
        break;
1736
    case CODEC_TYPE_SUBTITLE:
1737
        is->subtitle_st = NULL;
1738
        is->subtitle_stream = -1;
1739
        break;
1288 1740
    default:
1289 1741
        break;
1290 1742
    }
......
1328 1780
    audio_index = -1;
1329 1781
    is->video_stream = -1;
1330 1782
    is->audio_stream = -1;
1783
    is->subtitle_stream = -1;
1331 1784

  
1332 1785
    global_video_state = is;
1333 1786
    url_set_interrupt_cb(decode_interrupt_cb);
......
1446 1899
            /* XXX: must lock decoder threads */
1447 1900
            SDL_LockMutex(is->video_decoder_mutex);
1448 1901
            SDL_LockMutex(is->audio_decoder_mutex);
1902
            SDL_LockMutex(is->subtitle_decoder_mutex);
1449 1903
            ret = av_seek_frame(is->ic, -1, is->seek_pos, is->seek_flags);
1450 1904
            if (ret < 0) {
1451 1905
                fprintf(stderr, "%s: error while seeking\n", is->ic->filename);
......
1453 1907
                if (is->audio_stream >= 0) {
1454 1908
                    packet_queue_flush(&is->audioq);
1455 1909
                }
1910
                if (is->subtitle_stream >= 0) {
1911
                    packet_queue_flush(&is->subtitleq);
1912
                }
1456 1913
                if (is->video_stream >= 0) {
1457 1914
                    packet_queue_flush(&is->videoq);
1458 1915
                    avcodec_flush_buffers(ic->streams[video_index]->codec);
1459 1916
                }
1460 1917
            }
1918
            SDL_UnlockMutex(is->subtitle_decoder_mutex);
1461 1919
            SDL_UnlockMutex(is->audio_decoder_mutex);
1462 1920
            SDL_UnlockMutex(is->video_decoder_mutex);
1463 1921
            is->seek_req = 0;
......
1466 1924
        /* if the queue are full, no need to read more */
1467 1925
        if (is->audioq.size > MAX_AUDIOQ_SIZE ||
1468 1926
            is->videoq.size > MAX_VIDEOQ_SIZE || 
1927
            is->subtitleq.size > MAX_SUBTITLEQ_SIZE || 
1469 1928
            url_feof(&ic->pb)) {
1470 1929
            /* wait 10 ms */
1471 1930
            SDL_Delay(10);
......
1483 1942
            packet_queue_put(&is->audioq, pkt);
1484 1943
        } else if (pkt->stream_index == is->video_stream) {
1485 1944
            packet_queue_put(&is->videoq, pkt);
1945
        } else if (pkt->stream_index == is->subtitle_stream) {
1946
            packet_queue_put(&is->subtitleq, pkt);
1486 1947
        } else {
1487 1948
            av_free_packet(pkt);
1488 1949
        }
......
1502 1963
        stream_component_close(is, is->audio_stream);
1503 1964
    if (is->video_stream >= 0)
1504 1965
        stream_component_close(is, is->video_stream);
1966
    if (is->subtitle_stream >= 0)
1967
        stream_component_close(is, is->subtitle_stream);
1505 1968
    if (is->ic) {
1506 1969
        av_close_input_file(is->ic);
1507 1970
        is->ic = NULL; /* safety */
......
1538 2001
    is->pictq_mutex = SDL_CreateMutex();
1539 2002
    is->pictq_cond = SDL_CreateCond();
1540 2003
    
2004
    is->subpq_mutex = SDL_CreateMutex();
2005
    is->subpq_cond = SDL_CreateCond();
2006
    
2007
    is->subtitle_decoder_mutex = SDL_CreateMutex();
1541 2008
    is->audio_decoder_mutex = SDL_CreateMutex();
1542 2009
    is->video_decoder_mutex = SDL_CreateMutex();
1543 2010

  
......
1571 2038
    }
1572 2039
    SDL_DestroyMutex(is->pictq_mutex);
1573 2040
    SDL_DestroyCond(is->pictq_cond);
2041
    SDL_DestroyMutex(is->subpq_mutex);
2042
    SDL_DestroyCond(is->subpq_cond);
2043
    SDL_DestroyMutex(is->subtitle_decoder_mutex);
1574 2044
    SDL_DestroyMutex(is->audio_decoder_mutex);
1575 2045
    SDL_DestroyMutex(is->video_decoder_mutex);
1576 2046
}
......
1583 2053

  
1584 2054
    if (codec_type == CODEC_TYPE_VIDEO)
1585 2055
        start_index = is->video_stream;
1586
    else
2056
    else if (codec_type == CODEC_TYPE_AUDIO)
1587 2057
        start_index = is->audio_stream;
1588
    if (start_index < 0)
2058
    else
2059
        start_index = is->subtitle_stream;
2060
    if (start_index < (codec_type == CODEC_TYPE_SUBTITLE ? -1 : 0))
1589 2061
        return;
1590 2062
    stream_index = start_index;
1591 2063
    for(;;) {
1592 2064
        if (++stream_index >= is->ic->nb_streams)
1593
            stream_index = 0;
2065
        {
2066
            if (codec_type == CODEC_TYPE_SUBTITLE)
2067
            {
2068
                stream_index = -1;
2069
                goto the_end;
2070
            } else
2071
                stream_index = 0;
2072
        }
1594 2073
        if (stream_index == start_index)
1595 2074
            return;
1596 2075
        st = ic->streams[stream_index];
......
1603 2082
                    goto the_end;
1604 2083
                break;
1605 2084
            case CODEC_TYPE_VIDEO:
2085
            case CODEC_TYPE_SUBTITLE:
1606 2086
                goto the_end;
1607 2087
            default:
1608 2088
                break;
......
1709 2189
                if (cur_stream) 
1710 2190
                    stream_cycle_channel(cur_stream, CODEC_TYPE_VIDEO);
1711 2191
                break;
2192
            case SDLK_t:
2193
                if (cur_stream) 
2194
                    stream_cycle_channel(cur_stream, CODEC_TYPE_SUBTITLE);
2195
                break;
1712 2196
            case SDLK_w:
1713 2197
                toggle_audio_display();
1714 2198
                break;
......
1903 2387
           "p, SPC              pause\n"
1904 2388
           "a                   cycle audio channel\n"
1905 2389
           "v                   cycle video channel\n"
2390
           "t                   cycle subtitle channel\n"
1906 2391
           "w                   show audio waves\n"
1907 2392
           "left/right          seek backward/forward 10 seconds\n"
1908 2393
           "down/up             seek backward/forward 1 minute\n"

Also available in: Unified diff