FFmpeg coverage


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