FFmpeg
Loading...
Searching...
No Matches
ffplay.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2003 Fabrice Bellard
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21/**
22 * @file
23 * simple media player based on the FFmpeg libraries
24 */
25
26#include "config.h"
27#include "config_components.h"
28#include <math.h>
29#include <limits.h>
30#include <signal.h>
31#include <stdint.h>
32
34#include "libavutil/avstring.h"
37#include "libavutil/mem.h"
38#include "libavutil/pixdesc.h"
39#include "libavutil/dict.h"
40#include "libavutil/fifo.h"
42#include "libavutil/samplefmt.h"
43#include "libavutil/time.h"
44#include "libavutil/bprint.h"
45#include "libavcodec/bsf.h"
48#include "libswscale/swscale.h"
49#include "libavutil/opt.h"
50#include "libavutil/tx.h"
52
56
57#include <SDL.h>
58#include <SDL_thread.h>
59
60#include "cmdutils.h"
61#include "ffplay_renderer.h"
62#include "opt_common.h"
63
64const char program_name[] = "ffplay";
65const int program_birth_year = 2003;
66
67#define MAX_QUEUE_SIZE (15 * 1024 * 1024)
68#define MIN_FRAMES 25
69#define EXTERNAL_CLOCK_MIN_FRAMES 2
70#define EXTERNAL_CLOCK_MAX_FRAMES 10
71
72/* Minimum SDL audio buffer size, in samples. */
73#define SDL_AUDIO_MIN_BUFFER_SIZE 512
74/* Calculate actual buffer size keeping in mind not cause too frequent audio callbacks */
75#define SDL_AUDIO_MAX_CALLBACKS_PER_SEC 30
76
77/* Step size for volume control in dB */
78#define SDL_VOLUME_STEP (0.75)
79
80/* no AV sync correction is done if below the minimum AV sync threshold */
81#define AV_SYNC_THRESHOLD_MIN 0.04
82/* AV sync correction is done if above the maximum AV sync threshold */
83#define AV_SYNC_THRESHOLD_MAX 0.1
84/* If a frame duration is longer than this, it will not be duplicated to compensate AV sync */
85#define AV_SYNC_FRAMEDUP_THRESHOLD 0.1
86/* no AV correction is done if too big error */
87#define AV_NOSYNC_THRESHOLD 10.0
88
89/* maximum audio speed change to get correct sync */
90#define SAMPLE_CORRECTION_PERCENT_MAX 10
91
92/* external clock speed adjustment constants for realtime sources based on buffer fullness */
93#define EXTERNAL_CLOCK_SPEED_MIN 0.900
94#define EXTERNAL_CLOCK_SPEED_MAX 1.010
95#define EXTERNAL_CLOCK_SPEED_STEP 0.001
96
97/* we use about AUDIO_DIFF_AVG_NB A-V differences to make the average */
98#define AUDIO_DIFF_AVG_NB 20
99
100/* polls for possible required screen refresh at least this often, should be less than 1/fps */
101#define REFRESH_RATE 0.01
102
103/* NOTE: the size must be big enough to compensate the hardware audio buffersize size */
104/* TODO: We assume that a decoded and resampled frame fits into this buffer */
105#define SAMPLE_ARRAY_SIZE (8 * 65536)
106
107#define CURSOR_HIDE_DELAY 1000000
108
109#define CHAPTER_LIST_FADE_TIME 250000
110#define CHAPTER_LIST_HOLD_TIME 500000
111#define CHAPTER_LIST_ROWS 7
112
113enum {
120};
121
122typedef struct ChapterSortKey {
123 int key;
126
127typedef struct ChapterRow {
128 int index;
129 const char *artist;
130 const char *title;
132} ChapterRow;
133
134/* what lies under a window position: the row and the sort button, -1 for none, and whether it is inside the list at all */
135typedef struct ChapterListHit {
137 int row;
141
142/* a horizontal band of the chapter list bitmap, rendered on its own when its content changes */
143typedef struct ChapterStrip {
144 SDL_Rect rect;
145 const char *background;
146 char *script;
148
149#define USE_ONEPASS_SUBTITLE_RENDER 1
150
155
166
167#define VIDEO_PICTURE_QUEUE_SIZE 3
168#define SUBPICTURE_QUEUE_SIZE 16
169#define SAMPLE_QUEUE_SIZE 9
170#define FRAME_QUEUE_SIZE FFMAX(SAMPLE_QUEUE_SIZE, FFMAX(VIDEO_PICTURE_QUEUE_SIZE, SUBPICTURE_QUEUE_SIZE))
171
179
180typedef struct Clock {
181 double pts; /* clock base */
182 double pts_drift; /* clock base minus time at which we updated the clock */
184 double speed;
185 int serial; /* clock is based on a packet with this serial */
187 int *queue_serial; /* pointer to the current packet queue serial, used for obsolete clock detection */
188} Clock;
189
190typedef struct FrameData {
192} FrameData;
193
194/* Common struct for handling all types of decoded data and allocated render buffers. */
195typedef struct Frame {
199 double pts; /* presentation timestamp for the frame */
200 double duration; /* estimated duration of the frame */
201 int64_t pos; /* byte position of the frame in the input file */
202 int width;
208} Frame;
209
222
228
233
240
241enum {
242 AV_SYNC_AUDIO_MASTER, /* default choice */
244 AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */
245};
246
247typedef struct Decoder {
259 SDL_Thread *decoder_tid;
260} Decoder;
261
262typedef struct VideoState {
263 SDL_Thread *read_tid;
277
281
285
289
291
293
296 double audio_diff_cum; /* used for AV difference average computation */
303 uint8_t *audio_buf;
304 uint8_t *audio_buf1;
305 unsigned int audio_buf_size; /* in bytes */
306 unsigned int audio_buf1_size;
307 int audio_buf_index; /* in bytes */
310 int muted;
317
327 float *real_data;
329 int xpos;
332 SDL_Texture *vis_texture;
333 SDL_Texture *sub_texture;
334 SDL_Texture *vid_texture;
335 SDL_Texture *chapter_texture;
338 SDL_Rect chapter_rect;
357
361
368 double max_frame_duration; // maximum duration of a frame - above this, we consider the jump a timestamp discontinuity
370 int eof;
371
372 char *filename;
374 int step;
375
377 AVFilterContext *in_video_filter; // the first filter in the video chain
378 AVFilterContext *out_video_filter; // the last filter in the video chain
379 AVFilterContext *in_audio_filter; // the first filter in the audio chain
380 AVFilterContext *out_audio_filter; // the last filter in the audio chain
381 AVFilterGraph *agraph; // audio filter graph
382
384
386} VideoState;
387
388/* options specified by the user */
390static const char *input_filename;
391static const char *window_title;
392static int default_width = 640;
393static int default_height = 480;
394static int screen_width = 0;
395static int screen_height = 0;
396static int screen_left = SDL_WINDOWPOS_CENTERED;
397static int screen_top = SDL_WINDOWPOS_CENTERED;
398static int audio_disable;
399static int video_disable;
401static const char* wanted_stream_spec[AVMEDIA_TYPE_NB] = {0};
402static int seek_by_bytes = -1;
403static float seek_interval = 10;
405static int borderless;
406static int alwaysontop;
407static int startup_volume = 100;
408static int show_status = -1;
412static int fast = 0;
413static int genpts = 0;
414static int lowres = 0;
415static int decoder_reorder_pts = -1;
416static int autoexit;
419static int loop = 1;
420static int framedrop = -1;
421static int infinite_buffer = -1;
422static enum ShowMode show_mode = SHOW_MODE_NONE;
423/* the columns the chapter list is sorted by, the most recently clicked first */
427static const char *audio_codec_name;
428static const char *subtitle_codec_name;
429static const char *video_codec_name;
430double rdftspeed = 0.02;
432static int cursor_hidden = 0;
433static const char **vfilters_list = NULL;
434static int nb_vfilters = 0;
435static char *afilters = NULL;
436static int autorotate = 1;
437static int find_stream_info = 1;
438static int filter_nbthreads = 0;
439static int enable_vulkan = 0;
440static char *vulkan_params = NULL;
441static char *video_background = NULL;
442static const char *hwaccel = NULL;
443
444/* current context */
445static int is_full_screen;
447
448#define FF_QUIT_EVENT (SDL_USEREVENT + 2)
449
450static volatile sig_atomic_t received_sigterm = 0;
451static volatile int received_nb_signals = 0;
452static int exit_status = 0;
453
454static SDL_Window *window;
455static SDL_Renderer *renderer;
457static SDL_RendererInfo renderer_info = {0};
458static SDL_AudioDeviceID audio_dev;
459
461
466 { AV_PIX_FMT_RGB8, SDL_PIXELFORMAT_RGB332 },
467 { AV_PIX_FMT_RGB444, SDL_PIXELFORMAT_RGB444 },
468 { AV_PIX_FMT_RGB555, SDL_PIXELFORMAT_RGB555 },
469 { AV_PIX_FMT_BGR555, SDL_PIXELFORMAT_BGR555 },
470 { AV_PIX_FMT_RGB565, SDL_PIXELFORMAT_RGB565 },
471 { AV_PIX_FMT_BGR565, SDL_PIXELFORMAT_BGR565 },
472 { AV_PIX_FMT_RGB24, SDL_PIXELFORMAT_RGB24 },
473 { AV_PIX_FMT_BGR24, SDL_PIXELFORMAT_BGR24 },
474 { AV_PIX_FMT_0RGB32, SDL_PIXELFORMAT_RGB888 },
475 { AV_PIX_FMT_0BGR32, SDL_PIXELFORMAT_BGR888 },
476 { AV_PIX_FMT_NE(RGB0, 0BGR), SDL_PIXELFORMAT_RGBX8888 },
477 { AV_PIX_FMT_NE(BGR0, 0RGB), SDL_PIXELFORMAT_BGRX8888 },
478 { AV_PIX_FMT_RGB32, SDL_PIXELFORMAT_ARGB8888 },
479 { AV_PIX_FMT_RGB32_1, SDL_PIXELFORMAT_RGBA8888 },
480 { AV_PIX_FMT_BGR32, SDL_PIXELFORMAT_ABGR8888 },
481 { AV_PIX_FMT_BGR32_1, SDL_PIXELFORMAT_BGRA8888 },
482 { AV_PIX_FMT_YUV420P, SDL_PIXELFORMAT_IYUV },
483 { AV_PIX_FMT_YUYV422, SDL_PIXELFORMAT_YUY2 },
484 { AV_PIX_FMT_UYVY422, SDL_PIXELFORMAT_UYVY },
486
487static int opt_add_vfilter(void *optctx, const char *opt, const char *arg)
488{
490 if (ret < 0)
491 return ret;
492
494 if (!vfilters_list[nb_vfilters - 1])
495 return AVERROR(ENOMEM);
496
497 return 0;
498}
499
500static inline
501int cmp_audio_fmts(enum AVSampleFormat fmt1, int64_t channel_count1,
502 enum AVSampleFormat fmt2, int64_t channel_count2)
503{
504 /* If channel count == 1, planar and non-planar formats are the same */
505 if (channel_count1 == 1 && channel_count2 == 1)
507 else
508 return channel_count1 != channel_count2 || fmt1 != fmt2;
509}
510
512{
513 MyAVPacketList pkt1;
514 int ret;
515
516 if (q->abort_request)
517 return -1;
518
519
520 pkt1.pkt = pkt;
521 pkt1.serial = q->serial;
522
523 ret = av_fifo_write(q->pkt_list, &pkt1, 1);
524 if (ret < 0)
525 return ret;
526 q->nb_packets++;
527 q->size += pkt1.pkt->size + sizeof(pkt1);
528 q->duration += pkt1.pkt->duration;
529 /* XXX: should duplicate packet data in DV case */
530 SDL_CondSignal(q->cond);
531 return 0;
532}
533
535{
536 AVPacket *pkt1;
537 int ret;
538
539 pkt1 = av_packet_alloc();
540 if (!pkt1) {
542 return -1;
543 }
544 av_packet_move_ref(pkt1, pkt);
545
546 SDL_LockMutex(q->mutex);
547 ret = packet_queue_put_private(q, pkt1);
548 SDL_UnlockMutex(q->mutex);
549
550 if (ret < 0)
551 av_packet_free(&pkt1);
552
553 return ret;
554}
555
556static int packet_queue_put_nullpacket(PacketQueue *q, AVPacket *pkt, int stream_index)
557{
558 pkt->stream_index = stream_index;
559 return packet_queue_put(q, pkt);
560}
561
562/* packet queue handling */
564{
565 memset(q, 0, sizeof(PacketQueue));
567 if (!q->pkt_list)
568 return AVERROR(ENOMEM);
569 q->mutex = SDL_CreateMutex();
570 if (!q->mutex) {
571 av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError());
572 return AVERROR(ENOMEM);
573 }
574 q->cond = SDL_CreateCond();
575 if (!q->cond) {
576 av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError());
577 return AVERROR(ENOMEM);
578 }
579 q->abort_request = 1;
580 return 0;
581}
582
584{
585 MyAVPacketList pkt1;
586
587 SDL_LockMutex(q->mutex);
588 while (av_fifo_read(q->pkt_list, &pkt1, 1) >= 0)
589 av_packet_free(&pkt1.pkt);
590 q->nb_packets = 0;
591 q->size = 0;
592 q->duration = 0;
593 q->serial++;
594 SDL_UnlockMutex(q->mutex);
595}
596
598{
601 SDL_DestroyMutex(q->mutex);
602 SDL_DestroyCond(q->cond);
603}
604
606{
607 SDL_LockMutex(q->mutex);
608
609 q->abort_request = 1;
610
611 SDL_CondSignal(q->cond);
612
613 SDL_UnlockMutex(q->mutex);
614}
615
617{
618 SDL_LockMutex(q->mutex);
619 q->abort_request = 0;
620 q->serial++;
621 SDL_UnlockMutex(q->mutex);
622}
623
624/* return < 0 if aborted, 0 if no packet and > 0 if packet. */
625static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block, int *serial)
626{
627 MyAVPacketList pkt1;
628 int ret;
629
630 SDL_LockMutex(q->mutex);
631
632 for (;;) {
633 if (q->abort_request) {
634 ret = -1;
635 break;
636 }
637
638 if (av_fifo_read(q->pkt_list, &pkt1, 1) >= 0) {
639 q->nb_packets--;
640 q->size -= pkt1.pkt->size + sizeof(pkt1);
641 q->duration -= pkt1.pkt->duration;
643 if (serial)
644 *serial = pkt1.serial;
645 av_packet_free(&pkt1.pkt);
646 ret = 1;
647 break;
648 } else if (!block) {
649 ret = 0;
650 break;
651 } else {
652 SDL_CondWait(q->cond, q->mutex);
653 }
654 }
655 SDL_UnlockMutex(q->mutex);
656 return ret;
657}
658
659static int decoder_init(Decoder *d, AVCodecContext *avctx, PacketQueue *queue, SDL_cond *empty_queue_cond) {
660 memset(d, 0, sizeof(Decoder));
661 d->pkt = av_packet_alloc();
662 if (!d->pkt)
663 return AVERROR(ENOMEM);
664 d->avctx = avctx;
665 d->queue = queue;
666 d->empty_queue_cond = empty_queue_cond;
668 d->pkt_serial = -1;
669 return 0;
670}
671
673 int ret = AVERROR(EAGAIN);
674
675 for (;;) {
676 if (d->queue->serial == d->pkt_serial) {
677 do {
678 if (d->queue->abort_request)
679 return -1;
680
681 switch (d->avctx->codec_type) {
684 if (ret >= 0) {
685 if (decoder_reorder_pts == -1) {
686 frame->pts = frame->best_effort_timestamp;
687 } else if (!decoder_reorder_pts) {
688 frame->pts = frame->pkt_dts;
689 }
690 }
691 break;
694 if (ret >= 0) {
695 AVRational tb = (AVRational){1, frame->sample_rate};
696 if (frame->pts != AV_NOPTS_VALUE)
697 frame->pts = av_rescale_q(frame->pts, d->avctx->pkt_timebase, tb);
698 else if (d->next_pts != AV_NOPTS_VALUE)
699 frame->pts = av_rescale_q(d->next_pts, d->next_pts_tb, tb);
700 if (frame->pts != AV_NOPTS_VALUE) {
701 d->next_pts = frame->pts + frame->nb_samples;
702 d->next_pts_tb = tb;
703 }
704 }
705 break;
706 }
707 if (ret == AVERROR_EOF) {
708 d->finished = d->pkt_serial;
710 return 0;
711 }
712 if (ret >= 0)
713 return 1;
714 } while (ret != AVERROR(EAGAIN));
715 }
716
717 do {
718 if (d->queue->nb_packets == 0)
719 SDL_CondSignal(d->empty_queue_cond);
720 if (d->packet_pending) {
721 d->packet_pending = 0;
722 } else {
723 int old_serial = d->pkt_serial;
724 if (packet_queue_get(d->queue, d->pkt, 1, &d->pkt_serial) < 0)
725 return -1;
726 if (old_serial != d->pkt_serial) {
728 d->finished = 0;
729 d->next_pts = d->start_pts;
731 }
732 }
733 if (d->queue->serial == d->pkt_serial)
734 break;
736 } while (1);
737
739 int got_frame = 0;
740 ret = avcodec_decode_subtitle2(d->avctx, sub, &got_frame, d->pkt);
741 if (ret < 0) {
742 ret = AVERROR(EAGAIN);
743 } else {
744 if (got_frame && !d->pkt->data) {
745 d->packet_pending = 1;
746 }
747 ret = got_frame ? 0 : (d->pkt->data ? AVERROR(EAGAIN) : AVERROR_EOF);
748 }
750 } else {
751 if (d->pkt->buf && !d->pkt->opaque_ref) {
752 FrameData *fd;
753
754 d->pkt->opaque_ref = av_buffer_allocz(sizeof(*fd));
755 if (!d->pkt->opaque_ref)
756 return AVERROR(ENOMEM);
757 fd = (FrameData*)d->pkt->opaque_ref->data;
758 fd->pkt_pos = d->pkt->pos;
759 }
760
761 if (avcodec_send_packet(d->avctx, d->pkt) == AVERROR(EAGAIN)) {
762 av_log(d->avctx, AV_LOG_ERROR, "Receive_frame and send_packet both returned EAGAIN, which is an API violation.\n");
763 d->packet_pending = 1;
764 } else {
766 }
767 }
768 }
769}
770
771static void decoder_destroy(Decoder *d) {
772 av_packet_free(&d->pkt);
774}
775
777{
779 avsubtitle_free(&vp->sub);
780}
781
782static int frame_queue_init(FrameQueue *f, PacketQueue *pktq, int max_size, int keep_last)
783{
784 int i;
785 memset(f, 0, sizeof(FrameQueue));
786 if (!(f->mutex = SDL_CreateMutex())) {
787 av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError());
788 return AVERROR(ENOMEM);
789 }
790 if (!(f->cond = SDL_CreateCond())) {
791 av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError());
792 return AVERROR(ENOMEM);
793 }
794 f->pktq = pktq;
795 f->max_size = FFMIN(max_size, FRAME_QUEUE_SIZE);
796 f->keep_last = !!keep_last;
797 for (i = 0; i < f->max_size; i++)
798 if (!(f->queue[i].frame = av_frame_alloc()))
799 return AVERROR(ENOMEM);
800 return 0;
801}
802
804{
805 int i;
806 for (i = 0; i < f->max_size; i++) {
807 Frame *vp = &f->queue[i];
809 av_frame_free(&vp->frame);
810 }
811 SDL_DestroyMutex(f->mutex);
812 SDL_DestroyCond(f->cond);
813}
814
816{
817 SDL_LockMutex(f->mutex);
818 SDL_CondSignal(f->cond);
819 SDL_UnlockMutex(f->mutex);
820}
821
823{
824 return &f->queue[(f->rindex + f->rindex_shown) % f->max_size];
825}
826
828{
829 return &f->queue[(f->rindex + f->rindex_shown + 1) % f->max_size];
830}
831
833{
834 return &f->queue[f->rindex];
835}
836
838{
839 /* wait until we have space to put a new frame */
840 SDL_LockMutex(f->mutex);
841 while (f->size >= f->max_size &&
842 !f->pktq->abort_request) {
843 SDL_CondWait(f->cond, f->mutex);
844 }
845 SDL_UnlockMutex(f->mutex);
846
847 if (f->pktq->abort_request)
848 return NULL;
849
850 return &f->queue[f->windex];
851}
852
854{
855 /* wait until we have a readable a new frame */
856 SDL_LockMutex(f->mutex);
857 while (f->size - f->rindex_shown <= 0 &&
858 !f->pktq->abort_request) {
859 SDL_CondWait(f->cond, f->mutex);
860 }
861 SDL_UnlockMutex(f->mutex);
862
863 if (f->pktq->abort_request)
864 return NULL;
865
866 return &f->queue[(f->rindex + f->rindex_shown) % f->max_size];
867}
868
870{
871 if (++f->windex == f->max_size)
872 f->windex = 0;
873 SDL_LockMutex(f->mutex);
874 f->size++;
875 SDL_CondSignal(f->cond);
876 SDL_UnlockMutex(f->mutex);
877}
878
880{
881 if (f->keep_last && !f->rindex_shown) {
882 f->rindex_shown = 1;
883 return;
884 }
885 frame_queue_unref_item(&f->queue[f->rindex]);
886 if (++f->rindex == f->max_size)
887 f->rindex = 0;
888 SDL_LockMutex(f->mutex);
889 f->size--;
890 SDL_CondSignal(f->cond);
891 SDL_UnlockMutex(f->mutex);
892}
893
894/* return the number of undisplayed frames in the queue */
896{
897 return f->size - f->rindex_shown;
898}
899
900/* return last shown position */
902{
903 Frame *fp = &f->queue[f->rindex];
904 if (f->rindex_shown && fp->serial == f->pktq->serial)
905 return fp->pos;
906 else
907 return -1;
908}
909
910static void decoder_abort(Decoder *d, FrameQueue *fq)
911{
914 SDL_WaitThread(d->decoder_tid, NULL);
915 d->decoder_tid = NULL;
917}
918
919static inline void fill_rectangle(int x, int y, int w, int h)
920{
921 SDL_Rect rect;
922 rect.x = x;
923 rect.y = y;
924 rect.w = w;
925 rect.h = h;
926 if (w && h)
927 SDL_RenderFillRect(renderer, &rect);
928}
929
930static int realloc_texture(SDL_Texture **texture, Uint32 new_format, int new_width, int new_height, SDL_BlendMode blendmode, int init_texture)
931{
932 Uint32 format;
933 int access, w, h;
934 if (!*texture || SDL_QueryTexture(*texture, &format, &access, &w, &h) < 0 || new_width != w || new_height != h || new_format != format) {
935 void *pixels;
936 int pitch;
937 if (*texture)
938 SDL_DestroyTexture(*texture);
939 if (!(*texture = SDL_CreateTexture(renderer, new_format, SDL_TEXTUREACCESS_STREAMING, new_width, new_height)))
940 return -1;
941 if (SDL_SetTextureBlendMode(*texture, blendmode) < 0)
942 return -1;
943 if (init_texture) {
944 if (SDL_LockTexture(*texture, NULL, &pixels, &pitch) < 0)
945 return -1;
946 memset(pixels, 0, pitch * new_height);
947 SDL_UnlockTexture(*texture);
948 }
949 av_log(NULL, AV_LOG_VERBOSE, "Created %dx%d texture with %s.\n", new_width, new_height, SDL_GetPixelFormatName(new_format));
950 }
951 return 0;
952}
953
954static void calculate_display_rect(SDL_Rect *rect,
955 int scr_xleft, int scr_ytop, int scr_width, int scr_height,
956 int pic_width, int pic_height, AVRational pic_sar)
957{
958 AVRational aspect_ratio = pic_sar;
959 int64_t width, height, x, y;
960
961 if (av_cmp_q(aspect_ratio, av_make_q(0, 1)) <= 0)
962 aspect_ratio = av_make_q(1, 1);
963
964 aspect_ratio = av_mul_q(aspect_ratio, av_make_q(pic_width, pic_height));
965
966 /* XXX: we suppose the screen has a 1.0 pixel ratio */
967 height = scr_height;
968 width = av_rescale(height, aspect_ratio.num, aspect_ratio.den) & ~1;
969 if (width > scr_width) {
970 width = scr_width;
971 height = av_rescale(width, aspect_ratio.den, aspect_ratio.num) & ~1;
972 }
973 x = (scr_width - width) / 2;
974 y = (scr_height - height) / 2;
975 rect->x = scr_xleft + x;
976 rect->y = scr_ytop + y;
977 rect->w = FFMAX((int)width, 1);
978 rect->h = FFMAX((int)height, 1);
979}
980
981static void get_sdl_pix_fmt_and_blendmode(int format, Uint32 *sdl_pix_fmt, SDL_BlendMode *sdl_blendmode)
982{
983 int i;
984 *sdl_blendmode = SDL_BLENDMODE_NONE;
985 *sdl_pix_fmt = SDL_PIXELFORMAT_UNKNOWN;
986 if (format == AV_PIX_FMT_RGB32 ||
990 *sdl_blendmode = SDL_BLENDMODE_BLEND;
991 for (i = 0; i < FF_ARRAY_ELEMS(sdl_texture_format_map); i++) {
993 *sdl_pix_fmt = sdl_texture_format_map[i].texture_fmt;
994 return;
995 }
996 }
997}
998
999static int upload_texture(SDL_Texture **tex, AVFrame *frame)
1000{
1001 int ret = 0;
1002 Uint32 sdl_pix_fmt;
1003 SDL_BlendMode sdl_blendmode;
1004 get_sdl_pix_fmt_and_blendmode(frame->format, &sdl_pix_fmt, &sdl_blendmode);
1005 if (realloc_texture(tex, sdl_pix_fmt == SDL_PIXELFORMAT_UNKNOWN ? SDL_PIXELFORMAT_ARGB8888 : sdl_pix_fmt, frame->width, frame->height, sdl_blendmode, 0) < 0)
1006 return -1;
1007 switch (sdl_pix_fmt) {
1008 case SDL_PIXELFORMAT_IYUV:
1009 if (frame->linesize[0] > 0 && frame->linesize[1] > 0 && frame->linesize[2] > 0) {
1010 ret = SDL_UpdateYUVTexture(*tex, NULL, frame->data[0], frame->linesize[0],
1011 frame->data[1], frame->linesize[1],
1012 frame->data[2], frame->linesize[2]);
1013 } else if (frame->linesize[0] < 0 && frame->linesize[1] < 0 && frame->linesize[2] < 0) {
1014 ret = SDL_UpdateYUVTexture(*tex, NULL, frame->data[0] + frame->linesize[0] * (frame->height - 1), -frame->linesize[0],
1015 frame->data[1] + frame->linesize[1] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[1],
1016 frame->data[2] + frame->linesize[2] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[2]);
1017 } else {
1018 av_log(NULL, AV_LOG_ERROR, "Mixed negative and positive linesizes are not supported.\n");
1019 return -1;
1020 }
1021 break;
1022 default:
1023 if (frame->linesize[0] < 0) {
1024 ret = SDL_UpdateTexture(*tex, NULL, frame->data[0] + frame->linesize[0] * (frame->height - 1), -frame->linesize[0]);
1025 } else {
1026 ret = SDL_UpdateTexture(*tex, NULL, frame->data[0], frame->linesize[0]);
1027 }
1028 break;
1029 }
1030 return ret;
1031}
1032
1038
1043
1045{
1046#if SDL_VERSION_ATLEAST(2,0,8)
1047 SDL_YUV_CONVERSION_MODE mode = SDL_YUV_CONVERSION_AUTOMATIC;
1048 if (frame && (frame->format == AV_PIX_FMT_YUV420P || frame->format == AV_PIX_FMT_YUYV422 || frame->format == AV_PIX_FMT_UYVY422)) {
1049 if (frame->color_range == AVCOL_RANGE_JPEG)
1050 mode = SDL_YUV_CONVERSION_JPEG;
1051 else if (frame->colorspace == AVCOL_SPC_BT709)
1052 mode = SDL_YUV_CONVERSION_BT709;
1053 else if (frame->colorspace == AVCOL_SPC_BT470BG || frame->colorspace == AVCOL_SPC_SMPTE170M)
1054 mode = SDL_YUV_CONVERSION_BT601;
1055 }
1056 SDL_SetYUVConversionMode(mode); /* FIXME: no support for linear transfer */
1057#endif
1058}
1059
1061{
1062 const int tile_size = VIDEO_BACKGROUND_TILE_SIZE;
1063 SDL_Rect *rect = &is->render_params.target_rect;
1064 SDL_BlendMode blendMode;
1065
1066 if (!SDL_GetTextureBlendMode(is->vid_texture, &blendMode) && blendMode == SDL_BLENDMODE_BLEND) {
1067 switch (is->render_params.video_background_type) {
1069 SDL_SetRenderDrawColor(renderer, 237, 237, 237, 255);
1070 fill_rectangle(rect->x, rect->y, rect->w, rect->h);
1071 SDL_SetRenderDrawColor(renderer, 222, 222, 222, 255);
1072 for (int x = 0; x < rect->w; x += tile_size * 2)
1073 fill_rectangle(rect->x + x, rect->y, FFMIN(tile_size, rect->w - x), rect->h);
1074 for (int y = 0; y < rect->h; y += tile_size * 2)
1075 fill_rectangle(rect->x, rect->y + y, rect->w, FFMIN(tile_size, rect->h - y));
1076 SDL_SetRenderDrawColor(renderer, 237, 237, 237, 255);
1077 for (int y = 0; y < rect->h; y += tile_size * 2) {
1078 int h = FFMIN(tile_size, rect->h - y);
1079 for (int x = 0; x < rect->w; x += tile_size * 2)
1080 fill_rectangle(x + rect->x, y + rect->y, FFMIN(tile_size, rect->w - x), h);
1081 }
1082 break;
1084 const uint8_t *c = is->render_params.video_background_color;
1085 SDL_SetRenderDrawColor(renderer, c[0], c[1], c[2], c[3]);
1086 fill_rectangle(rect->x, rect->y, rect->w, rect->h);
1087 break;
1088 }
1090 SDL_SetTextureBlendMode(is->vid_texture, SDL_BLENDMODE_NONE);
1091 break;
1092 }
1093 }
1094}
1095
1096static int current_chapter(VideoState *is);
1097static void seek_chapter(VideoState *is, int i);
1098
1100{
1101 double alpha = (now - is->chapter_fade_start) / (double)CHAPTER_LIST_FADE_TIME;
1102
1103 if (!is->chapter_bitmap)
1104 return 0;
1105 if (!is->chapter_pinned)
1106 alpha = FFMIN(alpha, 1 - (now - is->chapter_last_input - CHAPTER_LIST_HOLD_TIME) / (double)CHAPTER_LIST_FADE_TIME);
1107 return av_clipd(alpha, 0, 1);
1108}
1109
1110static const char *chapter_tag(const AVChapter *chapter, const char *key)
1111{
1112 const AVDictionaryEntry *tag = av_dict_get(chapter->metadata, key, NULL, 0);
1113
1114 return tag ? tag->value : "";
1115}
1116
1117/* case-insensitive, with missing tags after all others */
1118static int compare_tags(const char *a, const char *b)
1119{
1120 return !*a != !*b ? !*a - !*b : av_strcasecmp(a, b);
1121}
1122
1123/* the rank of a chapter in the shuffled order for the current seed */
1124static uint32_t shuffle_rank(int index)
1125{
1126 uint32_t rank = (index + 1) * 0x9E3779B1u ^ chapter_shuffle_seed * 0x85EBCA77u;
1127
1128 rank ^= rank >> 15;
1129 rank *= 0x2C1B3C6Du;
1130 return rank ^ rank >> 12;
1131}
1132
1133static int compare_chapter_rows(const void *a, const void *b)
1134{
1135 const ChapterRow *ra = a, *rb = b;
1136
1137 for (int i = 0; i < CHAPTER_SORT_NB; i++) {
1138 int cmp;
1139
1140 switch (chapter_sort[i].key) {
1141 case CHAPTER_SORT_ARTIST: cmp = compare_tags(ra->artist, rb->artist); break;
1142 case CHAPTER_SORT_TITLE: cmp = compare_tags(ra->title, rb->title); break;
1143 case CHAPTER_SORT_LENGTH: cmp = FFDIFFSIGN(ra->length, rb->length); break;
1144 case CHAPTER_SORT_SHUFFLE: cmp = FFDIFFSIGN(shuffle_rank(ra->index), shuffle_rank(rb->index)); break;
1145 default: cmp = ra->index - rb->index; break;
1146 }
1147 if (cmp)
1148 return chapter_sort[i].descending ? -cmp : cmp;
1149 }
1150 return 0;
1151}
1152
1153/* a column clicked again flips its order, any other becomes the first key ahead of the previous ones;
1154 * the shuffle button instead steps its seed by the side it was clicked on */
1155static void chapter_sort_by(int key, int seed_step)
1156{
1157 int i = 0;
1158
1159 while (chapter_sort[i].key != key)
1160 i++;
1162 chapter_shuffle_seed += seed_step;
1163 else if (i == 0)
1164 chapter_sort[0].descending ^= 1;
1165 if (i == 0)
1166 return;
1167 memmove(&chapter_sort[1], &chapter_sort[0], i * sizeof(*chapter_sort));
1168 chapter_sort[0] = (ChapterSortKey){ key, 0 };
1169}
1170
1171/* rebuilds the rows matching the search in the current sort order, keeping the selected chapter selected */
1173{
1174 int selected = is->nb_chapter_rows ? is->chapter_rows[is->chapter_selected].index : 0;
1175 ChapterRow *rows = av_realloc_array(is->chapter_rows, is->ic->nb_chapters, sizeof(*rows));
1176
1177 if (!rows)
1178 return AVERROR(ENOMEM);
1179 is->chapter_rows = rows;
1180 is->nb_chapter_rows = 0;
1181 for (int i = 0; i < is->ic->nb_chapters; i++) {
1182 AVChapter *chapter = is->ic->chapters[i];
1183 ChapterRow row = { i, chapter_tag(chapter, "artist"), chapter_tag(chapter, "title"), -1 };
1184
1185 if (chapter->end != AV_NOPTS_VALUE && chapter->end > chapter->start &&
1186 (uint64_t)chapter->end - chapter->start <= INT64_MAX)
1187 row.length = av_rescale_q(chapter->end - chapter->start, chapter->time_base, AV_TIME_BASE_Q);
1188 if (av_stristr(row.artist, is->chapter_search) || av_stristr(row.title, is->chapter_search))
1189 is->chapter_rows[is->nb_chapter_rows++] = row;
1190 }
1191 qsort(is->chapter_rows, is->nb_chapter_rows, sizeof(*is->chapter_rows), compare_chapter_rows);
1192 is->chapter_selected = 0;
1193 for (int row = 0; row < is->nb_chapter_rows; row++)
1194 if (is->chapter_rows[row].index == selected)
1195 is->chapter_selected = row;
1196 return 0;
1197}
1198
1199static const struct {
1200 const char *label;
1203 [CHAPTER_SORT_NUMBER] = { "#", 5 },
1204 [CHAPTER_SORT_ARTIST] = { "Artist", 8 },
1205 [CHAPTER_SORT_TITLE] = { "Title", 7 },
1206 [CHAPTER_SORT_LENGTH] = { "Duration", 10 },
1207 [CHAPTER_SORT_SHUFFLE] = { "Shuffle", 14 },
1209
1210#define CHAPTER_LIST_EVENT "Dialogue: 0:00:00.00,9999:00:00.00,"
1211
1212static void bprint_chapter_box(AVBPrint *script, const char *style, int x, int y, int w, int h)
1213{
1214 av_bprintf(script, CHAPTER_LIST_EVENT "%s,{\\pos(%d,%d)\\p1}m 0 0 l %d 0 %d %d 0 %d{\\p0}\n", style, x, y, w, w, h, h);
1215}
1216
1217/* a text cell cut off at the right and bottom of its column, with the characters libass would read as tags or line breaks blanked */
1218static void bprint_chapter_cell(AVBPrint *script, const char *style, int x, int y, int right, int bottom, const char *text)
1219{
1220 av_bprintf(script, CHAPTER_LIST_EVENT "%s,{\\pos(%d,%d)\\clip(0,0,%d,%d)}", style, x, y, right, bottom);
1221 for (; *text; text++)
1222 av_bprint_chars(script, strchr("{}\\\r\n", *text) ? ' ' : *text, 1);
1223 av_bprint_chars(script, '\n', 1);
1224}
1225
1231
1232/* button widths are in half font sizes, a quarter apart, wrapping onto further lines when the panel is too narrow */
1234{
1236 int x, y;
1237
1238 l.font = FFMAX(is->height / 30, 12);
1239 l.line = l.font * 9 / 4;
1240 l.width = FFMIN(FFMAX(is->width * 3 / 5, l.font * 26), is->width - l.font * 2);
1241 x = y = l.font / 2;
1242 for (int b = 0; b < CHAPTER_SORT_NB; b++) {
1243 int w = sort_buttons[b].width * l.font / 2;
1244
1245 if (x > l.font / 2 && x + w > l.width - l.font / 2) {
1246 x = l.font / 2;
1247 y += l.font * 3 / 2;
1248 }
1249 l.button_x[b] = x;
1250 l.button_y[b] = y;
1251 x += w + l.font / 4;
1252 }
1253 /* the search field follows the buttons, or takes its own line when they leave it less than 8 em */
1254 if (x + l.font * 8 > l.width - l.font / 2) {
1255 x = l.font / 2;
1256 y += l.font * 3 / 2;
1257 }
1258 l.search_x = x;
1259 l.search_y = y;
1260 l.rows_y = is->chapter_pinned ? y + l.font * 3 / 2 : l.button_y[CHAPTER_SORT_NB - 1] + l.font * 3 / 2;
1261 l.canvas_h = FFMIN(y + l.font * 2 + CHAPTER_LIST_ROWS * l.line, is->height - l.font * 2);
1262 l.strip_h = FFMAX(l.line, y + l.font * 3 / 2);
1263 l.nb_rows = FFMIN(is->nb_chapter_rows, FFMAX(1, (l.canvas_h - l.rows_y - l.font / 2) / l.line));
1264 l.first = av_clip(is->chapter_selected - l.nb_rows / 2, 0, is->nb_chapter_rows - l.nb_rows);
1265 l.height = l.rows_y + l.nb_rows * l.line + l.font / 2;
1266 l.text_x = l.font * 3;
1267 l.text_right = l.width - l.font * 11 / 2;
1268 l.length_x = l.width - l.font * 5 / 2;
1269 l.detail_x = l.width - l.font * 5 / 4;
1270 l.canvas_w = is->width - l.font * 2;
1271 return l;
1272}
1273
1275{
1276 ChapterListHit hit = { 0, -1, -1, 0 };
1277 int line;
1278
1279 x -= l->font;
1280 y -= l->font;
1281 if (x < 0 || y < 0 || x >= l->width || y >= FFMIN(l->height, l->canvas_h))
1282 return hit;
1283 hit.inside = 1;
1284 line = (y - l->rows_y) / l->line;
1285 if (y >= l->rows_y && line < l->nb_rows) {
1286 hit.row = l->first + line;
1287 hit.detail = x >= l->width - l->font * 2;
1288 }
1289 for (int b = 0; b < FF_ARRAY_ELEMS(sort_buttons); b++)
1290 if (x >= l->button_x[b] && x < l->button_x[b] + sort_buttons[b].width * l->font / 2 &&
1291 y >= l->button_y[b] && y < l->button_y[b] + l->font * 5 / 4)
1292 hit.button = b;
1293 return hit;
1294}
1295
1296/* a circle outline drawn as four bezier arcs around a center */
1297static void bprint_chapter_ring(AVBPrint *script, int cx, int cy, int r)
1298{
1299 int k = r * 552 / 1000;
1300
1301 av_bprintf(script, CHAPTER_LIST_EVENT "Ring,{\\an5\\pos(%d,%d)\\p1}m 0 %d b 0 %d %d 0 %d 0 b %d 0 %d %d %d %d "
1302 "b %d %d %d %d %d %d b %d %d 0 %d 0 %d{\\p0}\n",
1303 cx, cy, r, r - k, r - k, r, r + k, 2 * r, r - k, 2 * r, r, 2 * r, r + k, r + k, 2 * r, r, 2 * r,
1304 r - k, 2 * r, r + k, r);
1305}
1306
1307/* strip backgrounds, with premultiplied alpha as the ass filter composites */
1308static const char chapter_panel_color[] = "0x000000BF";
1309static const char chapter_hover_color[] = "0x373737CD";
1310static const char chapter_popup_color[] = "0x000000DF";
1311
1312static void bprint_chapter_styles(AVBPrint *script, const ChapterListLayout *l)
1313{
1314 av_bprintf(script,
1315 "[Script Info]\nScriptType: v4.00+\nPlayResX: %d\nPlayResY: %d\nWrapStyle: 2\nYCbCr Matrix: None\n\n"
1316 "[V4+ Styles]\n"
1317 "Format: Name, Fontname, Fontsize, PrimaryColour, OutlineColour, Bold, Outline, Alignment\n"
1318 "Style: Button,Sans,%d,&H80FFFFFF,&H80FFFFFF,0,0,7\n"
1319 "Style: Row,Sans,%d,&H00FFFFFF,&H00000000,0,%d,7\n"
1320 "Style: Selected,Sans,%d,&H0080D0FF,&H00000000,-1,%d,7\n"
1321 "Style: Artist,Sans,%d,&H00C0C0C0,&H00000000,0,%d,7\n"
1322 "Style: ArtistSelected,Sans,%d,&H0080D0FF,&H00000000,-1,%d,7\n"
1323 "Style: Playing,Sans,%d,&H00FFFFFF,&H00FFFFFF,0,0,7\n"
1324 "Style: Hint,Sans,%d,&H00A0A0A0,&H00000000,0,%d,7\n"
1325 "Style: ButtonHover,Sans,%d,&H50FFFFFF,&H50FFFFFF,0,0,7\n"
1326 "Style: Ring,Sans,%d,&HFF000000,&H00A0A0A0,0,%d,7\n"
1327 "Style: Detail,Sans,%d,&H00FFFFFF,&H00000000,0,%d,7\n\n"
1328 "[Events]\nFormat: Start, End, Style, Text\n",
1329 l->canvas_w, l->strip_h, l->font, l->font, l->font / 16 + 1, l->font, l->font / 16 + 1,
1330 l->font * 4 / 5, l->font / 16 + 1, l->font * 4 / 5, l->font / 16 + 1, l->font, l->font, l->font / 16 + 1,
1331 l->font, l->font, l->font / 16 + 1, l->font * 4 / 5, l->font / 16 + 1);
1332}
1333
1334static void bprint_chapter_header_strip(VideoState *is, AVBPrint *script, const ChapterListLayout *l)
1335{
1336 if (is->chapter_pinned)
1337 bprint_chapter_cell(script, *is->chapter_search ? "Row" : "Hint", l->search_x, l->search_y, l->length_x,
1338 l->search_y + l->font * 3 / 2, *is->chapter_search ? is->chapter_search : "type to search");
1339 for (int b = 0; b < FF_ARRAY_ELEMS(sort_buttons); b++) {
1340 int x = l->button_x[b], y = l->button_y[b], w = sort_buttons[b].width * l->font / 2;
1341
1342 bprint_chapter_box(script, b == is->chapter_hover.button ? "ButtonHover" : "Button", x, y, w, l->font * 5 / 4);
1343 av_bprintf(script, CHAPTER_LIST_EVENT "%s,{\\an5\\pos(%d,%d)}", chapter_sort[0].key == b ? "Selected" : "Row",
1344 x + w / 2, y + l->font * 5 / 8);
1345 if (b == CHAPTER_SORT_SHUFFLE)
1346 av_bprintf(script, "\xe2\x97\x82 %s %d \xe2\x96\xb8\n", sort_buttons[b].label, chapter_shuffle_seed);
1347 else
1348 av_bprintf(script, "%s%s\n", sort_buttons[b].label,
1349 chapter_sort[0].key != b ? "" : chapter_sort[0].descending ? " \xe2\x96\xbc" : " \xe2\x96\xb2");
1350 }
1351}
1352
1353static void bprint_chapter_row_strip(VideoState *is, AVBPrint *script, const ChapterListLayout *l, int r)
1354{
1355 const ChapterRow *row = &is->chapter_rows[r];
1356 const char *style = r == is->chapter_selected ? "Selected" : "Row";
1357 int64_t seconds;
1358
1359 if (row->index == is->chapter_playing)
1360 bprint_chapter_box(script, "Playing", 0, 0, l->font / 6, l->line);
1361 av_bprintf(script, CHAPTER_LIST_EVENT "%s,{\\an6\\pos(%d,%d)}%d\n", style, l->font * 5 / 2, l->line / 2, row->index + 1);
1362 bprint_chapter_cell(script, style, l->text_x, l->font / 8, l->text_right, l->line, row->title);
1363 bprint_chapter_cell(script, r == is->chapter_selected ? "ArtistSelected" : "Artist", l->text_x, l->font * 5 / 4,
1364 l->text_right, l->line, row->artist);
1365 bprint_chapter_ring(script, l->detail_x, l->line / 2, l->font * 9 / 20);
1366 av_bprintf(script, CHAPTER_LIST_EVENT "Hint,{\\an5\\pos(%d,%d)}i\n", l->detail_x, l->line / 2);
1367 if (row->length < 0)
1368 return;
1370 av_bprintf(script, CHAPTER_LIST_EVENT "%s,{\\an6\\pos(%d,%d)}", style, l->length_x, l->line / 2);
1371 if (seconds >= 3600)
1372 av_bprintf(script, "%"PRId64":%02d:%02d\n", seconds / 3600, (int)(seconds / 60 % 60), (int)(seconds % 60));
1373 else
1374 av_bprintf(script, "%d:%02d\n", (int)(seconds / 60), (int)(seconds % 60));
1375}
1376
1377static int chapter_strip_add(ChapterStrip **strips, int *nb, SDL_Rect rect, const char *background, const AVBPrint *script)
1378{
1379 if (rect.w <= 0 || rect.h <= 0)
1380 return 0;
1381 if (!av_bprint_is_complete(script))
1382 return AVERROR(ENOMEM);
1383 if (!(*nb & (*nb - 1))) {
1384 ChapterStrip *grown = av_realloc_array(*strips, *nb ? 2 * *nb : 1, sizeof(**strips));
1385
1386 if (!grown)
1387 return AVERROR(ENOMEM);
1388 *strips = grown;
1389 }
1390 (*strips)[*nb] = (ChapterStrip){ rect, background, av_strdup(script->str) };
1391 if (!(*strips)[*nb].script)
1392 return AVERROR(ENOMEM);
1393 (*nb)++;
1394 return 0;
1395}
1396
1397/* the strips the list consists of right now: the header, each visible row, the bottom padding and the lines of the metadata
1398 * popup, beside the list or over its rows when the window leaves no room there */
1399static int chapter_list_strips(VideoState *is, const ChapterListLayout *l, ChapterStrip **strips, int *nb)
1400{
1401 AVBPrint script;
1402 int ret = 0;
1403
1405 is->chapter_playing = current_chapter(is);
1406 for (int i = 0; ret >= 0 && i < l->nb_rows + 2; i++) {
1407 int row = i && i <= l->nb_rows ? l->first + i - 1 : -1;
1408 SDL_Rect rect = { 0, i ? l->rows_y + (i - 1) * l->line : 0, l->width, i ? l->line : l->rows_y };
1409
1410 if (i > l->nb_rows)
1411 rect.h = l->font / 2;
1412 rect.h = FFMIN(rect.h, l->canvas_h - rect.y);
1413 av_bprint_clear(&script);
1414 bprint_chapter_styles(&script, l);
1415 if (!i)
1416 bprint_chapter_header_strip(is, &script, l);
1417 else if (row >= 0)
1418 bprint_chapter_row_strip(is, &script, l, row);
1419 ret = chapter_strip_add(strips, nb, rect, row >= 0 && row == is->chapter_hover.row ? chapter_hover_color : chapter_panel_color, &script);
1420 }
1421 if (ret >= 0 && is->chapter_hover.detail) {
1422 const AVDictionary *metadata = is->ic->chapters[is->chapter_rows[is->chapter_hover.row].index]->metadata;
1424 int beside = l->canvas_w - l->width >= l->font * 12;
1425 int height = FFMIN(av_dict_count(metadata) * l->font + l->font / 2, l->canvas_h);
1426 int x = beside ? l->width + l->font / 2 : l->text_x;
1427 int right = beside ? l->canvas_w : l->length_x - l->font / 2;
1428 int y = av_clip(l->rows_y + (is->chapter_hover.row - l->first) * l->line, 0, l->canvas_h - height);
1429
1430 /* the descenders of a line reach into the line below, so each line's strip also draws the line above it */
1431 for (int top = 0; ret >= 0 && top < height && (above || tag); top += l->font) {
1432 const AVDictionaryEntry *lines[2] = { above, tag };
1433 SDL_Rect rect = { x, y + top, right - x, FFMIN(l->font, height - top) };
1434
1435 av_bprint_clear(&script);
1436 bprint_chapter_styles(&script, l);
1437 for (int i = 0; i < 2; i++) {
1438 if (!lines[i])
1439 continue;
1440 bprint_chapter_cell(&script, "Detail", x + l->font / 2, l->font / 4 + (i - 1) * l->font, x + l->font * 7, rect.h,
1441 lines[i]->key);
1442 bprint_chapter_cell(&script, "Detail", x + l->font * 15 / 2, l->font / 4 + (i - 1) * l->font, right - l->font / 4,
1443 rect.h, lines[i]->value);
1444 }
1445 ret = chapter_strip_add(strips, nb, rect, chapter_popup_color, &script);
1446 above = tag;
1448 }
1449 }
1450 av_bprint_finalize(&script, NULL);
1451 return ret;
1452}
1453
1454static void chapter_strips_free(ChapterStrip **strips, int *nb)
1455{
1456 for (int i = 0; i < *nb; i++)
1457 av_freep(&(*strips)[i].script);
1458 av_freep(strips);
1459 *nb = 0;
1460}
1461
1463{
1464 avfilter_graph_free(&is->chapter_graph);
1465 av_freep(&is->chapter_bitmap);
1466 chapter_strips_free(&is->chapter_strips, &is->nb_chapter_strips);
1467 if (is->chapter_texture)
1468 SDL_DestroyTexture(is->chapter_texture);
1469 is->chapter_texture = NULL;
1470}
1471
1472/* a graph rendering one strip of the bitmap at a time, the bitmap itself and the texture it is uploaded to */
1473static int chapter_list_configure(VideoState *is, const ChapterListLayout *l, const SDL_Rect *canvas)
1474{
1475 const AVFilter *ass_filter = avfilter_get_by_name("ass");
1476 AVFilterContext *source, *ass;
1477 char source_args[64];
1478 int ret;
1479
1480 if (!ass_filter) {
1481 static int reported;
1482
1483 if (!reported++)
1484 av_log(NULL, AV_LOG_ERROR, "The chapter list needs the ass filter, which this build lacks\n");
1486 }
1488 is->chapter_rect = *canvas;
1489 if (l->canvas_w <= 0 || l->canvas_h <= 0 || l->canvas_w > INT_MAX / 4 / l->canvas_h)
1490 return AVERROR(EINVAL);
1491 if (!(is->chapter_graph = avfilter_graph_alloc()) ||
1492 !(is->chapter_bitmap = av_mallocz(l->canvas_w * l->canvas_h * 4)))
1493 return AVERROR(ENOMEM);
1494 if (realloc_texture(&is->chapter_texture, SDL_PIXELFORMAT_ARGB8888, l->canvas_w, l->canvas_h, SDL_BLENDMODE_BLEND, 0) < 0)
1495 return AVERROR_EXTERNAL;
1496 is->chapter_dirty = (SDL_Rect){ 0, 0, l->canvas_w, l->canvas_h };
1497 snprintf(source_args, sizeof(source_args), "color=black@0:rate=1:size=%dx%d", l->canvas_w, l->strip_h);
1498 ass = avfilter_graph_alloc_filter(is->chapter_graph, ass_filter, "ass");
1499 is->chapter_sink = avfilter_graph_alloc_filter(is->chapter_graph, avfilter_get_by_name("buffersink"), "sink");
1500 if (!ass || !is->chapter_sink)
1501 return AVERROR(ENOMEM);
1502 if ((ret = avfilter_graph_create_filter(&source, avfilter_get_by_name("color"), "source", source_args, NULL, is->chapter_graph)) < 0 ||
1503 (ret = av_opt_set(ass, "script", "[Script Info]\nScriptType: v4.00+\n", AV_OPT_SEARCH_CHILDREN)) < 0 ||
1504 (ret = av_opt_set_int(ass, "alpha", 1, AV_OPT_SEARCH_CHILDREN)) < 0 ||
1505 (ret = avfilter_init_str(ass, NULL)) < 0 ||
1506 (ret = av_opt_set_array(is->chapter_sink, "pixel_formats", AV_OPT_SEARCH_CHILDREN, 0, 1, AV_OPT_TYPE_PIXEL_FMT,
1507 &(enum AVPixelFormat){ AV_PIX_FMT_RGB32 })) < 0 ||
1508 (ret = avfilter_init_str(is->chapter_sink, NULL)) < 0 ||
1509 (ret = avfilter_link(source, 0, ass, 0)) < 0 ||
1510 (ret = avfilter_link(ass, 0, is->chapter_sink, 0)) < 0)
1511 return ret;
1512 return avfilter_graph_config(is->chapter_graph, NULL);
1513}
1514
1515/* renders the strip, the ass filter composing it over its background, and writes it into the bitmap */
1517{
1520 uint32_t scale[256] = { 1 << 16 };
1521 int ret;
1522
1523 if (!frame)
1524 return AVERROR(ENOMEM);
1525 for (int a = 1; a < 256; a++)
1526 scale[a] = ((255 << 16) + a - 1) / a;
1527 if ((ret = avfilter_graph_send_command(is->chapter_graph, "source", "color", strip->background, NULL, 0, 0)) >= 0 &&
1528 (ret = avfilter_graph_send_command(is->chapter_graph, "ass", "script", strip->script, NULL, 0, 0)) >= 0)
1529 ret = av_buffersink_get_frame(is->chapter_sink, frame);
1530 /* the ass filter composites with premultiplied alpha, SDL blends straight alpha */
1531 for (int y = 0; ret >= 0 && y < strip->rect.h; y++) {
1532 const uint8_t *src = frame->data[0] + y * frame->linesize[0] + strip->rect.x * 4;
1533 uint8_t *dst = is->chapter_bitmap + ((strip->rect.y + y) * is->chapter_rect.w + strip->rect.x) * 4;
1534
1535 for (int x = 0; x < strip->rect.w * 4; x += 4)
1536 for (int c = 0; c < 4; c++)
1537 dst[x + c] = c == alpha ? src[x + c] : FFMIN(src[x + c] * scale[src[x + alpha]] >> 16, 255);
1538 }
1540 return ret;
1541}
1542
1543static void chapter_bitmap_touched(VideoState *is, const SDL_Rect *rect)
1544{
1545 SDL_UnionRect(&is->chapter_dirty, rect, &is->chapter_dirty);
1546 is->force_refresh = 1;
1547}
1548
1549/* moves the pixels and strips of the rows that stay visible when the list scrolls, so that only the rows scrolling in are
1550 * rendered; rows the popup covered hold popup pixels and are rendered anew, as is that part of the popup */
1551static void chapter_list_scroll(VideoState *is, const ChapterListLayout *l, const ChapterStrip *strips, int nb)
1552{
1553 int shift = is->chapter_first - l->first, kept = l->nb_rows - FFABS(shift);
1554 SDL_Rect block = { 0, l->rows_y, l->width, l->nb_rows * l->line }, popup = { 0, 0, 0, 0 };
1555
1556 if (!shift || kept <= 0 || is->nb_chapter_strips <= l->nb_rows || nb <= l->nb_rows)
1557 return;
1558 ChapterStrip *rows = is->chapter_strips + 1;
1559 for (int j = 0; j < l->nb_rows; j++) {
1560 SDL_Rect slot = { 0, block.y + j * l->line, l->width, l->line };
1561
1562 if (!SDL_RectEquals(&rows[j].rect, &slot) || !SDL_RectEquals(&strips[j + 1].rect, &slot))
1563 return;
1564 }
1565 for (int i = 0; i < is->nb_chapter_strips; i++) {
1566 if (is->chapter_strips[i].background == chapter_popup_color && SDL_HasIntersection(&is->chapter_strips[i].rect, &block)) {
1567 SDL_UnionRect(&popup, &is->chapter_strips[i].rect, &popup);
1568 is->chapter_strips[i].background = NULL;
1569 }
1570 }
1571 for (int j = 0; j < l->nb_rows; j++)
1572 if (SDL_HasIntersection(&rows[j].rect, &popup))
1573 rows[j].background = NULL;
1574 for (int k = 0; k < kept * l->line; k++) {
1575 int y = shift > 0 ? block.y + block.h - 1 - k : block.y + k;
1576
1577 memcpy(is->chapter_bitmap + y * is->chapter_rect.w * 4, is->chapter_bitmap + (y - shift * l->line) * is->chapter_rect.w * 4,
1578 l->width * 4);
1579 }
1580 for (int j = 0; j < FFABS(shift); j++)
1581 av_freep(&rows[shift > 0 ? kept + j : j].script);
1582 memmove(rows + FFMAX(shift, 0), rows + FFMAX(-shift, 0), kept * sizeof(*rows));
1583 for (int j = 0; j < FFABS(shift); j++)
1584 rows[shift > 0 ? j : kept + j] = (ChapterStrip){ { 0 } };
1585 for (int j = 0; j < l->nb_rows; j++)
1586 rows[j].rect = strips[j + 1].rect;
1588}
1589
1590/* brings the bitmap up to date, rendering only the strips whose content, place or background changed */
1592{
1594 SDL_Rect canvas = { l.font, l.font, l.canvas_w, l.canvas_h }, redrawn = { 0, 0, 0, 0 };
1595 ChapterStrip *strips = NULL;
1596 int nb = 0, ret = 0;
1597
1598 is->chapter_render_pending = 0;
1599 is->chapter_hover = chapter_list_hit(is, &l, is->chapter_mouse_x, is->chapter_mouse_y);
1600 if (!is->chapter_graph || !SDL_RectEquals(&is->chapter_rect, &canvas))
1601 ret = chapter_list_configure(is, &l, &canvas);
1602 if (ret >= 0)
1603 ret = chapter_list_strips(is, &l, &strips, &nb);
1604 if (ret >= 0)
1605 chapter_list_scroll(is, &l, strips, nb);
1606 /* what the strips no longer cover becomes transparent again; a strip is drawn anew when it changed or lies on what was
1607 * cleared or drawn before it */
1608 for (int i = 0; ret >= 0 && i < is->nb_chapter_strips; i++) {
1609 const SDL_Rect *old = &is->chapter_strips[i].rect;
1610
1611 if (i < nb && SDL_RectEquals(old, &strips[i].rect))
1612 continue;
1613 for (int y = 0; y < old->h; y++)
1614 memset(is->chapter_bitmap + ((old->y + y) * is->chapter_rect.w + old->x) * 4, 0, old->w * 4);
1615 SDL_UnionRect(&redrawn, old, &redrawn);
1617 }
1618 for (int i = 0; ret >= 0 && i < nb; i++) {
1619 const ChapterStrip *old = i < is->nb_chapter_strips ? &is->chapter_strips[i] : NULL;
1620
1621 if (old && SDL_RectEquals(&old->rect, &strips[i].rect) && old->background == strips[i].background &&
1622 !strcmp(old->script, strips[i].script) && !SDL_HasIntersection(&strips[i].rect, &redrawn))
1623 continue;
1624 if ((ret = chapter_strip_render(is, &strips[i])) < 0)
1625 break;
1626 SDL_UnionRect(&redrawn, &strips[i].rect, &redrawn);
1627 chapter_bitmap_touched(is, &strips[i].rect);
1628 }
1629 if (ret < 0) {
1630 if (ret != AVERROR_FILTER_NOT_FOUND)
1631 av_log(NULL, AV_LOG_ERROR, "Could not render the chapter list: %s\n", av_err2str(ret));
1633 chapter_strips_free(&strips, &nb);
1634 is->chapter_pinned = 0;
1635 SDL_StopTextInput();
1636 }
1637 chapter_strips_free(&is->chapter_strips, &is->nb_chapter_strips);
1638 is->chapter_strips = strips;
1639 is->nb_chapter_strips = nb;
1640 is->chapter_first = l.first;
1641 return ret;
1642}
1643
1644static void chapter_list_select(VideoState *is, int row)
1645{
1647
1648 is->chapter_selected = row;
1649 is->chapter_fade_start = now - chapter_list_alpha(is, now) * CHAPTER_LIST_FADE_TIME;
1650 is->chapter_last_input = now;
1651 is->chapter_render_pending = 1;
1652}
1653
1654/* shows the list with the chapter selected, or with the selection kept when no row shows it */
1655static int chapter_list_show(VideoState *is, int chapter)
1656{
1657 int ret = renderer ? chapter_list_update_rows(is) : AVERROR(EINVAL);
1658
1659 if (ret < 0)
1660 return ret;
1661 for (int row = 0; row < is->nb_chapter_rows; row++)
1662 if (is->chapter_rows[row].index == chapter)
1663 is->chapter_selected = row;
1664 chapter_list_select(is, is->chapter_selected);
1665 return 0;
1666}
1667
1669{
1670 if (is->nb_chapter_rows)
1671 chapter_list_select(is, av_clip(is->chapter_selected + delta, 0, is->nb_chapter_rows - 1));
1672}
1673
1675{
1676 return is->chapter_pinned || chapter_list_alpha(is, av_gettime_relative()) > 0;
1677}
1678
1679/* appends the typed text to the search, or erases its last character when nothing was typed */
1680static void chapter_list_search(VideoState *is, const char *typed)
1681{
1682 int len = strlen(is->chapter_search);
1683
1684 if (typed) {
1685 if (len + strlen(typed) < sizeof(is->chapter_search))
1686 av_strlcat(is->chapter_search, typed, sizeof(is->chapter_search));
1687 } else if (len) {
1688 while (len > 0 && (is->chapter_search[--len] & 0xC0) == 0x80)
1689 ;
1690 is->chapter_search[len] = 0;
1691 }
1693 is->chapter_render_pending = 1;
1694}
1695
1696static void chapter_list_pin(VideoState *is, int pinned)
1697{
1698 if (!renderer)
1699 return;
1700 is->chapter_pinned = pinned;
1701 if (pinned) {
1702 is->chapter_pinned = chapter_list_show(is, current_chapter(is)) >= 0;
1703 if (is->chapter_pinned)
1704 SDL_StartTextInput();
1705 } else {
1706 SDL_StopTextInput();
1707 is->chapter_last_input = av_gettime_relative() - CHAPTER_LIST_HOLD_TIME;
1708 is->chapter_search[0] = 0;
1710 is->chapter_render_pending = 1;
1711 }
1712}
1713
1714/* keys while the list is pinned; typed characters arrive as text input instead */
1715static void chapter_list_key(VideoState *is, SDL_Keycode key)
1716{
1717 switch (key) {
1718 case SDLK_ESCAPE: chapter_list_pin(is, 0); break;
1719 case SDLK_UP: chapter_list_move(is, -1); break;
1720 case SDLK_DOWN: chapter_list_move(is, 1); break;
1721 case SDLK_PAGEUP: seek_chapter(is, current_chapter(is) + 1); break;
1722 case SDLK_PAGEDOWN: seek_chapter(is, current_chapter(is) - 1); break;
1723 case SDLK_BACKSPACE: chapter_list_search(is, NULL); break;
1724 case SDLK_RETURN:
1725 case SDLK_KP_ENTER:
1726 if (is->nb_chapter_rows)
1727 seek_chapter(is, is->chapter_rows[is->chapter_selected].index);
1728 break;
1729 }
1730}
1731
1732/* keeps the mouse position for the next render and asks for one when what a visible list points at changed;
1733 * the render waits until the pending events are handled, so a sweep across the list renders once */
1734static void chapter_list_hover(VideoState *is, int x, int y)
1735{
1737 ChapterListHit hit;
1738
1739 is->chapter_mouse_x = x;
1740 is->chapter_mouse_y = y;
1742 return;
1744 hit = chapter_list_hit(is, &l, x, y);
1745 if (hit.row != is->chapter_hover.row || hit.button != is->chapter_hover.button || hit.detail != is->chapter_hover.detail)
1746 is->chapter_render_pending = 1;
1747}
1748
1749/* seeks to the entry under a click or sorts by the button under it, returns whether the click hit the list at all */
1750static int chapter_list_click(VideoState *is, int x, int y)
1751{
1753 ChapterListHit hit = chapter_list_hit(is, &l, x, y);
1754
1755 if (hit.row >= 0 && !hit.detail)
1756 seek_chapter(is, is->chapter_rows[hit.row].index);
1757 if (hit.button >= 0) {
1758 int button_w = sort_buttons[hit.button].width * l.font / 2;
1759
1760 chapter_sort_by(hit.button, (x - l.font - l.button_x[hit.button]) * 2 < button_w ? -1 : 1);
1761 chapter_list_show(is, -1);
1762 }
1763 return hit.inside;
1764}
1765
1766/* uploads what the texture lacks of the bitmap, at most once per refresh */
1768{
1770 SDL_Rect *dirty = &is->chapter_dirty;
1771
1772 is->chapter_drawn_alpha = alpha;
1773 if (alpha <= 0)
1774 return;
1775 if (dirty->w && !SDL_UpdateTexture(is->chapter_texture, dirty,
1776 is->chapter_bitmap + (dirty->y * is->chapter_rect.w + dirty->x) * 4, is->chapter_rect.w * 4))
1777 *dirty = (SDL_Rect){ 0, 0, 0, 0 };
1778 SDL_SetTextureAlphaMod(is->chapter_texture, alpha * 255);
1779 SDL_RenderCopy(renderer, is->chapter_texture, NULL, &is->chapter_rect);
1780}
1781
1783{
1784 Frame *vp;
1785 Frame *sp = NULL;
1786 SDL_Rect *rect = &is->render_params.target_rect;
1787
1788 vp = frame_queue_peek_last(&is->pictq);
1789 calculate_display_rect(rect, is->xleft, is->ytop, is->width, is->height, vp->width, vp->height, vp->sar);
1790 if (vk_renderer) {
1791 vk_renderer_display(vk_renderer, vp->frame, &is->render_params);
1792 return;
1793 }
1794
1795 if (is->subtitle_st) {
1796 if (frame_queue_nb_remaining(&is->subpq) > 0) {
1797 sp = frame_queue_peek(&is->subpq);
1798
1799 if (vp->pts >= sp->pts + ((float) sp->sub.start_display_time / 1000)) {
1800 if (!sp->uploaded) {
1801 uint8_t* pixels[4];
1802 int pitch[4];
1803 int i;
1804 if (!sp->width || !sp->height) {
1805 sp->width = vp->width;
1806 sp->height = vp->height;
1807 }
1808 if (realloc_texture(&is->sub_texture, SDL_PIXELFORMAT_ARGB8888, sp->width, sp->height, SDL_BLENDMODE_BLEND, 1) < 0)
1809 return;
1810
1811 for (i = 0; i < sp->sub.num_rects; i++) {
1812 AVSubtitleRect *sub_rect = sp->sub.rects[i];
1813
1814 sub_rect->x = av_clip(sub_rect->x, 0, sp->width );
1815 sub_rect->y = av_clip(sub_rect->y, 0, sp->height);
1816 sub_rect->w = av_clip(sub_rect->w, 0, sp->width - sub_rect->x);
1817 sub_rect->h = av_clip(sub_rect->h, 0, sp->height - sub_rect->y);
1818
1819 is->sub_convert_ctx = sws_getCachedContext(is->sub_convert_ctx,
1820 sub_rect->w, sub_rect->h, AV_PIX_FMT_PAL8,
1821 sub_rect->w, sub_rect->h, AV_PIX_FMT_BGRA,
1822 0, NULL, NULL, NULL);
1823 if (!is->sub_convert_ctx) {
1824 av_log(NULL, AV_LOG_FATAL, "Cannot initialize the conversion context\n");
1825 return;
1826 }
1827 if (!SDL_LockTexture(is->sub_texture, (SDL_Rect *)sub_rect, (void **)pixels, pitch)) {
1828 sws_scale(is->sub_convert_ctx, (const uint8_t * const *)sub_rect->data, sub_rect->linesize,
1829 0, sub_rect->h, pixels, pitch);
1830 SDL_UnlockTexture(is->sub_texture);
1831 }
1832 }
1833 sp->uploaded = 1;
1834 }
1835 } else
1836 sp = NULL;
1837 }
1838 }
1839
1841
1842 if (!vp->uploaded) {
1843 if (upload_texture(&is->vid_texture, vp->frame) < 0) {
1845 return;
1846 }
1847 vp->uploaded = 1;
1848 vp->flip_v = vp->frame->linesize[0] < 0;
1849 }
1850
1852 SDL_RenderCopyEx(renderer, is->vid_texture, NULL, rect, 0, NULL, vp->flip_v ? SDL_FLIP_VERTICAL : 0);
1854 if (sp) {
1855#if USE_ONEPASS_SUBTITLE_RENDER
1856 SDL_RenderCopy(renderer, is->sub_texture, NULL, rect);
1857#else
1858 int i;
1859 double xratio = (double)rect->w / (double)sp->width;
1860 double yratio = (double)rect->h / (double)sp->height;
1861 for (i = 0; i < sp->sub.num_rects; i++) {
1862 SDL_Rect *sub_rect = (SDL_Rect*)sp->sub.rects[i];
1863 SDL_Rect target = {.x = rect.x + sub_rect->x * xratio,
1864 .y = rect.y + sub_rect->y * yratio,
1865 .w = sub_rect->w * xratio,
1866 .h = sub_rect->h * yratio};
1867 SDL_RenderCopy(renderer, is->sub_texture, sub_rect, &target);
1868 }
1869#endif
1870 }
1871}
1872
1873static inline int compute_mod(int a, int b)
1874{
1875 return a < 0 ? a%b + b : a%b;
1876}
1877
1879{
1880 int i, i_start, x, y1, y, ys, delay, n, nb_display_channels;
1881 int ch, channels, h, h2;
1882 int64_t time_diff;
1883 int rdft_bits, nb_freq;
1884
1885 for (rdft_bits = 1; (1 << rdft_bits) < 2 * s->height; rdft_bits++)
1886 ;
1887 nb_freq = 1 << (rdft_bits - 1);
1888
1889 /* compute display index : center on currently output samples */
1890 channels = s->audio_tgt.ch_layout.nb_channels;
1891 nb_display_channels = channels;
1892 if (!s->paused) {
1893 int data_used= s->show_mode == SHOW_MODE_WAVES ? s->width : (2*nb_freq);
1894 n = 2 * channels;
1895 delay = s->audio_write_buf_size;
1896 delay /= n;
1897
1898 /* to be more precise, we take into account the time spent since
1899 the last buffer computation */
1900 if (audio_callback_time) {
1902 delay -= (time_diff * s->audio_tgt.freq) / 1000000;
1903 }
1904
1905 delay += 2 * data_used;
1906 if (delay < data_used)
1907 delay = data_used;
1908
1909 i_start= x = compute_mod(s->sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE);
1910 if (s->show_mode == SHOW_MODE_WAVES) {
1911 h = INT_MIN;
1912 for (i = 0; i < 1000; i += channels) {
1913 int idx = (SAMPLE_ARRAY_SIZE + x - i) % SAMPLE_ARRAY_SIZE;
1914 int a = s->sample_array[idx];
1915 int b = s->sample_array[(idx + 4 * channels) % SAMPLE_ARRAY_SIZE];
1916 int c = s->sample_array[(idx + 5 * channels) % SAMPLE_ARRAY_SIZE];
1917 int d = s->sample_array[(idx + 9 * channels) % SAMPLE_ARRAY_SIZE];
1918 int score = a - d;
1919 if (h < score && (b ^ c) < 0) {
1920 h = score;
1921 i_start = idx;
1922 }
1923 }
1924 }
1925
1926 s->last_i_start = i_start;
1927 } else {
1928 i_start = s->last_i_start;
1929 }
1930
1931 if (s->show_mode == SHOW_MODE_WAVES) {
1932 SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
1933
1934 /* total height for one channel */
1935 h = s->height / nb_display_channels;
1936 /* graph height / 2 */
1937 h2 = (h * 9) / 20;
1938 for (ch = 0; ch < nb_display_channels; ch++) {
1939 i = i_start + ch;
1940 y1 = s->ytop + ch * h + (h / 2); /* position of center line */
1941 for (x = 0; x < s->width; x++) {
1942 y = (s->sample_array[i] * h2) >> 15;
1943 if (y < 0) {
1944 y = -y;
1945 ys = y1 - y;
1946 } else {
1947 ys = y1;
1948 }
1949 fill_rectangle(s->xleft + x, ys, 1, y);
1950 i += channels;
1951 if (i >= SAMPLE_ARRAY_SIZE)
1953 }
1954 }
1955
1956 SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
1957
1958 for (ch = 1; ch < nb_display_channels; ch++) {
1959 y = s->ytop + ch * h;
1960 fill_rectangle(s->xleft, y, s->width, 1);
1961 }
1962 } else {
1963 int err = 0;
1964 if (realloc_texture(&s->vis_texture, SDL_PIXELFORMAT_ARGB8888, s->width, s->height, SDL_BLENDMODE_NONE, 1) < 0)
1965 return;
1966
1967 if (s->xpos >= s->width)
1968 s->xpos = 0;
1969 nb_display_channels= FFMIN(nb_display_channels, 2);
1970 if (rdft_bits != s->rdft_bits) {
1971 const float rdft_scale = 1.0;
1972 av_tx_uninit(&s->rdft);
1973 av_freep(&s->real_data);
1974 av_freep(&s->rdft_data);
1975 s->rdft_bits = rdft_bits;
1976 s->real_data = av_malloc_array(nb_freq, 4 *sizeof(*s->real_data));
1977 s->rdft_data = av_malloc_array(nb_freq + 1, 2 *sizeof(*s->rdft_data));
1978 err = av_tx_init(&s->rdft, &s->rdft_fn, AV_TX_FLOAT_RDFT,
1979 0, 1 << rdft_bits, &rdft_scale, 0);
1980 }
1981 if (err < 0 || !s->rdft_data) {
1982 av_log(NULL, AV_LOG_ERROR, "Failed to allocate buffers for RDFT, switching to waves display\n");
1983 s->show_mode = SHOW_MODE_WAVES;
1984 } else {
1985 float *data_in[2];
1986 AVComplexFloat *data[2];
1987 SDL_Rect rect = {.x = s->xpos, .y = 0, .w = 1, .h = s->height};
1988 uint32_t *pixels;
1989 int pitch;
1990 for (ch = 0; ch < nb_display_channels; ch++) {
1991 data_in[ch] = s->real_data + 2 * nb_freq * ch;
1992 data[ch] = s->rdft_data + nb_freq * ch;
1993 i = i_start + ch;
1994 for (x = 0; x < 2 * nb_freq; x++) {
1995 double w = (x-nb_freq) * (1.0 / nb_freq);
1996 data_in[ch][x] = s->sample_array[i] * (1.0 - w * w);
1997 i += channels;
1998 if (i >= SAMPLE_ARRAY_SIZE)
2000 }
2001 s->rdft_fn(s->rdft, data[ch], data_in[ch], sizeof(float));
2002 data[ch][0].im = data[ch][nb_freq].re;
2003 data[ch][nb_freq].re = 0;
2004 }
2005 /* Least efficient way to do this, we should of course
2006 * directly access it but it is more than fast enough. */
2007 if (!SDL_LockTexture(s->vis_texture, &rect, (void **)&pixels, &pitch)) {
2008 pitch >>= 2;
2009 pixels += pitch * s->height;
2010 for (y = 0; y < s->height; y++) {
2011 double w = 1 / sqrt(nb_freq);
2012 int a = sqrt(w * sqrt(data[0][y].re * data[0][y].re + data[0][y].im * data[0][y].im));
2013 int b = (nb_display_channels == 2 ) ? sqrt(w * hypot(data[1][y].re, data[1][y].im))
2014 : a;
2015 a = FFMIN(a, 255);
2016 b = FFMIN(b, 255);
2017 pixels -= pitch;
2018 *pixels = (a << 16) + (b << 8) + ((a+b) >> 1);
2019 }
2020 SDL_UnlockTexture(s->vis_texture);
2021 }
2022 SDL_RenderCopy(renderer, s->vis_texture, NULL, NULL);
2023 }
2024 if (!s->paused)
2025 s->xpos++;
2026 }
2027}
2028
2029static void uninit_bsf_graph(AVFormatContext *ic, int stream_index)
2030{
2031 FormatContext *ici = ic->opaque;
2032 Stream *sti;
2033 StreamGroup *stgi;
2034
2035 if (stream_index >= ici->nb_streams)
2036 return;
2037
2038 sti = ici->streams[stream_index];
2039 sti->filter = NULL;
2040
2041 stgi = sti->group;
2042 if (stgi) {
2043 av_bsf_graph_free(&stgi->graph);
2044 stgi->sink = NULL;
2045
2046 for (int i = 0; i < stgi->stg->nb_entries; i++) {
2047 ici->streams[stgi->stg->entries[i]->stream->index]->filter = NULL;
2048 ici->streams[stgi->stg->entries[i]->stream->index]->group = NULL;
2049 }
2050 }
2051 sti->group = stgi;
2052}
2053
2054static void stream_component_close(VideoState *is, int stream_index)
2055{
2056 AVFormatContext *ic = is->ic;
2057
2058 AVCodecParameters *codecpar;
2059
2060 if (stream_index < 0 || stream_index >= ic->nb_streams)
2061 return;
2062 codecpar = ic->streams[stream_index]->codecpar;
2063
2064 uninit_bsf_graph(ic, stream_index);
2065
2066 switch (codecpar->codec_type) {
2067 case AVMEDIA_TYPE_AUDIO:
2068 decoder_abort(&is->auddec, &is->sampq);
2069 SDL_CloseAudioDevice(audio_dev);
2070 decoder_destroy(&is->auddec);
2071 swr_free(&is->swr_ctx);
2072 av_freep(&is->audio_buf1);
2073 is->audio_buf1_size = 0;
2074 is->audio_buf = NULL;
2075
2076 if (is->rdft) {
2077 av_tx_uninit(&is->rdft);
2078 av_freep(&is->real_data);
2079 av_freep(&is->rdft_data);
2080 is->rdft = NULL;
2081 is->rdft_bits = 0;
2082 }
2083 break;
2084 case AVMEDIA_TYPE_VIDEO:
2085 decoder_abort(&is->viddec, &is->pictq);
2086 decoder_destroy(&is->viddec);
2087 break;
2089 decoder_abort(&is->subdec, &is->subpq);
2090 decoder_destroy(&is->subdec);
2091 break;
2092 default:
2093 break;
2094 }
2095
2096 ic->streams[stream_index]->discard = AVDISCARD_ALL;
2097 switch (codecpar->codec_type) {
2098 case AVMEDIA_TYPE_AUDIO:
2099 is->audio_st = NULL;
2100 is->audio_stream = -1;
2101 break;
2102 case AVMEDIA_TYPE_VIDEO:
2103 is->video_st = NULL;
2104 is->video_stream = -1;
2105 break;
2107 is->subtitle_st = NULL;
2108 is->subtitle_stream = -1;
2109 break;
2110 default:
2111 break;
2112 }
2113}
2114
2116{
2117 /* XXX: use a special url_shutdown call to abort parse cleanly */
2118 is->abort_request = 1;
2119 SDL_WaitThread(is->read_tid, NULL);
2120
2121 /* close each stream */
2122 if (is->audio_stream >= 0)
2123 stream_component_close(is, is->audio_stream);
2124 if (is->video_stream >= 0)
2125 stream_component_close(is, is->video_stream);
2126 if (is->subtitle_stream >= 0)
2127 stream_component_close(is, is->subtitle_stream);
2128
2129 if (is->ic) {
2130 FormatContext *ici = is->ic->opaque;
2131 for (int i = 0; i < ici->nb_streams; i++)
2132 av_freep(&ici->streams[i]);
2133 av_freep(&ici->streams);
2134 for (int i = 0; i < ici->nb_stream_groups; i++)
2135 av_freep(&ici->stream_groups[i]);
2136 av_freep(&ici->stream_groups);
2137 av_freep(&is->ic->opaque);
2138 }
2139
2141
2142 packet_queue_destroy(&is->videoq);
2143 packet_queue_destroy(&is->audioq);
2144 packet_queue_destroy(&is->subtitleq);
2145
2146 /* free all pictures */
2147 frame_queue_destroy(&is->pictq);
2148 frame_queue_destroy(&is->sampq);
2149 frame_queue_destroy(&is->subpq);
2150 SDL_DestroyCond(is->continue_read_thread);
2151 sws_freeContext(is->sub_convert_ctx);
2152 av_free(is->filename);
2153 if (is->vis_texture)
2154 SDL_DestroyTexture(is->vis_texture);
2155 if (is->vid_texture)
2156 SDL_DestroyTexture(is->vid_texture);
2157 if (is->sub_texture)
2158 SDL_DestroyTexture(is->sub_texture);
2160 av_freep(&is->chapter_rows);
2161 av_free(is);
2162}
2163
2164static void do_exit(VideoState *is)
2165{
2166 if (is) {
2168 }
2169 if (renderer)
2170 SDL_DestroyRenderer(renderer);
2171 if (vk_renderer)
2173 if (window)
2174 SDL_DestroyWindow(window);
2175 uninit_opts();
2176 for (int i = 0; i < nb_vfilters; i++)
2184 if (show_status)
2185 printf("\n");
2186 SDL_Quit();
2187 av_log(NULL, AV_LOG_QUIET, "%s", "");
2188 exit(exit_status);
2189}
2190
2191static void sigterm_handler(int sig)
2192{
2194 if (++received_nb_signals > 3)
2195 exit(123);
2196}
2197
2199{
2200 SDL_Rect rect;
2201 int max_width = screen_width ? screen_width : INT_MAX;
2202 int max_height = screen_height ? screen_height : INT_MAX;
2203 if (max_width == INT_MAX && max_height == INT_MAX)
2204 max_height = height;
2205 calculate_display_rect(&rect, 0, 0, max_width, max_height, width, height, sar);
2208}
2209
2211{
2212 int w,h;
2213
2216
2217 if (!window_title)
2219 SDL_SetWindowTitle(window, window_title);
2220
2221 SDL_SetWindowSize(window, w, h);
2222 SDL_SetWindowPosition(window, screen_left, screen_top);
2223 if (is_full_screen)
2224 SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
2225 SDL_ShowWindow(window);
2226
2227 is->width = w;
2228 is->height = h;
2229
2230 return 0;
2231}
2232
2233/* display the current picture, if any */
2235{
2236 if (!is->width)
2237 video_open(is);
2238
2239 SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
2240 SDL_RenderClear(renderer);
2241 if (is->audio_st && is->show_mode != SHOW_MODE_VIDEO)
2243 else if (is->video_st)
2246 SDL_RenderPresent(renderer);
2247}
2248
2249static double get_clock(Clock *c)
2250{
2251 if (*c->queue_serial != c->serial)
2252 return NAN;
2253 if (c->paused) {
2254 return c->pts;
2255 } else {
2256 double time = av_gettime_relative() / 1000000.0;
2257 return c->pts_drift + time - (time - c->last_updated) * (1.0 - c->speed);
2258 }
2259}
2260
2261static void set_clock_at(Clock *c, double pts, int serial, double time)
2262{
2263 c->pts = pts;
2264 c->last_updated = time;
2265 c->pts_drift = c->pts - time;
2266 c->serial = serial;
2267}
2268
2269static void set_clock(Clock *c, double pts, int serial)
2270{
2271 double time = av_gettime_relative() / 1000000.0;
2272 set_clock_at(c, pts, serial, time);
2273}
2274
2275static void set_clock_speed(Clock *c, double speed)
2276{
2277 set_clock(c, get_clock(c), c->serial);
2278 c->speed = speed;
2279}
2280
2281static void init_clock(Clock *c, int *queue_serial)
2282{
2283 c->speed = 1.0;
2284 c->paused = 0;
2285 c->queue_serial = queue_serial;
2286 set_clock(c, NAN, -1);
2287}
2288
2289static void sync_clock_to_slave(Clock *c, Clock *slave)
2290{
2291 double clock = get_clock(c);
2292 double slave_clock = get_clock(slave);
2293 if (!isnan(slave_clock) && (isnan(clock) || fabs(clock - slave_clock) > AV_NOSYNC_THRESHOLD))
2294 set_clock(c, slave_clock, slave->serial);
2295}
2296
2298 if (is->av_sync_type == AV_SYNC_VIDEO_MASTER) {
2299 if (is->video_st)
2300 return AV_SYNC_VIDEO_MASTER;
2301 else
2302 return AV_SYNC_AUDIO_MASTER;
2303 } else if (is->av_sync_type == AV_SYNC_AUDIO_MASTER) {
2304 if (is->audio_st)
2305 return AV_SYNC_AUDIO_MASTER;
2306 else
2308 } else {
2310 }
2311}
2312
2313/* get the current master clock value */
2315{
2316 double val;
2317
2318 switch (get_master_sync_type(is)) {
2320 val = get_clock(&is->vidclk);
2321 break;
2323 val = get_clock(&is->audclk);
2324 break;
2325 default:
2326 val = get_clock(&is->extclk);
2327 break;
2328 }
2329 return val;
2330}
2331
2333 if (is->video_stream >= 0 && is->videoq.nb_packets <= EXTERNAL_CLOCK_MIN_FRAMES ||
2334 is->audio_stream >= 0 && is->audioq.nb_packets <= EXTERNAL_CLOCK_MIN_FRAMES) {
2336 } else if ((is->video_stream < 0 || is->videoq.nb_packets > EXTERNAL_CLOCK_MAX_FRAMES) &&
2337 (is->audio_stream < 0 || is->audioq.nb_packets > EXTERNAL_CLOCK_MAX_FRAMES)) {
2339 } else {
2340 double speed = is->extclk.speed;
2341 if (speed != 1.0)
2342 set_clock_speed(&is->extclk, speed + EXTERNAL_CLOCK_SPEED_STEP * (1.0 - speed) / fabs(1.0 - speed));
2343 }
2344}
2345
2346/* seek in the stream */
2347static void stream_seek(VideoState *is, int64_t pos, int64_t rel, int by_bytes)
2348{
2349 if (!is->seek_req) {
2350 is->seek_pos = pos;
2351 is->seek_rel = rel;
2352 is->seek_flags &= ~AVSEEK_FLAG_BYTE;
2353 if (by_bytes)
2354 is->seek_flags |= AVSEEK_FLAG_BYTE;
2355 is->seek_req = 1;
2356 SDL_CondSignal(is->continue_read_thread);
2357 }
2358}
2359
2360/* pause or resume the video */
2362{
2363 if (is->paused) {
2364 is->frame_timer += av_gettime_relative() / 1000000.0 - is->vidclk.last_updated;
2365 if (is->read_pause_return != AVERROR(ENOSYS)) {
2366 is->vidclk.paused = 0;
2367 }
2368 set_clock(&is->vidclk, get_clock(&is->vidclk), is->vidclk.serial);
2369 }
2370 set_clock(&is->extclk, get_clock(&is->extclk), is->extclk.serial);
2371 is->paused = is->audclk.paused = is->vidclk.paused = is->extclk.paused = !is->paused;
2372}
2373
2375{
2377 is->step = 0;
2378}
2379
2381{
2382 is->muted = !is->muted;
2383}
2384
2385static void update_volume(VideoState *is, int sign, double step)
2386{
2387 double volume_level = is->audio_volume ? (20 * log(is->audio_volume / (double)SDL_MIX_MAXVOLUME) / log(10)) : -1000.0;
2388 int new_volume = lrint(SDL_MIX_MAXVOLUME * pow(10.0, (volume_level + sign * step) / 20.0));
2389 is->audio_volume = av_clip(is->audio_volume == new_volume ? (is->audio_volume + sign) : new_volume, 0, SDL_MIX_MAXVOLUME);
2390}
2391
2393{
2394 /* if the stream is paused unpause it, then step */
2395 if (is->paused)
2397 is->step = 1;
2398}
2399
2400static double compute_target_delay(double delay, VideoState *is)
2401{
2402 double sync_threshold, diff = 0;
2403
2404 /* update delay to follow master synchronisation source */
2406 /* if video is slave, we try to correct big delays by
2407 duplicating or deleting a frame */
2408 diff = get_clock(&is->vidclk) - get_master_clock(is);
2409
2410 /* skip or repeat frame. We take into account the
2411 delay to compute the threshold. I still don't know
2412 if it is the best guess */
2413 sync_threshold = FFMAX(AV_SYNC_THRESHOLD_MIN, FFMIN(AV_SYNC_THRESHOLD_MAX, delay));
2414 if (!isnan(diff) && fabs(diff) < is->max_frame_duration) {
2415 if (diff <= -sync_threshold)
2416 delay = FFMAX(0, delay + diff);
2417 else if (diff >= sync_threshold && delay > AV_SYNC_FRAMEDUP_THRESHOLD)
2418 delay = delay + diff;
2419 else if (diff >= sync_threshold)
2420 delay = 2 * delay;
2421 }
2422 }
2423
2424 av_log(NULL, AV_LOG_TRACE, "video: delay=%0.3f A-V=%f\n",
2425 delay, -diff);
2426
2427 return delay;
2428}
2429
2430static double vp_duration(VideoState *is, Frame *vp, Frame *nextvp) {
2431 if (vp->serial == nextvp->serial) {
2432 double duration = nextvp->pts - vp->pts;
2433 if (isnan(duration) || duration <= 0 || duration > is->max_frame_duration)
2434 return vp->duration;
2435 else
2436 return duration;
2437 } else {
2438 return 0.0;
2439 }
2440}
2441
2442static void update_video_pts(VideoState *is, double pts, int serial)
2443{
2444 /* update current video pts */
2445 set_clock(&is->vidclk, pts, serial);
2446 sync_clock_to_slave(&is->extclk, &is->vidclk);
2447}
2448
2449/* called to display each frame */
2450static void video_refresh(void *opaque, double *remaining_time)
2451{
2452 VideoState *is = opaque;
2453 double time;
2454
2455 Frame *sp, *sp2;
2456
2457 if (!is->paused && get_master_sync_type(is) == AV_SYNC_EXTERNAL_CLOCK && is->realtime)
2459
2460 if (!display_disable && is->show_mode != SHOW_MODE_VIDEO && is->audio_st) {
2461 time = av_gettime_relative() / 1000000.0;
2462 if (is->force_refresh || is->last_vis_time + rdftspeed < time) {
2464 is->last_vis_time = time;
2465 }
2466 *remaining_time = FFMIN(*remaining_time, is->last_vis_time + rdftspeed - time);
2467 }
2468
2469 if (is->video_st) {
2470retry:
2471 if (frame_queue_nb_remaining(&is->pictq) == 0) {
2472 // nothing to do, no picture to display in the queue
2473 } else {
2474 double last_duration, duration, delay;
2475 Frame *vp, *lastvp;
2476
2477 /* dequeue the picture */
2478 lastvp = frame_queue_peek_last(&is->pictq);
2479 vp = frame_queue_peek(&is->pictq);
2480
2481 if (vp->serial != is->videoq.serial) {
2482 frame_queue_next(&is->pictq);
2483 goto retry;
2484 }
2485
2486 if (lastvp->serial != vp->serial)
2487 is->frame_timer = av_gettime_relative() / 1000000.0;
2488
2489 if (is->paused)
2490 goto display;
2491
2492 /* compute nominal last_duration */
2493 last_duration = vp_duration(is, lastvp, vp);
2494 delay = compute_target_delay(last_duration, is);
2495
2496 time= av_gettime_relative()/1000000.0;
2497 if (time < is->frame_timer + delay) {
2498 *remaining_time = FFMIN(is->frame_timer + delay - time, *remaining_time);
2499 goto display;
2500 }
2501
2502 is->frame_timer += delay;
2503 if (delay > 0 && time - is->frame_timer > AV_SYNC_THRESHOLD_MAX)
2504 is->frame_timer = time;
2505
2506 SDL_LockMutex(is->pictq.mutex);
2507 if (!isnan(vp->pts))
2508 update_video_pts(is, vp->pts, vp->serial);
2509 SDL_UnlockMutex(is->pictq.mutex);
2510
2511 if (frame_queue_nb_remaining(&is->pictq) > 1) {
2512 Frame *nextvp = frame_queue_peek_next(&is->pictq);
2513 duration = vp_duration(is, vp, nextvp);
2514 if(!is->step && (framedrop>0 || (framedrop && get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER)) && time > is->frame_timer + duration){
2515 is->frame_drops_late++;
2516 frame_queue_next(&is->pictq);
2517 goto retry;
2518 }
2519 }
2520
2521 if (is->subtitle_st) {
2522 while (frame_queue_nb_remaining(&is->subpq) > 0) {
2523 sp = frame_queue_peek(&is->subpq);
2524
2525 if (frame_queue_nb_remaining(&is->subpq) > 1)
2526 sp2 = frame_queue_peek_next(&is->subpq);
2527 else
2528 sp2 = NULL;
2529
2530 if (sp->serial != is->subtitleq.serial
2531 || (is->vidclk.pts > (sp->pts + ((float) sp->sub.end_display_time / 1000)))
2532 || (sp2 && is->vidclk.pts > (sp2->pts + ((float) sp2->sub.start_display_time / 1000))))
2533 {
2534 if (sp->uploaded) {
2535 int i;
2536 for (i = 0; i < sp->sub.num_rects; i++) {
2537 AVSubtitleRect *sub_rect = sp->sub.rects[i];
2538 uint8_t *pixels;
2539 int pitch, j;
2540
2541 if (!SDL_LockTexture(is->sub_texture, (SDL_Rect *)sub_rect, (void **)&pixels, &pitch)) {
2542 for (j = 0; j < sub_rect->h; j++, pixels += pitch)
2543 memset(pixels, 0, sub_rect->w << 2);
2544 SDL_UnlockTexture(is->sub_texture);
2545 }
2546 }
2547 }
2548 frame_queue_next(&is->subpq);
2549 } else {
2550 break;
2551 }
2552 }
2553 }
2554
2555 frame_queue_next(&is->pictq);
2556 is->force_refresh = 1;
2557
2558 if (is->step && !is->paused)
2560 }
2561display:
2562 /* display picture */
2563 if (!display_disable && is->force_refresh && is->show_mode == SHOW_MODE_VIDEO && is->pictq.rindex_shown)
2565 }
2566 is->force_refresh = 0;
2567 if (show_status) {
2568 AVBPrint buf;
2569 static int64_t last_time;
2570 int64_t cur_time;
2571 int aqsize, vqsize, sqsize;
2572 double av_diff;
2573
2574 cur_time = av_gettime_relative();
2575 if (!last_time || (cur_time - last_time) >= 30000) {
2576 aqsize = 0;
2577 vqsize = 0;
2578 sqsize = 0;
2579 if (is->audio_st)
2580 aqsize = is->audioq.size;
2581 if (is->video_st)
2582 vqsize = is->videoq.size;
2583 if (is->subtitle_st)
2584 sqsize = is->subtitleq.size;
2585 av_diff = 0;
2586 if (is->audio_st && is->video_st)
2587 av_diff = get_clock(&is->audclk) - get_clock(&is->vidclk);
2588 else if (is->video_st)
2589 av_diff = get_master_clock(is) - get_clock(&is->vidclk);
2590 else if (is->audio_st)
2591 av_diff = get_master_clock(is) - get_clock(&is->audclk);
2592
2594 av_bprintf(&buf,
2595 "%7.2f %s:%7.3f fd=%4d aq=%5dKB vq=%5dKB sq=%5dB \r",
2597 (is->audio_st && is->video_st) ? "A-V" : (is->video_st ? "M-V" : (is->audio_st ? "M-A" : " ")),
2598 av_diff,
2599 is->frame_drops_early + is->frame_drops_late,
2600 aqsize / 1024,
2601 vqsize / 1024,
2602 sqsize);
2603
2605 fprintf(stderr, "%s", buf.str);
2606 else
2607 av_log(NULL, AV_LOG_INFO, "%s", buf.str);
2608
2609 fflush(stderr);
2610 av_bprint_finalize(&buf, NULL);
2611
2612 last_time = cur_time;
2613 }
2614 }
2615}
2616
2617static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, double duration, int64_t pos, int serial)
2618{
2619 Frame *vp;
2620
2621#if defined(DEBUG_SYNC)
2622 printf("frame_type=%c pts=%0.3f\n",
2624#endif
2625
2626 if (!(vp = frame_queue_peek_writable(&is->pictq)))
2627 return -1;
2628
2629 vp->sar = src_frame->sample_aspect_ratio;
2630 vp->uploaded = 0;
2631
2632 vp->width = src_frame->width;
2633 vp->height = src_frame->height;
2634 vp->format = src_frame->format;
2635
2636 vp->pts = pts;
2637 vp->duration = duration;
2638 vp->pos = pos;
2639 vp->serial = serial;
2640
2641 set_default_window_size(vp->width, vp->height, vp->sar);
2642
2643 av_frame_move_ref(vp->frame, src_frame);
2644 frame_queue_push(&is->pictq);
2645 return 0;
2646}
2647
2649{
2650 int got_picture;
2651
2652 if ((got_picture = decoder_decode_frame(&is->viddec, frame, NULL)) < 0)
2653 return -1;
2654
2655 if (got_picture) {
2656 double dpts = NAN;
2657
2658 if (frame->pts != AV_NOPTS_VALUE)
2659 dpts = av_q2d(is->video_st->time_base) * frame->pts;
2660
2661 frame->sample_aspect_ratio = av_guess_sample_aspect_ratio(is->ic, is->video_st, frame);
2662
2664 if (frame->pts != AV_NOPTS_VALUE) {
2665 double diff = dpts - get_master_clock(is);
2666 if (!isnan(diff) && fabs(diff) < AV_NOSYNC_THRESHOLD &&
2667 diff - is->frame_last_filter_delay < 0 &&
2668 is->viddec.pkt_serial == is->vidclk.serial &&
2669 is->videoq.nb_packets) {
2670 is->frame_drops_early++;
2672 got_picture = 0;
2673 }
2674 }
2675 }
2676 }
2677
2678 return got_picture;
2679}
2680
2681static int configure_filtergraph(AVFilterGraph *graph, const char *filtergraph,
2682 AVFilterContext *source_ctx, AVFilterContext *sink_ctx)
2683{
2684 int ret, i;
2685 int nb_filters = graph->nb_filters;
2687
2688 if (filtergraph) {
2691 if (!outputs || !inputs) {
2692 ret = AVERROR(ENOMEM);
2693 goto fail;
2694 }
2695
2696 outputs->name = av_strdup("in");
2697 outputs->filter_ctx = source_ctx;
2698 outputs->pad_idx = 0;
2699 outputs->next = NULL;
2700
2701 inputs->name = av_strdup("out");
2702 inputs->filter_ctx = sink_ctx;
2703 inputs->pad_idx = 0;
2704 inputs->next = NULL;
2705
2706 if ((ret = avfilter_graph_parse_ptr(graph, filtergraph, &inputs, &outputs, NULL)) < 0)
2707 goto fail;
2708 } else {
2709 if ((ret = avfilter_link(source_ctx, 0, sink_ctx, 0)) < 0)
2710 goto fail;
2711 }
2712
2713 /* Reorder the filters to ensure that inputs of the custom filters are merged first */
2714 for (i = 0; i < graph->nb_filters - nb_filters; i++)
2715 FFSWAP(AVFilterContext*, graph->filters[i], graph->filters[i + nb_filters]);
2716
2717 ret = avfilter_graph_config(graph, NULL);
2718fail:
2721 return ret;
2722}
2723
2724static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const char *vfilters, AVFrame *frame)
2725{
2727 char sws_flags_str[512] = "";
2728 int ret;
2729 AVFilterContext *filt_src = NULL, *filt_out = NULL, *last_filter = NULL;
2730 AVCodecParameters *codecpar = is->video_st->codecpar;
2731 AVRational fr = av_guess_frame_rate(is->ic, is->video_st, NULL);
2732 const AVDictionaryEntry *e = NULL;
2733 int nb_pix_fmts = 0;
2734 int i, j;
2736
2737 if (!par)
2738 return AVERROR(ENOMEM);
2739
2740 for (i = 0; i < renderer_info.num_texture_formats; i++) {
2741 for (j = 0; j < FF_ARRAY_ELEMS(sdl_texture_format_map); j++) {
2742 if (renderer_info.texture_formats[i] == sdl_texture_format_map[j].texture_fmt) {
2743 pix_fmts[nb_pix_fmts++] = sdl_texture_format_map[j].format;
2744 break;
2745 }
2746 }
2747 }
2748
2749 while ((e = av_dict_iterate(sws_dict, e))) {
2750 if (!strcmp(e->key, "sws_flags")) {
2751 av_strlcatf(sws_flags_str, sizeof(sws_flags_str), "%s=%s:", "flags", e->value);
2752 } else
2753 av_strlcatf(sws_flags_str, sizeof(sws_flags_str), "%s=%s:", e->key, e->value);
2754 }
2755 if (strlen(sws_flags_str))
2756 sws_flags_str[strlen(sws_flags_str)-1] = '\0';
2757
2758 graph->scale_sws_opts = av_strdup(sws_flags_str);
2759
2760
2761 filt_src = avfilter_graph_alloc_filter(graph, avfilter_get_by_name("buffer"),
2762 "ffplay_buffer");
2763 if (!filt_src) {
2764 ret = AVERROR(ENOMEM);
2765 goto fail;
2766 }
2767
2768 par->format = frame->format;
2769 par->time_base = is->video_st->time_base;
2770 par->width = frame->width;
2771 par->height = frame->height;
2773 par->color_space = frame->colorspace;
2774 par->color_range = frame->color_range;
2775 par->alpha_mode = frame->alpha_mode;
2776 par->frame_rate = fr;
2777 par->hw_frames_ctx = frame->hw_frames_ctx;
2778 ret = av_buffersrc_parameters_set(filt_src, par);
2779 if (ret < 0)
2780 goto fail;
2781
2782 ret = avfilter_init_dict(filt_src, NULL);
2783 if (ret < 0)
2784 goto fail;
2785
2786 filt_out = avfilter_graph_alloc_filter(graph, avfilter_get_by_name("buffersink"),
2787 "ffplay_buffersink");
2788 if (!filt_out) {
2789 ret = AVERROR(ENOMEM);
2790 goto fail;
2791 }
2792
2793 if ((ret = av_opt_set_array(filt_out, "pixel_formats", AV_OPT_SEARCH_CHILDREN,
2794 0, nb_pix_fmts, AV_OPT_TYPE_PIXEL_FMT, pix_fmts)) < 0)
2795 goto fail;
2796 if (!vk_renderer &&
2797 (ret = av_opt_set_array(filt_out, "colorspaces", AV_OPT_SEARCH_CHILDREN,
2800 goto fail;
2801
2802 if ((ret = av_opt_set_array(filt_out, "alphamodes", AV_OPT_SEARCH_CHILDREN,
2805 goto fail;
2806
2807 ret = avfilter_init_dict(filt_out, NULL);
2808 if (ret < 0)
2809 goto fail;
2810
2811 last_filter = filt_out;
2812
2813/* Note: this macro adds a filter before the lastly added filter, so the
2814 * processing order of the filters is in reverse */
2815#define INSERT_FILT(name, arg) do { \
2816 AVFilterContext *filt_ctx; \
2817 \
2818 ret = avfilter_graph_create_filter(&filt_ctx, \
2819 avfilter_get_by_name(name), \
2820 "ffplay_" name, arg, NULL, graph); \
2821 if (ret < 0) \
2822 goto fail; \
2823 \
2824 ret = avfilter_link(filt_ctx, 0, last_filter, 0); \
2825 if (ret < 0) \
2826 goto fail; \
2827 \
2828 last_filter = filt_ctx; \
2829} while (0)
2830
2831 if (autorotate) {
2832 double theta = 0.0;
2833 int32_t *displaymatrix = NULL;
2835 if (sd)
2836 displaymatrix = (int32_t *)sd->data;
2837 if (!displaymatrix) {
2838 const AVPacketSideData *psd = av_packet_side_data_get(is->video_st->codecpar->coded_side_data,
2839 is->video_st->codecpar->nb_coded_side_data,
2841 if (psd)
2842 displaymatrix = (int32_t *)psd->data;
2843 }
2844 theta = get_rotation(displaymatrix);
2845
2846 if (fabs(theta - 90) < 1.0) {
2847 INSERT_FILT("transpose", displaymatrix[3] > 0 ? "cclock_flip" : "clock");
2848 } else if (fabs(theta - 180) < 1.0) {
2849 if (displaymatrix[0] < 0)
2850 INSERT_FILT("hflip", NULL);
2851 if (displaymatrix[4] < 0)
2852 INSERT_FILT("vflip", NULL);
2853 } else if (fabs(theta - 270) < 1.0) {
2854 INSERT_FILT("transpose", displaymatrix[3] < 0 ? "clock_flip" : "cclock");
2855 } else if (fabs(theta) > 1.0) {
2856 char rotate_buf[64];
2857 snprintf(rotate_buf, sizeof(rotate_buf), "%f*PI/180", theta);
2858 INSERT_FILT("rotate", rotate_buf);
2859 } else {
2860 if (displaymatrix && displaymatrix[4] < 0)
2861 INSERT_FILT("vflip", NULL);
2862 }
2863 }
2864
2865 if ((ret = configure_filtergraph(graph, vfilters, filt_src, last_filter)) < 0)
2866 goto fail;
2867
2868 is->in_video_filter = filt_src;
2869 is->out_video_filter = filt_out;
2870
2871fail:
2872 av_freep(&par);
2873 return ret;
2874}
2875
2876static int configure_audio_filters(VideoState *is, const char *afilters, int force_output_format)
2877{
2878 AVFilterContext *filt_asrc = NULL, *filt_asink = NULL;
2879 char aresample_swr_opts[512] = "";
2880 const AVDictionaryEntry *e = NULL;
2881 AVBPrint bp;
2882 char asrc_args[256];
2883 int ret;
2884
2885 avfilter_graph_free(&is->agraph);
2886 if (!(is->agraph = avfilter_graph_alloc()))
2887 return AVERROR(ENOMEM);
2888 is->agraph->nb_threads = filter_nbthreads;
2889
2891
2892 while ((e = av_dict_iterate(swr_opts, e)))
2893 av_strlcatf(aresample_swr_opts, sizeof(aresample_swr_opts), "%s=%s:", e->key, e->value);
2894 if (strlen(aresample_swr_opts))
2895 aresample_swr_opts[strlen(aresample_swr_opts)-1] = '\0';
2896 av_opt_set(is->agraph, "aresample_swr_opts", aresample_swr_opts, 0);
2897
2898 av_channel_layout_describe_bprint(&is->audio_filter_src.ch_layout, &bp);
2899
2900 ret = snprintf(asrc_args, sizeof(asrc_args),
2901 "sample_rate=%d:sample_fmt=%s:time_base=%d/%d:channel_layout=%s",
2902 is->audio_filter_src.freq, av_get_sample_fmt_name(is->audio_filter_src.fmt),
2903 1, is->audio_filter_src.freq, bp.str);
2904
2905 ret = avfilter_graph_create_filter(&filt_asrc,
2906 avfilter_get_by_name("abuffer"), "ffplay_abuffer",
2907 asrc_args, NULL, is->agraph);
2908 if (ret < 0)
2909 goto end;
2910
2911 filt_asink = avfilter_graph_alloc_filter(is->agraph, avfilter_get_by_name("abuffersink"),
2912 "ffplay_abuffersink");
2913 if (!filt_asink) {
2914 ret = AVERROR(ENOMEM);
2915 goto end;
2916 }
2917
2918 if ((ret = av_opt_set(filt_asink, "sample_formats", "s16", AV_OPT_SEARCH_CHILDREN)) < 0)
2919 goto end;
2920
2921 if (force_output_format) {
2922 if ((ret = av_opt_set_array(filt_asink, "channel_layouts", AV_OPT_SEARCH_CHILDREN,
2923 0, 1, AV_OPT_TYPE_CHLAYOUT, &is->audio_tgt.ch_layout)) < 0)
2924 goto end;
2925 if ((ret = av_opt_set_array(filt_asink, "samplerates", AV_OPT_SEARCH_CHILDREN,
2926 0, 1, AV_OPT_TYPE_INT, &is->audio_tgt.freq)) < 0)
2927 goto end;
2928 }
2929
2930 ret = avfilter_init_dict(filt_asink, NULL);
2931 if (ret < 0)
2932 goto end;
2933
2934 if ((ret = configure_filtergraph(is->agraph, afilters, filt_asrc, filt_asink)) < 0)
2935 goto end;
2936
2937 is->in_audio_filter = filt_asrc;
2938 is->out_audio_filter = filt_asink;
2939
2940end:
2941 if (ret < 0)
2942 avfilter_graph_free(&is->agraph);
2944
2945 return ret;
2946}
2947
2948static int audio_thread(void *arg)
2949{
2950 VideoState *is = arg;
2952 Frame *af;
2953 int last_serial = -1;
2954 int reconfigure;
2955 int got_frame = 0;
2956 AVRational tb;
2957 int ret = 0;
2958
2959 if (!frame)
2960 return AVERROR(ENOMEM);
2961
2962 do {
2963 if ((got_frame = decoder_decode_frame(&is->auddec, frame, NULL)) < 0)
2964 goto the_end;
2965
2966 if (got_frame) {
2967 tb = (AVRational){1, frame->sample_rate};
2968
2969 reconfigure =
2970 cmp_audio_fmts(is->audio_filter_src.fmt, is->audio_filter_src.ch_layout.nb_channels,
2971 frame->format, frame->ch_layout.nb_channels) ||
2972 av_channel_layout_compare(&is->audio_filter_src.ch_layout, &frame->ch_layout) ||
2973 is->audio_filter_src.freq != frame->sample_rate ||
2974 is->auddec.pkt_serial != last_serial;
2975
2976 if (reconfigure) {
2977 char buf1[1024], buf2[1024];
2978 av_channel_layout_describe(&is->audio_filter_src.ch_layout, buf1, sizeof(buf1));
2979 av_channel_layout_describe(&frame->ch_layout, buf2, sizeof(buf2));
2981 "Audio frame changed from rate:%d ch:%d fmt:%s layout:%s serial:%d to rate:%d ch:%d fmt:%s layout:%s serial:%d\n",
2982 is->audio_filter_src.freq, is->audio_filter_src.ch_layout.nb_channels, av_get_sample_fmt_name(is->audio_filter_src.fmt), buf1, last_serial,
2983 frame->sample_rate, frame->ch_layout.nb_channels, av_get_sample_fmt_name(frame->format), buf2, is->auddec.pkt_serial);
2984
2985 is->audio_filter_src.fmt = frame->format;
2986 ret = av_channel_layout_copy(&is->audio_filter_src.ch_layout, &frame->ch_layout);
2987 if (ret < 0)
2988 goto the_end;
2989 is->audio_filter_src.freq = frame->sample_rate;
2990 last_serial = is->auddec.pkt_serial;
2991
2992 if ((ret = configure_audio_filters(is, afilters, 1)) < 0)
2993 goto the_end;
2994 }
2995
2996 if ((ret = av_buffersrc_add_frame(is->in_audio_filter, frame)) < 0)
2997 goto the_end;
2998
2999 while ((ret = av_buffersink_get_frame_flags(is->out_audio_filter, frame, 0)) >= 0) {
3000 FrameData *fd = frame->opaque_ref ? (FrameData*)frame->opaque_ref->data : NULL;
3001 tb = av_buffersink_get_time_base(is->out_audio_filter);
3002 if (!(af = frame_queue_peek_writable(&is->sampq)))
3003 goto the_end;
3004
3005 af->pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb);
3006 af->pos = fd ? fd->pkt_pos : -1;
3007 af->serial = is->auddec.pkt_serial;
3008 af->duration = av_q2d((AVRational){frame->nb_samples, frame->sample_rate});
3009
3011 frame_queue_push(&is->sampq);
3012
3013 if (is->audioq.serial != is->auddec.pkt_serial)
3014 break;
3015 }
3016 if (ret == AVERROR_EOF)
3017 is->auddec.finished = is->auddec.pkt_serial;
3018 }
3019 } while (ret >= 0 || ret == AVERROR(EAGAIN) || ret == AVERROR_EOF);
3020 the_end:
3021 avfilter_graph_free(&is->agraph);
3023 return ret;
3024}
3025
3026static int decoder_start(Decoder *d, int (*fn)(void *), const char *thread_name, void* arg)
3027{
3029 d->decoder_tid = SDL_CreateThread(fn, thread_name, arg);
3030 if (!d->decoder_tid) {
3031 av_log(NULL, AV_LOG_ERROR, "SDL_CreateThread(): %s\n", SDL_GetError());
3032 return AVERROR(ENOMEM);
3033 }
3034 return 0;
3035}
3036
3037static int video_thread(void *arg)
3038{
3039 VideoState *is = arg;
3041 double pts;
3042 double duration;
3043 int ret;
3044 AVRational tb = is->video_st->time_base;
3045 AVRational frame_rate = av_guess_frame_rate(is->ic, is->video_st, NULL);
3046
3047 AVFilterGraph *graph = NULL;
3048 AVFilterContext *filt_out = NULL, *filt_in = NULL;
3049 int last_w = 0;
3050 int last_h = 0;
3051 enum AVPixelFormat last_format = -2;
3052 int last_serial = -1;
3053 int last_vfilter_idx = 0;
3054
3055 if (!frame)
3056 return AVERROR(ENOMEM);
3057
3058 for (;;) {
3059 ret = get_video_frame(is, frame);
3060 if (ret < 0)
3061 goto the_end;
3062 if (!ret)
3063 continue;
3064
3065 if ( last_w != frame->width
3066 || last_h != frame->height
3067 || last_format != frame->format
3068 || last_serial != is->viddec.pkt_serial
3069 || last_vfilter_idx != is->vfilter_idx) {
3071 "Video frame changed from size:%dx%d format:%s serial:%d to size:%dx%d format:%s serial:%d\n",
3072 last_w, last_h,
3073 (const char *)av_x_if_null(av_get_pix_fmt_name(last_format), "none"), last_serial,
3074 frame->width, frame->height,
3075 (const char *)av_x_if_null(av_get_pix_fmt_name(frame->format), "none"), is->viddec.pkt_serial);
3076 avfilter_graph_free(&graph);
3077 graph = avfilter_graph_alloc();
3078 if (!graph) {
3079 ret = AVERROR(ENOMEM);
3080 goto the_end;
3081 }
3083 if ((ret = configure_video_filters(graph, is, vfilters_list ? vfilters_list[is->vfilter_idx] : NULL, frame)) < 0) {
3084 SDL_Event event;
3085 event.type = FF_QUIT_EVENT;
3086 event.user.data1 = is;
3087 SDL_PushEvent(&event);
3088 goto the_end;
3089 }
3090 filt_in = is->in_video_filter;
3091 filt_out = is->out_video_filter;
3092 last_w = frame->width;
3093 last_h = frame->height;
3094 last_format = frame->format;
3095 last_serial = is->viddec.pkt_serial;
3096 last_vfilter_idx = is->vfilter_idx;
3097 frame_rate = av_buffersink_get_frame_rate(filt_out);
3098 }
3099
3100 ret = av_buffersrc_add_frame(filt_in, frame);
3101 if (ret < 0)
3102 goto the_end;
3103
3104 while (ret >= 0) {
3105 FrameData *fd;
3106
3107 is->frame_last_returned_time = av_gettime_relative() / 1000000.0;
3108
3109 ret = av_buffersink_get_frame_flags(filt_out, frame, 0);
3110 if (ret < 0) {
3111 if (ret == AVERROR_EOF)
3112 is->viddec.finished = is->viddec.pkt_serial;
3113 ret = 0;
3114 break;
3115 }
3116
3117 fd = frame->opaque_ref ? (FrameData*)frame->opaque_ref->data : NULL;
3118
3119 is->frame_last_filter_delay = av_gettime_relative() / 1000000.0 - is->frame_last_returned_time;
3120 if (fabs(is->frame_last_filter_delay) > AV_NOSYNC_THRESHOLD / 10.0)
3121 is->frame_last_filter_delay = 0;
3122 tb = av_buffersink_get_time_base(filt_out);
3123 duration = (frame_rate.num && frame_rate.den ? av_q2d((AVRational){frame_rate.den, frame_rate.num}) : 0);
3124 pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb);
3125 ret = queue_picture(is, frame, pts, duration, fd ? fd->pkt_pos : -1, is->viddec.pkt_serial);
3127 if (is->videoq.serial != is->viddec.pkt_serial)
3128 break;
3129 }
3130
3131 if (ret < 0)
3132 goto the_end;
3133 }
3134 the_end:
3135 avfilter_graph_free(&graph);
3137 return 0;
3138}
3139
3140static int subtitle_thread(void *arg)
3141{
3142 VideoState *is = arg;
3143 Frame *sp;
3144 int got_subtitle;
3145 double pts;
3146
3147 for (;;) {
3148 if (!(sp = frame_queue_peek_writable(&is->subpq)))
3149 return 0;
3150
3151 if ((got_subtitle = decoder_decode_frame(&is->subdec, NULL, &sp->sub)) < 0)
3152 break;
3153
3154 pts = 0;
3155
3156 if (got_subtitle && sp->sub.format == 0) {
3157 if (sp->sub.pts != AV_NOPTS_VALUE)
3158 pts = sp->sub.pts / (double)AV_TIME_BASE;
3159 sp->pts = pts;
3160 sp->serial = is->subdec.pkt_serial;
3161 sp->width = is->subdec.avctx->width;
3162 sp->height = is->subdec.avctx->height;
3163 sp->uploaded = 0;
3164
3165 /* now we can update the picture count */
3166 frame_queue_push(&is->subpq);
3167 } else if (got_subtitle) {
3168 avsubtitle_free(&sp->sub);
3169 }
3170 }
3171 return 0;
3172}
3173
3174/* copy samples for viewing in editor window */
3175static void update_sample_display(VideoState *is, short *samples, int samples_size)
3176{
3177 int size, len;
3178
3179 size = samples_size / sizeof(short);
3180 while (size > 0) {
3181 len = SAMPLE_ARRAY_SIZE - is->sample_array_index;
3182 if (len > size)
3183 len = size;
3184 memcpy(is->sample_array + is->sample_array_index, samples, len * sizeof(short));
3185 samples += len;
3186 is->sample_array_index += len;
3187 if (is->sample_array_index >= SAMPLE_ARRAY_SIZE)
3188 is->sample_array_index = 0;
3189 size -= len;
3190 }
3191}
3192
3193/* return the wanted number of samples to get better sync if sync_type is video
3194 * or external master clock */
3195static int synchronize_audio(VideoState *is, int nb_samples)
3196{
3197 int wanted_nb_samples = nb_samples;
3198
3199 /* if not master, then we try to remove or add samples to correct the clock */
3201 double diff, avg_diff;
3202 int min_nb_samples, max_nb_samples;
3203
3204 diff = get_clock(&is->audclk) - get_master_clock(is);
3205
3206 if (!isnan(diff) && fabs(diff) < AV_NOSYNC_THRESHOLD) {
3207 is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum;
3208 if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {
3209 /* not enough measures to have a correct estimate */
3210 is->audio_diff_avg_count++;
3211 } else {
3212 /* estimate the A-V difference */
3213 avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef);
3214
3215 if (fabs(avg_diff) >= is->audio_diff_threshold) {
3216 wanted_nb_samples = nb_samples + (int)(diff * is->audio_src.freq);
3217 min_nb_samples = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX) / 100));
3218 max_nb_samples = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX) / 100));
3219 wanted_nb_samples = av_clip(wanted_nb_samples, min_nb_samples, max_nb_samples);
3220 }
3221 av_log(NULL, AV_LOG_TRACE, "diff=%f adiff=%f sample_diff=%d apts=%0.3f %f\n",
3222 diff, avg_diff, wanted_nb_samples - nb_samples,
3223 is->audio_clock, is->audio_diff_threshold);
3224 }
3225 } else {
3226 /* too big difference : may be initial PTS errors, so
3227 reset A-V filter */
3228 is->audio_diff_avg_count = 0;
3229 is->audio_diff_cum = 0;
3230 }
3231 }
3232
3233 return wanted_nb_samples;
3234}
3235
3236/**
3237 * Decode one audio frame and return its uncompressed size.
3238 *
3239 * The processed audio frame is decoded, converted if required, and
3240 * stored in is->audio_buf, with size in bytes given by the return
3241 * value.
3242 */
3244{
3245 int data_size, resampled_data_size;
3246 av_unused double audio_clock0;
3247 int wanted_nb_samples;
3248 Frame *af;
3249
3250 if (is->paused)
3251 return -1;
3252
3253 do {
3254#if defined(_WIN32)
3255 while (frame_queue_nb_remaining(&is->sampq) == 0) {
3256 if ((av_gettime_relative() - audio_callback_time) > 1000000LL * is->audio_hw_buf_size / is->audio_tgt.bytes_per_sec / 2)
3257 return -1;
3258 av_usleep (1000);
3259 }
3260#endif
3261 if (!(af = frame_queue_peek_readable(&is->sampq)))
3262 return -1;
3263 frame_queue_next(&is->sampq);
3264 } while (af->serial != is->audioq.serial);
3265
3267 af->frame->nb_samples,
3268 af->frame->format, 1);
3269
3270 wanted_nb_samples = synchronize_audio(is, af->frame->nb_samples);
3271
3272 if (af->frame->format != is->audio_src.fmt ||
3273 av_channel_layout_compare(&af->frame->ch_layout, &is->audio_src.ch_layout) ||
3274 af->frame->sample_rate != is->audio_src.freq ||
3275 (wanted_nb_samples != af->frame->nb_samples && !is->swr_ctx)) {
3276 int ret;
3277 swr_free(&is->swr_ctx);
3278 ret = swr_alloc_set_opts2(&is->swr_ctx,
3279 &is->audio_tgt.ch_layout, is->audio_tgt.fmt, is->audio_tgt.freq,
3280 &af->frame->ch_layout, af->frame->format, af->frame->sample_rate,
3281 0, NULL);
3282 if (ret < 0 || swr_init(is->swr_ctx) < 0) {
3284 "Cannot create sample rate converter for conversion of %d Hz %s %d channels to %d Hz %s %d channels!\n",
3286 is->audio_tgt.freq, av_get_sample_fmt_name(is->audio_tgt.fmt), is->audio_tgt.ch_layout.nb_channels);
3287 swr_free(&is->swr_ctx);
3288 return -1;
3289 }
3290 if (av_channel_layout_copy(&is->audio_src.ch_layout, &af->frame->ch_layout) < 0)
3291 return -1;
3292 is->audio_src.freq = af->frame->sample_rate;
3293 is->audio_src.fmt = af->frame->format;
3294 }
3295
3296 if (is->swr_ctx) {
3297 const uint8_t **in = (const uint8_t **)af->frame->extended_data;
3298 uint8_t **out = &is->audio_buf1;
3299 int out_count = (int64_t)wanted_nb_samples * is->audio_tgt.freq / af->frame->sample_rate + 256;
3300 int out_size = av_samples_get_buffer_size(NULL, is->audio_tgt.ch_layout.nb_channels, out_count, is->audio_tgt.fmt, 0);
3301 int len2;
3302 if (out_size < 0) {
3303 av_log(NULL, AV_LOG_ERROR, "av_samples_get_buffer_size() failed\n");
3304 return -1;
3305 }
3306 if (wanted_nb_samples != af->frame->nb_samples) {
3307 if (swr_set_compensation(is->swr_ctx, (wanted_nb_samples - af->frame->nb_samples) * is->audio_tgt.freq / af->frame->sample_rate,
3308 wanted_nb_samples * is->audio_tgt.freq / af->frame->sample_rate) < 0) {
3309 av_log(NULL, AV_LOG_ERROR, "swr_set_compensation() failed\n");
3310 return -1;
3311 }
3312 }
3313 av_fast_malloc(&is->audio_buf1, &is->audio_buf1_size, out_size);
3314 if (!is->audio_buf1)
3315 return AVERROR(ENOMEM);
3316 len2 = swr_convert(is->swr_ctx, out, out_count, in, af->frame->nb_samples);
3317 if (len2 < 0) {
3318 av_log(NULL, AV_LOG_ERROR, "swr_convert() failed\n");
3319 return -1;
3320 }
3321 if (len2 == out_count) {
3322 av_log(NULL, AV_LOG_WARNING, "audio buffer is probably too small\n");
3323 if (swr_init(is->swr_ctx) < 0)
3324 swr_free(&is->swr_ctx);
3325 }
3326 is->audio_buf = is->audio_buf1;
3327 resampled_data_size = len2 * is->audio_tgt.ch_layout.nb_channels * av_get_bytes_per_sample(is->audio_tgt.fmt);
3328 } else {
3329 is->audio_buf = af->frame->data[0];
3330 resampled_data_size = data_size;
3331 }
3332
3333 audio_clock0 = is->audio_clock;
3334 /* update the audio clock with the pts */
3335 if (!isnan(af->pts))
3336 is->audio_clock = af->pts + (double) af->frame->nb_samples / af->frame->sample_rate;
3337 else
3338 is->audio_clock = NAN;
3339 is->audio_clock_serial = af->serial;
3340#ifdef DEBUG
3341 {
3342 static double last_clock;
3343 printf("audio: delay=%0.3f clock=%0.3f clock0=%0.3f\n",
3344 is->audio_clock - last_clock,
3345 is->audio_clock, audio_clock0);
3346 last_clock = is->audio_clock;
3347 }
3348#endif
3349 return resampled_data_size;
3350}
3351
3352/* prepare a new audio buffer */
3353static void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
3354{
3355 VideoState *is = opaque;
3356 int audio_size, len1;
3357
3359
3360 while (len > 0) {
3361 if (is->audio_buf_index >= is->audio_buf_size) {
3362 audio_size = audio_decode_frame(is);
3363 if (audio_size < 0) {
3364 /* if error, just output silence */
3365 is->audio_buf = NULL;
3366 is->audio_buf_size = SDL_AUDIO_MIN_BUFFER_SIZE / is->audio_tgt.frame_size * is->audio_tgt.frame_size;
3367 } else {
3368 if (is->show_mode != SHOW_MODE_VIDEO)
3369 update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
3370 is->audio_buf_size = audio_size;
3371 }
3372 is->audio_buf_index = 0;
3373 }
3374 len1 = is->audio_buf_size - is->audio_buf_index;
3375 if (len1 > len)
3376 len1 = len;
3377 if (!is->muted && is->audio_buf && is->audio_volume == SDL_MIX_MAXVOLUME)
3378 memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
3379 else {
3380 memset(stream, 0, len1);
3381 if (!is->muted && is->audio_buf)
3382 SDL_MixAudioFormat(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, AUDIO_S16SYS, len1, is->audio_volume);
3383 }
3384 len -= len1;
3385 stream += len1;
3386 is->audio_buf_index += len1;
3387 }
3388 is->audio_write_buf_size = is->audio_buf_size - is->audio_buf_index;
3389 /* Let's assume the audio driver that is used by SDL has two periods. */
3390 if (!isnan(is->audio_clock)) {
3391 set_clock_at(&is->audclk, is->audio_clock - (double)(2 * is->audio_hw_buf_size + is->audio_write_buf_size) / is->audio_tgt.bytes_per_sec, is->audio_clock_serial, audio_callback_time / 1000000.0);
3392 sync_clock_to_slave(&is->extclk, &is->audclk);
3393 }
3394}
3395
3396static int audio_open(void *opaque, AVChannelLayout *wanted_channel_layout, int wanted_sample_rate, struct AudioParams *audio_hw_params)
3397{
3398 SDL_AudioSpec wanted_spec, spec;
3399 const char *env;
3400 static const int next_nb_channels[] = {0, 0, 1, 6, 2, 6, 4, 6};
3401 static const int next_sample_rates[] = {0, 44100, 48000, 96000, 192000};
3402 int next_sample_rate_idx = FF_ARRAY_ELEMS(next_sample_rates) - 1;
3403 int wanted_nb_channels = wanted_channel_layout->nb_channels;
3404
3405 env = SDL_getenv("SDL_AUDIO_CHANNELS");
3406 if (env) {
3407 wanted_nb_channels = atoi(env);
3408 av_channel_layout_uninit(wanted_channel_layout);
3409 av_channel_layout_default(wanted_channel_layout, wanted_nb_channels);
3410 }
3411 if (wanted_channel_layout->order != AV_CHANNEL_ORDER_NATIVE) {
3412 av_channel_layout_uninit(wanted_channel_layout);
3413 av_channel_layout_default(wanted_channel_layout, wanted_nb_channels);
3414 }
3415 wanted_nb_channels = wanted_channel_layout->nb_channels;
3416 wanted_spec.channels = wanted_nb_channels;
3417 wanted_spec.freq = wanted_sample_rate;
3418 if (wanted_spec.freq <= 0 || wanted_spec.channels <= 0) {
3419 av_log(NULL, AV_LOG_ERROR, "Invalid sample rate or channel count!\n");
3420 return -1;
3421 }
3422 while (next_sample_rate_idx && next_sample_rates[next_sample_rate_idx] >= wanted_spec.freq)
3423 next_sample_rate_idx--;
3424 wanted_spec.format = AUDIO_S16SYS;
3425 wanted_spec.silence = 0;
3426 wanted_spec.samples = FFMAX(SDL_AUDIO_MIN_BUFFER_SIZE, 2 << av_log2(wanted_spec.freq / SDL_AUDIO_MAX_CALLBACKS_PER_SEC));
3427 wanted_spec.callback = sdl_audio_callback;
3428 wanted_spec.userdata = opaque;
3429 while (!(audio_dev = SDL_OpenAudioDevice(NULL, 0, &wanted_spec, &spec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE | SDL_AUDIO_ALLOW_CHANNELS_CHANGE))) {
3430 av_log(NULL, AV_LOG_WARNING, "SDL_OpenAudio (%d channels, %d Hz): %s\n",
3431 wanted_spec.channels, wanted_spec.freq, SDL_GetError());
3432 wanted_spec.channels = next_nb_channels[FFMIN(7, wanted_spec.channels)];
3433 if (!wanted_spec.channels) {
3434 wanted_spec.freq = next_sample_rates[next_sample_rate_idx--];
3435 wanted_spec.channels = wanted_nb_channels;
3436 if (!wanted_spec.freq) {
3438 "No more combinations to try, audio open failed\n");
3439 return -1;
3440 }
3441 }
3442 av_channel_layout_default(wanted_channel_layout, wanted_spec.channels);
3443 }
3444 if (spec.format != AUDIO_S16SYS) {
3446 "SDL advised audio format %d is not supported!\n", spec.format);
3447 return -1;
3448 }
3449 if (spec.channels != wanted_spec.channels) {
3450 av_channel_layout_uninit(wanted_channel_layout);
3451 av_channel_layout_default(wanted_channel_layout, spec.channels);
3452 if (wanted_channel_layout->order != AV_CHANNEL_ORDER_NATIVE) {
3454 "SDL advised channel count %d is not supported!\n", spec.channels);
3455 return -1;
3456 }
3457 }
3458
3459 audio_hw_params->fmt = AV_SAMPLE_FMT_S16;
3460 audio_hw_params->freq = spec.freq;
3461 if (av_channel_layout_copy(&audio_hw_params->ch_layout, wanted_channel_layout) < 0)
3462 return -1;
3463 audio_hw_params->frame_size = av_samples_get_buffer_size(NULL, audio_hw_params->ch_layout.nb_channels, 1, audio_hw_params->fmt, 1);
3464 audio_hw_params->bytes_per_sec = av_samples_get_buffer_size(NULL, audio_hw_params->ch_layout.nb_channels, audio_hw_params->freq, audio_hw_params->fmt, 1);
3465 if (audio_hw_params->bytes_per_sec <= 0 || audio_hw_params->frame_size <= 0) {
3466 av_log(NULL, AV_LOG_ERROR, "av_samples_get_buffer_size failed\n");
3467 return -1;
3468 }
3469 return spec.size;
3470}
3471
3472static int create_hwaccel(AVBufferRef **device_ctx)
3473{
3474 enum AVHWDeviceType type;
3475 int ret;
3476 AVBufferRef *vk_dev;
3477
3478 *device_ctx = NULL;
3479
3480 if (!hwaccel)
3481 return 0;
3482
3485 return AVERROR(ENOTSUP);
3486
3487 if (!vk_renderer) {
3488 av_log(NULL, AV_LOG_ERROR, "Vulkan renderer is not available\n");
3489 return AVERROR(ENOTSUP);
3490 }
3491
3492 ret = vk_renderer_get_hw_dev(vk_renderer, &vk_dev);
3493 if (ret < 0)
3494 return ret;
3495
3496 ret = av_hwdevice_ctx_create_derived(device_ctx, type, vk_dev, 0);
3497 if (!ret)
3498 return 0;
3499
3500 if (ret != AVERROR(ENOSYS))
3501 return ret;
3502
3503 av_log(NULL, AV_LOG_WARNING, "Derive %s from vulkan not supported.\n", hwaccel);
3504 ret = av_hwdevice_ctx_create(device_ctx, type, NULL, NULL, 0);
3505 return ret;
3506}
3507
3508static int init_lcevc_graph(AVFormatContext *ic, int stream_index)
3509{
3510 FormatContext *ici = ic->opaque;
3511 StreamGroup *stgi = ici->streams[stream_index]->group;
3512 AVStreamGroup *stg = stgi->stg;
3513 const AVBitStreamFilter *filter, *lcevc_filter = av_bsf_get_by_name("lcevc_merge");
3515 int ret;
3516
3517 stgi->graph = av_bsf_graph_alloc();
3518 if (!stgi->graph)
3519 return AVERROR(ENOMEM);
3520
3522 AVStream *base_st = ic->streams[stream_index];
3523 AVStream *lcevc_st = stg->entries[lcevc->el_index]->stream;
3524 Stream *lcevc_sti = ici->streams[lcevc_st->index];
3525 Stream *base_sti = ici->streams[stream_index];
3526
3527 filter = av_bsf_get_by_name("source");
3528 ret = av_bsf_graph_alloc_filter(&base_sti->filter, filter, "lcevc_merge_base", stgi->graph);
3529 if (ret < 0)
3530 return ret;
3531 av_opt_set_q(base_sti->filter->priv_data, "time_base", base_st->time_base, 0);
3532 ret = av_bsf_source_parameters_set(base_sti->filter, base_st->codecpar);
3533 if (ret < 0)
3534 return ret;
3535
3536 ret = av_bsf_graph_alloc_filter(&lcevc_sti->filter, filter, "lcevc_merge_enhancement", stgi->graph);
3537 if (ret < 0)
3538 return ret;
3539 av_opt_set_q(lcevc_sti->filter->priv_data, "time_base", lcevc_st->time_base, 0);
3540 ret = av_bsf_source_parameters_set(lcevc_sti->filter, lcevc_st->codecpar);
3541 if (ret < 0)
3542 return ret;
3543
3544 ret = av_bsf_graph_alloc_filter(&lcevc_merge, lcevc_filter, "lcevc_merge", stgi->graph);
3545 if (ret < 0)
3546 return ret;
3547
3548 filter = av_bsf_get_by_name("sink");
3549 ret = av_bsf_graph_alloc_filter(&stgi->sink, filter, "lcevc_merge_sink", stgi->graph);
3550 if (ret < 0)
3551 return ret;
3552
3553 ret = av_bsf_init_dict(base_sti->filter, NULL);
3554 if (ret < 0)
3555 return ret;
3556 ret = av_bsf_init_dict(lcevc_sti->filter, NULL);
3557 if (ret < 0)
3558 return ret;
3560 if (ret < 0)
3561 return ret;
3562 ret = av_bsf_init_dict(stgi->sink, NULL);
3563 if (ret < 0)
3564 return ret;
3565
3566 ret = av_bsf_link(base_sti->filter, 0, lcevc_merge, 0);
3567 if (ret < 0)
3568 return ret;
3569 ret = av_bsf_link(lcevc_sti->filter, 0, lcevc_merge, 1);
3570 if (ret < 0)
3571 return ret;
3572 ret = av_bsf_link(lcevc_merge, 0, stgi->sink, 0);
3573 if (ret < 0)
3574 return ret;
3575
3576 ret = av_bsf_graph_config(stgi->graph, NULL);
3577 if (ret < 0)
3578 return ret;
3579
3580 lcevc_st->discard = AVDISCARD_DEFAULT;
3581 lcevc_sti->group = stgi;
3582
3583 return 0;
3584}
3585
3586/* open a given stream. Return 0 if OK */
3587static int stream_component_open(VideoState *is, int stream_index)
3588{
3589 AVFormatContext *ic = is->ic;
3590 FormatContext *ici = ic->opaque;
3591 AVCodecContext *avctx;
3592 const AVCodec *codec;
3593 const char *forced_codec_name = NULL;
3595 int sample_rate;
3596 AVChannelLayout ch_layout = { 0 };
3597 int ret = 0;
3598 int stream_lowres = lowres;
3599
3600 if (stream_index < 0 || stream_index >= ic->nb_streams)
3601 return -1;
3602
3604 if (!avctx)
3605 return AVERROR(ENOMEM);
3606
3607 ret = avcodec_parameters_to_context(avctx, ic->streams[stream_index]->codecpar);
3608 if (ret < 0)
3609 goto fail;
3610 avctx->pkt_timebase = ic->streams[stream_index]->time_base;
3611
3612 codec = avcodec_find_decoder(avctx->codec_id);
3613
3614 switch(avctx->codec_type){
3615 case AVMEDIA_TYPE_AUDIO : is->last_audio_stream = stream_index; forced_codec_name = audio_codec_name; break;
3616 case AVMEDIA_TYPE_SUBTITLE: is->last_subtitle_stream = stream_index; forced_codec_name = subtitle_codec_name; break;
3617 case AVMEDIA_TYPE_VIDEO : is->last_video_stream = stream_index; forced_codec_name = video_codec_name; break;
3618 }
3619 if (forced_codec_name)
3620 codec = avcodec_find_decoder_by_name(forced_codec_name);
3621 if (!codec) {
3622 if (forced_codec_name) av_log(NULL, AV_LOG_WARNING,
3623 "No codec could be found with name '%s'\n", forced_codec_name);
3625 "No decoder could be found for codec %s\n", avcodec_get_name(avctx->codec_id));
3626 ret = AVERROR(EINVAL);
3627 goto fail;
3628 }
3629
3630 avctx->codec_id = codec->id;
3631 if (stream_lowres > codec->max_lowres) {
3632 av_log(avctx, AV_LOG_WARNING, "The maximum value for lowres supported by the decoder is %d\n",
3633 codec->max_lowres);
3634 stream_lowres = codec->max_lowres;
3635 }
3636 avctx->lowres = stream_lowres;
3637
3638 if (fast)
3639 avctx->flags2 |= AV_CODEC_FLAG2_FAST;
3640
3641 ret = filter_codec_opts(codec_opts, avctx->codec_id, ic,
3642 ic->streams[stream_index], codec, &opts, NULL);
3643 if (ret < 0)
3644 goto fail;
3645
3646 if (!av_dict_get(opts, "threads", NULL, 0))
3647 av_dict_set(&opts, "threads", "auto", 0);
3648 if (stream_lowres)
3649 av_dict_set_int(&opts, "lowres", stream_lowres, 0);
3650
3651 av_dict_set(&opts, "flags", "+copy_opaque", AV_DICT_MULTIKEY);
3652
3653 if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) {
3654 ret = create_hwaccel(&avctx->hw_device_ctx);
3655 if (ret < 0)
3656 goto fail;
3657 }
3658
3659 if ((ret = avcodec_open2(avctx, codec, &opts)) < 0) {
3660 goto fail;
3661 }
3662 ret = check_avoptions(opts);
3663 if (ret < 0)
3664 goto fail;
3665
3666 is->eof = 0;
3667 ic->streams[stream_index]->discard = AVDISCARD_DEFAULT;
3668 switch (avctx->codec_type) {
3669 case AVMEDIA_TYPE_AUDIO:
3670 {
3671 AVFilterContext *sink;
3672
3673 is->audio_filter_src.freq = avctx->sample_rate;
3674 ret = av_channel_layout_copy(&is->audio_filter_src.ch_layout, &avctx->ch_layout);
3675 if (ret < 0)
3676 goto fail;
3677 is->audio_filter_src.fmt = avctx->sample_fmt;
3678 if ((ret = configure_audio_filters(is, afilters, 0)) < 0)
3679 goto fail;
3680 sink = is->out_audio_filter;
3681 sample_rate = av_buffersink_get_sample_rate(sink);
3682 ret = av_buffersink_get_ch_layout(sink, &ch_layout);
3683 if (ret < 0)
3684 goto fail;
3685 }
3686
3687 /* prepare audio output */
3688 if ((ret = audio_open(is, &ch_layout, sample_rate, &is->audio_tgt)) < 0)
3689 goto fail;
3690 is->audio_hw_buf_size = ret;
3691 is->audio_src = is->audio_tgt;
3692 is->audio_buf_size = 0;
3693 is->audio_buf_index = 0;
3694
3695 /* init averaging filter */
3696 is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
3697 is->audio_diff_avg_count = 0;
3698 /* since we do not have a precise anough audio FIFO fullness,
3699 we correct audio sync only if larger than this threshold */
3700 is->audio_diff_threshold = (double)(is->audio_hw_buf_size) / is->audio_tgt.bytes_per_sec;
3701
3702 is->audio_stream = stream_index;
3703 is->audio_st = ic->streams[stream_index];
3704
3705 if ((ret = decoder_init(&is->auddec, avctx, &is->audioq, is->continue_read_thread)) < 0)
3706 goto fail;
3707 if (is->ic->iformat->flags & AVFMT_NOTIMESTAMPS) {
3708 is->auddec.start_pts = is->audio_st->start_time;
3709 is->auddec.start_pts_tb = is->audio_st->time_base;
3710 }
3711 if ((ret = decoder_start(&is->auddec, audio_thread, "audio_decoder", is)) < 0)
3712 goto out;
3713 SDL_PauseAudioDevice(audio_dev, 0);
3714 break;
3715 case AVMEDIA_TYPE_VIDEO:
3716 is->video_stream = stream_index;
3717 is->video_st = ic->streams[stream_index];
3718
3719 if (ici->streams[stream_index]->group) {
3720 if ((ret = init_lcevc_graph(ic, stream_index)) < 0)
3721 goto fail;
3722 }
3723 if ((ret = decoder_init(&is->viddec, avctx, &is->videoq, is->continue_read_thread)) < 0)
3724 goto fail;
3725 if ((ret = decoder_start(&is->viddec, video_thread, "video_decoder", is)) < 0)
3726 goto out;
3727 is->queue_attachments_req = 1;
3728 break;
3730 is->subtitle_stream = stream_index;
3731 is->subtitle_st = ic->streams[stream_index];
3732
3733 if ((ret = decoder_init(&is->subdec, avctx, &is->subtitleq, is->continue_read_thread)) < 0)
3734 goto fail;
3735 if ((ret = decoder_start(&is->subdec, subtitle_thread, "subtitle_decoder", is)) < 0)
3736 goto out;
3737 break;
3738 default:
3739 break;
3740 }
3741 goto out;
3742
3743fail:
3744 avcodec_free_context(&avctx);
3745out:
3746 av_channel_layout_uninit(&ch_layout);
3748
3749 return ret;
3750}
3751
3752static int decode_interrupt_cb(void *ctx)
3753{
3754 VideoState *is = ctx;
3755 return is->abort_request;
3756}
3757
3758static int stream_has_enough_packets(AVStream *st, int stream_id, PacketQueue *queue) {
3759 return stream_id < 0 ||
3760 queue->abort_request ||
3762 queue->nb_packets > MIN_FRAMES && (!queue->duration || av_q2d(st->time_base) * queue->duration > 1.0);
3763}
3764
3766{
3767 if( !strcmp(s->iformat->name, "rtp")
3768 || !strcmp(s->iformat->name, "rtsp")
3769 || !strcmp(s->iformat->name, "sdp")
3770 )
3771 return 1;
3772
3773 if(s->pb && ( !strncmp(s->url, "rtp:", 4)
3774 || !strncmp(s->url, "udp:", 4)
3775 )
3776 )
3777 return 1;
3778 return 0;
3779}
3780
3782 Stream *sti, AVPacket *pkt)
3783{
3784 StreamGroup *stgi = sti->group;
3785 AVBitStreamFilterContext *source = sti->filter;
3786 int ret;
3787
3789 if (ret < 0) {
3790 if (pkt)
3792 av_log(NULL, AV_LOG_ERROR, "Error submitting a packet for filtering: %s\n",
3793 av_err2str(ret));
3794 return ret;
3795 }
3796
3797 while (1) {
3798 ret = av_bsf_sink_get_packet(stgi->sink, pkt, 0);
3799 if (ret == AVERROR(EAGAIN))
3800 return 0;
3801 else if (ret < 0) {
3802 if (ret != AVERROR_EOF)
3804 "Error applying bitstream filters to a packet: %s\n",
3805 av_err2str(ret));
3806 return ret;
3807 }
3808 pkt->time_base = av_bsf_sink_get_time_base(stgi->sink);
3809 packet_queue_put(&is->videoq, pkt);
3810 }
3811
3812 return 0;
3813}
3814
3816{
3817 FormatContext *ici = ic->opaque;
3818 int ret;
3819
3820 for (unsigned i = 0; i < ic->nb_streams; i++) {
3821 Stream *sti = ici->streams[i];
3822 StreamGroup *stgi = sti->group;
3823
3824 if (!stgi || !stgi->graph)
3825 continue;
3826
3827 ret = do_bsf_graph(ic, is, sti, NULL);
3828 ret = (ret == AVERROR_EOF) ? 0 : (ret < 0) ? ret : AVERROR_BUG;
3829 if (ret < 0) {
3830 av_log(NULL, AV_LOG_ERROR, "Error flushing BSFs: %s\n",
3831 av_err2str(ret));
3832 return ret;
3833 }
3834 }
3835
3836 return 0;
3837}
3838
3839/* this thread gets the stream from the disk or the network */
3840static int read_thread(void *arg)
3841{
3842 VideoState *is = arg;
3843 AVFormatContext *ic = NULL;
3844 FormatContext *ici = NULL;
3845 int err, i, ret;
3846 int st_index[AVMEDIA_TYPE_NB];
3847 AVPacket *pkt = NULL;
3848 int64_t stream_start_time;
3849 char metadata_description[96];
3850 int pkt_in_play_range = 0;
3851 const AVDictionaryEntry *t;
3852 SDL_mutex *wait_mutex = SDL_CreateMutex();
3853 int scan_all_pmts_set = 0;
3854 int64_t pkt_ts;
3855
3856 if (!wait_mutex) {
3857 av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError());
3858 ret = AVERROR(ENOMEM);
3859 goto fail;
3860 }
3861
3862 memset(st_index, -1, sizeof(st_index));
3863 is->eof = 0;
3864
3865 pkt = av_packet_alloc();
3866 if (!pkt) {
3867 av_log(NULL, AV_LOG_FATAL, "Could not allocate packet.\n");
3868 ret = AVERROR(ENOMEM);
3869 goto fail;
3870 }
3872 if (!ic) {
3873 av_log(NULL, AV_LOG_FATAL, "Could not allocate context.\n");
3874 ret = AVERROR(ENOMEM);
3875 goto fail;
3876 }
3877 ic->opaque = av_mallocz(sizeof(FormatContext));
3878 if (!ic->opaque) {
3879 av_log(NULL, AV_LOG_FATAL, "Could not allocate internal context.\n");
3880 ret = AVERROR(ENOMEM);
3881 goto fail;
3882 }
3885 if (!av_dict_get(format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE)) {
3886 av_dict_set(&format_opts, "scan_all_pmts", "1", AV_DICT_DONT_OVERWRITE);
3887 scan_all_pmts_set = 1;
3888 }
3889 err = avformat_open_input(&ic, is->filename, is->iformat, &format_opts);
3890 if (err < 0) {
3891 print_error(is->filename, err);
3892 ret = -1;
3893 goto fail;
3894 }
3895 if (scan_all_pmts_set)
3896 av_dict_set(&format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE);
3898
3900 if (ret < 0)
3901 goto fail;
3902 is->ic = ic;
3903
3904 if (genpts)
3905 ic->flags |= AVFMT_FLAG_GENPTS;
3906
3907 if (find_stream_info) {
3909 int orig_nb_streams = ic->nb_streams;
3910
3912 if (err < 0) {
3914 "Error setting up avformat_find_stream_info() options\n");
3915 ret = err;
3916 goto fail;
3917 }
3918
3920
3921 for (i = 0; i < orig_nb_streams; i++)
3922 av_dict_free(&opts[i]);
3923 av_freep(&opts);
3924
3925 if (err < 0) {
3927 "%s: could not find codec parameters\n", is->filename);
3928 ret = -1;
3929 goto fail;
3930 }
3931 }
3932
3933 if (ic->pb)
3934 ic->pb->eof_reached = 0; // FIXME hack, ffplay maybe should not use avio_feof() to test for the end
3935
3936 if (seek_by_bytes < 0)
3938 !!(ic->iformat->flags & AVFMT_TS_DISCONT) &&
3939 strcmp("ogg", ic->iformat->name);
3940
3941 is->max_frame_duration = (ic->iformat->flags & AVFMT_TS_DISCONT) ? 10.0 : 3600.0;
3942
3943 if (!window_title && (t = av_dict_get(ic->metadata, "title", NULL, 0)))
3944 window_title = av_asprintf("%s - %s", t->value, input_filename);
3945
3946 /* if seeking requested, we execute it */
3947 if (start_time != AV_NOPTS_VALUE) {
3948 int64_t timestamp;
3949
3950 timestamp = start_time;
3951 /* add the stream start time */
3952 if (ic->start_time != AV_NOPTS_VALUE)
3953 timestamp += ic->start_time;
3954 ret = avformat_seek_file(ic, -1, INT64_MIN, timestamp, INT64_MAX, 0);
3955 if (ret < 0) {
3956 av_log(NULL, AV_LOG_WARNING, "%s: could not seek to position %0.3f\n",
3957 is->filename, (double)timestamp / AV_TIME_BASE);
3958 }
3959 }
3960
3961 is->realtime = is_realtime(ic);
3962
3963 if (show_status) {
3964 fprintf(stderr, "\x1b[2K\r");
3965 av_dump_format(ic, 0, is->filename, 0);
3966 }
3967
3968 ici = ic->opaque;
3969 ici->streams = av_calloc(ic->nb_streams, sizeof(*ici->streams));
3970 if (!ici->streams) {
3971 av_log(NULL, AV_LOG_FATAL, "Could not allocate internal streams context.\n");
3972 ret = AVERROR(ENOMEM);
3973 goto fail;
3974 }
3975 ici->nb_streams = ic->nb_streams;
3976 for (i = 0; i < ic->nb_streams; i++) {
3977 AVStream *st = ic->streams[i];
3978 enum AVMediaType type = st->codecpar->codec_type;
3979 ici->streams[i] = av_mallocz(sizeof(Stream));
3980 if (!ici->streams[i]) {
3981 av_log(NULL, AV_LOG_FATAL, "Could not allocate internal stream context.\n");
3982 ret = AVERROR(ENOMEM);
3983 goto fail;
3984 }
3985 st->discard = AVDISCARD_ALL;
3986 if (type >= 0 && wanted_stream_spec[type] && st_index[type] == -1)
3988 st_index[type] = i;
3989 // Clear all pre-existing metadata update flags to avoid printing
3990 // initial metadata as update.
3992 }
3993 ici->stream_groups = av_calloc(ic->nb_stream_groups, sizeof(*ici->stream_groups));
3994 if (!ici->stream_groups) {
3995 av_log(NULL, AV_LOG_FATAL, "Could not allocate internal stream groups context.\n");
3996 ret = AVERROR(ENOMEM);
3997 goto fail;
3998 }
4000 for (i = 0; i < ic->nb_stream_groups; i++) {
4001 AVStreamGroup *stg = ic->stream_groups[i];
4002
4003 ici->stream_groups[i] = av_mallocz(sizeof(*ici->stream_groups[i]));
4004 if (!ici->stream_groups[i]) {
4005 av_log(NULL, AV_LOG_FATAL, "Could not allocate internal stream group.\n");
4006 ret = AVERROR(ENOMEM);
4007 goto fail;
4008 }
4009 ici->stream_groups[i]->stg = stg;
4010
4012 continue;
4013 if (!av_bsf_get_by_name("lcevc_merge") || stg->nb_entries != 2)
4014 continue;
4015 for (int j = 0; j < stg->nb_entries; j++) {
4016 AVStreamGroupEntry *entry = stg->entries[j];
4017 if (entry->type != AV_STREAM_GROUP_ENTRY_STREAM) {
4018 ret = AVERROR_BUG;
4019 goto fail;
4020 }
4021 }
4022
4024 const AVStream *base_st = ic->streams[stg->entries[!lcevc->el_index]->stream->index];
4025 Stream *base_sti = ici->streams[base_st->index];
4026
4027 base_sti->group = ici->stream_groups[i];
4028 }
4030 for (i = 0; i < AVMEDIA_TYPE_NB; i++) {
4031 if (wanted_stream_spec[i] && st_index[i] == -1) {
4032 av_log(NULL, AV_LOG_ERROR, "Stream specifier %s does not match any %s stream\n", wanted_stream_spec[i], av_get_media_type_string(i));
4033 st_index[i] = INT_MAX;
4034 }
4035 }
4036
4037 if (!video_disable)
4038 st_index[AVMEDIA_TYPE_VIDEO] =
4040 st_index[AVMEDIA_TYPE_VIDEO], -1, NULL, 0);
4041 if (!audio_disable)
4042 st_index[AVMEDIA_TYPE_AUDIO] =
4044 st_index[AVMEDIA_TYPE_AUDIO],
4045 st_index[AVMEDIA_TYPE_VIDEO],
4046 NULL, 0);
4048 st_index[AVMEDIA_TYPE_SUBTITLE] =
4050 st_index[AVMEDIA_TYPE_SUBTITLE],
4051 (st_index[AVMEDIA_TYPE_AUDIO] >= 0 ?
4052 st_index[AVMEDIA_TYPE_AUDIO] :
4053 st_index[AVMEDIA_TYPE_VIDEO]),
4054 NULL, 0);
4055
4056 is->show_mode = show_mode;
4057 if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) {
4058 AVStream *st = ic->streams[st_index[AVMEDIA_TYPE_VIDEO]];
4059 AVCodecParameters *codecpar = st->codecpar;
4061 if (codecpar->width)
4062 set_default_window_size(codecpar->width, codecpar->height, sar);
4063 }
4064
4065 /* open the streams */
4066 if (st_index[AVMEDIA_TYPE_AUDIO] >= 0) {
4068 }
4069
4070 ret = -1;
4071 if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) {
4073 }
4074 if (is->show_mode == SHOW_MODE_NONE)
4075 is->show_mode = ret >= 0 ? SHOW_MODE_VIDEO : SHOW_MODE_RDFT;
4076
4077 if (st_index[AVMEDIA_TYPE_SUBTITLE] >= 0) {
4079 }
4080
4081 if (is->video_stream < 0 && is->audio_stream < 0) {
4082 av_log(NULL, AV_LOG_FATAL, "Failed to open file '%s' or configure filtergraph\n",
4083 is->filename);
4084 ret = -1;
4085 goto fail;
4086 }
4087
4088 if (infinite_buffer < 0 && is->realtime)
4089 infinite_buffer = 1;
4090
4091 for (;;) {
4092 if (is->abort_request)
4093 break;
4094 if (is->paused != is->last_paused) {
4095 is->last_paused = is->paused;
4096 if (is->paused)
4097 is->read_pause_return = av_read_pause(ic);
4098 else
4099 av_read_play(ic);
4100 }
4101#if CONFIG_RTSP_DEMUXER || CONFIG_MMSH_PROTOCOL
4102 if (is->paused &&
4103 (!strcmp(ic->iformat->name, "rtsp") ||
4104 (ic->pb && !strncmp(input_filename, "mmsh:", 5)))) {
4105 /* wait 10 ms to avoid trying to get another packet */
4106 /* XXX: horrible */
4107 SDL_Delay(10);
4108 continue;
4109 }
4110#endif
4111 if (is->seek_req) {
4112 int64_t seek_target = is->seek_pos;
4113 int64_t seek_min = is->seek_rel > 0 ? seek_target - is->seek_rel + 2: INT64_MIN;
4114 int64_t seek_max = is->seek_rel < 0 ? seek_target - is->seek_rel - 2: INT64_MAX;
4115// FIXME the +-2 is due to rounding being not done in the correct direction in generation
4116// of the seek_pos/seek_rel variables
4117
4118 ret = avformat_seek_file(is->ic, -1, seek_min, seek_target, seek_max, is->seek_flags);
4119 if (ret < 0) {
4121 "%s: error while seeking\n", is->ic->url);
4122 } else {
4123 if (is->audio_stream >= 0)
4124 packet_queue_flush(&is->audioq);
4125 if (is->subtitle_stream >= 0)
4126 packet_queue_flush(&is->subtitleq);
4127 if (is->video_stream >= 0) {
4128 packet_queue_flush(&is->videoq);
4129 uninit_bsf_graph(is->ic, is->video_stream);
4130 if (ici->streams[is->video_stream]->group) {
4131 if ((ret = init_lcevc_graph(is->ic, is->video_stream)) < 0)
4132 goto fail;
4133 }
4134 }
4135 if (is->seek_flags & AVSEEK_FLAG_BYTE) {
4136 set_clock(&is->extclk, NAN, 0);
4137 } else {
4138 set_clock(&is->extclk, seek_target / (double)AV_TIME_BASE, 0);
4139 }
4140 }
4141 is->seek_req = 0;
4142 is->queue_attachments_req = 1;
4143 is->eof = 0;
4144 if (is->paused)
4146 }
4147 if (is->queue_attachments_req) {
4148 if (is->video_st && is->video_st->disposition & AV_DISPOSITION_ATTACHED_PIC) {
4149 if ((ret = av_packet_ref(pkt, &is->video_st->attached_pic)) < 0)
4150 goto fail;
4151 packet_queue_put(&is->videoq, pkt);
4152 packet_queue_put_nullpacket(&is->videoq, pkt, is->video_stream);
4153 }
4154 is->queue_attachments_req = 0;
4155 }
4156
4157 /* if the queue are full, no need to read more */
4158 if (infinite_buffer<1 &&
4159 (is->audioq.size + is->videoq.size + is->subtitleq.size > MAX_QUEUE_SIZE
4160 || (stream_has_enough_packets(is->audio_st, is->audio_stream, &is->audioq) &&
4161 stream_has_enough_packets(is->video_st, is->video_stream, &is->videoq) &&
4162 stream_has_enough_packets(is->subtitle_st, is->subtitle_stream, &is->subtitleq)))) {
4163 /* wait 10 ms */
4164 SDL_LockMutex(wait_mutex);
4165 SDL_CondWaitTimeout(is->continue_read_thread, wait_mutex, 10);
4166 SDL_UnlockMutex(wait_mutex);
4167 continue;
4168 }
4169 if (!is->paused &&
4170 (!is->audio_st || (is->auddec.finished == is->audioq.serial && frame_queue_nb_remaining(&is->sampq) == 0)) &&
4171 (!is->video_st || (is->viddec.finished == is->videoq.serial && frame_queue_nb_remaining(&is->pictq) == 0))) {
4172 if (loop != 1 && (!loop || --loop)) {
4174 } else if (autoexit) {
4175 ret = AVERROR_EOF;
4176 goto fail;
4177 }
4178 }
4179 ret = av_read_frame(ic, pkt);
4180 if (ret < 0) {
4181 if ((ret == AVERROR_EOF || avio_feof(ic->pb)) && !is->eof) {
4182 if (is->video_stream >= 0) {
4183 ret = do_bsf_flush(ic, is);
4184 if (ret < 0)
4185 goto fail;
4186 packet_queue_put_nullpacket(&is->videoq, pkt, is->video_stream);
4187 }
4188 if (is->audio_stream >= 0)
4189 packet_queue_put_nullpacket(&is->audioq, pkt, is->audio_stream);
4190 if (is->subtitle_stream >= 0)
4191 packet_queue_put_nullpacket(&is->subtitleq, pkt, is->subtitle_stream);
4192 is->eof = 1;
4193 }
4194 if (ic->pb && ic->pb->error) {
4195 if (autoexit)
4196 goto fail;
4197 else
4198 break;
4199 }
4200 SDL_LockMutex(wait_mutex);
4201 SDL_CondWaitTimeout(is->continue_read_thread, wait_mutex, 10);
4202 SDL_UnlockMutex(wait_mutex);
4203 continue;
4204 } else {
4205 is->eof = 0;
4206 }
4207
4208 if (show_status) {
4210 fprintf(stderr, "\x1b[2K\r");
4212 "\r New metadata", " ", AV_LOG_INFO);
4213 }
4214 if (ic->streams[pkt->stream_index]->event_flags &
4216 fprintf(stderr, "\x1b[2K\r");
4217 snprintf(metadata_description,
4218 sizeof(metadata_description),
4219 "\r New metadata for stream %d",
4220 pkt->stream_index);
4221 dump_dictionary(NULL, ic->streams[pkt->stream_index]->metadata,
4222 metadata_description, " ", AV_LOG_INFO);
4223 }
4224 }
4227
4228 /* check if packet is in play range specified by user, then queue, otherwise discard */
4229 stream_start_time = ic->streams[pkt->stream_index]->start_time;
4230 pkt_ts = pkt->pts == AV_NOPTS_VALUE ? pkt->dts : pkt->pts;
4231 pkt_in_play_range = duration == AV_NOPTS_VALUE ||
4232 (pkt_ts - (stream_start_time != AV_NOPTS_VALUE ? stream_start_time : 0)) *
4233 av_q2d(ic->streams[pkt->stream_index]->time_base) -
4234 (double)(start_time != AV_NOPTS_VALUE ? start_time : 0) / 1000000
4235 <= ((double)duration / 1000000);
4236 if (pkt->stream_index == is->audio_stream && pkt_in_play_range) {
4237 packet_queue_put(&is->audioq, pkt);
4238 } else if (pkt->stream_index == is->video_stream && pkt_in_play_range
4239 && !(is->video_st->disposition & AV_DISPOSITION_ATTACHED_PIC)) {
4240 Stream *sti = ici->streams[is->video_stream];
4241 StreamGroup *stgi = sti->group;
4242 if (stgi && stgi->graph) {
4243 ret = do_bsf_graph(ic, is, sti, pkt);
4244 if (ret < 0)
4245 goto fail;
4246 } else
4247 packet_queue_put(&is->videoq, pkt);
4248 } else if (pkt->stream_index == is->subtitle_stream && pkt_in_play_range) {
4249 packet_queue_put(&is->subtitleq, pkt);
4250 } else {
4251 Stream *sti = ici->streams[pkt->stream_index];
4252 StreamGroup *stgi = sti->group;
4253 if (stgi && stgi->graph) {
4254 ret = do_bsf_graph(ic, is, sti, pkt);
4255 if (ret < 0)
4256 goto fail;
4257 }
4259 }
4260 }
4261
4262 ret = 0;
4263 fail:
4264 if (ic && !is->ic) {
4265 av_freep(&ic->opaque);
4267 }
4268
4270 if (ret != 0) {
4271 SDL_Event event;
4272
4273 event.type = FF_QUIT_EVENT;
4274 event.user.data1 = is;
4275 SDL_PushEvent(&event);
4276 }
4277 SDL_DestroyMutex(wait_mutex);
4278 return 0;
4279}
4280
4281static VideoState *stream_open(const char *filename,
4282 const AVInputFormat *iformat)
4283{
4284 VideoState *is;
4285
4286 is = av_mallocz(sizeof(VideoState));
4287 if (!is)
4288 return NULL;
4289 is->last_video_stream = is->video_stream = -1;
4290 is->last_audio_stream = is->audio_stream = -1;
4291 is->last_subtitle_stream = is->subtitle_stream = -1;
4292 is->filename = av_strdup(filename);
4293 if (!is->filename)
4294 goto fail;
4295 is->iformat = iformat;
4296 is->ytop = 0;
4297 is->xleft = 0;
4298
4299 /* start video display */
4300 if (frame_queue_init(&is->pictq, &is->videoq, VIDEO_PICTURE_QUEUE_SIZE, 1) < 0)
4301 goto fail;
4302 if (frame_queue_init(&is->subpq, &is->subtitleq, SUBPICTURE_QUEUE_SIZE, 0) < 0)
4303 goto fail;
4304 if (frame_queue_init(&is->sampq, &is->audioq, SAMPLE_QUEUE_SIZE, 1) < 0)
4305 goto fail;
4306
4307 if (packet_queue_init(&is->videoq) < 0 ||
4308 packet_queue_init(&is->audioq) < 0 ||
4309 packet_queue_init(&is->subtitleq) < 0)
4310 goto fail;
4311
4312 if (!(is->continue_read_thread = SDL_CreateCond())) {
4313 av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError());
4314 goto fail;
4315 }
4316
4317 init_clock(&is->vidclk, &is->videoq.serial);
4318 init_clock(&is->audclk, &is->audioq.serial);
4319 init_clock(&is->extclk, &is->extclk.serial);
4320 is->audio_clock_serial = -1;
4321 if (startup_volume < 0)
4322 av_log(NULL, AV_LOG_WARNING, "-volume=%d < 0, setting to 0\n", startup_volume);
4323 if (startup_volume > 100)
4324 av_log(NULL, AV_LOG_WARNING, "-volume=%d > 100, setting to 100\n", startup_volume);
4325 if (video_background) {
4326 if (!strcmp(video_background, "none")) {
4327 is->render_params.video_background_type = VIDEO_BACKGROUND_NONE;
4328 } else if (strcmp(video_background, "tiles")) {
4329 if (av_parse_color(is->render_params.video_background_color, video_background, -1, NULL) >= 0)
4330 is->render_params.video_background_type = VIDEO_BACKGROUND_COLOR;
4331 else
4332 goto fail;
4333 }
4334 }
4336 startup_volume = av_clip(SDL_MIX_MAXVOLUME * startup_volume / 100, 0, SDL_MIX_MAXVOLUME);
4337 is->audio_volume = startup_volume;
4338 is->muted = 0;
4339 is->av_sync_type = av_sync_type;
4340 is->read_tid = SDL_CreateThread(read_thread, "read_thread", is);
4341 if (!is->read_tid) {
4342 av_log(NULL, AV_LOG_FATAL, "SDL_CreateThread(): %s\n", SDL_GetError());
4343fail:
4345 return NULL;
4346 }
4347 return is;
4348}
4349
4351{
4352 AVFormatContext *ic = is->ic;
4353 int start_index, stream_index;
4354 int old_index;
4355 AVStream *st;
4356 AVProgram *p = NULL;
4357 int nb_streams = is->ic->nb_streams;
4358
4360 start_index = is->last_video_stream;
4361 old_index = is->video_stream;
4362 } else if (codec_type == AVMEDIA_TYPE_AUDIO) {
4363 start_index = is->last_audio_stream;
4364 old_index = is->audio_stream;
4365 } else {
4366 start_index = is->last_subtitle_stream;
4367 old_index = is->subtitle_stream;
4368 }
4369 stream_index = start_index;
4370
4371 if (codec_type != AVMEDIA_TYPE_VIDEO && is->video_stream != -1) {
4372 p = av_find_program_from_stream(ic, NULL, is->video_stream);
4373 if (p) {
4374 nb_streams = p->nb_stream_indexes;
4375 for (start_index = 0; start_index < nb_streams; start_index++)
4376 if (p->stream_index[start_index] == stream_index)
4377 break;
4378 if (start_index == nb_streams)
4379 start_index = -1;
4380 stream_index = start_index;
4381 }
4382 }
4383
4384 for (;;) {
4385 if (++stream_index >= nb_streams)
4386 {
4388 {
4389 stream_index = -1;
4390 is->last_subtitle_stream = -1;
4391 goto the_end;
4392 }
4393 if (start_index == -1)
4394 return;
4395 stream_index = 0;
4396 }
4397 if (stream_index == start_index)
4398 return;
4399 st = is->ic->streams[p ? p->stream_index[stream_index] : stream_index];
4400 if (st->codecpar->codec_type == codec_type) {
4401 /* check that parameters are OK */
4402 switch (codec_type) {
4403 case AVMEDIA_TYPE_AUDIO:
4404 if (st->codecpar->sample_rate != 0 &&
4405 st->codecpar->ch_layout.nb_channels != 0)
4406 goto the_end;
4407 break;
4408 case AVMEDIA_TYPE_VIDEO:
4410 goto the_end;
4411 default:
4412 break;
4413 }
4414 }
4415 }
4416 the_end:
4417 if (p && stream_index != -1)
4418 stream_index = p->stream_index[stream_index];
4419 av_log(NULL, AV_LOG_INFO, "Switch %s stream from #%d to #%d\n",
4421 old_index,
4422 stream_index);
4423
4424 stream_component_close(is, old_index);
4425 stream_component_open(is, stream_index);
4426}
4427
4428
4430{
4432 SDL_SetWindowFullscreen(window, is_full_screen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
4433}
4434
4436{
4437 int next = is->show_mode;
4438 do {
4439 next = (next + 1) % SHOW_MODE_NB;
4440 } while (next != is->show_mode && (next == SHOW_MODE_VIDEO && !is->video_st || next != SHOW_MODE_VIDEO && !is->audio_st));
4441 if (is->show_mode != next) {
4442 is->force_refresh = 1;
4443 is->show_mode = next;
4444 }
4445}
4446
4447static void refresh_loop_wait_event(VideoState *is, SDL_Event *event) {
4448 double remaining_time = 0.0;
4449 SDL_PumpEvents();
4450 while (!SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)) {
4451 if (received_sigterm) {
4452 exit_status = 123;
4453 do_exit(is);
4454 }
4456 SDL_ShowCursor(0);
4457 cursor_hidden = 1;
4458 }
4459 if (remaining_time > 0.0) {
4460 if (!wait_for_events)
4461 av_usleep((int64_t)(remaining_time * 1000000.0));
4462 else if (SDL_WaitEventTimeout(NULL, ceil(remaining_time * 1000)))
4463 continue;
4464 }
4465 remaining_time = REFRESH_RATE;
4466 if (is->chapter_render_pending || (chapter_list_visible(is) && current_chapter(is) != is->chapter_playing))
4468 if (chapter_list_alpha(is, av_gettime_relative()) != is->chapter_drawn_alpha)
4469 is->force_refresh = 1;
4470 if (is->show_mode != SHOW_MODE_NONE && (!is->paused || is->force_refresh))
4471 video_refresh(is, &remaining_time);
4472 SDL_PumpEvents();
4473 }
4474}
4475
4476/* index of the chapter containing the current playback position, -1 before the first one */
4478{
4480 int i;
4481
4482 for (i = 0; i < is->ic->nb_chapters; i++) {
4483 AVChapter *ch = is->ic->chapters[i];
4484 if (av_compare_ts(pos, AV_TIME_BASE_Q, ch->start, ch->time_base) < 0)
4485 break;
4486 }
4487 return i - 1;
4488}
4489
4490static void seek_chapter(VideoState *is, int i)
4491{
4492 i = FFMAX(i, 0);
4493 chapter_list_show(is, FFMIN(i, is->ic->nb_chapters - 1));
4494 if (i >= is->ic->nb_chapters)
4495 return;
4496
4497 av_log(NULL, AV_LOG_VERBOSE, "Seeking to chapter %d.\n", i);
4498 stream_seek(is, av_rescale_q(is->ic->chapters[i]->start, is->ic->chapters[i]->time_base,
4499 AV_TIME_BASE_Q), 0, 0);
4500}
4501
4502/* handle an event sent by the GUI */
4503static void event_loop(VideoState *cur_stream)
4504{
4505 SDL_Event event;
4506 double incr, pos, frac;
4507
4508 for (;;) {
4509 double x;
4510 refresh_loop_wait_event(cur_stream, &event);
4511 switch (event.type) {
4512 case SDL_KEYDOWN:
4513 if (exit_on_keydown || (!cur_stream->chapter_pinned &&
4514 (event.key.keysym.sym == SDLK_ESCAPE || event.key.keysym.sym == SDLK_q))) {
4515 do_exit(cur_stream);
4516 break;
4517 }
4518 // If we don't yet have a window, skip all key events, because read_thread might still be initializing...
4519 if (!cur_stream->width)
4520 continue;
4521 if (cur_stream->chapter_pinned) {
4522 chapter_list_key(cur_stream, event.key.keysym.sym);
4523 break;
4524 }
4525 switch (event.key.keysym.sym) {
4526 case SDLK_f:
4527 toggle_full_screen(cur_stream);
4528 cur_stream->force_refresh = 1;
4529 break;
4530 case SDLK_p:
4531 case SDLK_SPACE:
4532 toggle_pause(cur_stream);
4533 break;
4534 case SDLK_m:
4535 toggle_mute(cur_stream);
4536 break;
4537 case SDLK_KP_MULTIPLY:
4538 case SDLK_0:
4539 update_volume(cur_stream, 1, SDL_VOLUME_STEP);
4540 break;
4541 case SDLK_KP_DIVIDE:
4542 case SDLK_9:
4543 update_volume(cur_stream, -1, SDL_VOLUME_STEP);
4544 break;
4545 case SDLK_s: // S: Step to next frame
4546 step_to_next_frame(cur_stream);
4547 break;
4548 case SDLK_a:
4550 break;
4551 case SDLK_v:
4553 break;
4554 case SDLK_c:
4558 break;
4559 case SDLK_t:
4561 break;
4562 case SDLK_l:
4563 cur_stream->chapter_pin_requested = cur_stream->ic->nb_chapters > 0;
4564 break;
4565 case SDLK_RETURN:
4566 case SDLK_KP_ENTER:
4567 if (chapter_list_visible(cur_stream) && cur_stream->nb_chapter_rows)
4568 seek_chapter(cur_stream, cur_stream->chapter_rows[cur_stream->chapter_selected].index);
4569 break;
4570 case SDLK_w:
4571 if (cur_stream->show_mode == SHOW_MODE_VIDEO && cur_stream->vfilter_idx < nb_vfilters - 1) {
4572 if (++cur_stream->vfilter_idx >= nb_vfilters)
4573 cur_stream->vfilter_idx = 0;
4574 } else {
4575 cur_stream->vfilter_idx = 0;
4576 toggle_audio_display(cur_stream);
4577 }
4578 break;
4579 case SDLK_PAGEUP:
4580 if (cur_stream->ic->nb_chapters <= 1) {
4581 incr = 600.0;
4582 goto do_seek;
4583 }
4584 seek_chapter(cur_stream, current_chapter(cur_stream) + 1);
4585 break;
4586 case SDLK_PAGEDOWN:
4587 if (cur_stream->ic->nb_chapters <= 1) {
4588 incr = -600.0;
4589 goto do_seek;
4590 }
4591 seek_chapter(cur_stream, current_chapter(cur_stream) - 1);
4592 break;
4593 case SDLK_LEFT:
4594 incr = seek_interval ? -seek_interval : -10.0;
4595 goto do_seek;
4596 case SDLK_RIGHT:
4597 incr = seek_interval ? seek_interval : 10.0;
4598 goto do_seek;
4599 case SDLK_UP:
4600 incr = 60.0;
4601 goto do_seek;
4602 case SDLK_DOWN:
4603 incr = -60.0;
4604 do_seek:
4605 if (seek_by_bytes) {
4606 pos = -1;
4608 pos = frame_queue_last_pos(&cur_stream->pictq);
4610 pos = frame_queue_last_pos(&cur_stream->sampq);
4611 if (pos < 0)
4612 pos = avio_tell(cur_stream->ic->pb);
4613 if (cur_stream->ic->bit_rate)
4614 incr *= cur_stream->ic->bit_rate / 8.0;
4615 else
4616 incr *= 180000.0;
4617 pos += incr;
4618 stream_seek(cur_stream, pos, incr, 1);
4619 } else {
4620 pos = get_master_clock(cur_stream);
4621 if (isnan(pos))
4622 pos = (double)cur_stream->seek_pos / AV_TIME_BASE;
4623 pos += incr;
4624 if (cur_stream->ic->start_time != AV_NOPTS_VALUE && pos < cur_stream->ic->start_time / (double)AV_TIME_BASE)
4625 pos = cur_stream->ic->start_time / (double)AV_TIME_BASE;
4626 stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), (int64_t)(incr * AV_TIME_BASE), 0);
4627 }
4628 break;
4629 default:
4630 break;
4631 }
4632 break;
4633 case SDL_KEYUP:
4634 /* on the release of a press made while unpinned, so that the key's own text input does not start the search */
4635 if (event.key.keysym.sym == SDLK_l && cur_stream->chapter_pin_requested)
4636 chapter_list_pin(cur_stream, 1);
4637 cur_stream->chapter_pin_requested = 0;
4638 break;
4639 case SDL_TEXTINPUT:
4640 if (cur_stream->chapter_pinned)
4641 chapter_list_search(cur_stream, event.text.text);
4642 break;
4643 case SDL_MOUSEWHEEL:
4644 if (chapter_list_visible(cur_stream))
4645 chapter_list_move(cur_stream, -event.wheel.y);
4646 break;
4647 case SDL_MOUSEBUTTONDOWN:
4648 if (exit_on_mousedown) {
4649 do_exit(cur_stream);
4650 break;
4651 }
4652 if (event.button.button == SDL_BUTTON_LEFT && chapter_list_visible(cur_stream) &&
4653 chapter_list_click(cur_stream, event.button.x, event.button.y))
4654 break;
4655 if (event.button.button == SDL_BUTTON_LEFT) {
4656 static int64_t last_mouse_left_click = 0;
4657 if (av_gettime_relative() - last_mouse_left_click <= 500000) {
4658 toggle_full_screen(cur_stream);
4659 cur_stream->force_refresh = 1;
4660 last_mouse_left_click = 0;
4661 } else {
4662 last_mouse_left_click = av_gettime_relative();
4663 }
4664 }
4666 case SDL_MOUSEMOTION:
4667 if (cursor_hidden) {
4668 SDL_ShowCursor(1);
4669 cursor_hidden = 0;
4670 }
4672 if (event.type == SDL_MOUSEMOTION)
4673 chapter_list_hover(cur_stream, event.motion.x, event.motion.y);
4674 if (event.type == SDL_MOUSEBUTTONDOWN) {
4675 if (event.button.button != SDL_BUTTON_RIGHT)
4676 break;
4677 x = event.button.x;
4678 } else {
4679 if (!(event.motion.state & SDL_BUTTON_RMASK))
4680 break;
4681 x = event.motion.x;
4682 }
4683 if (seek_by_bytes || cur_stream->ic->duration <= 0) {
4684 uint64_t size = avio_size(cur_stream->ic->pb);
4685 stream_seek(cur_stream, size*x/cur_stream->width, 0, 1);
4686 } else {
4687 int64_t ts;
4688 int ns, hh, mm, ss;
4689 int tns, thh, tmm, tss;
4690 tns = cur_stream->ic->duration / 1000000LL;
4691 thh = tns / 3600;
4692 tmm = (tns % 3600) / 60;
4693 tss = (tns % 60);
4694 frac = x / cur_stream->width;
4695 ns = frac * tns;
4696 hh = ns / 3600;
4697 mm = (ns % 3600) / 60;
4698 ss = (ns % 60);
4700 "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
4701 hh, mm, ss, thh, tmm, tss);
4702 ts = frac * cur_stream->ic->duration;
4703 if (cur_stream->ic->start_time != AV_NOPTS_VALUE)
4704 ts += cur_stream->ic->start_time;
4705 stream_seek(cur_stream, ts, 0, 0);
4706 }
4707 break;
4708 case SDL_WINDOWEVENT:
4709 switch (event.window.event) {
4710 case SDL_WINDOWEVENT_LEAVE:
4711 chapter_list_hover(cur_stream, -1, -1);
4712 break;
4713 case SDL_WINDOWEVENT_SIZE_CHANGED:
4714 screen_width = cur_stream->width = event.window.data1;
4715 screen_height = cur_stream->height = event.window.data2;
4716 if (cur_stream->vis_texture) {
4717 SDL_DestroyTexture(cur_stream->vis_texture);
4718 cur_stream->vis_texture = NULL;
4719 }
4720 if (cur_stream->chapter_bitmap)
4721 cur_stream->chapter_render_pending = 1;
4722 if (vk_renderer)
4725 case SDL_WINDOWEVENT_EXPOSED:
4726 cur_stream->force_refresh = 1;
4727 }
4728 break;
4729 case SDL_QUIT:
4730 case FF_QUIT_EVENT:
4731 do_exit(cur_stream);
4732 break;
4733 default:
4734 break;
4735 }
4736 }
4737}
4738
4739static int opt_width(void *optctx, const char *opt, const char *arg)
4740{
4741 double num;
4742 int ret = parse_number(opt, arg, OPT_TYPE_INT64, 1, INT_MAX, &num);
4743 if (ret < 0)
4744 return ret;
4745
4746 screen_width = num;
4747 return 0;
4748}
4749
4750static int opt_height(void *optctx, const char *opt, const char *arg)
4751{
4752 double num;
4753 int ret = parse_number(opt, arg, OPT_TYPE_INT64, 1, INT_MAX, &num);
4754 if (ret < 0)
4755 return ret;
4756
4758 return 0;
4759}
4760
4761static int opt_format(void *optctx, const char *opt, const char *arg)
4762{
4764 if (!file_iformat) {
4765 av_log(NULL, AV_LOG_FATAL, "Unknown input format: %s\n", arg);
4766 return AVERROR(EINVAL);
4767 }
4768 return 0;
4769}
4770
4771static int opt_sync(void *optctx, const char *opt, const char *arg)
4772{
4773 if (!strcmp(arg, "audio"))
4775 else if (!strcmp(arg, "video"))
4777 else if (!strcmp(arg, "ext"))
4779 else {
4780 av_log(NULL, AV_LOG_ERROR, "Unknown value for %s: %s\n", opt, arg);
4781 exit(1);
4782 }
4783 return 0;
4784}
4785
4786static int opt_show_mode(void *optctx, const char *opt, const char *arg)
4787{
4788 show_mode = !strcmp(arg, "video") ? SHOW_MODE_VIDEO :
4789 !strcmp(arg, "waves") ? SHOW_MODE_WAVES :
4790 !strcmp(arg, "rdft" ) ? SHOW_MODE_RDFT : SHOW_MODE_NONE;
4791
4792 if (show_mode == SHOW_MODE_NONE) {
4793 double num;
4794 int ret = parse_number(opt, arg, OPT_TYPE_INT, 0, SHOW_MODE_NB-1, &num);
4795 if (ret < 0)
4796 return ret;
4797 show_mode = num;
4798 }
4799 return 0;
4800}
4801
4802static int opt_input_file(void *optctx, const char *filename)
4803{
4804 if (input_filename) {
4806 "Argument '%s' provided as input filename, but '%s' was already specified.\n",
4807 filename, input_filename);
4808 return AVERROR(EINVAL);
4809 }
4810 if (!strcmp(filename, "-"))
4811 filename = "fd:";
4812 input_filename = av_strdup(filename);
4813 if (!input_filename)
4814 return AVERROR(ENOMEM);
4815
4816 return 0;
4817}
4818
4819static int opt_codec(void *optctx, const char *opt, const char *arg)
4820{
4821 const char *spec = strchr(opt, ':');
4822 const char **name;
4823 if (!spec) {
4825 "No media specifier was specified in '%s' in option '%s'\n",
4826 arg, opt);
4827 return AVERROR(EINVAL);
4828 }
4829 spec++;
4830
4831 switch (spec[0]) {
4832 case 'a' : name = &audio_codec_name; break;
4833 case 's' : name = &subtitle_codec_name; break;
4834 case 'v' : name = &video_codec_name; break;
4835 default:
4837 "Invalid media specifier '%s' in option '%s'\n", spec, opt);
4838 return AVERROR(EINVAL);
4839 }
4840
4841 av_freep(name);
4842 *name = av_strdup(arg);
4843 return *name ? 0 : AVERROR(ENOMEM);
4844}
4845
4846static int dummy;
4847
4848static const OptionDef options[] = {
4850 { "x", OPT_TYPE_FUNC, OPT_FUNC_ARG, { .func_arg = opt_width }, "force displayed width", "width" },
4851 { "y", OPT_TYPE_FUNC, OPT_FUNC_ARG, { .func_arg = opt_height }, "force displayed height", "height" },
4852 { "fs", OPT_TYPE_BOOL, 0, { &is_full_screen }, "force full screen" },
4853 { "an", OPT_TYPE_BOOL, 0, { &audio_disable }, "disable audio" },
4854 { "vn", OPT_TYPE_BOOL, 0, { &video_disable }, "disable video" },
4855 { "sn", OPT_TYPE_BOOL, 0, { &subtitle_disable }, "disable subtitling" },
4856 { "ast", OPT_TYPE_STRING, OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_AUDIO] }, "select desired audio stream", "stream_specifier" },
4857 { "vst", OPT_TYPE_STRING, OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_VIDEO] }, "select desired video stream", "stream_specifier" },
4858 { "sst", OPT_TYPE_STRING, OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_SUBTITLE] }, "select desired subtitle stream", "stream_specifier" },
4859 { "ss", OPT_TYPE_TIME, 0, { &start_time }, "seek to a given position in seconds", "pos" },
4860 { "t", OPT_TYPE_TIME, 0, { &duration }, "play \"duration\" seconds of audio/video", "duration" },
4861 { "bytes", OPT_TYPE_INT, 0, { &seek_by_bytes }, "seek by bytes 0=off 1=on -1=auto", "val" },
4862 { "seek_interval", OPT_TYPE_FLOAT, 0, { &seek_interval }, "set seek interval for left/right keys, in seconds", "seconds" },
4863 { "nodisp", OPT_TYPE_BOOL, 0, { &display_disable }, "disable graphical display" },
4864 { "noborder", OPT_TYPE_BOOL, 0, { &borderless }, "borderless window" },
4865 { "alwaysontop", OPT_TYPE_BOOL, 0, { &alwaysontop }, "window always on top" },
4866 { "volume", OPT_TYPE_INT, 0, { &startup_volume}, "set startup volume 0=min 100=max", "volume" },
4867 { "f", OPT_TYPE_FUNC, OPT_FUNC_ARG, { .func_arg = opt_format }, "force format", "fmt" },
4868 { "stats", OPT_TYPE_BOOL, OPT_EXPERT, { &show_status }, "show status", "" },
4869 { "fast", OPT_TYPE_BOOL, OPT_EXPERT, { &fast }, "non spec compliant optimizations", "" },
4870 { "genpts", OPT_TYPE_BOOL, OPT_EXPERT, { &genpts }, "generate pts", "" },
4871 { "drp", OPT_TYPE_INT, OPT_EXPERT, { &decoder_reorder_pts }, "let decoder reorder pts 0=off 1=on -1=auto", ""},
4872 { "lowres", OPT_TYPE_INT, OPT_EXPERT, { &lowres }, "", "" },
4873 { "sync", OPT_TYPE_FUNC, OPT_FUNC_ARG | OPT_EXPERT, { .func_arg = opt_sync }, "set audio-video sync. type (type=audio/video/ext)", "type" },
4874 { "autoexit", OPT_TYPE_BOOL, OPT_EXPERT, { &autoexit }, "exit at the end", "" },
4875 { "exitonkeydown", OPT_TYPE_BOOL, OPT_EXPERT, { &exit_on_keydown }, "exit on key down", "" },
4876 { "exitonmousedown", OPT_TYPE_BOOL, OPT_EXPERT, { &exit_on_mousedown }, "exit on mouse down", "" },
4877 { "loop", OPT_TYPE_INT, OPT_EXPERT, { &loop }, "set number of times the playback shall be looped", "loop count" },
4878 { "framedrop", OPT_TYPE_BOOL, OPT_EXPERT, { &framedrop }, "drop frames when cpu is too slow", "" },
4879 { "infbuf", OPT_TYPE_BOOL, OPT_EXPERT, { &infinite_buffer }, "don't limit the input buffer size (useful with realtime streams)", "" },
4880 { "window_title", OPT_TYPE_STRING, 0, { &window_title }, "set window title", "window title" },
4881 { "left", OPT_TYPE_INT, OPT_EXPERT, { &screen_left }, "set the x position for the left of the window", "x pos" },
4882 { "top", OPT_TYPE_INT, OPT_EXPERT, { &screen_top }, "set the y position for the top of the window", "y pos" },
4883 { "vf", OPT_TYPE_FUNC, OPT_FUNC_ARG | OPT_EXPERT, { .func_arg = opt_add_vfilter }, "set video filters", "filter_graph" },
4884 { "af", OPT_TYPE_STRING, 0, { &afilters }, "set audio filters", "filter_graph" },
4885 { "rdftspeed", OPT_TYPE_INT, OPT_AUDIO | OPT_EXPERT, { &rdftspeed }, "rdft speed", "msecs" },
4886 { "showmode", OPT_TYPE_FUNC, OPT_FUNC_ARG, { .func_arg = opt_show_mode}, "select show mode (0 = video, 1 = waves, 2 = RDFT)", "mode" },
4887 { "i", OPT_TYPE_BOOL, 0, { &dummy}, "read specified file", "input_file"},
4888 { "codec", OPT_TYPE_FUNC, OPT_FUNC_ARG, { .func_arg = opt_codec}, "force decoder", "decoder_name" },
4889 { "acodec", OPT_TYPE_STRING, OPT_EXPERT, { &audio_codec_name }, "force audio decoder", "decoder_name" },
4890 { "scodec", OPT_TYPE_STRING, OPT_EXPERT, { &subtitle_codec_name }, "force subtitle decoder", "decoder_name" },
4891 { "vcodec", OPT_TYPE_STRING, OPT_EXPERT, { &video_codec_name }, "force video decoder", "decoder_name" },
4892 { "autorotate", OPT_TYPE_BOOL, 0, { &autorotate }, "automatically rotate video", "" },
4893 { "find_stream_info", OPT_TYPE_BOOL, OPT_INPUT | OPT_EXPERT, { &find_stream_info },
4894 "read and decode the streams to fill missing information with heuristics" },
4895 { "filter_threads", OPT_TYPE_INT, OPT_EXPERT, { &filter_nbthreads }, "number of filter threads per graph" },
4896 { "enable_vulkan", OPT_TYPE_BOOL, 0, { &enable_vulkan }, "enable vulkan renderer" },
4897 { "vulkan_params", OPT_TYPE_STRING, OPT_EXPERT, { &vulkan_params }, "vulkan configuration using a list of key=value pairs separated by ':'" },
4898 { "video_bg", OPT_TYPE_STRING, OPT_EXPERT, { &video_background }, "set video background for transparent videos" },
4899 { "hwaccel", OPT_TYPE_STRING, OPT_EXPERT, { &hwaccel }, "use HW accelerated decoding" },
4900 { NULL, },
4901};
4902
4903static void show_usage(void)
4904{
4905 av_log(NULL, AV_LOG_INFO, "Simple media player\n");
4906 av_log(NULL, AV_LOG_INFO, "usage: %s [options] input_file\n", program_name);
4907 av_log(NULL, AV_LOG_INFO, "\n");
4908}
4909
4910void show_help_default(const char *opt, const char *arg)
4911{
4913 show_usage();
4914 show_help_options(options, "Main options:", 0, OPT_EXPERT);
4915 show_help_options(options, "Advanced options:", OPT_EXPERT, 0);
4916 printf("\n");
4920 printf("\nWhile playing:\n"
4921 "q, ESC quit\n"
4922 "f toggle full screen\n"
4923 "p, SPC pause\n"
4924 "m toggle mute\n"
4925 "9, 0 decrease and increase volume respectively\n"
4926 "/, * decrease and increase volume respectively\n"
4927 "a cycle audio channel in the current program\n"
4928 "v cycle video channel\n"
4929 "t cycle subtitle channel in the current program\n"
4930 "c cycle program\n"
4931 "w cycle video filters or show modes\n"
4932 "s activate frame-step mode\n"
4933 "left/right seek backward/forward by 10 seconds or a custom interval if -seek_interval is set\n"
4934 "down/up seek backward/forward 1 minute\n"
4935 "page down/page up seek to previous/next chapter or backward/forward 10 minutes if no chapters\n"
4936 "l keep the chapter list on screen; typing then filters it, down/up move its selection and escape closes it\n"
4937 "enter seek to the chapter selected in the chapter list while it is shown\n"
4938 "mouse wheel move the chapter list selection while it is shown\n"
4939 "left click seek to the clicked chapter list entry, or sort the list by the clicked column, again to flip it;\n"
4940 " the left half of the shuffle button lowers its seed, the right half raises it\n"
4941 "mouse over (i) show the metadata of that chapter list entry\n"
4942 "right mouse click seek to percentage in file corresponding to fraction of width\n"
4943 "left double-click toggle full screen\n"
4944 );
4945}
4946
4947/* Called from the main */
4948int main(int argc, char **argv)
4949{
4950 int flags, ret;
4951 VideoState *is;
4952
4953 init_dynload();
4954
4956 parse_loglevel(argc, argv, options);
4957
4958 /* register all codecs, demux and protocols */
4959#if CONFIG_AVDEVICE
4961#endif
4963
4964 signal(SIGINT , sigterm_handler); /* Interrupt (ANSI). */
4965 signal(SIGTERM, sigterm_handler); /* Termination (ANSI). */
4966
4967 show_banner(argc, argv, options);
4968
4969 ret = parse_options(NULL, argc, argv, options, opt_input_file);
4970 if (ret < 0)
4971 exit(ret == AVERROR_EXIT ? 0 : 1);
4972
4973 if (!input_filename) {
4974 show_usage();
4975 av_log(NULL, AV_LOG_FATAL, "An input file must be specified\n");
4977 "Use -h to get full help or, even better, run 'man %s'\n", program_name);
4978 exit(1);
4979 }
4980
4981 if (display_disable) {
4982 video_disable = 1;
4983 }
4984 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
4985 if (audio_disable)
4986 flags &= ~SDL_INIT_AUDIO;
4987 if (display_disable)
4988 flags &= ~SDL_INIT_VIDEO;
4989 if (SDL_Init (flags)) {
4990 av_log(NULL, AV_LOG_FATAL, "Could not initialize SDL - %s\n", SDL_GetError());
4991 av_log(NULL, AV_LOG_FATAL, "(Did you set the DISPLAY variable?)\n");
4992 exit(1);
4993 }
4994
4995 SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
4996 SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
4997
4998 if (!display_disable) {
4999 int flags = SDL_WINDOW_HIDDEN;
5000 if (alwaysontop)
5001#if SDL_VERSION_ATLEAST(2,0,5)
5002 flags |= SDL_WINDOW_ALWAYS_ON_TOP;
5003#else
5004 av_log(NULL, AV_LOG_WARNING, "Your SDL version doesn't support SDL_WINDOW_ALWAYS_ON_TOP. Feature will be inactive.\n");
5005#endif
5006 if (borderless)
5007 flags |= SDL_WINDOW_BORDERLESS;
5008 else
5009 flags |= SDL_WINDOW_RESIZABLE;
5010
5011#ifdef SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR
5012 SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0");
5013#endif
5014 if (hwaccel && !enable_vulkan) {
5015 av_log(NULL, AV_LOG_INFO, "Enable vulkan renderer to support hwaccel %s\n", hwaccel);
5016 enable_vulkan = 1;
5017 }
5018 if (enable_vulkan) {
5020 if (vk_renderer) {
5021#if SDL_VERSION_ATLEAST(2, 0, 6)
5022 flags |= SDL_WINDOW_VULKAN;
5023#endif
5024 } else {
5025 av_log(NULL, AV_LOG_WARNING, "Doesn't support vulkan renderer, fallback to SDL renderer\n");
5026 enable_vulkan = 0;
5027 }
5028 }
5029 window = SDL_CreateWindow(program_name, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, default_width, default_height, flags);
5030 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
5031 if (!window) {
5032 av_log(NULL, AV_LOG_FATAL, "Failed to create window: %s", SDL_GetError());
5033 do_exit(NULL);
5034 }
5035 SDL_version version;
5036 SDL_GetVersion(&version);
5037 /* SDL before 2.0.16 waits for events by polling */
5038 wait_for_events = SDL_VERSIONNUM(version.major, version.minor, version.patch) >= SDL_VERSIONNUM(2, 0, 16);
5039
5040 if (vk_renderer) {
5041 AVDictionary *dict = NULL;
5042
5043 if (vulkan_params) {
5044 int ret = av_dict_parse_string(&dict, vulkan_params, "=", ":", 0);
5045 if (ret < 0) {
5046 av_log(NULL, AV_LOG_FATAL, "Failed to parse, %s\n", vulkan_params);
5047 do_exit(NULL);
5048 }
5049 }
5051 av_dict_free(&dict);
5052 if (ret < 0) {
5053 av_log(NULL, AV_LOG_FATAL, "Failed to create vulkan renderer, %s\n", av_err2str(ret));
5054 do_exit(NULL);
5055 }
5056 } else {
5057 renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
5058 if (!renderer) {
5059 av_log(NULL, AV_LOG_WARNING, "Failed to initialize a hardware accelerated renderer: %s\n", SDL_GetError());
5060 renderer = SDL_CreateRenderer(window, -1, 0);
5061 }
5062 if (renderer) {
5063 if (!SDL_GetRendererInfo(renderer, &renderer_info))
5064 av_log(NULL, AV_LOG_VERBOSE, "Initialized %s renderer.\n", renderer_info.name);
5065 }
5066 if (!renderer || !renderer_info.num_texture_formats) {
5067 av_log(NULL, AV_LOG_FATAL, "Failed to create window or renderer: %s", SDL_GetError());
5068 do_exit(NULL);
5069 }
5070 }
5071 }
5072
5074 if (!is) {
5075 av_log(NULL, AV_LOG_FATAL, "Failed to initialize VideoState!\n");
5076 do_exit(NULL);
5077 }
5078
5079 event_loop(is);
5080
5081 /* never returns */
5082
5083 return 0;
5084}
#define fn(a)
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:97
static double val(void *priv, double ch)
Definition aeval.c:77
static const AVFilterPad inputs[]
Definition af_aap.c:299
static const AVFilterPad outputs[]
Definition af_aap.c:310
static const char *const format[]
Definition af_aiir.c:445
#define entry
static FILE * out
static int out_size
static AVFormatContext * ctx
static AVDictionary * opts
channels
Definition aptx.h:31
int32_t
Main libavdevice API header.
Main libavfilter public API header.
int av_find_best_stream(AVFormatContext *ic, enum AVMediaType type, int wanted_stream_nb, int related_stream, const AVCodec **decoder_ret, int flags)
Definition avformat.c:520
Main libavformat public API header.
#define AVFMT_EVENT_FLAG_METADATA_UPDATED
Definition avformat.h:1795
@ AV_STREAM_GROUP_ENTRY_STREAM
Definition avformat.h:1172
@ AV_STREAM_GROUP_PARAMS_LCEVC
Definition avformat.h:1162
#define AVFMT_TS_DISCONT
Format allows timestamp discontinuities.
Definition avformat.h:502
#define AVFMT_NO_BYTE_SEEK
Format does not allow seeking by bytes.
Definition avformat.h:508
#define AVFMT_FLAG_GENPTS
Generate missing pts even if it requires parsing future frames.
Definition avformat.h:1553
#define AVSEEK_FLAG_BYTE
seeking based on position in bytes
Definition avformat.h:2712
#define AVSTREAM_EVENT_FLAG_METADATA_UPDATED
Definition avformat.h:886
#define AV_DISPOSITION_ATTACHED_PIC
The stream is stored in the file as an attached picture/"cover art" (e.g.
Definition avformat.h:694
#define AVFMT_NOTIMESTAMPS
Format does not need / have any timestamps.
Definition avformat.h:500
int64_t avio_size(AVIOContext *s)
Get the filesize.
Definition aviobuf.c:326
int avio_feof(AVIOContext *s)
Similar to feof() but also returns nonzero on read errors.
Definition aviobuf.c:349
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition avio.h:494
char * av_asprintf(const char *fmt,...)
Definition avstring.c:115
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
Definition avstring.c:103
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition bprint.c:121
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition bprint.c:68
AVBPrint public header.
#define AV_BPRINT_SIZE_UNLIMITED
#define AV_BPRINT_SIZE_AUTOMATIC
memory buffer sink API for audio and video
Memory buffer source API.
static int FUNC metadata(CodedBitstreamContext *ctx, RWContext *rw, APVRawMetadata *current)
#define is(width, name, range_min, range_max, subs,...)
Definition cbs_h264.c:78
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define f(width, name)
Definition cbs_vp8.c:236
#define ss(width, name, subs,...)
Definition cbs_vp9.c:202
#define s(width, name)
Definition cbs_vp9.c:198
Public libavutil channel layout APIs header.
void show_help_children(const AVClass *class, int flags)
Show help for all options with given flags in class and all its children.
Definition cmdutils.c:138
void init_dynload(void)
Initialize dynamic library loading.
Definition cmdutils.c:73
int check_avoptions(AVDictionary *m)
Definition cmdutils.c:1606
void dump_dictionary(void *ctx, const AVDictionary *m, const char *name, const char *indent, int log_level)
This does the same as libavformat/dump.c corresponding function and should probably be kept in sync w...
Definition cmdutils.c:1617
AVDictionary * swr_opts
Definition cmdutils.c:55
void parse_loglevel(int argc, char **argv, const OptionDef *options)
Find the '-loglevel' option in the command line args and apply it.
Definition cmdutils.c:554
void show_help_options(const OptionDef *options, const char *msg, int req_flags, int rej_flags)
Print help for all options matching specified flags.
Definition cmdutils.c:105
void log_callback_help(void *ptr, int level, const char *fmt, va_list vl)
Trivial log callback.
Definition cmdutils.c:68
AVDictionary * format_opts
Definition cmdutils.c:56
int parse_options(void *optctx, int argc, char **argv, const OptionDef *options, int(*parse_arg_function)(void *, const char *))
Parse the command line arguments.
Definition cmdutils.c:418
int filter_codec_opts(const AVDictionary *opts, enum AVCodecID codec_id, AVFormatContext *s, AVStream *st, const AVCodec *codec, AVDictionary **dst, AVDictionary **opts_used)
Filter out options for given codec.
Definition cmdutils.c:1424
void remove_avoptions(AVDictionary **a, AVDictionary *b)
Definition cmdutils.c:1597
AVDictionary * codec_opts
Definition cmdutils.c:56
void uninit_opts(void)
Uninitialize the cmdutils option system, in particular free the *_opts contexts and their contents.
Definition cmdutils.c:60
double get_rotation(const int32_t *displaymatrix)
Definition cmdutils.c:1554
int setup_find_stream_info_opts(AVFormatContext *s, AVDictionary *local_codec_opts, AVDictionary ***dst)
Setup AVCodecContext options for avformat_find_stream_info().
Definition cmdutils.c:1492
int parse_number(const char *context, const char *numstr, enum OptionType type, double min, double max, double *dst)
Parse a string and return its corresponding value as a double.
Definition cmdutils.c:82
AVDictionary * sws_dict
Definition cmdutils.c:54
const char program_name[]
program name, defined by the program for show_version().
Definition ffmpeg.c:89
#define OPT_FUNC_ARG
Definition cmdutils.h:205
#define OPT_INPUT
Definition cmdutils.h:237
static void print_error(const char *filename, int err)
Print an error message to stderr, indicating filename and a human readable description of the error c...
Definition cmdutils.h:472
@ OPT_TYPE_BOOL
Definition cmdutils.h:82
@ OPT_TYPE_STRING
Definition cmdutils.h:83
@ OPT_TYPE_INT64
Definition cmdutils.h:85
@ OPT_TYPE_INT
Definition cmdutils.h:84
@ OPT_TYPE_TIME
Definition cmdutils.h:88
@ OPT_TYPE_FUNC
Definition cmdutils.h:81
@ OPT_TYPE_FLOAT
Definition cmdutils.h:86
void show_banner(int argc, char **argv, const OptionDef *options)
Print the program banner to stderr.
Definition opt_common.c:240
#define GROW_ARRAY(array, nb_elems)
Definition cmdutils.h:536
#define OPT_AUDIO
Definition cmdutils.h:213
#define OPT_EXPERT
Definition cmdutils.h:211
const int program_birth_year
program birth year, defined by the program for show_banner()
Definition ffmpeg.c:90
int avcodec_parameters_to_context(AVCodecContext *codec, const AVCodecParameters *par)
Definition codec_par.c:206
#define av_clipd
Definition common.h:148
#define AV_CEIL_RSHIFT(a, b)
Definition common.h:60
#define av_clip
Definition common.h:100
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition common.h:74
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
static __device__ float ceil(float a)
__device__ int printf(const char *,...)
static __device__ float fabs(float a)
static int16_t block[64]
Definition dct.c:125
static AVPacket * pkt
static AVStream * video_stream
static AVStream * audio_stream
static AVFrame * frame
Public dictionary API.
int main
Definition dovi_rpuenc.c:38
int8_t exp
Definition eval.c:76
static volatile int received_sigterm
Definition ffmpeg.c:141
static int decode_interrupt_cb(void *ctx)
Definition ffmpeg.c:317
static volatile int received_nb_signals
Definition ffmpeg.c:142
static void sigterm_handler(int sig)
Definition ffmpeg.c:148
char * filter_nbthreads
Definition ffmpeg_opt.c:73
const char * key
static void show_usage(void)
Definition ffplay.c:4903
static char * vulkan_params
Definition ffplay.c:440
static VideoState * stream_open(const char *filename, const AVInputFormat *iformat)
Definition ffplay.c:4281
static double compute_target_delay(double delay, VideoState *is)
Definition ffplay.c:2400
#define SDL_AUDIO_MAX_CALLBACKS_PER_SEC
Definition ffplay.c:75
static int default_height
Definition ffplay.c:393
static char * video_background
Definition ffplay.c:441
static int autorotate
Definition ffplay.c:436
static int screen_left
Definition ffplay.c:396
static int is_realtime(AVFormatContext *s)
Definition ffplay.c:3765
static void frame_queue_destroy(FrameQueue *f)
Definition ffplay.c:803
static const char chapter_panel_color[]
Definition ffplay.c:1308
static int audio_open(void *opaque, AVChannelLayout *wanted_channel_layout, int wanted_sample_rate, struct AudioParams *audio_hw_params)
Definition ffplay.c:3396
static int chapter_list_click(VideoState *is, int x, int y)
Definition ffplay.c:1750
static int packet_queue_put_nullpacket(PacketQueue *q, AVPacket *pkt, int stream_index)
Definition ffplay.c:556
static int decoder_decode_frame(Decoder *d, AVFrame *frame, AVSubtitle *sub)
Definition ffplay.c:672
static void chapter_list_search(VideoState *is, const char *typed)
Definition ffplay.c:1680
static int chapter_strip_add(ChapterStrip **strips, int *nb, SDL_Rect rect, const char *background, const AVBPrint *script)
Definition ffplay.c:1377
static const char * hwaccel
Definition ffplay.c:442
#define CHAPTER_LIST_ROWS
Definition ffplay.c:111
static Frame * frame_queue_peek_writable(FrameQueue *f)
Definition ffplay.c:837
static int default_width
Definition ffplay.c:392
static int video_open(VideoState *is)
Definition ffplay.c:2210
static int current_chapter(VideoState *is)
Definition ffplay.c:4477
static int infinite_buffer
Definition ffplay.c:421
static void draw_video_background(VideoState *is)
Definition ffplay.c:1060
static void do_exit(VideoState *is)
Definition ffplay.c:2164
static int is_full_screen
Definition ffplay.c:445
static ChapterListHit chapter_list_hit(VideoState *is, const ChapterListLayout *l, int x, int y)
Definition ffplay.c:1274
static int chapter_list_configure(VideoState *is, const ChapterListLayout *l, const SDL_Rect *canvas)
Definition ffplay.c:1473
static int64_t duration
Definition ffplay.c:411
static int upload_texture(SDL_Texture **tex, AVFrame *frame)
Definition ffplay.c:999
static int chapter_strip_render(VideoState *is, const ChapterStrip *strip)
Definition ffplay.c:1516
static void set_clock_at(Clock *c, double pts, int serial, double time)
Definition ffplay.c:2261
static void stream_toggle_pause(VideoState *is)
Definition ffplay.c:2361
static void chapter_list_hover(VideoState *is, int x, int y)
Definition ffplay.c:1734
static SDL_AudioDeviceID audio_dev
Definition ffplay.c:458
static double get_master_clock(VideoState *is)
Definition ffplay.c:2314
static void chapter_bitmap_touched(VideoState *is, const SDL_Rect *rect)
Definition ffplay.c:1543
static double vp_duration(VideoState *is, Frame *vp, Frame *nextvp)
Definition ffplay.c:2430
static int display_disable
Definition ffplay.c:404
static uint32_t shuffle_rank(int index)
Definition ffplay.c:1124
static int compare_tags(const char *a, const char *b)
Definition ffplay.c:1118
static void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
Definition ffplay.c:3353
#define EXTERNAL_CLOCK_MAX_FRAMES
Definition ffplay.c:70
static int audio_decode_frame(VideoState *is)
Decode one audio frame and return its uncompressed size.
Definition ffplay.c:3243
static void event_loop(VideoState *cur_stream)
Definition ffplay.c:4503
static int opt_format(void *optctx, const char *opt, const char *arg)
Definition ffplay.c:4761
static double chapter_list_alpha(VideoState *is, int64_t now)
Definition ffplay.c:1099
#define EXTERNAL_CLOCK_SPEED_STEP
Definition ffplay.c:95
static const AVInputFormat * file_iformat
Definition ffplay.c:389
static int video_disable
Definition ffplay.c:399
#define AV_SYNC_THRESHOLD_MAX
Definition ffplay.c:83
static int find_stream_info
Definition ffplay.c:437
#define SAMPLE_QUEUE_SIZE
Definition ffplay.c:169
static int screen_height
Definition ffplay.c:395
#define MIN_FRAMES
Definition ffplay.c:68
static Frame * frame_queue_peek(FrameQueue *f)
Definition ffplay.c:822
static const char * chapter_tag(const AVChapter *chapter, const char *key)
Definition ffplay.c:1110
static const char chapter_hover_color[]
Definition ffplay.c:1309
static int opt_codec(void *optctx, const char *opt, const char *arg)
Definition ffplay.c:4819
static Frame * frame_queue_peek_next(FrameQueue *f)
Definition ffplay.c:827
static const char ** vfilters_list
Definition ffplay.c:433
static int genpts
Definition ffplay.c:413
static int get_master_sync_type(VideoState *is)
Definition ffplay.c:2297
static void video_image_display(VideoState *is)
Definition ffplay.c:1782
static int compare_chapter_rows(const void *a, const void *b)
Definition ffplay.c:1133
static Frame * frame_queue_peek_readable(FrameQueue *f)
Definition ffplay.c:853
static int decoder_reorder_pts
Definition ffplay.c:415
static int subtitle_disable
Definition ffplay.c:400
static ChapterListLayout chapter_list_layout(VideoState *is)
Definition ffplay.c:1233
static const struct @171016013232041267156014171031267212062350175105 sort_buttons[CHAPTER_SORT_NB]
static void packet_queue_destroy(PacketQueue *q)
Definition ffplay.c:597
static int nb_vfilters
Definition ffplay.c:434
static void set_clock(Clock *c, double pts, int serial)
Definition ffplay.c:2269
static int av_sync_type
Definition ffplay.c:409
static int init_lcevc_graph(AVFormatContext *ic, int stream_index)
Definition ffplay.c:3508
static int borderless
Definition ffplay.c:405
static int startup_volume
Definition ffplay.c:407
static void toggle_mute(VideoState *is)
Definition ffplay.c:2380
static void frame_queue_next(FrameQueue *f)
Definition ffplay.c:879
static int chapter_list_update_rows(VideoState *is)
Definition ffplay.c:1172
static void fill_rectangle(int x, int y, int w, int h)
Definition ffplay.c:919
static void stream_seek(VideoState *is, int64_t pos, int64_t rel, int by_bytes)
Definition ffplay.c:2347
#define EXTERNAL_CLOCK_SPEED_MAX
Definition ffplay.c:94
static int opt_input_file(void *optctx, const char *filename)
Definition ffplay.c:4802
@ AV_SYNC_AUDIO_MASTER
Definition ffplay.c:242
@ AV_SYNC_EXTERNAL_CLOCK
Definition ffplay.c:244
@ AV_SYNC_VIDEO_MASTER
Definition ffplay.c:243
static const char * video_codec_name
Definition ffplay.c:429
#define SAMPLE_ARRAY_SIZE
Definition ffplay.c:105
static const char * input_filename
Definition ffplay.c:390
static void video_display(VideoState *is)
Definition ffplay.c:2234
static void packet_queue_abort(PacketQueue *q)
Definition ffplay.c:605
static void update_volume(VideoState *is, int sign, double step)
Definition ffplay.c:2385
static void toggle_audio_display(VideoState *is)
Definition ffplay.c:4435
#define SDL_VOLUME_STEP
Definition ffplay.c:78
#define MAX_QUEUE_SIZE
Definition ffplay.c:67
static void refresh_loop_wait_event(VideoState *is, SDL_Event *event)
Definition ffplay.c:4447
static enum AVColorSpace sdl_supported_color_spaces[]
Definition ffplay.c:1033
static enum ShowMode show_mode
Definition ffplay.c:422
static void bprint_chapter_ring(AVBPrint *script, int cx, int cy, int r)
Definition ffplay.c:1297
static int show_status
Definition ffplay.c:408
static int subtitle_thread(void *arg)
Definition ffplay.c:3140
static int frame_queue_nb_remaining(FrameQueue *f)
Definition ffplay.c:895
static void chapter_list_scroll(VideoState *is, const ChapterListLayout *l, const ChapterStrip *strips, int nb)
Definition ffplay.c:1551
static const char * window_title
Definition ffplay.c:391
static int get_video_frame(VideoState *is, AVFrame *frame)
Definition ffplay.c:2648
static enum AVAlphaMode sdl_supported_alpha_modes[]
Definition ffplay.c:1039
static void video_audio_display(VideoState *s)
Definition ffplay.c:1878
static int decoder_start(Decoder *d, int(*fn)(void *), const char *thread_name, void *arg)
Definition ffplay.c:3026
static void decoder_abort(Decoder *d, FrameQueue *fq)
Definition ffplay.c:910
static int64_t frame_queue_last_pos(FrameQueue *f)
Definition ffplay.c:901
static void update_video_pts(VideoState *is, double pts, int serial)
Definition ffplay.c:2442
static int autoexit
Definition ffplay.c:416
static int64_t audio_callback_time
Definition ffplay.c:446
static void chapter_list_key(VideoState *is, SDL_Keycode key)
Definition ffplay.c:1715
static const char * audio_codec_name
Definition ffplay.c:427
static ChapterSortKey chapter_sort[CHAPTER_SORT_NB]
Definition ffplay.c:424
@ CHAPTER_SORT_NB
Definition ffplay.c:119
@ CHAPTER_SORT_LENGTH
Definition ffplay.c:117
@ CHAPTER_SORT_NUMBER
Definition ffplay.c:114
@ CHAPTER_SORT_ARTIST
Definition ffplay.c:115
@ CHAPTER_SORT_TITLE
Definition ffplay.c:116
@ CHAPTER_SORT_SHUFFLE
Definition ffplay.c:118
static int dummy
Definition ffplay.c:4846
static float seek_interval
Definition ffplay.c:403
static int packet_queue_init(PacketQueue *q)
Definition ffplay.c:563
static Frame * frame_queue_peek_last(FrameQueue *f)
Definition ffplay.c:832
static char * afilters
Definition ffplay.c:435
#define SUBPICTURE_QUEUE_SIZE
Definition ffplay.c:168
static const struct TextureFormatEntry sdl_texture_format_map[]
static void set_default_window_size(int width, int height, AVRational sar)
Definition ffplay.c:2198
#define INSERT_FILT(name, arg)
static int frame_queue_init(FrameQueue *f, PacketQueue *pktq, int max_size, int keep_last)
Definition ffplay.c:782
void show_help_default(const char *opt, const char *arg)
Per-fftool specific help handler.
Definition ffplay.c:4910
static void frame_queue_unref_item(Frame *vp)
Definition ffplay.c:776
static void init_clock(Clock *c, int *queue_serial)
Definition ffplay.c:2281
static void chapter_list_move(VideoState *is, int delta)
Definition ffplay.c:1668
static void bprint_chapter_header_strip(VideoState *is, AVBPrint *script, const ChapterListLayout *l)
Definition ffplay.c:1334
static int opt_show_mode(void *optctx, const char *opt, const char *arg)
Definition ffplay.c:4786
static int compute_mod(int a, int b)
Definition ffplay.c:1873
static int opt_sync(void *optctx, const char *opt, const char *arg)
Definition ffplay.c:4771
#define CHAPTER_LIST_EVENT
Definition ffplay.c:1210
static int do_bsf_flush(AVFormatContext *ic, VideoState *is)
Definition ffplay.c:3815
static const char chapter_popup_color[]
Definition ffplay.c:1310
static int chapter_list_show(VideoState *is, int chapter)
Definition ffplay.c:1655
#define EXTERNAL_CLOCK_SPEED_MIN
Definition ffplay.c:93
static void bprint_chapter_box(AVBPrint *script, const char *style, int x, int y, int w, int h)
Definition ffplay.c:1212
static void stream_cycle_channel(VideoState *is, int codec_type)
Definition ffplay.c:4350
static int exit_status
Definition ffplay.c:452
static SDL_Renderer * renderer
Definition ffplay.c:455
#define CHAPTER_LIST_FADE_TIME
Definition ffplay.c:109
static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block, int *serial)
Definition ffplay.c:625
#define AUDIO_DIFF_AVG_NB
Definition ffplay.c:98
static void bprint_chapter_styles(AVBPrint *script, const ChapterListLayout *l)
Definition ffplay.c:1312
static void frame_queue_push(FrameQueue *f)
Definition ffplay.c:869
static int decode_interrupt_cb(void *ctx)
Definition ffplay.c:3752
static int decoder_init(Decoder *d, AVCodecContext *avctx, PacketQueue *queue, SDL_cond *empty_queue_cond)
Definition ffplay.c:659
static int audio_thread(void *arg)
Definition ffplay.c:2948
static int configure_audio_filters(VideoState *is, const char *afilters, int force_output_format)
Definition ffplay.c:2876
static int64_t cursor_last_shown
Definition ffplay.c:431
static int lowres
Definition ffplay.c:414
static int fast
Definition ffplay.c:412
#define SDL_AUDIO_MIN_BUFFER_SIZE
Definition ffplay.c:73
static int configure_filtergraph(AVFilterGraph *graph, const char *filtergraph, AVFilterContext *source_ctx, AVFilterContext *sink_ctx)
Definition ffplay.c:2681
static void stream_close(VideoState *is)
Definition ffplay.c:2115
static int video_thread(void *arg)
Definition ffplay.c:3037
static int exit_on_mousedown
Definition ffplay.c:418
static int screen_width
Definition ffplay.c:394
static void chapter_list_select(VideoState *is, int row)
Definition ffplay.c:1644
#define AV_SYNC_THRESHOLD_MIN
Definition ffplay.c:81
static SDL_Window * window
Definition ffplay.c:454
static void decoder_destroy(Decoder *d)
Definition ffplay.c:771
static int chapter_list_render(VideoState *is)
Definition ffplay.c:1591
static int do_bsf_graph(AVFormatContext *ic, VideoState *is, Stream *sti, AVPacket *pkt)
Definition ffplay.c:3781
static int stream_component_open(VideoState *is, int stream_index)
Definition ffplay.c:3587
static void stream_component_close(VideoState *is, int stream_index)
Definition ffplay.c:2054
static int framedrop
Definition ffplay.c:420
static void uninit_bsf_graph(AVFormatContext *ic, int stream_index)
Definition ffplay.c:2029
const char * label
Definition ffplay.c:1200
static int seek_by_bytes
Definition ffplay.c:402
static void packet_queue_flush(PacketQueue *q)
Definition ffplay.c:583
#define REFRESH_RATE
Definition ffplay.c:101
static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const char *vfilters, AVFrame *frame)
Definition ffplay.c:2724
static int packet_queue_put_private(PacketQueue *q, AVPacket *pkt)
Definition ffplay.c:511
static void chapter_sort_by(int key, int seed_step)
Definition ffplay.c:1155
#define FF_QUIT_EVENT
Definition ffplay.c:448
#define CURSOR_HIDE_DELAY
Definition ffplay.c:107
static int screen_top
Definition ffplay.c:397
static int opt_width(void *optctx, const char *opt, const char *arg)
Definition ffplay.c:4739
static void packet_queue_start(PacketQueue *q)
Definition ffplay.c:616
static void get_sdl_pix_fmt_and_blendmode(int format, Uint32 *sdl_pix_fmt, SDL_BlendMode *sdl_blendmode)
Definition ffplay.c:981
static SDL_RendererInfo renderer_info
Definition ffplay.c:457
static void step_to_next_frame(VideoState *is)
Definition ffplay.c:2392
static int chapter_shuffle_seed
Definition ffplay.c:426
static int chapter_list_visible(VideoState *is)
Definition ffplay.c:1674
static void toggle_pause(VideoState *is)
Definition ffplay.c:2374
static void seek_chapter(VideoState *is, int i)
Definition ffplay.c:4490
static void chapter_list_discard(VideoState *is)
Definition ffplay.c:1462
static int opt_height(void *optctx, const char *opt, const char *arg)
Definition ffplay.c:4750
#define EXTERNAL_CLOCK_MIN_FRAMES
Definition ffplay.c:69
#define AV_NOSYNC_THRESHOLD
Definition ffplay.c:87
static void update_sample_display(VideoState *is, short *samples, int samples_size)
Definition ffplay.c:3175
static int cmp_audio_fmts(enum AVSampleFormat fmt1, int64_t channel_count1, enum AVSampleFormat fmt2, int64_t channel_count2)
Definition ffplay.c:501
static int exit_on_keydown
Definition ffplay.c:417
#define FRAME_QUEUE_SIZE
Definition ffplay.c:170
static int realloc_texture(SDL_Texture **texture, Uint32 new_format, int new_width, int new_height, SDL_BlendMode blendmode, int init_texture)
Definition ffplay.c:930
static int loop
Definition ffplay.c:419
static int opt_add_vfilter(void *optctx, const char *opt, const char *arg)
Definition ffplay.c:487
static int create_hwaccel(AVBufferRef **device_ctx)
Definition ffplay.c:3472
static void video_refresh(void *opaque, double *remaining_time)
Definition ffplay.c:2450
static void frame_queue_signal(FrameQueue *f)
Definition ffplay.c:815
static int enable_vulkan
Definition ffplay.c:439
static double get_clock(Clock *c)
Definition ffplay.c:2249
static int cursor_hidden
Definition ffplay.c:432
#define SAMPLE_CORRECTION_PERCENT_MAX
Definition ffplay.c:90
static const char * subtitle_codec_name
Definition ffplay.c:428
static int wait_for_events
Definition ffplay.c:456
#define VIDEO_PICTURE_QUEUE_SIZE
Definition ffplay.c:167
static void bprint_chapter_row_strip(VideoState *is, AVBPrint *script, const ChapterListLayout *l, int r)
Definition ffplay.c:1353
static int alwaysontop
Definition ffplay.c:406
static void set_clock_speed(Clock *c, double speed)
Definition ffplay.c:2275
static void chapter_list_draw(VideoState *is)
Definition ffplay.c:1767
static void calculate_display_rect(SDL_Rect *rect, int scr_xleft, int scr_ytop, int scr_width, int scr_height, int pic_width, int pic_height, AVRational pic_sar)
Definition ffplay.c:954
static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, double duration, int64_t pos, int serial)
Definition ffplay.c:2617
static int audio_disable
Definition ffplay.c:398
static void check_external_clock_speed(VideoState *is)
Definition ffplay.c:2332
static void sync_clock_to_slave(Clock *c, Clock *slave)
Definition ffplay.c:2289
static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
Definition ffplay.c:534
static void chapter_strips_free(ChapterStrip **strips, int *nb)
Definition ffplay.c:1454
double rdftspeed
Definition ffplay.c:430
static void toggle_full_screen(VideoState *is)
Definition ffplay.c:4429
#define CHAPTER_LIST_HOLD_TIME
Definition ffplay.c:110
static void chapter_list_pin(VideoState *is, int pinned)
Definition ffplay.c:1696
static const char * wanted_stream_spec[AVMEDIA_TYPE_NB]
Definition ffplay.c:401
static int stream_has_enough_packets(AVStream *st, int stream_id, PacketQueue *queue)
Definition ffplay.c:3758
#define AV_SYNC_FRAMEDUP_THRESHOLD
Definition ffplay.c:85
static void sigterm_handler(int sig)
Definition ffplay.c:2191
static int chapter_list_strips(VideoState *is, const ChapterListLayout *l, ChapterStrip **strips, int *nb)
Definition ffplay.c:1399
static int synchronize_audio(VideoState *is, int nb_samples)
Definition ffplay.c:3195
static int read_thread(void *arg)
Definition ffplay.c:3840
static VkRenderer * vk_renderer
Definition ffplay.c:460
static void set_sdl_yuv_conversion_mode(AVFrame *frame)
Definition ffplay.c:1044
static int64_t start_time
Definition ffplay.c:410
static void bprint_chapter_cell(AVBPrint *script, const char *style, int x, int y, int right, int bottom, const char *text)
Definition ffplay.c:1218
int vk_renderer_create(VkRenderer *renderer, SDL_Window *window, AVDictionary *opt)
int vk_renderer_display(VkRenderer *renderer, AVFrame *frame, RenderParams *render_params)
VkRenderer * vk_get_renderer(void)
int vk_renderer_get_hw_dev(VkRenderer *renderer, AVBufferRef **dev)
int vk_renderer_resize(VkRenderer *renderer, int width, int height)
void vk_renderer_destroy(VkRenderer *renderer)
#define VIDEO_BACKGROUND_TILE_SIZE
@ VIDEO_BACKGROUND_TILES
@ VIDEO_BACKGROUND_NONE
@ VIDEO_BACKGROUND_COLOR
static const AVInputFormat * iformat
Definition ffprobe.c:383
static unsigned int nb_streams
Definition ffprobe.c:390
A generic FIFO API.
#define fail
Definition test.h:479
#define AV_OPT_FLAG_FILTERING_PARAM
A generic parameter which can be set by the user for filtering.
Definition opt.h:380
#define AV_OPT_FLAG_DECODING_PARAM
A generic parameter which can be set by the user for demuxing or decoding.
Definition opt.h:355
@ AV_OPT_TYPE_PIXEL_FMT
Underlying C type is enum AVPixelFormat.
Definition opt.h:306
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition opt.h:258
@ AV_OPT_TYPE_CHLAYOUT
Underlying C type is AVChannelLayout.
Definition opt.h:330
const AVBitStreamFilter * av_bsf_get_by_name(const char *name)
int av_bsf_sink_get_packet(AVBitStreamFilterContext *ctx, AVPacket *pkt, int flags)
Get a packet with filtered data from sink and put it in packet.
Definition sink.c:52
AVRational av_bsf_sink_get_time_base(const AVBitStreamFilterContext *ctx)
Definition sink.c:126
int av_bsf_source_parameters_set(AVBitStreamFilterContext *ctx, const AVCodecParameters *par)
Initialize the source filter with the provided parameters.
Definition source.c:46
av_warn_unused_result int av_bsf_source_add_packet(AVBitStreamFilterContext *ctx, AVPacket *pkt, int flags)
Add a packet to the buffer source.
Definition source.c:67
@ AV_BSF_SOURCE_FLAG_PUSH
Immediately push the packet to the output.
Definition bsf.h:594
int av_bsf_init_dict(AVBitStreamFilterContext *ctx, AVDictionary **options)
Initialize a filter with the supplied dictionary of options.
AVBitStreamFilterGraph * av_bsf_graph_alloc(void)
Allocate a filter graph.
Definition bsfgraph.c:48
int av_bsf_link(AVBitStreamFilterContext *src, unsigned srcpad, AVBitStreamFilterContext *dst, unsigned dstpad)
Link two filters together.
int av_bsf_graph_config(AVBitStreamFilterGraph *graphctx, void *log_ctx)
Check validity and configure all the links and formats in the graph.
Definition bsfgraph.c:294
void av_bsf_graph_free(AVBitStreamFilterGraph **graph)
Free a graph, destroy its links, and set *graph to NULL.
Definition bsfgraph.c:93
int av_bsf_graph_alloc_filter(AVBitStreamFilterContext **filt_ctx, const AVBitStreamFilter *filter, const char *name, AVBitStreamFilterGraph *graph)
Create a new filter instance in a filter graph.
Definition bsfgraph.c:139
int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options)
Initialize the AVCodecContext to use the given AVCodec.
Definition avcodec.c:145
#define AV_CODEC_FLAG2_FAST
Allow non spec compliant speedup tricks.
Definition avcodec.h:337
const AVClass * avcodec_get_class(void)
Get the AVClass for AVCodecContext.
Definition options.c:188
AVCodecContext * avcodec_alloc_context3(const AVCodec *codec)
Allocate an AVCodecContext and set its fields to default values.
Definition options.c:149
const AVCodec * avcodec_find_decoder(enum AVCodecID id)
Find a registered decoder with a matching codec ID.
Definition allcodecs.c:997
const AVCodec * avcodec_find_decoder_by_name(const char *name)
Find a registered decoder with the specified name.
Definition allcodecs.c:1025
void avsubtitle_free(AVSubtitle *sub)
Free all allocated data in the given subtitle struct.
Definition avcodec.c:422
const char * avcodec_get_name(enum AVCodecID id)
Get the name of a codec.
Definition utils.c:421
void avcodec_free_context(AVCodecContext **avctx)
Free the codec context and everything associated with it and write NULL to the provided pointer.
Definition options.c:168
int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame)
Alias for avcodec_receive_frame_flags(avctx, frame, 0).
Definition avcodec.c:721
int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt)
Supply raw packet data as input to a decoder.
Definition decode.c:734
int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, int *got_sub_ptr, const AVPacket *avpkt)
Decode a subtitle message.
Definition decode.c:939
@ AVDISCARD_ALL
discard all
Definition defs.h:246
@ AVDISCARD_DEFAULT
discard useless packets like 0 size packets in avi
Definition defs.h:241
void avcodec_flush_buffers(AVCodecContext *avctx)
Reset the internal codec state / flush internal buffers.
Definition avcodec.c:390
const AVPacketSideData * av_packet_side_data_get(const AVPacketSideData *sd, int nb_sd, enum AVPacketSideDataType type)
Get side information from a side data array.
Definition packet.c:571
@ AV_PKT_DATA_DISPLAYMATRIX
This side data contains a 3x3 transformation matrix describing an affine transformation that needs to...
Definition packet.h:105
void av_packet_free(AVPacket **pkt)
Free the packet, if the packet is reference counted, it will be unreferenced first.
Definition packet.c:74
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition packet.c:435
void av_packet_move_ref(AVPacket *dst, AVPacket *src)
Move every field in src to dst and reset src.
Definition packet.c:492
AVPacket * av_packet_alloc(void)
Allocate an AVPacket and set its fields to default values.
Definition packet.c:63
int av_packet_ref(AVPacket *dst, const AVPacket *src)
Setup a new reference to the data described by a given packet.
Definition packet.c:443
FF_VISIBILITY_POP_HIDDEN av_cold void avdevice_register_all(void)
Initialize libavdevice and register all the input and output devices.
Definition alldevices.c:67
int avformat_network_deinit(void)
Undo the initialization done by avformat_network_init.
Definition utils.c:589
int avformat_network_init(void)
Do global initialization of network libraries.
Definition utils.c:577
AVFormatContext * avformat_alloc_context(void)
Allocate an AVFormatContext.
Definition options.c:165
const AVClass * avformat_get_class(void)
Get the AVClass for AVFormatContext.
Definition options.c:193
const AVInputFormat * av_find_input_format(const char *short_name)
Find AVInputFormat based on the short name of the input format.
Definition format.c:146
AVProgram * av_find_program_from_stream(AVFormatContext *ic, AVProgram *last, int s)
Find the programs which belong to a given stream.
Definition avformat.c:469
int av_read_pause(AVFormatContext *s)
Pause a network-based stream (e.g.
int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
Seek to timestamp ts.
Definition seek.c:667
int av_read_frame(AVFormatContext *s, AVPacket *pkt)
Return the next frame of a stream.
Definition demux.c:1611
int av_read_play(AVFormatContext *s)
Start playing a network-based stream (e.g.
int avformat_open_input(AVFormatContext **ps, const char *url, const AVInputFormat *fmt, AVDictionary **options)
Open an input stream and read the header.
Definition demux.c:231
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
Read packets of a media file to get stream information.
Definition demux.c:2639
void avformat_close_input(AVFormatContext **s)
Close an opened input AVFormatContext.
Definition demux.c:400
AVRational av_guess_frame_rate(AVFormatContext *format, AVStream *st, AVFrame *frame)
Guess the frame rate, based on both the container and codec information.
Definition avformat.c:833
int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec)
Check if the stream st contained in s is matched by the stream specifier spec.
Definition avformat.c:762
void av_dump_format(AVFormatContext *ic, int index, const char *url, int is_output)
Print detailed information about the input or output format, such as duration, bitrate,...
Definition dump.c:941
AVRational av_guess_sample_aspect_ratio(AVFormatContext *format, AVStream *stream, AVFrame *frame)
Guess the sample aspect ratio of a frame, based on both the stream and the frame aspect ratio.
Definition avformat.c:810
int av_buffersink_get_sample_rate(const AVFilterContext *ctx)
AVRational av_buffersink_get_frame_rate(const AVFilterContext *ctx)
Definition buffersink.c:259
int av_buffersink_get_ch_layout(const AVFilterContext *ctx, AVChannelLayout *out)
Definition buffersink.c:279
AVRational av_buffersink_get_time_base(const AVFilterContext *ctx)
int attribute_align_arg av_buffersink_get_frame(AVFilterContext *ctx, AVFrame *frame)
Get a frame with filtered data from sink and put it in frame.
Definition buffersink.c:77
int attribute_align_arg av_buffersink_get_frame_flags(AVFilterContext *ctx, AVFrame *frame, int flags)
Get a frame with filtered data from sink and put it in frame.
Definition buffersink.c:138
int av_buffersrc_parameters_set(AVFilterContext *ctx, AVBufferSrcParameters *param)
Initialize the buffersrc or abuffersrc filter with the provided parameters.
Definition buffersrc.c:131
int attribute_align_arg av_buffersrc_add_frame(AVFilterContext *ctx, AVFrame *frame)
Add a frame to the buffer source.
Definition buffersrc.c:202
AVBufferSrcParameters * av_buffersrc_parameters_alloc(void)
Allocate a new AVBufferSrcParameters instance.
Definition buffersrc.c:116
int avfilter_init_str(AVFilterContext *filter, const char *args)
Initialize a filter with the supplied parameters.
Definition avfilter.c:968
int avfilter_graph_config(AVFilterGraph *graphctx, void *log_ctx)
Check validity and configure all the links and formats in the graph.
const AVFilter * avfilter_get_by_name(const char *name)
Get a filter definition matching the given name.
Definition allfilters.c:656
void avfilter_inout_free(AVFilterInOut **inout)
Free the supplied list of AVFilterInOut and set *inout to NULL.
Definition graphparser.c:76
int avfilter_graph_parse_ptr(AVFilterGraph *graph, const char *filters, AVFilterInOut **inputs, AVFilterInOut **outputs, void *log_ctx)
Add a graph described by a string to a graph.
AVFilterContext * avfilter_graph_alloc_filter(AVFilterGraph *graph, const AVFilter *filter, const char *name)
Create a new filter instance in a filter graph.
void avfilter_graph_free(AVFilterGraph **graph)
Free a graph, destroy its links, and set *graph to NULL.
int avfilter_init_dict(AVFilterContext *ctx, AVDictionary **options)
Initialize a filter with the supplied dictionary of options.
Definition avfilter.c:927
int avfilter_graph_send_command(AVFilterGraph *graph, const char *target, const char *cmd, const char *arg, char *res, int res_len, int flags)
Send a command to one or more filter instances.
int avfilter_link(AVFilterContext *src, unsigned srcpad, AVFilterContext *dst, unsigned dstpad)
Link two filters together.
Definition avfilter.c:149
int avfilter_graph_create_filter(AVFilterContext **filt_ctx, const AVFilter *filt, const char *name, const char *args, void *opaque, AVFilterGraph *graph_ctx)
A convenience wrapper that allocates and initializes a filter in a single step.
const AVClass * avfilter_get_class(void)
Definition avfilter.c:1683
AVFilterInOut * avfilter_inout_alloc(void)
Allocate a single AVFilterInOut entry.
Definition graphparser.c:71
AVFilterGraph * avfilter_graph_alloc(void)
Allocate a filter graph.
void av_channel_layout_default(AVChannelLayout *ch_layout, int nb_channels)
Get the default channel layout for a given number of channels.
int av_channel_layout_describe_bprint(const AVChannelLayout *channel_layout, AVBPrint *bp)
bprint variant of av_channel_layout_describe().
int av_channel_layout_compare(const AVChannelLayout *chl, const AVChannelLayout *chl1)
Check whether two channel layouts are semantically the same, i.e.
void av_channel_layout_uninit(AVChannelLayout *channel_layout)
Free any allocated data in the channel layout and reset the channel count to 0.
int av_channel_layout_describe(const AVChannelLayout *channel_layout, char *buf, size_t buf_size)
Get a human-readable string describing the channel layout properties.
int av_channel_layout_copy(AVChannelLayout *dst, const AVChannelLayout *src)
Make a copy of a channel layout.
@ AV_CHANNEL_ORDER_NATIVE
The native channel order, i.e.
static int av_bprint_is_complete(const AVBPrint *buf)
Test if the print buffer is complete (not truncated).
Definition bprint.h:218
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition bprint.c:234
void av_bprint_chars(AVBPrint *buf, char c, unsigned n)
Append char c n times to a print buffer.
Definition bprint.c:129
void av_bprint_clear(AVBPrint *buf)
Reset the string to "" but keep internal allocated data.
Definition bprint.c:226
AVBufferRef * av_buffer_allocz(size_t size)
Same as av_buffer_alloc(), except the returned buffer will be initialized to zero.
Definition buffer.c:94
#define AV_DICT_MULTIKEY
Allow to store several equal keys in the dictionary.
Definition dict.h:84
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition dict.c:236
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
Definition dict.c:61
const AVDictionaryEntry * av_dict_iterate(const AVDictionary *m, const AVDictionaryEntry *prev)
Iterate over a dictionary.
Definition dict.c:43
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition dict.c:87
#define AV_DICT_DONT_OVERWRITE
Don't overwrite existing entries.
Definition dict.h:81
int av_dict_parse_string(AVDictionary **pm, const char *str, const char *key_val_sep, const char *pairs_sep, int flags)
Parse the key/value pairs list and add the parsed entries to a dictionary.
Definition dict.c:213
int av_dict_count(const AVDictionary *m)
Get number of entries in dictionary.
Definition dict.c:38
#define AV_DICT_MATCH_CASE
Only get an entry with exact-case key match.
Definition dict.h:74
int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags)
Convenience wrapper for av_dict_set() that converts the value to a string and stores it.
Definition dict.c:180
#define AVERROR_FILTER_NOT_FOUND
Filter not found.
Definition error.h:60
#define AVERROR_EXIT
Immediate exit was requested; the called function should not be restarted.
Definition error.h:58
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition error.h:59
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition error.h:52
#define AVERROR_EOF
End of file.
Definition error.h:57
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition error.h:122
#define AVERROR(e)
Definition error.h:45
AVFifo * av_fifo_alloc2(size_t nb_elems, size_t elem_size, unsigned int flags)
Allocate and initialize an AVFifo with a given element size.
Definition fifo.c:47
void av_fifo_freep2(AVFifo **f)
Free an AVFifo and reset pointer to NULL.
Definition fifo.c:286
#define AV_FIFO_FLAG_AUTO_GROW
Automatically resize the FIFO on writes, so that the data fits.
Definition fifo.h:63
int av_fifo_write(AVFifo *f, const void *buf, size_t nb_elems)
Write data into a FIFO.
Definition fifo.c:188
int av_fifo_read(AVFifo *f, void *buf, size_t nb_elems)
Read data from a FIFO.
Definition fifo.c:240
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition frame.c:496
AVFrameSideData * av_frame_get_side_data(const AVFrame *frame, enum AVFrameSideDataType type)
Definition frame.c:659
void av_frame_move_ref(AVFrame *dst, AVFrame *src)
Move everything contained in src to dst and reset src.
Definition frame.c:523
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition frame.c:64
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition frame.c:52
@ AV_FRAME_DATA_DISPLAYMATRIX
This side data contains a 3x3 transformation matrix describing an affine transformation that needs to...
Definition frame.h:85
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition log.h:236
#define AV_LOG_QUIET
Print no output.
Definition log.h:192
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_FATAL
Something went wrong and recovery is not possible.
Definition log.h:204
#define AV_LOG_VERBOSE
Detailed information.
Definition log.h:226
#define AV_LOG_INFO
Standard information.
Definition log.h:221
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
void av_log_set_callback(void(*callback)(void *, int, const char *, va_list))
Set the logging callback.
Definition log.c:491
#define AV_LOG_SKIP_REPEATED
Skip repeated messages, this requires the user app to use av_log() instead of (f)printf as the 2 woul...
Definition log.h:400
int av_log_get_level(void)
Get the current log level.
Definition log.c:471
void av_log_set_flags(int arg)
Definition log.c:481
AVRational av_mul_q(AVRational b, AVRational c)
Multiply two rationals.
Definition rational.c:80
static AVRational av_make_q(int num, int den)
Create an AVRational.
Definition rational.h:71
static double av_q2d(AVRational a)
Convert an AVRational to a double.
Definition rational.h:104
static int av_cmp_q(AVRational a, AVRational b)
Compare two rationals.
Definition rational.h:89
int av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b)
Compare two timestamps each in its own time base.
int64_t av_rescale(int64_t a, int64_t b, int64_t c)
Rescale a 64-bit integer with rounding to nearest.
int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding rnd)
Rescale a 64-bit integer with specified rounding.
Definition mathematics.c:58
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
@ AV_ROUND_NEAR_INF
Round to nearest and halfway cases away from zero.
void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size)
Allocate a buffer, reusing the given one if large enough.
Definition mem.c:661
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
Definition mem.c:318
const char * av_get_media_type_string(enum AVMediaType media_type)
Return a string describing the media_type enum, NULL if media_type is unknown.
Definition utils.c:28
AVMediaType
Definition avutil.h:198
static void * av_x_if_null(const void *p, const void *x)
Return x default pointer in case p is NULL.
Definition avutil.h:311
@ AVMEDIA_TYPE_AUDIO
Definition avutil.h:201
@ AVMEDIA_TYPE_NB
Definition avutil.h:205
@ AVMEDIA_TYPE_SUBTITLE
Definition avutil.h:203
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
char av_get_picture_type_char(enum AVPictureType pict_type)
Return a single letter to describe the given picture type pict_type.
Definition utils.c:40
int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt)
Return number of bytes per sample.
Definition samplefmt.c:109
enum AVSampleFormat av_get_packed_sample_fmt(enum AVSampleFormat sample_fmt)
Get the packed alternative form of the given sample format.
Definition samplefmt.c:78
int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples, enum AVSampleFormat sample_fmt, int align)
Get the required buffer size for the given audio parameters.
Definition samplefmt.c:122
const char * av_get_sample_fmt_name(enum AVSampleFormat sample_fmt)
Return the name of sample_fmt, or NULL if sample_fmt is not recognized.
Definition samplefmt.c:52
AVSampleFormat
Audio sample formats.
Definition samplefmt.h:55
@ AV_SAMPLE_FMT_S16
signed 16 bits
Definition samplefmt.h:58
size_t av_strlcat(char *dst, const char *src, size_t size)
Append the string src to the string dst, but to a total length of no more than size - 1 bytes,...
Definition avstring.c:95
char * av_stristr(const char *s1, const char *s2)
Locate the first case-independent occurrence in the string haystack of the string needle.
Definition avstring.c:58
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition avstring.c:208
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition avutil.h:247
#define AV_TIME_BASE
Internal time base represented as integer.
Definition avutil.h:253
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition avutil.h:263
SwsContext * sws_getCachedContext(SwsContext *context, int srcW, int srcH, enum AVPixelFormat srcFormat, int dstW, int dstH, enum AVPixelFormat dstFormat, int flags, SwsFilter *srcFilter, SwsFilter *dstFilter, const double *param)
Check if context can be reused, otherwise reallocate a new one.
Definition utils.c:2384
int attribute_align_arg sws_scale(SwsContext *sws, const uint8_t *const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[])
swscale wrapper, so we don't need to export the SwsContext.
Definition swscale.c:1644
void sws_freeContext(SwsContext *swsContext)
Free the swscaler context swsContext.
Definition utils.c:2303
int swr_alloc_set_opts2(struct SwrContext **ps, const AVChannelLayout *out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate, const AVChannelLayout *in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate, int log_offset, void *log_ctx)
Allocate SwrContext if needed and set/reset common parameters.
Definition swresample.c:54
av_cold void swr_free(SwrContext **ss)
Free the given SwrContext and set the pointer to NULL.
Definition swresample.c:137
int swr_set_compensation(struct SwrContext *s, int sample_delta, int compensation_distance)
Activate resampling compensation ("soft" compensation).
Definition swresample.c:939
int attribute_align_arg swr_convert(struct SwrContext *s, uint8_t *const *out_arg, int out_count, const uint8_t *const *in_arg, int in_count)
Convert audio.
Definition swresample.c:751
av_cold int swr_init(struct SwrContext *s)
Initialize context after user parameters have been set.
Definition swresample.c:156
#define AV_OPT_SEARCH_CHILDREN
Search in possible children of the given object first.
Definition opt.h:604
int av_opt_set_int(void *obj, const char *name, int64_t val, int search_flags)
Definition opt.c:938
int av_opt_set_q(void *obj, const char *name, AVRational val, int search_flags)
Definition opt.c:948
int av_opt_set_array(void *obj, const char *name, int search_flags, unsigned int start_elem, unsigned int nb_elems, enum AVOptionType val_type, const void *val)
Add, replace, or remove elements for an array option.
Definition opt.c:2358
int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
Definition opt.c:891
int index
Definition gxfenc.c:90
int a
int av_hwdevice_ctx_create(AVBufferRef **pdevice_ref, enum AVHWDeviceType type, const char *device, AVDictionary *opts, int flags)
Open a device of the specified type and create an AVHWDeviceContext for it.
Definition hwcontext.c:615
int av_hwdevice_ctx_create_derived(AVBufferRef **dst_ref_ptr, enum AVHWDeviceType type, AVBufferRef *src_ref, int flags)
Create a new device of the specified type from an existing device.
Definition hwcontext.c:718
enum AVHWDeviceType av_hwdevice_find_type_by_name(const char *name)
Look up an AVHWDeviceType by name.
Definition hwcontext.c:110
AVHWDeviceType
Definition hwcontext.h:27
@ AV_HWDEVICE_TYPE_NONE
Definition hwcontext.h:28
static const int16_t alpha[]
Definition ilbcdata.h:55
#define r
Definition input.c:42
#define b
Definition input.c:43
#define av_log2
Definition intmath.h:84
static void scale(int *out, const int *in, const int w, const int h, const int shift)
Definition intra.c:278
uint32_t type
Definition jpegmpfenc.c:80
static int lcevc_merge(FFPacketSync *fs)
Definition lcevc_merge.c:85
static int shift(int a, int b)
Definition bonk.c:261
const char * arg
Definition jacosubdec.c:65
Macro definitions for various function/variable attributes.
#define av_fallthrough
Definition attributes.h:67
#define av_unused
Definition attributes.h:164
version
Definition libkvazaar.c:313
static enum AVPixelFormat pix_fmts[]
Definition libkvazaar.c:296
uint8_t w
Definition llvidencdsp.c:39
#define FFSWAP(type, a, b)
Definition macros.h:52
#define FFMIN(a, b)
Definition macros.h:49
#define FFMAX(a, b)
Definition macros.h:47
#define FFDIFFSIGN(x, y)
Comparator.
Definition macros.h:45
#define NAN
void * av_calloc(size_t nmemb, size_t size)
Definition mem.c:370
Memory handling functions.
static av_always_inline int cmp(MPVEncContext *const s, const int x, const int y, const int subx, const int suby, const int size, const int h, int ref_index, int src_index, me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags)
compares a block (either a full macroblock or a partition thereof) against a proposed motion-compensa...
Definition motion_est.c:263
uint32_t tag
Definition movenc.c:2128
const char data[16]
Definition mxf.c:149
#define av_strdup(s)
Definition ops_static.c:55
AVOptions.
#define CMDUTILS_COMMON_OPTIONS
Definition opt_common.h:199
int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen, void *log_ctx)
Put the RGBA values that correspond to color_string in rgba_color.
Definition parseutils.c:359
misc parsing utilities
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
Definition pixdesc.c:3404
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3484
#define AV_PIX_FMT_0RGB32
Definition pixfmt.h:524
@ AVCOL_RANGE_JPEG
Full range content.
Definition pixfmt.h:788
#define AV_PIX_FMT_BGR555
Definition pixfmt.h:541
AVAlphaMode
Correlation between the alpha channel and color values.
Definition pixfmt.h:821
@ AVALPHA_MODE_STRAIGHT
Alpha channel is independent of color values.
Definition pixfmt.h:824
@ AVALPHA_MODE_UNSPECIFIED
Unknown alpha handling, or no alpha channel.
Definition pixfmt.h:822
#define AV_PIX_FMT_BGR32
Definition pixfmt.h:522
AVPixelFormat
Pixel format.
Definition pixfmt.h:71
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition pixfmt.h:75
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition pixfmt.h:73
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition pixfmt.h:102
@ AV_PIX_FMT_UYVY422
packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
Definition pixfmt.h:88
@ AV_PIX_FMT_RGB8
packed RGB 3:3:2, 8bpp, (msb)3R 3G 2B(lsb)
Definition pixfmt.h:93
@ AV_PIX_FMT_YUYV422
packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
Definition pixfmt.h:74
@ AV_PIX_FMT_PAL8
8 bits with AV_PIX_FMT_RGB32 palette
Definition pixfmt.h:84
@ AV_PIX_FMT_BGR24
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition pixfmt.h:76
#define AV_PIX_FMT_RGB32_1
Definition pixfmt.h:521
#define AV_PIX_FMT_BGR32_1
Definition pixfmt.h:523
#define AV_PIX_FMT_BGR565
Definition pixfmt.h:540
#define AV_PIX_FMT_RGB565
Definition pixfmt.h:535
#define AV_PIX_FMT_RGB444
Definition pixfmt.h:537
#define AV_PIX_FMT_NE(be, le)
Definition pixfmt.h:517
#define AV_PIX_FMT_0BGR32
Definition pixfmt.h:525
#define AV_PIX_FMT_RGB32
Definition pixfmt.h:520
#define AV_PIX_FMT_RGB555
Definition pixfmt.h:536
AVColorSpace
YUV colorspace type.
Definition pixfmt.h:711
@ AVCOL_SPC_BT709
also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / derived in SMPTE RP 177 Annex B
Definition pixfmt.h:713
@ AVCOL_SPC_BT470BG
also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601
Definition pixfmt.h:717
@ AVCOL_SPC_SMPTE170M
also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC / functionally identical to above
Definition pixfmt.h:718
const char * name
Definition qsvenc.c:142
enum AVMediaType codec_type
Definition rtp.c:37
static volatile sig_atomic_t sig
Definition signal.c:48
#define FF_ARRAY_ELEMS(a)
unsigned int pos
Definition spdifenc.c:431
An instance of a filter.
Definition bsf.h:347
void * priv_data
Opaque filter-specific private data.
Definition bsf.h:375
A reference to a data buffer.
Definition buffer.h:82
uint8_t * data
The data buffer.
Definition buffer.h:90
This structure contains the parameters describing the frames that will be passed to this filter.
Definition buffersrc.h:73
AVRational frame_rate
Video only, the frame rate of the input video.
Definition buffersrc.h:100
enum AVColorRange color_range
Definition buffersrc.h:122
int format
video: the pixel format, value corresponds to enum AVPixelFormat audio: the sample format,...
Definition buffersrc.h:78
int width
Video only, the display dimensions of the input frames.
Definition buffersrc.h:87
enum AVColorSpace color_space
Video only, the YUV colorspace and range.
Definition buffersrc.h:121
enum AVAlphaMode alpha_mode
Video only, the alpha mode.
Definition buffersrc.h:130
AVRational time_base
The timebase to be used for the timestamps on the input frames.
Definition buffersrc.h:82
AVBufferRef * hw_frames_ctx
Video with a hwaccel pixel format only.
Definition buffersrc.h:106
AVRational sample_aspect_ratio
Video only, the sample (pixel) aspect ratio.
Definition buffersrc.h:92
An AVChannelLayout holds information about the channel layout of audio data.
enum AVChannelOrder order
Channel order used in this layout.
int nb_channels
Number of channels in this layout.
int64_t start
Definition avformat.h:1362
AVDictionary * metadata
Definition avformat.h:1363
int64_t end
chapter start/end time in time_base units
Definition avformat.h:1362
AVRational time_base
time base in which the start/end timestamps are specified
Definition avformat.h:1361
main external API structure.
Definition avcodec.h:443
AVChannelLayout ch_layout
Audio channel layout.
Definition avcodec.h:1055
int flags2
AV_CODEC_FLAG2_*.
Definition avcodec.h:507
enum AVSampleFormat sample_fmt
audio sample format
Definition avcodec.h:1047
AVRational pkt_timebase
Timebase in which pkt_dts/pts and AVPacket.dts/pts are expressed.
Definition avcodec.h:554
enum AVMediaType codec_type
Definition avcodec.h:451
int sample_rate
samples per second
Definition avcodec.h:1040
AVBufferRef * hw_device_ctx
A reference to the AVHWDeviceContext describing the device which will be used by a hardware encoder/d...
Definition avcodec.h:1494
enum AVCodecID codec_id
Definition avcodec.h:453
int lowres
low resolution decoding, 1-> 1/2 size, 2->1/4 size
Definition avcodec.h:1707
This struct describes the properties of an encoded stream.
Definition codec_par.h:49
int height
The height of the video frame in pixels.
Definition codec_par.h:150
AVChannelLayout ch_layout
The channel layout and number of channels.
Definition codec_par.h:207
int width
The width of the video frame in pixels.
Definition codec_par.h:143
enum AVMediaType codec_type
General type of the encoded data.
Definition codec_par.h:53
AVRational sample_aspect_ratio
The aspect ratio (width/height) which a single pixel should have when displayed.
Definition codec_par.h:161
int sample_rate
The number of audio samples per second.
Definition codec_par.h:213
AVCodec.
Definition codec.h:175
enum AVCodecID id
Definition codec.h:189
uint8_t max_lowres
maximum value for lowres supported by the decoder
Definition codec.h:195
int offset
Number of elements before the component of the first pixel.
Definition pixdesc.h:46
char * key
Definition dict.h:91
char * value
Definition dict.h:92
Definition fifo.c:35
An instance of a filter.
Definition avfilter.h:279
unsigned nb_filters
Definition avfilter.h:575
char * scale_sws_opts
sws options to use for the auto-inserted scale filters
Definition avfilter.h:577
AVFilterContext ** filters
Definition avfilter.h:574
int nb_threads
Maximum number of threads used by filters in this graph.
Definition avfilter.h:598
A linked-list of the inputs/outputs of the filter chain.
Definition avfilter.h:729
Filter definition.
Definition avfilter.h:221
Format I/O context.
Definition avformat.h:1400
int event_flags
Flags indicating events happening on the file, a combination of AVFMT_EVENT_FLAG_*.
Definition avformat.h:1788
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
Definition avformat.h:1456
AVStreamGroup ** stream_groups
A list of all stream groups in the file.
Definition avformat.h:1488
AVIOContext * pb
I/O context.
Definition avformat.h:1442
int64_t start_time
Position of the first frame of the component, in AV_TIME_BASE fractional seconds.
Definition avformat.h:1526
AVDictionary * metadata
Metadata that applies to the whole file.
Definition avformat.h:1648
int flags
Flags modifying the (de)muxer behaviour.
Definition avformat.h:1552
AVIOInterruptCB interrupt_callback
Custom interrupt callbacks for the I/O layer.
Definition avformat.h:1686
const struct AVInputFormat * iformat
The input container format.
Definition avformat.h:1412
unsigned int nb_chapters
Number of chapters in AVChapter array.
Definition avformat.h:1501
void * opaque
User data.
Definition avformat.h:1980
int64_t bit_rate
Total stream bitrate in bit/s, 0 if not available.
Definition avformat.h:1543
unsigned int nb_stream_groups
Number of elements in AVFormatContext.stream_groups.
Definition avformat.h:1475
AVStream ** streams
A list of all streams in the file.
Definition avformat.h:1468
int64_t duration
Duration of the stream, in AV_TIME_BASE fractional seconds.
Definition avformat.h:1536
Structure to hold side data for an AVFrame.
Definition frame.h:334
uint8_t * data
Definition frame.h:336
This structure describes decoded (raw) audio or video data.
Definition frame.h:479
int nb_samples
number of audio samples (per channel) described by this frame
Definition frame.h:559
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition frame.h:500
int width
Definition frame.h:551
int height
Definition frame.h:551
AVRational sample_aspect_ratio
Sample aspect ratio for the video frame, 0/1 if unknown/unspecified.
Definition frame.h:576
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition frame.h:524
int sample_rate
Sample rate of the audio data.
Definition frame.h:642
AVChannelLayout ch_layout
Channel layout of the audio data.
Definition frame.h:822
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames,...
Definition frame.h:566
enum AVPictureType pict_type
Picture type of the frame.
Definition frame.h:571
uint8_t ** extended_data
pointers to the data planes/channels.
Definition frame.h:540
int eof_reached
true if was unable to read due to error or eof
Definition avio.h:238
int error
contains the error code or 0 if no error happened
Definition avio.h:239
void * opaque
Definition avio.h:61
int(* callback)(void *)
Definition avio.h:60
int flags
Can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_EXPERIMENTAL, AVFMT_SHOW_IDS,...
Definition avformat.h:587
const char * name
A comma separated list of short names for the format.
Definition avformat.h:572
This structure stores auxiliary information for decoding, presenting, or otherwise processing the cod...
Definition packet.h:431
uint8_t * data
Definition packet.h:432
This structure stores compressed data.
Definition packet.h:587
AVBufferRef * buf
A reference to the reference-counted buffer where the packet data is stored.
Definition packet.h:593
int size
Definition packet.h:611
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition packet.h:628
AVBufferRef * opaque_ref
AVBufferRef for free use by the API user.
Definition packet.h:646
uint8_t * data
Definition packet.h:610
int64_t pos
byte position in stream, -1 if unknown
Definition packet.h:630
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
Definition pixdesc.h:105
New fields can be added to the end with minor version bumps.
Definition avformat.h:1324
Rational number (pair of numerator and denominator).
Definition rational.h:58
int num
Numerator.
Definition rational.h:59
int den
Denominator.
Definition rational.h:60
AVStream * stream
Definition avformat.h:1179
AVStreamGroupLayeredVideo is meant to define the relation between a base layer video stream and a sep...
Definition avformat.h:1104
unsigned int el_index
Index of the enhancement layer stream in AVStreamGroup.
Definition avformat.h:1113
unsigned int nb_entries
Number of elements in AVStreamGroup.entries.
Definition avformat.h:1285
enum AVStreamGroupParamsType type
Group type.
Definition avformat.h:1211
AVStreamGroupEntry ** entries
A list of streams or child groups in the group.
Definition avformat.h:1298
union AVStreamGroup::@313244315204024013007202273061153315146016101155 params
Group type-specific parameters.
struct AVStreamGroupLayeredVideo * layered_video
Definition avformat.h:1220
Stream structure.
Definition avformat.h:768
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition avformat.h:791
enum AVDiscard discard
Selects which packets can be discarded at will and do not need to be demuxed.
Definition avformat.h:839
AVDictionary * metadata
Definition avformat.h:848
int index
stream index in AVFormatContext
Definition avformat.h:774
int64_t start_time
Decoding: pts of the first frame of the stream in presentation order, in stream time base.
Definition avformat.h:817
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
Definition avformat.h:807
int event_flags
Flags indicating events happening on the stream, a combination of AVSTREAM_EVENT_FLAG_*.
Definition avformat.h:879
int disposition
Stream disposition - a combination of AV_DISPOSITION_* flags.
Definition avformat.h:837
int x
top left corner of pict, undefined when pict is not set
Definition avcodec.h:2076
int w
width of pict, undefined when pict is not set
Definition avcodec.h:2078
uint8_t * data[4]
data+linesize for the bitmap of this subtitle.
Definition avcodec.h:2086
int y
top left corner of pict, undefined when pict is not set
Definition avcodec.h:2077
int linesize[4]
Definition avcodec.h:2087
int h
height of pict, undefined when pict is not set
Definition avcodec.h:2079
uint16_t format
Definition avcodec.h:2103
uint32_t start_display_time
Definition avcodec.h:2104
uint32_t end_display_time
Definition avcodec.h:2105
unsigned num_rects
Definition avcodec.h:2106
AVSubtitleRect ** rects
Definition avcodec.h:2107
int64_t pts
Same as packet pts, in AV_TIME_BASE.
Definition avcodec.h:2108
int bytes_per_sec
Definition ffplay.c:177
int frame_size
Definition ffplay.c:176
enum AVSampleFormat fmt
Definition ffplay.c:175
AVChannelLayout ch_layout
Definition ffplay.c:174
int button_y[CHAPTER_SORT_NB]
Definition ffplay.c:1228
int button_x[CHAPTER_SORT_NB]
Definition ffplay.c:1228
int index
Definition ffplay.c:128
const char * artist
Definition ffplay.c:129
int64_t length
Definition ffplay.c:131
const char * title
Definition ffplay.c:130
SDL_Rect rect
Definition ffplay.c:144
char * script
Definition ffplay.c:146
const char * background
Definition ffplay.c:145
int serial
Definition ffplay.c:185
double pts
Definition ffplay.c:181
double pts_drift
Definition ffplay.c:182
double last_updated
Definition ffplay.c:183
int paused
Definition ffplay.c:186
double speed
Definition ffplay.c:184
int * queue_serial
Definition ffplay.c:187
SDL_cond * empty_queue_cond
Definition ffplay.c:254
int64_t start_pts
Definition ffplay.c:255
int64_t next_pts
Definition ffplay.c:257
PacketQueue * queue
Definition ffplay.c:249
int packet_pending
Definition ffplay.c:253
int finished
Definition ffplay.c:252
SDL_Thread * decoder_tid
Definition ffplay.c:259
AVCodecContext * avctx
Definition ffplay.c:250
AVRational next_pts_tb
Definition ffplay.c:258
AVRational start_pts_tb
Definition ffplay.c:256
int pkt_serial
Definition ffplay.c:251
AVPacket * pkt
Definition ffplay.c:248
Stream ** streams
Definition ffplay.c:235
int nb_stream_groups
Definition ffplay.c:238
int nb_streams
Definition ffplay.c:236
StreamGroup ** stream_groups
Definition ffplay.c:237
int64_t pkt_pos
Definition ffplay.c:191
SDL_mutex * mutex
Definition ffplay.c:218
SDL_cond * cond
Definition ffplay.c:219
int keep_last
Definition ffplay.c:216
PacketQueue * pktq
Definition ffplay.c:220
int rindex
Definition ffplay.c:212
int size
Definition ffplay.c:214
int rindex_shown
Definition ffplay.c:217
Frame queue[FRAME_QUEUE_SIZE]
Definition ffplay.c:211
int windex
Definition ffplay.c:213
int max_size
Definition ffplay.c:215
int width
Definition ffplay.c:202
AVRational sar
Definition ffplay.c:205
int uploaded
Definition ffplay.c:206
AVFrame * frame
Definition ffplay.c:196
double duration
Definition ffplay.c:200
int serial
Definition ffplay.c:198
int height
Definition ffplay.c:203
int64_t pos
Definition ffplay.c:201
AVSubtitle sub
Definition ffplay.c:197
int format
Definition ffplay.c:204
double pts
Definition ffplay.c:199
int flip_v
Definition ffplay.c:207
AVPacket * pkt
Definition ffplay.c:152
int serial
Definition ffplay.c:162
AVFifo * pkt_list
Definition ffplay.c:157
SDL_mutex * mutex
Definition ffplay.c:163
SDL_cond * cond
Definition ffplay.c:164
int64_t duration
Definition ffplay.c:160
int abort_request
Definition ffplay.c:161
int nb_packets
Definition ffplay.c:158
Definition cms.c:66
AVBitStreamFilterContext * sink
Definition ffplay.c:226
AVBitStreamFilterGraph * graph
Definition ffplay.c:225
AVStreamGroup * stg
Definition ffplay.c:224
StreamGroup * group
Definition ffplay.c:230
AVBitStreamFilterContext * filter
Definition ffplay.c:231
The libswresample context.
Main external API structure.
Definition swscale.h:227
enum AVPixelFormat format
Definition ffplay.c:463
int chapter_pin_requested
Definition ffplay.c:353
ChapterStrip * chapter_strips
Definition ffplay.c:341
AVFilterContext * out_video_filter
Definition ffplay.c:378
float * real_data
Definition ffplay.c:327
AVFilterContext * chapter_sink
Definition ffplay.c:340
int last_i_start
Definition ffplay.c:323
struct AudioParams audio_src
Definition ffplay.c:311
int xpos
Definition ffplay.c:329
AVFilterGraph * agraph
Definition ffplay.c:381
int height
Definition ffplay.c:373
int last_paused
Definition ffplay.c:268
int16_t sample_array[SAMPLE_ARRAY_SIZE]
Definition ffplay.c:321
int chapter_playing
Definition ffplay.c:348
Decoder auddec
Definition ffplay.c:286
AVTXContext * rdft
Definition ffplay.c:324
int abort_request
Definition ffplay.c:265
int width
Definition ffplay.c:373
int chapter_mouse_y
Definition ffplay.c:349
SDL_Rect chapter_rect
Definition ffplay.c:338
int subtitle_stream
Definition ffplay.c:358
int av_sync_type
Definition ffplay.c:292
RenderParams render_params
Definition ffplay.c:331
int xleft
Definition ffplay.c:373
SDL_Texture * chapter_texture
Definition ffplay.c:335
SDL_Texture * vid_texture
Definition ffplay.c:334
int nb_chapter_rows
Definition ffplay.c:345
unsigned int audio_buf_size
Definition ffplay.c:305
int64_t chapter_fade_start
Definition ffplay.c:354
int vfilter_idx
Definition ffplay.c:376
enum VideoState::ShowMode show_mode
int audio_stream
Definition ffplay.c:290
int paused
Definition ffplay.c:267
int audio_volume
Definition ffplay.c:309
AVStream * video_st
Definition ffplay.c:366
struct AudioParams audio_tgt
Definition ffplay.c:313
Clock audclk
Definition ffplay.c:278
AVStream * audio_st
Definition ffplay.c:300
double audio_diff_cum
Definition ffplay.c:296
int rdft_bits
Definition ffplay.c:326
const AVInputFormat * iformat
Definition ffplay.c:264
double audio_diff_threshold
Definition ffplay.c:298
int read_pause_return
Definition ffplay.c:274
Clock extclk
Definition ffplay.c:280
double audio_diff_avg_coef
Definition ffplay.c:297
AVFilterContext * out_audio_filter
Definition ffplay.c:380
Decoder subdec
Definition ffplay.c:288
int sample_array_index
Definition ffplay.c:322
int frame_drops_late
Definition ffplay.c:316
int audio_buf_index
Definition ffplay.c:307
double frame_timer
Definition ffplay.c:362
int64_t seek_pos
Definition ffplay.c:272
double max_frame_duration
Definition ffplay.c:368
double frame_last_returned_time
Definition ffplay.c:363
int chapter_selected
Definition ffplay.c:347
struct SwrContext * swr_ctx
Definition ffplay.c:314
SDL_Texture * vis_texture
Definition ffplay.c:332
int step
Definition ffplay.c:374
int chapter_pinned
Definition ffplay.c:352
int frame_drops_early
Definition ffplay.c:315
int chapter_first
Definition ffplay.c:343
struct AudioParams audio_filter_src
Definition ffplay.c:312
int audio_hw_buf_size
Definition ffplay.c:302
SDL_cond * continue_read_thread
Definition ffplay.c:385
int ytop
Definition ffplay.c:373
FrameQueue subpq
Definition ffplay.c:283
int chapter_render_pending
Definition ffplay.c:351
AVFormatContext * ic
Definition ffplay.c:275
@ SHOW_MODE_VIDEO
Definition ffplay.c:319
@ SHOW_MODE_NONE
Definition ffplay.c:319
@ SHOW_MODE_RDFT
Definition ffplay.c:319
@ SHOW_MODE_NB
Definition ffplay.c:319
@ SHOW_MODE_WAVES
Definition ffplay.c:319
Decoder viddec
Definition ffplay.c:287
AVComplexFloat * rdft_data
Definition ffplay.c:328
int nb_chapter_strips
Definition ffplay.c:342
int audio_diff_avg_count
Definition ffplay.c:299
FrameQueue pictq
Definition ffplay.c:282
uint8_t * audio_buf1
Definition ffplay.c:304
ChapterListHit chapter_hover
Definition ffplay.c:350
char * filename
Definition ffplay.c:372
int last_subtitle_stream
Definition ffplay.c:383
SDL_Rect chapter_dirty
Definition ffplay.c:336
AVFilterGraph * chapter_graph
Definition ffplay.c:339
int64_t chapter_last_input
Definition ffplay.c:355
PacketQueue subtitleq
Definition ffplay.c:360
double chapter_drawn_alpha
Definition ffplay.c:356
int realtime
Definition ffplay.c:276
int video_stream
Definition ffplay.c:365
int muted
Definition ffplay.c:310
int force_refresh
Definition ffplay.c:266
char chapter_search[64]
Definition ffplay.c:346
int seek_flags
Definition ffplay.c:271
uint8_t * chapter_bitmap
Definition ffplay.c:337
double frame_last_filter_delay
Definition ffplay.c:364
int last_video_stream
Definition ffplay.c:383
int audio_clock_serial
Definition ffplay.c:295
int chapter_mouse_x
Definition ffplay.c:349
AVStream * subtitle_st
Definition ffplay.c:359
unsigned int audio_buf1_size
Definition ffplay.c:306
av_tx_fn rdft_fn
Definition ffplay.c:325
struct SwsContext * sub_convert_ctx
Definition ffplay.c:369
int last_audio_stream
Definition ffplay.c:383
double last_vis_time
Definition ffplay.c:330
int64_t seek_rel
Definition ffplay.c:273
PacketQueue audioq
Definition ffplay.c:301
AVFilterContext * in_video_filter
Definition ffplay.c:377
ChapterRow * chapter_rows
Definition ffplay.c:344
PacketQueue videoq
Definition ffplay.c:367
int audio_write_buf_size
Definition ffplay.c:308
double audio_clock
Definition ffplay.c:294
int seek_req
Definition ffplay.c:270
int queue_attachments_req
Definition ffplay.c:269
SDL_Thread * read_tid
Definition ffplay.c:263
SDL_Texture * sub_texture
Definition ffplay.c:333
uint8_t * audio_buf
Definition ffplay.c:303
int eof
Definition ffplay.c:370
FrameQueue sampq
Definition ffplay.c:284
AVFilterContext * in_audio_filter
Definition ffplay.c:379
Clock vidclk
Definition ffplay.c:279
Definition swscale.c:71
int w
Definition f_ebur128.c:78
int y
Definition f_ebur128.c:78
int h
Definition f_ebur128.c:78
int x
Definition f_ebur128.c:78
libswresample public header
external API header
#define lrint
Definition tablegen.h:53
#define av_free(p)
#define av_malloc_array(a, b)
#define av_mallocz(s)
#define av_freep(p)
#define av_log(a,...)
void(* filter)(uint8_t *src, ptrdiff_t stride, int qscale)
Definition h263dsp.c:29
#define src
Definition vp8dsp.c:248
int num
Definition error.c:23
#define height
Definition dsp.h:99
#define width
Definition dsp.h:99
int av_usleep(unsigned usec)
Sleep for a period of time.
Definition time.c:93
int64_t av_gettime_relative(void)
Get the current time in microseconds since some unspecified starting point.
Definition time.c:57
static int64_t pts
int size
av_cold void av_tx_uninit(AVTXContext **ctx)
Frees a context and sets *ctx to NULL, does nothing when *ctx == NULL.
Definition tx.c:295
av_cold int av_tx_init(AVTXContext **ctx, av_tx_fn *tx, enum AVTXType type, int inv, int len, const void *scale, uint64_t flags)
Initialize a transform context with the given configuration (i)MDCTs with an odd length are currently...
Definition tx.c:903
@ AV_TX_FLOAT_RDFT
Real to complex and complex to real DFTs.
Definition tx.h:90
void(* av_tx_fn)(AVTXContext *s, void *out, void *in, ptrdiff_t stride)
Function pointer to a function to perform the transform.
Definition tx.h:151
static av_always_inline int diff(const struct color_info *a, const struct color_info *b, const int trans_thresh)
float delta
int len
static double c[64]