2 * Copyright (c) 2003 Fabrice Bellard
4 * This file is part of FFmpeg.
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.
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.
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
23 * simple media player based on the FFmpeg libraries
33 #include "libavutil/avstring.h"
34 #include "libavutil/eval.h"
35 #include "libavutil/mathematics.h"
36 #include "libavutil/pixdesc.h"
37 #include "libavutil/imgutils.h"
38 #include "libavutil/dict.h"
39 #include "libavutil/parseutils.h"
40 #include "libavutil/samplefmt.h"
41 #include "libavutil/avassert.h"
42 #include "libavutil/time.h"
43 #include "libavformat/avformat.h"
44 #include "libavdevice/avdevice.h"
45 #include "libswscale/swscale.h"
46 #include "libavutil/opt.h"
47 #include "libavcodec/avfft.h"
48 #include "libswresample/swresample.h"
51 # include "libavfilter/avfilter.h"
52 # include "libavfilter/buffersink.h"
53 # include "libavfilter/buffersrc.h"
57 #include <SDL_thread.h>
63 const char program_name[] = "ffplay";
64 const int program_birth_year = 2003;
66 #define MAX_QUEUE_SIZE (15 * 1024 * 1024)
68 #define EXTERNAL_CLOCK_MIN_FRAMES 2
69 #define EXTERNAL_CLOCK_MAX_FRAMES 10
71 /* Minimum SDL audio buffer size, in samples. */
72 #define SDL_AUDIO_MIN_BUFFER_SIZE 512
73 /* Calculate actual buffer size keeping in mind not cause too frequent audio callbacks */
74 #define SDL_AUDIO_MAX_CALLBACKS_PER_SEC 30
76 /* Step size for volume control in dB */
77 #define SDL_VOLUME_STEP (0.75)
79 /* no AV sync correction is done if below the minimum AV sync threshold */
80 #define AV_SYNC_THRESHOLD_MIN 0.04
81 /* AV sync correction is done if above the maximum AV sync threshold */
82 #define AV_SYNC_THRESHOLD_MAX 0.1
83 /* If a frame duration is longer than this, it will not be duplicated to compensate AV sync */
84 #define AV_SYNC_FRAMEDUP_THRESHOLD 0.1
85 /* no AV correction is done if too big error */
86 #define AV_NOSYNC_THRESHOLD 10.0
88 /* maximum audio speed change to get correct sync */
89 #define SAMPLE_CORRECTION_PERCENT_MAX 10
91 /* external clock speed adjustment constants for realtime sources based on buffer fullness */
92 #define EXTERNAL_CLOCK_SPEED_MIN 0.900
93 #define EXTERNAL_CLOCK_SPEED_MAX 1.010
94 #define EXTERNAL_CLOCK_SPEED_STEP 0.001
96 /* we use about AUDIO_DIFF_AVG_NB A-V differences to make the average */
97 #define AUDIO_DIFF_AVG_NB 20
99 /* polls for possible required screen refresh at least this often, should be less than 1/fps */
100 #define REFRESH_RATE 0.01
102 /* NOTE: the size must be big enough to compensate the hardware audio buffersize size */
103 /* TODO: We assume that a decoded and resampled frame fits into this buffer */
104 #define SAMPLE_ARRAY_SIZE (8 * 65536)
106 #define CURSOR_HIDE_DELAY 1000000
108 #define USE_ONEPASS_SUBTITLE_RENDER 1
110 static unsigned sws_flags = SWS_BICUBIC;
112 typedef struct MyAVPacketList {
114 struct MyAVPacketList *next;
118 typedef struct PacketQueue {
119 MyAVPacketList *first_pkt, *last_pkt;
129 #define VIDEO_PICTURE_QUEUE_SIZE 3
130 #define SUBPICTURE_QUEUE_SIZE 16
131 #define SAMPLE_QUEUE_SIZE 9
132 #define FRAME_QUEUE_SIZE FFMAX(SAMPLE_QUEUE_SIZE, FFMAX(VIDEO_PICTURE_QUEUE_SIZE, SUBPICTURE_QUEUE_SIZE))
134 typedef struct AudioParams {
137 int64_t channel_layout;
138 enum AVSampleFormat fmt;
143 typedef struct Clock {
144 double pts; /* clock base */
145 double pts_drift; /* clock base minus time at which we updated the clock */
148 int serial; /* clock is based on a packet with this serial */
150 int *queue_serial; /* pointer to the current packet queue serial, used for obsolete clock detection */
153 /* Common struct for handling all types of decoded data and allocated render buffers. */
154 typedef struct Frame {
158 double pts; /* presentation timestamp for the frame */
159 double duration; /* estimated duration of the frame */
160 int64_t pos; /* byte position of the frame in the input file */
169 typedef struct FrameQueue {
170 Frame queue[FRAME_QUEUE_SIZE];
183 AV_SYNC_AUDIO_MASTER, /* default choice */
184 AV_SYNC_VIDEO_MASTER,
185 AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */
188 typedef struct Decoder {
191 AVCodecContext *avctx;
195 SDL_cond *empty_queue_cond;
197 AVRational start_pts_tb;
199 AVRational next_pts_tb;
200 SDL_Thread *decoder_tid;
203 typedef struct VideoState {
204 SDL_Thread *read_tid;
205 AVInputFormat *iformat;
210 int queue_attachments_req;
215 int read_pause_return;
236 int audio_clock_serial;
237 double audio_diff_cum; /* used for AV difference average computation */
238 double audio_diff_avg_coef;
239 double audio_diff_threshold;
240 int audio_diff_avg_count;
243 int audio_hw_buf_size;
246 unsigned int audio_buf_size; /* in bytes */
247 unsigned int audio_buf1_size;
248 int audio_buf_index; /* in bytes */
249 int audio_write_buf_size;
252 struct AudioParams audio_src;
254 struct AudioParams audio_filter_src;
256 struct AudioParams audio_tgt;
257 struct SwrContext *swr_ctx;
258 int frame_drops_early;
259 int frame_drops_late;
262 SHOW_MODE_NONE = -1, SHOW_MODE_VIDEO = 0, SHOW_MODE_WAVES, SHOW_MODE_RDFT, SHOW_MODE_NB
264 int16_t sample_array[SAMPLE_ARRAY_SIZE];
265 int sample_array_index;
269 FFTSample *rdft_data;
271 double last_vis_time;
272 SDL_Texture *vis_texture;
273 SDL_Texture *sub_texture;
274 SDL_Texture *vid_texture;
277 AVStream *subtitle_st;
278 PacketQueue subtitleq;
281 double frame_last_returned_time;
282 double frame_last_filter_delay;
286 double max_frame_duration; // maximum duration of a frame - above this, we consider the jump a timestamp discontinuity
287 struct SwsContext *img_convert_ctx;
288 struct SwsContext *sub_convert_ctx;
292 int width, height, xleft, ytop;
297 AVFilterContext *in_video_filter; // the first filter in the video chain
298 AVFilterContext *out_video_filter; // the last filter in the video chain
299 AVFilterContext *in_audio_filter; // the first filter in the audio chain
300 AVFilterContext *out_audio_filter; // the last filter in the audio chain
301 AVFilterGraph *agraph; // audio filter graph
304 int last_video_stream, last_audio_stream, last_subtitle_stream;
306 SDL_cond *continue_read_thread;
309 /* options specified by the user */
310 static AVInputFormat *file_iformat;
311 static const char *input_filename;
312 static const char *window_title;
313 static int default_width = 640;
314 static int default_height = 480;
315 static int screen_width = 0;
316 static int screen_height = 0;
317 static int screen_left = SDL_WINDOWPOS_CENTERED;
318 static int screen_top = SDL_WINDOWPOS_CENTERED;
319 static int audio_disable;
320 static int video_disable;
321 static int subtitle_disable;
322 static const char* wanted_stream_spec[AVMEDIA_TYPE_NB] = {0};
323 static int seek_by_bytes = -1;
324 static float seek_interval = 10;
325 static int display_disable;
326 static int borderless;
327 static int startup_volume = 100;
328 static int show_status = 1;
329 static int av_sync_type = AV_SYNC_AUDIO_MASTER;
330 static int64_t start_time = AV_NOPTS_VALUE;
331 static int64_t duration = AV_NOPTS_VALUE;
333 static int genpts = 0;
334 static int lowres = 0;
335 static int decoder_reorder_pts = -1;
337 static int exit_on_keydown;
338 static int exit_on_mousedown;
340 static int framedrop = -1;
341 static int infinite_buffer = -1;
342 static enum ShowMode show_mode = SHOW_MODE_NONE;
343 static const char *audio_codec_name;
344 static const char *subtitle_codec_name;
345 static const char *video_codec_name;
346 double rdftspeed = 0.02;
347 static int64_t cursor_last_shown;
348 static int cursor_hidden = 0;
350 static const char **vfilters_list = NULL;
351 static int nb_vfilters = 0;
352 static char *afilters = NULL;
354 static int autorotate = 1;
355 static int find_stream_info = 1;
357 /* current context */
358 static int is_full_screen;
359 static int64_t audio_callback_time;
361 static AVPacket flush_pkt;
363 #define FF_QUIT_EVENT (SDL_USEREVENT + 2)
365 static SDL_Window *window;
366 static SDL_Renderer *renderer;
367 static SDL_RendererInfo renderer_info = {0};
368 static SDL_AudioDeviceID audio_dev;
370 static const struct TextureFormatEntry {
371 enum AVPixelFormat format;
373 } sdl_texture_format_map[] = {
374 { AV_PIX_FMT_RGB8, SDL_PIXELFORMAT_RGB332 },
375 { AV_PIX_FMT_RGB444, SDL_PIXELFORMAT_RGB444 },
376 { AV_PIX_FMT_RGB555, SDL_PIXELFORMAT_RGB555 },
377 { AV_PIX_FMT_BGR555, SDL_PIXELFORMAT_BGR555 },
378 { AV_PIX_FMT_RGB565, SDL_PIXELFORMAT_RGB565 },
379 { AV_PIX_FMT_BGR565, SDL_PIXELFORMAT_BGR565 },
380 { AV_PIX_FMT_RGB24, SDL_PIXELFORMAT_RGB24 },
381 { AV_PIX_FMT_BGR24, SDL_PIXELFORMAT_BGR24 },
382 { AV_PIX_FMT_0RGB32, SDL_PIXELFORMAT_RGB888 },
383 { AV_PIX_FMT_0BGR32, SDL_PIXELFORMAT_BGR888 },
384 { AV_PIX_FMT_NE(RGB0, 0BGR), SDL_PIXELFORMAT_RGBX8888 },
385 { AV_PIX_FMT_NE(BGR0, 0RGB), SDL_PIXELFORMAT_BGRX8888 },
386 { AV_PIX_FMT_RGB32, SDL_PIXELFORMAT_ARGB8888 },
387 { AV_PIX_FMT_RGB32_1, SDL_PIXELFORMAT_RGBA8888 },
388 { AV_PIX_FMT_BGR32, SDL_PIXELFORMAT_ABGR8888 },
389 { AV_PIX_FMT_BGR32_1, SDL_PIXELFORMAT_BGRA8888 },
390 { AV_PIX_FMT_YUV420P, SDL_PIXELFORMAT_IYUV },
391 { AV_PIX_FMT_YUYV422, SDL_PIXELFORMAT_YUY2 },
392 { AV_PIX_FMT_UYVY422, SDL_PIXELFORMAT_UYVY },
393 { AV_PIX_FMT_NONE, SDL_PIXELFORMAT_UNKNOWN },
397 static int opt_add_vfilter(void *optctx, const char *opt, const char *arg)
399 GROW_ARRAY(vfilters_list, nb_vfilters);
400 vfilters_list[nb_vfilters - 1] = arg;
406 int cmp_audio_fmts(enum AVSampleFormat fmt1, int64_t channel_count1,
407 enum AVSampleFormat fmt2, int64_t channel_count2)
409 /* If channel count == 1, planar and non-planar formats are the same */
410 if (channel_count1 == 1 && channel_count2 == 1)
411 return av_get_packed_sample_fmt(fmt1) != av_get_packed_sample_fmt(fmt2);
413 return channel_count1 != channel_count2 || fmt1 != fmt2;
417 int64_t get_valid_channel_layout(int64_t channel_layout, int channels)
419 if (channel_layout && av_get_channel_layout_nb_channels(channel_layout) == channels)
420 return channel_layout;
425 static int packet_queue_put_private(PacketQueue *q, AVPacket *pkt)
427 MyAVPacketList *pkt1;
429 if (q->abort_request)
432 pkt1 = av_malloc(sizeof(MyAVPacketList));
437 if (pkt == &flush_pkt)
439 pkt1->serial = q->serial;
444 q->last_pkt->next = pkt1;
447 q->size += pkt1->pkt.size + sizeof(*pkt1);
448 q->duration += pkt1->pkt.duration;
449 /* XXX: should duplicate packet data in DV case */
450 SDL_CondSignal(q->cond);
454 static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
458 SDL_LockMutex(q->mutex);
459 ret = packet_queue_put_private(q, pkt);
460 SDL_UnlockMutex(q->mutex);
462 if (pkt != &flush_pkt && ret < 0)
463 av_packet_unref(pkt);
468 static int packet_queue_put_nullpacket(PacketQueue *q, int stream_index)
470 AVPacket pkt1, *pkt = &pkt1;
474 pkt->stream_index = stream_index;
475 return packet_queue_put(q, pkt);
478 /* packet queue handling */
479 static int packet_queue_init(PacketQueue *q)
481 memset(q, 0, sizeof(PacketQueue));
482 q->mutex = SDL_CreateMutex();
484 av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError());
485 return AVERROR(ENOMEM);
487 q->cond = SDL_CreateCond();
489 av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError());
490 return AVERROR(ENOMEM);
492 q->abort_request = 1;
496 static void packet_queue_flush(PacketQueue *q)
498 MyAVPacketList *pkt, *pkt1;
500 SDL_LockMutex(q->mutex);
501 for (pkt = q->first_pkt; pkt; pkt = pkt1) {
503 av_packet_unref(&pkt->pkt);
511 SDL_UnlockMutex(q->mutex);
514 static void packet_queue_destroy(PacketQueue *q)
516 packet_queue_flush(q);
517 SDL_DestroyMutex(q->mutex);
518 SDL_DestroyCond(q->cond);
521 static void packet_queue_abort(PacketQueue *q)
523 SDL_LockMutex(q->mutex);
525 q->abort_request = 1;
527 SDL_CondSignal(q->cond);
529 SDL_UnlockMutex(q->mutex);
532 static void packet_queue_start(PacketQueue *q)
534 SDL_LockMutex(q->mutex);
535 q->abort_request = 0;
536 packet_queue_put_private(q, &flush_pkt);
537 SDL_UnlockMutex(q->mutex);
540 /* return < 0 if aborted, 0 if no packet and > 0 if packet. */
541 static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block, int *serial)
543 MyAVPacketList *pkt1;
546 SDL_LockMutex(q->mutex);
549 if (q->abort_request) {
556 q->first_pkt = pkt1->next;
560 q->size -= pkt1->pkt.size + sizeof(*pkt1);
561 q->duration -= pkt1->pkt.duration;
564 *serial = pkt1->serial;
572 SDL_CondWait(q->cond, q->mutex);
575 SDL_UnlockMutex(q->mutex);
579 static void decoder_init(Decoder *d, AVCodecContext *avctx, PacketQueue *queue, SDL_cond *empty_queue_cond) {
580 memset(d, 0, sizeof(Decoder));
583 d->empty_queue_cond = empty_queue_cond;
584 d->start_pts = AV_NOPTS_VALUE;
588 static int decoder_decode_frame(Decoder *d, AVFrame *frame, AVSubtitle *sub) {
589 int ret = AVERROR(EAGAIN);
594 if (d->queue->serial == d->pkt_serial) {
596 if (d->queue->abort_request)
599 switch (d->avctx->codec_type) {
600 case AVMEDIA_TYPE_VIDEO:
601 ret = avcodec_receive_frame(d->avctx, frame);
603 if (decoder_reorder_pts == -1) {
604 frame->pts = frame->best_effort_timestamp;
605 } else if (!decoder_reorder_pts) {
606 frame->pts = frame->pkt_dts;
610 case AVMEDIA_TYPE_AUDIO:
611 ret = avcodec_receive_frame(d->avctx, frame);
613 AVRational tb = (AVRational){1, frame->sample_rate};
614 if (frame->pts != AV_NOPTS_VALUE)
615 frame->pts = av_rescale_q(frame->pts, d->avctx->pkt_timebase, tb);
616 else if (d->next_pts != AV_NOPTS_VALUE)
617 frame->pts = av_rescale_q(d->next_pts, d->next_pts_tb, tb);
618 if (frame->pts != AV_NOPTS_VALUE) {
619 d->next_pts = frame->pts + frame->nb_samples;
625 if (ret == AVERROR_EOF) {
626 d->finished = d->pkt_serial;
627 avcodec_flush_buffers(d->avctx);
632 } while (ret != AVERROR(EAGAIN));
636 if (d->queue->nb_packets == 0)
637 SDL_CondSignal(d->empty_queue_cond);
638 if (d->packet_pending) {
639 av_packet_move_ref(&pkt, &d->pkt);
640 d->packet_pending = 0;
642 if (packet_queue_get(d->queue, &pkt, 1, &d->pkt_serial) < 0)
645 } while (d->queue->serial != d->pkt_serial);
647 if (pkt.data == flush_pkt.data) {
648 avcodec_flush_buffers(d->avctx);
650 d->next_pts = d->start_pts;
651 d->next_pts_tb = d->start_pts_tb;
653 if (d->avctx->codec_type == AVMEDIA_TYPE_SUBTITLE) {
655 ret = avcodec_decode_subtitle2(d->avctx, sub, &got_frame, &pkt);
657 ret = AVERROR(EAGAIN);
659 if (got_frame && !pkt.data) {
660 d->packet_pending = 1;
661 av_packet_move_ref(&d->pkt, &pkt);
663 ret = got_frame ? 0 : (pkt.data ? AVERROR(EAGAIN) : AVERROR_EOF);
666 if (avcodec_send_packet(d->avctx, &pkt) == AVERROR(EAGAIN)) {
667 av_log(d->avctx, AV_LOG_ERROR, "Receive_frame and send_packet both returned EAGAIN, which is an API violation.\n");
668 d->packet_pending = 1;
669 av_packet_move_ref(&d->pkt, &pkt);
672 av_packet_unref(&pkt);
677 static void decoder_destroy(Decoder *d) {
678 av_packet_unref(&d->pkt);
679 avcodec_free_context(&d->avctx);
682 static void frame_queue_unref_item(Frame *vp)
684 av_frame_unref(vp->frame);
685 avsubtitle_free(&vp->sub);
688 static int frame_queue_init(FrameQueue *f, PacketQueue *pktq, int max_size, int keep_last)
691 memset(f, 0, sizeof(FrameQueue));
692 if (!(f->mutex = SDL_CreateMutex())) {
693 av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError());
694 return AVERROR(ENOMEM);
696 if (!(f->cond = SDL_CreateCond())) {
697 av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError());
698 return AVERROR(ENOMEM);
701 f->max_size = FFMIN(max_size, FRAME_QUEUE_SIZE);
702 f->keep_last = !!keep_last;
703 for (i = 0; i < f->max_size; i++)
704 if (!(f->queue[i].frame = av_frame_alloc()))
705 return AVERROR(ENOMEM);
709 static void frame_queue_destory(FrameQueue *f)
712 for (i = 0; i < f->max_size; i++) {
713 Frame *vp = &f->queue[i];
714 frame_queue_unref_item(vp);
715 av_frame_free(&vp->frame);
717 SDL_DestroyMutex(f->mutex);
718 SDL_DestroyCond(f->cond);
721 static void frame_queue_signal(FrameQueue *f)
723 SDL_LockMutex(f->mutex);
724 SDL_CondSignal(f->cond);
725 SDL_UnlockMutex(f->mutex);
728 static Frame *frame_queue_peek(FrameQueue *f)
730 return &f->queue[(f->rindex + f->rindex_shown) % f->max_size];
733 static Frame *frame_queue_peek_next(FrameQueue *f)
735 return &f->queue[(f->rindex + f->rindex_shown + 1) % f->max_size];
738 static Frame *frame_queue_peek_last(FrameQueue *f)
740 return &f->queue[f->rindex];
743 static Frame *frame_queue_peek_writable(FrameQueue *f)
745 /* wait until we have space to put a new frame */
746 SDL_LockMutex(f->mutex);
747 while (f->size >= f->max_size &&
748 !f->pktq->abort_request) {
749 SDL_CondWait(f->cond, f->mutex);
751 SDL_UnlockMutex(f->mutex);
753 if (f->pktq->abort_request)
756 return &f->queue[f->windex];
759 static Frame *frame_queue_peek_readable(FrameQueue *f)
761 /* wait until we have a readable a new frame */
762 SDL_LockMutex(f->mutex);
763 while (f->size - f->rindex_shown <= 0 &&
764 !f->pktq->abort_request) {
765 SDL_CondWait(f->cond, f->mutex);
767 SDL_UnlockMutex(f->mutex);
769 if (f->pktq->abort_request)
772 return &f->queue[(f->rindex + f->rindex_shown) % f->max_size];
775 static void frame_queue_push(FrameQueue *f)
777 if (++f->windex == f->max_size)
779 SDL_LockMutex(f->mutex);
781 SDL_CondSignal(f->cond);
782 SDL_UnlockMutex(f->mutex);
785 static void frame_queue_next(FrameQueue *f)
787 if (f->keep_last && !f->rindex_shown) {
791 frame_queue_unref_item(&f->queue[f->rindex]);
792 if (++f->rindex == f->max_size)
794 SDL_LockMutex(f->mutex);
796 SDL_CondSignal(f->cond);
797 SDL_UnlockMutex(f->mutex);
800 /* return the number of undisplayed frames in the queue */
801 static int frame_queue_nb_remaining(FrameQueue *f)
803 return f->size - f->rindex_shown;
806 /* return last shown position */
807 static int64_t frame_queue_last_pos(FrameQueue *f)
809 Frame *fp = &f->queue[f->rindex];
810 if (f->rindex_shown && fp->serial == f->pktq->serial)
816 static void decoder_abort(Decoder *d, FrameQueue *fq)
818 packet_queue_abort(d->queue);
819 frame_queue_signal(fq);
820 SDL_WaitThread(d->decoder_tid, NULL);
821 d->decoder_tid = NULL;
822 packet_queue_flush(d->queue);
825 static inline void fill_rectangle(int x, int y, int w, int h)
833 SDL_RenderFillRect(renderer, &rect);
836 static int realloc_texture(SDL_Texture **texture, Uint32 new_format, int new_width, int new_height, SDL_BlendMode blendmode, int init_texture)
840 if (!*texture || SDL_QueryTexture(*texture, &format, &access, &w, &h) < 0 || new_width != w || new_height != h || new_format != format) {
844 SDL_DestroyTexture(*texture);
845 if (!(*texture = SDL_CreateTexture(renderer, new_format, SDL_TEXTUREACCESS_STREAMING, new_width, new_height)))
847 if (SDL_SetTextureBlendMode(*texture, blendmode) < 0)
850 if (SDL_LockTexture(*texture, NULL, &pixels, &pitch) < 0)
852 memset(pixels, 0, pitch * new_height);
853 SDL_UnlockTexture(*texture);
855 av_log(NULL, AV_LOG_VERBOSE, "Created %dx%d texture with %s.\n", new_width, new_height, SDL_GetPixelFormatName(new_format));
860 static void calculate_display_rect(SDL_Rect *rect,
861 int scr_xleft, int scr_ytop, int scr_width, int scr_height,
862 int pic_width, int pic_height, AVRational pic_sar)
865 int width, height, x, y;
867 if (pic_sar.num == 0)
870 aspect_ratio = av_q2d(pic_sar);
872 if (aspect_ratio <= 0.0)
874 aspect_ratio *= (float)pic_width / (float)pic_height;
876 /* XXX: we suppose the screen has a 1.0 pixel ratio */
878 width = lrint(height * aspect_ratio) & ~1;
879 if (width > scr_width) {
881 height = lrint(width / aspect_ratio) & ~1;
883 x = (scr_width - width) / 2;
884 y = (scr_height - height) / 2;
885 rect->x = scr_xleft + x;
886 rect->y = scr_ytop + y;
887 rect->w = FFMAX(width, 1);
888 rect->h = FFMAX(height, 1);
891 static void get_sdl_pix_fmt_and_blendmode(int format, Uint32 *sdl_pix_fmt, SDL_BlendMode *sdl_blendmode)
894 *sdl_blendmode = SDL_BLENDMODE_NONE;
895 *sdl_pix_fmt = SDL_PIXELFORMAT_UNKNOWN;
896 if (format == AV_PIX_FMT_RGB32 ||
897 format == AV_PIX_FMT_RGB32_1 ||
898 format == AV_PIX_FMT_BGR32 ||
899 format == AV_PIX_FMT_BGR32_1)
900 *sdl_blendmode = SDL_BLENDMODE_BLEND;
901 for (i = 0; i < FF_ARRAY_ELEMS(sdl_texture_format_map) - 1; i++) {
902 if (format == sdl_texture_format_map[i].format) {
903 *sdl_pix_fmt = sdl_texture_format_map[i].texture_fmt;
909 static int upload_texture(SDL_Texture **tex, AVFrame *frame, struct SwsContext **img_convert_ctx) {
912 SDL_BlendMode sdl_blendmode;
913 get_sdl_pix_fmt_and_blendmode(frame->format, &sdl_pix_fmt, &sdl_blendmode);
914 if (realloc_texture(tex, sdl_pix_fmt == SDL_PIXELFORMAT_UNKNOWN ? SDL_PIXELFORMAT_ARGB8888 : sdl_pix_fmt, frame->width, frame->height, sdl_blendmode, 0) < 0)
916 switch (sdl_pix_fmt) {
917 case SDL_PIXELFORMAT_UNKNOWN:
918 /* This should only happen if we are not using avfilter... */
919 *img_convert_ctx = sws_getCachedContext(*img_convert_ctx,
920 frame->width, frame->height, frame->format, frame->width, frame->height,
921 AV_PIX_FMT_BGRA, sws_flags, NULL, NULL, NULL);
922 if (*img_convert_ctx != NULL) {
925 if (!SDL_LockTexture(*tex, NULL, (void **)pixels, pitch)) {
926 sws_scale(*img_convert_ctx, (const uint8_t * const *)frame->data, frame->linesize,
927 0, frame->height, pixels, pitch);
928 SDL_UnlockTexture(*tex);
931 av_log(NULL, AV_LOG_FATAL, "Cannot initialize the conversion context\n");
935 case SDL_PIXELFORMAT_IYUV:
936 if (frame->linesize[0] > 0 && frame->linesize[1] > 0 && frame->linesize[2] > 0) {
937 ret = SDL_UpdateYUVTexture(*tex, NULL, frame->data[0], frame->linesize[0],
938 frame->data[1], frame->linesize[1],
939 frame->data[2], frame->linesize[2]);
940 } else if (frame->linesize[0] < 0 && frame->linesize[1] < 0 && frame->linesize[2] < 0) {
941 ret = SDL_UpdateYUVTexture(*tex, NULL, frame->data[0] + frame->linesize[0] * (frame->height - 1), -frame->linesize[0],
942 frame->data[1] + frame->linesize[1] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[1],
943 frame->data[2] + frame->linesize[2] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[2]);
945 av_log(NULL, AV_LOG_ERROR, "Mixed negative and positive linesizes are not supported.\n");
950 if (frame->linesize[0] < 0) {
951 ret = SDL_UpdateTexture(*tex, NULL, frame->data[0] + frame->linesize[0] * (frame->height - 1), -frame->linesize[0]);
953 ret = SDL_UpdateTexture(*tex, NULL, frame->data[0], frame->linesize[0]);
960 static void set_sdl_yuv_conversion_mode(AVFrame *frame)
962 #if SDL_VERSION_ATLEAST(2,0,8)
963 SDL_YUV_CONVERSION_MODE mode = SDL_YUV_CONVERSION_AUTOMATIC;
964 if (frame && (frame->format == AV_PIX_FMT_YUV420P || frame->format == AV_PIX_FMT_YUYV422 || frame->format == AV_PIX_FMT_UYVY422)) {
965 if (frame->color_range == AVCOL_RANGE_JPEG)
966 mode = SDL_YUV_CONVERSION_JPEG;
967 else if (frame->colorspace == AVCOL_SPC_BT709)
968 mode = SDL_YUV_CONVERSION_BT709;
969 else if (frame->colorspace == AVCOL_SPC_BT470BG || frame->colorspace == AVCOL_SPC_SMPTE170M || frame->colorspace == AVCOL_SPC_SMPTE240M)
970 mode = SDL_YUV_CONVERSION_BT601;
972 SDL_SetYUVConversionMode(mode);
976 static void video_image_display(VideoState *is)
982 vp = frame_queue_peek_last(&is->pictq);
983 if (is->subtitle_st) {
984 if (frame_queue_nb_remaining(&is->subpq) > 0) {
985 sp = frame_queue_peek(&is->subpq);
987 if (vp->pts >= sp->pts + ((float) sp->sub.start_display_time / 1000)) {
992 if (!sp->width || !sp->height) {
993 sp->width = vp->width;
994 sp->height = vp->height;
996 if (realloc_texture(&is->sub_texture, SDL_PIXELFORMAT_ARGB8888, sp->width, sp->height, SDL_BLENDMODE_BLEND, 1) < 0)
999 for (i = 0; i < sp->sub.num_rects; i++) {
1000 AVSubtitleRect *sub_rect = sp->sub.rects[i];
1002 sub_rect->x = av_clip(sub_rect->x, 0, sp->width );
1003 sub_rect->y = av_clip(sub_rect->y, 0, sp->height);
1004 sub_rect->w = av_clip(sub_rect->w, 0, sp->width - sub_rect->x);
1005 sub_rect->h = av_clip(sub_rect->h, 0, sp->height - sub_rect->y);
1007 is->sub_convert_ctx = sws_getCachedContext(is->sub_convert_ctx,
1008 sub_rect->w, sub_rect->h, AV_PIX_FMT_PAL8,
1009 sub_rect->w, sub_rect->h, AV_PIX_FMT_BGRA,
1010 0, NULL, NULL, NULL);
1011 if (!is->sub_convert_ctx) {
1012 av_log(NULL, AV_LOG_FATAL, "Cannot initialize the conversion context\n");
1015 if (!SDL_LockTexture(is->sub_texture, (SDL_Rect *)sub_rect, (void **)pixels, pitch)) {
1016 sws_scale(is->sub_convert_ctx, (const uint8_t * const *)sub_rect->data, sub_rect->linesize,
1017 0, sub_rect->h, pixels, pitch);
1018 SDL_UnlockTexture(is->sub_texture);
1028 calculate_display_rect(&rect, is->xleft, is->ytop, is->width, is->height, vp->width, vp->height, vp->sar);
1030 if (!vp->uploaded) {
1031 if (upload_texture(&is->vid_texture, vp->frame, &is->img_convert_ctx) < 0)
1034 vp->flip_v = vp->frame->linesize[0] < 0;
1037 set_sdl_yuv_conversion_mode(vp->frame);
1038 SDL_RenderCopyEx(renderer, is->vid_texture, NULL, &rect, 0, NULL, vp->flip_v ? SDL_FLIP_VERTICAL : 0);
1039 set_sdl_yuv_conversion_mode(NULL);
1041 #if USE_ONEPASS_SUBTITLE_RENDER
1042 SDL_RenderCopy(renderer, is->sub_texture, NULL, &rect);
1045 double xratio = (double)rect.w / (double)sp->width;
1046 double yratio = (double)rect.h / (double)sp->height;
1047 for (i = 0; i < sp->sub.num_rects; i++) {
1048 SDL_Rect *sub_rect = (SDL_Rect*)sp->sub.rects[i];
1049 SDL_Rect target = {.x = rect.x + sub_rect->x * xratio,
1050 .y = rect.y + sub_rect->y * yratio,
1051 .w = sub_rect->w * xratio,
1052 .h = sub_rect->h * yratio};
1053 SDL_RenderCopy(renderer, is->sub_texture, sub_rect, &target);
1059 static inline int compute_mod(int a, int b)
1061 return a < 0 ? a%b + b : a%b;
1064 static void video_audio_display(VideoState *s)
1066 int i, i_start, x, y1, y, ys, delay, n, nb_display_channels;
1067 int ch, channels, h, h2;
1069 int rdft_bits, nb_freq;
1071 for (rdft_bits = 1; (1 << rdft_bits) < 2 * s->height; rdft_bits++)
1073 nb_freq = 1 << (rdft_bits - 1);
1075 /* compute display index : center on currently output samples */
1076 channels = s->audio_tgt.channels;
1077 nb_display_channels = channels;
1079 int data_used= s->show_mode == SHOW_MODE_WAVES ? s->width : (2*nb_freq);
1081 delay = s->audio_write_buf_size;
1084 /* to be more precise, we take into account the time spent since
1085 the last buffer computation */
1086 if (audio_callback_time) {
1087 time_diff = av_gettime_relative() - audio_callback_time;
1088 delay -= (time_diff * s->audio_tgt.freq) / 1000000;
1091 delay += 2 * data_used;
1092 if (delay < data_used)
1095 i_start= x = compute_mod(s->sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE);
1096 if (s->show_mode == SHOW_MODE_WAVES) {
1098 for (i = 0; i < 1000; i += channels) {
1099 int idx = (SAMPLE_ARRAY_SIZE + x - i) % SAMPLE_ARRAY_SIZE;
1100 int a = s->sample_array[idx];
1101 int b = s->sample_array[(idx + 4 * channels) % SAMPLE_ARRAY_SIZE];
1102 int c = s->sample_array[(idx + 5 * channels) % SAMPLE_ARRAY_SIZE];
1103 int d = s->sample_array[(idx + 9 * channels) % SAMPLE_ARRAY_SIZE];
1105 if (h < score && (b ^ c) < 0) {
1112 s->last_i_start = i_start;
1114 i_start = s->last_i_start;
1117 if (s->show_mode == SHOW_MODE_WAVES) {
1118 SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
1120 /* total height for one channel */
1121 h = s->height / nb_display_channels;
1122 /* graph height / 2 */
1124 for (ch = 0; ch < nb_display_channels; ch++) {
1126 y1 = s->ytop + ch * h + (h / 2); /* position of center line */
1127 for (x = 0; x < s->width; x++) {
1128 y = (s->sample_array[i] * h2) >> 15;
1135 fill_rectangle(s->xleft + x, ys, 1, y);
1137 if (i >= SAMPLE_ARRAY_SIZE)
1138 i -= SAMPLE_ARRAY_SIZE;
1142 SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
1144 for (ch = 1; ch < nb_display_channels; ch++) {
1145 y = s->ytop + ch * h;
1146 fill_rectangle(s->xleft, y, s->width, 1);
1149 if (realloc_texture(&s->vis_texture, SDL_PIXELFORMAT_ARGB8888, s->width, s->height, SDL_BLENDMODE_NONE, 1) < 0)
1152 nb_display_channels= FFMIN(nb_display_channels, 2);
1153 if (rdft_bits != s->rdft_bits) {
1154 av_rdft_end(s->rdft);
1155 av_free(s->rdft_data);
1156 s->rdft = av_rdft_init(rdft_bits, DFT_R2C);
1157 s->rdft_bits = rdft_bits;
1158 s->rdft_data = av_malloc_array(nb_freq, 4 *sizeof(*s->rdft_data));
1160 if (!s->rdft || !s->rdft_data){
1161 av_log(NULL, AV_LOG_ERROR, "Failed to allocate buffers for RDFT, switching to waves display\n");
1162 s->show_mode = SHOW_MODE_WAVES;
1165 SDL_Rect rect = {.x = s->xpos, .y = 0, .w = 1, .h = s->height};
1168 for (ch = 0; ch < nb_display_channels; ch++) {
1169 data[ch] = s->rdft_data + 2 * nb_freq * ch;
1171 for (x = 0; x < 2 * nb_freq; x++) {
1172 double w = (x-nb_freq) * (1.0 / nb_freq);
1173 data[ch][x] = s->sample_array[i] * (1.0 - w * w);
1175 if (i >= SAMPLE_ARRAY_SIZE)
1176 i -= SAMPLE_ARRAY_SIZE;
1178 av_rdft_calc(s->rdft, data[ch]);
1180 /* Least efficient way to do this, we should of course
1181 * directly access it but it is more than fast enough. */
1182 if (!SDL_LockTexture(s->vis_texture, &rect, (void **)&pixels, &pitch)) {
1184 pixels += pitch * s->height;
1185 for (y = 0; y < s->height; y++) {
1186 double w = 1 / sqrt(nb_freq);
1187 int a = sqrt(w * sqrt(data[0][2 * y + 0] * data[0][2 * y + 0] + data[0][2 * y + 1] * data[0][2 * y + 1]));
1188 int b = (nb_display_channels == 2 ) ? sqrt(w * hypot(data[1][2 * y + 0], data[1][2 * y + 1]))
1193 *pixels = (a << 16) + (b << 8) + ((a+b) >> 1);
1195 SDL_UnlockTexture(s->vis_texture);
1197 SDL_RenderCopy(renderer, s->vis_texture, NULL, NULL);
1201 if (s->xpos >= s->width)
1206 static void stream_component_close(VideoState *is, int stream_index)
1208 AVFormatContext *ic = is->ic;
1209 AVCodecParameters *codecpar;
1211 if (stream_index < 0 || stream_index >= ic->nb_streams)
1213 codecpar = ic->streams[stream_index]->codecpar;
1215 switch (codecpar->codec_type) {
1216 case AVMEDIA_TYPE_AUDIO:
1217 decoder_abort(&is->auddec, &is->sampq);
1218 SDL_CloseAudioDevice(audio_dev);
1219 decoder_destroy(&is->auddec);
1220 swr_free(&is->swr_ctx);
1221 av_freep(&is->audio_buf1);
1222 is->audio_buf1_size = 0;
1223 is->audio_buf = NULL;
1226 av_rdft_end(is->rdft);
1227 av_freep(&is->rdft_data);
1232 case AVMEDIA_TYPE_VIDEO:
1233 decoder_abort(&is->viddec, &is->pictq);
1234 decoder_destroy(&is->viddec);
1236 case AVMEDIA_TYPE_SUBTITLE:
1237 decoder_abort(&is->subdec, &is->subpq);
1238 decoder_destroy(&is->subdec);
1244 ic->streams[stream_index]->discard = AVDISCARD_ALL;
1245 switch (codecpar->codec_type) {
1246 case AVMEDIA_TYPE_AUDIO:
1247 is->audio_st = NULL;
1248 is->audio_stream = -1;
1250 case AVMEDIA_TYPE_VIDEO:
1251 is->video_st = NULL;
1252 is->video_stream = -1;
1254 case AVMEDIA_TYPE_SUBTITLE:
1255 is->subtitle_st = NULL;
1256 is->subtitle_stream = -1;
1263 static void stream_close(VideoState *is)
1265 /* XXX: use a special url_shutdown call to abort parse cleanly */
1266 is->abort_request = 1;
1267 SDL_WaitThread(is->read_tid, NULL);
1269 /* close each stream */
1270 if (is->audio_stream >= 0)
1271 stream_component_close(is, is->audio_stream);
1272 if (is->video_stream >= 0)
1273 stream_component_close(is, is->video_stream);
1274 if (is->subtitle_stream >= 0)
1275 stream_component_close(is, is->subtitle_stream);
1277 avformat_close_input(&is->ic);
1279 packet_queue_destroy(&is->videoq);
1280 packet_queue_destroy(&is->audioq);
1281 packet_queue_destroy(&is->subtitleq);
1283 /* free all pictures */
1284 frame_queue_destory(&is->pictq);
1285 frame_queue_destory(&is->sampq);
1286 frame_queue_destory(&is->subpq);
1287 SDL_DestroyCond(is->continue_read_thread);
1288 sws_freeContext(is->img_convert_ctx);
1289 sws_freeContext(is->sub_convert_ctx);
1290 av_free(is->filename);
1291 if (is->vis_texture)
1292 SDL_DestroyTexture(is->vis_texture);
1293 if (is->vid_texture)
1294 SDL_DestroyTexture(is->vid_texture);
1295 if (is->sub_texture)
1296 SDL_DestroyTexture(is->sub_texture);
1300 static void do_exit(VideoState *is)
1306 SDL_DestroyRenderer(renderer);
1308 SDL_DestroyWindow(window);
1311 av_freep(&vfilters_list);
1313 avformat_network_deinit();
1317 av_log(NULL, AV_LOG_QUIET, "%s", "");
1321 static void sigterm_handler(int sig)
1326 static void set_default_window_size(int width, int height, AVRational sar)
1329 calculate_display_rect(&rect, 0, 0, INT_MAX, height, width, height, sar);
1330 default_width = rect.w;
1331 default_height = rect.h;
1334 static int video_open(VideoState *is)
1347 window_title = input_filename;
1348 SDL_SetWindowTitle(window, window_title);
1350 SDL_SetWindowSize(window, w, h);
1351 SDL_SetWindowPosition(window, screen_left, screen_top);
1353 SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
1354 SDL_ShowWindow(window);
1362 /* display the current picture, if any */
1363 static void video_display(VideoState *is)
1368 SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
1369 SDL_RenderClear(renderer);
1370 if (is->audio_st && is->show_mode != SHOW_MODE_VIDEO)
1371 video_audio_display(is);
1372 else if (is->video_st)
1373 video_image_display(is);
1374 SDL_RenderPresent(renderer);
1377 static double get_clock(Clock *c)
1379 if (*c->queue_serial != c->serial)
1384 double time = av_gettime_relative() / 1000000.0;
1385 return c->pts_drift + time - (time - c->last_updated) * (1.0 - c->speed);
1389 static void set_clock_at(Clock *c, double pts, int serial, double time)
1392 c->last_updated = time;
1393 c->pts_drift = c->pts - time;
1397 static void set_clock(Clock *c, double pts, int serial)
1399 double time = av_gettime_relative() / 1000000.0;
1400 set_clock_at(c, pts, serial, time);
1403 static void set_clock_speed(Clock *c, double speed)
1405 set_clock(c, get_clock(c), c->serial);
1409 static void init_clock(Clock *c, int *queue_serial)
1413 c->queue_serial = queue_serial;
1414 set_clock(c, NAN, -1);
1417 static void sync_clock_to_slave(Clock *c, Clock *slave)
1419 double clock = get_clock(c);
1420 double slave_clock = get_clock(slave);
1421 if (!isnan(slave_clock) && (isnan(clock) || fabs(clock - slave_clock) > AV_NOSYNC_THRESHOLD))
1422 set_clock(c, slave_clock, slave->serial);
1425 static int get_master_sync_type(VideoState *is) {
1426 if (is->av_sync_type == AV_SYNC_VIDEO_MASTER) {
1428 return AV_SYNC_VIDEO_MASTER;
1430 return AV_SYNC_AUDIO_MASTER;
1431 } else if (is->av_sync_type == AV_SYNC_AUDIO_MASTER) {
1433 return AV_SYNC_AUDIO_MASTER;
1435 return AV_SYNC_EXTERNAL_CLOCK;
1437 return AV_SYNC_EXTERNAL_CLOCK;
1441 /* get the current master clock value */
1442 static double get_master_clock(VideoState *is)
1446 switch (get_master_sync_type(is)) {
1447 case AV_SYNC_VIDEO_MASTER:
1448 val = get_clock(&is->vidclk);
1450 case AV_SYNC_AUDIO_MASTER:
1451 val = get_clock(&is->audclk);
1454 val = get_clock(&is->extclk);
1460 static void check_external_clock_speed(VideoState *is) {
1461 if (is->video_stream >= 0 && is->videoq.nb_packets <= EXTERNAL_CLOCK_MIN_FRAMES ||
1462 is->audio_stream >= 0 && is->audioq.nb_packets <= EXTERNAL_CLOCK_MIN_FRAMES) {
1463 set_clock_speed(&is->extclk, FFMAX(EXTERNAL_CLOCK_SPEED_MIN, is->extclk.speed - EXTERNAL_CLOCK_SPEED_STEP));
1464 } else if ((is->video_stream < 0 || is->videoq.nb_packets > EXTERNAL_CLOCK_MAX_FRAMES) &&
1465 (is->audio_stream < 0 || is->audioq.nb_packets > EXTERNAL_CLOCK_MAX_FRAMES)) {
1466 set_clock_speed(&is->extclk, FFMIN(EXTERNAL_CLOCK_SPEED_MAX, is->extclk.speed + EXTERNAL_CLOCK_SPEED_STEP));
1468 double speed = is->extclk.speed;
1470 set_clock_speed(&is->extclk, speed + EXTERNAL_CLOCK_SPEED_STEP * (1.0 - speed) / fabs(1.0 - speed));
1474 /* seek in the stream */
1475 static void stream_seek(VideoState *is, int64_t pos, int64_t rel, int seek_by_bytes)
1477 if (!is->seek_req) {
1480 is->seek_flags &= ~AVSEEK_FLAG_BYTE;
1482 is->seek_flags |= AVSEEK_FLAG_BYTE;
1484 SDL_CondSignal(is->continue_read_thread);
1488 /* pause or resume the video */
1489 static void stream_toggle_pause(VideoState *is)
1492 is->frame_timer += av_gettime_relative() / 1000000.0 - is->vidclk.last_updated;
1493 if (is->read_pause_return != AVERROR(ENOSYS)) {
1494 is->vidclk.paused = 0;
1496 set_clock(&is->vidclk, get_clock(&is->vidclk), is->vidclk.serial);
1498 set_clock(&is->extclk, get_clock(&is->extclk), is->extclk.serial);
1499 is->paused = is->audclk.paused = is->vidclk.paused = is->extclk.paused = !is->paused;
1502 static void toggle_pause(VideoState *is)
1504 stream_toggle_pause(is);
1508 static void toggle_mute(VideoState *is)
1510 is->muted = !is->muted;
1513 static void update_volume(VideoState *is, int sign, double step)
1515 double volume_level = is->audio_volume ? (20 * log(is->audio_volume / (double)SDL_MIX_MAXVOLUME) / log(10)) : -1000.0;
1516 int new_volume = lrint(SDL_MIX_MAXVOLUME * pow(10.0, (volume_level + sign * step) / 20.0));
1517 is->audio_volume = av_clip(is->audio_volume == new_volume ? (is->audio_volume + sign) : new_volume, 0, SDL_MIX_MAXVOLUME);
1520 static void step_to_next_frame(VideoState *is)
1522 /* if the stream is paused unpause it, then step */
1524 stream_toggle_pause(is);
1528 static double compute_target_delay(double delay, VideoState *is)
1530 double sync_threshold, diff = 0;
1532 /* update delay to follow master synchronisation source */
1533 if (get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER) {
1534 /* if video is slave, we try to correct big delays by
1535 duplicating or deleting a frame */
1536 diff = get_clock(&is->vidclk) - get_master_clock(is);
1538 /* skip or repeat frame. We take into account the
1539 delay to compute the threshold. I still don't know
1540 if it is the best guess */
1541 sync_threshold = FFMAX(AV_SYNC_THRESHOLD_MIN, FFMIN(AV_SYNC_THRESHOLD_MAX, delay));
1542 if (!isnan(diff) && fabs(diff) < is->max_frame_duration) {
1543 if (diff <= -sync_threshold)
1544 delay = FFMAX(0, delay + diff);
1545 else if (diff >= sync_threshold && delay > AV_SYNC_FRAMEDUP_THRESHOLD)
1546 delay = delay + diff;
1547 else if (diff >= sync_threshold)
1552 av_log(NULL, AV_LOG_TRACE, "video: delay=%0.3f A-V=%f\n",
1558 static double vp_duration(VideoState *is, Frame *vp, Frame *nextvp) {
1559 if (vp->serial == nextvp->serial) {
1560 double duration = nextvp->pts - vp->pts;
1561 if (isnan(duration) || duration <= 0 || duration > is->max_frame_duration)
1562 return vp->duration;
1570 static void update_video_pts(VideoState *is, double pts, int64_t pos, int serial) {
1571 /* update current video pts */
1572 set_clock(&is->vidclk, pts, serial);
1573 sync_clock_to_slave(&is->extclk, &is->vidclk);
1576 /* called to display each frame */
1577 static void video_refresh(void *opaque, double *remaining_time)
1579 VideoState *is = opaque;
1584 if (!is->paused && get_master_sync_type(is) == AV_SYNC_EXTERNAL_CLOCK && is->realtime)
1585 check_external_clock_speed(is);
1587 if (!display_disable && is->show_mode != SHOW_MODE_VIDEO && is->audio_st) {
1588 time = av_gettime_relative() / 1000000.0;
1589 if (is->force_refresh || is->last_vis_time + rdftspeed < time) {
1591 is->last_vis_time = time;
1593 *remaining_time = FFMIN(*remaining_time, is->last_vis_time + rdftspeed - time);
1598 if (frame_queue_nb_remaining(&is->pictq) == 0) {
1599 // nothing to do, no picture to display in the queue
1601 double last_duration, duration, delay;
1604 /* dequeue the picture */
1605 lastvp = frame_queue_peek_last(&is->pictq);
1606 vp = frame_queue_peek(&is->pictq);
1608 if (vp->serial != is->videoq.serial) {
1609 frame_queue_next(&is->pictq);
1613 if (lastvp->serial != vp->serial)
1614 is->frame_timer = av_gettime_relative() / 1000000.0;
1619 /* compute nominal last_duration */
1620 last_duration = vp_duration(is, lastvp, vp);
1621 delay = compute_target_delay(last_duration, is);
1623 time= av_gettime_relative()/1000000.0;
1624 if (time < is->frame_timer + delay) {
1625 *remaining_time = FFMIN(is->frame_timer + delay - time, *remaining_time);
1629 is->frame_timer += delay;
1630 if (delay > 0 && time - is->frame_timer > AV_SYNC_THRESHOLD_MAX)
1631 is->frame_timer = time;
1633 SDL_LockMutex(is->pictq.mutex);
1634 if (!isnan(vp->pts))
1635 update_video_pts(is, vp->pts, vp->pos, vp->serial);
1636 SDL_UnlockMutex(is->pictq.mutex);
1638 if (frame_queue_nb_remaining(&is->pictq) > 1) {
1639 Frame *nextvp = frame_queue_peek_next(&is->pictq);
1640 duration = vp_duration(is, vp, nextvp);
1641 if(!is->step && (framedrop>0 || (framedrop && get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER)) && time > is->frame_timer + duration){
1642 is->frame_drops_late++;
1643 frame_queue_next(&is->pictq);
1648 if (is->subtitle_st) {
1649 while (frame_queue_nb_remaining(&is->subpq) > 0) {
1650 sp = frame_queue_peek(&is->subpq);
1652 if (frame_queue_nb_remaining(&is->subpq) > 1)
1653 sp2 = frame_queue_peek_next(&is->subpq);
1657 if (sp->serial != is->subtitleq.serial
1658 || (is->vidclk.pts > (sp->pts + ((float) sp->sub.end_display_time / 1000)))
1659 || (sp2 && is->vidclk.pts > (sp2->pts + ((float) sp2->sub.start_display_time / 1000))))
1663 for (i = 0; i < sp->sub.num_rects; i++) {
1664 AVSubtitleRect *sub_rect = sp->sub.rects[i];
1668 if (!SDL_LockTexture(is->sub_texture, (SDL_Rect *)sub_rect, (void **)&pixels, &pitch)) {
1669 for (j = 0; j < sub_rect->h; j++, pixels += pitch)
1670 memset(pixels, 0, sub_rect->w << 2);
1671 SDL_UnlockTexture(is->sub_texture);
1675 frame_queue_next(&is->subpq);
1682 frame_queue_next(&is->pictq);
1683 is->force_refresh = 1;
1685 if (is->step && !is->paused)
1686 stream_toggle_pause(is);
1689 /* display picture */
1690 if (!display_disable && is->force_refresh && is->show_mode == SHOW_MODE_VIDEO && is->pictq.rindex_shown)
1693 is->force_refresh = 0;
1695 static int64_t last_time;
1697 int aqsize, vqsize, sqsize;
1700 cur_time = av_gettime_relative();
1701 if (!last_time || (cur_time - last_time) >= 30000) {
1706 aqsize = is->audioq.size;
1708 vqsize = is->videoq.size;
1709 if (is->subtitle_st)
1710 sqsize = is->subtitleq.size;
1712 if (is->audio_st && is->video_st)
1713 av_diff = get_clock(&is->audclk) - get_clock(&is->vidclk);
1714 else if (is->video_st)
1715 av_diff = get_master_clock(is) - get_clock(&is->vidclk);
1716 else if (is->audio_st)
1717 av_diff = get_master_clock(is) - get_clock(&is->audclk);
1718 av_log(NULL, AV_LOG_INFO,
1719 "%7.2f %s:%7.3f fd=%4d aq=%5dKB vq=%5dKB sq=%5dB f=%"PRId64"/%"PRId64" \r",
1720 get_master_clock(is),
1721 (is->audio_st && is->video_st) ? "A-V" : (is->video_st ? "M-V" : (is->audio_st ? "M-A" : " ")),
1723 is->frame_drops_early + is->frame_drops_late,
1727 is->video_st ? is->viddec.avctx->pts_correction_num_faulty_dts : 0,
1728 is->video_st ? is->viddec.avctx->pts_correction_num_faulty_pts : 0);
1730 last_time = cur_time;
1735 static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, double duration, int64_t pos, int serial)
1739 #if defined(DEBUG_SYNC)
1740 printf("frame_type=%c pts=%0.3f\n",
1741 av_get_picture_type_char(src_frame->pict_type), pts);
1744 if (!(vp = frame_queue_peek_writable(&is->pictq)))
1747 vp->sar = src_frame->sample_aspect_ratio;
1750 vp->width = src_frame->width;
1751 vp->height = src_frame->height;
1752 vp->format = src_frame->format;
1755 vp->duration = duration;
1757 vp->serial = serial;
1759 set_default_window_size(vp->width, vp->height, vp->sar);
1761 av_frame_move_ref(vp->frame, src_frame);
1762 frame_queue_push(&is->pictq);
1766 static int get_video_frame(VideoState *is, AVFrame *frame)
1770 if ((got_picture = decoder_decode_frame(&is->viddec, frame, NULL)) < 0)
1776 if (frame->pts != AV_NOPTS_VALUE)
1777 dpts = av_q2d(is->video_st->time_base) * frame->pts;
1779 frame->sample_aspect_ratio = av_guess_sample_aspect_ratio(is->ic, is->video_st, frame);
1781 if (framedrop>0 || (framedrop && get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER)) {
1782 if (frame->pts != AV_NOPTS_VALUE) {
1783 double diff = dpts - get_master_clock(is);
1784 if (!isnan(diff) && fabs(diff) < AV_NOSYNC_THRESHOLD &&
1785 diff - is->frame_last_filter_delay < 0 &&
1786 is->viddec.pkt_serial == is->vidclk.serial &&
1787 is->videoq.nb_packets) {
1788 is->frame_drops_early++;
1789 av_frame_unref(frame);
1800 static int configure_filtergraph(AVFilterGraph *graph, const char *filtergraph,
1801 AVFilterContext *source_ctx, AVFilterContext *sink_ctx)
1804 int nb_filters = graph->nb_filters;
1805 AVFilterInOut *outputs = NULL, *inputs = NULL;
1808 outputs = avfilter_inout_alloc();
1809 inputs = avfilter_inout_alloc();
1810 if (!outputs || !inputs) {
1811 ret = AVERROR(ENOMEM);
1815 outputs->name = av_strdup("in");
1816 outputs->filter_ctx = source_ctx;
1817 outputs->pad_idx = 0;
1818 outputs->next = NULL;
1820 inputs->name = av_strdup("out");
1821 inputs->filter_ctx = sink_ctx;
1822 inputs->pad_idx = 0;
1823 inputs->next = NULL;
1825 if ((ret = avfilter_graph_parse_ptr(graph, filtergraph, &inputs, &outputs, NULL)) < 0)
1828 if ((ret = avfilter_link(source_ctx, 0, sink_ctx, 0)) < 0)
1832 /* Reorder the filters to ensure that inputs of the custom filters are merged first */
1833 for (i = 0; i < graph->nb_filters - nb_filters; i++)
1834 FFSWAP(AVFilterContext*, graph->filters[i], graph->filters[i + nb_filters]);
1836 ret = avfilter_graph_config(graph, NULL);
1838 avfilter_inout_free(&outputs);
1839 avfilter_inout_free(&inputs);
1843 static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const char *vfilters, AVFrame *frame)
1845 enum AVPixelFormat pix_fmts[FF_ARRAY_ELEMS(sdl_texture_format_map)];
1846 char sws_flags_str[512] = "";
1847 char buffersrc_args[256];
1849 AVFilterContext *filt_src = NULL, *filt_out = NULL, *last_filter = NULL;
1850 AVCodecParameters *codecpar = is->video_st->codecpar;
1851 AVRational fr = av_guess_frame_rate(is->ic, is->video_st, NULL);
1852 AVDictionaryEntry *e = NULL;
1853 int nb_pix_fmts = 0;
1856 for (i = 0; i < renderer_info.num_texture_formats; i++) {
1857 for (j = 0; j < FF_ARRAY_ELEMS(sdl_texture_format_map) - 1; j++) {
1858 if (renderer_info.texture_formats[i] == sdl_texture_format_map[j].texture_fmt) {
1859 pix_fmts[nb_pix_fmts++] = sdl_texture_format_map[j].format;
1864 pix_fmts[nb_pix_fmts] = AV_PIX_FMT_NONE;
1866 while ((e = av_dict_get(sws_dict, "", e, AV_DICT_IGNORE_SUFFIX))) {
1867 if (!strcmp(e->key, "sws_flags")) {
1868 av_strlcatf(sws_flags_str, sizeof(sws_flags_str), "%s=%s:", "flags", e->value);
1870 av_strlcatf(sws_flags_str, sizeof(sws_flags_str), "%s=%s:", e->key, e->value);
1872 if (strlen(sws_flags_str))
1873 sws_flags_str[strlen(sws_flags_str)-1] = '\0';
1875 graph->scale_sws_opts = av_strdup(sws_flags_str);
1877 snprintf(buffersrc_args, sizeof(buffersrc_args),
1878 "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
1879 frame->width, frame->height, frame->format,
1880 is->video_st->time_base.num, is->video_st->time_base.den,
1881 codecpar->sample_aspect_ratio.num, FFMAX(codecpar->sample_aspect_ratio.den, 1));
1882 if (fr.num && fr.den)
1883 av_strlcatf(buffersrc_args, sizeof(buffersrc_args), ":frame_rate=%d/%d", fr.num, fr.den);
1885 if ((ret = avfilter_graph_create_filter(&filt_src,
1886 avfilter_get_by_name("buffer"),
1887 "ffplay_buffer", buffersrc_args, NULL,
1891 ret = avfilter_graph_create_filter(&filt_out,
1892 avfilter_get_by_name("buffersink"),
1893 "ffplay_buffersink", NULL, NULL, graph);
1897 if ((ret = av_opt_set_int_list(filt_out, "pix_fmts", pix_fmts, AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN)) < 0)
1900 last_filter = filt_out;
1902 /* Note: this macro adds a filter before the lastly added filter, so the
1903 * processing order of the filters is in reverse */
1904 #define INSERT_FILT(name, arg) do { \
1905 AVFilterContext *filt_ctx; \
1907 ret = avfilter_graph_create_filter(&filt_ctx, \
1908 avfilter_get_by_name(name), \
1909 "ffplay_" name, arg, NULL, graph); \
1913 ret = avfilter_link(filt_ctx, 0, last_filter, 0); \
1917 last_filter = filt_ctx; \
1921 double theta = get_rotation(is->video_st);
1923 if (fabs(theta - 90) < 1.0) {
1924 INSERT_FILT("transpose", "clock");
1925 } else if (fabs(theta - 180) < 1.0) {
1926 INSERT_FILT("hflip", NULL);
1927 INSERT_FILT("vflip", NULL);
1928 } else if (fabs(theta - 270) < 1.0) {
1929 INSERT_FILT("transpose", "cclock");
1930 } else if (fabs(theta) > 1.0) {
1931 char rotate_buf[64];
1932 snprintf(rotate_buf, sizeof(rotate_buf), "%f*PI/180", theta);
1933 INSERT_FILT("rotate", rotate_buf);
1937 if ((ret = configure_filtergraph(graph, vfilters, filt_src, last_filter)) < 0)
1940 is->in_video_filter = filt_src;
1941 is->out_video_filter = filt_out;
1947 static int configure_audio_filters(VideoState *is, const char *afilters, int force_output_format)
1949 static const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE };
1950 int sample_rates[2] = { 0, -1 };
1951 int64_t channel_layouts[2] = { 0, -1 };
1952 int channels[2] = { 0, -1 };
1953 AVFilterContext *filt_asrc = NULL, *filt_asink = NULL;
1954 char aresample_swr_opts[512] = "";
1955 AVDictionaryEntry *e = NULL;
1956 char asrc_args[256];
1959 avfilter_graph_free(&is->agraph);
1960 if (!(is->agraph = avfilter_graph_alloc()))
1961 return AVERROR(ENOMEM);
1963 while ((e = av_dict_get(swr_opts, "", e, AV_DICT_IGNORE_SUFFIX)))
1964 av_strlcatf(aresample_swr_opts, sizeof(aresample_swr_opts), "%s=%s:", e->key, e->value);
1965 if (strlen(aresample_swr_opts))
1966 aresample_swr_opts[strlen(aresample_swr_opts)-1] = '\0';
1967 av_opt_set(is->agraph, "aresample_swr_opts", aresample_swr_opts, 0);
1969 ret = snprintf(asrc_args, sizeof(asrc_args),
1970 "sample_rate=%d:sample_fmt=%s:channels=%d:time_base=%d/%d",
1971 is->audio_filter_src.freq, av_get_sample_fmt_name(is->audio_filter_src.fmt),
1972 is->audio_filter_src.channels,
1973 1, is->audio_filter_src.freq);
1974 if (is->audio_filter_src.channel_layout)
1975 snprintf(asrc_args + ret, sizeof(asrc_args) - ret,
1976 ":channel_layout=0x%"PRIx64, is->audio_filter_src.channel_layout);
1978 ret = avfilter_graph_create_filter(&filt_asrc,
1979 avfilter_get_by_name("abuffer"), "ffplay_abuffer",
1980 asrc_args, NULL, is->agraph);
1985 ret = avfilter_graph_create_filter(&filt_asink,
1986 avfilter_get_by_name("abuffersink"), "ffplay_abuffersink",
1987 NULL, NULL, is->agraph);
1991 if ((ret = av_opt_set_int_list(filt_asink, "sample_fmts", sample_fmts, AV_SAMPLE_FMT_NONE, AV_OPT_SEARCH_CHILDREN)) < 0)
1993 if ((ret = av_opt_set_int(filt_asink, "all_channel_counts", 1, AV_OPT_SEARCH_CHILDREN)) < 0)
1996 if (force_output_format) {
1997 channel_layouts[0] = is->audio_tgt.channel_layout;
1998 channels [0] = is->audio_tgt.channels;
1999 sample_rates [0] = is->audio_tgt.freq;
2000 if ((ret = av_opt_set_int(filt_asink, "all_channel_counts", 0, AV_OPT_SEARCH_CHILDREN)) < 0)
2002 if ((ret = av_opt_set_int_list(filt_asink, "channel_layouts", channel_layouts, -1, AV_OPT_SEARCH_CHILDREN)) < 0)
2004 if ((ret = av_opt_set_int_list(filt_asink, "channel_counts" , channels , -1, AV_OPT_SEARCH_CHILDREN)) < 0)
2006 if ((ret = av_opt_set_int_list(filt_asink, "sample_rates" , sample_rates , -1, AV_OPT_SEARCH_CHILDREN)) < 0)
2011 if ((ret = configure_filtergraph(is->agraph, afilters, filt_asrc, filt_asink)) < 0)
2014 is->in_audio_filter = filt_asrc;
2015 is->out_audio_filter = filt_asink;
2019 avfilter_graph_free(&is->agraph);
2022 #endif /* CONFIG_AVFILTER */
2024 static int audio_thread(void *arg)
2026 VideoState *is = arg;
2027 AVFrame *frame = av_frame_alloc();
2030 int last_serial = -1;
2031 int64_t dec_channel_layout;
2039 return AVERROR(ENOMEM);
2042 if ((got_frame = decoder_decode_frame(&is->auddec, frame, NULL)) < 0)
2046 tb = (AVRational){1, frame->sample_rate};
2049 dec_channel_layout = get_valid_channel_layout(frame->channel_layout, frame->channels);
2052 cmp_audio_fmts(is->audio_filter_src.fmt, is->audio_filter_src.channels,
2053 frame->format, frame->channels) ||
2054 is->audio_filter_src.channel_layout != dec_channel_layout ||
2055 is->audio_filter_src.freq != frame->sample_rate ||
2056 is->auddec.pkt_serial != last_serial;
2059 char buf1[1024], buf2[1024];
2060 av_get_channel_layout_string(buf1, sizeof(buf1), -1, is->audio_filter_src.channel_layout);
2061 av_get_channel_layout_string(buf2, sizeof(buf2), -1, dec_channel_layout);
2062 av_log(NULL, AV_LOG_DEBUG,
2063 "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",
2064 is->audio_filter_src.freq, is->audio_filter_src.channels, av_get_sample_fmt_name(is->audio_filter_src.fmt), buf1, last_serial,
2065 frame->sample_rate, frame->channels, av_get_sample_fmt_name(frame->format), buf2, is->auddec.pkt_serial);
2067 is->audio_filter_src.fmt = frame->format;
2068 is->audio_filter_src.channels = frame->channels;
2069 is->audio_filter_src.channel_layout = dec_channel_layout;
2070 is->audio_filter_src.freq = frame->sample_rate;
2071 last_serial = is->auddec.pkt_serial;
2073 if ((ret = configure_audio_filters(is, afilters, 1)) < 0)
2077 if ((ret = av_buffersrc_add_frame(is->in_audio_filter, frame)) < 0)
2080 while ((ret = av_buffersink_get_frame_flags(is->out_audio_filter, frame, 0)) >= 0) {
2081 tb = av_buffersink_get_time_base(is->out_audio_filter);
2083 if (!(af = frame_queue_peek_writable(&is->sampq)))
2086 af->pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb);
2087 af->pos = frame->pkt_pos;
2088 af->serial = is->auddec.pkt_serial;
2089 af->duration = av_q2d((AVRational){frame->nb_samples, frame->sample_rate});
2091 av_frame_move_ref(af->frame, frame);
2092 frame_queue_push(&is->sampq);
2095 if (is->audioq.serial != is->auddec.pkt_serial)
2098 if (ret == AVERROR_EOF)
2099 is->auddec.finished = is->auddec.pkt_serial;
2102 } while (ret >= 0 || ret == AVERROR(EAGAIN) || ret == AVERROR_EOF);
2105 avfilter_graph_free(&is->agraph);
2107 av_frame_free(&frame);
2111 static int decoder_start(Decoder *d, int (*fn)(void *), void *arg)
2113 packet_queue_start(d->queue);
2114 d->decoder_tid = SDL_CreateThread(fn, "decoder", arg);
2115 if (!d->decoder_tid) {
2116 av_log(NULL, AV_LOG_ERROR, "SDL_CreateThread(): %s\n", SDL_GetError());
2117 return AVERROR(ENOMEM);
2122 static int video_thread(void *arg)
2124 VideoState *is = arg;
2125 AVFrame *frame = av_frame_alloc();
2129 AVRational tb = is->video_st->time_base;
2130 AVRational frame_rate = av_guess_frame_rate(is->ic, is->video_st, NULL);
2133 AVFilterGraph *graph = avfilter_graph_alloc();
2134 AVFilterContext *filt_out = NULL, *filt_in = NULL;
2137 enum AVPixelFormat last_format = -2;
2138 int last_serial = -1;
2139 int last_vfilter_idx = 0;
2141 av_frame_free(&frame);
2142 return AVERROR(ENOMEM);
2149 avfilter_graph_free(&graph);
2151 return AVERROR(ENOMEM);
2155 ret = get_video_frame(is, frame);
2162 if ( last_w != frame->width
2163 || last_h != frame->height
2164 || last_format != frame->format
2165 || last_serial != is->viddec.pkt_serial
2166 || last_vfilter_idx != is->vfilter_idx) {
2167 av_log(NULL, AV_LOG_DEBUG,
2168 "Video frame changed from size:%dx%d format:%s serial:%d to size:%dx%d format:%s serial:%d\n",
2170 (const char *)av_x_if_null(av_get_pix_fmt_name(last_format), "none"), last_serial,
2171 frame->width, frame->height,
2172 (const char *)av_x_if_null(av_get_pix_fmt_name(frame->format), "none"), is->viddec.pkt_serial);
2173 avfilter_graph_free(&graph);
2174 graph = avfilter_graph_alloc();
2175 if ((ret = configure_video_filters(graph, is, vfilters_list ? vfilters_list[is->vfilter_idx] : NULL, frame)) < 0) {
2177 event.type = FF_QUIT_EVENT;
2178 event.user.data1 = is;
2179 SDL_PushEvent(&event);
2182 filt_in = is->in_video_filter;
2183 filt_out = is->out_video_filter;
2184 last_w = frame->width;
2185 last_h = frame->height;
2186 last_format = frame->format;
2187 last_serial = is->viddec.pkt_serial;
2188 last_vfilter_idx = is->vfilter_idx;
2189 frame_rate = av_buffersink_get_frame_rate(filt_out);
2192 ret = av_buffersrc_add_frame(filt_in, frame);
2197 is->frame_last_returned_time = av_gettime_relative() / 1000000.0;
2199 ret = av_buffersink_get_frame_flags(filt_out, frame, 0);
2201 if (ret == AVERROR_EOF)
2202 is->viddec.finished = is->viddec.pkt_serial;
2207 is->frame_last_filter_delay = av_gettime_relative() / 1000000.0 - is->frame_last_returned_time;
2208 if (fabs(is->frame_last_filter_delay) > AV_NOSYNC_THRESHOLD / 10.0)
2209 is->frame_last_filter_delay = 0;
2210 tb = av_buffersink_get_time_base(filt_out);
2212 duration = (frame_rate.num && frame_rate.den ? av_q2d((AVRational){frame_rate.den, frame_rate.num}) : 0);
2213 pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb);
2214 ret = queue_picture(is, frame, pts, duration, frame->pkt_pos, is->viddec.pkt_serial);
2215 av_frame_unref(frame);
2217 if (is->videoq.serial != is->viddec.pkt_serial)
2227 avfilter_graph_free(&graph);
2229 av_frame_free(&frame);
2233 static int subtitle_thread(void *arg)
2235 VideoState *is = arg;
2241 if (!(sp = frame_queue_peek_writable(&is->subpq)))
2244 if ((got_subtitle = decoder_decode_frame(&is->subdec, NULL, &sp->sub)) < 0)
2249 if (got_subtitle && sp->sub.format == 0) {
2250 if (sp->sub.pts != AV_NOPTS_VALUE)
2251 pts = sp->sub.pts / (double)AV_TIME_BASE;
2253 sp->serial = is->subdec.pkt_serial;
2254 sp->width = is->subdec.avctx->width;
2255 sp->height = is->subdec.avctx->height;
2258 /* now we can update the picture count */
2259 frame_queue_push(&is->subpq);
2260 } else if (got_subtitle) {
2261 avsubtitle_free(&sp->sub);
2267 /* copy samples for viewing in editor window */
2268 static void update_sample_display(VideoState *is, short *samples, int samples_size)
2272 size = samples_size / sizeof(short);
2274 len = SAMPLE_ARRAY_SIZE - is->sample_array_index;
2277 memcpy(is->sample_array + is->sample_array_index, samples, len * sizeof(short));
2279 is->sample_array_index += len;
2280 if (is->sample_array_index >= SAMPLE_ARRAY_SIZE)
2281 is->sample_array_index = 0;
2286 /* return the wanted number of samples to get better sync if sync_type is video
2287 * or external master clock */
2288 static int synchronize_audio(VideoState *is, int nb_samples)
2290 int wanted_nb_samples = nb_samples;
2292 /* if not master, then we try to remove or add samples to correct the clock */
2293 if (get_master_sync_type(is) != AV_SYNC_AUDIO_MASTER) {
2294 double diff, avg_diff;
2295 int min_nb_samples, max_nb_samples;
2297 diff = get_clock(&is->audclk) - get_master_clock(is);
2299 if (!isnan(diff) && fabs(diff) < AV_NOSYNC_THRESHOLD) {
2300 is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum;
2301 if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {
2302 /* not enough measures to have a correct estimate */
2303 is->audio_diff_avg_count++;
2305 /* estimate the A-V difference */
2306 avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef);
2308 if (fabs(avg_diff) >= is->audio_diff_threshold) {
2309 wanted_nb_samples = nb_samples + (int)(diff * is->audio_src.freq);
2310 min_nb_samples = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX) / 100));
2311 max_nb_samples = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX) / 100));
2312 wanted_nb_samples = av_clip(wanted_nb_samples, min_nb_samples, max_nb_samples);
2314 av_log(NULL, AV_LOG_TRACE, "diff=%f adiff=%f sample_diff=%d apts=%0.3f %f\n",
2315 diff, avg_diff, wanted_nb_samples - nb_samples,
2316 is->audio_clock, is->audio_diff_threshold);
2319 /* too big difference : may be initial PTS errors, so
2321 is->audio_diff_avg_count = 0;
2322 is->audio_diff_cum = 0;
2326 return wanted_nb_samples;
2330 * Decode one audio frame and return its uncompressed size.
2332 * The processed audio frame is decoded, converted if required, and
2333 * stored in is->audio_buf, with size in bytes given by the return
2336 static int audio_decode_frame(VideoState *is)
2338 int data_size, resampled_data_size;
2339 int64_t dec_channel_layout;
2340 av_unused double audio_clock0;
2341 int wanted_nb_samples;
2349 while (frame_queue_nb_remaining(&is->sampq) == 0) {
2350 if ((av_gettime_relative() - audio_callback_time) > 1000000LL * is->audio_hw_buf_size / is->audio_tgt.bytes_per_sec / 2)
2355 if (!(af = frame_queue_peek_readable(&is->sampq)))
2357 frame_queue_next(&is->sampq);
2358 } while (af->serial != is->audioq.serial);
2360 data_size = av_samples_get_buffer_size(NULL, af->frame->channels,
2361 af->frame->nb_samples,
2362 af->frame->format, 1);
2364 dec_channel_layout =
2365 (af->frame->channel_layout && af->frame->channels == av_get_channel_layout_nb_channels(af->frame->channel_layout)) ?
2366 af->frame->channel_layout : av_get_default_channel_layout(af->frame->channels);
2367 wanted_nb_samples = synchronize_audio(is, af->frame->nb_samples);
2369 if (af->frame->format != is->audio_src.fmt ||
2370 dec_channel_layout != is->audio_src.channel_layout ||
2371 af->frame->sample_rate != is->audio_src.freq ||
2372 (wanted_nb_samples != af->frame->nb_samples && !is->swr_ctx)) {
2373 swr_free(&is->swr_ctx);
2374 is->swr_ctx = swr_alloc_set_opts(NULL,
2375 is->audio_tgt.channel_layout, is->audio_tgt.fmt, is->audio_tgt.freq,
2376 dec_channel_layout, af->frame->format, af->frame->sample_rate,
2378 if (!is->swr_ctx || swr_init(is->swr_ctx) < 0) {
2379 av_log(NULL, AV_LOG_ERROR,
2380 "Cannot create sample rate converter for conversion of %d Hz %s %d channels to %d Hz %s %d channels!\n",
2381 af->frame->sample_rate, av_get_sample_fmt_name(af->frame->format), af->frame->channels,
2382 is->audio_tgt.freq, av_get_sample_fmt_name(is->audio_tgt.fmt), is->audio_tgt.channels);
2383 swr_free(&is->swr_ctx);
2386 is->audio_src.channel_layout = dec_channel_layout;
2387 is->audio_src.channels = af->frame->channels;
2388 is->audio_src.freq = af->frame->sample_rate;
2389 is->audio_src.fmt = af->frame->format;
2393 const uint8_t **in = (const uint8_t **)af->frame->extended_data;
2394 uint8_t **out = &is->audio_buf1;
2395 int out_count = (int64_t)wanted_nb_samples * is->audio_tgt.freq / af->frame->sample_rate + 256;
2396 int out_size = av_samples_get_buffer_size(NULL, is->audio_tgt.channels, out_count, is->audio_tgt.fmt, 0);
2399 av_log(NULL, AV_LOG_ERROR, "av_samples_get_buffer_size() failed\n");
2402 if (wanted_nb_samples != af->frame->nb_samples) {
2403 if (swr_set_compensation(is->swr_ctx, (wanted_nb_samples - af->frame->nb_samples) * is->audio_tgt.freq / af->frame->sample_rate,
2404 wanted_nb_samples * is->audio_tgt.freq / af->frame->sample_rate) < 0) {
2405 av_log(NULL, AV_LOG_ERROR, "swr_set_compensation() failed\n");
2409 av_fast_malloc(&is->audio_buf1, &is->audio_buf1_size, out_size);
2410 if (!is->audio_buf1)
2411 return AVERROR(ENOMEM);
2412 len2 = swr_convert(is->swr_ctx, out, out_count, in, af->frame->nb_samples);
2414 av_log(NULL, AV_LOG_ERROR, "swr_convert() failed\n");
2417 if (len2 == out_count) {
2418 av_log(NULL, AV_LOG_WARNING, "audio buffer is probably too small\n");
2419 if (swr_init(is->swr_ctx) < 0)
2420 swr_free(&is->swr_ctx);
2422 is->audio_buf = is->audio_buf1;
2423 resampled_data_size = len2 * is->audio_tgt.channels * av_get_bytes_per_sample(is->audio_tgt.fmt);
2425 is->audio_buf = af->frame->data[0];
2426 resampled_data_size = data_size;
2429 audio_clock0 = is->audio_clock;
2430 /* update the audio clock with the pts */
2431 if (!isnan(af->pts))
2432 is->audio_clock = af->pts + (double) af->frame->nb_samples / af->frame->sample_rate;
2434 is->audio_clock = NAN;
2435 is->audio_clock_serial = af->serial;
2438 static double last_clock;
2439 printf("audio: delay=%0.3f clock=%0.3f clock0=%0.3f\n",
2440 is->audio_clock - last_clock,
2441 is->audio_clock, audio_clock0);
2442 last_clock = is->audio_clock;
2445 return resampled_data_size;
2448 /* prepare a new audio buffer */
2449 static void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
2451 VideoState *is = opaque;
2452 int audio_size, len1;
2454 audio_callback_time = av_gettime_relative();
2457 if (is->audio_buf_index >= is->audio_buf_size) {
2458 audio_size = audio_decode_frame(is);
2459 if (audio_size < 0) {
2460 /* if error, just output silence */
2461 is->audio_buf = NULL;
2462 is->audio_buf_size = SDL_AUDIO_MIN_BUFFER_SIZE / is->audio_tgt.frame_size * is->audio_tgt.frame_size;
2464 if (is->show_mode != SHOW_MODE_VIDEO)
2465 update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
2466 is->audio_buf_size = audio_size;
2468 is->audio_buf_index = 0;
2470 len1 = is->audio_buf_size - is->audio_buf_index;
2473 if (!is->muted && is->audio_buf && is->audio_volume == SDL_MIX_MAXVOLUME)
2474 memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
2476 memset(stream, 0, len1);
2477 if (!is->muted && is->audio_buf)
2478 SDL_MixAudioFormat(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, AUDIO_S16SYS, len1, is->audio_volume);
2482 is->audio_buf_index += len1;
2484 is->audio_write_buf_size = is->audio_buf_size - is->audio_buf_index;
2485 /* Let's assume the audio driver that is used by SDL has two periods. */
2486 if (!isnan(is->audio_clock)) {
2487 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);
2488 sync_clock_to_slave(&is->extclk, &is->audclk);
2492 static int audio_open(void *opaque, int64_t wanted_channel_layout, int wanted_nb_channels, int wanted_sample_rate, struct AudioParams *audio_hw_params)
2494 SDL_AudioSpec wanted_spec, spec;
2496 static const int next_nb_channels[] = {0, 0, 1, 6, 2, 6, 4, 6};
2497 static const int next_sample_rates[] = {0, 44100, 48000, 96000, 192000};
2498 int next_sample_rate_idx = FF_ARRAY_ELEMS(next_sample_rates) - 1;
2500 env = SDL_getenv("SDL_AUDIO_CHANNELS");
2502 wanted_nb_channels = atoi(env);
2503 wanted_channel_layout = av_get_default_channel_layout(wanted_nb_channels);
2505 if (!wanted_channel_layout || wanted_nb_channels != av_get_channel_layout_nb_channels(wanted_channel_layout)) {
2506 wanted_channel_layout = av_get_default_channel_layout(wanted_nb_channels);
2507 wanted_channel_layout &= ~AV_CH_LAYOUT_STEREO_DOWNMIX;
2509 wanted_nb_channels = av_get_channel_layout_nb_channels(wanted_channel_layout);
2510 wanted_spec.channels = wanted_nb_channels;
2511 wanted_spec.freq = wanted_sample_rate;
2512 if (wanted_spec.freq <= 0 || wanted_spec.channels <= 0) {
2513 av_log(NULL, AV_LOG_ERROR, "Invalid sample rate or channel count!\n");
2516 while (next_sample_rate_idx && next_sample_rates[next_sample_rate_idx] >= wanted_spec.freq)
2517 next_sample_rate_idx--;
2518 wanted_spec.format = AUDIO_S16SYS;
2519 wanted_spec.silence = 0;
2520 wanted_spec.samples = FFMAX(SDL_AUDIO_MIN_BUFFER_SIZE, 2 << av_log2(wanted_spec.freq / SDL_AUDIO_MAX_CALLBACKS_PER_SEC));
2521 wanted_spec.callback = sdl_audio_callback;
2522 wanted_spec.userdata = opaque;
2523 while (!(audio_dev = SDL_OpenAudioDevice(NULL, 0, &wanted_spec, &spec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE | SDL_AUDIO_ALLOW_CHANNELS_CHANGE))) {
2524 av_log(NULL, AV_LOG_WARNING, "SDL_OpenAudio (%d channels, %d Hz): %s\n",
2525 wanted_spec.channels, wanted_spec.freq, SDL_GetError());
2526 wanted_spec.channels = next_nb_channels[FFMIN(7, wanted_spec.channels)];
2527 if (!wanted_spec.channels) {
2528 wanted_spec.freq = next_sample_rates[next_sample_rate_idx--];
2529 wanted_spec.channels = wanted_nb_channels;
2530 if (!wanted_spec.freq) {
2531 av_log(NULL, AV_LOG_ERROR,
2532 "No more combinations to try, audio open failed\n");
2536 wanted_channel_layout = av_get_default_channel_layout(wanted_spec.channels);
2538 if (spec.format != AUDIO_S16SYS) {
2539 av_log(NULL, AV_LOG_ERROR,
2540 "SDL advised audio format %d is not supported!\n", spec.format);
2543 if (spec.channels != wanted_spec.channels) {
2544 wanted_channel_layout = av_get_default_channel_layout(spec.channels);
2545 if (!wanted_channel_layout) {
2546 av_log(NULL, AV_LOG_ERROR,
2547 "SDL advised channel count %d is not supported!\n", spec.channels);
2552 audio_hw_params->fmt = AV_SAMPLE_FMT_S16;
2553 audio_hw_params->freq = spec.freq;
2554 audio_hw_params->channel_layout = wanted_channel_layout;
2555 audio_hw_params->channels = spec.channels;
2556 audio_hw_params->frame_size = av_samples_get_buffer_size(NULL, audio_hw_params->channels, 1, audio_hw_params->fmt, 1);
2557 audio_hw_params->bytes_per_sec = av_samples_get_buffer_size(NULL, audio_hw_params->channels, audio_hw_params->freq, audio_hw_params->fmt, 1);
2558 if (audio_hw_params->bytes_per_sec <= 0 || audio_hw_params->frame_size <= 0) {
2559 av_log(NULL, AV_LOG_ERROR, "av_samples_get_buffer_size failed\n");
2565 /* open a given stream. Return 0 if OK */
2566 static int stream_component_open(VideoState *is, int stream_index)
2568 AVFormatContext *ic = is->ic;
2569 AVCodecContext *avctx;
2571 const char *forced_codec_name = NULL;
2572 AVDictionary *opts = NULL;
2573 AVDictionaryEntry *t = NULL;
2574 int sample_rate, nb_channels;
2575 int64_t channel_layout;
2577 int stream_lowres = lowres;
2579 if (stream_index < 0 || stream_index >= ic->nb_streams)
2582 avctx = avcodec_alloc_context3(NULL);
2584 return AVERROR(ENOMEM);
2586 ret = avcodec_parameters_to_context(avctx, ic->streams[stream_index]->codecpar);
2589 avctx->pkt_timebase = ic->streams[stream_index]->time_base;
2591 codec = avcodec_find_decoder(avctx->codec_id);
2593 switch(avctx->codec_type){
2594 case AVMEDIA_TYPE_AUDIO : is->last_audio_stream = stream_index; forced_codec_name = audio_codec_name; break;
2595 case AVMEDIA_TYPE_SUBTITLE: is->last_subtitle_stream = stream_index; forced_codec_name = subtitle_codec_name; break;
2596 case AVMEDIA_TYPE_VIDEO : is->last_video_stream = stream_index; forced_codec_name = video_codec_name; break;
2598 if (forced_codec_name)
2599 codec = avcodec_find_decoder_by_name(forced_codec_name);
2601 if (forced_codec_name) av_log(NULL, AV_LOG_WARNING,
2602 "No codec could be found with name '%s'\n", forced_codec_name);
2603 else av_log(NULL, AV_LOG_WARNING,
2604 "No decoder could be found for codec %s\n", avcodec_get_name(avctx->codec_id));
2605 ret = AVERROR(EINVAL);
2609 avctx->codec_id = codec->id;
2610 if (stream_lowres > codec->max_lowres) {
2611 av_log(avctx, AV_LOG_WARNING, "The maximum value for lowres supported by the decoder is %d\n",
2613 stream_lowres = codec->max_lowres;
2615 avctx->lowres = stream_lowres;
2618 avctx->flags2 |= AV_CODEC_FLAG2_FAST;
2620 opts = filter_codec_opts(codec_opts, avctx->codec_id, ic, ic->streams[stream_index], codec);
2621 if (!av_dict_get(opts, "threads", NULL, 0))
2622 av_dict_set(&opts, "threads", "auto", 0);
2624 av_dict_set_int(&opts, "lowres", stream_lowres, 0);
2625 if (avctx->codec_type == AVMEDIA_TYPE_VIDEO || avctx->codec_type == AVMEDIA_TYPE_AUDIO)
2626 av_dict_set(&opts, "refcounted_frames", "1", 0);
2627 if ((ret = avcodec_open2(avctx, codec, &opts)) < 0) {
2630 if ((t = av_dict_get(opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
2631 av_log(NULL, AV_LOG_ERROR, "Option %s not found.\n", t->key);
2632 ret = AVERROR_OPTION_NOT_FOUND;
2637 ic->streams[stream_index]->discard = AVDISCARD_DEFAULT;
2638 switch (avctx->codec_type) {
2639 case AVMEDIA_TYPE_AUDIO:
2642 AVFilterContext *sink;
2644 is->audio_filter_src.freq = avctx->sample_rate;
2645 is->audio_filter_src.channels = avctx->channels;
2646 is->audio_filter_src.channel_layout = get_valid_channel_layout(avctx->channel_layout, avctx->channels);
2647 is->audio_filter_src.fmt = avctx->sample_fmt;
2648 if ((ret = configure_audio_filters(is, afilters, 0)) < 0)
2650 sink = is->out_audio_filter;
2651 sample_rate = av_buffersink_get_sample_rate(sink);
2652 nb_channels = av_buffersink_get_channels(sink);
2653 channel_layout = av_buffersink_get_channel_layout(sink);
2656 sample_rate = avctx->sample_rate;
2657 nb_channels = avctx->channels;
2658 channel_layout = avctx->channel_layout;
2661 /* prepare audio output */
2662 if ((ret = audio_open(is, channel_layout, nb_channels, sample_rate, &is->audio_tgt)) < 0)
2664 is->audio_hw_buf_size = ret;
2665 is->audio_src = is->audio_tgt;
2666 is->audio_buf_size = 0;
2667 is->audio_buf_index = 0;
2669 /* init averaging filter */
2670 is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
2671 is->audio_diff_avg_count = 0;
2672 /* since we do not have a precise anough audio FIFO fullness,
2673 we correct audio sync only if larger than this threshold */
2674 is->audio_diff_threshold = (double)(is->audio_hw_buf_size) / is->audio_tgt.bytes_per_sec;
2676 is->audio_stream = stream_index;
2677 is->audio_st = ic->streams[stream_index];
2679 decoder_init(&is->auddec, avctx, &is->audioq, is->continue_read_thread);
2680 if ((is->ic->iformat->flags & (AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH | AVFMT_NO_BYTE_SEEK)) && !is->ic->iformat->read_seek) {
2681 is->auddec.start_pts = is->audio_st->start_time;
2682 is->auddec.start_pts_tb = is->audio_st->time_base;
2684 if ((ret = decoder_start(&is->auddec, audio_thread, is)) < 0)
2686 SDL_PauseAudioDevice(audio_dev, 0);
2688 case AVMEDIA_TYPE_VIDEO:
2689 is->video_stream = stream_index;
2690 is->video_st = ic->streams[stream_index];
2692 decoder_init(&is->viddec, avctx, &is->videoq, is->continue_read_thread);
2693 if ((ret = decoder_start(&is->viddec, video_thread, is)) < 0)
2695 is->queue_attachments_req = 1;
2697 case AVMEDIA_TYPE_SUBTITLE:
2698 is->subtitle_stream = stream_index;
2699 is->subtitle_st = ic->streams[stream_index];
2701 decoder_init(&is->subdec, avctx, &is->subtitleq, is->continue_read_thread);
2702 if ((ret = decoder_start(&is->subdec, subtitle_thread, is)) < 0)
2711 avcodec_free_context(&avctx);
2713 av_dict_free(&opts);
2718 static int decode_interrupt_cb(void *ctx)
2720 VideoState *is = ctx;
2721 return is->abort_request;
2724 static int stream_has_enough_packets(AVStream *st, int stream_id, PacketQueue *queue) {
2725 return stream_id < 0 ||
2726 queue->abort_request ||
2727 (st->disposition & AV_DISPOSITION_ATTACHED_PIC) ||
2728 queue->nb_packets > MIN_FRAMES && (!queue->duration || av_q2d(st->time_base) * queue->duration > 1.0);
2731 static int is_realtime(AVFormatContext *s)
2733 if( !strcmp(s->iformat->name, "rtp")
2734 || !strcmp(s->iformat->name, "rtsp")
2735 || !strcmp(s->iformat->name, "sdp")
2739 if(s->pb && ( !strncmp(s->url, "rtp:", 4)
2740 || !strncmp(s->url, "udp:", 4)
2747 /* this thread gets the stream from the disk or the network */
2748 static int read_thread(void *arg)
2750 VideoState *is = arg;
2751 AVFormatContext *ic = NULL;
2753 int st_index[AVMEDIA_TYPE_NB];
2754 AVPacket pkt1, *pkt = &pkt1;
2755 int64_t stream_start_time;
2756 int pkt_in_play_range = 0;
2757 AVDictionaryEntry *t;
2758 SDL_mutex *wait_mutex = SDL_CreateMutex();
2759 int scan_all_pmts_set = 0;
2763 av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError());
2764 ret = AVERROR(ENOMEM);
2768 memset(st_index, -1, sizeof(st_index));
2769 is->last_video_stream = is->video_stream = -1;
2770 is->last_audio_stream = is->audio_stream = -1;
2771 is->last_subtitle_stream = is->subtitle_stream = -1;
2774 ic = avformat_alloc_context();
2776 av_log(NULL, AV_LOG_FATAL, "Could not allocate context.\n");
2777 ret = AVERROR(ENOMEM);
2780 ic->interrupt_callback.callback = decode_interrupt_cb;
2781 ic->interrupt_callback.opaque = is;
2782 if (!av_dict_get(format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE)) {
2783 av_dict_set(&format_opts, "scan_all_pmts", "1", AV_DICT_DONT_OVERWRITE);
2784 scan_all_pmts_set = 1;
2786 err = avformat_open_input(&ic, is->filename, is->iformat, &format_opts);
2788 print_error(is->filename, err);
2792 if (scan_all_pmts_set)
2793 av_dict_set(&format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE);
2795 if ((t = av_dict_get(format_opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
2796 av_log(NULL, AV_LOG_ERROR, "Option %s not found.\n", t->key);
2797 ret = AVERROR_OPTION_NOT_FOUND;
2803 ic->flags |= AVFMT_FLAG_GENPTS;
2805 av_format_inject_global_side_data(ic);
2807 if (find_stream_info) {
2808 AVDictionary **opts = setup_find_stream_info_opts(ic, codec_opts);
2809 int orig_nb_streams = ic->nb_streams;
2811 err = avformat_find_stream_info(ic, opts);
2813 for (i = 0; i < orig_nb_streams; i++)
2814 av_dict_free(&opts[i]);
2818 av_log(NULL, AV_LOG_WARNING,
2819 "%s: could not find codec parameters\n", is->filename);
2826 ic->pb->eof_reached = 0; // FIXME hack, ffplay maybe should not use avio_feof() to test for the end
2828 if (seek_by_bytes < 0)
2829 seek_by_bytes = !!(ic->iformat->flags & AVFMT_TS_DISCONT) && strcmp("ogg", ic->iformat->name);
2831 is->max_frame_duration = (ic->iformat->flags & AVFMT_TS_DISCONT) ? 10.0 : 3600.0;
2833 if (!window_title && (t = av_dict_get(ic->metadata, "title", NULL, 0)))
2834 window_title = av_asprintf("%s - %s", t->value, input_filename);
2836 /* if seeking requested, we execute it */
2837 if (start_time != AV_NOPTS_VALUE) {
2840 timestamp = start_time;
2841 /* add the stream start time */
2842 if (ic->start_time != AV_NOPTS_VALUE)
2843 timestamp += ic->start_time;
2844 ret = avformat_seek_file(ic, -1, INT64_MIN, timestamp, INT64_MAX, 0);
2846 av_log(NULL, AV_LOG_WARNING, "%s: could not seek to position %0.3f\n",
2847 is->filename, (double)timestamp / AV_TIME_BASE);
2851 is->realtime = is_realtime(ic);
2854 av_dump_format(ic, 0, is->filename, 0);
2856 for (i = 0; i < ic->nb_streams; i++) {
2857 AVStream *st = ic->streams[i];
2858 enum AVMediaType type = st->codecpar->codec_type;
2859 st->discard = AVDISCARD_ALL;
2860 if (type >= 0 && wanted_stream_spec[type] && st_index[type] == -1)
2861 if (avformat_match_stream_specifier(ic, st, wanted_stream_spec[type]) > 0)
2864 for (i = 0; i < AVMEDIA_TYPE_NB; i++) {
2865 if (wanted_stream_spec[i] && st_index[i] == -1) {
2866 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));
2867 st_index[i] = INT_MAX;
2872 st_index[AVMEDIA_TYPE_VIDEO] =
2873 av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO,
2874 st_index[AVMEDIA_TYPE_VIDEO], -1, NULL, 0);
2876 st_index[AVMEDIA_TYPE_AUDIO] =
2877 av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO,
2878 st_index[AVMEDIA_TYPE_AUDIO],
2879 st_index[AVMEDIA_TYPE_VIDEO],
2881 if (!video_disable && !subtitle_disable)
2882 st_index[AVMEDIA_TYPE_SUBTITLE] =
2883 av_find_best_stream(ic, AVMEDIA_TYPE_SUBTITLE,
2884 st_index[AVMEDIA_TYPE_SUBTITLE],
2885 (st_index[AVMEDIA_TYPE_AUDIO] >= 0 ?
2886 st_index[AVMEDIA_TYPE_AUDIO] :
2887 st_index[AVMEDIA_TYPE_VIDEO]),
2890 is->show_mode = show_mode;
2891 if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) {
2892 AVStream *st = ic->streams[st_index[AVMEDIA_TYPE_VIDEO]];
2893 AVCodecParameters *codecpar = st->codecpar;
2894 AVRational sar = av_guess_sample_aspect_ratio(ic, st, NULL);
2895 if (codecpar->width)
2896 set_default_window_size(codecpar->width, codecpar->height, sar);
2899 /* open the streams */
2900 if (st_index[AVMEDIA_TYPE_AUDIO] >= 0) {
2901 stream_component_open(is, st_index[AVMEDIA_TYPE_AUDIO]);
2905 if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) {
2906 ret = stream_component_open(is, st_index[AVMEDIA_TYPE_VIDEO]);
2908 if (is->show_mode == SHOW_MODE_NONE)
2909 is->show_mode = ret >= 0 ? SHOW_MODE_VIDEO : SHOW_MODE_RDFT;
2911 if (st_index[AVMEDIA_TYPE_SUBTITLE] >= 0) {
2912 stream_component_open(is, st_index[AVMEDIA_TYPE_SUBTITLE]);
2915 if (is->video_stream < 0 && is->audio_stream < 0) {
2916 av_log(NULL, AV_LOG_FATAL, "Failed to open file '%s' or configure filtergraph\n",
2922 if (infinite_buffer < 0 && is->realtime)
2923 infinite_buffer = 1;
2926 if (is->abort_request)
2928 if (is->paused != is->last_paused) {
2929 is->last_paused = is->paused;
2931 is->read_pause_return = av_read_pause(ic);
2935 #if CONFIG_RTSP_DEMUXER || CONFIG_MMSH_PROTOCOL
2937 (!strcmp(ic->iformat->name, "rtsp") ||
2938 (ic->pb && !strncmp(input_filename, "mmsh:", 5)))) {
2939 /* wait 10 ms to avoid trying to get another packet */
2946 int64_t seek_target = is->seek_pos;
2947 int64_t seek_min = is->seek_rel > 0 ? seek_target - is->seek_rel + 2: INT64_MIN;
2948 int64_t seek_max = is->seek_rel < 0 ? seek_target - is->seek_rel - 2: INT64_MAX;
2949 // FIXME the +-2 is due to rounding being not done in the correct direction in generation
2950 // of the seek_pos/seek_rel variables
2952 ret = avformat_seek_file(is->ic, -1, seek_min, seek_target, seek_max, is->seek_flags);
2954 av_log(NULL, AV_LOG_ERROR,
2955 "%s: error while seeking\n", is->ic->url);
2957 if (is->audio_stream >= 0) {
2958 packet_queue_flush(&is->audioq);
2959 packet_queue_put(&is->audioq, &flush_pkt);
2961 if (is->subtitle_stream >= 0) {
2962 packet_queue_flush(&is->subtitleq);
2963 packet_queue_put(&is->subtitleq, &flush_pkt);
2965 if (is->video_stream >= 0) {
2966 packet_queue_flush(&is->videoq);
2967 packet_queue_put(&is->videoq, &flush_pkt);
2969 if (is->seek_flags & AVSEEK_FLAG_BYTE) {
2970 set_clock(&is->extclk, NAN, 0);
2972 set_clock(&is->extclk, seek_target / (double)AV_TIME_BASE, 0);
2976 is->queue_attachments_req = 1;
2979 step_to_next_frame(is);
2981 if (is->queue_attachments_req) {
2982 if (is->video_st && is->video_st->disposition & AV_DISPOSITION_ATTACHED_PIC) {
2983 AVPacket copy = { 0 };
2984 if ((ret = av_packet_ref(©, &is->video_st->attached_pic)) < 0)
2986 packet_queue_put(&is->videoq, ©);
2987 packet_queue_put_nullpacket(&is->videoq, is->video_stream);
2989 is->queue_attachments_req = 0;
2992 /* if the queue are full, no need to read more */
2993 if (infinite_buffer<1 &&
2994 (is->audioq.size + is->videoq.size + is->subtitleq.size > MAX_QUEUE_SIZE
2995 || (stream_has_enough_packets(is->audio_st, is->audio_stream, &is->audioq) &&
2996 stream_has_enough_packets(is->video_st, is->video_stream, &is->videoq) &&
2997 stream_has_enough_packets(is->subtitle_st, is->subtitle_stream, &is->subtitleq)))) {
2999 SDL_LockMutex(wait_mutex);
3000 SDL_CondWaitTimeout(is->continue_read_thread, wait_mutex, 10);
3001 SDL_UnlockMutex(wait_mutex);
3005 (!is->audio_st || (is->auddec.finished == is->audioq.serial && frame_queue_nb_remaining(&is->sampq) == 0)) &&
3006 (!is->video_st || (is->viddec.finished == is->videoq.serial && frame_queue_nb_remaining(&is->pictq) == 0))) {
3007 if (loop != 1 && (!loop || --loop)) {
3008 stream_seek(is, start_time != AV_NOPTS_VALUE ? start_time : 0, 0, 0);
3009 } else if (autoexit) {
3014 ret = av_read_frame(ic, pkt);
3016 if ((ret == AVERROR_EOF || avio_feof(ic->pb)) && !is->eof) {
3017 if (is->video_stream >= 0)
3018 packet_queue_put_nullpacket(&is->videoq, is->video_stream);
3019 if (is->audio_stream >= 0)
3020 packet_queue_put_nullpacket(&is->audioq, is->audio_stream);
3021 if (is->subtitle_stream >= 0)
3022 packet_queue_put_nullpacket(&is->subtitleq, is->subtitle_stream);
3025 if (ic->pb && ic->pb->error)
3027 SDL_LockMutex(wait_mutex);
3028 SDL_CondWaitTimeout(is->continue_read_thread, wait_mutex, 10);
3029 SDL_UnlockMutex(wait_mutex);
3034 /* check if packet is in play range specified by user, then queue, otherwise discard */
3035 stream_start_time = ic->streams[pkt->stream_index]->start_time;
3036 pkt_ts = pkt->pts == AV_NOPTS_VALUE ? pkt->dts : pkt->pts;
3037 pkt_in_play_range = duration == AV_NOPTS_VALUE ||
3038 (pkt_ts - (stream_start_time != AV_NOPTS_VALUE ? stream_start_time : 0)) *
3039 av_q2d(ic->streams[pkt->stream_index]->time_base) -
3040 (double)(start_time != AV_NOPTS_VALUE ? start_time : 0) / 1000000
3041 <= ((double)duration / 1000000);
3042 if (pkt->stream_index == is->audio_stream && pkt_in_play_range) {
3043 packet_queue_put(&is->audioq, pkt);
3044 } else if (pkt->stream_index == is->video_stream && pkt_in_play_range
3045 && !(is->video_st->disposition & AV_DISPOSITION_ATTACHED_PIC)) {
3046 packet_queue_put(&is->videoq, pkt);
3047 } else if (pkt->stream_index == is->subtitle_stream && pkt_in_play_range) {
3048 packet_queue_put(&is->subtitleq, pkt);
3050 av_packet_unref(pkt);
3057 avformat_close_input(&ic);
3062 event.type = FF_QUIT_EVENT;
3063 event.user.data1 = is;
3064 SDL_PushEvent(&event);
3066 SDL_DestroyMutex(wait_mutex);
3070 static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
3074 is = av_mallocz(sizeof(VideoState));
3077 is->filename = av_strdup(filename);
3080 is->iformat = iformat;
3084 /* start video display */
3085 if (frame_queue_init(&is->pictq, &is->videoq, VIDEO_PICTURE_QUEUE_SIZE, 1) < 0)
3087 if (frame_queue_init(&is->subpq, &is->subtitleq, SUBPICTURE_QUEUE_SIZE, 0) < 0)
3089 if (frame_queue_init(&is->sampq, &is->audioq, SAMPLE_QUEUE_SIZE, 1) < 0)
3092 if (packet_queue_init(&is->videoq) < 0 ||
3093 packet_queue_init(&is->audioq) < 0 ||
3094 packet_queue_init(&is->subtitleq) < 0)
3097 if (!(is->continue_read_thread = SDL_CreateCond())) {
3098 av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError());
3102 init_clock(&is->vidclk, &is->videoq.serial);
3103 init_clock(&is->audclk, &is->audioq.serial);
3104 init_clock(&is->extclk, &is->extclk.serial);
3105 is->audio_clock_serial = -1;
3106 if (startup_volume < 0)
3107 av_log(NULL, AV_LOG_WARNING, "-volume=%d < 0, setting to 0\n", startup_volume);
3108 if (startup_volume > 100)
3109 av_log(NULL, AV_LOG_WARNING, "-volume=%d > 100, setting to 100\n", startup_volume);
3110 startup_volume = av_clip(startup_volume, 0, 100);
3111 startup_volume = av_clip(SDL_MIX_MAXVOLUME * startup_volume / 100, 0, SDL_MIX_MAXVOLUME);
3112 is->audio_volume = startup_volume;
3114 is->av_sync_type = av_sync_type;
3115 is->read_tid = SDL_CreateThread(read_thread, "read_thread", is);
3116 if (!is->read_tid) {
3117 av_log(NULL, AV_LOG_FATAL, "SDL_CreateThread(): %s\n", SDL_GetError());
3125 static void stream_cycle_channel(VideoState *is, int codec_type)
3127 AVFormatContext *ic = is->ic;
3128 int start_index, stream_index;
3131 AVProgram *p = NULL;
3132 int nb_streams = is->ic->nb_streams;
3134 if (codec_type == AVMEDIA_TYPE_VIDEO) {
3135 start_index = is->last_video_stream;
3136 old_index = is->video_stream;
3137 } else if (codec_type == AVMEDIA_TYPE_AUDIO) {
3138 start_index = is->last_audio_stream;
3139 old_index = is->audio_stream;
3141 start_index = is->last_subtitle_stream;
3142 old_index = is->subtitle_stream;
3144 stream_index = start_index;
3146 if (codec_type != AVMEDIA_TYPE_VIDEO && is->video_stream != -1) {
3147 p = av_find_program_from_stream(ic, NULL, is->video_stream);
3149 nb_streams = p->nb_stream_indexes;
3150 for (start_index = 0; start_index < nb_streams; start_index++)
3151 if (p->stream_index[start_index] == stream_index)
3153 if (start_index == nb_streams)
3155 stream_index = start_index;
3160 if (++stream_index >= nb_streams)
3162 if (codec_type == AVMEDIA_TYPE_SUBTITLE)
3165 is->last_subtitle_stream = -1;
3168 if (start_index == -1)
3172 if (stream_index == start_index)
3174 st = is->ic->streams[p ? p->stream_index[stream_index] : stream_index];
3175 if (st->codecpar->codec_type == codec_type) {
3176 /* check that parameters are OK */
3177 switch (codec_type) {
3178 case AVMEDIA_TYPE_AUDIO:
3179 if (st->codecpar->sample_rate != 0 &&
3180 st->codecpar->channels != 0)
3183 case AVMEDIA_TYPE_VIDEO:
3184 case AVMEDIA_TYPE_SUBTITLE:
3192 if (p && stream_index != -1)
3193 stream_index = p->stream_index[stream_index];
3194 av_log(NULL, AV_LOG_INFO, "Switch %s stream from #%d to #%d\n",
3195 av_get_media_type_string(codec_type),
3199 stream_component_close(is, old_index);
3200 stream_component_open(is, stream_index);
3204 static void toggle_full_screen(VideoState *is)
3206 is_full_screen = !is_full_screen;
3207 SDL_SetWindowFullscreen(window, is_full_screen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
3210 static void toggle_audio_display(VideoState *is)
3212 int next = is->show_mode;
3214 next = (next + 1) % SHOW_MODE_NB;
3215 } while (next != is->show_mode && (next == SHOW_MODE_VIDEO && !is->video_st || next != SHOW_MODE_VIDEO && !is->audio_st));
3216 if (is->show_mode != next) {
3217 is->force_refresh = 1;
3218 is->show_mode = next;
3222 static void refresh_loop_wait_event(VideoState *is, SDL_Event *event) {
3223 double remaining_time = 0.0;
3225 while (!SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)) {
3226 if (!cursor_hidden && av_gettime_relative() - cursor_last_shown > CURSOR_HIDE_DELAY) {
3230 if (remaining_time > 0.0)
3231 av_usleep((int64_t)(remaining_time * 1000000.0));
3232 remaining_time = REFRESH_RATE;
3233 if (is->show_mode != SHOW_MODE_NONE && (!is->paused || is->force_refresh))
3234 video_refresh(is, &remaining_time);
3239 static void seek_chapter(VideoState *is, int incr)
3241 int64_t pos = get_master_clock(is) * AV_TIME_BASE;
3244 if (!is->ic->nb_chapters)
3247 /* find the current chapter */
3248 for (i = 0; i < is->ic->nb_chapters; i++) {
3249 AVChapter *ch = is->ic->chapters[i];
3250 if (av_compare_ts(pos, AV_TIME_BASE_Q, ch->start, ch->time_base) < 0) {
3258 if (i >= is->ic->nb_chapters)
3261 av_log(NULL, AV_LOG_VERBOSE, "Seeking to chapter %d.\n", i);
3262 stream_seek(is, av_rescale_q(is->ic->chapters[i]->start, is->ic->chapters[i]->time_base,
3263 AV_TIME_BASE_Q), 0, 0);
3266 /* handle an event sent by the GUI */
3267 static void event_loop(VideoState *cur_stream)
3270 double incr, pos, frac;
3274 refresh_loop_wait_event(cur_stream, &event);
3275 switch (event.type) {
3277 if (exit_on_keydown || event.key.keysym.sym == SDLK_ESCAPE || event.key.keysym.sym == SDLK_q) {
3278 do_exit(cur_stream);
3281 // If we don't yet have a window, skip all key events, because read_thread might still be initializing...
3282 if (!cur_stream->width)
3284 switch (event.key.keysym.sym) {
3286 toggle_full_screen(cur_stream);
3287 cur_stream->force_refresh = 1;
3291 toggle_pause(cur_stream);
3294 toggle_mute(cur_stream);
3296 case SDLK_KP_MULTIPLY:
3298 update_volume(cur_stream, 1, SDL_VOLUME_STEP);
3300 case SDLK_KP_DIVIDE:
3302 update_volume(cur_stream, -1, SDL_VOLUME_STEP);
3304 case SDLK_s: // S: Step to next frame
3305 step_to_next_frame(cur_stream);
3308 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_AUDIO);
3311 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_VIDEO);
3314 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_VIDEO);
3315 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_AUDIO);
3316 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_SUBTITLE);
3319 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_SUBTITLE);
3323 if (cur_stream->show_mode == SHOW_MODE_VIDEO && cur_stream->vfilter_idx < nb_vfilters - 1) {
3324 if (++cur_stream->vfilter_idx >= nb_vfilters)
3325 cur_stream->vfilter_idx = 0;
3327 cur_stream->vfilter_idx = 0;
3328 toggle_audio_display(cur_stream);
3331 toggle_audio_display(cur_stream);
3335 if (cur_stream->ic->nb_chapters <= 1) {
3339 seek_chapter(cur_stream, 1);
3342 if (cur_stream->ic->nb_chapters <= 1) {
3346 seek_chapter(cur_stream, -1);
3349 incr = seek_interval ? -seek_interval : -10.0;
3352 incr = seek_interval ? seek_interval : 10.0;
3360 if (seek_by_bytes) {
3362 if (pos < 0 && cur_stream->video_stream >= 0)
3363 pos = frame_queue_last_pos(&cur_stream->pictq);
3364 if (pos < 0 && cur_stream->audio_stream >= 0)
3365 pos = frame_queue_last_pos(&cur_stream->sampq);
3367 pos = avio_tell(cur_stream->ic->pb);
3368 if (cur_stream->ic->bit_rate)
3369 incr *= cur_stream->ic->bit_rate / 8.0;
3373 stream_seek(cur_stream, pos, incr, 1);
3375 pos = get_master_clock(cur_stream);
3377 pos = (double)cur_stream->seek_pos / AV_TIME_BASE;
3379 if (cur_stream->ic->start_time != AV_NOPTS_VALUE && pos < cur_stream->ic->start_time / (double)AV_TIME_BASE)
3380 pos = cur_stream->ic->start_time / (double)AV_TIME_BASE;
3381 stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), (int64_t)(incr * AV_TIME_BASE), 0);
3388 case SDL_MOUSEBUTTONDOWN:
3389 if (exit_on_mousedown) {
3390 do_exit(cur_stream);
3393 if (event.button.button == SDL_BUTTON_LEFT) {
3394 static int64_t last_mouse_left_click = 0;
3395 if (av_gettime_relative() - last_mouse_left_click <= 500000) {
3396 toggle_full_screen(cur_stream);
3397 cur_stream->force_refresh = 1;
3398 last_mouse_left_click = 0;
3400 last_mouse_left_click = av_gettime_relative();
3403 case SDL_MOUSEMOTION:
3404 if (cursor_hidden) {
3408 cursor_last_shown = av_gettime_relative();
3409 if (event.type == SDL_MOUSEBUTTONDOWN) {
3410 if (event.button.button != SDL_BUTTON_RIGHT)
3414 if (!(event.motion.state & SDL_BUTTON_RMASK))
3418 if (seek_by_bytes || cur_stream->ic->duration <= 0) {
3419 uint64_t size = avio_size(cur_stream->ic->pb);
3420 stream_seek(cur_stream, size*x/cur_stream->width, 0, 1);
3424 int tns, thh, tmm, tss;
3425 tns = cur_stream->ic->duration / 1000000LL;
3427 tmm = (tns % 3600) / 60;
3429 frac = x / cur_stream->width;
3432 mm = (ns % 3600) / 60;
3434 av_log(NULL, AV_LOG_INFO,
3435 "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
3436 hh, mm, ss, thh, tmm, tss);
3437 ts = frac * cur_stream->ic->duration;
3438 if (cur_stream->ic->start_time != AV_NOPTS_VALUE)
3439 ts += cur_stream->ic->start_time;
3440 stream_seek(cur_stream, ts, 0, 0);
3443 case SDL_WINDOWEVENT:
3444 switch (event.window.event) {
3445 case SDL_WINDOWEVENT_RESIZED:
3446 screen_width = cur_stream->width = event.window.data1;
3447 screen_height = cur_stream->height = event.window.data2;
3448 if (cur_stream->vis_texture) {
3449 SDL_DestroyTexture(cur_stream->vis_texture);
3450 cur_stream->vis_texture = NULL;
3452 case SDL_WINDOWEVENT_EXPOSED:
3453 cur_stream->force_refresh = 1;
3458 do_exit(cur_stream);
3466 static int opt_frame_size(void *optctx, const char *opt, const char *arg)
3468 av_log(NULL, AV_LOG_WARNING, "Option -s is deprecated, use -video_size.\n");
3469 return opt_default(NULL, "video_size", arg);
3472 static int opt_width(void *optctx, const char *opt, const char *arg)
3474 screen_width = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
3478 static int opt_height(void *optctx, const char *opt, const char *arg)
3480 screen_height = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
3484 static int opt_format(void *optctx, const char *opt, const char *arg)
3486 file_iformat = av_find_input_format(arg);
3487 if (!file_iformat) {
3488 av_log(NULL, AV_LOG_FATAL, "Unknown input format: %s\n", arg);
3489 return AVERROR(EINVAL);
3494 static int opt_frame_pix_fmt(void *optctx, const char *opt, const char *arg)
3496 av_log(NULL, AV_LOG_WARNING, "Option -pix_fmt is deprecated, use -pixel_format.\n");
3497 return opt_default(NULL, "pixel_format", arg);
3500 static int opt_sync(void *optctx, const char *opt, const char *arg)
3502 if (!strcmp(arg, "audio"))
3503 av_sync_type = AV_SYNC_AUDIO_MASTER;
3504 else if (!strcmp(arg, "video"))
3505 av_sync_type = AV_SYNC_VIDEO_MASTER;
3506 else if (!strcmp(arg, "ext"))
3507 av_sync_type = AV_SYNC_EXTERNAL_CLOCK;
3509 av_log(NULL, AV_LOG_ERROR, "Unknown value for %s: %s\n", opt, arg);
3515 static int opt_seek(void *optctx, const char *opt, const char *arg)
3517 start_time = parse_time_or_die(opt, arg, 1);
3521 static int opt_duration(void *optctx, const char *opt, const char *arg)
3523 duration = parse_time_or_die(opt, arg, 1);
3527 static int opt_show_mode(void *optctx, const char *opt, const char *arg)
3529 show_mode = !strcmp(arg, "video") ? SHOW_MODE_VIDEO :
3530 !strcmp(arg, "waves") ? SHOW_MODE_WAVES :
3531 !strcmp(arg, "rdft" ) ? SHOW_MODE_RDFT :
3532 parse_number_or_die(opt, arg, OPT_INT, 0, SHOW_MODE_NB-1);
3536 static void opt_input_file(void *optctx, const char *filename)
3538 if (input_filename) {
3539 av_log(NULL, AV_LOG_FATAL,
3540 "Argument '%s' provided as input filename, but '%s' was already specified.\n",
3541 filename, input_filename);
3544 if (!strcmp(filename, "-"))
3546 input_filename = filename;
3549 static int opt_codec(void *optctx, const char *opt, const char *arg)
3551 const char *spec = strchr(opt, ':');
3553 av_log(NULL, AV_LOG_ERROR,
3554 "No media specifier was specified in '%s' in option '%s'\n",
3556 return AVERROR(EINVAL);
3560 case 'a' : audio_codec_name = arg; break;
3561 case 's' : subtitle_codec_name = arg; break;
3562 case 'v' : video_codec_name = arg; break;
3564 av_log(NULL, AV_LOG_ERROR,
3565 "Invalid media specifier '%s' in option '%s'\n", spec, opt);
3566 return AVERROR(EINVAL);
3573 static const OptionDef options[] = {
3574 CMDUTILS_COMMON_OPTIONS
3575 { "x", HAS_ARG, { .func_arg = opt_width }, "force displayed width", "width" },
3576 { "y", HAS_ARG, { .func_arg = opt_height }, "force displayed height", "height" },
3577 { "s", HAS_ARG | OPT_VIDEO, { .func_arg = opt_frame_size }, "set frame size (WxH or abbreviation)", "size" },
3578 { "fs", OPT_BOOL, { &is_full_screen }, "force full screen" },
3579 { "an", OPT_BOOL, { &audio_disable }, "disable audio" },
3580 { "vn", OPT_BOOL, { &video_disable }, "disable video" },
3581 { "sn", OPT_BOOL, { &subtitle_disable }, "disable subtitling" },
3582 { "ast", OPT_STRING | HAS_ARG | OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_AUDIO] }, "select desired audio stream", "stream_specifier" },
3583 { "vst", OPT_STRING | HAS_ARG | OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_VIDEO] }, "select desired video stream", "stream_specifier" },
3584 { "sst", OPT_STRING | HAS_ARG | OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_SUBTITLE] }, "select desired subtitle stream", "stream_specifier" },
3585 { "ss", HAS_ARG, { .func_arg = opt_seek }, "seek to a given position in seconds", "pos" },
3586 { "t", HAS_ARG, { .func_arg = opt_duration }, "play \"duration\" seconds of audio/video", "duration" },
3587 { "bytes", OPT_INT | HAS_ARG, { &seek_by_bytes }, "seek by bytes 0=off 1=on -1=auto", "val" },
3588 { "seek_interval", OPT_FLOAT | HAS_ARG, { &seek_interval }, "set seek interval for left/right keys, in seconds", "seconds" },
3589 { "nodisp", OPT_BOOL, { &display_disable }, "disable graphical display" },
3590 { "noborder", OPT_BOOL, { &borderless }, "borderless window" },
3591 { "volume", OPT_INT | HAS_ARG, { &startup_volume}, "set startup volume 0=min 100=max", "volume" },
3592 { "f", HAS_ARG, { .func_arg = opt_format }, "force format", "fmt" },
3593 { "pix_fmt", HAS_ARG | OPT_EXPERT | OPT_VIDEO, { .func_arg = opt_frame_pix_fmt }, "set pixel format", "format" },
3594 { "stats", OPT_BOOL | OPT_EXPERT, { &show_status }, "show status", "" },
3595 { "fast", OPT_BOOL | OPT_EXPERT, { &fast }, "non spec compliant optimizations", "" },
3596 { "genpts", OPT_BOOL | OPT_EXPERT, { &genpts }, "generate pts", "" },
3597 { "drp", OPT_INT | HAS_ARG | OPT_EXPERT, { &decoder_reorder_pts }, "let decoder reorder pts 0=off 1=on -1=auto", ""},
3598 { "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, { &lowres }, "", "" },
3599 { "sync", HAS_ARG | OPT_EXPERT, { .func_arg = opt_sync }, "set audio-video sync. type (type=audio/video/ext)", "type" },
3600 { "autoexit", OPT_BOOL | OPT_EXPERT, { &autoexit }, "exit at the end", "" },
3601 { "exitonkeydown", OPT_BOOL | OPT_EXPERT, { &exit_on_keydown }, "exit on key down", "" },
3602 { "exitonmousedown", OPT_BOOL | OPT_EXPERT, { &exit_on_mousedown }, "exit on mouse down", "" },
3603 { "loop", OPT_INT | HAS_ARG | OPT_EXPERT, { &loop }, "set number of times the playback shall be looped", "loop count" },
3604 { "framedrop", OPT_BOOL | OPT_EXPERT, { &framedrop }, "drop frames when cpu is too slow", "" },
3605 { "infbuf", OPT_BOOL | OPT_EXPERT, { &infinite_buffer }, "don't limit the input buffer size (useful with realtime streams)", "" },
3606 { "window_title", OPT_STRING | HAS_ARG, { &window_title }, "set window title", "window title" },
3607 { "left", OPT_INT | HAS_ARG | OPT_EXPERT, { &screen_left }, "set the x position for the left of the window", "x pos" },
3608 { "top", OPT_INT | HAS_ARG | OPT_EXPERT, { &screen_top }, "set the y position for the top of the window", "y pos" },
3610 { "vf", OPT_EXPERT | HAS_ARG, { .func_arg = opt_add_vfilter }, "set video filters", "filter_graph" },
3611 { "af", OPT_STRING | HAS_ARG, { &afilters }, "set audio filters", "filter_graph" },
3613 { "rdftspeed", OPT_INT | HAS_ARG| OPT_AUDIO | OPT_EXPERT, { &rdftspeed }, "rdft speed", "msecs" },
3614 { "showmode", HAS_ARG, { .func_arg = opt_show_mode}, "select show mode (0 = video, 1 = waves, 2 = RDFT)", "mode" },
3615 { "default", HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, { .func_arg = opt_default }, "generic catch all option", "" },
3616 { "i", OPT_BOOL, { &dummy}, "read specified file", "input_file"},
3617 { "codec", HAS_ARG, { .func_arg = opt_codec}, "force decoder", "decoder_name" },
3618 { "acodec", HAS_ARG | OPT_STRING | OPT_EXPERT, { &audio_codec_name }, "force audio decoder", "decoder_name" },
3619 { "scodec", HAS_ARG | OPT_STRING | OPT_EXPERT, { &subtitle_codec_name }, "force subtitle decoder", "decoder_name" },
3620 { "vcodec", HAS_ARG | OPT_STRING | OPT_EXPERT, { &video_codec_name }, "force video decoder", "decoder_name" },
3621 { "autorotate", OPT_BOOL, { &autorotate }, "automatically rotate video", "" },
3622 { "find_stream_info", OPT_BOOL | OPT_INPUT | OPT_EXPERT, { &find_stream_info },
3623 "read and decode the streams to fill missing information with heuristics" },
3627 static void show_usage(void)
3629 av_log(NULL, AV_LOG_INFO, "Simple media player\n");
3630 av_log(NULL, AV_LOG_INFO, "usage: %s [options] input_file\n", program_name);
3631 av_log(NULL, AV_LOG_INFO, "\n");
3634 void show_help_default(const char *opt, const char *arg)
3636 av_log_set_callback(log_callback_help);
3638 show_help_options(options, "Main options:", 0, OPT_EXPERT, 0);
3639 show_help_options(options, "Advanced options:", OPT_EXPERT, 0, 0);
3641 show_help_children(avcodec_get_class(), AV_OPT_FLAG_DECODING_PARAM);
3642 show_help_children(avformat_get_class(), AV_OPT_FLAG_DECODING_PARAM);
3643 #if !CONFIG_AVFILTER
3644 show_help_children(sws_get_class(), AV_OPT_FLAG_ENCODING_PARAM);
3646 show_help_children(avfilter_get_class(), AV_OPT_FLAG_FILTERING_PARAM);
3648 printf("\nWhile playing:\n"
3650 "f toggle full screen\n"
3653 "9, 0 decrease and increase volume respectively\n"
3654 "/, * decrease and increase volume respectively\n"
3655 "a cycle audio channel in the current program\n"
3656 "v cycle video channel\n"
3657 "t cycle subtitle channel in the current program\n"
3659 "w cycle video filters or show modes\n"
3660 "s activate frame-step mode\n"
3661 "left/right seek backward/forward 10 seconds or to custom interval if -seek_interval is set\n"
3662 "down/up seek backward/forward 1 minute\n"
3663 "page down/page up seek backward/forward 10 minutes\n"
3664 "right mouse click seek to percentage in file corresponding to fraction of width\n"
3665 "left double-click toggle full screen\n"
3669 /* Called from the main */
3670 int main(int argc, char **argv)
3677 av_log_set_flags(AV_LOG_SKIP_REPEATED);
3678 parse_loglevel(argc, argv, options);
3680 /* register all codecs, demux and protocols */
3682 avdevice_register_all();
3684 avformat_network_init();
3688 signal(SIGINT , sigterm_handler); /* Interrupt (ANSI). */
3689 signal(SIGTERM, sigterm_handler); /* Termination (ANSI). */
3691 show_banner(argc, argv, options);
3693 parse_options(NULL, argc, argv, options, opt_input_file);
3695 if (!input_filename) {
3697 av_log(NULL, AV_LOG_FATAL, "An input file must be specified\n");
3698 av_log(NULL, AV_LOG_FATAL,
3699 "Use -h to get full help or, even better, run 'man %s'\n", program_name);
3703 if (display_disable) {
3706 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
3708 flags &= ~SDL_INIT_AUDIO;
3710 /* Try to work around an occasional ALSA buffer underflow issue when the
3711 * period size is NPOT due to ALSA resampling by forcing the buffer size. */
3712 if (!SDL_getenv("SDL_AUDIO_ALSA_SET_BUFFER_SIZE"))
3713 SDL_setenv("SDL_AUDIO_ALSA_SET_BUFFER_SIZE","1", 1);
3715 if (display_disable)
3716 flags &= ~SDL_INIT_VIDEO;
3717 if (SDL_Init (flags)) {
3718 av_log(NULL, AV_LOG_FATAL, "Could not initialize SDL - %s\n", SDL_GetError());
3719 av_log(NULL, AV_LOG_FATAL, "(Did you set the DISPLAY variable?)\n");
3723 SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
3724 SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
3726 av_init_packet(&flush_pkt);
3727 flush_pkt.data = (uint8_t *)&flush_pkt;
3729 if (!display_disable) {
3730 int flags = SDL_WINDOW_HIDDEN;
3732 flags |= SDL_WINDOW_BORDERLESS;
3734 flags |= SDL_WINDOW_RESIZABLE;
3735 window = SDL_CreateWindow(program_name, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, default_width, default_height, flags);
3736 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
3738 renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
3740 av_log(NULL, AV_LOG_WARNING, "Failed to initialize a hardware accelerated renderer: %s\n", SDL_GetError());
3741 renderer = SDL_CreateRenderer(window, -1, 0);
3744 if (!SDL_GetRendererInfo(renderer, &renderer_info))
3745 av_log(NULL, AV_LOG_VERBOSE, "Initialized %s renderer.\n", renderer_info.name);
3748 if (!window || !renderer || !renderer_info.num_texture_formats) {
3749 av_log(NULL, AV_LOG_FATAL, "Failed to create window or renderer: %s", SDL_GetError());
3754 is = stream_open(input_filename, file_iformat);
3756 av_log(NULL, AV_LOG_FATAL, "Failed to initialize VideoState!\n");