FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/fftools/ffplay.c
Date: 2026-09-19 20:18:21
Exec Total Coverage
Lines: 0 2280 0.0%
Functions: 0 101 0.0%
Branches: 0 1542 0.0%

Line Branch Exec Source
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
33 #include "libavutil/attributes.h"
34 #include "libavutil/avstring.h"
35 #include "libavutil/channel_layout.h"
36 #include "libavutil/mathematics.h"
37 #include "libavutil/mem.h"
38 #include "libavutil/pixdesc.h"
39 #include "libavutil/dict.h"
40 #include "libavutil/fifo.h"
41 #include "libavutil/parseutils.h"
42 #include "libavutil/samplefmt.h"
43 #include "libavutil/time.h"
44 #include "libavutil/bprint.h"
45 #include "libavformat/avformat.h"
46 #include "libavdevice/avdevice.h"
47 #include "libswscale/swscale.h"
48 #include "libavutil/opt.h"
49 #include "libavutil/tx.h"
50 #include "libswresample/swresample.h"
51
52 #include "libavfilter/avfilter.h"
53 #include "libavfilter/buffersink.h"
54 #include "libavfilter/buffersrc.h"
55
56 #include <SDL.h>
57 #include <SDL_thread.h>
58
59 #include "cmdutils.h"
60 #include "ffplay_renderer.h"
61 #include "opt_common.h"
62
63 const char program_name[] = "ffplay";
64 const int program_birth_year = 2003;
65
66 #define MAX_QUEUE_SIZE (15 * 1024 * 1024)
67 #define MIN_FRAMES 25
68 #define EXTERNAL_CLOCK_MIN_FRAMES 2
69 #define EXTERNAL_CLOCK_MAX_FRAMES 10
70
71 /* Minimum SDL audio buffer size, in samples. */
72 #define SDL_AUDIO_MIN_BUFFER_SIZE 512
73 /* Calculate actual buffer size keeping in mind not cause too frequent audio callbacks */
74 #define SDL_AUDIO_MAX_CALLBACKS_PER_SEC 30
75
76 /* Step size for volume control in dB */
77 #define SDL_VOLUME_STEP (0.75)
78
79 /* no AV sync correction is done if below the minimum AV sync threshold */
80 #define AV_SYNC_THRESHOLD_MIN 0.04
81 /* AV sync correction is done if above the maximum AV sync threshold */
82 #define AV_SYNC_THRESHOLD_MAX 0.1
83 /* If a frame duration is longer than this, it will not be duplicated to compensate AV sync */
84 #define AV_SYNC_FRAMEDUP_THRESHOLD 0.1
85 /* no AV correction is done if too big error */
86 #define AV_NOSYNC_THRESHOLD 10.0
87
88 /* maximum audio speed change to get correct sync */
89 #define SAMPLE_CORRECTION_PERCENT_MAX 10
90
91 /* external clock speed adjustment constants for realtime sources based on buffer fullness */
92 #define EXTERNAL_CLOCK_SPEED_MIN 0.900
93 #define EXTERNAL_CLOCK_SPEED_MAX 1.010
94 #define EXTERNAL_CLOCK_SPEED_STEP 0.001
95
96 /* we use about AUDIO_DIFF_AVG_NB A-V differences to make the average */
97 #define AUDIO_DIFF_AVG_NB 20
98
99 /* polls for possible required screen refresh at least this often, should be less than 1/fps */
100 #define REFRESH_RATE 0.01
101
102 /* NOTE: the size must be big enough to compensate the hardware audio buffersize size */
103 /* TODO: We assume that a decoded and resampled frame fits into this buffer */
104 #define SAMPLE_ARRAY_SIZE (8 * 65536)
105
106 #define CURSOR_HIDE_DELAY 1000000
107
108 #define USE_ONEPASS_SUBTITLE_RENDER 1
109
110 typedef struct MyAVPacketList {
111 AVPacket *pkt;
112 int serial;
113 } MyAVPacketList;
114
115 typedef struct PacketQueue {
116 AVFifo *pkt_list;
117 int nb_packets;
118 int size;
119 int64_t duration;
120 int abort_request;
121 int serial;
122 SDL_mutex *mutex;
123 SDL_cond *cond;
124 } PacketQueue;
125
126 #define VIDEO_PICTURE_QUEUE_SIZE 3
127 #define SUBPICTURE_QUEUE_SIZE 16
128 #define SAMPLE_QUEUE_SIZE 9
129 #define FRAME_QUEUE_SIZE FFMAX(SAMPLE_QUEUE_SIZE, FFMAX(VIDEO_PICTURE_QUEUE_SIZE, SUBPICTURE_QUEUE_SIZE))
130
131 typedef struct AudioParams {
132 int freq;
133 AVChannelLayout ch_layout;
134 enum AVSampleFormat fmt;
135 int frame_size;
136 int bytes_per_sec;
137 } AudioParams;
138
139 typedef struct Clock {
140 double pts; /* clock base */
141 double pts_drift; /* clock base minus time at which we updated the clock */
142 double last_updated;
143 double speed;
144 int serial; /* clock is based on a packet with this serial */
145 int paused;
146 int *queue_serial; /* pointer to the current packet queue serial, used for obsolete clock detection */
147 } Clock;
148
149 typedef struct FrameData {
150 int64_t pkt_pos;
151 } FrameData;
152
153 /* Common struct for handling all types of decoded data and allocated render buffers. */
154 typedef struct Frame {
155 AVFrame *frame;
156 AVSubtitle sub;
157 int serial;
158 double pts; /* presentation timestamp for the frame */
159 double duration; /* estimated duration of the frame */
160 int64_t pos; /* byte position of the frame in the input file */
161 int width;
162 int height;
163 int format;
164 AVRational sar;
165 int uploaded;
166 int flip_v;
167 } Frame;
168
169 typedef struct FrameQueue {
170 Frame queue[FRAME_QUEUE_SIZE];
171 int rindex;
172 int windex;
173 int size;
174 int max_size;
175 int keep_last;
176 int rindex_shown;
177 SDL_mutex *mutex;
178 SDL_cond *cond;
179 PacketQueue *pktq;
180 } FrameQueue;
181
182 enum {
183 AV_SYNC_AUDIO_MASTER, /* default choice */
184 AV_SYNC_VIDEO_MASTER,
185 AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */
186 };
187
188 typedef struct Decoder {
189 AVPacket *pkt;
190 PacketQueue *queue;
191 AVCodecContext *avctx;
192 int pkt_serial;
193 int finished;
194 int packet_pending;
195 SDL_cond *empty_queue_cond;
196 int64_t start_pts;
197 AVRational start_pts_tb;
198 int64_t next_pts;
199 AVRational next_pts_tb;
200 SDL_Thread *decoder_tid;
201 } Decoder;
202
203 typedef struct VideoState {
204 SDL_Thread *read_tid;
205 const AVInputFormat *iformat;
206 int abort_request;
207 int force_refresh;
208 int paused;
209 int last_paused;
210 int queue_attachments_req;
211 int seek_req;
212 int seek_flags;
213 int64_t seek_pos;
214 int64_t seek_rel;
215 int read_pause_return;
216 AVFormatContext *ic;
217 int realtime;
218
219 Clock audclk;
220 Clock vidclk;
221 Clock extclk;
222
223 FrameQueue pictq;
224 FrameQueue subpq;
225 FrameQueue sampq;
226
227 Decoder auddec;
228 Decoder viddec;
229 Decoder subdec;
230
231 int audio_stream;
232
233 int av_sync_type;
234
235 double audio_clock;
236 int audio_clock_serial;
237 double audio_diff_cum; /* used for AV difference average computation */
238 double audio_diff_avg_coef;
239 double audio_diff_threshold;
240 int audio_diff_avg_count;
241 AVStream *audio_st;
242 PacketQueue audioq;
243 int audio_hw_buf_size;
244 uint8_t *audio_buf;
245 uint8_t *audio_buf1;
246 unsigned int audio_buf_size; /* in bytes */
247 unsigned int audio_buf1_size;
248 int audio_buf_index; /* in bytes */
249 int audio_write_buf_size;
250 int audio_volume;
251 int muted;
252 struct AudioParams audio_src;
253 struct AudioParams audio_filter_src;
254 struct AudioParams audio_tgt;
255 struct SwrContext *swr_ctx;
256 int frame_drops_early;
257 int frame_drops_late;
258
259 enum ShowMode {
260 SHOW_MODE_NONE = -1, SHOW_MODE_VIDEO = 0, SHOW_MODE_WAVES, SHOW_MODE_RDFT, SHOW_MODE_NB
261 } show_mode;
262 int16_t sample_array[SAMPLE_ARRAY_SIZE];
263 int sample_array_index;
264 int last_i_start;
265 AVTXContext *rdft;
266 av_tx_fn rdft_fn;
267 int rdft_bits;
268 float *real_data;
269 AVComplexFloat *rdft_data;
270 int xpos;
271 double last_vis_time;
272 RenderParams render_params;
273 SDL_Texture *vis_texture;
274 SDL_Texture *sub_texture;
275 SDL_Texture *vid_texture;
276
277 int subtitle_stream;
278 AVStream *subtitle_st;
279 PacketQueue subtitleq;
280
281 double frame_timer;
282 double frame_last_returned_time;
283 double frame_last_filter_delay;
284 int video_stream;
285 AVStream *video_st;
286 PacketQueue videoq;
287 double max_frame_duration; // maximum duration of a frame - above this, we consider the jump a timestamp discontinuity
288 struct SwsContext *sub_convert_ctx;
289 int eof;
290
291 char *filename;
292 int width, height, xleft, ytop;
293 int step;
294
295 int vfilter_idx;
296 AVFilterContext *in_video_filter; // the first filter in the video chain
297 AVFilterContext *out_video_filter; // the last filter in the video chain
298 AVFilterContext *in_audio_filter; // the first filter in the audio chain
299 AVFilterContext *out_audio_filter; // the last filter in the audio chain
300 AVFilterGraph *agraph; // audio filter graph
301
302 int last_video_stream, last_audio_stream, last_subtitle_stream;
303
304 SDL_cond *continue_read_thread;
305 } VideoState;
306
307 /* options specified by the user */
308 static const AVInputFormat *file_iformat;
309 static const char *input_filename;
310 static const char *window_title;
311 static int default_width = 640;
312 static int default_height = 480;
313 static int screen_width = 0;
314 static int screen_height = 0;
315 static int screen_left = SDL_WINDOWPOS_CENTERED;
316 static int screen_top = SDL_WINDOWPOS_CENTERED;
317 static int audio_disable;
318 static int video_disable;
319 static int subtitle_disable;
320 static const char* wanted_stream_spec[AVMEDIA_TYPE_NB] = {0};
321 static int seek_by_bytes = -1;
322 static float seek_interval = 10;
323 static int display_disable;
324 static int borderless;
325 static int alwaysontop;
326 static int startup_volume = 100;
327 static int show_status = -1;
328 static int av_sync_type = AV_SYNC_AUDIO_MASTER;
329 static int64_t start_time = AV_NOPTS_VALUE;
330 static int64_t duration = AV_NOPTS_VALUE;
331 static int fast = 0;
332 static int genpts = 0;
333 static int lowres = 0;
334 static int decoder_reorder_pts = -1;
335 static int autoexit;
336 static int exit_on_keydown;
337 static int exit_on_mousedown;
338 static int loop = 1;
339 static int framedrop = -1;
340 static int infinite_buffer = -1;
341 static enum ShowMode show_mode = SHOW_MODE_NONE;
342 static const char *audio_codec_name;
343 static const char *subtitle_codec_name;
344 static const char *video_codec_name;
345 double rdftspeed = 0.02;
346 static int64_t cursor_last_shown;
347 static int cursor_hidden = 0;
348 static const char **vfilters_list = NULL;
349 static int nb_vfilters = 0;
350 static char *afilters = NULL;
351 static int autorotate = 1;
352 static int find_stream_info = 1;
353 static int filter_nbthreads = 0;
354 static int enable_vulkan = 0;
355 static char *vulkan_params = NULL;
356 static char *video_background = NULL;
357 static const char *hwaccel = NULL;
358
359 /* current context */
360 static int is_full_screen;
361 static int64_t audio_callback_time;
362
363 #define FF_QUIT_EVENT (SDL_USEREVENT + 2)
364
365 static volatile sig_atomic_t received_sigterm = 0;
366 static volatile int received_nb_signals = 0;
367 static int exit_status = 0;
368
369 static SDL_Window *window;
370 static SDL_Renderer *renderer;
371 static SDL_RendererInfo renderer_info = {0};
372 static SDL_AudioDeviceID audio_dev;
373
374 static VkRenderer *vk_renderer;
375
376 static const struct TextureFormatEntry {
377 enum AVPixelFormat format;
378 int texture_fmt;
379 } sdl_texture_format_map[] = {
380 { AV_PIX_FMT_RGB8, SDL_PIXELFORMAT_RGB332 },
381 { AV_PIX_FMT_RGB444, SDL_PIXELFORMAT_RGB444 },
382 { AV_PIX_FMT_RGB555, SDL_PIXELFORMAT_RGB555 },
383 { AV_PIX_FMT_BGR555, SDL_PIXELFORMAT_BGR555 },
384 { AV_PIX_FMT_RGB565, SDL_PIXELFORMAT_RGB565 },
385 { AV_PIX_FMT_BGR565, SDL_PIXELFORMAT_BGR565 },
386 { AV_PIX_FMT_RGB24, SDL_PIXELFORMAT_RGB24 },
387 { AV_PIX_FMT_BGR24, SDL_PIXELFORMAT_BGR24 },
388 { AV_PIX_FMT_0RGB32, SDL_PIXELFORMAT_RGB888 },
389 { AV_PIX_FMT_0BGR32, SDL_PIXELFORMAT_BGR888 },
390 { AV_PIX_FMT_NE(RGB0, 0BGR), SDL_PIXELFORMAT_RGBX8888 },
391 { AV_PIX_FMT_NE(BGR0, 0RGB), SDL_PIXELFORMAT_BGRX8888 },
392 { AV_PIX_FMT_RGB32, SDL_PIXELFORMAT_ARGB8888 },
393 { AV_PIX_FMT_RGB32_1, SDL_PIXELFORMAT_RGBA8888 },
394 { AV_PIX_FMT_BGR32, SDL_PIXELFORMAT_ABGR8888 },
395 { AV_PIX_FMT_BGR32_1, SDL_PIXELFORMAT_BGRA8888 },
396 { AV_PIX_FMT_YUV420P, SDL_PIXELFORMAT_IYUV },
397 { AV_PIX_FMT_YUYV422, SDL_PIXELFORMAT_YUY2 },
398 { AV_PIX_FMT_UYVY422, SDL_PIXELFORMAT_UYVY },
399 };
400
401 static int opt_add_vfilter(void *optctx, const char *opt, const char *arg)
402 {
403 int ret = GROW_ARRAY(vfilters_list, nb_vfilters);
404 if (ret < 0)
405 return ret;
406
407 vfilters_list[nb_vfilters - 1] = av_strdup(arg);
408 if (!vfilters_list[nb_vfilters - 1])
409 return AVERROR(ENOMEM);
410
411 return 0;
412 }
413
414 static inline
415 int cmp_audio_fmts(enum AVSampleFormat fmt1, int64_t channel_count1,
416 enum AVSampleFormat fmt2, int64_t channel_count2)
417 {
418 /* If channel count == 1, planar and non-planar formats are the same */
419 if (channel_count1 == 1 && channel_count2 == 1)
420 return av_get_packed_sample_fmt(fmt1) != av_get_packed_sample_fmt(fmt2);
421 else
422 return channel_count1 != channel_count2 || fmt1 != fmt2;
423 }
424
425 static int packet_queue_put_private(PacketQueue *q, AVPacket *pkt)
426 {
427 MyAVPacketList pkt1;
428 int ret;
429
430 if (q->abort_request)
431 return -1;
432
433
434 pkt1.pkt = pkt;
435 pkt1.serial = q->serial;
436
437 ret = av_fifo_write(q->pkt_list, &pkt1, 1);
438 if (ret < 0)
439 return ret;
440 q->nb_packets++;
441 q->size += pkt1.pkt->size + sizeof(pkt1);
442 q->duration += pkt1.pkt->duration;
443 /* XXX: should duplicate packet data in DV case */
444 SDL_CondSignal(q->cond);
445 return 0;
446 }
447
448 static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
449 {
450 AVPacket *pkt1;
451 int ret;
452
453 pkt1 = av_packet_alloc();
454 if (!pkt1) {
455 av_packet_unref(pkt);
456 return -1;
457 }
458 av_packet_move_ref(pkt1, pkt);
459
460 SDL_LockMutex(q->mutex);
461 ret = packet_queue_put_private(q, pkt1);
462 SDL_UnlockMutex(q->mutex);
463
464 if (ret < 0)
465 av_packet_free(&pkt1);
466
467 return ret;
468 }
469
470 static int packet_queue_put_nullpacket(PacketQueue *q, AVPacket *pkt, int stream_index)
471 {
472 pkt->stream_index = stream_index;
473 return packet_queue_put(q, pkt);
474 }
475
476 /* packet queue handling */
477 static int packet_queue_init(PacketQueue *q)
478 {
479 memset(q, 0, sizeof(PacketQueue));
480 q->pkt_list = av_fifo_alloc2(1, sizeof(MyAVPacketList), AV_FIFO_FLAG_AUTO_GROW);
481 if (!q->pkt_list)
482 return AVERROR(ENOMEM);
483 q->mutex = SDL_CreateMutex();
484 if (!q->mutex) {
485 av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError());
486 return AVERROR(ENOMEM);
487 }
488 q->cond = SDL_CreateCond();
489 if (!q->cond) {
490 av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError());
491 return AVERROR(ENOMEM);
492 }
493 q->abort_request = 1;
494 return 0;
495 }
496
497 static void packet_queue_flush(PacketQueue *q)
498 {
499 MyAVPacketList pkt1;
500
501 SDL_LockMutex(q->mutex);
502 while (av_fifo_read(q->pkt_list, &pkt1, 1) >= 0)
503 av_packet_free(&pkt1.pkt);
504 q->nb_packets = 0;
505 q->size = 0;
506 q->duration = 0;
507 q->serial++;
508 SDL_UnlockMutex(q->mutex);
509 }
510
511 static void packet_queue_destroy(PacketQueue *q)
512 {
513 packet_queue_flush(q);
514 av_fifo_freep2(&q->pkt_list);
515 SDL_DestroyMutex(q->mutex);
516 SDL_DestroyCond(q->cond);
517 }
518
519 static void packet_queue_abort(PacketQueue *q)
520 {
521 SDL_LockMutex(q->mutex);
522
523 q->abort_request = 1;
524
525 SDL_CondSignal(q->cond);
526
527 SDL_UnlockMutex(q->mutex);
528 }
529
530 static void packet_queue_start(PacketQueue *q)
531 {
532 SDL_LockMutex(q->mutex);
533 q->abort_request = 0;
534 q->serial++;
535 SDL_UnlockMutex(q->mutex);
536 }
537
538 /* return < 0 if aborted, 0 if no packet and > 0 if packet. */
539 static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block, int *serial)
540 {
541 MyAVPacketList pkt1;
542 int ret;
543
544 SDL_LockMutex(q->mutex);
545
546 for (;;) {
547 if (q->abort_request) {
548 ret = -1;
549 break;
550 }
551
552 if (av_fifo_read(q->pkt_list, &pkt1, 1) >= 0) {
553 q->nb_packets--;
554 q->size -= pkt1.pkt->size + sizeof(pkt1);
555 q->duration -= pkt1.pkt->duration;
556 av_packet_move_ref(pkt, pkt1.pkt);
557 if (serial)
558 *serial = pkt1.serial;
559 av_packet_free(&pkt1.pkt);
560 ret = 1;
561 break;
562 } else if (!block) {
563 ret = 0;
564 break;
565 } else {
566 SDL_CondWait(q->cond, q->mutex);
567 }
568 }
569 SDL_UnlockMutex(q->mutex);
570 return ret;
571 }
572
573 static int decoder_init(Decoder *d, AVCodecContext *avctx, PacketQueue *queue, SDL_cond *empty_queue_cond) {
574 memset(d, 0, sizeof(Decoder));
575 d->pkt = av_packet_alloc();
576 if (!d->pkt)
577 return AVERROR(ENOMEM);
578 d->avctx = avctx;
579 d->queue = queue;
580 d->empty_queue_cond = empty_queue_cond;
581 d->start_pts = AV_NOPTS_VALUE;
582 d->pkt_serial = -1;
583 return 0;
584 }
585
586 static int decoder_decode_frame(Decoder *d, AVFrame *frame, AVSubtitle *sub) {
587 int ret = AVERROR(EAGAIN);
588
589 for (;;) {
590 if (d->queue->serial == d->pkt_serial) {
591 do {
592 if (d->queue->abort_request)
593 return -1;
594
595 switch (d->avctx->codec_type) {
596 case AVMEDIA_TYPE_VIDEO:
597 ret = avcodec_receive_frame(d->avctx, frame);
598 if (ret >= 0) {
599 if (decoder_reorder_pts == -1) {
600 frame->pts = frame->best_effort_timestamp;
601 } else if (!decoder_reorder_pts) {
602 frame->pts = frame->pkt_dts;
603 }
604 }
605 break;
606 case AVMEDIA_TYPE_AUDIO:
607 ret = avcodec_receive_frame(d->avctx, frame);
608 if (ret >= 0) {
609 AVRational tb = (AVRational){1, frame->sample_rate};
610 if (frame->pts != AV_NOPTS_VALUE)
611 frame->pts = av_rescale_q(frame->pts, d->avctx->pkt_timebase, tb);
612 else if (d->next_pts != AV_NOPTS_VALUE)
613 frame->pts = av_rescale_q(d->next_pts, d->next_pts_tb, tb);
614 if (frame->pts != AV_NOPTS_VALUE) {
615 d->next_pts = frame->pts + frame->nb_samples;
616 d->next_pts_tb = tb;
617 }
618 }
619 break;
620 }
621 if (ret == AVERROR_EOF) {
622 d->finished = d->pkt_serial;
623 avcodec_flush_buffers(d->avctx);
624 return 0;
625 }
626 if (ret >= 0)
627 return 1;
628 } while (ret != AVERROR(EAGAIN));
629 }
630
631 do {
632 if (d->queue->nb_packets == 0)
633 SDL_CondSignal(d->empty_queue_cond);
634 if (d->packet_pending) {
635 d->packet_pending = 0;
636 } else {
637 int old_serial = d->pkt_serial;
638 if (packet_queue_get(d->queue, d->pkt, 1, &d->pkt_serial) < 0)
639 return -1;
640 if (old_serial != d->pkt_serial) {
641 avcodec_flush_buffers(d->avctx);
642 d->finished = 0;
643 d->next_pts = d->start_pts;
644 d->next_pts_tb = d->start_pts_tb;
645 }
646 }
647 if (d->queue->serial == d->pkt_serial)
648 break;
649 av_packet_unref(d->pkt);
650 } while (1);
651
652 if (d->avctx->codec_type == AVMEDIA_TYPE_SUBTITLE) {
653 int got_frame = 0;
654 ret = avcodec_decode_subtitle2(d->avctx, sub, &got_frame, d->pkt);
655 if (ret < 0) {
656 ret = AVERROR(EAGAIN);
657 } else {
658 if (got_frame && !d->pkt->data) {
659 d->packet_pending = 1;
660 }
661 ret = got_frame ? 0 : (d->pkt->data ? AVERROR(EAGAIN) : AVERROR_EOF);
662 }
663 av_packet_unref(d->pkt);
664 } else {
665 if (d->pkt->buf && !d->pkt->opaque_ref) {
666 FrameData *fd;
667
668 d->pkt->opaque_ref = av_buffer_allocz(sizeof(*fd));
669 if (!d->pkt->opaque_ref)
670 return AVERROR(ENOMEM);
671 fd = (FrameData*)d->pkt->opaque_ref->data;
672 fd->pkt_pos = d->pkt->pos;
673 }
674
675 if (avcodec_send_packet(d->avctx, d->pkt) == AVERROR(EAGAIN)) {
676 av_log(d->avctx, AV_LOG_ERROR, "Receive_frame and send_packet both returned EAGAIN, which is an API violation.\n");
677 d->packet_pending = 1;
678 } else {
679 av_packet_unref(d->pkt);
680 }
681 }
682 }
683 }
684
685 static void decoder_destroy(Decoder *d) {
686 av_packet_free(&d->pkt);
687 avcodec_free_context(&d->avctx);
688 }
689
690 static void frame_queue_unref_item(Frame *vp)
691 {
692 av_frame_unref(vp->frame);
693 avsubtitle_free(&vp->sub);
694 }
695
696 static int frame_queue_init(FrameQueue *f, PacketQueue *pktq, int max_size, int keep_last)
697 {
698 int i;
699 memset(f, 0, sizeof(FrameQueue));
700 if (!(f->mutex = SDL_CreateMutex())) {
701 av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError());
702 return AVERROR(ENOMEM);
703 }
704 if (!(f->cond = SDL_CreateCond())) {
705 av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError());
706 return AVERROR(ENOMEM);
707 }
708 f->pktq = pktq;
709 f->max_size = FFMIN(max_size, FRAME_QUEUE_SIZE);
710 f->keep_last = !!keep_last;
711 for (i = 0; i < f->max_size; i++)
712 if (!(f->queue[i].frame = av_frame_alloc()))
713 return AVERROR(ENOMEM);
714 return 0;
715 }
716
717 static void frame_queue_destroy(FrameQueue *f)
718 {
719 int i;
720 for (i = 0; i < f->max_size; i++) {
721 Frame *vp = &f->queue[i];
722 frame_queue_unref_item(vp);
723 av_frame_free(&vp->frame);
724 }
725 SDL_DestroyMutex(f->mutex);
726 SDL_DestroyCond(f->cond);
727 }
728
729 static void frame_queue_signal(FrameQueue *f)
730 {
731 SDL_LockMutex(f->mutex);
732 SDL_CondSignal(f->cond);
733 SDL_UnlockMutex(f->mutex);
734 }
735
736 static Frame *frame_queue_peek(FrameQueue *f)
737 {
738 return &f->queue[(f->rindex + f->rindex_shown) % f->max_size];
739 }
740
741 static Frame *frame_queue_peek_next(FrameQueue *f)
742 {
743 return &f->queue[(f->rindex + f->rindex_shown + 1) % f->max_size];
744 }
745
746 static Frame *frame_queue_peek_last(FrameQueue *f)
747 {
748 return &f->queue[f->rindex];
749 }
750
751 static Frame *frame_queue_peek_writable(FrameQueue *f)
752 {
753 /* wait until we have space to put a new frame */
754 SDL_LockMutex(f->mutex);
755 while (f->size >= f->max_size &&
756 !f->pktq->abort_request) {
757 SDL_CondWait(f->cond, f->mutex);
758 }
759 SDL_UnlockMutex(f->mutex);
760
761 if (f->pktq->abort_request)
762 return NULL;
763
764 return &f->queue[f->windex];
765 }
766
767 static Frame *frame_queue_peek_readable(FrameQueue *f)
768 {
769 /* wait until we have a readable a new frame */
770 SDL_LockMutex(f->mutex);
771 while (f->size - f->rindex_shown <= 0 &&
772 !f->pktq->abort_request) {
773 SDL_CondWait(f->cond, f->mutex);
774 }
775 SDL_UnlockMutex(f->mutex);
776
777 if (f->pktq->abort_request)
778 return NULL;
779
780 return &f->queue[(f->rindex + f->rindex_shown) % f->max_size];
781 }
782
783 static void frame_queue_push(FrameQueue *f)
784 {
785 if (++f->windex == f->max_size)
786 f->windex = 0;
787 SDL_LockMutex(f->mutex);
788 f->size++;
789 SDL_CondSignal(f->cond);
790 SDL_UnlockMutex(f->mutex);
791 }
792
793 static void frame_queue_next(FrameQueue *f)
794 {
795 if (f->keep_last && !f->rindex_shown) {
796 f->rindex_shown = 1;
797 return;
798 }
799 frame_queue_unref_item(&f->queue[f->rindex]);
800 if (++f->rindex == f->max_size)
801 f->rindex = 0;
802 SDL_LockMutex(f->mutex);
803 f->size--;
804 SDL_CondSignal(f->cond);
805 SDL_UnlockMutex(f->mutex);
806 }
807
808 /* return the number of undisplayed frames in the queue */
809 static int frame_queue_nb_remaining(FrameQueue *f)
810 {
811 return f->size - f->rindex_shown;
812 }
813
814 /* return last shown position */
815 static int64_t frame_queue_last_pos(FrameQueue *f)
816 {
817 Frame *fp = &f->queue[f->rindex];
818 if (f->rindex_shown && fp->serial == f->pktq->serial)
819 return fp->pos;
820 else
821 return -1;
822 }
823
824 static void decoder_abort(Decoder *d, FrameQueue *fq)
825 {
826 packet_queue_abort(d->queue);
827 frame_queue_signal(fq);
828 SDL_WaitThread(d->decoder_tid, NULL);
829 d->decoder_tid = NULL;
830 packet_queue_flush(d->queue);
831 }
832
833 static inline void fill_rectangle(int x, int y, int w, int h)
834 {
835 SDL_Rect rect;
836 rect.x = x;
837 rect.y = y;
838 rect.w = w;
839 rect.h = h;
840 if (w && h)
841 SDL_RenderFillRect(renderer, &rect);
842 }
843
844 static int realloc_texture(SDL_Texture **texture, Uint32 new_format, int new_width, int new_height, SDL_BlendMode blendmode, int init_texture)
845 {
846 Uint32 format;
847 int access, w, h;
848 if (!*texture || SDL_QueryTexture(*texture, &format, &access, &w, &h) < 0 || new_width != w || new_height != h || new_format != format) {
849 void *pixels;
850 int pitch;
851 if (*texture)
852 SDL_DestroyTexture(*texture);
853 if (!(*texture = SDL_CreateTexture(renderer, new_format, SDL_TEXTUREACCESS_STREAMING, new_width, new_height)))
854 return -1;
855 if (SDL_SetTextureBlendMode(*texture, blendmode) < 0)
856 return -1;
857 if (init_texture) {
858 if (SDL_LockTexture(*texture, NULL, &pixels, &pitch) < 0)
859 return -1;
860 memset(pixels, 0, pitch * new_height);
861 SDL_UnlockTexture(*texture);
862 }
863 av_log(NULL, AV_LOG_VERBOSE, "Created %dx%d texture with %s.\n", new_width, new_height, SDL_GetPixelFormatName(new_format));
864 }
865 return 0;
866 }
867
868 static void calculate_display_rect(SDL_Rect *rect,
869 int scr_xleft, int scr_ytop, int scr_width, int scr_height,
870 int pic_width, int pic_height, AVRational pic_sar)
871 {
872 AVRational aspect_ratio = pic_sar;
873 int64_t width, height, x, y;
874
875 if (av_cmp_q(aspect_ratio, av_make_q(0, 1)) <= 0)
876 aspect_ratio = av_make_q(1, 1);
877
878 aspect_ratio = av_mul_q(aspect_ratio, av_make_q(pic_width, pic_height));
879
880 /* XXX: we suppose the screen has a 1.0 pixel ratio */
881 height = scr_height;
882 width = av_rescale(height, aspect_ratio.num, aspect_ratio.den) & ~1;
883 if (width > scr_width) {
884 width = scr_width;
885 height = av_rescale(width, aspect_ratio.den, aspect_ratio.num) & ~1;
886 }
887 x = (scr_width - width) / 2;
888 y = (scr_height - height) / 2;
889 rect->x = scr_xleft + x;
890 rect->y = scr_ytop + y;
891 rect->w = FFMAX((int)width, 1);
892 rect->h = FFMAX((int)height, 1);
893 }
894
895 static void get_sdl_pix_fmt_and_blendmode(int format, Uint32 *sdl_pix_fmt, SDL_BlendMode *sdl_blendmode)
896 {
897 int i;
898 *sdl_blendmode = SDL_BLENDMODE_NONE;
899 *sdl_pix_fmt = SDL_PIXELFORMAT_UNKNOWN;
900 if (format == AV_PIX_FMT_RGB32 ||
901 format == AV_PIX_FMT_RGB32_1 ||
902 format == AV_PIX_FMT_BGR32 ||
903 format == AV_PIX_FMT_BGR32_1)
904 *sdl_blendmode = SDL_BLENDMODE_BLEND;
905 for (i = 0; i < FF_ARRAY_ELEMS(sdl_texture_format_map); i++) {
906 if (format == sdl_texture_format_map[i].format) {
907 *sdl_pix_fmt = sdl_texture_format_map[i].texture_fmt;
908 return;
909 }
910 }
911 }
912
913 static int upload_texture(SDL_Texture **tex, AVFrame *frame)
914 {
915 int ret = 0;
916 Uint32 sdl_pix_fmt;
917 SDL_BlendMode sdl_blendmode;
918 get_sdl_pix_fmt_and_blendmode(frame->format, &sdl_pix_fmt, &sdl_blendmode);
919 if (realloc_texture(tex, sdl_pix_fmt == SDL_PIXELFORMAT_UNKNOWN ? SDL_PIXELFORMAT_ARGB8888 : sdl_pix_fmt, frame->width, frame->height, sdl_blendmode, 0) < 0)
920 return -1;
921 switch (sdl_pix_fmt) {
922 case SDL_PIXELFORMAT_IYUV:
923 if (frame->linesize[0] > 0 && frame->linesize[1] > 0 && frame->linesize[2] > 0) {
924 ret = SDL_UpdateYUVTexture(*tex, NULL, frame->data[0], frame->linesize[0],
925 frame->data[1], frame->linesize[1],
926 frame->data[2], frame->linesize[2]);
927 } else if (frame->linesize[0] < 0 && frame->linesize[1] < 0 && frame->linesize[2] < 0) {
928 ret = SDL_UpdateYUVTexture(*tex, NULL, frame->data[0] + frame->linesize[0] * (frame->height - 1), -frame->linesize[0],
929 frame->data[1] + frame->linesize[1] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[1],
930 frame->data[2] + frame->linesize[2] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[2]);
931 } else {
932 av_log(NULL, AV_LOG_ERROR, "Mixed negative and positive linesizes are not supported.\n");
933 return -1;
934 }
935 break;
936 default:
937 if (frame->linesize[0] < 0) {
938 ret = SDL_UpdateTexture(*tex, NULL, frame->data[0] + frame->linesize[0] * (frame->height - 1), -frame->linesize[0]);
939 } else {
940 ret = SDL_UpdateTexture(*tex, NULL, frame->data[0], frame->linesize[0]);
941 }
942 break;
943 }
944 return ret;
945 }
946
947 static enum AVColorSpace sdl_supported_color_spaces[] = {
948 AVCOL_SPC_BT709,
949 AVCOL_SPC_BT470BG,
950 AVCOL_SPC_SMPTE170M,
951 };
952
953 static enum AVAlphaMode sdl_supported_alpha_modes[] = {
954 AVALPHA_MODE_UNSPECIFIED,
955 AVALPHA_MODE_STRAIGHT,
956 };
957
958 static void set_sdl_yuv_conversion_mode(AVFrame *frame)
959 {
960 #if SDL_VERSION_ATLEAST(2,0,8)
961 SDL_YUV_CONVERSION_MODE mode = SDL_YUV_CONVERSION_AUTOMATIC;
962 if (frame && (frame->format == AV_PIX_FMT_YUV420P || frame->format == AV_PIX_FMT_YUYV422 || frame->format == AV_PIX_FMT_UYVY422)) {
963 if (frame->color_range == AVCOL_RANGE_JPEG)
964 mode = SDL_YUV_CONVERSION_JPEG;
965 else if (frame->colorspace == AVCOL_SPC_BT709)
966 mode = SDL_YUV_CONVERSION_BT709;
967 else if (frame->colorspace == AVCOL_SPC_BT470BG || frame->colorspace == AVCOL_SPC_SMPTE170M)
968 mode = SDL_YUV_CONVERSION_BT601;
969 }
970 SDL_SetYUVConversionMode(mode); /* FIXME: no support for linear transfer */
971 #endif
972 }
973
974 static void draw_video_background(VideoState *is)
975 {
976 const int tile_size = VIDEO_BACKGROUND_TILE_SIZE;
977 SDL_Rect *rect = &is->render_params.target_rect;
978 SDL_BlendMode blendMode;
979
980 if (!SDL_GetTextureBlendMode(is->vid_texture, &blendMode) && blendMode == SDL_BLENDMODE_BLEND) {
981 switch (is->render_params.video_background_type) {
982 case VIDEO_BACKGROUND_TILES:
983 SDL_SetRenderDrawColor(renderer, 237, 237, 237, 255);
984 fill_rectangle(rect->x, rect->y, rect->w, rect->h);
985 SDL_SetRenderDrawColor(renderer, 222, 222, 222, 255);
986 for (int x = 0; x < rect->w; x += tile_size * 2)
987 fill_rectangle(rect->x + x, rect->y, FFMIN(tile_size, rect->w - x), rect->h);
988 for (int y = 0; y < rect->h; y += tile_size * 2)
989 fill_rectangle(rect->x, rect->y + y, rect->w, FFMIN(tile_size, rect->h - y));
990 SDL_SetRenderDrawColor(renderer, 237, 237, 237, 255);
991 for (int y = 0; y < rect->h; y += tile_size * 2) {
992 int h = FFMIN(tile_size, rect->h - y);
993 for (int x = 0; x < rect->w; x += tile_size * 2)
994 fill_rectangle(x + rect->x, y + rect->y, FFMIN(tile_size, rect->w - x), h);
995 }
996 break;
997 case VIDEO_BACKGROUND_COLOR: {
998 const uint8_t *c = is->render_params.video_background_color;
999 SDL_SetRenderDrawColor(renderer, c[0], c[1], c[2], c[3]);
1000 fill_rectangle(rect->x, rect->y, rect->w, rect->h);
1001 break;
1002 }
1003 case VIDEO_BACKGROUND_NONE:
1004 SDL_SetTextureBlendMode(is->vid_texture, SDL_BLENDMODE_NONE);
1005 break;
1006 }
1007 }
1008 }
1009
1010 static void video_image_display(VideoState *is)
1011 {
1012 Frame *vp;
1013 Frame *sp = NULL;
1014 SDL_Rect *rect = &is->render_params.target_rect;
1015
1016 vp = frame_queue_peek_last(&is->pictq);
1017 calculate_display_rect(rect, is->xleft, is->ytop, is->width, is->height, vp->width, vp->height, vp->sar);
1018 if (vk_renderer) {
1019 vk_renderer_display(vk_renderer, vp->frame, &is->render_params);
1020 return;
1021 }
1022
1023 if (is->subtitle_st) {
1024 if (frame_queue_nb_remaining(&is->subpq) > 0) {
1025 sp = frame_queue_peek(&is->subpq);
1026
1027 if (vp->pts >= sp->pts + ((float) sp->sub.start_display_time / 1000)) {
1028 if (!sp->uploaded) {
1029 uint8_t* pixels[4];
1030 int pitch[4];
1031 int i;
1032 if (!sp->width || !sp->height) {
1033 sp->width = vp->width;
1034 sp->height = vp->height;
1035 }
1036 if (realloc_texture(&is->sub_texture, SDL_PIXELFORMAT_ARGB8888, sp->width, sp->height, SDL_BLENDMODE_BLEND, 1) < 0)
1037 return;
1038
1039 for (i = 0; i < sp->sub.num_rects; i++) {
1040 AVSubtitleRect *sub_rect = sp->sub.rects[i];
1041
1042 sub_rect->x = av_clip(sub_rect->x, 0, sp->width );
1043 sub_rect->y = av_clip(sub_rect->y, 0, sp->height);
1044 sub_rect->w = av_clip(sub_rect->w, 0, sp->width - sub_rect->x);
1045 sub_rect->h = av_clip(sub_rect->h, 0, sp->height - sub_rect->y);
1046
1047 is->sub_convert_ctx = sws_getCachedContext(is->sub_convert_ctx,
1048 sub_rect->w, sub_rect->h, AV_PIX_FMT_PAL8,
1049 sub_rect->w, sub_rect->h, AV_PIX_FMT_BGRA,
1050 0, NULL, NULL, NULL);
1051 if (!is->sub_convert_ctx) {
1052 av_log(NULL, AV_LOG_FATAL, "Cannot initialize the conversion context\n");
1053 return;
1054 }
1055 if (!SDL_LockTexture(is->sub_texture, (SDL_Rect *)sub_rect, (void **)pixels, pitch)) {
1056 sws_scale(is->sub_convert_ctx, (const uint8_t * const *)sub_rect->data, sub_rect->linesize,
1057 0, sub_rect->h, pixels, pitch);
1058 SDL_UnlockTexture(is->sub_texture);
1059 }
1060 }
1061 sp->uploaded = 1;
1062 }
1063 } else
1064 sp = NULL;
1065 }
1066 }
1067
1068 set_sdl_yuv_conversion_mode(vp->frame);
1069
1070 if (!vp->uploaded) {
1071 if (upload_texture(&is->vid_texture, vp->frame) < 0) {
1072 set_sdl_yuv_conversion_mode(NULL);
1073 return;
1074 }
1075 vp->uploaded = 1;
1076 vp->flip_v = vp->frame->linesize[0] < 0;
1077 }
1078
1079 draw_video_background(is);
1080 SDL_RenderCopyEx(renderer, is->vid_texture, NULL, rect, 0, NULL, vp->flip_v ? SDL_FLIP_VERTICAL : 0);
1081 set_sdl_yuv_conversion_mode(NULL);
1082 if (sp) {
1083 #if USE_ONEPASS_SUBTITLE_RENDER
1084 SDL_RenderCopy(renderer, is->sub_texture, NULL, rect);
1085 #else
1086 int i;
1087 double xratio = (double)rect->w / (double)sp->width;
1088 double yratio = (double)rect->h / (double)sp->height;
1089 for (i = 0; i < sp->sub.num_rects; i++) {
1090 SDL_Rect *sub_rect = (SDL_Rect*)sp->sub.rects[i];
1091 SDL_Rect target = {.x = rect.x + sub_rect->x * xratio,
1092 .y = rect.y + sub_rect->y * yratio,
1093 .w = sub_rect->w * xratio,
1094 .h = sub_rect->h * yratio};
1095 SDL_RenderCopy(renderer, is->sub_texture, sub_rect, &target);
1096 }
1097 #endif
1098 }
1099 }
1100
1101 static inline int compute_mod(int a, int b)
1102 {
1103 return a < 0 ? a%b + b : a%b;
1104 }
1105
1106 static void video_audio_display(VideoState *s)
1107 {
1108 int i, i_start, x, y1, y, ys, delay, n, nb_display_channels;
1109 int ch, channels, h, h2;
1110 int64_t time_diff;
1111 int rdft_bits, nb_freq;
1112
1113 for (rdft_bits = 1; (1 << rdft_bits) < 2 * s->height; rdft_bits++)
1114 ;
1115 nb_freq = 1 << (rdft_bits - 1);
1116
1117 /* compute display index : center on currently output samples */
1118 channels = s->audio_tgt.ch_layout.nb_channels;
1119 nb_display_channels = channels;
1120 if (!s->paused) {
1121 int data_used= s->show_mode == SHOW_MODE_WAVES ? s->width : (2*nb_freq);
1122 n = 2 * channels;
1123 delay = s->audio_write_buf_size;
1124 delay /= n;
1125
1126 /* to be more precise, we take into account the time spent since
1127 the last buffer computation */
1128 if (audio_callback_time) {
1129 time_diff = av_gettime_relative() - audio_callback_time;
1130 delay -= (time_diff * s->audio_tgt.freq) / 1000000;
1131 }
1132
1133 delay += 2 * data_used;
1134 if (delay < data_used)
1135 delay = data_used;
1136
1137 i_start= x = compute_mod(s->sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE);
1138 if (s->show_mode == SHOW_MODE_WAVES) {
1139 h = INT_MIN;
1140 for (i = 0; i < 1000; i += channels) {
1141 int idx = (SAMPLE_ARRAY_SIZE + x - i) % SAMPLE_ARRAY_SIZE;
1142 int a = s->sample_array[idx];
1143 int b = s->sample_array[(idx + 4 * channels) % SAMPLE_ARRAY_SIZE];
1144 int c = s->sample_array[(idx + 5 * channels) % SAMPLE_ARRAY_SIZE];
1145 int d = s->sample_array[(idx + 9 * channels) % SAMPLE_ARRAY_SIZE];
1146 int score = a - d;
1147 if (h < score && (b ^ c) < 0) {
1148 h = score;
1149 i_start = idx;
1150 }
1151 }
1152 }
1153
1154 s->last_i_start = i_start;
1155 } else {
1156 i_start = s->last_i_start;
1157 }
1158
1159 if (s->show_mode == SHOW_MODE_WAVES) {
1160 SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
1161
1162 /* total height for one channel */
1163 h = s->height / nb_display_channels;
1164 /* graph height / 2 */
1165 h2 = (h * 9) / 20;
1166 for (ch = 0; ch < nb_display_channels; ch++) {
1167 i = i_start + ch;
1168 y1 = s->ytop + ch * h + (h / 2); /* position of center line */
1169 for (x = 0; x < s->width; x++) {
1170 y = (s->sample_array[i] * h2) >> 15;
1171 if (y < 0) {
1172 y = -y;
1173 ys = y1 - y;
1174 } else {
1175 ys = y1;
1176 }
1177 fill_rectangle(s->xleft + x, ys, 1, y);
1178 i += channels;
1179 if (i >= SAMPLE_ARRAY_SIZE)
1180 i -= SAMPLE_ARRAY_SIZE;
1181 }
1182 }
1183
1184 SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
1185
1186 for (ch = 1; ch < nb_display_channels; ch++) {
1187 y = s->ytop + ch * h;
1188 fill_rectangle(s->xleft, y, s->width, 1);
1189 }
1190 } else {
1191 int err = 0;
1192 if (realloc_texture(&s->vis_texture, SDL_PIXELFORMAT_ARGB8888, s->width, s->height, SDL_BLENDMODE_NONE, 1) < 0)
1193 return;
1194
1195 if (s->xpos >= s->width)
1196 s->xpos = 0;
1197 nb_display_channels= FFMIN(nb_display_channels, 2);
1198 if (rdft_bits != s->rdft_bits) {
1199 const float rdft_scale = 1.0;
1200 av_tx_uninit(&s->rdft);
1201 av_freep(&s->real_data);
1202 av_freep(&s->rdft_data);
1203 s->rdft_bits = rdft_bits;
1204 s->real_data = av_malloc_array(nb_freq, 4 *sizeof(*s->real_data));
1205 s->rdft_data = av_malloc_array(nb_freq + 1, 2 *sizeof(*s->rdft_data));
1206 err = av_tx_init(&s->rdft, &s->rdft_fn, AV_TX_FLOAT_RDFT,
1207 0, 1 << rdft_bits, &rdft_scale, 0);
1208 }
1209 if (err < 0 || !s->rdft_data) {
1210 av_log(NULL, AV_LOG_ERROR, "Failed to allocate buffers for RDFT, switching to waves display\n");
1211 s->show_mode = SHOW_MODE_WAVES;
1212 } else {
1213 float *data_in[2];
1214 AVComplexFloat *data[2];
1215 SDL_Rect rect = {.x = s->xpos, .y = 0, .w = 1, .h = s->height};
1216 uint32_t *pixels;
1217 int pitch;
1218 for (ch = 0; ch < nb_display_channels; ch++) {
1219 data_in[ch] = s->real_data + 2 * nb_freq * ch;
1220 data[ch] = s->rdft_data + nb_freq * ch;
1221 i = i_start + ch;
1222 for (x = 0; x < 2 * nb_freq; x++) {
1223 double w = (x-nb_freq) * (1.0 / nb_freq);
1224 data_in[ch][x] = s->sample_array[i] * (1.0 - w * w);
1225 i += channels;
1226 if (i >= SAMPLE_ARRAY_SIZE)
1227 i -= SAMPLE_ARRAY_SIZE;
1228 }
1229 s->rdft_fn(s->rdft, data[ch], data_in[ch], sizeof(float));
1230 data[ch][0].im = data[ch][nb_freq].re;
1231 data[ch][nb_freq].re = 0;
1232 }
1233 /* Least efficient way to do this, we should of course
1234 * directly access it but it is more than fast enough. */
1235 if (!SDL_LockTexture(s->vis_texture, &rect, (void **)&pixels, &pitch)) {
1236 pitch >>= 2;
1237 pixels += pitch * s->height;
1238 for (y = 0; y < s->height; y++) {
1239 double w = 1 / sqrt(nb_freq);
1240 int a = sqrt(w * sqrt(data[0][y].re * data[0][y].re + data[0][y].im * data[0][y].im));
1241 int b = (nb_display_channels == 2 ) ? sqrt(w * hypot(data[1][y].re, data[1][y].im))
1242 : a;
1243 a = FFMIN(a, 255);
1244 b = FFMIN(b, 255);
1245 pixels -= pitch;
1246 *pixels = (a << 16) + (b << 8) + ((a+b) >> 1);
1247 }
1248 SDL_UnlockTexture(s->vis_texture);
1249 }
1250 SDL_RenderCopy(renderer, s->vis_texture, NULL, NULL);
1251 }
1252 if (!s->paused)
1253 s->xpos++;
1254 }
1255 }
1256
1257 static void stream_component_close(VideoState *is, int stream_index)
1258 {
1259 AVFormatContext *ic = is->ic;
1260 AVCodecParameters *codecpar;
1261
1262 if (stream_index < 0 || stream_index >= ic->nb_streams)
1263 return;
1264 codecpar = ic->streams[stream_index]->codecpar;
1265
1266 switch (codecpar->codec_type) {
1267 case AVMEDIA_TYPE_AUDIO:
1268 decoder_abort(&is->auddec, &is->sampq);
1269 SDL_CloseAudioDevice(audio_dev);
1270 decoder_destroy(&is->auddec);
1271 swr_free(&is->swr_ctx);
1272 av_freep(&is->audio_buf1);
1273 is->audio_buf1_size = 0;
1274 is->audio_buf = NULL;
1275
1276 if (is->rdft) {
1277 av_tx_uninit(&is->rdft);
1278 av_freep(&is->real_data);
1279 av_freep(&is->rdft_data);
1280 is->rdft = NULL;
1281 is->rdft_bits = 0;
1282 }
1283 break;
1284 case AVMEDIA_TYPE_VIDEO:
1285 decoder_abort(&is->viddec, &is->pictq);
1286 decoder_destroy(&is->viddec);
1287 break;
1288 case AVMEDIA_TYPE_SUBTITLE:
1289 decoder_abort(&is->subdec, &is->subpq);
1290 decoder_destroy(&is->subdec);
1291 break;
1292 default:
1293 break;
1294 }
1295
1296 ic->streams[stream_index]->discard = AVDISCARD_ALL;
1297 switch (codecpar->codec_type) {
1298 case AVMEDIA_TYPE_AUDIO:
1299 is->audio_st = NULL;
1300 is->audio_stream = -1;
1301 break;
1302 case AVMEDIA_TYPE_VIDEO:
1303 is->video_st = NULL;
1304 is->video_stream = -1;
1305 break;
1306 case AVMEDIA_TYPE_SUBTITLE:
1307 is->subtitle_st = NULL;
1308 is->subtitle_stream = -1;
1309 break;
1310 default:
1311 break;
1312 }
1313 }
1314
1315 static void stream_close(VideoState *is)
1316 {
1317 /* XXX: use a special url_shutdown call to abort parse cleanly */
1318 is->abort_request = 1;
1319 SDL_WaitThread(is->read_tid, NULL);
1320
1321 /* close each stream */
1322 if (is->audio_stream >= 0)
1323 stream_component_close(is, is->audio_stream);
1324 if (is->video_stream >= 0)
1325 stream_component_close(is, is->video_stream);
1326 if (is->subtitle_stream >= 0)
1327 stream_component_close(is, is->subtitle_stream);
1328
1329 avformat_close_input(&is->ic);
1330
1331 packet_queue_destroy(&is->videoq);
1332 packet_queue_destroy(&is->audioq);
1333 packet_queue_destroy(&is->subtitleq);
1334
1335 /* free all pictures */
1336 frame_queue_destroy(&is->pictq);
1337 frame_queue_destroy(&is->sampq);
1338 frame_queue_destroy(&is->subpq);
1339 SDL_DestroyCond(is->continue_read_thread);
1340 sws_freeContext(is->sub_convert_ctx);
1341 av_free(is->filename);
1342 if (is->vis_texture)
1343 SDL_DestroyTexture(is->vis_texture);
1344 if (is->vid_texture)
1345 SDL_DestroyTexture(is->vid_texture);
1346 if (is->sub_texture)
1347 SDL_DestroyTexture(is->sub_texture);
1348 av_free(is);
1349 }
1350
1351 static void do_exit(VideoState *is)
1352 {
1353 if (is) {
1354 stream_close(is);
1355 }
1356 if (renderer)
1357 SDL_DestroyRenderer(renderer);
1358 if (vk_renderer)
1359 vk_renderer_destroy(vk_renderer);
1360 if (window)
1361 SDL_DestroyWindow(window);
1362 uninit_opts();
1363 for (int i = 0; i < nb_vfilters; i++)
1364 av_freep(&vfilters_list[i]);
1365 av_freep(&vfilters_list);
1366 av_freep(&video_codec_name);
1367 av_freep(&audio_codec_name);
1368 av_freep(&subtitle_codec_name);
1369 av_freep(&input_filename);
1370 avformat_network_deinit();
1371 if (show_status)
1372 printf("\n");
1373 SDL_Quit();
1374 av_log(NULL, AV_LOG_QUIET, "%s", "");
1375 exit(exit_status);
1376 }
1377
1378 static void sigterm_handler(int sig)
1379 {
1380 received_sigterm = sig;
1381 if (++received_nb_signals > 3)
1382 exit(123);
1383 }
1384
1385 static void set_default_window_size(int width, int height, AVRational sar)
1386 {
1387 SDL_Rect rect;
1388 int max_width = screen_width ? screen_width : INT_MAX;
1389 int max_height = screen_height ? screen_height : INT_MAX;
1390 if (max_width == INT_MAX && max_height == INT_MAX)
1391 max_height = height;
1392 calculate_display_rect(&rect, 0, 0, max_width, max_height, width, height, sar);
1393 default_width = rect.w;
1394 default_height = rect.h;
1395 }
1396
1397 static int video_open(VideoState *is)
1398 {
1399 int w,h;
1400
1401 w = screen_width ? screen_width : default_width;
1402 h = screen_height ? screen_height : default_height;
1403
1404 if (!window_title)
1405 window_title = input_filename;
1406 SDL_SetWindowTitle(window, window_title);
1407
1408 SDL_SetWindowSize(window, w, h);
1409 SDL_SetWindowPosition(window, screen_left, screen_top);
1410 if (is_full_screen)
1411 SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
1412 SDL_ShowWindow(window);
1413
1414 is->width = w;
1415 is->height = h;
1416
1417 return 0;
1418 }
1419
1420 /* display the current picture, if any */
1421 static void video_display(VideoState *is)
1422 {
1423 if (!is->width)
1424 video_open(is);
1425
1426 SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
1427 SDL_RenderClear(renderer);
1428 if (is->audio_st && is->show_mode != SHOW_MODE_VIDEO)
1429 video_audio_display(is);
1430 else if (is->video_st)
1431 video_image_display(is);
1432 SDL_RenderPresent(renderer);
1433 }
1434
1435 static double get_clock(Clock *c)
1436 {
1437 if (*c->queue_serial != c->serial)
1438 return NAN;
1439 if (c->paused) {
1440 return c->pts;
1441 } else {
1442 double time = av_gettime_relative() / 1000000.0;
1443 return c->pts_drift + time - (time - c->last_updated) * (1.0 - c->speed);
1444 }
1445 }
1446
1447 static void set_clock_at(Clock *c, double pts, int serial, double time)
1448 {
1449 c->pts = pts;
1450 c->last_updated = time;
1451 c->pts_drift = c->pts - time;
1452 c->serial = serial;
1453 }
1454
1455 static void set_clock(Clock *c, double pts, int serial)
1456 {
1457 double time = av_gettime_relative() / 1000000.0;
1458 set_clock_at(c, pts, serial, time);
1459 }
1460
1461 static void set_clock_speed(Clock *c, double speed)
1462 {
1463 set_clock(c, get_clock(c), c->serial);
1464 c->speed = speed;
1465 }
1466
1467 static void init_clock(Clock *c, int *queue_serial)
1468 {
1469 c->speed = 1.0;
1470 c->paused = 0;
1471 c->queue_serial = queue_serial;
1472 set_clock(c, NAN, -1);
1473 }
1474
1475 static void sync_clock_to_slave(Clock *c, Clock *slave)
1476 {
1477 double clock = get_clock(c);
1478 double slave_clock = get_clock(slave);
1479 if (!isnan(slave_clock) && (isnan(clock) || fabs(clock - slave_clock) > AV_NOSYNC_THRESHOLD))
1480 set_clock(c, slave_clock, slave->serial);
1481 }
1482
1483 static int get_master_sync_type(VideoState *is) {
1484 if (is->av_sync_type == AV_SYNC_VIDEO_MASTER) {
1485 if (is->video_st)
1486 return AV_SYNC_VIDEO_MASTER;
1487 else
1488 return AV_SYNC_AUDIO_MASTER;
1489 } else if (is->av_sync_type == AV_SYNC_AUDIO_MASTER) {
1490 if (is->audio_st)
1491 return AV_SYNC_AUDIO_MASTER;
1492 else
1493 return AV_SYNC_EXTERNAL_CLOCK;
1494 } else {
1495 return AV_SYNC_EXTERNAL_CLOCK;
1496 }
1497 }
1498
1499 /* get the current master clock value */
1500 static double get_master_clock(VideoState *is)
1501 {
1502 double val;
1503
1504 switch (get_master_sync_type(is)) {
1505 case AV_SYNC_VIDEO_MASTER:
1506 val = get_clock(&is->vidclk);
1507 break;
1508 case AV_SYNC_AUDIO_MASTER:
1509 val = get_clock(&is->audclk);
1510 break;
1511 default:
1512 val = get_clock(&is->extclk);
1513 break;
1514 }
1515 return val;
1516 }
1517
1518 static void check_external_clock_speed(VideoState *is) {
1519 if (is->video_stream >= 0 && is->videoq.nb_packets <= EXTERNAL_CLOCK_MIN_FRAMES ||
1520 is->audio_stream >= 0 && is->audioq.nb_packets <= EXTERNAL_CLOCK_MIN_FRAMES) {
1521 set_clock_speed(&is->extclk, FFMAX(EXTERNAL_CLOCK_SPEED_MIN, is->extclk.speed - EXTERNAL_CLOCK_SPEED_STEP));
1522 } else if ((is->video_stream < 0 || is->videoq.nb_packets > EXTERNAL_CLOCK_MAX_FRAMES) &&
1523 (is->audio_stream < 0 || is->audioq.nb_packets > EXTERNAL_CLOCK_MAX_FRAMES)) {
1524 set_clock_speed(&is->extclk, FFMIN(EXTERNAL_CLOCK_SPEED_MAX, is->extclk.speed + EXTERNAL_CLOCK_SPEED_STEP));
1525 } else {
1526 double speed = is->extclk.speed;
1527 if (speed != 1.0)
1528 set_clock_speed(&is->extclk, speed + EXTERNAL_CLOCK_SPEED_STEP * (1.0 - speed) / fabs(1.0 - speed));
1529 }
1530 }
1531
1532 /* seek in the stream */
1533 static void stream_seek(VideoState *is, int64_t pos, int64_t rel, int by_bytes)
1534 {
1535 if (!is->seek_req) {
1536 is->seek_pos = pos;
1537 is->seek_rel = rel;
1538 is->seek_flags &= ~AVSEEK_FLAG_BYTE;
1539 if (by_bytes)
1540 is->seek_flags |= AVSEEK_FLAG_BYTE;
1541 is->seek_req = 1;
1542 SDL_CondSignal(is->continue_read_thread);
1543 }
1544 }
1545
1546 /* pause or resume the video */
1547 static void stream_toggle_pause(VideoState *is)
1548 {
1549 if (is->paused) {
1550 is->frame_timer += av_gettime_relative() / 1000000.0 - is->vidclk.last_updated;
1551 if (is->read_pause_return != AVERROR(ENOSYS)) {
1552 is->vidclk.paused = 0;
1553 }
1554 set_clock(&is->vidclk, get_clock(&is->vidclk), is->vidclk.serial);
1555 }
1556 set_clock(&is->extclk, get_clock(&is->extclk), is->extclk.serial);
1557 is->paused = is->audclk.paused = is->vidclk.paused = is->extclk.paused = !is->paused;
1558 }
1559
1560 static void toggle_pause(VideoState *is)
1561 {
1562 stream_toggle_pause(is);
1563 is->step = 0;
1564 }
1565
1566 static void toggle_mute(VideoState *is)
1567 {
1568 is->muted = !is->muted;
1569 }
1570
1571 static void update_volume(VideoState *is, int sign, double step)
1572 {
1573 double volume_level = is->audio_volume ? (20 * log(is->audio_volume / (double)SDL_MIX_MAXVOLUME) / log(10)) : -1000.0;
1574 int new_volume = lrint(SDL_MIX_MAXVOLUME * pow(10.0, (volume_level + sign * step) / 20.0));
1575 is->audio_volume = av_clip(is->audio_volume == new_volume ? (is->audio_volume + sign) : new_volume, 0, SDL_MIX_MAXVOLUME);
1576 }
1577
1578 static void step_to_next_frame(VideoState *is)
1579 {
1580 /* if the stream is paused unpause it, then step */
1581 if (is->paused)
1582 stream_toggle_pause(is);
1583 is->step = 1;
1584 }
1585
1586 static double compute_target_delay(double delay, VideoState *is)
1587 {
1588 double sync_threshold, diff = 0;
1589
1590 /* update delay to follow master synchronisation source */
1591 if (get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER) {
1592 /* if video is slave, we try to correct big delays by
1593 duplicating or deleting a frame */
1594 diff = get_clock(&is->vidclk) - get_master_clock(is);
1595
1596 /* skip or repeat frame. We take into account the
1597 delay to compute the threshold. I still don't know
1598 if it is the best guess */
1599 sync_threshold = FFMAX(AV_SYNC_THRESHOLD_MIN, FFMIN(AV_SYNC_THRESHOLD_MAX, delay));
1600 if (!isnan(diff) && fabs(diff) < is->max_frame_duration) {
1601 if (diff <= -sync_threshold)
1602 delay = FFMAX(0, delay + diff);
1603 else if (diff >= sync_threshold && delay > AV_SYNC_FRAMEDUP_THRESHOLD)
1604 delay = delay + diff;
1605 else if (diff >= sync_threshold)
1606 delay = 2 * delay;
1607 }
1608 }
1609
1610 av_log(NULL, AV_LOG_TRACE, "video: delay=%0.3f A-V=%f\n",
1611 delay, -diff);
1612
1613 return delay;
1614 }
1615
1616 static double vp_duration(VideoState *is, Frame *vp, Frame *nextvp) {
1617 if (vp->serial == nextvp->serial) {
1618 double duration = nextvp->pts - vp->pts;
1619 if (isnan(duration) || duration <= 0 || duration > is->max_frame_duration)
1620 return vp->duration;
1621 else
1622 return duration;
1623 } else {
1624 return 0.0;
1625 }
1626 }
1627
1628 static void update_video_pts(VideoState *is, double pts, int serial)
1629 {
1630 /* update current video pts */
1631 set_clock(&is->vidclk, pts, serial);
1632 sync_clock_to_slave(&is->extclk, &is->vidclk);
1633 }
1634
1635 /* called to display each frame */
1636 static void video_refresh(void *opaque, double *remaining_time)
1637 {
1638 VideoState *is = opaque;
1639 double time;
1640
1641 Frame *sp, *sp2;
1642
1643 if (!is->paused && get_master_sync_type(is) == AV_SYNC_EXTERNAL_CLOCK && is->realtime)
1644 check_external_clock_speed(is);
1645
1646 if (!display_disable && is->show_mode != SHOW_MODE_VIDEO && is->audio_st) {
1647 time = av_gettime_relative() / 1000000.0;
1648 if (is->force_refresh || is->last_vis_time + rdftspeed < time) {
1649 video_display(is);
1650 is->last_vis_time = time;
1651 }
1652 *remaining_time = FFMIN(*remaining_time, is->last_vis_time + rdftspeed - time);
1653 }
1654
1655 if (is->video_st) {
1656 retry:
1657 if (frame_queue_nb_remaining(&is->pictq) == 0) {
1658 // nothing to do, no picture to display in the queue
1659 } else {
1660 double last_duration, duration, delay;
1661 Frame *vp, *lastvp;
1662
1663 /* dequeue the picture */
1664 lastvp = frame_queue_peek_last(&is->pictq);
1665 vp = frame_queue_peek(&is->pictq);
1666
1667 if (vp->serial != is->videoq.serial) {
1668 frame_queue_next(&is->pictq);
1669 goto retry;
1670 }
1671
1672 if (lastvp->serial != vp->serial)
1673 is->frame_timer = av_gettime_relative() / 1000000.0;
1674
1675 if (is->paused)
1676 goto display;
1677
1678 /* compute nominal last_duration */
1679 last_duration = vp_duration(is, lastvp, vp);
1680 delay = compute_target_delay(last_duration, is);
1681
1682 time= av_gettime_relative()/1000000.0;
1683 if (time < is->frame_timer + delay) {
1684 *remaining_time = FFMIN(is->frame_timer + delay - time, *remaining_time);
1685 goto display;
1686 }
1687
1688 is->frame_timer += delay;
1689 if (delay > 0 && time - is->frame_timer > AV_SYNC_THRESHOLD_MAX)
1690 is->frame_timer = time;
1691
1692 SDL_LockMutex(is->pictq.mutex);
1693 if (!isnan(vp->pts))
1694 update_video_pts(is, vp->pts, vp->serial);
1695 SDL_UnlockMutex(is->pictq.mutex);
1696
1697 if (frame_queue_nb_remaining(&is->pictq) > 1) {
1698 Frame *nextvp = frame_queue_peek_next(&is->pictq);
1699 duration = vp_duration(is, vp, nextvp);
1700 if(!is->step && (framedrop>0 || (framedrop && get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER)) && time > is->frame_timer + duration){
1701 is->frame_drops_late++;
1702 frame_queue_next(&is->pictq);
1703 goto retry;
1704 }
1705 }
1706
1707 if (is->subtitle_st) {
1708 while (frame_queue_nb_remaining(&is->subpq) > 0) {
1709 sp = frame_queue_peek(&is->subpq);
1710
1711 if (frame_queue_nb_remaining(&is->subpq) > 1)
1712 sp2 = frame_queue_peek_next(&is->subpq);
1713 else
1714 sp2 = NULL;
1715
1716 if (sp->serial != is->subtitleq.serial
1717 || (is->vidclk.pts > (sp->pts + ((float) sp->sub.end_display_time / 1000)))
1718 || (sp2 && is->vidclk.pts > (sp2->pts + ((float) sp2->sub.start_display_time / 1000))))
1719 {
1720 if (sp->uploaded) {
1721 int i;
1722 for (i = 0; i < sp->sub.num_rects; i++) {
1723 AVSubtitleRect *sub_rect = sp->sub.rects[i];
1724 uint8_t *pixels;
1725 int pitch, j;
1726
1727 if (!SDL_LockTexture(is->sub_texture, (SDL_Rect *)sub_rect, (void **)&pixels, &pitch)) {
1728 for (j = 0; j < sub_rect->h; j++, pixels += pitch)
1729 memset(pixels, 0, sub_rect->w << 2);
1730 SDL_UnlockTexture(is->sub_texture);
1731 }
1732 }
1733 }
1734 frame_queue_next(&is->subpq);
1735 } else {
1736 break;
1737 }
1738 }
1739 }
1740
1741 frame_queue_next(&is->pictq);
1742 is->force_refresh = 1;
1743
1744 if (is->step && !is->paused)
1745 stream_toggle_pause(is);
1746 }
1747 display:
1748 /* display picture */
1749 if (!display_disable && is->force_refresh && is->show_mode == SHOW_MODE_VIDEO && is->pictq.rindex_shown)
1750 video_display(is);
1751 }
1752 is->force_refresh = 0;
1753 if (show_status) {
1754 AVBPrint buf;
1755 static int64_t last_time;
1756 int64_t cur_time;
1757 int aqsize, vqsize, sqsize;
1758 double av_diff;
1759
1760 cur_time = av_gettime_relative();
1761 if (!last_time || (cur_time - last_time) >= 30000) {
1762 aqsize = 0;
1763 vqsize = 0;
1764 sqsize = 0;
1765 if (is->audio_st)
1766 aqsize = is->audioq.size;
1767 if (is->video_st)
1768 vqsize = is->videoq.size;
1769 if (is->subtitle_st)
1770 sqsize = is->subtitleq.size;
1771 av_diff = 0;
1772 if (is->audio_st && is->video_st)
1773 av_diff = get_clock(&is->audclk) - get_clock(&is->vidclk);
1774 else if (is->video_st)
1775 av_diff = get_master_clock(is) - get_clock(&is->vidclk);
1776 else if (is->audio_st)
1777 av_diff = get_master_clock(is) - get_clock(&is->audclk);
1778
1779 av_bprint_init(&buf, 0, AV_BPRINT_SIZE_AUTOMATIC);
1780 av_bprintf(&buf,
1781 "%7.2f %s:%7.3f fd=%4d aq=%5dKB vq=%5dKB sq=%5dB \r",
1782 get_master_clock(is),
1783 (is->audio_st && is->video_st) ? "A-V" : (is->video_st ? "M-V" : (is->audio_st ? "M-A" : " ")),
1784 av_diff,
1785 is->frame_drops_early + is->frame_drops_late,
1786 aqsize / 1024,
1787 vqsize / 1024,
1788 sqsize);
1789
1790 if (show_status == 1 && AV_LOG_INFO > av_log_get_level())
1791 fprintf(stderr, "%s", buf.str);
1792 else
1793 av_log(NULL, AV_LOG_INFO, "%s", buf.str);
1794
1795 fflush(stderr);
1796 av_bprint_finalize(&buf, NULL);
1797
1798 last_time = cur_time;
1799 }
1800 }
1801 }
1802
1803 static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, double duration, int64_t pos, int serial)
1804 {
1805 Frame *vp;
1806
1807 #if defined(DEBUG_SYNC)
1808 printf("frame_type=%c pts=%0.3f\n",
1809 av_get_picture_type_char(src_frame->pict_type), pts);
1810 #endif
1811
1812 if (!(vp = frame_queue_peek_writable(&is->pictq)))
1813 return -1;
1814
1815 vp->sar = src_frame->sample_aspect_ratio;
1816 vp->uploaded = 0;
1817
1818 vp->width = src_frame->width;
1819 vp->height = src_frame->height;
1820 vp->format = src_frame->format;
1821
1822 vp->pts = pts;
1823 vp->duration = duration;
1824 vp->pos = pos;
1825 vp->serial = serial;
1826
1827 set_default_window_size(vp->width, vp->height, vp->sar);
1828
1829 av_frame_move_ref(vp->frame, src_frame);
1830 frame_queue_push(&is->pictq);
1831 return 0;
1832 }
1833
1834 static int get_video_frame(VideoState *is, AVFrame *frame)
1835 {
1836 int got_picture;
1837
1838 if ((got_picture = decoder_decode_frame(&is->viddec, frame, NULL)) < 0)
1839 return -1;
1840
1841 if (got_picture) {
1842 double dpts = NAN;
1843
1844 if (frame->pts != AV_NOPTS_VALUE)
1845 dpts = av_q2d(is->video_st->time_base) * frame->pts;
1846
1847 frame->sample_aspect_ratio = av_guess_sample_aspect_ratio(is->ic, is->video_st, frame);
1848
1849 if (framedrop>0 || (framedrop && get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER)) {
1850 if (frame->pts != AV_NOPTS_VALUE) {
1851 double diff = dpts - get_master_clock(is);
1852 if (!isnan(diff) && fabs(diff) < AV_NOSYNC_THRESHOLD &&
1853 diff - is->frame_last_filter_delay < 0 &&
1854 is->viddec.pkt_serial == is->vidclk.serial &&
1855 is->videoq.nb_packets) {
1856 is->frame_drops_early++;
1857 av_frame_unref(frame);
1858 got_picture = 0;
1859 }
1860 }
1861 }
1862 }
1863
1864 return got_picture;
1865 }
1866
1867 static int configure_filtergraph(AVFilterGraph *graph, const char *filtergraph,
1868 AVFilterContext *source_ctx, AVFilterContext *sink_ctx)
1869 {
1870 int ret, i;
1871 int nb_filters = graph->nb_filters;
1872 AVFilterInOut *outputs = NULL, *inputs = NULL;
1873
1874 if (filtergraph) {
1875 outputs = avfilter_inout_alloc();
1876 inputs = avfilter_inout_alloc();
1877 if (!outputs || !inputs) {
1878 ret = AVERROR(ENOMEM);
1879 goto fail;
1880 }
1881
1882 outputs->name = av_strdup("in");
1883 outputs->filter_ctx = source_ctx;
1884 outputs->pad_idx = 0;
1885 outputs->next = NULL;
1886
1887 inputs->name = av_strdup("out");
1888 inputs->filter_ctx = sink_ctx;
1889 inputs->pad_idx = 0;
1890 inputs->next = NULL;
1891
1892 if ((ret = avfilter_graph_parse_ptr(graph, filtergraph, &inputs, &outputs, NULL)) < 0)
1893 goto fail;
1894 } else {
1895 if ((ret = avfilter_link(source_ctx, 0, sink_ctx, 0)) < 0)
1896 goto fail;
1897 }
1898
1899 /* Reorder the filters to ensure that inputs of the custom filters are merged first */
1900 for (i = 0; i < graph->nb_filters - nb_filters; i++)
1901 FFSWAP(AVFilterContext*, graph->filters[i], graph->filters[i + nb_filters]);
1902
1903 ret = avfilter_graph_config(graph, NULL);
1904 fail:
1905 avfilter_inout_free(&outputs);
1906 avfilter_inout_free(&inputs);
1907 return ret;
1908 }
1909
1910 static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const char *vfilters, AVFrame *frame)
1911 {
1912 enum AVPixelFormat pix_fmts[FF_ARRAY_ELEMS(sdl_texture_format_map)];
1913 char sws_flags_str[512] = "";
1914 int ret;
1915 AVFilterContext *filt_src = NULL, *filt_out = NULL, *last_filter = NULL;
1916 AVCodecParameters *codecpar = is->video_st->codecpar;
1917 AVRational fr = av_guess_frame_rate(is->ic, is->video_st, NULL);
1918 const AVDictionaryEntry *e = NULL;
1919 int nb_pix_fmts = 0;
1920 int i, j;
1921 AVBufferSrcParameters *par = av_buffersrc_parameters_alloc();
1922
1923 if (!par)
1924 return AVERROR(ENOMEM);
1925
1926 for (i = 0; i < renderer_info.num_texture_formats; i++) {
1927 for (j = 0; j < FF_ARRAY_ELEMS(sdl_texture_format_map); j++) {
1928 if (renderer_info.texture_formats[i] == sdl_texture_format_map[j].texture_fmt) {
1929 pix_fmts[nb_pix_fmts++] = sdl_texture_format_map[j].format;
1930 break;
1931 }
1932 }
1933 }
1934
1935 while ((e = av_dict_iterate(sws_dict, e))) {
1936 if (!strcmp(e->key, "sws_flags")) {
1937 av_strlcatf(sws_flags_str, sizeof(sws_flags_str), "%s=%s:", "flags", e->value);
1938 } else
1939 av_strlcatf(sws_flags_str, sizeof(sws_flags_str), "%s=%s:", e->key, e->value);
1940 }
1941 if (strlen(sws_flags_str))
1942 sws_flags_str[strlen(sws_flags_str)-1] = '\0';
1943
1944 graph->scale_sws_opts = av_strdup(sws_flags_str);
1945
1946
1947 filt_src = avfilter_graph_alloc_filter(graph, avfilter_get_by_name("buffer"),
1948 "ffplay_buffer");
1949 if (!filt_src) {
1950 ret = AVERROR(ENOMEM);
1951 goto fail;
1952 }
1953
1954 par->format = frame->format;
1955 par->time_base = is->video_st->time_base;
1956 par->width = frame->width;
1957 par->height = frame->height;
1958 par->sample_aspect_ratio = codecpar->sample_aspect_ratio;
1959 par->color_space = frame->colorspace;
1960 par->color_range = frame->color_range;
1961 par->alpha_mode = frame->alpha_mode;
1962 par->frame_rate = fr;
1963 par->hw_frames_ctx = frame->hw_frames_ctx;
1964 ret = av_buffersrc_parameters_set(filt_src, par);
1965 if (ret < 0)
1966 goto fail;
1967
1968 ret = avfilter_init_dict(filt_src, NULL);
1969 if (ret < 0)
1970 goto fail;
1971
1972 filt_out = avfilter_graph_alloc_filter(graph, avfilter_get_by_name("buffersink"),
1973 "ffplay_buffersink");
1974 if (!filt_out) {
1975 ret = AVERROR(ENOMEM);
1976 goto fail;
1977 }
1978
1979 if ((ret = av_opt_set_array(filt_out, "pixel_formats", AV_OPT_SEARCH_CHILDREN,
1980 0, nb_pix_fmts, AV_OPT_TYPE_PIXEL_FMT, pix_fmts)) < 0)
1981 goto fail;
1982 if (!vk_renderer &&
1983 (ret = av_opt_set_array(filt_out, "colorspaces", AV_OPT_SEARCH_CHILDREN,
1984 0, FF_ARRAY_ELEMS(sdl_supported_color_spaces),
1985 AV_OPT_TYPE_INT, sdl_supported_color_spaces)) < 0)
1986 goto fail;
1987
1988 if ((ret = av_opt_set_array(filt_out, "alphamodes", AV_OPT_SEARCH_CHILDREN,
1989 0, FF_ARRAY_ELEMS(sdl_supported_alpha_modes),
1990 AV_OPT_TYPE_INT, sdl_supported_alpha_modes)) < 0)
1991 goto fail;
1992
1993 ret = avfilter_init_dict(filt_out, NULL);
1994 if (ret < 0)
1995 goto fail;
1996
1997 last_filter = filt_out;
1998
1999 /* Note: this macro adds a filter before the lastly added filter, so the
2000 * processing order of the filters is in reverse */
2001 #define INSERT_FILT(name, arg) do { \
2002 AVFilterContext *filt_ctx; \
2003 \
2004 ret = avfilter_graph_create_filter(&filt_ctx, \
2005 avfilter_get_by_name(name), \
2006 "ffplay_" name, arg, NULL, graph); \
2007 if (ret < 0) \
2008 goto fail; \
2009 \
2010 ret = avfilter_link(filt_ctx, 0, last_filter, 0); \
2011 if (ret < 0) \
2012 goto fail; \
2013 \
2014 last_filter = filt_ctx; \
2015 } while (0)
2016
2017 if (autorotate) {
2018 double theta = 0.0;
2019 int32_t *displaymatrix = NULL;
2020 AVFrameSideData *sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX);
2021 if (sd)
2022 displaymatrix = (int32_t *)sd->data;
2023 if (!displaymatrix) {
2024 const AVPacketSideData *psd = av_packet_side_data_get(is->video_st->codecpar->coded_side_data,
2025 is->video_st->codecpar->nb_coded_side_data,
2026 AV_PKT_DATA_DISPLAYMATRIX);
2027 if (psd)
2028 displaymatrix = (int32_t *)psd->data;
2029 }
2030 theta = get_rotation(displaymatrix);
2031
2032 if (fabs(theta - 90) < 1.0) {
2033 INSERT_FILT("transpose", displaymatrix[3] > 0 ? "cclock_flip" : "clock");
2034 } else if (fabs(theta - 180) < 1.0) {
2035 if (displaymatrix[0] < 0)
2036 INSERT_FILT("hflip", NULL);
2037 if (displaymatrix[4] < 0)
2038 INSERT_FILT("vflip", NULL);
2039 } else if (fabs(theta - 270) < 1.0) {
2040 INSERT_FILT("transpose", displaymatrix[3] < 0 ? "clock_flip" : "cclock");
2041 } else if (fabs(theta) > 1.0) {
2042 char rotate_buf[64];
2043 snprintf(rotate_buf, sizeof(rotate_buf), "%f*PI/180", theta);
2044 INSERT_FILT("rotate", rotate_buf);
2045 } else {
2046 if (displaymatrix && displaymatrix[4] < 0)
2047 INSERT_FILT("vflip", NULL);
2048 }
2049 }
2050
2051 if ((ret = configure_filtergraph(graph, vfilters, filt_src, last_filter)) < 0)
2052 goto fail;
2053
2054 is->in_video_filter = filt_src;
2055 is->out_video_filter = filt_out;
2056
2057 fail:
2058 av_freep(&par);
2059 return ret;
2060 }
2061
2062 static int configure_audio_filters(VideoState *is, const char *afilters, int force_output_format)
2063 {
2064 AVFilterContext *filt_asrc = NULL, *filt_asink = NULL;
2065 char aresample_swr_opts[512] = "";
2066 const AVDictionaryEntry *e = NULL;
2067 AVBPrint bp;
2068 char asrc_args[256];
2069 int ret;
2070
2071 avfilter_graph_free(&is->agraph);
2072 if (!(is->agraph = avfilter_graph_alloc()))
2073 return AVERROR(ENOMEM);
2074 is->agraph->nb_threads = filter_nbthreads;
2075
2076 av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
2077
2078 while ((e = av_dict_iterate(swr_opts, e)))
2079 av_strlcatf(aresample_swr_opts, sizeof(aresample_swr_opts), "%s=%s:", e->key, e->value);
2080 if (strlen(aresample_swr_opts))
2081 aresample_swr_opts[strlen(aresample_swr_opts)-1] = '\0';
2082 av_opt_set(is->agraph, "aresample_swr_opts", aresample_swr_opts, 0);
2083
2084 av_channel_layout_describe_bprint(&is->audio_filter_src.ch_layout, &bp);
2085
2086 ret = snprintf(asrc_args, sizeof(asrc_args),
2087 "sample_rate=%d:sample_fmt=%s:time_base=%d/%d:channel_layout=%s",
2088 is->audio_filter_src.freq, av_get_sample_fmt_name(is->audio_filter_src.fmt),
2089 1, is->audio_filter_src.freq, bp.str);
2090
2091 ret = avfilter_graph_create_filter(&filt_asrc,
2092 avfilter_get_by_name("abuffer"), "ffplay_abuffer",
2093 asrc_args, NULL, is->agraph);
2094 if (ret < 0)
2095 goto end;
2096
2097 filt_asink = avfilter_graph_alloc_filter(is->agraph, avfilter_get_by_name("abuffersink"),
2098 "ffplay_abuffersink");
2099 if (!filt_asink) {
2100 ret = AVERROR(ENOMEM);
2101 goto end;
2102 }
2103
2104 if ((ret = av_opt_set(filt_asink, "sample_formats", "s16", AV_OPT_SEARCH_CHILDREN)) < 0)
2105 goto end;
2106
2107 if (force_output_format) {
2108 if ((ret = av_opt_set_array(filt_asink, "channel_layouts", AV_OPT_SEARCH_CHILDREN,
2109 0, 1, AV_OPT_TYPE_CHLAYOUT, &is->audio_tgt.ch_layout)) < 0)
2110 goto end;
2111 if ((ret = av_opt_set_array(filt_asink, "samplerates", AV_OPT_SEARCH_CHILDREN,
2112 0, 1, AV_OPT_TYPE_INT, &is->audio_tgt.freq)) < 0)
2113 goto end;
2114 }
2115
2116 ret = avfilter_init_dict(filt_asink, NULL);
2117 if (ret < 0)
2118 goto end;
2119
2120 if ((ret = configure_filtergraph(is->agraph, afilters, filt_asrc, filt_asink)) < 0)
2121 goto end;
2122
2123 is->in_audio_filter = filt_asrc;
2124 is->out_audio_filter = filt_asink;
2125
2126 end:
2127 if (ret < 0)
2128 avfilter_graph_free(&is->agraph);
2129 av_bprint_finalize(&bp, NULL);
2130
2131 return ret;
2132 }
2133
2134 static int audio_thread(void *arg)
2135 {
2136 VideoState *is = arg;
2137 AVFrame *frame = av_frame_alloc();
2138 Frame *af;
2139 int last_serial = -1;
2140 int reconfigure;
2141 int got_frame = 0;
2142 AVRational tb;
2143 int ret = 0;
2144
2145 if (!frame)
2146 return AVERROR(ENOMEM);
2147
2148 do {
2149 if ((got_frame = decoder_decode_frame(&is->auddec, frame, NULL)) < 0)
2150 goto the_end;
2151
2152 if (got_frame) {
2153 tb = (AVRational){1, frame->sample_rate};
2154
2155 reconfigure =
2156 cmp_audio_fmts(is->audio_filter_src.fmt, is->audio_filter_src.ch_layout.nb_channels,
2157 frame->format, frame->ch_layout.nb_channels) ||
2158 av_channel_layout_compare(&is->audio_filter_src.ch_layout, &frame->ch_layout) ||
2159 is->audio_filter_src.freq != frame->sample_rate ||
2160 is->auddec.pkt_serial != last_serial;
2161
2162 if (reconfigure) {
2163 char buf1[1024], buf2[1024];
2164 av_channel_layout_describe(&is->audio_filter_src.ch_layout, buf1, sizeof(buf1));
2165 av_channel_layout_describe(&frame->ch_layout, buf2, sizeof(buf2));
2166 av_log(NULL, AV_LOG_DEBUG,
2167 "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",
2168 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,
2169 frame->sample_rate, frame->ch_layout.nb_channels, av_get_sample_fmt_name(frame->format), buf2, is->auddec.pkt_serial);
2170
2171 is->audio_filter_src.fmt = frame->format;
2172 ret = av_channel_layout_copy(&is->audio_filter_src.ch_layout, &frame->ch_layout);
2173 if (ret < 0)
2174 goto the_end;
2175 is->audio_filter_src.freq = frame->sample_rate;
2176 last_serial = is->auddec.pkt_serial;
2177
2178 if ((ret = configure_audio_filters(is, afilters, 1)) < 0)
2179 goto the_end;
2180 }
2181
2182 if ((ret = av_buffersrc_add_frame(is->in_audio_filter, frame)) < 0)
2183 goto the_end;
2184
2185 while ((ret = av_buffersink_get_frame_flags(is->out_audio_filter, frame, 0)) >= 0) {
2186 FrameData *fd = frame->opaque_ref ? (FrameData*)frame->opaque_ref->data : NULL;
2187 tb = av_buffersink_get_time_base(is->out_audio_filter);
2188 if (!(af = frame_queue_peek_writable(&is->sampq)))
2189 goto the_end;
2190
2191 af->pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb);
2192 af->pos = fd ? fd->pkt_pos : -1;
2193 af->serial = is->auddec.pkt_serial;
2194 af->duration = av_q2d((AVRational){frame->nb_samples, frame->sample_rate});
2195
2196 av_frame_move_ref(af->frame, frame);
2197 frame_queue_push(&is->sampq);
2198
2199 if (is->audioq.serial != is->auddec.pkt_serial)
2200 break;
2201 }
2202 if (ret == AVERROR_EOF)
2203 is->auddec.finished = is->auddec.pkt_serial;
2204 }
2205 } while (ret >= 0 || ret == AVERROR(EAGAIN) || ret == AVERROR_EOF);
2206 the_end:
2207 avfilter_graph_free(&is->agraph);
2208 av_frame_free(&frame);
2209 return ret;
2210 }
2211
2212 static int decoder_start(Decoder *d, int (*fn)(void *), const char *thread_name, void* arg)
2213 {
2214 packet_queue_start(d->queue);
2215 d->decoder_tid = SDL_CreateThread(fn, thread_name, arg);
2216 if (!d->decoder_tid) {
2217 av_log(NULL, AV_LOG_ERROR, "SDL_CreateThread(): %s\n", SDL_GetError());
2218 return AVERROR(ENOMEM);
2219 }
2220 return 0;
2221 }
2222
2223 static int video_thread(void *arg)
2224 {
2225 VideoState *is = arg;
2226 AVFrame *frame = av_frame_alloc();
2227 double pts;
2228 double duration;
2229 int ret;
2230 AVRational tb = is->video_st->time_base;
2231 AVRational frame_rate = av_guess_frame_rate(is->ic, is->video_st, NULL);
2232
2233 AVFilterGraph *graph = NULL;
2234 AVFilterContext *filt_out = NULL, *filt_in = NULL;
2235 int last_w = 0;
2236 int last_h = 0;
2237 enum AVPixelFormat last_format = -2;
2238 int last_serial = -1;
2239 int last_vfilter_idx = 0;
2240
2241 if (!frame)
2242 return AVERROR(ENOMEM);
2243
2244 for (;;) {
2245 ret = get_video_frame(is, frame);
2246 if (ret < 0)
2247 goto the_end;
2248 if (!ret)
2249 continue;
2250
2251 if ( last_w != frame->width
2252 || last_h != frame->height
2253 || last_format != frame->format
2254 || last_serial != is->viddec.pkt_serial
2255 || last_vfilter_idx != is->vfilter_idx) {
2256 av_log(NULL, AV_LOG_DEBUG,
2257 "Video frame changed from size:%dx%d format:%s serial:%d to size:%dx%d format:%s serial:%d\n",
2258 last_w, last_h,
2259 (const char *)av_x_if_null(av_get_pix_fmt_name(last_format), "none"), last_serial,
2260 frame->width, frame->height,
2261 (const char *)av_x_if_null(av_get_pix_fmt_name(frame->format), "none"), is->viddec.pkt_serial);
2262 avfilter_graph_free(&graph);
2263 graph = avfilter_graph_alloc();
2264 if (!graph) {
2265 ret = AVERROR(ENOMEM);
2266 goto the_end;
2267 }
2268 graph->nb_threads = filter_nbthreads;
2269 if ((ret = configure_video_filters(graph, is, vfilters_list ? vfilters_list[is->vfilter_idx] : NULL, frame)) < 0) {
2270 SDL_Event event;
2271 event.type = FF_QUIT_EVENT;
2272 event.user.data1 = is;
2273 SDL_PushEvent(&event);
2274 goto the_end;
2275 }
2276 filt_in = is->in_video_filter;
2277 filt_out = is->out_video_filter;
2278 last_w = frame->width;
2279 last_h = frame->height;
2280 last_format = frame->format;
2281 last_serial = is->viddec.pkt_serial;
2282 last_vfilter_idx = is->vfilter_idx;
2283 frame_rate = av_buffersink_get_frame_rate(filt_out);
2284 }
2285
2286 ret = av_buffersrc_add_frame(filt_in, frame);
2287 if (ret < 0)
2288 goto the_end;
2289
2290 while (ret >= 0) {
2291 FrameData *fd;
2292
2293 is->frame_last_returned_time = av_gettime_relative() / 1000000.0;
2294
2295 ret = av_buffersink_get_frame_flags(filt_out, frame, 0);
2296 if (ret < 0) {
2297 if (ret == AVERROR_EOF)
2298 is->viddec.finished = is->viddec.pkt_serial;
2299 ret = 0;
2300 break;
2301 }
2302
2303 fd = frame->opaque_ref ? (FrameData*)frame->opaque_ref->data : NULL;
2304
2305 is->frame_last_filter_delay = av_gettime_relative() / 1000000.0 - is->frame_last_returned_time;
2306 if (fabs(is->frame_last_filter_delay) > AV_NOSYNC_THRESHOLD / 10.0)
2307 is->frame_last_filter_delay = 0;
2308 tb = av_buffersink_get_time_base(filt_out);
2309 duration = (frame_rate.num && frame_rate.den ? av_q2d((AVRational){frame_rate.den, frame_rate.num}) : 0);
2310 pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb);
2311 ret = queue_picture(is, frame, pts, duration, fd ? fd->pkt_pos : -1, is->viddec.pkt_serial);
2312 av_frame_unref(frame);
2313 if (is->videoq.serial != is->viddec.pkt_serial)
2314 break;
2315 }
2316
2317 if (ret < 0)
2318 goto the_end;
2319 }
2320 the_end:
2321 avfilter_graph_free(&graph);
2322 av_frame_free(&frame);
2323 return 0;
2324 }
2325
2326 static int subtitle_thread(void *arg)
2327 {
2328 VideoState *is = arg;
2329 Frame *sp;
2330 int got_subtitle;
2331 double pts;
2332
2333 for (;;) {
2334 if (!(sp = frame_queue_peek_writable(&is->subpq)))
2335 return 0;
2336
2337 if ((got_subtitle = decoder_decode_frame(&is->subdec, NULL, &sp->sub)) < 0)
2338 break;
2339
2340 pts = 0;
2341
2342 if (got_subtitle && sp->sub.format == 0) {
2343 if (sp->sub.pts != AV_NOPTS_VALUE)
2344 pts = sp->sub.pts / (double)AV_TIME_BASE;
2345 sp->pts = pts;
2346 sp->serial = is->subdec.pkt_serial;
2347 sp->width = is->subdec.avctx->width;
2348 sp->height = is->subdec.avctx->height;
2349 sp->uploaded = 0;
2350
2351 /* now we can update the picture count */
2352 frame_queue_push(&is->subpq);
2353 } else if (got_subtitle) {
2354 avsubtitle_free(&sp->sub);
2355 }
2356 }
2357 return 0;
2358 }
2359
2360 /* copy samples for viewing in editor window */
2361 static void update_sample_display(VideoState *is, short *samples, int samples_size)
2362 {
2363 int size, len;
2364
2365 size = samples_size / sizeof(short);
2366 while (size > 0) {
2367 len = SAMPLE_ARRAY_SIZE - is->sample_array_index;
2368 if (len > size)
2369 len = size;
2370 memcpy(is->sample_array + is->sample_array_index, samples, len * sizeof(short));
2371 samples += len;
2372 is->sample_array_index += len;
2373 if (is->sample_array_index >= SAMPLE_ARRAY_SIZE)
2374 is->sample_array_index = 0;
2375 size -= len;
2376 }
2377 }
2378
2379 /* return the wanted number of samples to get better sync if sync_type is video
2380 * or external master clock */
2381 static int synchronize_audio(VideoState *is, int nb_samples)
2382 {
2383 int wanted_nb_samples = nb_samples;
2384
2385 /* if not master, then we try to remove or add samples to correct the clock */
2386 if (get_master_sync_type(is) != AV_SYNC_AUDIO_MASTER) {
2387 double diff, avg_diff;
2388 int min_nb_samples, max_nb_samples;
2389
2390 diff = get_clock(&is->audclk) - get_master_clock(is);
2391
2392 if (!isnan(diff) && fabs(diff) < AV_NOSYNC_THRESHOLD) {
2393 is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum;
2394 if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {
2395 /* not enough measures to have a correct estimate */
2396 is->audio_diff_avg_count++;
2397 } else {
2398 /* estimate the A-V difference */
2399 avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef);
2400
2401 if (fabs(avg_diff) >= is->audio_diff_threshold) {
2402 wanted_nb_samples = nb_samples + (int)(diff * is->audio_src.freq);
2403 min_nb_samples = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX) / 100));
2404 max_nb_samples = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX) / 100));
2405 wanted_nb_samples = av_clip(wanted_nb_samples, min_nb_samples, max_nb_samples);
2406 }
2407 av_log(NULL, AV_LOG_TRACE, "diff=%f adiff=%f sample_diff=%d apts=%0.3f %f\n",
2408 diff, avg_diff, wanted_nb_samples - nb_samples,
2409 is->audio_clock, is->audio_diff_threshold);
2410 }
2411 } else {
2412 /* too big difference : may be initial PTS errors, so
2413 reset A-V filter */
2414 is->audio_diff_avg_count = 0;
2415 is->audio_diff_cum = 0;
2416 }
2417 }
2418
2419 return wanted_nb_samples;
2420 }
2421
2422 /**
2423 * Decode one audio frame and return its uncompressed size.
2424 *
2425 * The processed audio frame is decoded, converted if required, and
2426 * stored in is->audio_buf, with size in bytes given by the return
2427 * value.
2428 */
2429 static int audio_decode_frame(VideoState *is)
2430 {
2431 int data_size, resampled_data_size;
2432 av_unused double audio_clock0;
2433 int wanted_nb_samples;
2434 Frame *af;
2435
2436 if (is->paused)
2437 return -1;
2438
2439 do {
2440 #if defined(_WIN32)
2441 while (frame_queue_nb_remaining(&is->sampq) == 0) {
2442 if ((av_gettime_relative() - audio_callback_time) > 1000000LL * is->audio_hw_buf_size / is->audio_tgt.bytes_per_sec / 2)
2443 return -1;
2444 av_usleep (1000);
2445 }
2446 #endif
2447 if (!(af = frame_queue_peek_readable(&is->sampq)))
2448 return -1;
2449 frame_queue_next(&is->sampq);
2450 } while (af->serial != is->audioq.serial);
2451
2452 data_size = av_samples_get_buffer_size(NULL, af->frame->ch_layout.nb_channels,
2453 af->frame->nb_samples,
2454 af->frame->format, 1);
2455
2456 wanted_nb_samples = synchronize_audio(is, af->frame->nb_samples);
2457
2458 if (af->frame->format != is->audio_src.fmt ||
2459 av_channel_layout_compare(&af->frame->ch_layout, &is->audio_src.ch_layout) ||
2460 af->frame->sample_rate != is->audio_src.freq ||
2461 (wanted_nb_samples != af->frame->nb_samples && !is->swr_ctx)) {
2462 int ret;
2463 swr_free(&is->swr_ctx);
2464 ret = swr_alloc_set_opts2(&is->swr_ctx,
2465 &is->audio_tgt.ch_layout, is->audio_tgt.fmt, is->audio_tgt.freq,
2466 &af->frame->ch_layout, af->frame->format, af->frame->sample_rate,
2467 0, NULL);
2468 if (ret < 0 || swr_init(is->swr_ctx) < 0) {
2469 av_log(NULL, AV_LOG_ERROR,
2470 "Cannot create sample rate converter for conversion of %d Hz %s %d channels to %d Hz %s %d channels!\n",
2471 af->frame->sample_rate, av_get_sample_fmt_name(af->frame->format), af->frame->ch_layout.nb_channels,
2472 is->audio_tgt.freq, av_get_sample_fmt_name(is->audio_tgt.fmt), is->audio_tgt.ch_layout.nb_channels);
2473 swr_free(&is->swr_ctx);
2474 return -1;
2475 }
2476 if (av_channel_layout_copy(&is->audio_src.ch_layout, &af->frame->ch_layout) < 0)
2477 return -1;
2478 is->audio_src.freq = af->frame->sample_rate;
2479 is->audio_src.fmt = af->frame->format;
2480 }
2481
2482 if (is->swr_ctx) {
2483 const uint8_t **in = (const uint8_t **)af->frame->extended_data;
2484 uint8_t **out = &is->audio_buf1;
2485 int out_count = (int64_t)wanted_nb_samples * is->audio_tgt.freq / af->frame->sample_rate + 256;
2486 int out_size = av_samples_get_buffer_size(NULL, is->audio_tgt.ch_layout.nb_channels, out_count, is->audio_tgt.fmt, 0);
2487 int len2;
2488 if (out_size < 0) {
2489 av_log(NULL, AV_LOG_ERROR, "av_samples_get_buffer_size() failed\n");
2490 return -1;
2491 }
2492 if (wanted_nb_samples != af->frame->nb_samples) {
2493 if (swr_set_compensation(is->swr_ctx, (wanted_nb_samples - af->frame->nb_samples) * is->audio_tgt.freq / af->frame->sample_rate,
2494 wanted_nb_samples * is->audio_tgt.freq / af->frame->sample_rate) < 0) {
2495 av_log(NULL, AV_LOG_ERROR, "swr_set_compensation() failed\n");
2496 return -1;
2497 }
2498 }
2499 av_fast_malloc(&is->audio_buf1, &is->audio_buf1_size, out_size);
2500 if (!is->audio_buf1)
2501 return AVERROR(ENOMEM);
2502 len2 = swr_convert(is->swr_ctx, out, out_count, in, af->frame->nb_samples);
2503 if (len2 < 0) {
2504 av_log(NULL, AV_LOG_ERROR, "swr_convert() failed\n");
2505 return -1;
2506 }
2507 if (len2 == out_count) {
2508 av_log(NULL, AV_LOG_WARNING, "audio buffer is probably too small\n");
2509 if (swr_init(is->swr_ctx) < 0)
2510 swr_free(&is->swr_ctx);
2511 }
2512 is->audio_buf = is->audio_buf1;
2513 resampled_data_size = len2 * is->audio_tgt.ch_layout.nb_channels * av_get_bytes_per_sample(is->audio_tgt.fmt);
2514 } else {
2515 is->audio_buf = af->frame->data[0];
2516 resampled_data_size = data_size;
2517 }
2518
2519 audio_clock0 = is->audio_clock;
2520 /* update the audio clock with the pts */
2521 if (!isnan(af->pts))
2522 is->audio_clock = af->pts + (double) af->frame->nb_samples / af->frame->sample_rate;
2523 else
2524 is->audio_clock = NAN;
2525 is->audio_clock_serial = af->serial;
2526 #ifdef DEBUG
2527 {
2528 static double last_clock;
2529 printf("audio: delay=%0.3f clock=%0.3f clock0=%0.3f\n",
2530 is->audio_clock - last_clock,
2531 is->audio_clock, audio_clock0);
2532 last_clock = is->audio_clock;
2533 }
2534 #endif
2535 return resampled_data_size;
2536 }
2537
2538 /* prepare a new audio buffer */
2539 static void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
2540 {
2541 VideoState *is = opaque;
2542 int audio_size, len1;
2543
2544 audio_callback_time = av_gettime_relative();
2545
2546 while (len > 0) {
2547 if (is->audio_buf_index >= is->audio_buf_size) {
2548 audio_size = audio_decode_frame(is);
2549 if (audio_size < 0) {
2550 /* if error, just output silence */
2551 is->audio_buf = NULL;
2552 is->audio_buf_size = SDL_AUDIO_MIN_BUFFER_SIZE / is->audio_tgt.frame_size * is->audio_tgt.frame_size;
2553 } else {
2554 if (is->show_mode != SHOW_MODE_VIDEO)
2555 update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
2556 is->audio_buf_size = audio_size;
2557 }
2558 is->audio_buf_index = 0;
2559 }
2560 len1 = is->audio_buf_size - is->audio_buf_index;
2561 if (len1 > len)
2562 len1 = len;
2563 if (!is->muted && is->audio_buf && is->audio_volume == SDL_MIX_MAXVOLUME)
2564 memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
2565 else {
2566 memset(stream, 0, len1);
2567 if (!is->muted && is->audio_buf)
2568 SDL_MixAudioFormat(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, AUDIO_S16SYS, len1, is->audio_volume);
2569 }
2570 len -= len1;
2571 stream += len1;
2572 is->audio_buf_index += len1;
2573 }
2574 is->audio_write_buf_size = is->audio_buf_size - is->audio_buf_index;
2575 /* Let's assume the audio driver that is used by SDL has two periods. */
2576 if (!isnan(is->audio_clock)) {
2577 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);
2578 sync_clock_to_slave(&is->extclk, &is->audclk);
2579 }
2580 }
2581
2582 static int audio_open(void *opaque, AVChannelLayout *wanted_channel_layout, int wanted_sample_rate, struct AudioParams *audio_hw_params)
2583 {
2584 SDL_AudioSpec wanted_spec, spec;
2585 const char *env;
2586 static const int next_nb_channels[] = {0, 0, 1, 6, 2, 6, 4, 6};
2587 static const int next_sample_rates[] = {0, 44100, 48000, 96000, 192000};
2588 int next_sample_rate_idx = FF_ARRAY_ELEMS(next_sample_rates) - 1;
2589 int wanted_nb_channels = wanted_channel_layout->nb_channels;
2590
2591 env = SDL_getenv("SDL_AUDIO_CHANNELS");
2592 if (env) {
2593 wanted_nb_channels = atoi(env);
2594 av_channel_layout_uninit(wanted_channel_layout);
2595 av_channel_layout_default(wanted_channel_layout, wanted_nb_channels);
2596 }
2597 if (wanted_channel_layout->order != AV_CHANNEL_ORDER_NATIVE) {
2598 av_channel_layout_uninit(wanted_channel_layout);
2599 av_channel_layout_default(wanted_channel_layout, wanted_nb_channels);
2600 }
2601 wanted_nb_channels = wanted_channel_layout->nb_channels;
2602 wanted_spec.channels = wanted_nb_channels;
2603 wanted_spec.freq = wanted_sample_rate;
2604 if (wanted_spec.freq <= 0 || wanted_spec.channels <= 0) {
2605 av_log(NULL, AV_LOG_ERROR, "Invalid sample rate or channel count!\n");
2606 return -1;
2607 }
2608 while (next_sample_rate_idx && next_sample_rates[next_sample_rate_idx] >= wanted_spec.freq)
2609 next_sample_rate_idx--;
2610 wanted_spec.format = AUDIO_S16SYS;
2611 wanted_spec.silence = 0;
2612 wanted_spec.samples = FFMAX(SDL_AUDIO_MIN_BUFFER_SIZE, 2 << av_log2(wanted_spec.freq / SDL_AUDIO_MAX_CALLBACKS_PER_SEC));
2613 wanted_spec.callback = sdl_audio_callback;
2614 wanted_spec.userdata = opaque;
2615 while (!(audio_dev = SDL_OpenAudioDevice(NULL, 0, &wanted_spec, &spec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE | SDL_AUDIO_ALLOW_CHANNELS_CHANGE))) {
2616 av_log(NULL, AV_LOG_WARNING, "SDL_OpenAudio (%d channels, %d Hz): %s\n",
2617 wanted_spec.channels, wanted_spec.freq, SDL_GetError());
2618 wanted_spec.channels = next_nb_channels[FFMIN(7, wanted_spec.channels)];
2619 if (!wanted_spec.channels) {
2620 wanted_spec.freq = next_sample_rates[next_sample_rate_idx--];
2621 wanted_spec.channels = wanted_nb_channels;
2622 if (!wanted_spec.freq) {
2623 av_log(NULL, AV_LOG_ERROR,
2624 "No more combinations to try, audio open failed\n");
2625 return -1;
2626 }
2627 }
2628 av_channel_layout_default(wanted_channel_layout, wanted_spec.channels);
2629 }
2630 if (spec.format != AUDIO_S16SYS) {
2631 av_log(NULL, AV_LOG_ERROR,
2632 "SDL advised audio format %d is not supported!\n", spec.format);
2633 return -1;
2634 }
2635 if (spec.channels != wanted_spec.channels) {
2636 av_channel_layout_uninit(wanted_channel_layout);
2637 av_channel_layout_default(wanted_channel_layout, spec.channels);
2638 if (wanted_channel_layout->order != AV_CHANNEL_ORDER_NATIVE) {
2639 av_log(NULL, AV_LOG_ERROR,
2640 "SDL advised channel count %d is not supported!\n", spec.channels);
2641 return -1;
2642 }
2643 }
2644
2645 audio_hw_params->fmt = AV_SAMPLE_FMT_S16;
2646 audio_hw_params->freq = spec.freq;
2647 if (av_channel_layout_copy(&audio_hw_params->ch_layout, wanted_channel_layout) < 0)
2648 return -1;
2649 audio_hw_params->frame_size = av_samples_get_buffer_size(NULL, audio_hw_params->ch_layout.nb_channels, 1, audio_hw_params->fmt, 1);
2650 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);
2651 if (audio_hw_params->bytes_per_sec <= 0 || audio_hw_params->frame_size <= 0) {
2652 av_log(NULL, AV_LOG_ERROR, "av_samples_get_buffer_size failed\n");
2653 return -1;
2654 }
2655 return spec.size;
2656 }
2657
2658 static int create_hwaccel(AVBufferRef **device_ctx)
2659 {
2660 enum AVHWDeviceType type;
2661 int ret;
2662 AVBufferRef *vk_dev;
2663
2664 *device_ctx = NULL;
2665
2666 if (!hwaccel)
2667 return 0;
2668
2669 type = av_hwdevice_find_type_by_name(hwaccel);
2670 if (type == AV_HWDEVICE_TYPE_NONE)
2671 return AVERROR(ENOTSUP);
2672
2673 if (!vk_renderer) {
2674 av_log(NULL, AV_LOG_ERROR, "Vulkan renderer is not available\n");
2675 return AVERROR(ENOTSUP);
2676 }
2677
2678 ret = vk_renderer_get_hw_dev(vk_renderer, &vk_dev);
2679 if (ret < 0)
2680 return ret;
2681
2682 ret = av_hwdevice_ctx_create_derived(device_ctx, type, vk_dev, 0);
2683 if (!ret)
2684 return 0;
2685
2686 if (ret != AVERROR(ENOSYS))
2687 return ret;
2688
2689 av_log(NULL, AV_LOG_WARNING, "Derive %s from vulkan not supported.\n", hwaccel);
2690 ret = av_hwdevice_ctx_create(device_ctx, type, NULL, NULL, 0);
2691 return ret;
2692 }
2693
2694 /* open a given stream. Return 0 if OK */
2695 static int stream_component_open(VideoState *is, int stream_index)
2696 {
2697 AVFormatContext *ic = is->ic;
2698 AVCodecContext *avctx;
2699 const AVCodec *codec;
2700 const char *forced_codec_name = NULL;
2701 AVDictionary *opts = NULL;
2702 int sample_rate;
2703 AVChannelLayout ch_layout = { 0 };
2704 int ret = 0;
2705 int stream_lowres = lowres;
2706
2707 if (stream_index < 0 || stream_index >= ic->nb_streams)
2708 return -1;
2709
2710 avctx = avcodec_alloc_context3(NULL);
2711 if (!avctx)
2712 return AVERROR(ENOMEM);
2713
2714 ret = avcodec_parameters_to_context(avctx, ic->streams[stream_index]->codecpar);
2715 if (ret < 0)
2716 goto fail;
2717 avctx->pkt_timebase = ic->streams[stream_index]->time_base;
2718
2719 codec = avcodec_find_decoder(avctx->codec_id);
2720
2721 switch(avctx->codec_type){
2722 case AVMEDIA_TYPE_AUDIO : is->last_audio_stream = stream_index; forced_codec_name = audio_codec_name; break;
2723 case AVMEDIA_TYPE_SUBTITLE: is->last_subtitle_stream = stream_index; forced_codec_name = subtitle_codec_name; break;
2724 case AVMEDIA_TYPE_VIDEO : is->last_video_stream = stream_index; forced_codec_name = video_codec_name; break;
2725 }
2726 if (forced_codec_name)
2727 codec = avcodec_find_decoder_by_name(forced_codec_name);
2728 if (!codec) {
2729 if (forced_codec_name) av_log(NULL, AV_LOG_WARNING,
2730 "No codec could be found with name '%s'\n", forced_codec_name);
2731 else av_log(NULL, AV_LOG_WARNING,
2732 "No decoder could be found for codec %s\n", avcodec_get_name(avctx->codec_id));
2733 ret = AVERROR(EINVAL);
2734 goto fail;
2735 }
2736
2737 avctx->codec_id = codec->id;
2738 if (stream_lowres > codec->max_lowres) {
2739 av_log(avctx, AV_LOG_WARNING, "The maximum value for lowres supported by the decoder is %d\n",
2740 codec->max_lowres);
2741 stream_lowres = codec->max_lowres;
2742 }
2743 avctx->lowres = stream_lowres;
2744
2745 if (fast)
2746 avctx->flags2 |= AV_CODEC_FLAG2_FAST;
2747
2748 ret = filter_codec_opts(codec_opts, avctx->codec_id, ic,
2749 ic->streams[stream_index], codec, &opts, NULL);
2750 if (ret < 0)
2751 goto fail;
2752
2753 if (!av_dict_get(opts, "threads", NULL, 0))
2754 av_dict_set(&opts, "threads", "auto", 0);
2755 if (stream_lowres)
2756 av_dict_set_int(&opts, "lowres", stream_lowres, 0);
2757
2758 av_dict_set(&opts, "flags", "+copy_opaque", AV_DICT_MULTIKEY);
2759
2760 if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) {
2761 ret = create_hwaccel(&avctx->hw_device_ctx);
2762 if (ret < 0)
2763 goto fail;
2764 }
2765
2766 if ((ret = avcodec_open2(avctx, codec, &opts)) < 0) {
2767 goto fail;
2768 }
2769 ret = check_avoptions(opts);
2770 if (ret < 0)
2771 goto fail;
2772
2773 is->eof = 0;
2774 ic->streams[stream_index]->discard = AVDISCARD_DEFAULT;
2775 switch (avctx->codec_type) {
2776 case AVMEDIA_TYPE_AUDIO:
2777 {
2778 AVFilterContext *sink;
2779
2780 is->audio_filter_src.freq = avctx->sample_rate;
2781 ret = av_channel_layout_copy(&is->audio_filter_src.ch_layout, &avctx->ch_layout);
2782 if (ret < 0)
2783 goto fail;
2784 is->audio_filter_src.fmt = avctx->sample_fmt;
2785 if ((ret = configure_audio_filters(is, afilters, 0)) < 0)
2786 goto fail;
2787 sink = is->out_audio_filter;
2788 sample_rate = av_buffersink_get_sample_rate(sink);
2789 ret = av_buffersink_get_ch_layout(sink, &ch_layout);
2790 if (ret < 0)
2791 goto fail;
2792 }
2793
2794 /* prepare audio output */
2795 if ((ret = audio_open(is, &ch_layout, sample_rate, &is->audio_tgt)) < 0)
2796 goto fail;
2797 is->audio_hw_buf_size = ret;
2798 is->audio_src = is->audio_tgt;
2799 is->audio_buf_size = 0;
2800 is->audio_buf_index = 0;
2801
2802 /* init averaging filter */
2803 is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
2804 is->audio_diff_avg_count = 0;
2805 /* since we do not have a precise anough audio FIFO fullness,
2806 we correct audio sync only if larger than this threshold */
2807 is->audio_diff_threshold = (double)(is->audio_hw_buf_size) / is->audio_tgt.bytes_per_sec;
2808
2809 is->audio_stream = stream_index;
2810 is->audio_st = ic->streams[stream_index];
2811
2812 if ((ret = decoder_init(&is->auddec, avctx, &is->audioq, is->continue_read_thread)) < 0)
2813 goto fail;
2814 if (is->ic->iformat->flags & AVFMT_NOTIMESTAMPS) {
2815 is->auddec.start_pts = is->audio_st->start_time;
2816 is->auddec.start_pts_tb = is->audio_st->time_base;
2817 }
2818 if ((ret = decoder_start(&is->auddec, audio_thread, "audio_decoder", is)) < 0)
2819 goto out;
2820 SDL_PauseAudioDevice(audio_dev, 0);
2821 break;
2822 case AVMEDIA_TYPE_VIDEO:
2823 is->video_stream = stream_index;
2824 is->video_st = ic->streams[stream_index];
2825
2826 if ((ret = decoder_init(&is->viddec, avctx, &is->videoq, is->continue_read_thread)) < 0)
2827 goto fail;
2828 if ((ret = decoder_start(&is->viddec, video_thread, "video_decoder", is)) < 0)
2829 goto out;
2830 is->queue_attachments_req = 1;
2831 break;
2832 case AVMEDIA_TYPE_SUBTITLE:
2833 is->subtitle_stream = stream_index;
2834 is->subtitle_st = ic->streams[stream_index];
2835
2836 if ((ret = decoder_init(&is->subdec, avctx, &is->subtitleq, is->continue_read_thread)) < 0)
2837 goto fail;
2838 if ((ret = decoder_start(&is->subdec, subtitle_thread, "subtitle_decoder", is)) < 0)
2839 goto out;
2840 break;
2841 default:
2842 break;
2843 }
2844 goto out;
2845
2846 fail:
2847 avcodec_free_context(&avctx);
2848 out:
2849 av_channel_layout_uninit(&ch_layout);
2850 av_dict_free(&opts);
2851
2852 return ret;
2853 }
2854
2855 static int decode_interrupt_cb(void *ctx)
2856 {
2857 VideoState *is = ctx;
2858 return is->abort_request;
2859 }
2860
2861 static int stream_has_enough_packets(AVStream *st, int stream_id, PacketQueue *queue) {
2862 return stream_id < 0 ||
2863 queue->abort_request ||
2864 (st->disposition & AV_DISPOSITION_ATTACHED_PIC) ||
2865 queue->nb_packets > MIN_FRAMES && (!queue->duration || av_q2d(st->time_base) * queue->duration > 1.0);
2866 }
2867
2868 static int is_realtime(AVFormatContext *s)
2869 {
2870 if( !strcmp(s->iformat->name, "rtp")
2871 || !strcmp(s->iformat->name, "rtsp")
2872 || !strcmp(s->iformat->name, "sdp")
2873 )
2874 return 1;
2875
2876 if(s->pb && ( !strncmp(s->url, "rtp:", 4)
2877 || !strncmp(s->url, "udp:", 4)
2878 )
2879 )
2880 return 1;
2881 return 0;
2882 }
2883
2884 /* this thread gets the stream from the disk or the network */
2885 static int read_thread(void *arg)
2886 {
2887 VideoState *is = arg;
2888 AVFormatContext *ic = NULL;
2889 int err, i, ret;
2890 int st_index[AVMEDIA_TYPE_NB];
2891 AVPacket *pkt = NULL;
2892 int64_t stream_start_time;
2893 char metadata_description[96];
2894 int pkt_in_play_range = 0;
2895 const AVDictionaryEntry *t;
2896 SDL_mutex *wait_mutex = SDL_CreateMutex();
2897 int scan_all_pmts_set = 0;
2898 int64_t pkt_ts;
2899
2900 if (!wait_mutex) {
2901 av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError());
2902 ret = AVERROR(ENOMEM);
2903 goto fail;
2904 }
2905
2906 memset(st_index, -1, sizeof(st_index));
2907 is->eof = 0;
2908
2909 pkt = av_packet_alloc();
2910 if (!pkt) {
2911 av_log(NULL, AV_LOG_FATAL, "Could not allocate packet.\n");
2912 ret = AVERROR(ENOMEM);
2913 goto fail;
2914 }
2915 ic = avformat_alloc_context();
2916 if (!ic) {
2917 av_log(NULL, AV_LOG_FATAL, "Could not allocate context.\n");
2918 ret = AVERROR(ENOMEM);
2919 goto fail;
2920 }
2921 ic->interrupt_callback.callback = decode_interrupt_cb;
2922 ic->interrupt_callback.opaque = is;
2923 if (!av_dict_get(format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE)) {
2924 av_dict_set(&format_opts, "scan_all_pmts", "1", AV_DICT_DONT_OVERWRITE);
2925 scan_all_pmts_set = 1;
2926 }
2927 err = avformat_open_input(&ic, is->filename, is->iformat, &format_opts);
2928 if (err < 0) {
2929 print_error(is->filename, err);
2930 ret = -1;
2931 goto fail;
2932 }
2933 if (scan_all_pmts_set)
2934 av_dict_set(&format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE);
2935 remove_avoptions(&format_opts, codec_opts);
2936
2937 ret = check_avoptions(format_opts);
2938 if (ret < 0)
2939 goto fail;
2940 is->ic = ic;
2941
2942 if (genpts)
2943 ic->flags |= AVFMT_FLAG_GENPTS;
2944
2945 if (find_stream_info) {
2946 AVDictionary **opts;
2947 int orig_nb_streams = ic->nb_streams;
2948
2949 err = setup_find_stream_info_opts(ic, codec_opts, &opts);
2950 if (err < 0) {
2951 av_log(NULL, AV_LOG_ERROR,
2952 "Error setting up avformat_find_stream_info() options\n");
2953 ret = err;
2954 goto fail;
2955 }
2956
2957 err = avformat_find_stream_info(ic, opts);
2958
2959 for (i = 0; i < orig_nb_streams; i++)
2960 av_dict_free(&opts[i]);
2961 av_freep(&opts);
2962
2963 if (err < 0) {
2964 av_log(NULL, AV_LOG_WARNING,
2965 "%s: could not find codec parameters\n", is->filename);
2966 ret = -1;
2967 goto fail;
2968 }
2969 }
2970
2971 if (ic->pb)
2972 ic->pb->eof_reached = 0; // FIXME hack, ffplay maybe should not use avio_feof() to test for the end
2973
2974 if (seek_by_bytes < 0)
2975 seek_by_bytes = !(ic->iformat->flags & AVFMT_NO_BYTE_SEEK) &&
2976 !!(ic->iformat->flags & AVFMT_TS_DISCONT) &&
2977 strcmp("ogg", ic->iformat->name);
2978
2979 is->max_frame_duration = (ic->iformat->flags & AVFMT_TS_DISCONT) ? 10.0 : 3600.0;
2980
2981 if (!window_title && (t = av_dict_get(ic->metadata, "title", NULL, 0)))
2982 window_title = av_asprintf("%s - %s", t->value, input_filename);
2983
2984 /* if seeking requested, we execute it */
2985 if (start_time != AV_NOPTS_VALUE) {
2986 int64_t timestamp;
2987
2988 timestamp = start_time;
2989 /* add the stream start time */
2990 if (ic->start_time != AV_NOPTS_VALUE)
2991 timestamp += ic->start_time;
2992 ret = avformat_seek_file(ic, -1, INT64_MIN, timestamp, INT64_MAX, 0);
2993 if (ret < 0) {
2994 av_log(NULL, AV_LOG_WARNING, "%s: could not seek to position %0.3f\n",
2995 is->filename, (double)timestamp / AV_TIME_BASE);
2996 }
2997 }
2998
2999 is->realtime = is_realtime(ic);
3000
3001 if (show_status) {
3002 fprintf(stderr, "\x1b[2K\r");
3003 av_dump_format(ic, 0, is->filename, 0);
3004 }
3005
3006 for (i = 0; i < ic->nb_streams; i++) {
3007 AVStream *st = ic->streams[i];
3008 enum AVMediaType type = st->codecpar->codec_type;
3009 st->discard = AVDISCARD_ALL;
3010 if (type >= 0 && wanted_stream_spec[type] && st_index[type] == -1)
3011 if (avformat_match_stream_specifier(ic, st, wanted_stream_spec[type]) > 0)
3012 st_index[type] = i;
3013 // Clear all pre-existing metadata update flags to avoid printing
3014 // initial metadata as update.
3015 st->event_flags &= ~AVSTREAM_EVENT_FLAG_METADATA_UPDATED;
3016 }
3017 ic->event_flags &= ~AVFMT_EVENT_FLAG_METADATA_UPDATED;
3018 for (i = 0; i < AVMEDIA_TYPE_NB; i++) {
3019 if (wanted_stream_spec[i] && st_index[i] == -1) {
3020 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));
3021 st_index[i] = INT_MAX;
3022 }
3023 }
3024
3025 if (!video_disable)
3026 st_index[AVMEDIA_TYPE_VIDEO] =
3027 av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO,
3028 st_index[AVMEDIA_TYPE_VIDEO], -1, NULL, 0);
3029 if (!audio_disable)
3030 st_index[AVMEDIA_TYPE_AUDIO] =
3031 av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO,
3032 st_index[AVMEDIA_TYPE_AUDIO],
3033 st_index[AVMEDIA_TYPE_VIDEO],
3034 NULL, 0);
3035 if (!video_disable && !subtitle_disable)
3036 st_index[AVMEDIA_TYPE_SUBTITLE] =
3037 av_find_best_stream(ic, AVMEDIA_TYPE_SUBTITLE,
3038 st_index[AVMEDIA_TYPE_SUBTITLE],
3039 (st_index[AVMEDIA_TYPE_AUDIO] >= 0 ?
3040 st_index[AVMEDIA_TYPE_AUDIO] :
3041 st_index[AVMEDIA_TYPE_VIDEO]),
3042 NULL, 0);
3043
3044 is->show_mode = show_mode;
3045 if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) {
3046 AVStream *st = ic->streams[st_index[AVMEDIA_TYPE_VIDEO]];
3047 AVCodecParameters *codecpar = st->codecpar;
3048 AVRational sar = av_guess_sample_aspect_ratio(ic, st, NULL);
3049 if (codecpar->width)
3050 set_default_window_size(codecpar->width, codecpar->height, sar);
3051 }
3052
3053 /* open the streams */
3054 if (st_index[AVMEDIA_TYPE_AUDIO] >= 0) {
3055 stream_component_open(is, st_index[AVMEDIA_TYPE_AUDIO]);
3056 }
3057
3058 ret = -1;
3059 if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) {
3060 ret = stream_component_open(is, st_index[AVMEDIA_TYPE_VIDEO]);
3061 }
3062 if (is->show_mode == SHOW_MODE_NONE)
3063 is->show_mode = ret >= 0 ? SHOW_MODE_VIDEO : SHOW_MODE_RDFT;
3064
3065 if (st_index[AVMEDIA_TYPE_SUBTITLE] >= 0) {
3066 stream_component_open(is, st_index[AVMEDIA_TYPE_SUBTITLE]);
3067 }
3068
3069 if (is->video_stream < 0 && is->audio_stream < 0) {
3070 av_log(NULL, AV_LOG_FATAL, "Failed to open file '%s' or configure filtergraph\n",
3071 is->filename);
3072 ret = -1;
3073 goto fail;
3074 }
3075
3076 if (infinite_buffer < 0 && is->realtime)
3077 infinite_buffer = 1;
3078
3079 for (;;) {
3080 if (is->abort_request)
3081 break;
3082 if (is->paused != is->last_paused) {
3083 is->last_paused = is->paused;
3084 if (is->paused)
3085 is->read_pause_return = av_read_pause(ic);
3086 else
3087 av_read_play(ic);
3088 }
3089 #if CONFIG_RTSP_DEMUXER || CONFIG_MMSH_PROTOCOL
3090 if (is->paused &&
3091 (!strcmp(ic->iformat->name, "rtsp") ||
3092 (ic->pb && !strncmp(input_filename, "mmsh:", 5)))) {
3093 /* wait 10 ms to avoid trying to get another packet */
3094 /* XXX: horrible */
3095 SDL_Delay(10);
3096 continue;
3097 }
3098 #endif
3099 if (is->seek_req) {
3100 int64_t seek_target = is->seek_pos;
3101 int64_t seek_min = is->seek_rel > 0 ? seek_target - is->seek_rel + 2: INT64_MIN;
3102 int64_t seek_max = is->seek_rel < 0 ? seek_target - is->seek_rel - 2: INT64_MAX;
3103 // FIXME the +-2 is due to rounding being not done in the correct direction in generation
3104 // of the seek_pos/seek_rel variables
3105
3106 ret = avformat_seek_file(is->ic, -1, seek_min, seek_target, seek_max, is->seek_flags);
3107 if (ret < 0) {
3108 av_log(NULL, AV_LOG_ERROR,
3109 "%s: error while seeking\n", is->ic->url);
3110 } else {
3111 if (is->audio_stream >= 0)
3112 packet_queue_flush(&is->audioq);
3113 if (is->subtitle_stream >= 0)
3114 packet_queue_flush(&is->subtitleq);
3115 if (is->video_stream >= 0)
3116 packet_queue_flush(&is->videoq);
3117 if (is->seek_flags & AVSEEK_FLAG_BYTE) {
3118 set_clock(&is->extclk, NAN, 0);
3119 } else {
3120 set_clock(&is->extclk, seek_target / (double)AV_TIME_BASE, 0);
3121 }
3122 }
3123 is->seek_req = 0;
3124 is->queue_attachments_req = 1;
3125 is->eof = 0;
3126 if (is->paused)
3127 step_to_next_frame(is);
3128 }
3129 if (is->queue_attachments_req) {
3130 if (is->video_st && is->video_st->disposition & AV_DISPOSITION_ATTACHED_PIC) {
3131 if ((ret = av_packet_ref(pkt, &is->video_st->attached_pic)) < 0)
3132 goto fail;
3133 packet_queue_put(&is->videoq, pkt);
3134 packet_queue_put_nullpacket(&is->videoq, pkt, is->video_stream);
3135 }
3136 is->queue_attachments_req = 0;
3137 }
3138
3139 /* if the queue are full, no need to read more */
3140 if (infinite_buffer<1 &&
3141 (is->audioq.size + is->videoq.size + is->subtitleq.size > MAX_QUEUE_SIZE
3142 || (stream_has_enough_packets(is->audio_st, is->audio_stream, &is->audioq) &&
3143 stream_has_enough_packets(is->video_st, is->video_stream, &is->videoq) &&
3144 stream_has_enough_packets(is->subtitle_st, is->subtitle_stream, &is->subtitleq)))) {
3145 /* wait 10 ms */
3146 SDL_LockMutex(wait_mutex);
3147 SDL_CondWaitTimeout(is->continue_read_thread, wait_mutex, 10);
3148 SDL_UnlockMutex(wait_mutex);
3149 continue;
3150 }
3151 if (!is->paused &&
3152 (!is->audio_st || (is->auddec.finished == is->audioq.serial && frame_queue_nb_remaining(&is->sampq) == 0)) &&
3153 (!is->video_st || (is->viddec.finished == is->videoq.serial && frame_queue_nb_remaining(&is->pictq) == 0))) {
3154 if (loop != 1 && (!loop || --loop)) {
3155 stream_seek(is, start_time != AV_NOPTS_VALUE ? start_time : 0, 0, 0);
3156 } else if (autoexit) {
3157 ret = AVERROR_EOF;
3158 goto fail;
3159 }
3160 }
3161 ret = av_read_frame(ic, pkt);
3162 if (ret < 0) {
3163 if ((ret == AVERROR_EOF || avio_feof(ic->pb)) && !is->eof) {
3164 if (is->video_stream >= 0)
3165 packet_queue_put_nullpacket(&is->videoq, pkt, is->video_stream);
3166 if (is->audio_stream >= 0)
3167 packet_queue_put_nullpacket(&is->audioq, pkt, is->audio_stream);
3168 if (is->subtitle_stream >= 0)
3169 packet_queue_put_nullpacket(&is->subtitleq, pkt, is->subtitle_stream);
3170 is->eof = 1;
3171 }
3172 if (ic->pb && ic->pb->error) {
3173 if (autoexit)
3174 goto fail;
3175 else
3176 break;
3177 }
3178 SDL_LockMutex(wait_mutex);
3179 SDL_CondWaitTimeout(is->continue_read_thread, wait_mutex, 10);
3180 SDL_UnlockMutex(wait_mutex);
3181 continue;
3182 } else {
3183 is->eof = 0;
3184 }
3185
3186 if (show_status) {
3187 if (ic->event_flags & AVFMT_EVENT_FLAG_METADATA_UPDATED) {
3188 fprintf(stderr, "\x1b[2K\r");
3189 dump_dictionary(NULL, ic->metadata,
3190 "\r New metadata", " ", AV_LOG_INFO);
3191 }
3192 if (ic->streams[pkt->stream_index]->event_flags &
3193 AVSTREAM_EVENT_FLAG_METADATA_UPDATED) {
3194 fprintf(stderr, "\x1b[2K\r");
3195 snprintf(metadata_description,
3196 sizeof(metadata_description),
3197 "\r New metadata for stream %d",
3198 pkt->stream_index);
3199 dump_dictionary(NULL, ic->streams[pkt->stream_index]->metadata,
3200 metadata_description, " ", AV_LOG_INFO);
3201 }
3202 }
3203 ic->event_flags &= ~AVFMT_EVENT_FLAG_METADATA_UPDATED;
3204 ic->streams[pkt->stream_index]->event_flags &= ~AVSTREAM_EVENT_FLAG_METADATA_UPDATED;
3205
3206 /* check if packet is in play range specified by user, then queue, otherwise discard */
3207 stream_start_time = ic->streams[pkt->stream_index]->start_time;
3208 pkt_ts = pkt->pts == AV_NOPTS_VALUE ? pkt->dts : pkt->pts;
3209 pkt_in_play_range = duration == AV_NOPTS_VALUE ||
3210 (pkt_ts - (stream_start_time != AV_NOPTS_VALUE ? stream_start_time : 0)) *
3211 av_q2d(ic->streams[pkt->stream_index]->time_base) -
3212 (double)(start_time != AV_NOPTS_VALUE ? start_time : 0) / 1000000
3213 <= ((double)duration / 1000000);
3214 if (pkt->stream_index == is->audio_stream && pkt_in_play_range) {
3215 packet_queue_put(&is->audioq, pkt);
3216 } else if (pkt->stream_index == is->video_stream && pkt_in_play_range
3217 && !(is->video_st->disposition & AV_DISPOSITION_ATTACHED_PIC)) {
3218 packet_queue_put(&is->videoq, pkt);
3219 } else if (pkt->stream_index == is->subtitle_stream && pkt_in_play_range) {
3220 packet_queue_put(&is->subtitleq, pkt);
3221 } else {
3222 av_packet_unref(pkt);
3223 }
3224 }
3225
3226 ret = 0;
3227 fail:
3228 if (ic && !is->ic)
3229 avformat_close_input(&ic);
3230
3231 av_packet_free(&pkt);
3232 if (ret != 0) {
3233 SDL_Event event;
3234
3235 event.type = FF_QUIT_EVENT;
3236 event.user.data1 = is;
3237 SDL_PushEvent(&event);
3238 }
3239 SDL_DestroyMutex(wait_mutex);
3240 return 0;
3241 }
3242
3243 static VideoState *stream_open(const char *filename,
3244 const AVInputFormat *iformat)
3245 {
3246 VideoState *is;
3247
3248 is = av_mallocz(sizeof(VideoState));
3249 if (!is)
3250 return NULL;
3251 is->last_video_stream = is->video_stream = -1;
3252 is->last_audio_stream = is->audio_stream = -1;
3253 is->last_subtitle_stream = is->subtitle_stream = -1;
3254 is->filename = av_strdup(filename);
3255 if (!is->filename)
3256 goto fail;
3257 is->iformat = iformat;
3258 is->ytop = 0;
3259 is->xleft = 0;
3260
3261 /* start video display */
3262 if (frame_queue_init(&is->pictq, &is->videoq, VIDEO_PICTURE_QUEUE_SIZE, 1) < 0)
3263 goto fail;
3264 if (frame_queue_init(&is->subpq, &is->subtitleq, SUBPICTURE_QUEUE_SIZE, 0) < 0)
3265 goto fail;
3266 if (frame_queue_init(&is->sampq, &is->audioq, SAMPLE_QUEUE_SIZE, 1) < 0)
3267 goto fail;
3268
3269 if (packet_queue_init(&is->videoq) < 0 ||
3270 packet_queue_init(&is->audioq) < 0 ||
3271 packet_queue_init(&is->subtitleq) < 0)
3272 goto fail;
3273
3274 if (!(is->continue_read_thread = SDL_CreateCond())) {
3275 av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError());
3276 goto fail;
3277 }
3278
3279 init_clock(&is->vidclk, &is->videoq.serial);
3280 init_clock(&is->audclk, &is->audioq.serial);
3281 init_clock(&is->extclk, &is->extclk.serial);
3282 is->audio_clock_serial = -1;
3283 if (startup_volume < 0)
3284 av_log(NULL, AV_LOG_WARNING, "-volume=%d < 0, setting to 0\n", startup_volume);
3285 if (startup_volume > 100)
3286 av_log(NULL, AV_LOG_WARNING, "-volume=%d > 100, setting to 100\n", startup_volume);
3287 if (video_background) {
3288 if (!strcmp(video_background, "none")) {
3289 is->render_params.video_background_type = VIDEO_BACKGROUND_NONE;
3290 } else if (strcmp(video_background, "tiles")) {
3291 if (av_parse_color(is->render_params.video_background_color, video_background, -1, NULL) >= 0)
3292 is->render_params.video_background_type = VIDEO_BACKGROUND_COLOR;
3293 else
3294 goto fail;
3295 }
3296 }
3297 startup_volume = av_clip(startup_volume, 0, 100);
3298 startup_volume = av_clip(SDL_MIX_MAXVOLUME * startup_volume / 100, 0, SDL_MIX_MAXVOLUME);
3299 is->audio_volume = startup_volume;
3300 is->muted = 0;
3301 is->av_sync_type = av_sync_type;
3302 is->read_tid = SDL_CreateThread(read_thread, "read_thread", is);
3303 if (!is->read_tid) {
3304 av_log(NULL, AV_LOG_FATAL, "SDL_CreateThread(): %s\n", SDL_GetError());
3305 fail:
3306 stream_close(is);
3307 return NULL;
3308 }
3309 return is;
3310 }
3311
3312 static void stream_cycle_channel(VideoState *is, int codec_type)
3313 {
3314 AVFormatContext *ic = is->ic;
3315 int start_index, stream_index;
3316 int old_index;
3317 AVStream *st;
3318 AVProgram *p = NULL;
3319 int nb_streams = is->ic->nb_streams;
3320
3321 if (codec_type == AVMEDIA_TYPE_VIDEO) {
3322 start_index = is->last_video_stream;
3323 old_index = is->video_stream;
3324 } else if (codec_type == AVMEDIA_TYPE_AUDIO) {
3325 start_index = is->last_audio_stream;
3326 old_index = is->audio_stream;
3327 } else {
3328 start_index = is->last_subtitle_stream;
3329 old_index = is->subtitle_stream;
3330 }
3331 stream_index = start_index;
3332
3333 if (codec_type != AVMEDIA_TYPE_VIDEO && is->video_stream != -1) {
3334 p = av_find_program_from_stream(ic, NULL, is->video_stream);
3335 if (p) {
3336 nb_streams = p->nb_stream_indexes;
3337 for (start_index = 0; start_index < nb_streams; start_index++)
3338 if (p->stream_index[start_index] == stream_index)
3339 break;
3340 if (start_index == nb_streams)
3341 start_index = -1;
3342 stream_index = start_index;
3343 }
3344 }
3345
3346 for (;;) {
3347 if (++stream_index >= nb_streams)
3348 {
3349 if (codec_type == AVMEDIA_TYPE_SUBTITLE)
3350 {
3351 stream_index = -1;
3352 is->last_subtitle_stream = -1;
3353 goto the_end;
3354 }
3355 if (start_index == -1)
3356 return;
3357 stream_index = 0;
3358 }
3359 if (stream_index == start_index)
3360 return;
3361 st = is->ic->streams[p ? p->stream_index[stream_index] : stream_index];
3362 if (st->codecpar->codec_type == codec_type) {
3363 /* check that parameters are OK */
3364 switch (codec_type) {
3365 case AVMEDIA_TYPE_AUDIO:
3366 if (st->codecpar->sample_rate != 0 &&
3367 st->codecpar->ch_layout.nb_channels != 0)
3368 goto the_end;
3369 break;
3370 case AVMEDIA_TYPE_VIDEO:
3371 case AVMEDIA_TYPE_SUBTITLE:
3372 goto the_end;
3373 default:
3374 break;
3375 }
3376 }
3377 }
3378 the_end:
3379 if (p && stream_index != -1)
3380 stream_index = p->stream_index[stream_index];
3381 av_log(NULL, AV_LOG_INFO, "Switch %s stream from #%d to #%d\n",
3382 av_get_media_type_string(codec_type),
3383 old_index,
3384 stream_index);
3385
3386 stream_component_close(is, old_index);
3387 stream_component_open(is, stream_index);
3388 }
3389
3390
3391 static void toggle_full_screen(VideoState *is)
3392 {
3393 is_full_screen = !is_full_screen;
3394 SDL_SetWindowFullscreen(window, is_full_screen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
3395 }
3396
3397 static void toggle_audio_display(VideoState *is)
3398 {
3399 int next = is->show_mode;
3400 do {
3401 next = (next + 1) % SHOW_MODE_NB;
3402 } while (next != is->show_mode && (next == SHOW_MODE_VIDEO && !is->video_st || next != SHOW_MODE_VIDEO && !is->audio_st));
3403 if (is->show_mode != next) {
3404 is->force_refresh = 1;
3405 is->show_mode = next;
3406 }
3407 }
3408
3409 static void refresh_loop_wait_event(VideoState *is, SDL_Event *event) {
3410 double remaining_time = 0.0;
3411 SDL_PumpEvents();
3412 while (!SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)) {
3413 if (received_sigterm) {
3414 exit_status = 123;
3415 do_exit(is);
3416 }
3417 if (!cursor_hidden && av_gettime_relative() - cursor_last_shown > CURSOR_HIDE_DELAY) {
3418 SDL_ShowCursor(0);
3419 cursor_hidden = 1;
3420 }
3421 if (remaining_time > 0.0)
3422 av_usleep((int64_t)(remaining_time * 1000000.0));
3423 remaining_time = REFRESH_RATE;
3424 if (is->show_mode != SHOW_MODE_NONE && (!is->paused || is->force_refresh))
3425 video_refresh(is, &remaining_time);
3426 SDL_PumpEvents();
3427 }
3428 }
3429
3430 static void seek_chapter(VideoState *is, int incr)
3431 {
3432 int64_t pos = get_master_clock(is) * AV_TIME_BASE;
3433 int i;
3434
3435 if (!is->ic->nb_chapters)
3436 return;
3437
3438 /* find the current chapter */
3439 for (i = 0; i < is->ic->nb_chapters; i++) {
3440 AVChapter *ch = is->ic->chapters[i];
3441 if (av_compare_ts(pos, AV_TIME_BASE_Q, ch->start, ch->time_base) < 0) {
3442 i--;
3443 break;
3444 }
3445 }
3446
3447 i += incr;
3448 i = FFMAX(i, 0);
3449 if (i >= is->ic->nb_chapters)
3450 return;
3451
3452 av_log(NULL, AV_LOG_VERBOSE, "Seeking to chapter %d.\n", i);
3453 stream_seek(is, av_rescale_q(is->ic->chapters[i]->start, is->ic->chapters[i]->time_base,
3454 AV_TIME_BASE_Q), 0, 0);
3455 }
3456
3457 /* handle an event sent by the GUI */
3458 static void event_loop(VideoState *cur_stream)
3459 {
3460 SDL_Event event;
3461 double incr, pos, frac;
3462
3463 for (;;) {
3464 double x;
3465 refresh_loop_wait_event(cur_stream, &event);
3466 switch (event.type) {
3467 case SDL_KEYDOWN:
3468 if (exit_on_keydown || event.key.keysym.sym == SDLK_ESCAPE || event.key.keysym.sym == SDLK_q) {
3469 do_exit(cur_stream);
3470 break;
3471 }
3472 // If we don't yet have a window, skip all key events, because read_thread might still be initializing...
3473 if (!cur_stream->width)
3474 continue;
3475 switch (event.key.keysym.sym) {
3476 case SDLK_f:
3477 toggle_full_screen(cur_stream);
3478 cur_stream->force_refresh = 1;
3479 break;
3480 case SDLK_p:
3481 case SDLK_SPACE:
3482 toggle_pause(cur_stream);
3483 break;
3484 case SDLK_m:
3485 toggle_mute(cur_stream);
3486 break;
3487 case SDLK_KP_MULTIPLY:
3488 case SDLK_0:
3489 update_volume(cur_stream, 1, SDL_VOLUME_STEP);
3490 break;
3491 case SDLK_KP_DIVIDE:
3492 case SDLK_9:
3493 update_volume(cur_stream, -1, SDL_VOLUME_STEP);
3494 break;
3495 case SDLK_s: // S: Step to next frame
3496 step_to_next_frame(cur_stream);
3497 break;
3498 case SDLK_a:
3499 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_AUDIO);
3500 break;
3501 case SDLK_v:
3502 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_VIDEO);
3503 break;
3504 case SDLK_c:
3505 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_VIDEO);
3506 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_AUDIO);
3507 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_SUBTITLE);
3508 break;
3509 case SDLK_t:
3510 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_SUBTITLE);
3511 break;
3512 case SDLK_w:
3513 if (cur_stream->show_mode == SHOW_MODE_VIDEO && cur_stream->vfilter_idx < nb_vfilters - 1) {
3514 if (++cur_stream->vfilter_idx >= nb_vfilters)
3515 cur_stream->vfilter_idx = 0;
3516 } else {
3517 cur_stream->vfilter_idx = 0;
3518 toggle_audio_display(cur_stream);
3519 }
3520 break;
3521 case SDLK_PAGEUP:
3522 if (cur_stream->ic->nb_chapters <= 1) {
3523 incr = 600.0;
3524 goto do_seek;
3525 }
3526 seek_chapter(cur_stream, 1);
3527 break;
3528 case SDLK_PAGEDOWN:
3529 if (cur_stream->ic->nb_chapters <= 1) {
3530 incr = -600.0;
3531 goto do_seek;
3532 }
3533 seek_chapter(cur_stream, -1);
3534 break;
3535 case SDLK_LEFT:
3536 incr = seek_interval ? -seek_interval : -10.0;
3537 goto do_seek;
3538 case SDLK_RIGHT:
3539 incr = seek_interval ? seek_interval : 10.0;
3540 goto do_seek;
3541 case SDLK_UP:
3542 incr = 60.0;
3543 goto do_seek;
3544 case SDLK_DOWN:
3545 incr = -60.0;
3546 do_seek:
3547 if (seek_by_bytes) {
3548 pos = -1;
3549 if (pos < 0 && cur_stream->video_stream >= 0)
3550 pos = frame_queue_last_pos(&cur_stream->pictq);
3551 if (pos < 0 && cur_stream->audio_stream >= 0)
3552 pos = frame_queue_last_pos(&cur_stream->sampq);
3553 if (pos < 0)
3554 pos = avio_tell(cur_stream->ic->pb);
3555 if (cur_stream->ic->bit_rate)
3556 incr *= cur_stream->ic->bit_rate / 8.0;
3557 else
3558 incr *= 180000.0;
3559 pos += incr;
3560 stream_seek(cur_stream, pos, incr, 1);
3561 } else {
3562 pos = get_master_clock(cur_stream);
3563 if (isnan(pos))
3564 pos = (double)cur_stream->seek_pos / AV_TIME_BASE;
3565 pos += incr;
3566 if (cur_stream->ic->start_time != AV_NOPTS_VALUE && pos < cur_stream->ic->start_time / (double)AV_TIME_BASE)
3567 pos = cur_stream->ic->start_time / (double)AV_TIME_BASE;
3568 stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), (int64_t)(incr * AV_TIME_BASE), 0);
3569 }
3570 break;
3571 default:
3572 break;
3573 }
3574 break;
3575 case SDL_MOUSEBUTTONDOWN:
3576 if (exit_on_mousedown) {
3577 do_exit(cur_stream);
3578 break;
3579 }
3580 if (event.button.button == SDL_BUTTON_LEFT) {
3581 static int64_t last_mouse_left_click = 0;
3582 if (av_gettime_relative() - last_mouse_left_click <= 500000) {
3583 toggle_full_screen(cur_stream);
3584 cur_stream->force_refresh = 1;
3585 last_mouse_left_click = 0;
3586 } else {
3587 last_mouse_left_click = av_gettime_relative();
3588 }
3589 }
3590 av_fallthrough;
3591 case SDL_MOUSEMOTION:
3592 if (cursor_hidden) {
3593 SDL_ShowCursor(1);
3594 cursor_hidden = 0;
3595 }
3596 cursor_last_shown = av_gettime_relative();
3597 if (event.type == SDL_MOUSEBUTTONDOWN) {
3598 if (event.button.button != SDL_BUTTON_RIGHT)
3599 break;
3600 x = event.button.x;
3601 } else {
3602 if (!(event.motion.state & SDL_BUTTON_RMASK))
3603 break;
3604 x = event.motion.x;
3605 }
3606 if (seek_by_bytes || cur_stream->ic->duration <= 0) {
3607 uint64_t size = avio_size(cur_stream->ic->pb);
3608 stream_seek(cur_stream, size*x/cur_stream->width, 0, 1);
3609 } else {
3610 int64_t ts;
3611 int ns, hh, mm, ss;
3612 int tns, thh, tmm, tss;
3613 tns = cur_stream->ic->duration / 1000000LL;
3614 thh = tns / 3600;
3615 tmm = (tns % 3600) / 60;
3616 tss = (tns % 60);
3617 frac = x / cur_stream->width;
3618 ns = frac * tns;
3619 hh = ns / 3600;
3620 mm = (ns % 3600) / 60;
3621 ss = (ns % 60);
3622 av_log(NULL, AV_LOG_INFO,
3623 "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
3624 hh, mm, ss, thh, tmm, tss);
3625 ts = frac * cur_stream->ic->duration;
3626 if (cur_stream->ic->start_time != AV_NOPTS_VALUE)
3627 ts += cur_stream->ic->start_time;
3628 stream_seek(cur_stream, ts, 0, 0);
3629 }
3630 break;
3631 case SDL_WINDOWEVENT:
3632 switch (event.window.event) {
3633 case SDL_WINDOWEVENT_SIZE_CHANGED:
3634 screen_width = cur_stream->width = event.window.data1;
3635 screen_height = cur_stream->height = event.window.data2;
3636 if (cur_stream->vis_texture) {
3637 SDL_DestroyTexture(cur_stream->vis_texture);
3638 cur_stream->vis_texture = NULL;
3639 }
3640 if (vk_renderer)
3641 vk_renderer_resize(vk_renderer, screen_width, screen_height);
3642 av_fallthrough;
3643 case SDL_WINDOWEVENT_EXPOSED:
3644 cur_stream->force_refresh = 1;
3645 }
3646 break;
3647 case SDL_QUIT:
3648 case FF_QUIT_EVENT:
3649 do_exit(cur_stream);
3650 break;
3651 default:
3652 break;
3653 }
3654 }
3655 }
3656
3657 static int opt_width(void *optctx, const char *opt, const char *arg)
3658 {
3659 double num;
3660 int ret = parse_number(opt, arg, OPT_TYPE_INT64, 1, INT_MAX, &num);
3661 if (ret < 0)
3662 return ret;
3663
3664 screen_width = num;
3665 return 0;
3666 }
3667
3668 static int opt_height(void *optctx, const char *opt, const char *arg)
3669 {
3670 double num;
3671 int ret = parse_number(opt, arg, OPT_TYPE_INT64, 1, INT_MAX, &num);
3672 if (ret < 0)
3673 return ret;
3674
3675 screen_height = num;
3676 return 0;
3677 }
3678
3679 static int opt_format(void *optctx, const char *opt, const char *arg)
3680 {
3681 file_iformat = av_find_input_format(arg);
3682 if (!file_iformat) {
3683 av_log(NULL, AV_LOG_FATAL, "Unknown input format: %s\n", arg);
3684 return AVERROR(EINVAL);
3685 }
3686 return 0;
3687 }
3688
3689 static int opt_sync(void *optctx, const char *opt, const char *arg)
3690 {
3691 if (!strcmp(arg, "audio"))
3692 av_sync_type = AV_SYNC_AUDIO_MASTER;
3693 else if (!strcmp(arg, "video"))
3694 av_sync_type = AV_SYNC_VIDEO_MASTER;
3695 else if (!strcmp(arg, "ext"))
3696 av_sync_type = AV_SYNC_EXTERNAL_CLOCK;
3697 else {
3698 av_log(NULL, AV_LOG_ERROR, "Unknown value for %s: %s\n", opt, arg);
3699 exit(1);
3700 }
3701 return 0;
3702 }
3703
3704 static int opt_show_mode(void *optctx, const char *opt, const char *arg)
3705 {
3706 show_mode = !strcmp(arg, "video") ? SHOW_MODE_VIDEO :
3707 !strcmp(arg, "waves") ? SHOW_MODE_WAVES :
3708 !strcmp(arg, "rdft" ) ? SHOW_MODE_RDFT : SHOW_MODE_NONE;
3709
3710 if (show_mode == SHOW_MODE_NONE) {
3711 double num;
3712 int ret = parse_number(opt, arg, OPT_TYPE_INT, 0, SHOW_MODE_NB-1, &num);
3713 if (ret < 0)
3714 return ret;
3715 show_mode = num;
3716 }
3717 return 0;
3718 }
3719
3720 static int opt_input_file(void *optctx, const char *filename)
3721 {
3722 if (input_filename) {
3723 av_log(NULL, AV_LOG_FATAL,
3724 "Argument '%s' provided as input filename, but '%s' was already specified.\n",
3725 filename, input_filename);
3726 return AVERROR(EINVAL);
3727 }
3728 if (!strcmp(filename, "-"))
3729 filename = "fd:";
3730 input_filename = av_strdup(filename);
3731 if (!input_filename)
3732 return AVERROR(ENOMEM);
3733
3734 return 0;
3735 }
3736
3737 static int opt_codec(void *optctx, const char *opt, const char *arg)
3738 {
3739 const char *spec = strchr(opt, ':');
3740 const char **name;
3741 if (!spec) {
3742 av_log(NULL, AV_LOG_ERROR,
3743 "No media specifier was specified in '%s' in option '%s'\n",
3744 arg, opt);
3745 return AVERROR(EINVAL);
3746 }
3747 spec++;
3748
3749 switch (spec[0]) {
3750 case 'a' : name = &audio_codec_name; break;
3751 case 's' : name = &subtitle_codec_name; break;
3752 case 'v' : name = &video_codec_name; break;
3753 default:
3754 av_log(NULL, AV_LOG_ERROR,
3755 "Invalid media specifier '%s' in option '%s'\n", spec, opt);
3756 return AVERROR(EINVAL);
3757 }
3758
3759 av_freep(name);
3760 *name = av_strdup(arg);
3761 return *name ? 0 : AVERROR(ENOMEM);
3762 }
3763
3764 static int dummy;
3765
3766 static const OptionDef options[] = {
3767 CMDUTILS_COMMON_OPTIONS
3768 { "x", OPT_TYPE_FUNC, OPT_FUNC_ARG, { .func_arg = opt_width }, "force displayed width", "width" },
3769 { "y", OPT_TYPE_FUNC, OPT_FUNC_ARG, { .func_arg = opt_height }, "force displayed height", "height" },
3770 { "fs", OPT_TYPE_BOOL, 0, { &is_full_screen }, "force full screen" },
3771 { "an", OPT_TYPE_BOOL, 0, { &audio_disable }, "disable audio" },
3772 { "vn", OPT_TYPE_BOOL, 0, { &video_disable }, "disable video" },
3773 { "sn", OPT_TYPE_BOOL, 0, { &subtitle_disable }, "disable subtitling" },
3774 { "ast", OPT_TYPE_STRING, OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_AUDIO] }, "select desired audio stream", "stream_specifier" },
3775 { "vst", OPT_TYPE_STRING, OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_VIDEO] }, "select desired video stream", "stream_specifier" },
3776 { "sst", OPT_TYPE_STRING, OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_SUBTITLE] }, "select desired subtitle stream", "stream_specifier" },
3777 { "ss", OPT_TYPE_TIME, 0, { &start_time }, "seek to a given position in seconds", "pos" },
3778 { "t", OPT_TYPE_TIME, 0, { &duration }, "play \"duration\" seconds of audio/video", "duration" },
3779 { "bytes", OPT_TYPE_INT, 0, { &seek_by_bytes }, "seek by bytes 0=off 1=on -1=auto", "val" },
3780 { "seek_interval", OPT_TYPE_FLOAT, 0, { &seek_interval }, "set seek interval for left/right keys, in seconds", "seconds" },
3781 { "nodisp", OPT_TYPE_BOOL, 0, { &display_disable }, "disable graphical display" },
3782 { "noborder", OPT_TYPE_BOOL, 0, { &borderless }, "borderless window" },
3783 { "alwaysontop", OPT_TYPE_BOOL, 0, { &alwaysontop }, "window always on top" },
3784 { "volume", OPT_TYPE_INT, 0, { &startup_volume}, "set startup volume 0=min 100=max", "volume" },
3785 { "f", OPT_TYPE_FUNC, OPT_FUNC_ARG, { .func_arg = opt_format }, "force format", "fmt" },
3786 { "stats", OPT_TYPE_BOOL, OPT_EXPERT, { &show_status }, "show status", "" },
3787 { "fast", OPT_TYPE_BOOL, OPT_EXPERT, { &fast }, "non spec compliant optimizations", "" },
3788 { "genpts", OPT_TYPE_BOOL, OPT_EXPERT, { &genpts }, "generate pts", "" },
3789 { "drp", OPT_TYPE_INT, OPT_EXPERT, { &decoder_reorder_pts }, "let decoder reorder pts 0=off 1=on -1=auto", ""},
3790 { "lowres", OPT_TYPE_INT, OPT_EXPERT, { &lowres }, "", "" },
3791 { "sync", OPT_TYPE_FUNC, OPT_FUNC_ARG | OPT_EXPERT, { .func_arg = opt_sync }, "set audio-video sync. type (type=audio/video/ext)", "type" },
3792 { "autoexit", OPT_TYPE_BOOL, OPT_EXPERT, { &autoexit }, "exit at the end", "" },
3793 { "exitonkeydown", OPT_TYPE_BOOL, OPT_EXPERT, { &exit_on_keydown }, "exit on key down", "" },
3794 { "exitonmousedown", OPT_TYPE_BOOL, OPT_EXPERT, { &exit_on_mousedown }, "exit on mouse down", "" },
3795 { "loop", OPT_TYPE_INT, OPT_EXPERT, { &loop }, "set number of times the playback shall be looped", "loop count" },
3796 { "framedrop", OPT_TYPE_BOOL, OPT_EXPERT, { &framedrop }, "drop frames when cpu is too slow", "" },
3797 { "infbuf", OPT_TYPE_BOOL, OPT_EXPERT, { &infinite_buffer }, "don't limit the input buffer size (useful with realtime streams)", "" },
3798 { "window_title", OPT_TYPE_STRING, 0, { &window_title }, "set window title", "window title" },
3799 { "left", OPT_TYPE_INT, OPT_EXPERT, { &screen_left }, "set the x position for the left of the window", "x pos" },
3800 { "top", OPT_TYPE_INT, OPT_EXPERT, { &screen_top }, "set the y position for the top of the window", "y pos" },
3801 { "vf", OPT_TYPE_FUNC, OPT_FUNC_ARG | OPT_EXPERT, { .func_arg = opt_add_vfilter }, "set video filters", "filter_graph" },
3802 { "af", OPT_TYPE_STRING, 0, { &afilters }, "set audio filters", "filter_graph" },
3803 { "rdftspeed", OPT_TYPE_INT, OPT_AUDIO | OPT_EXPERT, { &rdftspeed }, "rdft speed", "msecs" },
3804 { "showmode", OPT_TYPE_FUNC, OPT_FUNC_ARG, { .func_arg = opt_show_mode}, "select show mode (0 = video, 1 = waves, 2 = RDFT)", "mode" },
3805 { "i", OPT_TYPE_BOOL, 0, { &dummy}, "read specified file", "input_file"},
3806 { "codec", OPT_TYPE_FUNC, OPT_FUNC_ARG, { .func_arg = opt_codec}, "force decoder", "decoder_name" },
3807 { "acodec", OPT_TYPE_STRING, OPT_EXPERT, { &audio_codec_name }, "force audio decoder", "decoder_name" },
3808 { "scodec", OPT_TYPE_STRING, OPT_EXPERT, { &subtitle_codec_name }, "force subtitle decoder", "decoder_name" },
3809 { "vcodec", OPT_TYPE_STRING, OPT_EXPERT, { &video_codec_name }, "force video decoder", "decoder_name" },
3810 { "autorotate", OPT_TYPE_BOOL, 0, { &autorotate }, "automatically rotate video", "" },
3811 { "find_stream_info", OPT_TYPE_BOOL, OPT_INPUT | OPT_EXPERT, { &find_stream_info },
3812 "read and decode the streams to fill missing information with heuristics" },
3813 { "filter_threads", OPT_TYPE_INT, OPT_EXPERT, { &filter_nbthreads }, "number of filter threads per graph" },
3814 { "enable_vulkan", OPT_TYPE_BOOL, 0, { &enable_vulkan }, "enable vulkan renderer" },
3815 { "vulkan_params", OPT_TYPE_STRING, OPT_EXPERT, { &vulkan_params }, "vulkan configuration using a list of key=value pairs separated by ':'" },
3816 { "video_bg", OPT_TYPE_STRING, OPT_EXPERT, { &video_background }, "set video background for transparent videos" },
3817 { "hwaccel", OPT_TYPE_STRING, OPT_EXPERT, { &hwaccel }, "use HW accelerated decoding" },
3818 { NULL, },
3819 };
3820
3821 static void show_usage(void)
3822 {
3823 av_log(NULL, AV_LOG_INFO, "Simple media player\n");
3824 av_log(NULL, AV_LOG_INFO, "usage: %s [options] input_file\n", program_name);
3825 av_log(NULL, AV_LOG_INFO, "\n");
3826 }
3827
3828 void show_help_default(const char *opt, const char *arg)
3829 {
3830 av_log_set_callback(log_callback_help);
3831 show_usage();
3832 show_help_options(options, "Main options:", 0, OPT_EXPERT);
3833 show_help_options(options, "Advanced options:", OPT_EXPERT, 0);
3834 printf("\n");
3835 show_help_children(avcodec_get_class(), AV_OPT_FLAG_DECODING_PARAM);
3836 show_help_children(avformat_get_class(), AV_OPT_FLAG_DECODING_PARAM);
3837 show_help_children(avfilter_get_class(), AV_OPT_FLAG_FILTERING_PARAM);
3838 printf("\nWhile playing:\n"
3839 "q, ESC quit\n"
3840 "f toggle full screen\n"
3841 "p, SPC pause\n"
3842 "m toggle mute\n"
3843 "9, 0 decrease and increase volume respectively\n"
3844 "/, * decrease and increase volume respectively\n"
3845 "a cycle audio channel in the current program\n"
3846 "v cycle video channel\n"
3847 "t cycle subtitle channel in the current program\n"
3848 "c cycle program\n"
3849 "w cycle video filters or show modes\n"
3850 "s activate frame-step mode\n"
3851 "left/right seek backward/forward by 10 seconds or a custom interval if -seek_interval is set\n"
3852 "down/up seek backward/forward 1 minute\n"
3853 "page down/page up seek to previous/next chapter or backward/forward 10 minutes if no chapters\n"
3854 "right mouse click seek to percentage in file corresponding to fraction of width\n"
3855 "left double-click toggle full screen\n"
3856 );
3857 }
3858
3859 /* Called from the main */
3860 int main(int argc, char **argv)
3861 {
3862 int flags, ret;
3863 VideoState *is;
3864
3865 init_dynload();
3866
3867 av_log_set_flags(AV_LOG_SKIP_REPEATED);
3868 parse_loglevel(argc, argv, options);
3869
3870 /* register all codecs, demux and protocols */
3871 #if CONFIG_AVDEVICE
3872 avdevice_register_all();
3873 #endif
3874 avformat_network_init();
3875
3876 signal(SIGINT , sigterm_handler); /* Interrupt (ANSI). */
3877 signal(SIGTERM, sigterm_handler); /* Termination (ANSI). */
3878
3879 show_banner(argc, argv, options);
3880
3881 ret = parse_options(NULL, argc, argv, options, opt_input_file);
3882 if (ret < 0)
3883 exit(ret == AVERROR_EXIT ? 0 : 1);
3884
3885 if (!input_filename) {
3886 show_usage();
3887 av_log(NULL, AV_LOG_FATAL, "An input file must be specified\n");
3888 av_log(NULL, AV_LOG_FATAL,
3889 "Use -h to get full help or, even better, run 'man %s'\n", program_name);
3890 exit(1);
3891 }
3892
3893 if (display_disable) {
3894 video_disable = 1;
3895 }
3896 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
3897 if (audio_disable)
3898 flags &= ~SDL_INIT_AUDIO;
3899 if (display_disable)
3900 flags &= ~SDL_INIT_VIDEO;
3901 if (SDL_Init (flags)) {
3902 av_log(NULL, AV_LOG_FATAL, "Could not initialize SDL - %s\n", SDL_GetError());
3903 av_log(NULL, AV_LOG_FATAL, "(Did you set the DISPLAY variable?)\n");
3904 exit(1);
3905 }
3906
3907 SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
3908 SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
3909
3910 if (!display_disable) {
3911 int flags = SDL_WINDOW_HIDDEN;
3912 if (alwaysontop)
3913 #if SDL_VERSION_ATLEAST(2,0,5)
3914 flags |= SDL_WINDOW_ALWAYS_ON_TOP;
3915 #else
3916 av_log(NULL, AV_LOG_WARNING, "Your SDL version doesn't support SDL_WINDOW_ALWAYS_ON_TOP. Feature will be inactive.\n");
3917 #endif
3918 if (borderless)
3919 flags |= SDL_WINDOW_BORDERLESS;
3920 else
3921 flags |= SDL_WINDOW_RESIZABLE;
3922
3923 #ifdef SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR
3924 SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0");
3925 #endif
3926 if (hwaccel && !enable_vulkan) {
3927 av_log(NULL, AV_LOG_INFO, "Enable vulkan renderer to support hwaccel %s\n", hwaccel);
3928 enable_vulkan = 1;
3929 }
3930 if (enable_vulkan) {
3931 vk_renderer = vk_get_renderer();
3932 if (vk_renderer) {
3933 #if SDL_VERSION_ATLEAST(2, 0, 6)
3934 flags |= SDL_WINDOW_VULKAN;
3935 #endif
3936 } else {
3937 av_log(NULL, AV_LOG_WARNING, "Doesn't support vulkan renderer, fallback to SDL renderer\n");
3938 enable_vulkan = 0;
3939 }
3940 }
3941 window = SDL_CreateWindow(program_name, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, default_width, default_height, flags);
3942 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
3943 if (!window) {
3944 av_log(NULL, AV_LOG_FATAL, "Failed to create window: %s", SDL_GetError());
3945 do_exit(NULL);
3946 }
3947
3948 if (vk_renderer) {
3949 AVDictionary *dict = NULL;
3950
3951 if (vulkan_params) {
3952 int ret = av_dict_parse_string(&dict, vulkan_params, "=", ":", 0);
3953 if (ret < 0) {
3954 av_log(NULL, AV_LOG_FATAL, "Failed to parse, %s\n", vulkan_params);
3955 do_exit(NULL);
3956 }
3957 }
3958 ret = vk_renderer_create(vk_renderer, window, dict);
3959 av_dict_free(&dict);
3960 if (ret < 0) {
3961 av_log(NULL, AV_LOG_FATAL, "Failed to create vulkan renderer, %s\n", av_err2str(ret));
3962 do_exit(NULL);
3963 }
3964 } else {
3965 renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
3966 if (!renderer) {
3967 av_log(NULL, AV_LOG_WARNING, "Failed to initialize a hardware accelerated renderer: %s\n", SDL_GetError());
3968 renderer = SDL_CreateRenderer(window, -1, 0);
3969 }
3970 if (renderer) {
3971 if (!SDL_GetRendererInfo(renderer, &renderer_info))
3972 av_log(NULL, AV_LOG_VERBOSE, "Initialized %s renderer.\n", renderer_info.name);
3973 }
3974 if (!renderer || !renderer_info.num_texture_formats) {
3975 av_log(NULL, AV_LOG_FATAL, "Failed to create window or renderer: %s", SDL_GetError());
3976 do_exit(NULL);
3977 }
3978 }
3979 }
3980
3981 is = stream_open(input_filename, file_iformat);
3982 if (!is) {
3983 av_log(NULL, AV_LOG_FATAL, "Failed to initialize VideoState!\n");
3984 do_exit(NULL);
3985 }
3986
3987 event_loop(is);
3988
3989 /* never returns */
3990
3991 return 0;
3992 }
3993