FFmpeg coverage


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