FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/fftools/ffplay.c
Date: 2026-09-23 01:51:16
Exec Total Coverage
Lines: 0 2464 0.0%
Functions: 0 105 0.0%
Branches: 0 1648 0.0%

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