History

subtitles support for ffplay patch by (Ian Caulfield, imc25 : cam ac uk)

Originally committed as revision 4521 to svn://svn.ffmpeg.org/ffmpeg/trunk

Ian Caulfield committed 21 years ago

Commit 72ce0531 parent bf01fb61 file · +491 −6Browse files

Unified · Split

ffplay.c+491−6
@@ -57,6 +57,7 @@ · 56 unmodified lines
57 57
58#define MAX_VIDEOQ_SIZE (5 * 256 * 1024)58#define MAX_VIDEOQ_SIZE (5 * 256 * 1024)
59#define MAX_AUDIOQ_SIZE (5 * 16 * 1024)59#define MAX_AUDIOQ_SIZE (5 * 16 * 1024)
60#define MAX_SUBTITLEQ_SIZE (5 * 16 * 1024)
60 61
61/* SDL audio buffer size, in samples. Should be small to have precise62/* SDL audio buffer size, in samples. Should be small to have precise
62 A/V sync as SDL does not have hardware buffer fullness info. */63 A/V sync as SDL does not have hardware buffer fullness info. */
@@ -86,6 +87,7 @@ typedef struct PacketQueue { · 23 unmodified lines
86} PacketQueue;87} PacketQueue;
87 88
88#define VIDEO_PICTURE_QUEUE_SIZE 189#define VIDEO_PICTURE_QUEUE_SIZE 1
90#define SUBPICTURE_QUEUE_SIZE 4
89 91
90typedef struct VideoPicture {92typedef struct VideoPicture {
91 double pts; /* presentation time stamp for this picture */93 double pts; /* presentation time stamp for this picture */
@@ -94,6 +96,11 @@ typedef struct VideoPicture { · 2 unmodified lines
94 int allocated;96 int allocated;
95} VideoPicture;97} VideoPicture;
96 98
99typedef struct SubPicture {
100 double pts; /* presentation time stamp for this picture */
101 AVSubtitle sub;
102} SubPicture;
103
97enum {104enum {
98 AV_SYNC_AUDIO_MASTER, /* default choice */105 AV_SYNC_AUDIO_MASTER, /* default choice */
99 AV_SYNC_VIDEO_MASTER,106 AV_SYNC_VIDEO_MASTER,
@@ -142,6 +149,16 @@ typedef struct VideoState { · 42 unmodified lines
142 int sample_array_index;149 int sample_array_index;
143 int last_i_start;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 double frame_timer;162 double frame_timer;
146 double frame_last_pts;163 double frame_last_pts;
147 double frame_last_delay;164 double frame_last_delay;
@@ -163,6 +180,7 @@ typedef struct VideoState { · 15 unmodified lines
163 180
164 SDL_mutex *video_decoder_mutex;181 SDL_mutex *video_decoder_mutex;
165 SDL_mutex *audio_decoder_mutex;182 SDL_mutex *audio_decoder_mutex;
183 SDL_mutex *subtitle_decoder_mutex;
166 184
167 // QETimer *video_timer;185 // QETimer *video_timer;
168 char filename[1024];186 char filename[1024];
@@ -371,12 +389,270 @@ void fill_border(VideoState *s, int x, int y, int w, int h, int color) · 202 unmodified lines
371}389}
372#endif390#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
439static 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
632static 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
374static void video_image_display(VideoState *is)647static void video_image_display(VideoState *is)
375{648{
376 VideoPicture *vp;649 VideoPicture *vp;
650 SubPicture *sp;
651 AVPicture pict;
377 float aspect_ratio;652 float aspect_ratio;
378 int width, height, x, y;653 int width, height, x, y;
379 SDL_Rect rect;654 SDL_Rect rect;
655 int i;
380 656
381 vp = &is->pictq[is->pictq_rindex];657 vp = &is->pictq[is->pictq_rindex];
382 if (vp->bmp) {658 if (vp->bmp) {
@@ -424,6 +700,33 @@ static void video_image_display(VideoState *is) · 41 unmodified lines
424 }700 }
425#endif701#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 /* XXX: we suppose the screen has a 1.0 pixel ratio */730 /* XXX: we suppose the screen has a 1.0 pixel ratio */
428 height = is->height;731 height = is->height;
429 width = ((int)rint(height * aspect_ratio)) & -3;732 width = ((int)rint(height * aspect_ratio)) & -3;
@@ -642,6 +945,7 @@ static void video_refresh_timer(void *opaque) · 212 unmodified lines
642 VideoPicture *vp;945 VideoPicture *vp;
643 double actual_delay, delay, sync_threshold, ref_clock, diff;946 double actual_delay, delay, sync_threshold, ref_clock, diff;
644 947
948 SubPicture *sp, *sp2;
645 949
646 if (is->video_st) {950 if (is->video_st) {
647 if (is->pictq_size == 0) {951 if (is->pictq_size == 0) {
@@ -702,6 +1006,50 @@ static void video_refresh_timer(void *opaque) · 54 unmodified lines
702 delay, actual_delay, vp->pts, -diff);1006 delay, actual_delay, vp->pts, -diff);
703#endif1007#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 /* display picture */1053 /* display picture */
706 video_display(is);1054 video_display(is);
707 1055
@@ -730,22 +1078,25 @@ static void video_refresh_timer(void *opaque) · 22 unmodified lines
730 if (show_status) {1078 if (show_status) {
731 static int64_t last_time;1079 static int64_t last_time;
732 int64_t cur_time;1080 int64_t cur_time;
733 int aqsize, vqsize;1081 int aqsize, vqsize, sqsize;
734 double av_diff;1082 double av_diff;
735 1083
736 cur_time = av_gettime();1084 cur_time = av_gettime();
737 if (!last_time || (cur_time - last_time) >= 500 * 1000) {1085 if (!last_time || (cur_time - last_time) >= 500 * 1000) {
738 aqsize = 0;1086 aqsize = 0;
739 vqsize = 0;1087 vqsize = 0;
1088 sqsize = 0;
740 if (is->audio_st)1089 if (is->audio_st)
741 aqsize = is->audioq.size;1090 aqsize = is->audioq.size;
742 if (is->video_st)1091 if (is->video_st)
743 vqsize = is->videoq.size;1092 vqsize = is->videoq.size;
1093 if (is->subtitle_st)
1094 sqsize = is->subtitleq.size;
744 av_diff = 0;1095 av_diff = 0;
745 if (is->audio_st && is->video_st)1096 if (is->audio_st && is->video_st)
746 av_diff = get_audio_clock(is) - get_video_clock(is);1097 av_diff = get_audio_clock(is) - get_video_clock(is);
747 printf("%7.2f A-V:%7.3f aq=%5dKB vq=%5dKB \r", 1098 printf("%7.2f A-V:%7.3f aq=%5dKB vq=%5dKB sq=%5dB \r",
748 get_master_clock(is), av_diff, aqsize / 1024, vqsize / 1024);1099 get_master_clock(is), av_diff, aqsize / 1024, vqsize / 1024, sqsize);
749 fflush(stdout);1100 fflush(stdout);
750 last_time = cur_time;1101 last_time = cur_time;
751 }1102 }
@@ -948,6 +1299,79 @@ static int video_thread(void *arg) · 196 unmodified lines
948 return 0;1299 return 0;
949}1300}
950 1301
1302static 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/* copy samples for viewing in editor window */1375/* copy samples for viewing in editor window */
952static void update_sample_display(VideoState *is, short *samples, int samples_size)1376static void update_sample_display(VideoState *is, short *samples, int samples_size)
953{1377{
@@ -1237,6 +1661,13 @@ static int stream_component_open(VideoState *is, int stream_index) · 283 unmodified lines
1237 packet_queue_init(&is->videoq);1661 packet_queue_init(&is->videoq);
1238 is->video_tid = SDL_CreateThread(video_thread, is);1662 is->video_tid = SDL_CreateThread(video_thread, is);
1239 break;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 default:1671 default:
1241 break;1672 break;
1242 }1673 }
@@ -1248,6 +1679,8 @@ static void stream_component_close(VideoState *is, int stream_index) · 5 unmodified lines
1248 AVFormatContext *ic = is->ic;1679 AVFormatContext *ic = is->ic;
1249 AVCodecContext *enc;1680 AVCodecContext *enc;
1250 1681
1682 if (stream_index < 0 || stream_index >= ic->nb_streams)
1683 return;
1251 enc = ic->streams[stream_index]->codec;1684 enc = ic->streams[stream_index]->codec;
1252 1685
1253 switch(enc->codec_type) {1686 switch(enc->codec_type) {
@@ -1271,6 +1704,21 @@ static void stream_component_close(VideoState *is, int stream_index) · 17 unmodified lines
1271 1704
1272 packet_queue_end(&is->videoq);1705 packet_queue_end(&is->videoq);
1273 break;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 default:1722 default:
1275 break;1723 break;
1276 }1724 }
@@ -1285,6 +1733,10 @@ static void stream_component_close(VideoState *is, int stream_index) · 8 unmodified lines
1285 is->video_st = NULL;1733 is->video_st = NULL;
1286 is->video_stream = -1;1734 is->video_stream = -1;
1287 break;1735 break;
1736 case CODEC_TYPE_SUBTITLE:
1737 is->subtitle_st = NULL;
1738 is->subtitle_stream = -1;
1739 break;
1288 default:1740 default:
1289 break;1741 break;
1290 }1742 }
@@ -1328,6 +1780,7 @@ static int decode_thread(void *arg) · 37 unmodified lines
1328 audio_index = -1;1780 audio_index = -1;
1329 is->video_stream = -1;1781 is->video_stream = -1;
1330 is->audio_stream = -1;1782 is->audio_stream = -1;
1783 is->subtitle_stream = -1;
1331 1784
1332 global_video_state = is;1785 global_video_state = is;
1333 url_set_interrupt_cb(decode_interrupt_cb);1786 url_set_interrupt_cb(decode_interrupt_cb);
@@ -1446,6 +1899,7 @@ static int decode_thread(void *arg) · 112 unmodified lines
1446 /* XXX: must lock decoder threads */1899 /* XXX: must lock decoder threads */
1447 SDL_LockMutex(is->video_decoder_mutex);1900 SDL_LockMutex(is->video_decoder_mutex);
1448 SDL_LockMutex(is->audio_decoder_mutex);1901 SDL_LockMutex(is->audio_decoder_mutex);
1902 SDL_LockMutex(is->subtitle_decoder_mutex);
1449 ret = av_seek_frame(is->ic, -1, is->seek_pos, is->seek_flags);1903 ret = av_seek_frame(is->ic, -1, is->seek_pos, is->seek_flags);
1450 if (ret < 0) {1904 if (ret < 0) {
1451 fprintf(stderr, "%s: error while seeking\n", is->ic->filename);1905 fprintf(stderr, "%s: error while seeking\n", is->ic->filename);
@@ -1453,11 +1907,15 @@ static int decode_thread(void *arg) · 1 unmodified line
1453 if (is->audio_stream >= 0) {1907 if (is->audio_stream >= 0) {
1454 packet_queue_flush(&is->audioq);1908 packet_queue_flush(&is->audioq);
1455 }1909 }
1910 if (is->subtitle_stream >= 0) {
1911 packet_queue_flush(&is->subtitleq);
1912 }
1456 if (is->video_stream >= 0) {1913 if (is->video_stream >= 0) {
1457 packet_queue_flush(&is->videoq);1914 packet_queue_flush(&is->videoq);
1458 avcodec_flush_buffers(ic->streams[video_index]->codec);1915 avcodec_flush_buffers(ic->streams[video_index]->codec);
1459 }1916 }
1460 }1917 }
1918 SDL_UnlockMutex(is->subtitle_decoder_mutex);
1461 SDL_UnlockMutex(is->audio_decoder_mutex);1919 SDL_UnlockMutex(is->audio_decoder_mutex);
1462 SDL_UnlockMutex(is->video_decoder_mutex);1920 SDL_UnlockMutex(is->video_decoder_mutex);
1463 is->seek_req = 0;1921 is->seek_req = 0;
@@ -1466,6 +1924,7 @@ static int decode_thread(void *arg) · 2 unmodified lines
1466 /* if the queue are full, no need to read more */1924 /* if the queue are full, no need to read more */
1467 if (is->audioq.size > MAX_AUDIOQ_SIZE ||1925 if (is->audioq.size > MAX_AUDIOQ_SIZE ||
1468 is->videoq.size > MAX_VIDEOQ_SIZE || 1926 is->videoq.size > MAX_VIDEOQ_SIZE ||
1927 is->subtitleq.size > MAX_SUBTITLEQ_SIZE ||
1469 url_feof(&ic->pb)) {1928 url_feof(&ic->pb)) {
1470 /* wait 10 ms */1929 /* wait 10 ms */
1471 SDL_Delay(10);1930 SDL_Delay(10);
@@ -1483,6 +1942,8 @@ static int decode_thread(void *arg) · 11 unmodified lines
1483 packet_queue_put(&is->audioq, pkt);1942 packet_queue_put(&is->audioq, pkt);
1484 } else if (pkt->stream_index == is->video_stream) {1943 } else if (pkt->stream_index == is->video_stream) {
1485 packet_queue_put(&is->videoq, pkt);1944 packet_queue_put(&is->videoq, pkt);
1945 } else if (pkt->stream_index == is->subtitle_stream) {
1946 packet_queue_put(&is->subtitleq, pkt);
1486 } else {1947 } else {
1487 av_free_packet(pkt);1948 av_free_packet(pkt);
1488 }1949 }
@@ -1502,6 +1963,8 @@ static int decode_thread(void *arg) · 13 unmodified lines
1502 stream_component_close(is, is->audio_stream);1963 stream_component_close(is, is->audio_stream);
1503 if (is->video_stream >= 0)1964 if (is->video_stream >= 0)
1504 stream_component_close(is, is->video_stream);1965 stream_component_close(is, is->video_stream);
1966 if (is->subtitle_stream >= 0)
1967 stream_component_close(is, is->subtitle_stream);
1505 if (is->ic) {1968 if (is->ic) {
1506 av_close_input_file(is->ic);1969 av_close_input_file(is->ic);
1507 is->ic = NULL; /* safety */1970 is->ic = NULL; /* safety */
@@ -1538,6 +2001,10 @@ static VideoState *stream_open(const char *filename, AVInputFormat *iformat) · 30 unmodified lines
1538 is->pictq_mutex = SDL_CreateMutex();2001 is->pictq_mutex = SDL_CreateMutex();
1539 is->pictq_cond = SDL_CreateCond();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 is->audio_decoder_mutex = SDL_CreateMutex();2008 is->audio_decoder_mutex = SDL_CreateMutex();
1542 is->video_decoder_mutex = SDL_CreateMutex();2009 is->video_decoder_mutex = SDL_CreateMutex();
1543 2010
@@ -1571,6 +2038,9 @@ static void stream_close(VideoState *is) · 27 unmodified lines
1571 }2038 }
1572 SDL_DestroyMutex(is->pictq_mutex);2039 SDL_DestroyMutex(is->pictq_mutex);
1573 SDL_DestroyCond(is->pictq_cond);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 SDL_DestroyMutex(is->audio_decoder_mutex);2044 SDL_DestroyMutex(is->audio_decoder_mutex);
1575 SDL_DestroyMutex(is->video_decoder_mutex);2045 SDL_DestroyMutex(is->video_decoder_mutex);
1576}2046}
@@ -1583,14 +2053,23 @@ void stream_cycle_channel(VideoState *is, int codec_type) · 6 unmodified lines
1583 2053
1584 if (codec_type == CODEC_TYPE_VIDEO)2054 if (codec_type == CODEC_TYPE_VIDEO)
1585 start_index = is->video_stream;2055 start_index = is->video_stream;
1586 else2056 else if (codec_type == CODEC_TYPE_AUDIO)
1587 start_index = is->audio_stream;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 return;2061 return;
1590 stream_index = start_index;2062 stream_index = start_index;
1591 for(;;) {2063 for(;;) {
1592 if (++stream_index >= is->ic->nb_streams)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 if (stream_index == start_index)2073 if (stream_index == start_index)
1595 return;2074 return;
1596 st = ic->streams[stream_index];2075 st = ic->streams[stream_index];
@@ -1603,6 +2082,7 @@ void stream_cycle_channel(VideoState *is, int codec_type) · 6 unmodified lines
1603 goto the_end;2082 goto the_end;
1604 break;2083 break;
1605 case CODEC_TYPE_VIDEO:2084 case CODEC_TYPE_VIDEO:
2085 case CODEC_TYPE_SUBTITLE:
1606 goto the_end;2086 goto the_end;
1607 default:2087 default:
1608 break;2088 break;
@@ -1709,6 +2189,10 @@ void event_loop(void) · 100 unmodified lines
1709 if (cur_stream) 2189 if (cur_stream)
1710 stream_cycle_channel(cur_stream, CODEC_TYPE_VIDEO);2190 stream_cycle_channel(cur_stream, CODEC_TYPE_VIDEO);
1711 break;2191 break;
2192 case SDLK_t:
2193 if (cur_stream)
2194 stream_cycle_channel(cur_stream, CODEC_TYPE_SUBTITLE);
2195 break;
1712 case SDLK_w:2196 case SDLK_w:
1713 toggle_audio_display();2197 toggle_audio_display();
1714 break;2198 break;
@@ -1903,6 +2387,7 @@ void show_help(void) · 188 unmodified lines
1903 "p, SPC pause\n"2387 "p, SPC pause\n"
1904 "a cycle audio channel\n"2388 "a cycle audio channel\n"
1905 "v cycle video channel\n"2389 "v cycle video channel\n"
2390 "t cycle subtitle channel\n"
1906 "w show audio waves\n"2391 "w show audio waves\n"
1907 "left/right seek backward/forward 10 seconds\n"2392 "left/right seek backward/forward 10 seconds\n"
1908 "down/up seek backward/forward 1 minute\n"2393 "down/up seek backward/forward 1 minute\n"

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t