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 audio_disable;
318 static int video_disable;
319 static int subtitle_disable;
320 static const char* wanted_stream_spec[AVMEDIA_TYPE_NB] = {0};
321 static int seek_by_bytes = -1;
322 static int display_disable;
323 static int borderless;
324 static int startup_volume = 100;
325 static int show_status = 1;
326 static int av_sync_type = AV_SYNC_AUDIO_MASTER;
327 static int64_t start_time = AV_NOPTS_VALUE;
328 static int64_t duration = AV_NOPTS_VALUE;
330 static int genpts = 0;
331 static int lowres = 0;
332 static int decoder_reorder_pts = -1;
334 static int exit_on_keydown;
335 static int exit_on_mousedown;
337 static int framedrop = -1;
338 static int infinite_buffer = -1;
339 static enum ShowMode show_mode = SHOW_MODE_NONE;
340 static const char *audio_codec_name;
341 static const char *subtitle_codec_name;
342 static const char *video_codec_name;
343 double rdftspeed = 0.02;
344 static int64_t cursor_last_shown;
345 static int cursor_hidden = 0;
347 static const char **vfilters_list = NULL;
348 static int nb_vfilters = 0;
349 static char *afilters = NULL;
351 static int autorotate = 1;
352 static int find_stream_info = 1;
354 /* current context */
355 static int is_full_screen;
356 static int64_t audio_callback_time;
358 static AVPacket flush_pkt;
360 #define FF_QUIT_EVENT (SDL_USEREVENT + 2)
362 static SDL_Window *window;
363 static SDL_Renderer *renderer;
364 static SDL_RendererInfo renderer_info = {0};
365 static SDL_AudioDeviceID audio_dev;
367 static const struct TextureFormatEntry {
368 enum AVPixelFormat format;
370 } sdl_texture_format_map[] = {
371 { AV_PIX_FMT_RGB8, SDL_PIXELFORMAT_RGB332 },
372 { AV_PIX_FMT_RGB444, SDL_PIXELFORMAT_RGB444 },
373 { AV_PIX_FMT_RGB555, SDL_PIXELFORMAT_RGB555 },
374 { AV_PIX_FMT_BGR555, SDL_PIXELFORMAT_BGR555 },
375 { AV_PIX_FMT_RGB565, SDL_PIXELFORMAT_RGB565 },
376 { AV_PIX_FMT_BGR565, SDL_PIXELFORMAT_BGR565 },
377 { AV_PIX_FMT_RGB24, SDL_PIXELFORMAT_RGB24 },
378 { AV_PIX_FMT_BGR24, SDL_PIXELFORMAT_BGR24 },
379 { AV_PIX_FMT_0RGB32, SDL_PIXELFORMAT_RGB888 },
380 { AV_PIX_FMT_0BGR32, SDL_PIXELFORMAT_BGR888 },
381 { AV_PIX_FMT_NE(RGB0, 0BGR), SDL_PIXELFORMAT_RGBX8888 },
382 { AV_PIX_FMT_NE(BGR0, 0RGB), SDL_PIXELFORMAT_BGRX8888 },
383 { AV_PIX_FMT_RGB32, SDL_PIXELFORMAT_ARGB8888 },
384 { AV_PIX_FMT_RGB32_1, SDL_PIXELFORMAT_RGBA8888 },
385 { AV_PIX_FMT_BGR32, SDL_PIXELFORMAT_ABGR8888 },
386 { AV_PIX_FMT_BGR32_1, SDL_PIXELFORMAT_BGRA8888 },
387 { AV_PIX_FMT_YUV420P, SDL_PIXELFORMAT_IYUV },
388 { AV_PIX_FMT_YUYV422, SDL_PIXELFORMAT_YUY2 },
389 { AV_PIX_FMT_UYVY422, SDL_PIXELFORMAT_UYVY },
390 { AV_PIX_FMT_NONE, SDL_PIXELFORMAT_UNKNOWN },
394 static int opt_add_vfilter(void *optctx, const char *opt, const char *arg)
396 GROW_ARRAY(vfilters_list, nb_vfilters);
397 vfilters_list[nb_vfilters - 1] = arg;
403 int cmp_audio_fmts(enum AVSampleFormat fmt1, int64_t channel_count1,
404 enum AVSampleFormat fmt2, int64_t channel_count2)
406 /* If channel count == 1, planar and non-planar formats are the same */
407 if (channel_count1 == 1 && channel_count2 == 1)
408 return av_get_packed_sample_fmt(fmt1) != av_get_packed_sample_fmt(fmt2);
410 return channel_count1 != channel_count2 || fmt1 != fmt2;
414 int64_t get_valid_channel_layout(int64_t channel_layout, int channels)
416 if (channel_layout && av_get_channel_layout_nb_channels(channel_layout) == channels)
417 return channel_layout;
422 static int packet_queue_put_private(PacketQueue *q, AVPacket *pkt)
424 MyAVPacketList *pkt1;
426 if (q->abort_request)
429 pkt1 = av_malloc(sizeof(MyAVPacketList));
434 if (pkt == &flush_pkt)
436 pkt1->serial = q->serial;
441 q->last_pkt->next = pkt1;
444 q->size += pkt1->pkt.size + sizeof(*pkt1);
445 q->duration += pkt1->pkt.duration;
446 /* XXX: should duplicate packet data in DV case */
447 SDL_CondSignal(q->cond);
451 static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
455 SDL_LockMutex(q->mutex);
456 ret = packet_queue_put_private(q, pkt);
457 SDL_UnlockMutex(q->mutex);
459 if (pkt != &flush_pkt && ret < 0)
460 av_packet_unref(pkt);
465 static int packet_queue_put_nullpacket(PacketQueue *q, int stream_index)
467 AVPacket pkt1, *pkt = &pkt1;
471 pkt->stream_index = stream_index;
472 return packet_queue_put(q, pkt);
475 /* packet queue handling */
476 static int packet_queue_init(PacketQueue *q)
478 memset(q, 0, sizeof(PacketQueue));
479 q->mutex = SDL_CreateMutex();
481 av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError());
482 return AVERROR(ENOMEM);
484 q->cond = SDL_CreateCond();
486 av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError());
487 return AVERROR(ENOMEM);
489 q->abort_request = 1;
493 static void packet_queue_flush(PacketQueue *q)
495 MyAVPacketList *pkt, *pkt1;
497 SDL_LockMutex(q->mutex);
498 for (pkt = q->first_pkt; pkt; pkt = pkt1) {
500 av_packet_unref(&pkt->pkt);
508 SDL_UnlockMutex(q->mutex);
511 static void packet_queue_destroy(PacketQueue *q)
513 packet_queue_flush(q);
514 SDL_DestroyMutex(q->mutex);
515 SDL_DestroyCond(q->cond);
518 static void packet_queue_abort(PacketQueue *q)
520 SDL_LockMutex(q->mutex);
522 q->abort_request = 1;
524 SDL_CondSignal(q->cond);
526 SDL_UnlockMutex(q->mutex);
529 static void packet_queue_start(PacketQueue *q)
531 SDL_LockMutex(q->mutex);
532 q->abort_request = 0;
533 packet_queue_put_private(q, &flush_pkt);
534 SDL_UnlockMutex(q->mutex);
537 /* return < 0 if aborted, 0 if no packet and > 0 if packet. */
538 static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block, int *serial)
540 MyAVPacketList *pkt1;
543 SDL_LockMutex(q->mutex);
546 if (q->abort_request) {
553 q->first_pkt = pkt1->next;
557 q->size -= pkt1->pkt.size + sizeof(*pkt1);
558 q->duration -= pkt1->pkt.duration;
561 *serial = pkt1->serial;
569 SDL_CondWait(q->cond, q->mutex);
572 SDL_UnlockMutex(q->mutex);
576 static void decoder_init(Decoder *d, AVCodecContext *avctx, PacketQueue *queue, SDL_cond *empty_queue_cond) {
577 memset(d, 0, sizeof(Decoder));
580 d->empty_queue_cond = empty_queue_cond;
581 d->start_pts = AV_NOPTS_VALUE;
585 static int decoder_decode_frame(Decoder *d, AVFrame *frame, AVSubtitle *sub) {
586 int ret = AVERROR(EAGAIN);
591 if (d->queue->serial == d->pkt_serial) {
593 if (d->queue->abort_request)
596 switch (d->avctx->codec_type) {
597 case AVMEDIA_TYPE_VIDEO:
598 ret = avcodec_receive_frame(d->avctx, frame);
600 if (decoder_reorder_pts == -1) {
601 frame->pts = frame->best_effort_timestamp;
602 } else if (!decoder_reorder_pts) {
603 frame->pts = frame->pkt_dts;
607 case AVMEDIA_TYPE_AUDIO:
608 ret = avcodec_receive_frame(d->avctx, frame);
610 AVRational tb = (AVRational){1, frame->sample_rate};
611 if (frame->pts != AV_NOPTS_VALUE)
612 frame->pts = av_rescale_q(frame->pts, d->avctx->pkt_timebase, tb);
613 else if (d->next_pts != AV_NOPTS_VALUE)
614 frame->pts = av_rescale_q(d->next_pts, d->next_pts_tb, tb);
615 if (frame->pts != AV_NOPTS_VALUE) {
616 d->next_pts = frame->pts + frame->nb_samples;
622 if (ret == AVERROR_EOF) {
623 d->finished = d->pkt_serial;
624 avcodec_flush_buffers(d->avctx);
629 } while (ret != AVERROR(EAGAIN));
633 if (d->queue->nb_packets == 0)
634 SDL_CondSignal(d->empty_queue_cond);
635 if (d->packet_pending) {
636 av_packet_move_ref(&pkt, &d->pkt);
637 d->packet_pending = 0;
639 if (packet_queue_get(d->queue, &pkt, 1, &d->pkt_serial) < 0)
642 } while (d->queue->serial != d->pkt_serial);
644 if (pkt.data == flush_pkt.data) {
645 avcodec_flush_buffers(d->avctx);
647 d->next_pts = d->start_pts;
648 d->next_pts_tb = d->start_pts_tb;
650 if (d->avctx->codec_type == AVMEDIA_TYPE_SUBTITLE) {
652 ret = avcodec_decode_subtitle2(d->avctx, sub, &got_frame, &pkt);
654 ret = AVERROR(EAGAIN);
656 if (got_frame && !pkt.data) {
657 d->packet_pending = 1;
658 av_packet_move_ref(&d->pkt, &pkt);
660 ret = got_frame ? 0 : (pkt.data ? AVERROR(EAGAIN) : AVERROR_EOF);
663 if (avcodec_send_packet(d->avctx, &pkt) == AVERROR(EAGAIN)) {
664 av_log(d->avctx, AV_LOG_ERROR, "Receive_frame and send_packet both returned EAGAIN, which is an API violation.\n");
665 d->packet_pending = 1;
666 av_packet_move_ref(&d->pkt, &pkt);
669 av_packet_unref(&pkt);
674 static void decoder_destroy(Decoder *d) {
675 av_packet_unref(&d->pkt);
676 avcodec_free_context(&d->avctx);
679 static void frame_queue_unref_item(Frame *vp)
681 av_frame_unref(vp->frame);
682 avsubtitle_free(&vp->sub);
685 static int frame_queue_init(FrameQueue *f, PacketQueue *pktq, int max_size, int keep_last)
688 memset(f, 0, sizeof(FrameQueue));
689 if (!(f->mutex = SDL_CreateMutex())) {
690 av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError());
691 return AVERROR(ENOMEM);
693 if (!(f->cond = SDL_CreateCond())) {
694 av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError());
695 return AVERROR(ENOMEM);
698 f->max_size = FFMIN(max_size, FRAME_QUEUE_SIZE);
699 f->keep_last = !!keep_last;
700 for (i = 0; i < f->max_size; i++)
701 if (!(f->queue[i].frame = av_frame_alloc()))
702 return AVERROR(ENOMEM);
706 static void frame_queue_destory(FrameQueue *f)
709 for (i = 0; i < f->max_size; i++) {
710 Frame *vp = &f->queue[i];
711 frame_queue_unref_item(vp);
712 av_frame_free(&vp->frame);
714 SDL_DestroyMutex(f->mutex);
715 SDL_DestroyCond(f->cond);
718 static void frame_queue_signal(FrameQueue *f)
720 SDL_LockMutex(f->mutex);
721 SDL_CondSignal(f->cond);
722 SDL_UnlockMutex(f->mutex);
725 static Frame *frame_queue_peek(FrameQueue *f)
727 return &f->queue[(f->rindex + f->rindex_shown) % f->max_size];
730 static Frame *frame_queue_peek_next(FrameQueue *f)
732 return &f->queue[(f->rindex + f->rindex_shown + 1) % f->max_size];
735 static Frame *frame_queue_peek_last(FrameQueue *f)
737 return &f->queue[f->rindex];
740 static Frame *frame_queue_peek_writable(FrameQueue *f)
742 /* wait until we have space to put a new frame */
743 SDL_LockMutex(f->mutex);
744 while (f->size >= f->max_size &&
745 !f->pktq->abort_request) {
746 SDL_CondWait(f->cond, f->mutex);
748 SDL_UnlockMutex(f->mutex);
750 if (f->pktq->abort_request)
753 return &f->queue[f->windex];
756 static Frame *frame_queue_peek_readable(FrameQueue *f)
758 /* wait until we have a readable a new frame */
759 SDL_LockMutex(f->mutex);
760 while (f->size - f->rindex_shown <= 0 &&
761 !f->pktq->abort_request) {
762 SDL_CondWait(f->cond, f->mutex);
764 SDL_UnlockMutex(f->mutex);
766 if (f->pktq->abort_request)
769 return &f->queue[(f->rindex + f->rindex_shown) % f->max_size];
772 static void frame_queue_push(FrameQueue *f)
774 if (++f->windex == f->max_size)
776 SDL_LockMutex(f->mutex);
778 SDL_CondSignal(f->cond);
779 SDL_UnlockMutex(f->mutex);
782 static void frame_queue_next(FrameQueue *f)
784 if (f->keep_last && !f->rindex_shown) {
788 frame_queue_unref_item(&f->queue[f->rindex]);
789 if (++f->rindex == f->max_size)
791 SDL_LockMutex(f->mutex);
793 SDL_CondSignal(f->cond);
794 SDL_UnlockMutex(f->mutex);
797 /* return the number of undisplayed frames in the queue */
798 static int frame_queue_nb_remaining(FrameQueue *f)
800 return f->size - f->rindex_shown;
803 /* return last shown position */
804 static int64_t frame_queue_last_pos(FrameQueue *f)
806 Frame *fp = &f->queue[f->rindex];
807 if (f->rindex_shown && fp->serial == f->pktq->serial)
813 static void decoder_abort(Decoder *d, FrameQueue *fq)
815 packet_queue_abort(d->queue);
816 frame_queue_signal(fq);
817 SDL_WaitThread(d->decoder_tid, NULL);
818 d->decoder_tid = NULL;
819 packet_queue_flush(d->queue);
822 static inline void fill_rectangle(int x, int y, int w, int h)
830 SDL_RenderFillRect(renderer, &rect);
833 static int realloc_texture(SDL_Texture **texture, Uint32 new_format, int new_width, int new_height, SDL_BlendMode blendmode, int init_texture)
837 if (SDL_QueryTexture(*texture, &format, &access, &w, &h) < 0 || new_width != w || new_height != h || new_format != format) {
840 SDL_DestroyTexture(*texture);
841 if (!(*texture = SDL_CreateTexture(renderer, new_format, SDL_TEXTUREACCESS_STREAMING, new_width, new_height)))
843 if (SDL_SetTextureBlendMode(*texture, blendmode) < 0)
846 if (SDL_LockTexture(*texture, NULL, &pixels, &pitch) < 0)
848 memset(pixels, 0, pitch * new_height);
849 SDL_UnlockTexture(*texture);
851 av_log(NULL, AV_LOG_VERBOSE, "Created %dx%d texture with %s.\n", new_width, new_height, SDL_GetPixelFormatName(new_format));
856 static void calculate_display_rect(SDL_Rect *rect,
857 int scr_xleft, int scr_ytop, int scr_width, int scr_height,
858 int pic_width, int pic_height, AVRational pic_sar)
861 int width, height, x, y;
863 if (pic_sar.num == 0)
866 aspect_ratio = av_q2d(pic_sar);
868 if (aspect_ratio <= 0.0)
870 aspect_ratio *= (float)pic_width / (float)pic_height;
872 /* XXX: we suppose the screen has a 1.0 pixel ratio */
874 width = lrint(height * aspect_ratio) & ~1;
875 if (width > scr_width) {
877 height = lrint(width / aspect_ratio) & ~1;
879 x = (scr_width - width) / 2;
880 y = (scr_height - height) / 2;
881 rect->x = scr_xleft + x;
882 rect->y = scr_ytop + y;
883 rect->w = FFMAX(width, 1);
884 rect->h = FFMAX(height, 1);
887 static void get_sdl_pix_fmt_and_blendmode(int format, Uint32 *sdl_pix_fmt, SDL_BlendMode *sdl_blendmode)
890 *sdl_blendmode = SDL_BLENDMODE_NONE;
891 *sdl_pix_fmt = SDL_PIXELFORMAT_UNKNOWN;
892 if (format == AV_PIX_FMT_RGB32 ||
893 format == AV_PIX_FMT_RGB32_1 ||
894 format == AV_PIX_FMT_BGR32 ||
895 format == AV_PIX_FMT_BGR32_1)
896 *sdl_blendmode = SDL_BLENDMODE_BLEND;
897 for (i = 0; i < FF_ARRAY_ELEMS(sdl_texture_format_map) - 1; i++) {
898 if (format == sdl_texture_format_map[i].format) {
899 *sdl_pix_fmt = sdl_texture_format_map[i].texture_fmt;
905 static int upload_texture(SDL_Texture **tex, AVFrame *frame, struct SwsContext **img_convert_ctx) {
908 SDL_BlendMode sdl_blendmode;
909 get_sdl_pix_fmt_and_blendmode(frame->format, &sdl_pix_fmt, &sdl_blendmode);
910 if (realloc_texture(tex, sdl_pix_fmt == SDL_PIXELFORMAT_UNKNOWN ? SDL_PIXELFORMAT_ARGB8888 : sdl_pix_fmt, frame->width, frame->height, sdl_blendmode, 0) < 0)
912 switch (sdl_pix_fmt) {
913 case SDL_PIXELFORMAT_UNKNOWN:
914 /* This should only happen if we are not using avfilter... */
915 *img_convert_ctx = sws_getCachedContext(*img_convert_ctx,
916 frame->width, frame->height, frame->format, frame->width, frame->height,
917 AV_PIX_FMT_BGRA, sws_flags, NULL, NULL, NULL);
918 if (*img_convert_ctx != NULL) {
921 if (!SDL_LockTexture(*tex, NULL, (void **)pixels, pitch)) {
922 sws_scale(*img_convert_ctx, (const uint8_t * const *)frame->data, frame->linesize,
923 0, frame->height, pixels, pitch);
924 SDL_UnlockTexture(*tex);
927 av_log(NULL, AV_LOG_FATAL, "Cannot initialize the conversion context\n");
931 case SDL_PIXELFORMAT_IYUV:
932 if (frame->linesize[0] > 0 && frame->linesize[1] > 0 && frame->linesize[2] > 0) {
933 ret = SDL_UpdateYUVTexture(*tex, NULL, frame->data[0], frame->linesize[0],
934 frame->data[1], frame->linesize[1],
935 frame->data[2], frame->linesize[2]);
936 } else 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] * (frame->height - 1), -frame->linesize[0],
938 frame->data[1] + frame->linesize[1] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[1],
939 frame->data[2] + frame->linesize[2] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[2]);
941 av_log(NULL, AV_LOG_ERROR, "Mixed negative and positive linesizes are not supported.\n");
946 if (frame->linesize[0] < 0) {
947 ret = SDL_UpdateTexture(*tex, NULL, frame->data[0] + frame->linesize[0] * (frame->height - 1), -frame->linesize[0]);
949 ret = SDL_UpdateTexture(*tex, NULL, frame->data[0], frame->linesize[0]);
956 static void video_image_display(VideoState *is)
962 vp = frame_queue_peek_last(&is->pictq);
963 if (is->subtitle_st) {
964 if (frame_queue_nb_remaining(&is->subpq) > 0) {
965 sp = frame_queue_peek(&is->subpq);
967 if (vp->pts >= sp->pts + ((float) sp->sub.start_display_time / 1000)) {
972 if (!sp->width || !sp->height) {
973 sp->width = vp->width;
974 sp->height = vp->height;
976 if (realloc_texture(&is->sub_texture, SDL_PIXELFORMAT_ARGB8888, sp->width, sp->height, SDL_BLENDMODE_BLEND, 1) < 0)
979 for (i = 0; i < sp->sub.num_rects; i++) {
980 AVSubtitleRect *sub_rect = sp->sub.rects[i];
982 sub_rect->x = av_clip(sub_rect->x, 0, sp->width );
983 sub_rect->y = av_clip(sub_rect->y, 0, sp->height);
984 sub_rect->w = av_clip(sub_rect->w, 0, sp->width - sub_rect->x);
985 sub_rect->h = av_clip(sub_rect->h, 0, sp->height - sub_rect->y);
987 is->sub_convert_ctx = sws_getCachedContext(is->sub_convert_ctx,
988 sub_rect->w, sub_rect->h, AV_PIX_FMT_PAL8,
989 sub_rect->w, sub_rect->h, AV_PIX_FMT_BGRA,
990 0, NULL, NULL, NULL);
991 if (!is->sub_convert_ctx) {
992 av_log(NULL, AV_LOG_FATAL, "Cannot initialize the conversion context\n");
995 if (!SDL_LockTexture(is->sub_texture, (SDL_Rect *)sub_rect, (void **)pixels, pitch)) {
996 sws_scale(is->sub_convert_ctx, (const uint8_t * const *)sub_rect->data, sub_rect->linesize,
997 0, sub_rect->h, pixels, pitch);
998 SDL_UnlockTexture(is->sub_texture);
1008 calculate_display_rect(&rect, is->xleft, is->ytop, is->width, is->height, vp->width, vp->height, vp->sar);
1010 if (!vp->uploaded) {
1011 if (upload_texture(&is->vid_texture, vp->frame, &is->img_convert_ctx) < 0)
1014 vp->flip_v = vp->frame->linesize[0] < 0;
1017 SDL_RenderCopyEx(renderer, is->vid_texture, NULL, &rect, 0, NULL, vp->flip_v ? SDL_FLIP_VERTICAL : 0);
1019 #if USE_ONEPASS_SUBTITLE_RENDER
1020 SDL_RenderCopy(renderer, is->sub_texture, NULL, &rect);
1023 double xratio = (double)rect.w / (double)sp->width;
1024 double yratio = (double)rect.h / (double)sp->height;
1025 for (i = 0; i < sp->sub.num_rects; i++) {
1026 SDL_Rect *sub_rect = (SDL_Rect*)sp->sub.rects[i];
1027 SDL_Rect target = {.x = rect.x + sub_rect->x * xratio,
1028 .y = rect.y + sub_rect->y * yratio,
1029 .w = sub_rect->w * xratio,
1030 .h = sub_rect->h * yratio};
1031 SDL_RenderCopy(renderer, is->sub_texture, sub_rect, &target);
1037 static inline int compute_mod(int a, int b)
1039 return a < 0 ? a%b + b : a%b;
1042 static void video_audio_display(VideoState *s)
1044 int i, i_start, x, y1, y, ys, delay, n, nb_display_channels;
1045 int ch, channels, h, h2;
1047 int rdft_bits, nb_freq;
1049 for (rdft_bits = 1; (1 << rdft_bits) < 2 * s->height; rdft_bits++)
1051 nb_freq = 1 << (rdft_bits - 1);
1053 /* compute display index : center on currently output samples */
1054 channels = s->audio_tgt.channels;
1055 nb_display_channels = channels;
1057 int data_used= s->show_mode == SHOW_MODE_WAVES ? s->width : (2*nb_freq);
1059 delay = s->audio_write_buf_size;
1062 /* to be more precise, we take into account the time spent since
1063 the last buffer computation */
1064 if (audio_callback_time) {
1065 time_diff = av_gettime_relative() - audio_callback_time;
1066 delay -= (time_diff * s->audio_tgt.freq) / 1000000;
1069 delay += 2 * data_used;
1070 if (delay < data_used)
1073 i_start= x = compute_mod(s->sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE);
1074 if (s->show_mode == SHOW_MODE_WAVES) {
1076 for (i = 0; i < 1000; i += channels) {
1077 int idx = (SAMPLE_ARRAY_SIZE + x - i) % SAMPLE_ARRAY_SIZE;
1078 int a = s->sample_array[idx];
1079 int b = s->sample_array[(idx + 4 * channels) % SAMPLE_ARRAY_SIZE];
1080 int c = s->sample_array[(idx + 5 * channels) % SAMPLE_ARRAY_SIZE];
1081 int d = s->sample_array[(idx + 9 * channels) % SAMPLE_ARRAY_SIZE];
1083 if (h < score && (b ^ c) < 0) {
1090 s->last_i_start = i_start;
1092 i_start = s->last_i_start;
1095 if (s->show_mode == SHOW_MODE_WAVES) {
1096 SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
1098 /* total height for one channel */
1099 h = s->height / nb_display_channels;
1100 /* graph height / 2 */
1102 for (ch = 0; ch < nb_display_channels; ch++) {
1104 y1 = s->ytop + ch * h + (h / 2); /* position of center line */
1105 for (x = 0; x < s->width; x++) {
1106 y = (s->sample_array[i] * h2) >> 15;
1113 fill_rectangle(s->xleft + x, ys, 1, y);
1115 if (i >= SAMPLE_ARRAY_SIZE)
1116 i -= SAMPLE_ARRAY_SIZE;
1120 SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
1122 for (ch = 1; ch < nb_display_channels; ch++) {
1123 y = s->ytop + ch * h;
1124 fill_rectangle(s->xleft, y, s->width, 1);
1127 if (realloc_texture(&s->vis_texture, SDL_PIXELFORMAT_ARGB8888, s->width, s->height, SDL_BLENDMODE_NONE, 1) < 0)
1130 nb_display_channels= FFMIN(nb_display_channels, 2);
1131 if (rdft_bits != s->rdft_bits) {
1132 av_rdft_end(s->rdft);
1133 av_free(s->rdft_data);
1134 s->rdft = av_rdft_init(rdft_bits, DFT_R2C);
1135 s->rdft_bits = rdft_bits;
1136 s->rdft_data = av_malloc_array(nb_freq, 4 *sizeof(*s->rdft_data));
1138 if (!s->rdft || !s->rdft_data){
1139 av_log(NULL, AV_LOG_ERROR, "Failed to allocate buffers for RDFT, switching to waves display\n");
1140 s->show_mode = SHOW_MODE_WAVES;
1143 SDL_Rect rect = {.x = s->xpos, .y = 0, .w = 1, .h = s->height};
1146 for (ch = 0; ch < nb_display_channels; ch++) {
1147 data[ch] = s->rdft_data + 2 * nb_freq * ch;
1149 for (x = 0; x < 2 * nb_freq; x++) {
1150 double w = (x-nb_freq) * (1.0 / nb_freq);
1151 data[ch][x] = s->sample_array[i] * (1.0 - w * w);
1153 if (i >= SAMPLE_ARRAY_SIZE)
1154 i -= SAMPLE_ARRAY_SIZE;
1156 av_rdft_calc(s->rdft, data[ch]);
1158 /* Least efficient way to do this, we should of course
1159 * directly access it but it is more than fast enough. */
1160 if (!SDL_LockTexture(s->vis_texture, &rect, (void **)&pixels, &pitch)) {
1162 pixels += pitch * s->height;
1163 for (y = 0; y < s->height; y++) {
1164 double w = 1 / sqrt(nb_freq);
1165 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]));
1166 int b = (nb_display_channels == 2 ) ? sqrt(w * hypot(data[1][2 * y + 0], data[1][2 * y + 1]))
1171 *pixels = (a << 16) + (b << 8) + ((a+b) >> 1);
1173 SDL_UnlockTexture(s->vis_texture);
1175 SDL_RenderCopy(renderer, s->vis_texture, NULL, NULL);
1179 if (s->xpos >= s->width)
1184 static void stream_component_close(VideoState *is, int stream_index)
1186 AVFormatContext *ic = is->ic;
1187 AVCodecParameters *codecpar;
1189 if (stream_index < 0 || stream_index >= ic->nb_streams)
1191 codecpar = ic->streams[stream_index]->codecpar;
1193 switch (codecpar->codec_type) {
1194 case AVMEDIA_TYPE_AUDIO:
1195 decoder_abort(&is->auddec, &is->sampq);
1196 SDL_CloseAudioDevice(audio_dev);
1197 decoder_destroy(&is->auddec);
1198 swr_free(&is->swr_ctx);
1199 av_freep(&is->audio_buf1);
1200 is->audio_buf1_size = 0;
1201 is->audio_buf = NULL;
1204 av_rdft_end(is->rdft);
1205 av_freep(&is->rdft_data);
1210 case AVMEDIA_TYPE_VIDEO:
1211 decoder_abort(&is->viddec, &is->pictq);
1212 decoder_destroy(&is->viddec);
1214 case AVMEDIA_TYPE_SUBTITLE:
1215 decoder_abort(&is->subdec, &is->subpq);
1216 decoder_destroy(&is->subdec);
1222 ic->streams[stream_index]->discard = AVDISCARD_ALL;
1223 switch (codecpar->codec_type) {
1224 case AVMEDIA_TYPE_AUDIO:
1225 is->audio_st = NULL;
1226 is->audio_stream = -1;
1228 case AVMEDIA_TYPE_VIDEO:
1229 is->video_st = NULL;
1230 is->video_stream = -1;
1232 case AVMEDIA_TYPE_SUBTITLE:
1233 is->subtitle_st = NULL;
1234 is->subtitle_stream = -1;
1241 static void stream_close(VideoState *is)
1243 /* XXX: use a special url_shutdown call to abort parse cleanly */
1244 is->abort_request = 1;
1245 SDL_WaitThread(is->read_tid, NULL);
1247 /* close each stream */
1248 if (is->audio_stream >= 0)
1249 stream_component_close(is, is->audio_stream);
1250 if (is->video_stream >= 0)
1251 stream_component_close(is, is->video_stream);
1252 if (is->subtitle_stream >= 0)
1253 stream_component_close(is, is->subtitle_stream);
1255 avformat_close_input(&is->ic);
1257 packet_queue_destroy(&is->videoq);
1258 packet_queue_destroy(&is->audioq);
1259 packet_queue_destroy(&is->subtitleq);
1261 /* free all pictures */
1262 frame_queue_destory(&is->pictq);
1263 frame_queue_destory(&is->sampq);
1264 frame_queue_destory(&is->subpq);
1265 SDL_DestroyCond(is->continue_read_thread);
1266 sws_freeContext(is->img_convert_ctx);
1267 sws_freeContext(is->sub_convert_ctx);
1268 av_free(is->filename);
1269 if (is->vis_texture)
1270 SDL_DestroyTexture(is->vis_texture);
1271 if (is->vid_texture)
1272 SDL_DestroyTexture(is->vid_texture);
1273 if (is->sub_texture)
1274 SDL_DestroyTexture(is->sub_texture);
1278 static void do_exit(VideoState *is)
1284 SDL_DestroyRenderer(renderer);
1286 SDL_DestroyWindow(window);
1289 av_freep(&vfilters_list);
1291 avformat_network_deinit();
1295 av_log(NULL, AV_LOG_QUIET, "%s", "");
1299 static void sigterm_handler(int sig)
1304 static void set_default_window_size(int width, int height, AVRational sar)
1307 calculate_display_rect(&rect, 0, 0, INT_MAX, height, width, height, sar);
1308 default_width = rect.w;
1309 default_height = rect.h;
1312 static int video_open(VideoState *is)
1325 window_title = input_filename;
1326 SDL_SetWindowTitle(window, window_title);
1328 SDL_SetWindowSize(window, w, h);
1329 SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
1331 SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
1332 SDL_ShowWindow(window);
1340 /* display the current picture, if any */
1341 static void video_display(VideoState *is)
1346 SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
1347 SDL_RenderClear(renderer);
1348 if (is->audio_st && is->show_mode != SHOW_MODE_VIDEO)
1349 video_audio_display(is);
1350 else if (is->video_st)
1351 video_image_display(is);
1352 SDL_RenderPresent(renderer);
1355 static double get_clock(Clock *c)
1357 if (*c->queue_serial != c->serial)
1362 double time = av_gettime_relative() / 1000000.0;
1363 return c->pts_drift + time - (time - c->last_updated) * (1.0 - c->speed);
1367 static void set_clock_at(Clock *c, double pts, int serial, double time)
1370 c->last_updated = time;
1371 c->pts_drift = c->pts - time;
1375 static void set_clock(Clock *c, double pts, int serial)
1377 double time = av_gettime_relative() / 1000000.0;
1378 set_clock_at(c, pts, serial, time);
1381 static void set_clock_speed(Clock *c, double speed)
1383 set_clock(c, get_clock(c), c->serial);
1387 static void init_clock(Clock *c, int *queue_serial)
1391 c->queue_serial = queue_serial;
1392 set_clock(c, NAN, -1);
1395 static void sync_clock_to_slave(Clock *c, Clock *slave)
1397 double clock = get_clock(c);
1398 double slave_clock = get_clock(slave);
1399 if (!isnan(slave_clock) && (isnan(clock) || fabs(clock - slave_clock) > AV_NOSYNC_THRESHOLD))
1400 set_clock(c, slave_clock, slave->serial);
1403 static int get_master_sync_type(VideoState *is) {
1404 if (is->av_sync_type == AV_SYNC_VIDEO_MASTER) {
1406 return AV_SYNC_VIDEO_MASTER;
1408 return AV_SYNC_AUDIO_MASTER;
1409 } else if (is->av_sync_type == AV_SYNC_AUDIO_MASTER) {
1411 return AV_SYNC_AUDIO_MASTER;
1413 return AV_SYNC_EXTERNAL_CLOCK;
1415 return AV_SYNC_EXTERNAL_CLOCK;
1419 /* get the current master clock value */
1420 static double get_master_clock(VideoState *is)
1424 switch (get_master_sync_type(is)) {
1425 case AV_SYNC_VIDEO_MASTER:
1426 val = get_clock(&is->vidclk);
1428 case AV_SYNC_AUDIO_MASTER:
1429 val = get_clock(&is->audclk);
1432 val = get_clock(&is->extclk);
1438 static void check_external_clock_speed(VideoState *is) {
1439 if (is->video_stream >= 0 && is->videoq.nb_packets <= EXTERNAL_CLOCK_MIN_FRAMES ||
1440 is->audio_stream >= 0 && is->audioq.nb_packets <= EXTERNAL_CLOCK_MIN_FRAMES) {
1441 set_clock_speed(&is->extclk, FFMAX(EXTERNAL_CLOCK_SPEED_MIN, is->extclk.speed - EXTERNAL_CLOCK_SPEED_STEP));
1442 } else if ((is->video_stream < 0 || is->videoq.nb_packets > EXTERNAL_CLOCK_MAX_FRAMES) &&
1443 (is->audio_stream < 0 || is->audioq.nb_packets > EXTERNAL_CLOCK_MAX_FRAMES)) {
1444 set_clock_speed(&is->extclk, FFMIN(EXTERNAL_CLOCK_SPEED_MAX, is->extclk.speed + EXTERNAL_CLOCK_SPEED_STEP));
1446 double speed = is->extclk.speed;
1448 set_clock_speed(&is->extclk, speed + EXTERNAL_CLOCK_SPEED_STEP * (1.0 - speed) / fabs(1.0 - speed));
1452 /* seek in the stream */
1453 static void stream_seek(VideoState *is, int64_t pos, int64_t rel, int seek_by_bytes)
1455 if (!is->seek_req) {
1458 is->seek_flags &= ~AVSEEK_FLAG_BYTE;
1460 is->seek_flags |= AVSEEK_FLAG_BYTE;
1462 SDL_CondSignal(is->continue_read_thread);
1466 /* pause or resume the video */
1467 static void stream_toggle_pause(VideoState *is)
1470 is->frame_timer += av_gettime_relative() / 1000000.0 - is->vidclk.last_updated;
1471 if (is->read_pause_return != AVERROR(ENOSYS)) {
1472 is->vidclk.paused = 0;
1474 set_clock(&is->vidclk, get_clock(&is->vidclk), is->vidclk.serial);
1476 set_clock(&is->extclk, get_clock(&is->extclk), is->extclk.serial);
1477 is->paused = is->audclk.paused = is->vidclk.paused = is->extclk.paused = !is->paused;
1480 static void toggle_pause(VideoState *is)
1482 stream_toggle_pause(is);
1486 static void toggle_mute(VideoState *is)
1488 is->muted = !is->muted;
1491 static void update_volume(VideoState *is, int sign, double step)
1493 double volume_level = is->audio_volume ? (20 * log(is->audio_volume / (double)SDL_MIX_MAXVOLUME) / log(10)) : -1000.0;
1494 int new_volume = lrint(SDL_MIX_MAXVOLUME * pow(10.0, (volume_level + sign * step) / 20.0));
1495 is->audio_volume = av_clip(is->audio_volume == new_volume ? (is->audio_volume + sign) : new_volume, 0, SDL_MIX_MAXVOLUME);
1498 static void step_to_next_frame(VideoState *is)
1500 /* if the stream is paused unpause it, then step */
1502 stream_toggle_pause(is);
1506 static double compute_target_delay(double delay, VideoState *is)
1508 double sync_threshold, diff = 0;
1510 /* update delay to follow master synchronisation source */
1511 if (get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER) {
1512 /* if video is slave, we try to correct big delays by
1513 duplicating or deleting a frame */
1514 diff = get_clock(&is->vidclk) - get_master_clock(is);
1516 /* skip or repeat frame. We take into account the
1517 delay to compute the threshold. I still don't know
1518 if it is the best guess */
1519 sync_threshold = FFMAX(AV_SYNC_THRESHOLD_MIN, FFMIN(AV_SYNC_THRESHOLD_MAX, delay));
1520 if (!isnan(diff) && fabs(diff) < is->max_frame_duration) {
1521 if (diff <= -sync_threshold)
1522 delay = FFMAX(0, delay + diff);
1523 else if (diff >= sync_threshold && delay > AV_SYNC_FRAMEDUP_THRESHOLD)
1524 delay = delay + diff;
1525 else if (diff >= sync_threshold)
1530 av_log(NULL, AV_LOG_TRACE, "video: delay=%0.3f A-V=%f\n",
1536 static double vp_duration(VideoState *is, Frame *vp, Frame *nextvp) {
1537 if (vp->serial == nextvp->serial) {
1538 double duration = nextvp->pts - vp->pts;
1539 if (isnan(duration) || duration <= 0 || duration > is->max_frame_duration)
1540 return vp->duration;
1548 static void update_video_pts(VideoState *is, double pts, int64_t pos, int serial) {
1549 /* update current video pts */
1550 set_clock(&is->vidclk, pts, serial);
1551 sync_clock_to_slave(&is->extclk, &is->vidclk);
1554 /* called to display each frame */
1555 static void video_refresh(void *opaque, double *remaining_time)
1557 VideoState *is = opaque;
1562 if (!is->paused && get_master_sync_type(is) == AV_SYNC_EXTERNAL_CLOCK && is->realtime)
1563 check_external_clock_speed(is);
1565 if (!display_disable && is->show_mode != SHOW_MODE_VIDEO && is->audio_st) {
1566 time = av_gettime_relative() / 1000000.0;
1567 if (is->force_refresh || is->last_vis_time + rdftspeed < time) {
1569 is->last_vis_time = time;
1571 *remaining_time = FFMIN(*remaining_time, is->last_vis_time + rdftspeed - time);
1576 if (frame_queue_nb_remaining(&is->pictq) == 0) {
1577 // nothing to do, no picture to display in the queue
1579 double last_duration, duration, delay;
1582 /* dequeue the picture */
1583 lastvp = frame_queue_peek_last(&is->pictq);
1584 vp = frame_queue_peek(&is->pictq);
1586 if (vp->serial != is->videoq.serial) {
1587 frame_queue_next(&is->pictq);
1591 if (lastvp->serial != vp->serial)
1592 is->frame_timer = av_gettime_relative() / 1000000.0;
1597 /* compute nominal last_duration */
1598 last_duration = vp_duration(is, lastvp, vp);
1599 delay = compute_target_delay(last_duration, is);
1601 time= av_gettime_relative()/1000000.0;
1602 if (time < is->frame_timer + delay) {
1603 *remaining_time = FFMIN(is->frame_timer + delay - time, *remaining_time);
1607 is->frame_timer += delay;
1608 if (delay > 0 && time - is->frame_timer > AV_SYNC_THRESHOLD_MAX)
1609 is->frame_timer = time;
1611 SDL_LockMutex(is->pictq.mutex);
1612 if (!isnan(vp->pts))
1613 update_video_pts(is, vp->pts, vp->pos, vp->serial);
1614 SDL_UnlockMutex(is->pictq.mutex);
1616 if (frame_queue_nb_remaining(&is->pictq) > 1) {
1617 Frame *nextvp = frame_queue_peek_next(&is->pictq);
1618 duration = vp_duration(is, vp, nextvp);
1619 if(!is->step && (framedrop>0 || (framedrop && get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER)) && time > is->frame_timer + duration){
1620 is->frame_drops_late++;
1621 frame_queue_next(&is->pictq);
1626 if (is->subtitle_st) {
1627 while (frame_queue_nb_remaining(&is->subpq) > 0) {
1628 sp = frame_queue_peek(&is->subpq);
1630 if (frame_queue_nb_remaining(&is->subpq) > 1)
1631 sp2 = frame_queue_peek_next(&is->subpq);
1635 if (sp->serial != is->subtitleq.serial
1636 || (is->vidclk.pts > (sp->pts + ((float) sp->sub.end_display_time / 1000)))
1637 || (sp2 && is->vidclk.pts > (sp2->pts + ((float) sp2->sub.start_display_time / 1000))))
1641 for (i = 0; i < sp->sub.num_rects; i++) {
1642 AVSubtitleRect *sub_rect = sp->sub.rects[i];
1646 if (!SDL_LockTexture(is->sub_texture, (SDL_Rect *)sub_rect, (void **)&pixels, &pitch)) {
1647 for (j = 0; j < sub_rect->h; j++, pixels += pitch)
1648 memset(pixels, 0, sub_rect->w << 2);
1649 SDL_UnlockTexture(is->sub_texture);
1653 frame_queue_next(&is->subpq);
1660 frame_queue_next(&is->pictq);
1661 is->force_refresh = 1;
1663 if (is->step && !is->paused)
1664 stream_toggle_pause(is);
1667 /* display picture */
1668 if (!display_disable && is->force_refresh && is->show_mode == SHOW_MODE_VIDEO && is->pictq.rindex_shown)
1671 is->force_refresh = 0;
1673 static int64_t last_time;
1675 int aqsize, vqsize, sqsize;
1678 cur_time = av_gettime_relative();
1679 if (!last_time || (cur_time - last_time) >= 30000) {
1684 aqsize = is->audioq.size;
1686 vqsize = is->videoq.size;
1687 if (is->subtitle_st)
1688 sqsize = is->subtitleq.size;
1690 if (is->audio_st && is->video_st)
1691 av_diff = get_clock(&is->audclk) - get_clock(&is->vidclk);
1692 else if (is->video_st)
1693 av_diff = get_master_clock(is) - get_clock(&is->vidclk);
1694 else if (is->audio_st)
1695 av_diff = get_master_clock(is) - get_clock(&is->audclk);
1696 av_log(NULL, AV_LOG_INFO,
1697 "%7.2f %s:%7.3f fd=%4d aq=%5dKB vq=%5dKB sq=%5dB f=%"PRId64"/%"PRId64" \r",
1698 get_master_clock(is),
1699 (is->audio_st && is->video_st) ? "A-V" : (is->video_st ? "M-V" : (is->audio_st ? "M-A" : " ")),
1701 is->frame_drops_early + is->frame_drops_late,
1705 is->video_st ? is->viddec.avctx->pts_correction_num_faulty_dts : 0,
1706 is->video_st ? is->viddec.avctx->pts_correction_num_faulty_pts : 0);
1708 last_time = cur_time;
1713 static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, double duration, int64_t pos, int serial)
1717 #if defined(DEBUG_SYNC)
1718 printf("frame_type=%c pts=%0.3f\n",
1719 av_get_picture_type_char(src_frame->pict_type), pts);
1722 if (!(vp = frame_queue_peek_writable(&is->pictq)))
1725 vp->sar = src_frame->sample_aspect_ratio;
1728 vp->width = src_frame->width;
1729 vp->height = src_frame->height;
1730 vp->format = src_frame->format;
1733 vp->duration = duration;
1735 vp->serial = serial;
1737 set_default_window_size(vp->width, vp->height, vp->sar);
1739 av_frame_move_ref(vp->frame, src_frame);
1740 frame_queue_push(&is->pictq);
1744 static int get_video_frame(VideoState *is, AVFrame *frame)
1748 if ((got_picture = decoder_decode_frame(&is->viddec, frame, NULL)) < 0)
1754 if (frame->pts != AV_NOPTS_VALUE)
1755 dpts = av_q2d(is->video_st->time_base) * frame->pts;
1757 frame->sample_aspect_ratio = av_guess_sample_aspect_ratio(is->ic, is->video_st, frame);
1759 if (framedrop>0 || (framedrop && get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER)) {
1760 if (frame->pts != AV_NOPTS_VALUE) {
1761 double diff = dpts - get_master_clock(is);
1762 if (!isnan(diff) && fabs(diff) < AV_NOSYNC_THRESHOLD &&
1763 diff - is->frame_last_filter_delay < 0 &&
1764 is->viddec.pkt_serial == is->vidclk.serial &&
1765 is->videoq.nb_packets) {
1766 is->frame_drops_early++;
1767 av_frame_unref(frame);
1778 static int configure_filtergraph(AVFilterGraph *graph, const char *filtergraph,
1779 AVFilterContext *source_ctx, AVFilterContext *sink_ctx)
1782 int nb_filters = graph->nb_filters;
1783 AVFilterInOut *outputs = NULL, *inputs = NULL;
1786 outputs = avfilter_inout_alloc();
1787 inputs = avfilter_inout_alloc();
1788 if (!outputs || !inputs) {
1789 ret = AVERROR(ENOMEM);
1793 outputs->name = av_strdup("in");
1794 outputs->filter_ctx = source_ctx;
1795 outputs->pad_idx = 0;
1796 outputs->next = NULL;
1798 inputs->name = av_strdup("out");
1799 inputs->filter_ctx = sink_ctx;
1800 inputs->pad_idx = 0;
1801 inputs->next = NULL;
1803 if ((ret = avfilter_graph_parse_ptr(graph, filtergraph, &inputs, &outputs, NULL)) < 0)
1806 if ((ret = avfilter_link(source_ctx, 0, sink_ctx, 0)) < 0)
1810 /* Reorder the filters to ensure that inputs of the custom filters are merged first */
1811 for (i = 0; i < graph->nb_filters - nb_filters; i++)
1812 FFSWAP(AVFilterContext*, graph->filters[i], graph->filters[i + nb_filters]);
1814 ret = avfilter_graph_config(graph, NULL);
1816 avfilter_inout_free(&outputs);
1817 avfilter_inout_free(&inputs);
1821 static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const char *vfilters, AVFrame *frame)
1823 enum AVPixelFormat pix_fmts[FF_ARRAY_ELEMS(sdl_texture_format_map)];
1824 char sws_flags_str[512] = "";
1825 char buffersrc_args[256];
1827 AVFilterContext *filt_src = NULL, *filt_out = NULL, *last_filter = NULL;
1828 AVCodecParameters *codecpar = is->video_st->codecpar;
1829 AVRational fr = av_guess_frame_rate(is->ic, is->video_st, NULL);
1830 AVDictionaryEntry *e = NULL;
1831 int nb_pix_fmts = 0;
1834 for (i = 0; i < renderer_info.num_texture_formats; i++) {
1835 for (j = 0; j < FF_ARRAY_ELEMS(sdl_texture_format_map) - 1; j++) {
1836 if (renderer_info.texture_formats[i] == sdl_texture_format_map[j].texture_fmt) {
1837 pix_fmts[nb_pix_fmts++] = sdl_texture_format_map[j].format;
1842 pix_fmts[nb_pix_fmts] = AV_PIX_FMT_NONE;
1844 while ((e = av_dict_get(sws_dict, "", e, AV_DICT_IGNORE_SUFFIX))) {
1845 if (!strcmp(e->key, "sws_flags")) {
1846 av_strlcatf(sws_flags_str, sizeof(sws_flags_str), "%s=%s:", "flags", e->value);
1848 av_strlcatf(sws_flags_str, sizeof(sws_flags_str), "%s=%s:", e->key, e->value);
1850 if (strlen(sws_flags_str))
1851 sws_flags_str[strlen(sws_flags_str)-1] = '\0';
1853 graph->scale_sws_opts = av_strdup(sws_flags_str);
1855 snprintf(buffersrc_args, sizeof(buffersrc_args),
1856 "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
1857 frame->width, frame->height, frame->format,
1858 is->video_st->time_base.num, is->video_st->time_base.den,
1859 codecpar->sample_aspect_ratio.num, FFMAX(codecpar->sample_aspect_ratio.den, 1));
1860 if (fr.num && fr.den)
1861 av_strlcatf(buffersrc_args, sizeof(buffersrc_args), ":frame_rate=%d/%d", fr.num, fr.den);
1863 if ((ret = avfilter_graph_create_filter(&filt_src,
1864 avfilter_get_by_name("buffer"),
1865 "ffplay_buffer", buffersrc_args, NULL,
1869 ret = avfilter_graph_create_filter(&filt_out,
1870 avfilter_get_by_name("buffersink"),
1871 "ffplay_buffersink", NULL, NULL, graph);
1875 if ((ret = av_opt_set_int_list(filt_out, "pix_fmts", pix_fmts, AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN)) < 0)
1878 last_filter = filt_out;
1880 /* Note: this macro adds a filter before the lastly added filter, so the
1881 * processing order of the filters is in reverse */
1882 #define INSERT_FILT(name, arg) do { \
1883 AVFilterContext *filt_ctx; \
1885 ret = avfilter_graph_create_filter(&filt_ctx, \
1886 avfilter_get_by_name(name), \
1887 "ffplay_" name, arg, NULL, graph); \
1891 ret = avfilter_link(filt_ctx, 0, last_filter, 0); \
1895 last_filter = filt_ctx; \
1899 double theta = get_rotation(is->video_st);
1901 if (fabs(theta - 90) < 1.0) {
1902 INSERT_FILT("transpose", "clock");
1903 } else if (fabs(theta - 180) < 1.0) {
1904 INSERT_FILT("hflip", NULL);
1905 INSERT_FILT("vflip", NULL);
1906 } else if (fabs(theta - 270) < 1.0) {
1907 INSERT_FILT("transpose", "cclock");
1908 } else if (fabs(theta) > 1.0) {
1909 char rotate_buf[64];
1910 snprintf(rotate_buf, sizeof(rotate_buf), "%f*PI/180", theta);
1911 INSERT_FILT("rotate", rotate_buf);
1915 if ((ret = configure_filtergraph(graph, vfilters, filt_src, last_filter)) < 0)
1918 is->in_video_filter = filt_src;
1919 is->out_video_filter = filt_out;
1925 static int configure_audio_filters(VideoState *is, const char *afilters, int force_output_format)
1927 static const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE };
1928 int sample_rates[2] = { 0, -1 };
1929 int64_t channel_layouts[2] = { 0, -1 };
1930 int channels[2] = { 0, -1 };
1931 AVFilterContext *filt_asrc = NULL, *filt_asink = NULL;
1932 char aresample_swr_opts[512] = "";
1933 AVDictionaryEntry *e = NULL;
1934 char asrc_args[256];
1937 avfilter_graph_free(&is->agraph);
1938 if (!(is->agraph = avfilter_graph_alloc()))
1939 return AVERROR(ENOMEM);
1941 while ((e = av_dict_get(swr_opts, "", e, AV_DICT_IGNORE_SUFFIX)))
1942 av_strlcatf(aresample_swr_opts, sizeof(aresample_swr_opts), "%s=%s:", e->key, e->value);
1943 if (strlen(aresample_swr_opts))
1944 aresample_swr_opts[strlen(aresample_swr_opts)-1] = '\0';
1945 av_opt_set(is->agraph, "aresample_swr_opts", aresample_swr_opts, 0);
1947 ret = snprintf(asrc_args, sizeof(asrc_args),
1948 "sample_rate=%d:sample_fmt=%s:channels=%d:time_base=%d/%d",
1949 is->audio_filter_src.freq, av_get_sample_fmt_name(is->audio_filter_src.fmt),
1950 is->audio_filter_src.channels,
1951 1, is->audio_filter_src.freq);
1952 if (is->audio_filter_src.channel_layout)
1953 snprintf(asrc_args + ret, sizeof(asrc_args) - ret,
1954 ":channel_layout=0x%"PRIx64, is->audio_filter_src.channel_layout);
1956 ret = avfilter_graph_create_filter(&filt_asrc,
1957 avfilter_get_by_name("abuffer"), "ffplay_abuffer",
1958 asrc_args, NULL, is->agraph);
1963 ret = avfilter_graph_create_filter(&filt_asink,
1964 avfilter_get_by_name("abuffersink"), "ffplay_abuffersink",
1965 NULL, NULL, is->agraph);
1969 if ((ret = av_opt_set_int_list(filt_asink, "sample_fmts", sample_fmts, AV_SAMPLE_FMT_NONE, AV_OPT_SEARCH_CHILDREN)) < 0)
1971 if ((ret = av_opt_set_int(filt_asink, "all_channel_counts", 1, AV_OPT_SEARCH_CHILDREN)) < 0)
1974 if (force_output_format) {
1975 channel_layouts[0] = is->audio_tgt.channel_layout;
1976 channels [0] = is->audio_tgt.channels;
1977 sample_rates [0] = is->audio_tgt.freq;
1978 if ((ret = av_opt_set_int(filt_asink, "all_channel_counts", 0, AV_OPT_SEARCH_CHILDREN)) < 0)
1980 if ((ret = av_opt_set_int_list(filt_asink, "channel_layouts", channel_layouts, -1, AV_OPT_SEARCH_CHILDREN)) < 0)
1982 if ((ret = av_opt_set_int_list(filt_asink, "channel_counts" , channels , -1, AV_OPT_SEARCH_CHILDREN)) < 0)
1984 if ((ret = av_opt_set_int_list(filt_asink, "sample_rates" , sample_rates , -1, AV_OPT_SEARCH_CHILDREN)) < 0)
1989 if ((ret = configure_filtergraph(is->agraph, afilters, filt_asrc, filt_asink)) < 0)
1992 is->in_audio_filter = filt_asrc;
1993 is->out_audio_filter = filt_asink;
1997 avfilter_graph_free(&is->agraph);
2000 #endif /* CONFIG_AVFILTER */
2002 static int audio_thread(void *arg)
2004 VideoState *is = arg;
2005 AVFrame *frame = av_frame_alloc();
2008 int last_serial = -1;
2009 int64_t dec_channel_layout;
2017 return AVERROR(ENOMEM);
2020 if ((got_frame = decoder_decode_frame(&is->auddec, frame, NULL)) < 0)
2024 tb = (AVRational){1, frame->sample_rate};
2027 dec_channel_layout = get_valid_channel_layout(frame->channel_layout, frame->channels);
2030 cmp_audio_fmts(is->audio_filter_src.fmt, is->audio_filter_src.channels,
2031 frame->format, frame->channels) ||
2032 is->audio_filter_src.channel_layout != dec_channel_layout ||
2033 is->audio_filter_src.freq != frame->sample_rate ||
2034 is->auddec.pkt_serial != last_serial;
2037 char buf1[1024], buf2[1024];
2038 av_get_channel_layout_string(buf1, sizeof(buf1), -1, is->audio_filter_src.channel_layout);
2039 av_get_channel_layout_string(buf2, sizeof(buf2), -1, dec_channel_layout);
2040 av_log(NULL, AV_LOG_DEBUG,
2041 "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",
2042 is->audio_filter_src.freq, is->audio_filter_src.channels, av_get_sample_fmt_name(is->audio_filter_src.fmt), buf1, last_serial,
2043 frame->sample_rate, frame->channels, av_get_sample_fmt_name(frame->format), buf2, is->auddec.pkt_serial);
2045 is->audio_filter_src.fmt = frame->format;
2046 is->audio_filter_src.channels = frame->channels;
2047 is->audio_filter_src.channel_layout = dec_channel_layout;
2048 is->audio_filter_src.freq = frame->sample_rate;
2049 last_serial = is->auddec.pkt_serial;
2051 if ((ret = configure_audio_filters(is, afilters, 1)) < 0)
2055 if ((ret = av_buffersrc_add_frame(is->in_audio_filter, frame)) < 0)
2058 while ((ret = av_buffersink_get_frame_flags(is->out_audio_filter, frame, 0)) >= 0) {
2059 tb = av_buffersink_get_time_base(is->out_audio_filter);
2061 if (!(af = frame_queue_peek_writable(&is->sampq)))
2064 af->pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb);
2065 af->pos = frame->pkt_pos;
2066 af->serial = is->auddec.pkt_serial;
2067 af->duration = av_q2d((AVRational){frame->nb_samples, frame->sample_rate});
2069 av_frame_move_ref(af->frame, frame);
2070 frame_queue_push(&is->sampq);
2073 if (is->audioq.serial != is->auddec.pkt_serial)
2076 if (ret == AVERROR_EOF)
2077 is->auddec.finished = is->auddec.pkt_serial;
2080 } while (ret >= 0 || ret == AVERROR(EAGAIN) || ret == AVERROR_EOF);
2083 avfilter_graph_free(&is->agraph);
2085 av_frame_free(&frame);
2089 static int decoder_start(Decoder *d, int (*fn)(void *), void *arg)
2091 packet_queue_start(d->queue);
2092 d->decoder_tid = SDL_CreateThread(fn, "decoder", arg);
2093 if (!d->decoder_tid) {
2094 av_log(NULL, AV_LOG_ERROR, "SDL_CreateThread(): %s\n", SDL_GetError());
2095 return AVERROR(ENOMEM);
2100 static int video_thread(void *arg)
2102 VideoState *is = arg;
2103 AVFrame *frame = av_frame_alloc();
2107 AVRational tb = is->video_st->time_base;
2108 AVRational frame_rate = av_guess_frame_rate(is->ic, is->video_st, NULL);
2111 AVFilterGraph *graph = avfilter_graph_alloc();
2112 AVFilterContext *filt_out = NULL, *filt_in = NULL;
2115 enum AVPixelFormat last_format = -2;
2116 int last_serial = -1;
2117 int last_vfilter_idx = 0;
2119 av_frame_free(&frame);
2120 return AVERROR(ENOMEM);
2127 avfilter_graph_free(&graph);
2129 return AVERROR(ENOMEM);
2133 ret = get_video_frame(is, frame);
2140 if ( last_w != frame->width
2141 || last_h != frame->height
2142 || last_format != frame->format
2143 || last_serial != is->viddec.pkt_serial
2144 || last_vfilter_idx != is->vfilter_idx) {
2145 av_log(NULL, AV_LOG_DEBUG,
2146 "Video frame changed from size:%dx%d format:%s serial:%d to size:%dx%d format:%s serial:%d\n",
2148 (const char *)av_x_if_null(av_get_pix_fmt_name(last_format), "none"), last_serial,
2149 frame->width, frame->height,
2150 (const char *)av_x_if_null(av_get_pix_fmt_name(frame->format), "none"), is->viddec.pkt_serial);
2151 avfilter_graph_free(&graph);
2152 graph = avfilter_graph_alloc();
2153 if ((ret = configure_video_filters(graph, is, vfilters_list ? vfilters_list[is->vfilter_idx] : NULL, frame)) < 0) {
2155 event.type = FF_QUIT_EVENT;
2156 event.user.data1 = is;
2157 SDL_PushEvent(&event);
2160 filt_in = is->in_video_filter;
2161 filt_out = is->out_video_filter;
2162 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 frame_rate = av_buffersink_get_frame_rate(filt_out);
2170 ret = av_buffersrc_add_frame(filt_in, frame);
2175 is->frame_last_returned_time = av_gettime_relative() / 1000000.0;
2177 ret = av_buffersink_get_frame_flags(filt_out, frame, 0);
2179 if (ret == AVERROR_EOF)
2180 is->viddec.finished = is->viddec.pkt_serial;
2185 is->frame_last_filter_delay = av_gettime_relative() / 1000000.0 - is->frame_last_returned_time;
2186 if (fabs(is->frame_last_filter_delay) > AV_NOSYNC_THRESHOLD / 10.0)
2187 is->frame_last_filter_delay = 0;
2188 tb = av_buffersink_get_time_base(filt_out);
2190 duration = (frame_rate.num && frame_rate.den ? av_q2d((AVRational){frame_rate.den, frame_rate.num}) : 0);
2191 pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb);
2192 ret = queue_picture(is, frame, pts, duration, frame->pkt_pos, is->viddec.pkt_serial);
2193 av_frame_unref(frame);
2203 avfilter_graph_free(&graph);
2205 av_frame_free(&frame);
2209 static int subtitle_thread(void *arg)
2211 VideoState *is = arg;
2217 if (!(sp = frame_queue_peek_writable(&is->subpq)))
2220 if ((got_subtitle = decoder_decode_frame(&is->subdec, NULL, &sp->sub)) < 0)
2225 if (got_subtitle && sp->sub.format == 0) {
2226 if (sp->sub.pts != AV_NOPTS_VALUE)
2227 pts = sp->sub.pts / (double)AV_TIME_BASE;
2229 sp->serial = is->subdec.pkt_serial;
2230 sp->width = is->subdec.avctx->width;
2231 sp->height = is->subdec.avctx->height;
2234 /* now we can update the picture count */
2235 frame_queue_push(&is->subpq);
2236 } else if (got_subtitle) {
2237 avsubtitle_free(&sp->sub);
2243 /* copy samples for viewing in editor window */
2244 static void update_sample_display(VideoState *is, short *samples, int samples_size)
2248 size = samples_size / sizeof(short);
2250 len = SAMPLE_ARRAY_SIZE - is->sample_array_index;
2253 memcpy(is->sample_array + is->sample_array_index, samples, len * sizeof(short));
2255 is->sample_array_index += len;
2256 if (is->sample_array_index >= SAMPLE_ARRAY_SIZE)
2257 is->sample_array_index = 0;
2262 /* return the wanted number of samples to get better sync if sync_type is video
2263 * or external master clock */
2264 static int synchronize_audio(VideoState *is, int nb_samples)
2266 int wanted_nb_samples = nb_samples;
2268 /* if not master, then we try to remove or add samples to correct the clock */
2269 if (get_master_sync_type(is) != AV_SYNC_AUDIO_MASTER) {
2270 double diff, avg_diff;
2271 int min_nb_samples, max_nb_samples;
2273 diff = get_clock(&is->audclk) - get_master_clock(is);
2275 if (!isnan(diff) && fabs(diff) < AV_NOSYNC_THRESHOLD) {
2276 is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum;
2277 if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {
2278 /* not enough measures to have a correct estimate */
2279 is->audio_diff_avg_count++;
2281 /* estimate the A-V difference */
2282 avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef);
2284 if (fabs(avg_diff) >= is->audio_diff_threshold) {
2285 wanted_nb_samples = nb_samples + (int)(diff * is->audio_src.freq);
2286 min_nb_samples = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX) / 100));
2287 max_nb_samples = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX) / 100));
2288 wanted_nb_samples = av_clip(wanted_nb_samples, min_nb_samples, max_nb_samples);
2290 av_log(NULL, AV_LOG_TRACE, "diff=%f adiff=%f sample_diff=%d apts=%0.3f %f\n",
2291 diff, avg_diff, wanted_nb_samples - nb_samples,
2292 is->audio_clock, is->audio_diff_threshold);
2295 /* too big difference : may be initial PTS errors, so
2297 is->audio_diff_avg_count = 0;
2298 is->audio_diff_cum = 0;
2302 return wanted_nb_samples;
2306 * Decode one audio frame and return its uncompressed size.
2308 * The processed audio frame is decoded, converted if required, and
2309 * stored in is->audio_buf, with size in bytes given by the return
2312 static int audio_decode_frame(VideoState *is)
2314 int data_size, resampled_data_size;
2315 int64_t dec_channel_layout;
2316 av_unused double audio_clock0;
2317 int wanted_nb_samples;
2325 while (frame_queue_nb_remaining(&is->sampq) == 0) {
2326 if ((av_gettime_relative() - audio_callback_time) > 1000000LL * is->audio_hw_buf_size / is->audio_tgt.bytes_per_sec / 2)
2331 if (!(af = frame_queue_peek_readable(&is->sampq)))
2333 frame_queue_next(&is->sampq);
2334 } while (af->serial != is->audioq.serial);
2336 data_size = av_samples_get_buffer_size(NULL, af->frame->channels,
2337 af->frame->nb_samples,
2338 af->frame->format, 1);
2340 dec_channel_layout =
2341 (af->frame->channel_layout && af->frame->channels == av_get_channel_layout_nb_channels(af->frame->channel_layout)) ?
2342 af->frame->channel_layout : av_get_default_channel_layout(af->frame->channels);
2343 wanted_nb_samples = synchronize_audio(is, af->frame->nb_samples);
2345 if (af->frame->format != is->audio_src.fmt ||
2346 dec_channel_layout != is->audio_src.channel_layout ||
2347 af->frame->sample_rate != is->audio_src.freq ||
2348 (wanted_nb_samples != af->frame->nb_samples && !is->swr_ctx)) {
2349 swr_free(&is->swr_ctx);
2350 is->swr_ctx = swr_alloc_set_opts(NULL,
2351 is->audio_tgt.channel_layout, is->audio_tgt.fmt, is->audio_tgt.freq,
2352 dec_channel_layout, af->frame->format, af->frame->sample_rate,
2354 if (!is->swr_ctx || swr_init(is->swr_ctx) < 0) {
2355 av_log(NULL, AV_LOG_ERROR,
2356 "Cannot create sample rate converter for conversion of %d Hz %s %d channels to %d Hz %s %d channels!\n",
2357 af->frame->sample_rate, av_get_sample_fmt_name(af->frame->format), af->frame->channels,
2358 is->audio_tgt.freq, av_get_sample_fmt_name(is->audio_tgt.fmt), is->audio_tgt.channels);
2359 swr_free(&is->swr_ctx);
2362 is->audio_src.channel_layout = dec_channel_layout;
2363 is->audio_src.channels = af->frame->channels;
2364 is->audio_src.freq = af->frame->sample_rate;
2365 is->audio_src.fmt = af->frame->format;
2369 const uint8_t **in = (const uint8_t **)af->frame->extended_data;
2370 uint8_t **out = &is->audio_buf1;
2371 int out_count = (int64_t)wanted_nb_samples * is->audio_tgt.freq / af->frame->sample_rate + 256;
2372 int out_size = av_samples_get_buffer_size(NULL, is->audio_tgt.channels, out_count, is->audio_tgt.fmt, 0);
2375 av_log(NULL, AV_LOG_ERROR, "av_samples_get_buffer_size() failed\n");
2378 if (wanted_nb_samples != af->frame->nb_samples) {
2379 if (swr_set_compensation(is->swr_ctx, (wanted_nb_samples - af->frame->nb_samples) * is->audio_tgt.freq / af->frame->sample_rate,
2380 wanted_nb_samples * is->audio_tgt.freq / af->frame->sample_rate) < 0) {
2381 av_log(NULL, AV_LOG_ERROR, "swr_set_compensation() failed\n");
2385 av_fast_malloc(&is->audio_buf1, &is->audio_buf1_size, out_size);
2386 if (!is->audio_buf1)
2387 return AVERROR(ENOMEM);
2388 len2 = swr_convert(is->swr_ctx, out, out_count, in, af->frame->nb_samples);
2390 av_log(NULL, AV_LOG_ERROR, "swr_convert() failed\n");
2393 if (len2 == out_count) {
2394 av_log(NULL, AV_LOG_WARNING, "audio buffer is probably too small\n");
2395 if (swr_init(is->swr_ctx) < 0)
2396 swr_free(&is->swr_ctx);
2398 is->audio_buf = is->audio_buf1;
2399 resampled_data_size = len2 * is->audio_tgt.channels * av_get_bytes_per_sample(is->audio_tgt.fmt);
2401 is->audio_buf = af->frame->data[0];
2402 resampled_data_size = data_size;
2405 audio_clock0 = is->audio_clock;
2406 /* update the audio clock with the pts */
2407 if (!isnan(af->pts))
2408 is->audio_clock = af->pts + (double) af->frame->nb_samples / af->frame->sample_rate;
2410 is->audio_clock = NAN;
2411 is->audio_clock_serial = af->serial;
2414 static double last_clock;
2415 printf("audio: delay=%0.3f clock=%0.3f clock0=%0.3f\n",
2416 is->audio_clock - last_clock,
2417 is->audio_clock, audio_clock0);
2418 last_clock = is->audio_clock;
2421 return resampled_data_size;
2424 /* prepare a new audio buffer */
2425 static void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
2427 VideoState *is = opaque;
2428 int audio_size, len1;
2430 audio_callback_time = av_gettime_relative();
2433 if (is->audio_buf_index >= is->audio_buf_size) {
2434 audio_size = audio_decode_frame(is);
2435 if (audio_size < 0) {
2436 /* if error, just output silence */
2437 is->audio_buf = NULL;
2438 is->audio_buf_size = SDL_AUDIO_MIN_BUFFER_SIZE / is->audio_tgt.frame_size * is->audio_tgt.frame_size;
2440 if (is->show_mode != SHOW_MODE_VIDEO)
2441 update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
2442 is->audio_buf_size = audio_size;
2444 is->audio_buf_index = 0;
2446 len1 = is->audio_buf_size - is->audio_buf_index;
2449 if (!is->muted && is->audio_buf && is->audio_volume == SDL_MIX_MAXVOLUME)
2450 memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
2452 memset(stream, 0, len1);
2453 if (!is->muted && is->audio_buf)
2454 SDL_MixAudioFormat(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, AUDIO_S16SYS, len1, is->audio_volume);
2458 is->audio_buf_index += len1;
2460 is->audio_write_buf_size = is->audio_buf_size - is->audio_buf_index;
2461 /* Let's assume the audio driver that is used by SDL has two periods. */
2462 if (!isnan(is->audio_clock)) {
2463 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);
2464 sync_clock_to_slave(&is->extclk, &is->audclk);
2468 static int audio_open(void *opaque, int64_t wanted_channel_layout, int wanted_nb_channels, int wanted_sample_rate, struct AudioParams *audio_hw_params)
2470 SDL_AudioSpec wanted_spec, spec;
2472 static const int next_nb_channels[] = {0, 0, 1, 6, 2, 6, 4, 6};
2473 static const int next_sample_rates[] = {0, 44100, 48000, 96000, 192000};
2474 int next_sample_rate_idx = FF_ARRAY_ELEMS(next_sample_rates) - 1;
2476 env = SDL_getenv("SDL_AUDIO_CHANNELS");
2478 wanted_nb_channels = atoi(env);
2479 wanted_channel_layout = av_get_default_channel_layout(wanted_nb_channels);
2481 if (!wanted_channel_layout || wanted_nb_channels != av_get_channel_layout_nb_channels(wanted_channel_layout)) {
2482 wanted_channel_layout = av_get_default_channel_layout(wanted_nb_channels);
2483 wanted_channel_layout &= ~AV_CH_LAYOUT_STEREO_DOWNMIX;
2485 wanted_nb_channels = av_get_channel_layout_nb_channels(wanted_channel_layout);
2486 wanted_spec.channels = wanted_nb_channels;
2487 wanted_spec.freq = wanted_sample_rate;
2488 if (wanted_spec.freq <= 0 || wanted_spec.channels <= 0) {
2489 av_log(NULL, AV_LOG_ERROR, "Invalid sample rate or channel count!\n");
2492 while (next_sample_rate_idx && next_sample_rates[next_sample_rate_idx] >= wanted_spec.freq)
2493 next_sample_rate_idx--;
2494 wanted_spec.format = AUDIO_S16SYS;
2495 wanted_spec.silence = 0;
2496 wanted_spec.samples = FFMAX(SDL_AUDIO_MIN_BUFFER_SIZE, 2 << av_log2(wanted_spec.freq / SDL_AUDIO_MAX_CALLBACKS_PER_SEC));
2497 wanted_spec.callback = sdl_audio_callback;
2498 wanted_spec.userdata = opaque;
2499 while (!(audio_dev = SDL_OpenAudioDevice(NULL, 0, &wanted_spec, &spec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE | SDL_AUDIO_ALLOW_CHANNELS_CHANGE))) {
2500 av_log(NULL, AV_LOG_WARNING, "SDL_OpenAudio (%d channels, %d Hz): %s\n",
2501 wanted_spec.channels, wanted_spec.freq, SDL_GetError());
2502 wanted_spec.channels = next_nb_channels[FFMIN(7, wanted_spec.channels)];
2503 if (!wanted_spec.channels) {
2504 wanted_spec.freq = next_sample_rates[next_sample_rate_idx--];
2505 wanted_spec.channels = wanted_nb_channels;
2506 if (!wanted_spec.freq) {
2507 av_log(NULL, AV_LOG_ERROR,
2508 "No more combinations to try, audio open failed\n");
2512 wanted_channel_layout = av_get_default_channel_layout(wanted_spec.channels);
2514 if (spec.format != AUDIO_S16SYS) {
2515 av_log(NULL, AV_LOG_ERROR,
2516 "SDL advised audio format %d is not supported!\n", spec.format);
2519 if (spec.channels != wanted_spec.channels) {
2520 wanted_channel_layout = av_get_default_channel_layout(spec.channels);
2521 if (!wanted_channel_layout) {
2522 av_log(NULL, AV_LOG_ERROR,
2523 "SDL advised channel count %d is not supported!\n", spec.channels);
2528 audio_hw_params->fmt = AV_SAMPLE_FMT_S16;
2529 audio_hw_params->freq = spec.freq;
2530 audio_hw_params->channel_layout = wanted_channel_layout;
2531 audio_hw_params->channels = spec.channels;
2532 audio_hw_params->frame_size = av_samples_get_buffer_size(NULL, audio_hw_params->channels, 1, audio_hw_params->fmt, 1);
2533 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);
2534 if (audio_hw_params->bytes_per_sec <= 0 || audio_hw_params->frame_size <= 0) {
2535 av_log(NULL, AV_LOG_ERROR, "av_samples_get_buffer_size failed\n");
2541 /* open a given stream. Return 0 if OK */
2542 static int stream_component_open(VideoState *is, int stream_index)
2544 AVFormatContext *ic = is->ic;
2545 AVCodecContext *avctx;
2547 const char *forced_codec_name = NULL;
2548 AVDictionary *opts = NULL;
2549 AVDictionaryEntry *t = NULL;
2550 int sample_rate, nb_channels;
2551 int64_t channel_layout;
2553 int stream_lowres = lowres;
2555 if (stream_index < 0 || stream_index >= ic->nb_streams)
2558 avctx = avcodec_alloc_context3(NULL);
2560 return AVERROR(ENOMEM);
2562 ret = avcodec_parameters_to_context(avctx, ic->streams[stream_index]->codecpar);
2565 avctx->pkt_timebase = ic->streams[stream_index]->time_base;
2567 codec = avcodec_find_decoder(avctx->codec_id);
2569 switch(avctx->codec_type){
2570 case AVMEDIA_TYPE_AUDIO : is->last_audio_stream = stream_index; forced_codec_name = audio_codec_name; break;
2571 case AVMEDIA_TYPE_SUBTITLE: is->last_subtitle_stream = stream_index; forced_codec_name = subtitle_codec_name; break;
2572 case AVMEDIA_TYPE_VIDEO : is->last_video_stream = stream_index; forced_codec_name = video_codec_name; break;
2574 if (forced_codec_name)
2575 codec = avcodec_find_decoder_by_name(forced_codec_name);
2577 if (forced_codec_name) av_log(NULL, AV_LOG_WARNING,
2578 "No codec could be found with name '%s'\n", forced_codec_name);
2579 else av_log(NULL, AV_LOG_WARNING,
2580 "No codec could be found with id %d\n", avctx->codec_id);
2581 ret = AVERROR(EINVAL);
2585 avctx->codec_id = codec->id;
2586 if (stream_lowres > codec->max_lowres) {
2587 av_log(avctx, AV_LOG_WARNING, "The maximum value for lowres supported by the decoder is %d\n",
2589 stream_lowres = codec->max_lowres;
2591 avctx->lowres = stream_lowres;
2594 avctx->flags2 |= AV_CODEC_FLAG2_FAST;
2596 opts = filter_codec_opts(codec_opts, avctx->codec_id, ic, ic->streams[stream_index], codec);
2597 if (!av_dict_get(opts, "threads", NULL, 0))
2598 av_dict_set(&opts, "threads", "auto", 0);
2600 av_dict_set_int(&opts, "lowres", stream_lowres, 0);
2601 if (avctx->codec_type == AVMEDIA_TYPE_VIDEO || avctx->codec_type == AVMEDIA_TYPE_AUDIO)
2602 av_dict_set(&opts, "refcounted_frames", "1", 0);
2603 if ((ret = avcodec_open2(avctx, codec, &opts)) < 0) {
2606 if ((t = av_dict_get(opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
2607 av_log(NULL, AV_LOG_ERROR, "Option %s not found.\n", t->key);
2608 ret = AVERROR_OPTION_NOT_FOUND;
2613 ic->streams[stream_index]->discard = AVDISCARD_DEFAULT;
2614 switch (avctx->codec_type) {
2615 case AVMEDIA_TYPE_AUDIO:
2618 AVFilterContext *sink;
2620 is->audio_filter_src.freq = avctx->sample_rate;
2621 is->audio_filter_src.channels = avctx->channels;
2622 is->audio_filter_src.channel_layout = get_valid_channel_layout(avctx->channel_layout, avctx->channels);
2623 is->audio_filter_src.fmt = avctx->sample_fmt;
2624 if ((ret = configure_audio_filters(is, afilters, 0)) < 0)
2626 sink = is->out_audio_filter;
2627 sample_rate = av_buffersink_get_sample_rate(sink);
2628 nb_channels = av_buffersink_get_channels(sink);
2629 channel_layout = av_buffersink_get_channel_layout(sink);
2632 sample_rate = avctx->sample_rate;
2633 nb_channels = avctx->channels;
2634 channel_layout = avctx->channel_layout;
2637 /* prepare audio output */
2638 if ((ret = audio_open(is, channel_layout, nb_channels, sample_rate, &is->audio_tgt)) < 0)
2640 is->audio_hw_buf_size = ret;
2641 is->audio_src = is->audio_tgt;
2642 is->audio_buf_size = 0;
2643 is->audio_buf_index = 0;
2645 /* init averaging filter */
2646 is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
2647 is->audio_diff_avg_count = 0;
2648 /* since we do not have a precise anough audio FIFO fullness,
2649 we correct audio sync only if larger than this threshold */
2650 is->audio_diff_threshold = (double)(is->audio_hw_buf_size) / is->audio_tgt.bytes_per_sec;
2652 is->audio_stream = stream_index;
2653 is->audio_st = ic->streams[stream_index];
2655 decoder_init(&is->auddec, avctx, &is->audioq, is->continue_read_thread);
2656 if ((is->ic->iformat->flags & (AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH | AVFMT_NO_BYTE_SEEK)) && !is->ic->iformat->read_seek) {
2657 is->auddec.start_pts = is->audio_st->start_time;
2658 is->auddec.start_pts_tb = is->audio_st->time_base;
2660 if ((ret = decoder_start(&is->auddec, audio_thread, is)) < 0)
2662 SDL_PauseAudioDevice(audio_dev, 0);
2664 case AVMEDIA_TYPE_VIDEO:
2665 is->video_stream = stream_index;
2666 is->video_st = ic->streams[stream_index];
2668 decoder_init(&is->viddec, avctx, &is->videoq, is->continue_read_thread);
2669 if ((ret = decoder_start(&is->viddec, video_thread, is)) < 0)
2671 is->queue_attachments_req = 1;
2673 case AVMEDIA_TYPE_SUBTITLE:
2674 is->subtitle_stream = stream_index;
2675 is->subtitle_st = ic->streams[stream_index];
2677 decoder_init(&is->subdec, avctx, &is->subtitleq, is->continue_read_thread);
2678 if ((ret = decoder_start(&is->subdec, subtitle_thread, is)) < 0)
2687 avcodec_free_context(&avctx);
2689 av_dict_free(&opts);
2694 static int decode_interrupt_cb(void *ctx)
2696 VideoState *is = ctx;
2697 return is->abort_request;
2700 static int stream_has_enough_packets(AVStream *st, int stream_id, PacketQueue *queue) {
2701 return stream_id < 0 ||
2702 queue->abort_request ||
2703 (st->disposition & AV_DISPOSITION_ATTACHED_PIC) ||
2704 queue->nb_packets > MIN_FRAMES && (!queue->duration || av_q2d(st->time_base) * queue->duration > 1.0);
2707 static int is_realtime(AVFormatContext *s)
2709 if( !strcmp(s->iformat->name, "rtp")
2710 || !strcmp(s->iformat->name, "rtsp")
2711 || !strcmp(s->iformat->name, "sdp")
2715 if(s->pb && ( !strncmp(s->url, "rtp:", 4)
2716 || !strncmp(s->url, "udp:", 4)
2723 /* this thread gets the stream from the disk or the network */
2724 static int read_thread(void *arg)
2726 VideoState *is = arg;
2727 AVFormatContext *ic = NULL;
2729 int st_index[AVMEDIA_TYPE_NB];
2730 AVPacket pkt1, *pkt = &pkt1;
2731 int64_t stream_start_time;
2732 int pkt_in_play_range = 0;
2733 AVDictionaryEntry *t;
2734 SDL_mutex *wait_mutex = SDL_CreateMutex();
2735 int scan_all_pmts_set = 0;
2739 av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError());
2740 ret = AVERROR(ENOMEM);
2744 memset(st_index, -1, sizeof(st_index));
2745 is->last_video_stream = is->video_stream = -1;
2746 is->last_audio_stream = is->audio_stream = -1;
2747 is->last_subtitle_stream = is->subtitle_stream = -1;
2750 ic = avformat_alloc_context();
2752 av_log(NULL, AV_LOG_FATAL, "Could not allocate context.\n");
2753 ret = AVERROR(ENOMEM);
2756 ic->interrupt_callback.callback = decode_interrupt_cb;
2757 ic->interrupt_callback.opaque = is;
2758 if (!av_dict_get(format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE)) {
2759 av_dict_set(&format_opts, "scan_all_pmts", "1", AV_DICT_DONT_OVERWRITE);
2760 scan_all_pmts_set = 1;
2762 err = avformat_open_input(&ic, is->filename, is->iformat, &format_opts);
2764 print_error(is->filename, err);
2768 if (scan_all_pmts_set)
2769 av_dict_set(&format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE);
2771 if ((t = av_dict_get(format_opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
2772 av_log(NULL, AV_LOG_ERROR, "Option %s not found.\n", t->key);
2773 ret = AVERROR_OPTION_NOT_FOUND;
2779 ic->flags |= AVFMT_FLAG_GENPTS;
2781 av_format_inject_global_side_data(ic);
2783 if (find_stream_info) {
2784 AVDictionary **opts = setup_find_stream_info_opts(ic, codec_opts);
2785 int orig_nb_streams = ic->nb_streams;
2787 err = avformat_find_stream_info(ic, opts);
2789 for (i = 0; i < orig_nb_streams; i++)
2790 av_dict_free(&opts[i]);
2794 av_log(NULL, AV_LOG_WARNING,
2795 "%s: could not find codec parameters\n", is->filename);
2802 ic->pb->eof_reached = 0; // FIXME hack, ffplay maybe should not use avio_feof() to test for the end
2804 if (seek_by_bytes < 0)
2805 seek_by_bytes = !!(ic->iformat->flags & AVFMT_TS_DISCONT) && strcmp("ogg", ic->iformat->name);
2807 is->max_frame_duration = (ic->iformat->flags & AVFMT_TS_DISCONT) ? 10.0 : 3600.0;
2809 if (!window_title && (t = av_dict_get(ic->metadata, "title", NULL, 0)))
2810 window_title = av_asprintf("%s - %s", t->value, input_filename);
2812 /* if seeking requested, we execute it */
2813 if (start_time != AV_NOPTS_VALUE) {
2816 timestamp = start_time;
2817 /* add the stream start time */
2818 if (ic->start_time != AV_NOPTS_VALUE)
2819 timestamp += ic->start_time;
2820 ret = avformat_seek_file(ic, -1, INT64_MIN, timestamp, INT64_MAX, 0);
2822 av_log(NULL, AV_LOG_WARNING, "%s: could not seek to position %0.3f\n",
2823 is->filename, (double)timestamp / AV_TIME_BASE);
2827 is->realtime = is_realtime(ic);
2830 av_dump_format(ic, 0, is->filename, 0);
2832 for (i = 0; i < ic->nb_streams; i++) {
2833 AVStream *st = ic->streams[i];
2834 enum AVMediaType type = st->codecpar->codec_type;
2835 st->discard = AVDISCARD_ALL;
2836 if (type >= 0 && wanted_stream_spec[type] && st_index[type] == -1)
2837 if (avformat_match_stream_specifier(ic, st, wanted_stream_spec[type]) > 0)
2840 for (i = 0; i < AVMEDIA_TYPE_NB; i++) {
2841 if (wanted_stream_spec[i] && st_index[i] == -1) {
2842 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));
2843 st_index[i] = INT_MAX;
2848 st_index[AVMEDIA_TYPE_VIDEO] =
2849 av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO,
2850 st_index[AVMEDIA_TYPE_VIDEO], -1, NULL, 0);
2852 st_index[AVMEDIA_TYPE_AUDIO] =
2853 av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO,
2854 st_index[AVMEDIA_TYPE_AUDIO],
2855 st_index[AVMEDIA_TYPE_VIDEO],
2857 if (!video_disable && !subtitle_disable)
2858 st_index[AVMEDIA_TYPE_SUBTITLE] =
2859 av_find_best_stream(ic, AVMEDIA_TYPE_SUBTITLE,
2860 st_index[AVMEDIA_TYPE_SUBTITLE],
2861 (st_index[AVMEDIA_TYPE_AUDIO] >= 0 ?
2862 st_index[AVMEDIA_TYPE_AUDIO] :
2863 st_index[AVMEDIA_TYPE_VIDEO]),
2866 is->show_mode = show_mode;
2867 if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) {
2868 AVStream *st = ic->streams[st_index[AVMEDIA_TYPE_VIDEO]];
2869 AVCodecParameters *codecpar = st->codecpar;
2870 AVRational sar = av_guess_sample_aspect_ratio(ic, st, NULL);
2871 if (codecpar->width)
2872 set_default_window_size(codecpar->width, codecpar->height, sar);
2875 /* open the streams */
2876 if (st_index[AVMEDIA_TYPE_AUDIO] >= 0) {
2877 stream_component_open(is, st_index[AVMEDIA_TYPE_AUDIO]);
2881 if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) {
2882 ret = stream_component_open(is, st_index[AVMEDIA_TYPE_VIDEO]);
2884 if (is->show_mode == SHOW_MODE_NONE)
2885 is->show_mode = ret >= 0 ? SHOW_MODE_VIDEO : SHOW_MODE_RDFT;
2887 if (st_index[AVMEDIA_TYPE_SUBTITLE] >= 0) {
2888 stream_component_open(is, st_index[AVMEDIA_TYPE_SUBTITLE]);
2891 if (is->video_stream < 0 && is->audio_stream < 0) {
2892 av_log(NULL, AV_LOG_FATAL, "Failed to open file '%s' or configure filtergraph\n",
2898 if (infinite_buffer < 0 && is->realtime)
2899 infinite_buffer = 1;
2902 if (is->abort_request)
2904 if (is->paused != is->last_paused) {
2905 is->last_paused = is->paused;
2907 is->read_pause_return = av_read_pause(ic);
2911 #if CONFIG_RTSP_DEMUXER || CONFIG_MMSH_PROTOCOL
2913 (!strcmp(ic->iformat->name, "rtsp") ||
2914 (ic->pb && !strncmp(input_filename, "mmsh:", 5)))) {
2915 /* wait 10 ms to avoid trying to get another packet */
2922 int64_t seek_target = is->seek_pos;
2923 int64_t seek_min = is->seek_rel > 0 ? seek_target - is->seek_rel + 2: INT64_MIN;
2924 int64_t seek_max = is->seek_rel < 0 ? seek_target - is->seek_rel - 2: INT64_MAX;
2925 // FIXME the +-2 is due to rounding being not done in the correct direction in generation
2926 // of the seek_pos/seek_rel variables
2928 ret = avformat_seek_file(is->ic, -1, seek_min, seek_target, seek_max, is->seek_flags);
2930 av_log(NULL, AV_LOG_ERROR,
2931 "%s: error while seeking\n", is->ic->url);
2933 if (is->audio_stream >= 0) {
2934 packet_queue_flush(&is->audioq);
2935 packet_queue_put(&is->audioq, &flush_pkt);
2937 if (is->subtitle_stream >= 0) {
2938 packet_queue_flush(&is->subtitleq);
2939 packet_queue_put(&is->subtitleq, &flush_pkt);
2941 if (is->video_stream >= 0) {
2942 packet_queue_flush(&is->videoq);
2943 packet_queue_put(&is->videoq, &flush_pkt);
2945 if (is->seek_flags & AVSEEK_FLAG_BYTE) {
2946 set_clock(&is->extclk, NAN, 0);
2948 set_clock(&is->extclk, seek_target / (double)AV_TIME_BASE, 0);
2952 is->queue_attachments_req = 1;
2955 step_to_next_frame(is);
2957 if (is->queue_attachments_req) {
2958 if (is->video_st && is->video_st->disposition & AV_DISPOSITION_ATTACHED_PIC) {
2959 AVPacket copy = { 0 };
2960 if ((ret = av_packet_ref(©, &is->video_st->attached_pic)) < 0)
2962 packet_queue_put(&is->videoq, ©);
2963 packet_queue_put_nullpacket(&is->videoq, is->video_stream);
2965 is->queue_attachments_req = 0;
2968 /* if the queue are full, no need to read more */
2969 if (infinite_buffer<1 &&
2970 (is->audioq.size + is->videoq.size + is->subtitleq.size > MAX_QUEUE_SIZE
2971 || (stream_has_enough_packets(is->audio_st, is->audio_stream, &is->audioq) &&
2972 stream_has_enough_packets(is->video_st, is->video_stream, &is->videoq) &&
2973 stream_has_enough_packets(is->subtitle_st, is->subtitle_stream, &is->subtitleq)))) {
2975 SDL_LockMutex(wait_mutex);
2976 SDL_CondWaitTimeout(is->continue_read_thread, wait_mutex, 10);
2977 SDL_UnlockMutex(wait_mutex);
2981 (!is->audio_st || (is->auddec.finished == is->audioq.serial && frame_queue_nb_remaining(&is->sampq) == 0)) &&
2982 (!is->video_st || (is->viddec.finished == is->videoq.serial && frame_queue_nb_remaining(&is->pictq) == 0))) {
2983 if (loop != 1 && (!loop || --loop)) {
2984 stream_seek(is, start_time != AV_NOPTS_VALUE ? start_time : 0, 0, 0);
2985 } else if (autoexit) {
2990 ret = av_read_frame(ic, pkt);
2992 if ((ret == AVERROR_EOF || avio_feof(ic->pb)) && !is->eof) {
2993 if (is->video_stream >= 0)
2994 packet_queue_put_nullpacket(&is->videoq, is->video_stream);
2995 if (is->audio_stream >= 0)
2996 packet_queue_put_nullpacket(&is->audioq, is->audio_stream);
2997 if (is->subtitle_stream >= 0)
2998 packet_queue_put_nullpacket(&is->subtitleq, is->subtitle_stream);
3001 if (ic->pb && ic->pb->error)
3003 SDL_LockMutex(wait_mutex);
3004 SDL_CondWaitTimeout(is->continue_read_thread, wait_mutex, 10);
3005 SDL_UnlockMutex(wait_mutex);
3010 /* check if packet is in play range specified by user, then queue, otherwise discard */
3011 stream_start_time = ic->streams[pkt->stream_index]->start_time;
3012 pkt_ts = pkt->pts == AV_NOPTS_VALUE ? pkt->dts : pkt->pts;
3013 pkt_in_play_range = duration == AV_NOPTS_VALUE ||
3014 (pkt_ts - (stream_start_time != AV_NOPTS_VALUE ? stream_start_time : 0)) *
3015 av_q2d(ic->streams[pkt->stream_index]->time_base) -
3016 (double)(start_time != AV_NOPTS_VALUE ? start_time : 0) / 1000000
3017 <= ((double)duration / 1000000);
3018 if (pkt->stream_index == is->audio_stream && pkt_in_play_range) {
3019 packet_queue_put(&is->audioq, pkt);
3020 } else if (pkt->stream_index == is->video_stream && pkt_in_play_range
3021 && !(is->video_st->disposition & AV_DISPOSITION_ATTACHED_PIC)) {
3022 packet_queue_put(&is->videoq, pkt);
3023 } else if (pkt->stream_index == is->subtitle_stream && pkt_in_play_range) {
3024 packet_queue_put(&is->subtitleq, pkt);
3026 av_packet_unref(pkt);
3033 avformat_close_input(&ic);
3038 event.type = FF_QUIT_EVENT;
3039 event.user.data1 = is;
3040 SDL_PushEvent(&event);
3042 SDL_DestroyMutex(wait_mutex);
3046 static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
3050 is = av_mallocz(sizeof(VideoState));
3053 is->filename = av_strdup(filename);
3056 is->iformat = iformat;
3060 /* start video display */
3061 if (frame_queue_init(&is->pictq, &is->videoq, VIDEO_PICTURE_QUEUE_SIZE, 1) < 0)
3063 if (frame_queue_init(&is->subpq, &is->subtitleq, SUBPICTURE_QUEUE_SIZE, 0) < 0)
3065 if (frame_queue_init(&is->sampq, &is->audioq, SAMPLE_QUEUE_SIZE, 1) < 0)
3068 if (packet_queue_init(&is->videoq) < 0 ||
3069 packet_queue_init(&is->audioq) < 0 ||
3070 packet_queue_init(&is->subtitleq) < 0)
3073 if (!(is->continue_read_thread = SDL_CreateCond())) {
3074 av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError());
3078 init_clock(&is->vidclk, &is->videoq.serial);
3079 init_clock(&is->audclk, &is->audioq.serial);
3080 init_clock(&is->extclk, &is->extclk.serial);
3081 is->audio_clock_serial = -1;
3082 if (startup_volume < 0)
3083 av_log(NULL, AV_LOG_WARNING, "-volume=%d < 0, setting to 0\n", startup_volume);
3084 if (startup_volume > 100)
3085 av_log(NULL, AV_LOG_WARNING, "-volume=%d > 100, setting to 100\n", startup_volume);
3086 startup_volume = av_clip(startup_volume, 0, 100);
3087 startup_volume = av_clip(SDL_MIX_MAXVOLUME * startup_volume / 100, 0, SDL_MIX_MAXVOLUME);
3088 is->audio_volume = startup_volume;
3090 is->av_sync_type = av_sync_type;
3091 is->read_tid = SDL_CreateThread(read_thread, "read_thread", is);
3092 if (!is->read_tid) {
3093 av_log(NULL, AV_LOG_FATAL, "SDL_CreateThread(): %s\n", SDL_GetError());
3101 static void stream_cycle_channel(VideoState *is, int codec_type)
3103 AVFormatContext *ic = is->ic;
3104 int start_index, stream_index;
3107 AVProgram *p = NULL;
3108 int nb_streams = is->ic->nb_streams;
3110 if (codec_type == AVMEDIA_TYPE_VIDEO) {
3111 start_index = is->last_video_stream;
3112 old_index = is->video_stream;
3113 } else if (codec_type == AVMEDIA_TYPE_AUDIO) {
3114 start_index = is->last_audio_stream;
3115 old_index = is->audio_stream;
3117 start_index = is->last_subtitle_stream;
3118 old_index = is->subtitle_stream;
3120 stream_index = start_index;
3122 if (codec_type != AVMEDIA_TYPE_VIDEO && is->video_stream != -1) {
3123 p = av_find_program_from_stream(ic, NULL, is->video_stream);
3125 nb_streams = p->nb_stream_indexes;
3126 for (start_index = 0; start_index < nb_streams; start_index++)
3127 if (p->stream_index[start_index] == stream_index)
3129 if (start_index == nb_streams)
3131 stream_index = start_index;
3136 if (++stream_index >= nb_streams)
3138 if (codec_type == AVMEDIA_TYPE_SUBTITLE)
3141 is->last_subtitle_stream = -1;
3144 if (start_index == -1)
3148 if (stream_index == start_index)
3150 st = is->ic->streams[p ? p->stream_index[stream_index] : stream_index];
3151 if (st->codecpar->codec_type == codec_type) {
3152 /* check that parameters are OK */
3153 switch (codec_type) {
3154 case AVMEDIA_TYPE_AUDIO:
3155 if (st->codecpar->sample_rate != 0 &&
3156 st->codecpar->channels != 0)
3159 case AVMEDIA_TYPE_VIDEO:
3160 case AVMEDIA_TYPE_SUBTITLE:
3168 if (p && stream_index != -1)
3169 stream_index = p->stream_index[stream_index];
3170 av_log(NULL, AV_LOG_INFO, "Switch %s stream from #%d to #%d\n",
3171 av_get_media_type_string(codec_type),
3175 stream_component_close(is, old_index);
3176 stream_component_open(is, stream_index);
3180 static void toggle_full_screen(VideoState *is)
3182 is_full_screen = !is_full_screen;
3183 SDL_SetWindowFullscreen(window, is_full_screen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
3186 static void toggle_audio_display(VideoState *is)
3188 int next = is->show_mode;
3190 next = (next + 1) % SHOW_MODE_NB;
3191 } while (next != is->show_mode && (next == SHOW_MODE_VIDEO && !is->video_st || next != SHOW_MODE_VIDEO && !is->audio_st));
3192 if (is->show_mode != next) {
3193 is->force_refresh = 1;
3194 is->show_mode = next;
3198 static void refresh_loop_wait_event(VideoState *is, SDL_Event *event) {
3199 double remaining_time = 0.0;
3201 while (!SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)) {
3202 if (!cursor_hidden && av_gettime_relative() - cursor_last_shown > CURSOR_HIDE_DELAY) {
3206 if (remaining_time > 0.0)
3207 av_usleep((int64_t)(remaining_time * 1000000.0));
3208 remaining_time = REFRESH_RATE;
3209 if (is->show_mode != SHOW_MODE_NONE && (!is->paused || is->force_refresh))
3210 video_refresh(is, &remaining_time);
3215 static void seek_chapter(VideoState *is, int incr)
3217 int64_t pos = get_master_clock(is) * AV_TIME_BASE;
3220 if (!is->ic->nb_chapters)
3223 /* find the current chapter */
3224 for (i = 0; i < is->ic->nb_chapters; i++) {
3225 AVChapter *ch = is->ic->chapters[i];
3226 if (av_compare_ts(pos, AV_TIME_BASE_Q, ch->start, ch->time_base) < 0) {
3234 if (i >= is->ic->nb_chapters)
3237 av_log(NULL, AV_LOG_VERBOSE, "Seeking to chapter %d.\n", i);
3238 stream_seek(is, av_rescale_q(is->ic->chapters[i]->start, is->ic->chapters[i]->time_base,
3239 AV_TIME_BASE_Q), 0, 0);
3242 /* handle an event sent by the GUI */
3243 static void event_loop(VideoState *cur_stream)
3246 double incr, pos, frac;
3250 refresh_loop_wait_event(cur_stream, &event);
3251 switch (event.type) {
3253 if (exit_on_keydown) {
3254 do_exit(cur_stream);
3257 switch (event.key.keysym.sym) {
3260 do_exit(cur_stream);
3263 toggle_full_screen(cur_stream);
3264 cur_stream->force_refresh = 1;
3268 toggle_pause(cur_stream);
3271 toggle_mute(cur_stream);
3273 case SDLK_KP_MULTIPLY:
3275 update_volume(cur_stream, 1, SDL_VOLUME_STEP);
3277 case SDLK_KP_DIVIDE:
3279 update_volume(cur_stream, -1, SDL_VOLUME_STEP);
3281 case SDLK_s: // S: Step to next frame
3282 step_to_next_frame(cur_stream);
3285 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_AUDIO);
3288 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_VIDEO);
3291 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_VIDEO);
3292 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_AUDIO);
3293 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_SUBTITLE);
3296 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_SUBTITLE);
3300 if (cur_stream->show_mode == SHOW_MODE_VIDEO && cur_stream->vfilter_idx < nb_vfilters - 1) {
3301 if (++cur_stream->vfilter_idx >= nb_vfilters)
3302 cur_stream->vfilter_idx = 0;
3304 cur_stream->vfilter_idx = 0;
3305 toggle_audio_display(cur_stream);
3308 toggle_audio_display(cur_stream);
3312 if (cur_stream->ic->nb_chapters <= 1) {
3316 seek_chapter(cur_stream, 1);
3319 if (cur_stream->ic->nb_chapters <= 1) {
3323 seek_chapter(cur_stream, -1);
3337 if (seek_by_bytes) {
3339 if (pos < 0 && cur_stream->video_stream >= 0)
3340 pos = frame_queue_last_pos(&cur_stream->pictq);
3341 if (pos < 0 && cur_stream->audio_stream >= 0)
3342 pos = frame_queue_last_pos(&cur_stream->sampq);
3344 pos = avio_tell(cur_stream->ic->pb);
3345 if (cur_stream->ic->bit_rate)
3346 incr *= cur_stream->ic->bit_rate / 8.0;
3350 stream_seek(cur_stream, pos, incr, 1);
3352 pos = get_master_clock(cur_stream);
3354 pos = (double)cur_stream->seek_pos / AV_TIME_BASE;
3356 if (cur_stream->ic->start_time != AV_NOPTS_VALUE && pos < cur_stream->ic->start_time / (double)AV_TIME_BASE)
3357 pos = cur_stream->ic->start_time / (double)AV_TIME_BASE;
3358 stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), (int64_t)(incr * AV_TIME_BASE), 0);
3365 case SDL_MOUSEBUTTONDOWN:
3366 if (exit_on_mousedown) {
3367 do_exit(cur_stream);
3370 if (event.button.button == SDL_BUTTON_LEFT) {
3371 static int64_t last_mouse_left_click = 0;
3372 if (av_gettime_relative() - last_mouse_left_click <= 500000) {
3373 toggle_full_screen(cur_stream);
3374 cur_stream->force_refresh = 1;
3375 last_mouse_left_click = 0;
3377 last_mouse_left_click = av_gettime_relative();
3380 case SDL_MOUSEMOTION:
3381 if (cursor_hidden) {
3385 cursor_last_shown = av_gettime_relative();
3386 if (event.type == SDL_MOUSEBUTTONDOWN) {
3387 if (event.button.button != SDL_BUTTON_RIGHT)
3391 if (!(event.motion.state & SDL_BUTTON_RMASK))
3395 if (seek_by_bytes || cur_stream->ic->duration <= 0) {
3396 uint64_t size = avio_size(cur_stream->ic->pb);
3397 stream_seek(cur_stream, size*x/cur_stream->width, 0, 1);
3401 int tns, thh, tmm, tss;
3402 tns = cur_stream->ic->duration / 1000000LL;
3404 tmm = (tns % 3600) / 60;
3406 frac = x / cur_stream->width;
3409 mm = (ns % 3600) / 60;
3411 av_log(NULL, AV_LOG_INFO,
3412 "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
3413 hh, mm, ss, thh, tmm, tss);
3414 ts = frac * cur_stream->ic->duration;
3415 if (cur_stream->ic->start_time != AV_NOPTS_VALUE)
3416 ts += cur_stream->ic->start_time;
3417 stream_seek(cur_stream, ts, 0, 0);
3420 case SDL_WINDOWEVENT:
3421 switch (event.window.event) {
3422 case SDL_WINDOWEVENT_RESIZED:
3423 screen_width = cur_stream->width = event.window.data1;
3424 screen_height = cur_stream->height = event.window.data2;
3425 if (cur_stream->vis_texture) {
3426 SDL_DestroyTexture(cur_stream->vis_texture);
3427 cur_stream->vis_texture = NULL;
3429 case SDL_WINDOWEVENT_EXPOSED:
3430 cur_stream->force_refresh = 1;
3435 do_exit(cur_stream);
3443 static int opt_frame_size(void *optctx, const char *opt, const char *arg)
3445 av_log(NULL, AV_LOG_WARNING, "Option -s is deprecated, use -video_size.\n");
3446 return opt_default(NULL, "video_size", arg);
3449 static int opt_width(void *optctx, const char *opt, const char *arg)
3451 screen_width = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
3455 static int opt_height(void *optctx, const char *opt, const char *arg)
3457 screen_height = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
3461 static int opt_format(void *optctx, const char *opt, const char *arg)
3463 file_iformat = av_find_input_format(arg);
3464 if (!file_iformat) {
3465 av_log(NULL, AV_LOG_FATAL, "Unknown input format: %s\n", arg);
3466 return AVERROR(EINVAL);
3471 static int opt_frame_pix_fmt(void *optctx, const char *opt, const char *arg)
3473 av_log(NULL, AV_LOG_WARNING, "Option -pix_fmt is deprecated, use -pixel_format.\n");
3474 return opt_default(NULL, "pixel_format", arg);
3477 static int opt_sync(void *optctx, const char *opt, const char *arg)
3479 if (!strcmp(arg, "audio"))
3480 av_sync_type = AV_SYNC_AUDIO_MASTER;
3481 else if (!strcmp(arg, "video"))
3482 av_sync_type = AV_SYNC_VIDEO_MASTER;
3483 else if (!strcmp(arg, "ext"))
3484 av_sync_type = AV_SYNC_EXTERNAL_CLOCK;
3486 av_log(NULL, AV_LOG_ERROR, "Unknown value for %s: %s\n", opt, arg);
3492 static int opt_seek(void *optctx, const char *opt, const char *arg)
3494 start_time = parse_time_or_die(opt, arg, 1);
3498 static int opt_duration(void *optctx, const char *opt, const char *arg)
3500 duration = parse_time_or_die(opt, arg, 1);
3504 static int opt_show_mode(void *optctx, const char *opt, const char *arg)
3506 show_mode = !strcmp(arg, "video") ? SHOW_MODE_VIDEO :
3507 !strcmp(arg, "waves") ? SHOW_MODE_WAVES :
3508 !strcmp(arg, "rdft" ) ? SHOW_MODE_RDFT :
3509 parse_number_or_die(opt, arg, OPT_INT, 0, SHOW_MODE_NB-1);
3513 static void opt_input_file(void *optctx, const char *filename)
3515 if (input_filename) {
3516 av_log(NULL, AV_LOG_FATAL,
3517 "Argument '%s' provided as input filename, but '%s' was already specified.\n",
3518 filename, input_filename);
3521 if (!strcmp(filename, "-"))
3523 input_filename = filename;
3526 static int opt_codec(void *optctx, const char *opt, const char *arg)
3528 const char *spec = strchr(opt, ':');
3530 av_log(NULL, AV_LOG_ERROR,
3531 "No media specifier was specified in '%s' in option '%s'\n",
3533 return AVERROR(EINVAL);
3537 case 'a' : audio_codec_name = arg; break;
3538 case 's' : subtitle_codec_name = arg; break;
3539 case 'v' : video_codec_name = arg; break;
3541 av_log(NULL, AV_LOG_ERROR,
3542 "Invalid media specifier '%s' in option '%s'\n", spec, opt);
3543 return AVERROR(EINVAL);
3550 static const OptionDef options[] = {
3551 CMDUTILS_COMMON_OPTIONS
3552 { "x", HAS_ARG, { .func_arg = opt_width }, "force displayed width", "width" },
3553 { "y", HAS_ARG, { .func_arg = opt_height }, "force displayed height", "height" },
3554 { "s", HAS_ARG | OPT_VIDEO, { .func_arg = opt_frame_size }, "set frame size (WxH or abbreviation)", "size" },
3555 { "fs", OPT_BOOL, { &is_full_screen }, "force full screen" },
3556 { "an", OPT_BOOL, { &audio_disable }, "disable audio" },
3557 { "vn", OPT_BOOL, { &video_disable }, "disable video" },
3558 { "sn", OPT_BOOL, { &subtitle_disable }, "disable subtitling" },
3559 { "ast", OPT_STRING | HAS_ARG | OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_AUDIO] }, "select desired audio stream", "stream_specifier" },
3560 { "vst", OPT_STRING | HAS_ARG | OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_VIDEO] }, "select desired video stream", "stream_specifier" },
3561 { "sst", OPT_STRING | HAS_ARG | OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_SUBTITLE] }, "select desired subtitle stream", "stream_specifier" },
3562 { "ss", HAS_ARG, { .func_arg = opt_seek }, "seek to a given position in seconds", "pos" },
3563 { "t", HAS_ARG, { .func_arg = opt_duration }, "play \"duration\" seconds of audio/video", "duration" },
3564 { "bytes", OPT_INT | HAS_ARG, { &seek_by_bytes }, "seek by bytes 0=off 1=on -1=auto", "val" },
3565 { "nodisp", OPT_BOOL, { &display_disable }, "disable graphical display" },
3566 { "noborder", OPT_BOOL, { &borderless }, "borderless window" },
3567 { "volume", OPT_INT | HAS_ARG, { &startup_volume}, "set startup volume 0=min 100=max", "volume" },
3568 { "f", HAS_ARG, { .func_arg = opt_format }, "force format", "fmt" },
3569 { "pix_fmt", HAS_ARG | OPT_EXPERT | OPT_VIDEO, { .func_arg = opt_frame_pix_fmt }, "set pixel format", "format" },
3570 { "stats", OPT_BOOL | OPT_EXPERT, { &show_status }, "show status", "" },
3571 { "fast", OPT_BOOL | OPT_EXPERT, { &fast }, "non spec compliant optimizations", "" },
3572 { "genpts", OPT_BOOL | OPT_EXPERT, { &genpts }, "generate pts", "" },
3573 { "drp", OPT_INT | HAS_ARG | OPT_EXPERT, { &decoder_reorder_pts }, "let decoder reorder pts 0=off 1=on -1=auto", ""},
3574 { "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, { &lowres }, "", "" },
3575 { "sync", HAS_ARG | OPT_EXPERT, { .func_arg = opt_sync }, "set audio-video sync. type (type=audio/video/ext)", "type" },
3576 { "autoexit", OPT_BOOL | OPT_EXPERT, { &autoexit }, "exit at the end", "" },
3577 { "exitonkeydown", OPT_BOOL | OPT_EXPERT, { &exit_on_keydown }, "exit on key down", "" },
3578 { "exitonmousedown", OPT_BOOL | OPT_EXPERT, { &exit_on_mousedown }, "exit on mouse down", "" },
3579 { "loop", OPT_INT | HAS_ARG | OPT_EXPERT, { &loop }, "set number of times the playback shall be looped", "loop count" },
3580 { "framedrop", OPT_BOOL | OPT_EXPERT, { &framedrop }, "drop frames when cpu is too slow", "" },
3581 { "infbuf", OPT_BOOL | OPT_EXPERT, { &infinite_buffer }, "don't limit the input buffer size (useful with realtime streams)", "" },
3582 { "window_title", OPT_STRING | HAS_ARG, { &window_title }, "set window title", "window title" },
3584 { "vf", OPT_EXPERT | HAS_ARG, { .func_arg = opt_add_vfilter }, "set video filters", "filter_graph" },
3585 { "af", OPT_STRING | HAS_ARG, { &afilters }, "set audio filters", "filter_graph" },
3587 { "rdftspeed", OPT_INT | HAS_ARG| OPT_AUDIO | OPT_EXPERT, { &rdftspeed }, "rdft speed", "msecs" },
3588 { "showmode", HAS_ARG, { .func_arg = opt_show_mode}, "select show mode (0 = video, 1 = waves, 2 = RDFT)", "mode" },
3589 { "default", HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, { .func_arg = opt_default }, "generic catch all option", "" },
3590 { "i", OPT_BOOL, { &dummy}, "read specified file", "input_file"},
3591 { "codec", HAS_ARG, { .func_arg = opt_codec}, "force decoder", "decoder_name" },
3592 { "acodec", HAS_ARG | OPT_STRING | OPT_EXPERT, { &audio_codec_name }, "force audio decoder", "decoder_name" },
3593 { "scodec", HAS_ARG | OPT_STRING | OPT_EXPERT, { &subtitle_codec_name }, "force subtitle decoder", "decoder_name" },
3594 { "vcodec", HAS_ARG | OPT_STRING | OPT_EXPERT, { &video_codec_name }, "force video decoder", "decoder_name" },
3595 { "autorotate", OPT_BOOL, { &autorotate }, "automatically rotate video", "" },
3596 { "find_stream_info", OPT_BOOL | OPT_INPUT | OPT_EXPERT, { &find_stream_info },
3597 "read and decode the streams to fill missing information with heuristics" },
3601 static void show_usage(void)
3603 av_log(NULL, AV_LOG_INFO, "Simple media player\n");
3604 av_log(NULL, AV_LOG_INFO, "usage: %s [options] input_file\n", program_name);
3605 av_log(NULL, AV_LOG_INFO, "\n");
3608 void show_help_default(const char *opt, const char *arg)
3610 av_log_set_callback(log_callback_help);
3612 show_help_options(options, "Main options:", 0, OPT_EXPERT, 0);
3613 show_help_options(options, "Advanced options:", OPT_EXPERT, 0, 0);
3615 show_help_children(avcodec_get_class(), AV_OPT_FLAG_DECODING_PARAM);
3616 show_help_children(avformat_get_class(), AV_OPT_FLAG_DECODING_PARAM);
3617 #if !CONFIG_AVFILTER
3618 show_help_children(sws_get_class(), AV_OPT_FLAG_ENCODING_PARAM);
3620 show_help_children(avfilter_get_class(), AV_OPT_FLAG_FILTERING_PARAM);
3622 printf("\nWhile playing:\n"
3624 "f toggle full screen\n"
3627 "9, 0 decrease and increase volume respectively\n"
3628 "/, * decrease and increase volume respectively\n"
3629 "a cycle audio channel in the current program\n"
3630 "v cycle video channel\n"
3631 "t cycle subtitle channel in the current program\n"
3633 "w cycle video filters or show modes\n"
3634 "s activate frame-step mode\n"
3635 "left/right seek backward/forward 10 seconds\n"
3636 "down/up seek backward/forward 1 minute\n"
3637 "page down/page up seek backward/forward 10 minutes\n"
3638 "right mouse click seek to percentage in file corresponding to fraction of width\n"
3639 "left double-click toggle full screen\n"
3643 /* Called from the main */
3644 int main(int argc, char **argv)
3651 av_log_set_flags(AV_LOG_SKIP_REPEATED);
3652 parse_loglevel(argc, argv, options);
3654 /* register all codecs, demux and protocols */
3656 avdevice_register_all();
3659 avfilter_register_all();
3662 avformat_network_init();
3666 signal(SIGINT , sigterm_handler); /* Interrupt (ANSI). */
3667 signal(SIGTERM, sigterm_handler); /* Termination (ANSI). */
3669 show_banner(argc, argv, options);
3671 parse_options(NULL, argc, argv, options, opt_input_file);
3673 if (!input_filename) {
3675 av_log(NULL, AV_LOG_FATAL, "An input file must be specified\n");
3676 av_log(NULL, AV_LOG_FATAL,
3677 "Use -h to get full help or, even better, run 'man %s'\n", program_name);
3681 if (display_disable) {
3684 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
3686 flags &= ~SDL_INIT_AUDIO;
3688 /* Try to work around an occasional ALSA buffer underflow issue when the
3689 * period size is NPOT due to ALSA resampling by forcing the buffer size. */
3690 if (!SDL_getenv("SDL_AUDIO_ALSA_SET_BUFFER_SIZE"))
3691 SDL_setenv("SDL_AUDIO_ALSA_SET_BUFFER_SIZE","1", 1);
3693 if (display_disable)
3694 flags &= ~SDL_INIT_VIDEO;
3695 if (SDL_Init (flags)) {
3696 av_log(NULL, AV_LOG_FATAL, "Could not initialize SDL - %s\n", SDL_GetError());
3697 av_log(NULL, AV_LOG_FATAL, "(Did you set the DISPLAY variable?)\n");
3701 SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
3702 SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
3704 av_init_packet(&flush_pkt);
3705 flush_pkt.data = (uint8_t *)&flush_pkt;
3707 if (!display_disable) {
3708 int flags = SDL_WINDOW_HIDDEN;
3710 flags |= SDL_WINDOW_BORDERLESS;
3712 flags |= SDL_WINDOW_RESIZABLE;
3713 window = SDL_CreateWindow(program_name, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, default_width, default_height, flags);
3714 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
3716 renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
3718 av_log(NULL, AV_LOG_WARNING, "Failed to initialize a hardware accelerated renderer: %s\n", SDL_GetError());
3719 renderer = SDL_CreateRenderer(window, -1, 0);
3722 if (!SDL_GetRendererInfo(renderer, &renderer_info))
3723 av_log(NULL, AV_LOG_VERBOSE, "Initialized %s renderer.\n", renderer_info.name);
3726 if (!window || !renderer || !renderer_info.num_texture_formats) {
3727 av_log(NULL, AV_LOG_FATAL, "Failed to create window or renderer: %s", SDL_GetError());
3732 is = stream_open(input_filename, file_iformat);
3734 av_log(NULL, AV_LOG_FATAL, "Failed to initialize VideoState!\n");