2 * Copyright (c) 2003 Fabrice Bellard
4 * This file is part of FFmpeg.
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 * simple media player based on the FFmpeg libraries
33 #include "libavutil/avstring.h"
34 #include "libavutil/eval.h"
35 #include "libavutil/mathematics.h"
36 #include "libavutil/pixdesc.h"
37 #include "libavutil/imgutils.h"
38 #include "libavutil/dict.h"
39 #include "libavutil/parseutils.h"
40 #include "libavutil/samplefmt.h"
41 #include "libavutil/avassert.h"
42 #include "libavutil/time.h"
43 #include "libavformat/avformat.h"
44 #include "libavdevice/avdevice.h"
45 #include "libswscale/swscale.h"
46 #include "libavutil/opt.h"
47 #include "libavcodec/avfft.h"
48 #include "libswresample/swresample.h"
51 # include "libavfilter/avfilter.h"
52 # include "libavfilter/buffersink.h"
53 # include "libavfilter/buffersrc.h"
57 #include <SDL_thread.h>
63 const char program_name[] = "ffplay";
64 const int program_birth_year = 2003;
66 #define MAX_QUEUE_SIZE (15 * 1024 * 1024)
68 #define EXTERNAL_CLOCK_MIN_FRAMES 2
69 #define EXTERNAL_CLOCK_MAX_FRAMES 10
71 /* Minimum SDL audio buffer size, in samples. */
72 #define SDL_AUDIO_MIN_BUFFER_SIZE 512
73 /* Calculate actual buffer size keeping in mind not cause too frequent audio callbacks */
74 #define SDL_AUDIO_MAX_CALLBACKS_PER_SEC 30
76 /* Step size for volume control in dB */
77 #define SDL_VOLUME_STEP (0.75)
79 /* no AV sync correction is done if below the minimum AV sync threshold */
80 #define AV_SYNC_THRESHOLD_MIN 0.04
81 /* AV sync correction is done if above the maximum AV sync threshold */
82 #define AV_SYNC_THRESHOLD_MAX 0.1
83 /* If a frame duration is longer than this, it will not be duplicated to compensate AV sync */
84 #define AV_SYNC_FRAMEDUP_THRESHOLD 0.1
85 /* no AV correction is done if too big error */
86 #define AV_NOSYNC_THRESHOLD 10.0
88 /* maximum audio speed change to get correct sync */
89 #define SAMPLE_CORRECTION_PERCENT_MAX 10
91 /* external clock speed adjustment constants for realtime sources based on buffer fullness */
92 #define EXTERNAL_CLOCK_SPEED_MIN 0.900
93 #define EXTERNAL_CLOCK_SPEED_MAX 1.010
94 #define EXTERNAL_CLOCK_SPEED_STEP 0.001
96 /* we use about AUDIO_DIFF_AVG_NB A-V differences to make the average */
97 #define AUDIO_DIFF_AVG_NB 20
99 /* polls for possible required screen refresh at least this often, should be less than 1/fps */
100 #define REFRESH_RATE 0.01
102 /* NOTE: the size must be big enough to compensate the hardware audio buffersize size */
103 /* TODO: We assume that a decoded and resampled frame fits into this buffer */
104 #define SAMPLE_ARRAY_SIZE (8 * 65536)
106 #define CURSOR_HIDE_DELAY 1000000
108 #define USE_ONEPASS_SUBTITLE_RENDER 1
110 static unsigned sws_flags = SWS_BICUBIC;
112 typedef struct MyAVPacketList {
114 struct MyAVPacketList *next;
118 typedef struct PacketQueue {
119 MyAVPacketList *first_pkt, *last_pkt;
129 #define VIDEO_PICTURE_QUEUE_SIZE 3
130 #define SUBPICTURE_QUEUE_SIZE 16
131 #define SAMPLE_QUEUE_SIZE 9
132 #define FRAME_QUEUE_SIZE FFMAX(SAMPLE_QUEUE_SIZE, FFMAX(VIDEO_PICTURE_QUEUE_SIZE, SUBPICTURE_QUEUE_SIZE))
134 typedef struct AudioParams {
137 int64_t channel_layout;
138 enum AVSampleFormat fmt;
143 typedef struct Clock {
144 double pts; /* clock base */
145 double pts_drift; /* clock base minus time at which we updated the clock */
148 int serial; /* clock is based on a packet with this serial */
150 int *queue_serial; /* pointer to the current packet queue serial, used for obsolete clock detection */
153 /* Common struct for handling all types of decoded data and allocated render buffers. */
154 typedef struct Frame {
158 double pts; /* presentation timestamp for the frame */
159 double duration; /* estimated duration of the frame */
160 int64_t pos; /* byte position of the frame in the input file */
169 typedef struct FrameQueue {
170 Frame queue[FRAME_QUEUE_SIZE];
183 AV_SYNC_AUDIO_MASTER, /* default choice */
184 AV_SYNC_VIDEO_MASTER,
185 AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */
188 typedef struct Decoder {
191 AVCodecContext *avctx;
195 SDL_cond *empty_queue_cond;
197 AVRational start_pts_tb;
199 AVRational next_pts_tb;
200 SDL_Thread *decoder_tid;
203 typedef struct VideoState {
204 SDL_Thread *read_tid;
205 AVInputFormat *iformat;
210 int queue_attachments_req;
215 int read_pause_return;
236 int audio_clock_serial;
237 double audio_diff_cum; /* used for AV difference average computation */
238 double audio_diff_avg_coef;
239 double audio_diff_threshold;
240 int audio_diff_avg_count;
243 int audio_hw_buf_size;
246 unsigned int audio_buf_size; /* in bytes */
247 unsigned int audio_buf1_size;
248 int audio_buf_index; /* in bytes */
249 int audio_write_buf_size;
252 struct AudioParams audio_src;
254 struct AudioParams audio_filter_src;
256 struct AudioParams audio_tgt;
257 struct SwrContext *swr_ctx;
258 int frame_drops_early;
259 int frame_drops_late;
262 SHOW_MODE_NONE = -1, SHOW_MODE_VIDEO = 0, SHOW_MODE_WAVES, SHOW_MODE_RDFT, SHOW_MODE_NB
264 int16_t sample_array[SAMPLE_ARRAY_SIZE];
265 int sample_array_index;
269 FFTSample *rdft_data;
271 double last_vis_time;
272 SDL_Texture *vis_texture;
273 SDL_Texture *sub_texture;
274 SDL_Texture *vid_texture;
277 AVStream *subtitle_st;
278 PacketQueue subtitleq;
281 double frame_last_returned_time;
282 double frame_last_filter_delay;
286 double max_frame_duration; // maximum duration of a frame - above this, we consider the jump a timestamp discontinuity
287 struct SwsContext *img_convert_ctx;
288 struct SwsContext *sub_convert_ctx;
292 int width, height, xleft, ytop;
297 AVFilterContext *in_video_filter; // the first filter in the video chain
298 AVFilterContext *out_video_filter; // the last filter in the video chain
299 AVFilterContext *in_audio_filter; // the first filter in the audio chain
300 AVFilterContext *out_audio_filter; // the last filter in the audio chain
301 AVFilterGraph *agraph; // audio filter graph
304 int last_video_stream, last_audio_stream, last_subtitle_stream;
306 SDL_cond *continue_read_thread;
309 /* options specified by the user */
310 static AVInputFormat *file_iformat;
311 static const char *input_filename;
312 static const char *window_title;
313 static int default_width = 640;
314 static int default_height = 480;
315 static int screen_width = 0;
316 static int screen_height = 0;
317 static int screen_left = SDL_WINDOWPOS_CENTERED;
318 static int screen_top = SDL_WINDOWPOS_CENTERED;
319 static int audio_disable;
320 static int video_disable;
321 static int subtitle_disable;
322 static const char* wanted_stream_spec[AVMEDIA_TYPE_NB] = {0};
323 static int seek_by_bytes = -1;
324 static float seek_interval = 10;
325 static int display_disable;
326 static int borderless;
327 static int startup_volume = 100;
328 static int show_status = 1;
329 static int av_sync_type = AV_SYNC_AUDIO_MASTER;
330 static int64_t start_time = AV_NOPTS_VALUE;
331 static int64_t duration = AV_NOPTS_VALUE;
333 static int genpts = 0;
334 static int lowres = 0;
335 static int decoder_reorder_pts = -1;
337 static int exit_on_keydown;
338 static int exit_on_mousedown;
340 static int framedrop = -1;
341 static int infinite_buffer = -1;
342 static enum ShowMode show_mode = SHOW_MODE_NONE;
343 static const char *audio_codec_name;
344 static const char *subtitle_codec_name;
345 static const char *video_codec_name;
346 double rdftspeed = 0.02;
347 static int64_t cursor_last_shown;
348 static int cursor_hidden = 0;
350 static const char **vfilters_list = NULL;
351 static int nb_vfilters = 0;
352 static char *afilters = NULL;
354 static int autorotate = 1;
355 static int find_stream_info = 1;
357 /* current context */
358 static int is_full_screen;
359 static int64_t audio_callback_time;
361 static AVPacket flush_pkt;
363 #define FF_QUIT_EVENT (SDL_USEREVENT + 2)
365 static SDL_Window *window;
366 static SDL_Renderer *renderer;
367 static SDL_RendererInfo renderer_info = {0};
368 static SDL_AudioDeviceID audio_dev;
370 static const struct TextureFormatEntry {
371 enum AVPixelFormat format;
373 } sdl_texture_format_map[] = {
374 { AV_PIX_FMT_RGB8, SDL_PIXELFORMAT_RGB332 },
375 { AV_PIX_FMT_RGB444, SDL_PIXELFORMAT_RGB444 },
376 { AV_PIX_FMT_RGB555, SDL_PIXELFORMAT_RGB555 },
377 { AV_PIX_FMT_BGR555, SDL_PIXELFORMAT_BGR555 },
378 { AV_PIX_FMT_RGB565, SDL_PIXELFORMAT_RGB565 },
379 { AV_PIX_FMT_BGR565, SDL_PIXELFORMAT_BGR565 },
380 { AV_PIX_FMT_RGB24, SDL_PIXELFORMAT_RGB24 },
381 { AV_PIX_FMT_BGR24, SDL_PIXELFORMAT_BGR24 },
382 { AV_PIX_FMT_0RGB32, SDL_PIXELFORMAT_RGB888 },
383 { AV_PIX_FMT_0BGR32, SDL_PIXELFORMAT_BGR888 },
384 { AV_PIX_FMT_NE(RGB0, 0BGR), SDL_PIXELFORMAT_RGBX8888 },
385 { AV_PIX_FMT_NE(BGR0, 0RGB), SDL_PIXELFORMAT_BGRX8888 },
386 { AV_PIX_FMT_RGB32, SDL_PIXELFORMAT_ARGB8888 },
387 { AV_PIX_FMT_RGB32_1, SDL_PIXELFORMAT_RGBA8888 },
388 { AV_PIX_FMT_BGR32, SDL_PIXELFORMAT_ABGR8888 },
389 { AV_PIX_FMT_BGR32_1, SDL_PIXELFORMAT_BGRA8888 },
390 { AV_PIX_FMT_YUV420P, SDL_PIXELFORMAT_IYUV },
391 { AV_PIX_FMT_YUYV422, SDL_PIXELFORMAT_YUY2 },
392 { AV_PIX_FMT_UYVY422, SDL_PIXELFORMAT_UYVY },
393 { AV_PIX_FMT_NONE, SDL_PIXELFORMAT_UNKNOWN },
397 static int opt_add_vfilter(void *optctx, const char *opt, const char *arg)
399 GROW_ARRAY(vfilters_list, nb_vfilters);
400 vfilters_list[nb_vfilters - 1] = arg;
406 int cmp_audio_fmts(enum AVSampleFormat fmt1, int64_t channel_count1,
407 enum AVSampleFormat fmt2, int64_t channel_count2)
409 /* If channel count == 1, planar and non-planar formats are the same */
410 if (channel_count1 == 1 && channel_count2 == 1)
411 return av_get_packed_sample_fmt(fmt1) != av_get_packed_sample_fmt(fmt2);
413 return channel_count1 != channel_count2 || fmt1 != fmt2;
417 int64_t get_valid_channel_layout(int64_t channel_layout, int channels)
419 if (channel_layout && av_get_channel_layout_nb_channels(channel_layout) == channels)
420 return channel_layout;
425 static int packet_queue_put_private(PacketQueue *q, AVPacket *pkt)
427 MyAVPacketList *pkt1;
429 if (q->abort_request)
432 pkt1 = av_malloc(sizeof(MyAVPacketList));
437 if (pkt == &flush_pkt)
439 pkt1->serial = q->serial;
444 q->last_pkt->next = pkt1;
447 q->size += pkt1->pkt.size + sizeof(*pkt1);
448 q->duration += pkt1->pkt.duration;
449 /* XXX: should duplicate packet data in DV case */
450 SDL_CondSignal(q->cond);
454 static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
458 SDL_LockMutex(q->mutex);
459 ret = packet_queue_put_private(q, pkt);
460 SDL_UnlockMutex(q->mutex);
462 if (pkt != &flush_pkt && ret < 0)
463 av_packet_unref(pkt);
468 static int packet_queue_put_nullpacket(PacketQueue *q, int stream_index)
470 AVPacket pkt1, *pkt = &pkt1;
474 pkt->stream_index = stream_index;
475 return packet_queue_put(q, pkt);
478 /* packet queue handling */
479 static int packet_queue_init(PacketQueue *q)
481 memset(q, 0, sizeof(PacketQueue));
482 q->mutex = SDL_CreateMutex();
484 av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError());
485 return AVERROR(ENOMEM);
487 q->cond = SDL_CreateCond();
489 av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError());
490 return AVERROR(ENOMEM);
492 q->abort_request = 1;
496 static void packet_queue_flush(PacketQueue *q)
498 MyAVPacketList *pkt, *pkt1;
500 SDL_LockMutex(q->mutex);
501 for (pkt = q->first_pkt; pkt; pkt = pkt1) {
503 av_packet_unref(&pkt->pkt);
511 SDL_UnlockMutex(q->mutex);
514 static void packet_queue_destroy(PacketQueue *q)
516 packet_queue_flush(q);
517 SDL_DestroyMutex(q->mutex);
518 SDL_DestroyCond(q->cond);
521 static void packet_queue_abort(PacketQueue *q)
523 SDL_LockMutex(q->mutex);
525 q->abort_request = 1;
527 SDL_CondSignal(q->cond);
529 SDL_UnlockMutex(q->mutex);
532 static void packet_queue_start(PacketQueue *q)
534 SDL_LockMutex(q->mutex);
535 q->abort_request = 0;
536 packet_queue_put_private(q, &flush_pkt);
537 SDL_UnlockMutex(q->mutex);
540 /* return < 0 if aborted, 0 if no packet and > 0 if packet. */
541 static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block, int *serial)
543 MyAVPacketList *pkt1;
546 SDL_LockMutex(q->mutex);
549 if (q->abort_request) {
556 q->first_pkt = pkt1->next;
560 q->size -= pkt1->pkt.size + sizeof(*pkt1);
561 q->duration -= pkt1->pkt.duration;
564 *serial = pkt1->serial;
572 SDL_CondWait(q->cond, q->mutex);
575 SDL_UnlockMutex(q->mutex);
579 static void decoder_init(Decoder *d, AVCodecContext *avctx, PacketQueue *queue, SDL_cond *empty_queue_cond) {
580 memset(d, 0, sizeof(Decoder));
583 d->empty_queue_cond = empty_queue_cond;
584 d->start_pts = AV_NOPTS_VALUE;
588 static int decoder_decode_frame(Decoder *d, AVFrame *frame, AVSubtitle *sub) {
589 int ret = AVERROR(EAGAIN);
594 if (d->queue->serial == d->pkt_serial) {
596 if (d->queue->abort_request)
599 switch (d->avctx->codec_type) {
600 case AVMEDIA_TYPE_VIDEO:
601 ret = avcodec_receive_frame(d->avctx, frame);
603 if (decoder_reorder_pts == -1) {
604 frame->pts = frame->best_effort_timestamp;
605 } else if (!decoder_reorder_pts) {
606 frame->pts = frame->pkt_dts;
610 case AVMEDIA_TYPE_AUDIO:
611 ret = avcodec_receive_frame(d->avctx, frame);
613 AVRational tb = (AVRational){1, frame->sample_rate};
614 if (frame->pts != AV_NOPTS_VALUE)
615 frame->pts = av_rescale_q(frame->pts, d->avctx->pkt_timebase, tb);
616 else if (d->next_pts != AV_NOPTS_VALUE)
617 frame->pts = av_rescale_q(d->next_pts, d->next_pts_tb, tb);
618 if (frame->pts != AV_NOPTS_VALUE) {
619 d->next_pts = frame->pts + frame->nb_samples;
625 if (ret == AVERROR_EOF) {
626 d->finished = d->pkt_serial;
627 avcodec_flush_buffers(d->avctx);
632 } while (ret != AVERROR(EAGAIN));
636 if (d->queue->nb_packets == 0)
637 SDL_CondSignal(d->empty_queue_cond);
638 if (d->packet_pending) {
639 av_packet_move_ref(&pkt, &d->pkt);
640 d->packet_pending = 0;
642 if (packet_queue_get(d->queue, &pkt, 1, &d->pkt_serial) < 0)
645 } while (d->queue->serial != d->pkt_serial);
647 if (pkt.data == flush_pkt.data) {
648 avcodec_flush_buffers(d->avctx);
650 d->next_pts = d->start_pts;
651 d->next_pts_tb = d->start_pts_tb;
653 if (d->avctx->codec_type == AVMEDIA_TYPE_SUBTITLE) {
655 ret = avcodec_decode_subtitle2(d->avctx, sub, &got_frame, &pkt);
657 ret = AVERROR(EAGAIN);
659 if (got_frame && !pkt.data) {
660 d->packet_pending = 1;
661 av_packet_move_ref(&d->pkt, &pkt);
663 ret = got_frame ? 0 : (pkt.data ? AVERROR(EAGAIN) : AVERROR_EOF);
666 if (avcodec_send_packet(d->avctx, &pkt) == AVERROR(EAGAIN)) {
667 av_log(d->avctx, AV_LOG_ERROR, "Receive_frame and send_packet both returned EAGAIN, which is an API violation.\n");
668 d->packet_pending = 1;
669 av_packet_move_ref(&d->pkt, &pkt);
672 av_packet_unref(&pkt);
677 static void decoder_destroy(Decoder *d) {
678 av_packet_unref(&d->pkt);
679 avcodec_free_context(&d->avctx);
682 static void frame_queue_unref_item(Frame *vp)
684 av_frame_unref(vp->frame);
685 avsubtitle_free(&vp->sub);
688 static int frame_queue_init(FrameQueue *f, PacketQueue *pktq, int max_size, int keep_last)
691 memset(f, 0, sizeof(FrameQueue));
692 if (!(f->mutex = SDL_CreateMutex())) {
693 av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError());
694 return AVERROR(ENOMEM);
696 if (!(f->cond = SDL_CreateCond())) {
697 av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError());
698 return AVERROR(ENOMEM);
701 f->max_size = FFMIN(max_size, FRAME_QUEUE_SIZE);
702 f->keep_last = !!keep_last;
703 for (i = 0; i < f->max_size; i++)
704 if (!(f->queue[i].frame = av_frame_alloc()))
705 return AVERROR(ENOMEM);
709 static void frame_queue_destory(FrameQueue *f)
712 for (i = 0; i < f->max_size; i++) {
713 Frame *vp = &f->queue[i];
714 frame_queue_unref_item(vp);
715 av_frame_free(&vp->frame);
717 SDL_DestroyMutex(f->mutex);
718 SDL_DestroyCond(f->cond);
721 static void frame_queue_signal(FrameQueue *f)
723 SDL_LockMutex(f->mutex);
724 SDL_CondSignal(f->cond);
725 SDL_UnlockMutex(f->mutex);
728 static Frame *frame_queue_peek(FrameQueue *f)
730 return &f->queue[(f->rindex + f->rindex_shown) % f->max_size];
733 static Frame *frame_queue_peek_next(FrameQueue *f)
735 return &f->queue[(f->rindex + f->rindex_shown + 1) % f->max_size];
738 static Frame *frame_queue_peek_last(FrameQueue *f)
740 return &f->queue[f->rindex];
743 static Frame *frame_queue_peek_writable(FrameQueue *f)
745 /* wait until we have space to put a new frame */
746 SDL_LockMutex(f->mutex);
747 while (f->size >= f->max_size &&
748 !f->pktq->abort_request) {
749 SDL_CondWait(f->cond, f->mutex);
751 SDL_UnlockMutex(f->mutex);
753 if (f->pktq->abort_request)
756 return &f->queue[f->windex];
759 static Frame *frame_queue_peek_readable(FrameQueue *f)
761 /* wait until we have a readable a new frame */
762 SDL_LockMutex(f->mutex);
763 while (f->size - f->rindex_shown <= 0 &&
764 !f->pktq->abort_request) {
765 SDL_CondWait(f->cond, f->mutex);
767 SDL_UnlockMutex(f->mutex);
769 if (f->pktq->abort_request)
772 return &f->queue[(f->rindex + f->rindex_shown) % f->max_size];
775 static void frame_queue_push(FrameQueue *f)
777 if (++f->windex == f->max_size)
779 SDL_LockMutex(f->mutex);
781 SDL_CondSignal(f->cond);
782 SDL_UnlockMutex(f->mutex);
785 static void frame_queue_next(FrameQueue *f)
787 if (f->keep_last && !f->rindex_shown) {
791 frame_queue_unref_item(&f->queue[f->rindex]);
792 if (++f->rindex == f->max_size)
794 SDL_LockMutex(f->mutex);
796 SDL_CondSignal(f->cond);
797 SDL_UnlockMutex(f->mutex);
800 /* return the number of undisplayed frames in the queue */
801 static int frame_queue_nb_remaining(FrameQueue *f)
803 return f->size - f->rindex_shown;
806 /* return last shown position */
807 static int64_t frame_queue_last_pos(FrameQueue *f)
809 Frame *fp = &f->queue[f->rindex];
810 if (f->rindex_shown && fp->serial == f->pktq->serial)
816 static void decoder_abort(Decoder *d, FrameQueue *fq)
818 packet_queue_abort(d->queue);
819 frame_queue_signal(fq);
820 SDL_WaitThread(d->decoder_tid, NULL);
821 d->decoder_tid = NULL;
822 packet_queue_flush(d->queue);
825 static inline void fill_rectangle(int x, int y, int w, int h)
833 SDL_RenderFillRect(renderer, &rect);
836 static int realloc_texture(SDL_Texture **texture, Uint32 new_format, int new_width, int new_height, SDL_BlendMode blendmode, int init_texture)
840 if (!*texture || SDL_QueryTexture(*texture, &format, &access, &w, &h) < 0 || new_width != w || new_height != h || new_format != format) {
844 SDL_DestroyTexture(*texture);
845 if (!(*texture = SDL_CreateTexture(renderer, new_format, SDL_TEXTUREACCESS_STREAMING, new_width, new_height)))
847 if (SDL_SetTextureBlendMode(*texture, blendmode) < 0)
850 if (SDL_LockTexture(*texture, NULL, &pixels, &pitch) < 0)
852 memset(pixels, 0, pitch * new_height);
853 SDL_UnlockTexture(*texture);
855 av_log(NULL, AV_LOG_VERBOSE, "Created %dx%d texture with %s.\n", new_width, new_height, SDL_GetPixelFormatName(new_format));
860 static void calculate_display_rect(SDL_Rect *rect,
861 int scr_xleft, int scr_ytop, int scr_width, int scr_height,
862 int pic_width, int pic_height, AVRational pic_sar)
864 AVRational aspect_ratio = pic_sar;
865 int64_t width, height, x, y;
867 if (av_cmp_q(aspect_ratio, av_make_q(0, 1)) <= 0)
868 aspect_ratio = av_make_q(1, 1);
870 aspect_ratio = av_mul_q(aspect_ratio, av_make_q(pic_width, pic_height));
872 /* XXX: we suppose the screen has a 1.0 pixel ratio */
874 width = av_rescale(height, aspect_ratio.num, aspect_ratio.den) & ~1;
875 if (width > scr_width) {
877 height = av_rescale(width, aspect_ratio.den, aspect_ratio.num) & ~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((int)width, 1);
884 rect->h = FFMAX((int)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 set_sdl_yuv_conversion_mode(AVFrame *frame)
958 #if SDL_VERSION_ATLEAST(2,0,8)
959 SDL_YUV_CONVERSION_MODE mode = SDL_YUV_CONVERSION_AUTOMATIC;
960 if (frame && (frame->format == AV_PIX_FMT_YUV420P || frame->format == AV_PIX_FMT_YUYV422 || frame->format == AV_PIX_FMT_UYVY422)) {
961 if (frame->color_range == AVCOL_RANGE_JPEG)
962 mode = SDL_YUV_CONVERSION_JPEG;
963 else if (frame->colorspace == AVCOL_SPC_BT709)
964 mode = SDL_YUV_CONVERSION_BT709;
965 else if (frame->colorspace == AVCOL_SPC_BT470BG || frame->colorspace == AVCOL_SPC_SMPTE170M || frame->colorspace == AVCOL_SPC_SMPTE240M)
966 mode = SDL_YUV_CONVERSION_BT601;
968 SDL_SetYUVConversionMode(mode);
972 static void video_image_display(VideoState *is)
978 vp = frame_queue_peek_last(&is->pictq);
979 if (is->subtitle_st) {
980 if (frame_queue_nb_remaining(&is->subpq) > 0) {
981 sp = frame_queue_peek(&is->subpq);
983 if (vp->pts >= sp->pts + ((float) sp->sub.start_display_time / 1000)) {
988 if (!sp->width || !sp->height) {
989 sp->width = vp->width;
990 sp->height = vp->height;
992 if (realloc_texture(&is->sub_texture, SDL_PIXELFORMAT_ARGB8888, sp->width, sp->height, SDL_BLENDMODE_BLEND, 1) < 0)
995 for (i = 0; i < sp->sub.num_rects; i++) {
996 AVSubtitleRect *sub_rect = sp->sub.rects[i];
998 sub_rect->x = av_clip(sub_rect->x, 0, sp->width );
999 sub_rect->y = av_clip(sub_rect->y, 0, sp->height);
1000 sub_rect->w = av_clip(sub_rect->w, 0, sp->width - sub_rect->x);
1001 sub_rect->h = av_clip(sub_rect->h, 0, sp->height - sub_rect->y);
1003 is->sub_convert_ctx = sws_getCachedContext(is->sub_convert_ctx,
1004 sub_rect->w, sub_rect->h, AV_PIX_FMT_PAL8,
1005 sub_rect->w, sub_rect->h, AV_PIX_FMT_BGRA,
1006 0, NULL, NULL, NULL);
1007 if (!is->sub_convert_ctx) {
1008 av_log(NULL, AV_LOG_FATAL, "Cannot initialize the conversion context\n");
1011 if (!SDL_LockTexture(is->sub_texture, (SDL_Rect *)sub_rect, (void **)pixels, pitch)) {
1012 sws_scale(is->sub_convert_ctx, (const uint8_t * const *)sub_rect->data, sub_rect->linesize,
1013 0, sub_rect->h, pixels, pitch);
1014 SDL_UnlockTexture(is->sub_texture);
1024 calculate_display_rect(&rect, is->xleft, is->ytop, is->width, is->height, vp->width, vp->height, vp->sar);
1026 if (!vp->uploaded) {
1027 if (upload_texture(&is->vid_texture, vp->frame, &is->img_convert_ctx) < 0)
1030 vp->flip_v = vp->frame->linesize[0] < 0;
1033 set_sdl_yuv_conversion_mode(vp->frame);
1034 SDL_RenderCopyEx(renderer, is->vid_texture, NULL, &rect, 0, NULL, vp->flip_v ? SDL_FLIP_VERTICAL : 0);
1035 set_sdl_yuv_conversion_mode(NULL);
1037 #if USE_ONEPASS_SUBTITLE_RENDER
1038 SDL_RenderCopy(renderer, is->sub_texture, NULL, &rect);
1041 double xratio = (double)rect.w / (double)sp->width;
1042 double yratio = (double)rect.h / (double)sp->height;
1043 for (i = 0; i < sp->sub.num_rects; i++) {
1044 SDL_Rect *sub_rect = (SDL_Rect*)sp->sub.rects[i];
1045 SDL_Rect target = {.x = rect.x + sub_rect->x * xratio,
1046 .y = rect.y + sub_rect->y * yratio,
1047 .w = sub_rect->w * xratio,
1048 .h = sub_rect->h * yratio};
1049 SDL_RenderCopy(renderer, is->sub_texture, sub_rect, &target);
1055 static inline int compute_mod(int a, int b)
1057 return a < 0 ? a%b + b : a%b;
1060 static void video_audio_display(VideoState *s)
1062 int i, i_start, x, y1, y, ys, delay, n, nb_display_channels;
1063 int ch, channels, h, h2;
1065 int rdft_bits, nb_freq;
1067 for (rdft_bits = 1; (1 << rdft_bits) < 2 * s->height; rdft_bits++)
1069 nb_freq = 1 << (rdft_bits - 1);
1071 /* compute display index : center on currently output samples */
1072 channels = s->audio_tgt.channels;
1073 nb_display_channels = channels;
1075 int data_used= s->show_mode == SHOW_MODE_WAVES ? s->width : (2*nb_freq);
1077 delay = s->audio_write_buf_size;
1080 /* to be more precise, we take into account the time spent since
1081 the last buffer computation */
1082 if (audio_callback_time) {
1083 time_diff = av_gettime_relative() - audio_callback_time;
1084 delay -= (time_diff * s->audio_tgt.freq) / 1000000;
1087 delay += 2 * data_used;
1088 if (delay < data_used)
1091 i_start= x = compute_mod(s->sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE);
1092 if (s->show_mode == SHOW_MODE_WAVES) {
1094 for (i = 0; i < 1000; i += channels) {
1095 int idx = (SAMPLE_ARRAY_SIZE + x - i) % SAMPLE_ARRAY_SIZE;
1096 int a = s->sample_array[idx];
1097 int b = s->sample_array[(idx + 4 * channels) % SAMPLE_ARRAY_SIZE];
1098 int c = s->sample_array[(idx + 5 * channels) % SAMPLE_ARRAY_SIZE];
1099 int d = s->sample_array[(idx + 9 * channels) % SAMPLE_ARRAY_SIZE];
1101 if (h < score && (b ^ c) < 0) {
1108 s->last_i_start = i_start;
1110 i_start = s->last_i_start;
1113 if (s->show_mode == SHOW_MODE_WAVES) {
1114 SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
1116 /* total height for one channel */
1117 h = s->height / nb_display_channels;
1118 /* graph height / 2 */
1120 for (ch = 0; ch < nb_display_channels; ch++) {
1122 y1 = s->ytop + ch * h + (h / 2); /* position of center line */
1123 for (x = 0; x < s->width; x++) {
1124 y = (s->sample_array[i] * h2) >> 15;
1131 fill_rectangle(s->xleft + x, ys, 1, y);
1133 if (i >= SAMPLE_ARRAY_SIZE)
1134 i -= SAMPLE_ARRAY_SIZE;
1138 SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
1140 for (ch = 1; ch < nb_display_channels; ch++) {
1141 y = s->ytop + ch * h;
1142 fill_rectangle(s->xleft, y, s->width, 1);
1145 if (realloc_texture(&s->vis_texture, SDL_PIXELFORMAT_ARGB8888, s->width, s->height, SDL_BLENDMODE_NONE, 1) < 0)
1148 nb_display_channels= FFMIN(nb_display_channels, 2);
1149 if (rdft_bits != s->rdft_bits) {
1150 av_rdft_end(s->rdft);
1151 av_free(s->rdft_data);
1152 s->rdft = av_rdft_init(rdft_bits, DFT_R2C);
1153 s->rdft_bits = rdft_bits;
1154 s->rdft_data = av_malloc_array(nb_freq, 4 *sizeof(*s->rdft_data));
1156 if (!s->rdft || !s->rdft_data){
1157 av_log(NULL, AV_LOG_ERROR, "Failed to allocate buffers for RDFT, switching to waves display\n");
1158 s->show_mode = SHOW_MODE_WAVES;
1161 SDL_Rect rect = {.x = s->xpos, .y = 0, .w = 1, .h = s->height};
1164 for (ch = 0; ch < nb_display_channels; ch++) {
1165 data[ch] = s->rdft_data + 2 * nb_freq * ch;
1167 for (x = 0; x < 2 * nb_freq; x++) {
1168 double w = (x-nb_freq) * (1.0 / nb_freq);
1169 data[ch][x] = s->sample_array[i] * (1.0 - w * w);
1171 if (i >= SAMPLE_ARRAY_SIZE)
1172 i -= SAMPLE_ARRAY_SIZE;
1174 av_rdft_calc(s->rdft, data[ch]);
1176 /* Least efficient way to do this, we should of course
1177 * directly access it but it is more than fast enough. */
1178 if (!SDL_LockTexture(s->vis_texture, &rect, (void **)&pixels, &pitch)) {
1180 pixels += pitch * s->height;
1181 for (y = 0; y < s->height; y++) {
1182 double w = 1 / sqrt(nb_freq);
1183 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]));
1184 int b = (nb_display_channels == 2 ) ? sqrt(w * hypot(data[1][2 * y + 0], data[1][2 * y + 1]))
1189 *pixels = (a << 16) + (b << 8) + ((a+b) >> 1);
1191 SDL_UnlockTexture(s->vis_texture);
1193 SDL_RenderCopy(renderer, s->vis_texture, NULL, NULL);
1197 if (s->xpos >= s->width)
1202 static void stream_component_close(VideoState *is, int stream_index)
1204 AVFormatContext *ic = is->ic;
1205 AVCodecParameters *codecpar;
1207 if (stream_index < 0 || stream_index >= ic->nb_streams)
1209 codecpar = ic->streams[stream_index]->codecpar;
1211 switch (codecpar->codec_type) {
1212 case AVMEDIA_TYPE_AUDIO:
1213 decoder_abort(&is->auddec, &is->sampq);
1214 SDL_CloseAudioDevice(audio_dev);
1215 decoder_destroy(&is->auddec);
1216 swr_free(&is->swr_ctx);
1217 av_freep(&is->audio_buf1);
1218 is->audio_buf1_size = 0;
1219 is->audio_buf = NULL;
1222 av_rdft_end(is->rdft);
1223 av_freep(&is->rdft_data);
1228 case AVMEDIA_TYPE_VIDEO:
1229 decoder_abort(&is->viddec, &is->pictq);
1230 decoder_destroy(&is->viddec);
1232 case AVMEDIA_TYPE_SUBTITLE:
1233 decoder_abort(&is->subdec, &is->subpq);
1234 decoder_destroy(&is->subdec);
1240 ic->streams[stream_index]->discard = AVDISCARD_ALL;
1241 switch (codecpar->codec_type) {
1242 case AVMEDIA_TYPE_AUDIO:
1243 is->audio_st = NULL;
1244 is->audio_stream = -1;
1246 case AVMEDIA_TYPE_VIDEO:
1247 is->video_st = NULL;
1248 is->video_stream = -1;
1250 case AVMEDIA_TYPE_SUBTITLE:
1251 is->subtitle_st = NULL;
1252 is->subtitle_stream = -1;
1259 static void stream_close(VideoState *is)
1261 /* XXX: use a special url_shutdown call to abort parse cleanly */
1262 is->abort_request = 1;
1263 SDL_WaitThread(is->read_tid, NULL);
1265 /* close each stream */
1266 if (is->audio_stream >= 0)
1267 stream_component_close(is, is->audio_stream);
1268 if (is->video_stream >= 0)
1269 stream_component_close(is, is->video_stream);
1270 if (is->subtitle_stream >= 0)
1271 stream_component_close(is, is->subtitle_stream);
1273 avformat_close_input(&is->ic);
1275 packet_queue_destroy(&is->videoq);
1276 packet_queue_destroy(&is->audioq);
1277 packet_queue_destroy(&is->subtitleq);
1279 /* free all pictures */
1280 frame_queue_destory(&is->pictq);
1281 frame_queue_destory(&is->sampq);
1282 frame_queue_destory(&is->subpq);
1283 SDL_DestroyCond(is->continue_read_thread);
1284 sws_freeContext(is->img_convert_ctx);
1285 sws_freeContext(is->sub_convert_ctx);
1286 av_free(is->filename);
1287 if (is->vis_texture)
1288 SDL_DestroyTexture(is->vis_texture);
1289 if (is->vid_texture)
1290 SDL_DestroyTexture(is->vid_texture);
1291 if (is->sub_texture)
1292 SDL_DestroyTexture(is->sub_texture);
1296 static void do_exit(VideoState *is)
1302 SDL_DestroyRenderer(renderer);
1304 SDL_DestroyWindow(window);
1307 av_freep(&vfilters_list);
1309 avformat_network_deinit();
1313 av_log(NULL, AV_LOG_QUIET, "%s", "");
1317 static void sigterm_handler(int sig)
1322 static void set_default_window_size(int width, int height, AVRational sar)
1325 calculate_display_rect(&rect, 0, 0, INT_MAX, height, width, height, sar);
1326 default_width = rect.w;
1327 default_height = rect.h;
1330 static int video_open(VideoState *is)
1343 window_title = input_filename;
1344 SDL_SetWindowTitle(window, window_title);
1346 SDL_SetWindowSize(window, w, h);
1347 SDL_SetWindowPosition(window, screen_left, screen_top);
1349 SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
1350 SDL_ShowWindow(window);
1358 /* display the current picture, if any */
1359 static void video_display(VideoState *is)
1364 SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
1365 SDL_RenderClear(renderer);
1366 if (is->audio_st && is->show_mode != SHOW_MODE_VIDEO)
1367 video_audio_display(is);
1368 else if (is->video_st)
1369 video_image_display(is);
1370 SDL_RenderPresent(renderer);
1373 static double get_clock(Clock *c)
1375 if (*c->queue_serial != c->serial)
1380 double time = av_gettime_relative() / 1000000.0;
1381 return c->pts_drift + time - (time - c->last_updated) * (1.0 - c->speed);
1385 static void set_clock_at(Clock *c, double pts, int serial, double time)
1388 c->last_updated = time;
1389 c->pts_drift = c->pts - time;
1393 static void set_clock(Clock *c, double pts, int serial)
1395 double time = av_gettime_relative() / 1000000.0;
1396 set_clock_at(c, pts, serial, time);
1399 static void set_clock_speed(Clock *c, double speed)
1401 set_clock(c, get_clock(c), c->serial);
1405 static void init_clock(Clock *c, int *queue_serial)
1409 c->queue_serial = queue_serial;
1410 set_clock(c, NAN, -1);
1413 static void sync_clock_to_slave(Clock *c, Clock *slave)
1415 double clock = get_clock(c);
1416 double slave_clock = get_clock(slave);
1417 if (!isnan(slave_clock) && (isnan(clock) || fabs(clock - slave_clock) > AV_NOSYNC_THRESHOLD))
1418 set_clock(c, slave_clock, slave->serial);
1421 static int get_master_sync_type(VideoState *is) {
1422 if (is->av_sync_type == AV_SYNC_VIDEO_MASTER) {
1424 return AV_SYNC_VIDEO_MASTER;
1426 return AV_SYNC_AUDIO_MASTER;
1427 } else if (is->av_sync_type == AV_SYNC_AUDIO_MASTER) {
1429 return AV_SYNC_AUDIO_MASTER;
1431 return AV_SYNC_EXTERNAL_CLOCK;
1433 return AV_SYNC_EXTERNAL_CLOCK;
1437 /* get the current master clock value */
1438 static double get_master_clock(VideoState *is)
1442 switch (get_master_sync_type(is)) {
1443 case AV_SYNC_VIDEO_MASTER:
1444 val = get_clock(&is->vidclk);
1446 case AV_SYNC_AUDIO_MASTER:
1447 val = get_clock(&is->audclk);
1450 val = get_clock(&is->extclk);
1456 static void check_external_clock_speed(VideoState *is) {
1457 if (is->video_stream >= 0 && is->videoq.nb_packets <= EXTERNAL_CLOCK_MIN_FRAMES ||
1458 is->audio_stream >= 0 && is->audioq.nb_packets <= EXTERNAL_CLOCK_MIN_FRAMES) {
1459 set_clock_speed(&is->extclk, FFMAX(EXTERNAL_CLOCK_SPEED_MIN, is->extclk.speed - EXTERNAL_CLOCK_SPEED_STEP));
1460 } else if ((is->video_stream < 0 || is->videoq.nb_packets > EXTERNAL_CLOCK_MAX_FRAMES) &&
1461 (is->audio_stream < 0 || is->audioq.nb_packets > EXTERNAL_CLOCK_MAX_FRAMES)) {
1462 set_clock_speed(&is->extclk, FFMIN(EXTERNAL_CLOCK_SPEED_MAX, is->extclk.speed + EXTERNAL_CLOCK_SPEED_STEP));
1464 double speed = is->extclk.speed;
1466 set_clock_speed(&is->extclk, speed + EXTERNAL_CLOCK_SPEED_STEP * (1.0 - speed) / fabs(1.0 - speed));
1470 /* seek in the stream */
1471 static void stream_seek(VideoState *is, int64_t pos, int64_t rel, int seek_by_bytes)
1473 if (!is->seek_req) {
1476 is->seek_flags &= ~AVSEEK_FLAG_BYTE;
1478 is->seek_flags |= AVSEEK_FLAG_BYTE;
1480 SDL_CondSignal(is->continue_read_thread);
1484 /* pause or resume the video */
1485 static void stream_toggle_pause(VideoState *is)
1488 is->frame_timer += av_gettime_relative() / 1000000.0 - is->vidclk.last_updated;
1489 if (is->read_pause_return != AVERROR(ENOSYS)) {
1490 is->vidclk.paused = 0;
1492 set_clock(&is->vidclk, get_clock(&is->vidclk), is->vidclk.serial);
1494 set_clock(&is->extclk, get_clock(&is->extclk), is->extclk.serial);
1495 is->paused = is->audclk.paused = is->vidclk.paused = is->extclk.paused = !is->paused;
1498 static void toggle_pause(VideoState *is)
1500 stream_toggle_pause(is);
1504 static void toggle_mute(VideoState *is)
1506 is->muted = !is->muted;
1509 static void update_volume(VideoState *is, int sign, double step)
1511 double volume_level = is->audio_volume ? (20 * log(is->audio_volume / (double)SDL_MIX_MAXVOLUME) / log(10)) : -1000.0;
1512 int new_volume = lrint(SDL_MIX_MAXVOLUME * pow(10.0, (volume_level + sign * step) / 20.0));
1513 is->audio_volume = av_clip(is->audio_volume == new_volume ? (is->audio_volume + sign) : new_volume, 0, SDL_MIX_MAXVOLUME);
1516 static void step_to_next_frame(VideoState *is)
1518 /* if the stream is paused unpause it, then step */
1520 stream_toggle_pause(is);
1524 static double compute_target_delay(double delay, VideoState *is)
1526 double sync_threshold, diff = 0;
1528 /* update delay to follow master synchronisation source */
1529 if (get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER) {
1530 /* if video is slave, we try to correct big delays by
1531 duplicating or deleting a frame */
1532 diff = get_clock(&is->vidclk) - get_master_clock(is);
1534 /* skip or repeat frame. We take into account the
1535 delay to compute the threshold. I still don't know
1536 if it is the best guess */
1537 sync_threshold = FFMAX(AV_SYNC_THRESHOLD_MIN, FFMIN(AV_SYNC_THRESHOLD_MAX, delay));
1538 if (!isnan(diff) && fabs(diff) < is->max_frame_duration) {
1539 if (diff <= -sync_threshold)
1540 delay = FFMAX(0, delay + diff);
1541 else if (diff >= sync_threshold && delay > AV_SYNC_FRAMEDUP_THRESHOLD)
1542 delay = delay + diff;
1543 else if (diff >= sync_threshold)
1548 av_log(NULL, AV_LOG_TRACE, "video: delay=%0.3f A-V=%f\n",
1554 static double vp_duration(VideoState *is, Frame *vp, Frame *nextvp) {
1555 if (vp->serial == nextvp->serial) {
1556 double duration = nextvp->pts - vp->pts;
1557 if (isnan(duration) || duration <= 0 || duration > is->max_frame_duration)
1558 return vp->duration;
1566 static void update_video_pts(VideoState *is, double pts, int64_t pos, int serial) {
1567 /* update current video pts */
1568 set_clock(&is->vidclk, pts, serial);
1569 sync_clock_to_slave(&is->extclk, &is->vidclk);
1572 /* called to display each frame */
1573 static void video_refresh(void *opaque, double *remaining_time)
1575 VideoState *is = opaque;
1580 if (!is->paused && get_master_sync_type(is) == AV_SYNC_EXTERNAL_CLOCK && is->realtime)
1581 check_external_clock_speed(is);
1583 if (!display_disable && is->show_mode != SHOW_MODE_VIDEO && is->audio_st) {
1584 time = av_gettime_relative() / 1000000.0;
1585 if (is->force_refresh || is->last_vis_time + rdftspeed < time) {
1587 is->last_vis_time = time;
1589 *remaining_time = FFMIN(*remaining_time, is->last_vis_time + rdftspeed - time);
1594 if (frame_queue_nb_remaining(&is->pictq) == 0) {
1595 // nothing to do, no picture to display in the queue
1597 double last_duration, duration, delay;
1600 /* dequeue the picture */
1601 lastvp = frame_queue_peek_last(&is->pictq);
1602 vp = frame_queue_peek(&is->pictq);
1604 if (vp->serial != is->videoq.serial) {
1605 frame_queue_next(&is->pictq);
1609 if (lastvp->serial != vp->serial)
1610 is->frame_timer = av_gettime_relative() / 1000000.0;
1615 /* compute nominal last_duration */
1616 last_duration = vp_duration(is, lastvp, vp);
1617 delay = compute_target_delay(last_duration, is);
1619 time= av_gettime_relative()/1000000.0;
1620 if (time < is->frame_timer + delay) {
1621 *remaining_time = FFMIN(is->frame_timer + delay - time, *remaining_time);
1625 is->frame_timer += delay;
1626 if (delay > 0 && time - is->frame_timer > AV_SYNC_THRESHOLD_MAX)
1627 is->frame_timer = time;
1629 SDL_LockMutex(is->pictq.mutex);
1630 if (!isnan(vp->pts))
1631 update_video_pts(is, vp->pts, vp->pos, vp->serial);
1632 SDL_UnlockMutex(is->pictq.mutex);
1634 if (frame_queue_nb_remaining(&is->pictq) > 1) {
1635 Frame *nextvp = frame_queue_peek_next(&is->pictq);
1636 duration = vp_duration(is, vp, nextvp);
1637 if(!is->step && (framedrop>0 || (framedrop && get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER)) && time > is->frame_timer + duration){
1638 is->frame_drops_late++;
1639 frame_queue_next(&is->pictq);
1644 if (is->subtitle_st) {
1645 while (frame_queue_nb_remaining(&is->subpq) > 0) {
1646 sp = frame_queue_peek(&is->subpq);
1648 if (frame_queue_nb_remaining(&is->subpq) > 1)
1649 sp2 = frame_queue_peek_next(&is->subpq);
1653 if (sp->serial != is->subtitleq.serial
1654 || (is->vidclk.pts > (sp->pts + ((float) sp->sub.end_display_time / 1000)))
1655 || (sp2 && is->vidclk.pts > (sp2->pts + ((float) sp2->sub.start_display_time / 1000))))
1659 for (i = 0; i < sp->sub.num_rects; i++) {
1660 AVSubtitleRect *sub_rect = sp->sub.rects[i];
1664 if (!SDL_LockTexture(is->sub_texture, (SDL_Rect *)sub_rect, (void **)&pixels, &pitch)) {
1665 for (j = 0; j < sub_rect->h; j++, pixels += pitch)
1666 memset(pixels, 0, sub_rect->w << 2);
1667 SDL_UnlockTexture(is->sub_texture);
1671 frame_queue_next(&is->subpq);
1678 frame_queue_next(&is->pictq);
1679 is->force_refresh = 1;
1681 if (is->step && !is->paused)
1682 stream_toggle_pause(is);
1685 /* display picture */
1686 if (!display_disable && is->force_refresh && is->show_mode == SHOW_MODE_VIDEO && is->pictq.rindex_shown)
1689 is->force_refresh = 0;
1691 static int64_t last_time;
1693 int aqsize, vqsize, sqsize;
1696 cur_time = av_gettime_relative();
1697 if (!last_time || (cur_time - last_time) >= 30000) {
1702 aqsize = is->audioq.size;
1704 vqsize = is->videoq.size;
1705 if (is->subtitle_st)
1706 sqsize = is->subtitleq.size;
1708 if (is->audio_st && is->video_st)
1709 av_diff = get_clock(&is->audclk) - get_clock(&is->vidclk);
1710 else if (is->video_st)
1711 av_diff = get_master_clock(is) - get_clock(&is->vidclk);
1712 else if (is->audio_st)
1713 av_diff = get_master_clock(is) - get_clock(&is->audclk);
1714 av_log(NULL, AV_LOG_INFO,
1715 "%7.2f %s:%7.3f fd=%4d aq=%5dKB vq=%5dKB sq=%5dB f=%"PRId64"/%"PRId64" \r",
1716 get_master_clock(is),
1717 (is->audio_st && is->video_st) ? "A-V" : (is->video_st ? "M-V" : (is->audio_st ? "M-A" : " ")),
1719 is->frame_drops_early + is->frame_drops_late,
1723 is->video_st ? is->viddec.avctx->pts_correction_num_faulty_dts : 0,
1724 is->video_st ? is->viddec.avctx->pts_correction_num_faulty_pts : 0);
1726 last_time = cur_time;
1731 static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, double duration, int64_t pos, int serial)
1735 #if defined(DEBUG_SYNC)
1736 printf("frame_type=%c pts=%0.3f\n",
1737 av_get_picture_type_char(src_frame->pict_type), pts);
1740 if (!(vp = frame_queue_peek_writable(&is->pictq)))
1743 vp->sar = src_frame->sample_aspect_ratio;
1746 vp->width = src_frame->width;
1747 vp->height = src_frame->height;
1748 vp->format = src_frame->format;
1751 vp->duration = duration;
1753 vp->serial = serial;
1755 set_default_window_size(vp->width, vp->height, vp->sar);
1757 av_frame_move_ref(vp->frame, src_frame);
1758 frame_queue_push(&is->pictq);
1762 static int get_video_frame(VideoState *is, AVFrame *frame)
1766 if ((got_picture = decoder_decode_frame(&is->viddec, frame, NULL)) < 0)
1772 if (frame->pts != AV_NOPTS_VALUE)
1773 dpts = av_q2d(is->video_st->time_base) * frame->pts;
1775 frame->sample_aspect_ratio = av_guess_sample_aspect_ratio(is->ic, is->video_st, frame);
1777 if (framedrop>0 || (framedrop && get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER)) {
1778 if (frame->pts != AV_NOPTS_VALUE) {
1779 double diff = dpts - get_master_clock(is);
1780 if (!isnan(diff) && fabs(diff) < AV_NOSYNC_THRESHOLD &&
1781 diff - is->frame_last_filter_delay < 0 &&
1782 is->viddec.pkt_serial == is->vidclk.serial &&
1783 is->videoq.nb_packets) {
1784 is->frame_drops_early++;
1785 av_frame_unref(frame);
1796 static int configure_filtergraph(AVFilterGraph *graph, const char *filtergraph,
1797 AVFilterContext *source_ctx, AVFilterContext *sink_ctx)
1800 int nb_filters = graph->nb_filters;
1801 AVFilterInOut *outputs = NULL, *inputs = NULL;
1804 outputs = avfilter_inout_alloc();
1805 inputs = avfilter_inout_alloc();
1806 if (!outputs || !inputs) {
1807 ret = AVERROR(ENOMEM);
1811 outputs->name = av_strdup("in");
1812 outputs->filter_ctx = source_ctx;
1813 outputs->pad_idx = 0;
1814 outputs->next = NULL;
1816 inputs->name = av_strdup("out");
1817 inputs->filter_ctx = sink_ctx;
1818 inputs->pad_idx = 0;
1819 inputs->next = NULL;
1821 if ((ret = avfilter_graph_parse_ptr(graph, filtergraph, &inputs, &outputs, NULL)) < 0)
1824 if ((ret = avfilter_link(source_ctx, 0, sink_ctx, 0)) < 0)
1828 /* Reorder the filters to ensure that inputs of the custom filters are merged first */
1829 for (i = 0; i < graph->nb_filters - nb_filters; i++)
1830 FFSWAP(AVFilterContext*, graph->filters[i], graph->filters[i + nb_filters]);
1832 ret = avfilter_graph_config(graph, NULL);
1834 avfilter_inout_free(&outputs);
1835 avfilter_inout_free(&inputs);
1839 static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const char *vfilters, AVFrame *frame)
1841 enum AVPixelFormat pix_fmts[FF_ARRAY_ELEMS(sdl_texture_format_map)];
1842 char sws_flags_str[512] = "";
1843 char buffersrc_args[256];
1845 AVFilterContext *filt_src = NULL, *filt_out = NULL, *last_filter = NULL;
1846 AVCodecParameters *codecpar = is->video_st->codecpar;
1847 AVRational fr = av_guess_frame_rate(is->ic, is->video_st, NULL);
1848 AVDictionaryEntry *e = NULL;
1849 int nb_pix_fmts = 0;
1852 for (i = 0; i < renderer_info.num_texture_formats; i++) {
1853 for (j = 0; j < FF_ARRAY_ELEMS(sdl_texture_format_map) - 1; j++) {
1854 if (renderer_info.texture_formats[i] == sdl_texture_format_map[j].texture_fmt) {
1855 pix_fmts[nb_pix_fmts++] = sdl_texture_format_map[j].format;
1860 pix_fmts[nb_pix_fmts] = AV_PIX_FMT_NONE;
1862 while ((e = av_dict_get(sws_dict, "", e, AV_DICT_IGNORE_SUFFIX))) {
1863 if (!strcmp(e->key, "sws_flags")) {
1864 av_strlcatf(sws_flags_str, sizeof(sws_flags_str), "%s=%s:", "flags", e->value);
1866 av_strlcatf(sws_flags_str, sizeof(sws_flags_str), "%s=%s:", e->key, e->value);
1868 if (strlen(sws_flags_str))
1869 sws_flags_str[strlen(sws_flags_str)-1] = '\0';
1871 graph->scale_sws_opts = av_strdup(sws_flags_str);
1873 snprintf(buffersrc_args, sizeof(buffersrc_args),
1874 "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
1875 frame->width, frame->height, frame->format,
1876 is->video_st->time_base.num, is->video_st->time_base.den,
1877 codecpar->sample_aspect_ratio.num, FFMAX(codecpar->sample_aspect_ratio.den, 1));
1878 if (fr.num && fr.den)
1879 av_strlcatf(buffersrc_args, sizeof(buffersrc_args), ":frame_rate=%d/%d", fr.num, fr.den);
1881 if ((ret = avfilter_graph_create_filter(&filt_src,
1882 avfilter_get_by_name("buffer"),
1883 "ffplay_buffer", buffersrc_args, NULL,
1887 ret = avfilter_graph_create_filter(&filt_out,
1888 avfilter_get_by_name("buffersink"),
1889 "ffplay_buffersink", NULL, NULL, graph);
1893 if ((ret = av_opt_set_int_list(filt_out, "pix_fmts", pix_fmts, AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN)) < 0)
1896 last_filter = filt_out;
1898 /* Note: this macro adds a filter before the lastly added filter, so the
1899 * processing order of the filters is in reverse */
1900 #define INSERT_FILT(name, arg) do { \
1901 AVFilterContext *filt_ctx; \
1903 ret = avfilter_graph_create_filter(&filt_ctx, \
1904 avfilter_get_by_name(name), \
1905 "ffplay_" name, arg, NULL, graph); \
1909 ret = avfilter_link(filt_ctx, 0, last_filter, 0); \
1913 last_filter = filt_ctx; \
1917 double theta = get_rotation(is->video_st);
1919 if (fabs(theta - 90) < 1.0) {
1920 INSERT_FILT("transpose", "clock");
1921 } else if (fabs(theta - 180) < 1.0) {
1922 INSERT_FILT("hflip", NULL);
1923 INSERT_FILT("vflip", NULL);
1924 } else if (fabs(theta - 270) < 1.0) {
1925 INSERT_FILT("transpose", "cclock");
1926 } else if (fabs(theta) > 1.0) {
1927 char rotate_buf[64];
1928 snprintf(rotate_buf, sizeof(rotate_buf), "%f*PI/180", theta);
1929 INSERT_FILT("rotate", rotate_buf);
1933 if ((ret = configure_filtergraph(graph, vfilters, filt_src, last_filter)) < 0)
1936 is->in_video_filter = filt_src;
1937 is->out_video_filter = filt_out;
1943 static int configure_audio_filters(VideoState *is, const char *afilters, int force_output_format)
1945 static const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE };
1946 int sample_rates[2] = { 0, -1 };
1947 int64_t channel_layouts[2] = { 0, -1 };
1948 int channels[2] = { 0, -1 };
1949 AVFilterContext *filt_asrc = NULL, *filt_asink = NULL;
1950 char aresample_swr_opts[512] = "";
1951 AVDictionaryEntry *e = NULL;
1952 char asrc_args[256];
1955 avfilter_graph_free(&is->agraph);
1956 if (!(is->agraph = avfilter_graph_alloc()))
1957 return AVERROR(ENOMEM);
1959 while ((e = av_dict_get(swr_opts, "", e, AV_DICT_IGNORE_SUFFIX)))
1960 av_strlcatf(aresample_swr_opts, sizeof(aresample_swr_opts), "%s=%s:", e->key, e->value);
1961 if (strlen(aresample_swr_opts))
1962 aresample_swr_opts[strlen(aresample_swr_opts)-1] = '\0';
1963 av_opt_set(is->agraph, "aresample_swr_opts", aresample_swr_opts, 0);
1965 ret = snprintf(asrc_args, sizeof(asrc_args),
1966 "sample_rate=%d:sample_fmt=%s:channels=%d:time_base=%d/%d",
1967 is->audio_filter_src.freq, av_get_sample_fmt_name(is->audio_filter_src.fmt),
1968 is->audio_filter_src.channels,
1969 1, is->audio_filter_src.freq);
1970 if (is->audio_filter_src.channel_layout)
1971 snprintf(asrc_args + ret, sizeof(asrc_args) - ret,
1972 ":channel_layout=0x%"PRIx64, is->audio_filter_src.channel_layout);
1974 ret = avfilter_graph_create_filter(&filt_asrc,
1975 avfilter_get_by_name("abuffer"), "ffplay_abuffer",
1976 asrc_args, NULL, is->agraph);
1981 ret = avfilter_graph_create_filter(&filt_asink,
1982 avfilter_get_by_name("abuffersink"), "ffplay_abuffersink",
1983 NULL, NULL, is->agraph);
1987 if ((ret = av_opt_set_int_list(filt_asink, "sample_fmts", sample_fmts, AV_SAMPLE_FMT_NONE, AV_OPT_SEARCH_CHILDREN)) < 0)
1989 if ((ret = av_opt_set_int(filt_asink, "all_channel_counts", 1, AV_OPT_SEARCH_CHILDREN)) < 0)
1992 if (force_output_format) {
1993 channel_layouts[0] = is->audio_tgt.channel_layout;
1994 channels [0] = is->audio_tgt.channels;
1995 sample_rates [0] = is->audio_tgt.freq;
1996 if ((ret = av_opt_set_int(filt_asink, "all_channel_counts", 0, AV_OPT_SEARCH_CHILDREN)) < 0)
1998 if ((ret = av_opt_set_int_list(filt_asink, "channel_layouts", channel_layouts, -1, AV_OPT_SEARCH_CHILDREN)) < 0)
2000 if ((ret = av_opt_set_int_list(filt_asink, "channel_counts" , channels , -1, AV_OPT_SEARCH_CHILDREN)) < 0)
2002 if ((ret = av_opt_set_int_list(filt_asink, "sample_rates" , sample_rates , -1, AV_OPT_SEARCH_CHILDREN)) < 0)
2007 if ((ret = configure_filtergraph(is->agraph, afilters, filt_asrc, filt_asink)) < 0)
2010 is->in_audio_filter = filt_asrc;
2011 is->out_audio_filter = filt_asink;
2015 avfilter_graph_free(&is->agraph);
2018 #endif /* CONFIG_AVFILTER */
2020 static int audio_thread(void *arg)
2022 VideoState *is = arg;
2023 AVFrame *frame = av_frame_alloc();
2026 int last_serial = -1;
2027 int64_t dec_channel_layout;
2035 return AVERROR(ENOMEM);
2038 if ((got_frame = decoder_decode_frame(&is->auddec, frame, NULL)) < 0)
2042 tb = (AVRational){1, frame->sample_rate};
2045 dec_channel_layout = get_valid_channel_layout(frame->channel_layout, frame->channels);
2048 cmp_audio_fmts(is->audio_filter_src.fmt, is->audio_filter_src.channels,
2049 frame->format, frame->channels) ||
2050 is->audio_filter_src.channel_layout != dec_channel_layout ||
2051 is->audio_filter_src.freq != frame->sample_rate ||
2052 is->auddec.pkt_serial != last_serial;
2055 char buf1[1024], buf2[1024];
2056 av_get_channel_layout_string(buf1, sizeof(buf1), -1, is->audio_filter_src.channel_layout);
2057 av_get_channel_layout_string(buf2, sizeof(buf2), -1, dec_channel_layout);
2058 av_log(NULL, AV_LOG_DEBUG,
2059 "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",
2060 is->audio_filter_src.freq, is->audio_filter_src.channels, av_get_sample_fmt_name(is->audio_filter_src.fmt), buf1, last_serial,
2061 frame->sample_rate, frame->channels, av_get_sample_fmt_name(frame->format), buf2, is->auddec.pkt_serial);
2063 is->audio_filter_src.fmt = frame->format;
2064 is->audio_filter_src.channels = frame->channels;
2065 is->audio_filter_src.channel_layout = dec_channel_layout;
2066 is->audio_filter_src.freq = frame->sample_rate;
2067 last_serial = is->auddec.pkt_serial;
2069 if ((ret = configure_audio_filters(is, afilters, 1)) < 0)
2073 if ((ret = av_buffersrc_add_frame(is->in_audio_filter, frame)) < 0)
2076 while ((ret = av_buffersink_get_frame_flags(is->out_audio_filter, frame, 0)) >= 0) {
2077 tb = av_buffersink_get_time_base(is->out_audio_filter);
2079 if (!(af = frame_queue_peek_writable(&is->sampq)))
2082 af->pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb);
2083 af->pos = frame->pkt_pos;
2084 af->serial = is->auddec.pkt_serial;
2085 af->duration = av_q2d((AVRational){frame->nb_samples, frame->sample_rate});
2087 av_frame_move_ref(af->frame, frame);
2088 frame_queue_push(&is->sampq);
2091 if (is->audioq.serial != is->auddec.pkt_serial)
2094 if (ret == AVERROR_EOF)
2095 is->auddec.finished = is->auddec.pkt_serial;
2098 } while (ret >= 0 || ret == AVERROR(EAGAIN) || ret == AVERROR_EOF);
2101 avfilter_graph_free(&is->agraph);
2103 av_frame_free(&frame);
2107 static int decoder_start(Decoder *d, int (*fn)(void *), void *arg)
2109 packet_queue_start(d->queue);
2110 d->decoder_tid = SDL_CreateThread(fn, "decoder", arg);
2111 if (!d->decoder_tid) {
2112 av_log(NULL, AV_LOG_ERROR, "SDL_CreateThread(): %s\n", SDL_GetError());
2113 return AVERROR(ENOMEM);
2118 static int video_thread(void *arg)
2120 VideoState *is = arg;
2121 AVFrame *frame = av_frame_alloc();
2125 AVRational tb = is->video_st->time_base;
2126 AVRational frame_rate = av_guess_frame_rate(is->ic, is->video_st, NULL);
2129 AVFilterGraph *graph = avfilter_graph_alloc();
2130 AVFilterContext *filt_out = NULL, *filt_in = NULL;
2133 enum AVPixelFormat last_format = -2;
2134 int last_serial = -1;
2135 int last_vfilter_idx = 0;
2137 av_frame_free(&frame);
2138 return AVERROR(ENOMEM);
2145 avfilter_graph_free(&graph);
2147 return AVERROR(ENOMEM);
2151 ret = get_video_frame(is, frame);
2158 if ( last_w != frame->width
2159 || last_h != frame->height
2160 || last_format != frame->format
2161 || last_serial != is->viddec.pkt_serial
2162 || last_vfilter_idx != is->vfilter_idx) {
2163 av_log(NULL, AV_LOG_DEBUG,
2164 "Video frame changed from size:%dx%d format:%s serial:%d to size:%dx%d format:%s serial:%d\n",
2166 (const char *)av_x_if_null(av_get_pix_fmt_name(last_format), "none"), last_serial,
2167 frame->width, frame->height,
2168 (const char *)av_x_if_null(av_get_pix_fmt_name(frame->format), "none"), is->viddec.pkt_serial);
2169 avfilter_graph_free(&graph);
2170 graph = avfilter_graph_alloc();
2171 if ((ret = configure_video_filters(graph, is, vfilters_list ? vfilters_list[is->vfilter_idx] : NULL, frame)) < 0) {
2173 event.type = FF_QUIT_EVENT;
2174 event.user.data1 = is;
2175 SDL_PushEvent(&event);
2178 filt_in = is->in_video_filter;
2179 filt_out = is->out_video_filter;
2180 last_w = frame->width;
2181 last_h = frame->height;
2182 last_format = frame->format;
2183 last_serial = is->viddec.pkt_serial;
2184 last_vfilter_idx = is->vfilter_idx;
2185 frame_rate = av_buffersink_get_frame_rate(filt_out);
2188 ret = av_buffersrc_add_frame(filt_in, frame);
2193 is->frame_last_returned_time = av_gettime_relative() / 1000000.0;
2195 ret = av_buffersink_get_frame_flags(filt_out, frame, 0);
2197 if (ret == AVERROR_EOF)
2198 is->viddec.finished = is->viddec.pkt_serial;
2203 is->frame_last_filter_delay = av_gettime_relative() / 1000000.0 - is->frame_last_returned_time;
2204 if (fabs(is->frame_last_filter_delay) > AV_NOSYNC_THRESHOLD / 10.0)
2205 is->frame_last_filter_delay = 0;
2206 tb = av_buffersink_get_time_base(filt_out);
2208 duration = (frame_rate.num && frame_rate.den ? av_q2d((AVRational){frame_rate.den, frame_rate.num}) : 0);
2209 pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb);
2210 ret = queue_picture(is, frame, pts, duration, frame->pkt_pos, is->viddec.pkt_serial);
2211 av_frame_unref(frame);
2213 if (is->videoq.serial != is->viddec.pkt_serial)
2223 avfilter_graph_free(&graph);
2225 av_frame_free(&frame);
2229 static int subtitle_thread(void *arg)
2231 VideoState *is = arg;
2237 if (!(sp = frame_queue_peek_writable(&is->subpq)))
2240 if ((got_subtitle = decoder_decode_frame(&is->subdec, NULL, &sp->sub)) < 0)
2245 if (got_subtitle && sp->sub.format == 0) {
2246 if (sp->sub.pts != AV_NOPTS_VALUE)
2247 pts = sp->sub.pts / (double)AV_TIME_BASE;
2249 sp->serial = is->subdec.pkt_serial;
2250 sp->width = is->subdec.avctx->width;
2251 sp->height = is->subdec.avctx->height;
2254 /* now we can update the picture count */
2255 frame_queue_push(&is->subpq);
2256 } else if (got_subtitle) {
2257 avsubtitle_free(&sp->sub);
2263 /* copy samples for viewing in editor window */
2264 static void update_sample_display(VideoState *is, short *samples, int samples_size)
2268 size = samples_size / sizeof(short);
2270 len = SAMPLE_ARRAY_SIZE - is->sample_array_index;
2273 memcpy(is->sample_array + is->sample_array_index, samples, len * sizeof(short));
2275 is->sample_array_index += len;
2276 if (is->sample_array_index >= SAMPLE_ARRAY_SIZE)
2277 is->sample_array_index = 0;
2282 /* return the wanted number of samples to get better sync if sync_type is video
2283 * or external master clock */
2284 static int synchronize_audio(VideoState *is, int nb_samples)
2286 int wanted_nb_samples = nb_samples;
2288 /* if not master, then we try to remove or add samples to correct the clock */
2289 if (get_master_sync_type(is) != AV_SYNC_AUDIO_MASTER) {
2290 double diff, avg_diff;
2291 int min_nb_samples, max_nb_samples;
2293 diff = get_clock(&is->audclk) - get_master_clock(is);
2295 if (!isnan(diff) && fabs(diff) < AV_NOSYNC_THRESHOLD) {
2296 is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum;
2297 if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {
2298 /* not enough measures to have a correct estimate */
2299 is->audio_diff_avg_count++;
2301 /* estimate the A-V difference */
2302 avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef);
2304 if (fabs(avg_diff) >= is->audio_diff_threshold) {
2305 wanted_nb_samples = nb_samples + (int)(diff * is->audio_src.freq);
2306 min_nb_samples = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX) / 100));
2307 max_nb_samples = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX) / 100));
2308 wanted_nb_samples = av_clip(wanted_nb_samples, min_nb_samples, max_nb_samples);
2310 av_log(NULL, AV_LOG_TRACE, "diff=%f adiff=%f sample_diff=%d apts=%0.3f %f\n",
2311 diff, avg_diff, wanted_nb_samples - nb_samples,
2312 is->audio_clock, is->audio_diff_threshold);
2315 /* too big difference : may be initial PTS errors, so
2317 is->audio_diff_avg_count = 0;
2318 is->audio_diff_cum = 0;
2322 return wanted_nb_samples;
2326 * Decode one audio frame and return its uncompressed size.
2328 * The processed audio frame is decoded, converted if required, and
2329 * stored in is->audio_buf, with size in bytes given by the return
2332 static int audio_decode_frame(VideoState *is)
2334 int data_size, resampled_data_size;
2335 int64_t dec_channel_layout;
2336 av_unused double audio_clock0;
2337 int wanted_nb_samples;
2345 while (frame_queue_nb_remaining(&is->sampq) == 0) {
2346 if ((av_gettime_relative() - audio_callback_time) > 1000000LL * is->audio_hw_buf_size / is->audio_tgt.bytes_per_sec / 2)
2351 if (!(af = frame_queue_peek_readable(&is->sampq)))
2353 frame_queue_next(&is->sampq);
2354 } while (af->serial != is->audioq.serial);
2356 data_size = av_samples_get_buffer_size(NULL, af->frame->channels,
2357 af->frame->nb_samples,
2358 af->frame->format, 1);
2360 dec_channel_layout =
2361 (af->frame->channel_layout && af->frame->channels == av_get_channel_layout_nb_channels(af->frame->channel_layout)) ?
2362 af->frame->channel_layout : av_get_default_channel_layout(af->frame->channels);
2363 wanted_nb_samples = synchronize_audio(is, af->frame->nb_samples);
2365 if (af->frame->format != is->audio_src.fmt ||
2366 dec_channel_layout != is->audio_src.channel_layout ||
2367 af->frame->sample_rate != is->audio_src.freq ||
2368 (wanted_nb_samples != af->frame->nb_samples && !is->swr_ctx)) {
2369 swr_free(&is->swr_ctx);
2370 is->swr_ctx = swr_alloc_set_opts(NULL,
2371 is->audio_tgt.channel_layout, is->audio_tgt.fmt, is->audio_tgt.freq,
2372 dec_channel_layout, af->frame->format, af->frame->sample_rate,
2374 if (!is->swr_ctx || swr_init(is->swr_ctx) < 0) {
2375 av_log(NULL, AV_LOG_ERROR,
2376 "Cannot create sample rate converter for conversion of %d Hz %s %d channels to %d Hz %s %d channels!\n",
2377 af->frame->sample_rate, av_get_sample_fmt_name(af->frame->format), af->frame->channels,
2378 is->audio_tgt.freq, av_get_sample_fmt_name(is->audio_tgt.fmt), is->audio_tgt.channels);
2379 swr_free(&is->swr_ctx);
2382 is->audio_src.channel_layout = dec_channel_layout;
2383 is->audio_src.channels = af->frame->channels;
2384 is->audio_src.freq = af->frame->sample_rate;
2385 is->audio_src.fmt = af->frame->format;
2389 const uint8_t **in = (const uint8_t **)af->frame->extended_data;
2390 uint8_t **out = &is->audio_buf1;
2391 int out_count = (int64_t)wanted_nb_samples * is->audio_tgt.freq / af->frame->sample_rate + 256;
2392 int out_size = av_samples_get_buffer_size(NULL, is->audio_tgt.channels, out_count, is->audio_tgt.fmt, 0);
2395 av_log(NULL, AV_LOG_ERROR, "av_samples_get_buffer_size() failed\n");
2398 if (wanted_nb_samples != af->frame->nb_samples) {
2399 if (swr_set_compensation(is->swr_ctx, (wanted_nb_samples - af->frame->nb_samples) * is->audio_tgt.freq / af->frame->sample_rate,
2400 wanted_nb_samples * is->audio_tgt.freq / af->frame->sample_rate) < 0) {
2401 av_log(NULL, AV_LOG_ERROR, "swr_set_compensation() failed\n");
2405 av_fast_malloc(&is->audio_buf1, &is->audio_buf1_size, out_size);
2406 if (!is->audio_buf1)
2407 return AVERROR(ENOMEM);
2408 len2 = swr_convert(is->swr_ctx, out, out_count, in, af->frame->nb_samples);
2410 av_log(NULL, AV_LOG_ERROR, "swr_convert() failed\n");
2413 if (len2 == out_count) {
2414 av_log(NULL, AV_LOG_WARNING, "audio buffer is probably too small\n");
2415 if (swr_init(is->swr_ctx) < 0)
2416 swr_free(&is->swr_ctx);
2418 is->audio_buf = is->audio_buf1;
2419 resampled_data_size = len2 * is->audio_tgt.channels * av_get_bytes_per_sample(is->audio_tgt.fmt);
2421 is->audio_buf = af->frame->data[0];
2422 resampled_data_size = data_size;
2425 audio_clock0 = is->audio_clock;
2426 /* update the audio clock with the pts */
2427 if (!isnan(af->pts))
2428 is->audio_clock = af->pts + (double) af->frame->nb_samples / af->frame->sample_rate;
2430 is->audio_clock = NAN;
2431 is->audio_clock_serial = af->serial;
2434 static double last_clock;
2435 printf("audio: delay=%0.3f clock=%0.3f clock0=%0.3f\n",
2436 is->audio_clock - last_clock,
2437 is->audio_clock, audio_clock0);
2438 last_clock = is->audio_clock;
2441 return resampled_data_size;
2444 /* prepare a new audio buffer */
2445 static void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
2447 VideoState *is = opaque;
2448 int audio_size, len1;
2450 audio_callback_time = av_gettime_relative();
2453 if (is->audio_buf_index >= is->audio_buf_size) {
2454 audio_size = audio_decode_frame(is);
2455 if (audio_size < 0) {
2456 /* if error, just output silence */
2457 is->audio_buf = NULL;
2458 is->audio_buf_size = SDL_AUDIO_MIN_BUFFER_SIZE / is->audio_tgt.frame_size * is->audio_tgt.frame_size;
2460 if (is->show_mode != SHOW_MODE_VIDEO)
2461 update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
2462 is->audio_buf_size = audio_size;
2464 is->audio_buf_index = 0;
2466 len1 = is->audio_buf_size - is->audio_buf_index;
2469 if (!is->muted && is->audio_buf && is->audio_volume == SDL_MIX_MAXVOLUME)
2470 memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
2472 memset(stream, 0, len1);
2473 if (!is->muted && is->audio_buf)
2474 SDL_MixAudioFormat(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, AUDIO_S16SYS, len1, is->audio_volume);
2478 is->audio_buf_index += len1;
2480 is->audio_write_buf_size = is->audio_buf_size - is->audio_buf_index;
2481 /* Let's assume the audio driver that is used by SDL has two periods. */
2482 if (!isnan(is->audio_clock)) {
2483 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);
2484 sync_clock_to_slave(&is->extclk, &is->audclk);
2488 static int audio_open(void *opaque, int64_t wanted_channel_layout, int wanted_nb_channels, int wanted_sample_rate, struct AudioParams *audio_hw_params)
2490 SDL_AudioSpec wanted_spec, spec;
2492 static const int next_nb_channels[] = {0, 0, 1, 6, 2, 6, 4, 6};
2493 static const int next_sample_rates[] = {0, 44100, 48000, 96000, 192000};
2494 int next_sample_rate_idx = FF_ARRAY_ELEMS(next_sample_rates) - 1;
2496 env = SDL_getenv("SDL_AUDIO_CHANNELS");
2498 wanted_nb_channels = atoi(env);
2499 wanted_channel_layout = av_get_default_channel_layout(wanted_nb_channels);
2501 if (!wanted_channel_layout || wanted_nb_channels != av_get_channel_layout_nb_channels(wanted_channel_layout)) {
2502 wanted_channel_layout = av_get_default_channel_layout(wanted_nb_channels);
2503 wanted_channel_layout &= ~AV_CH_LAYOUT_STEREO_DOWNMIX;
2505 wanted_nb_channels = av_get_channel_layout_nb_channels(wanted_channel_layout);
2506 wanted_spec.channels = wanted_nb_channels;
2507 wanted_spec.freq = wanted_sample_rate;
2508 if (wanted_spec.freq <= 0 || wanted_spec.channels <= 0) {
2509 av_log(NULL, AV_LOG_ERROR, "Invalid sample rate or channel count!\n");
2512 while (next_sample_rate_idx && next_sample_rates[next_sample_rate_idx] >= wanted_spec.freq)
2513 next_sample_rate_idx--;
2514 wanted_spec.format = AUDIO_S16SYS;
2515 wanted_spec.silence = 0;
2516 wanted_spec.samples = FFMAX(SDL_AUDIO_MIN_BUFFER_SIZE, 2 << av_log2(wanted_spec.freq / SDL_AUDIO_MAX_CALLBACKS_PER_SEC));
2517 wanted_spec.callback = sdl_audio_callback;
2518 wanted_spec.userdata = opaque;
2519 while (!(audio_dev = SDL_OpenAudioDevice(NULL, 0, &wanted_spec, &spec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE | SDL_AUDIO_ALLOW_CHANNELS_CHANGE))) {
2520 av_log(NULL, AV_LOG_WARNING, "SDL_OpenAudio (%d channels, %d Hz): %s\n",
2521 wanted_spec.channels, wanted_spec.freq, SDL_GetError());
2522 wanted_spec.channels = next_nb_channels[FFMIN(7, wanted_spec.channels)];
2523 if (!wanted_spec.channels) {
2524 wanted_spec.freq = next_sample_rates[next_sample_rate_idx--];
2525 wanted_spec.channels = wanted_nb_channels;
2526 if (!wanted_spec.freq) {
2527 av_log(NULL, AV_LOG_ERROR,
2528 "No more combinations to try, audio open failed\n");
2532 wanted_channel_layout = av_get_default_channel_layout(wanted_spec.channels);
2534 if (spec.format != AUDIO_S16SYS) {
2535 av_log(NULL, AV_LOG_ERROR,
2536 "SDL advised audio format %d is not supported!\n", spec.format);
2539 if (spec.channels != wanted_spec.channels) {
2540 wanted_channel_layout = av_get_default_channel_layout(spec.channels);
2541 if (!wanted_channel_layout) {
2542 av_log(NULL, AV_LOG_ERROR,
2543 "SDL advised channel count %d is not supported!\n", spec.channels);
2548 audio_hw_params->fmt = AV_SAMPLE_FMT_S16;
2549 audio_hw_params->freq = spec.freq;
2550 audio_hw_params->channel_layout = wanted_channel_layout;
2551 audio_hw_params->channels = spec.channels;
2552 audio_hw_params->frame_size = av_samples_get_buffer_size(NULL, audio_hw_params->channels, 1, audio_hw_params->fmt, 1);
2553 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);
2554 if (audio_hw_params->bytes_per_sec <= 0 || audio_hw_params->frame_size <= 0) {
2555 av_log(NULL, AV_LOG_ERROR, "av_samples_get_buffer_size failed\n");
2561 /* open a given stream. Return 0 if OK */
2562 static int stream_component_open(VideoState *is, int stream_index)
2564 AVFormatContext *ic = is->ic;
2565 AVCodecContext *avctx;
2567 const char *forced_codec_name = NULL;
2568 AVDictionary *opts = NULL;
2569 AVDictionaryEntry *t = NULL;
2570 int sample_rate, nb_channels;
2571 int64_t channel_layout;
2573 int stream_lowres = lowres;
2575 if (stream_index < 0 || stream_index >= ic->nb_streams)
2578 avctx = avcodec_alloc_context3(NULL);
2580 return AVERROR(ENOMEM);
2582 ret = avcodec_parameters_to_context(avctx, ic->streams[stream_index]->codecpar);
2585 avctx->pkt_timebase = ic->streams[stream_index]->time_base;
2587 codec = avcodec_find_decoder(avctx->codec_id);
2589 switch(avctx->codec_type){
2590 case AVMEDIA_TYPE_AUDIO : is->last_audio_stream = stream_index; forced_codec_name = audio_codec_name; break;
2591 case AVMEDIA_TYPE_SUBTITLE: is->last_subtitle_stream = stream_index; forced_codec_name = subtitle_codec_name; break;
2592 case AVMEDIA_TYPE_VIDEO : is->last_video_stream = stream_index; forced_codec_name = video_codec_name; break;
2594 if (forced_codec_name)
2595 codec = avcodec_find_decoder_by_name(forced_codec_name);
2597 if (forced_codec_name) av_log(NULL, AV_LOG_WARNING,
2598 "No codec could be found with name '%s'\n", forced_codec_name);
2599 else av_log(NULL, AV_LOG_WARNING,
2600 "No decoder could be found for codec %s\n", avcodec_get_name(avctx->codec_id));
2601 ret = AVERROR(EINVAL);
2605 avctx->codec_id = codec->id;
2606 if (stream_lowres > codec->max_lowres) {
2607 av_log(avctx, AV_LOG_WARNING, "The maximum value for lowres supported by the decoder is %d\n",
2609 stream_lowres = codec->max_lowres;
2611 avctx->lowres = stream_lowres;
2614 avctx->flags2 |= AV_CODEC_FLAG2_FAST;
2616 opts = filter_codec_opts(codec_opts, avctx->codec_id, ic, ic->streams[stream_index], codec);
2617 if (!av_dict_get(opts, "threads", NULL, 0))
2618 av_dict_set(&opts, "threads", "auto", 0);
2620 av_dict_set_int(&opts, "lowres", stream_lowres, 0);
2621 if (avctx->codec_type == AVMEDIA_TYPE_VIDEO || avctx->codec_type == AVMEDIA_TYPE_AUDIO)
2622 av_dict_set(&opts, "refcounted_frames", "1", 0);
2623 if ((ret = avcodec_open2(avctx, codec, &opts)) < 0) {
2626 if ((t = av_dict_get(opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
2627 av_log(NULL, AV_LOG_ERROR, "Option %s not found.\n", t->key);
2628 ret = AVERROR_OPTION_NOT_FOUND;
2633 ic->streams[stream_index]->discard = AVDISCARD_DEFAULT;
2634 switch (avctx->codec_type) {
2635 case AVMEDIA_TYPE_AUDIO:
2638 AVFilterContext *sink;
2640 is->audio_filter_src.freq = avctx->sample_rate;
2641 is->audio_filter_src.channels = avctx->channels;
2642 is->audio_filter_src.channel_layout = get_valid_channel_layout(avctx->channel_layout, avctx->channels);
2643 is->audio_filter_src.fmt = avctx->sample_fmt;
2644 if ((ret = configure_audio_filters(is, afilters, 0)) < 0)
2646 sink = is->out_audio_filter;
2647 sample_rate = av_buffersink_get_sample_rate(sink);
2648 nb_channels = av_buffersink_get_channels(sink);
2649 channel_layout = av_buffersink_get_channel_layout(sink);
2652 sample_rate = avctx->sample_rate;
2653 nb_channels = avctx->channels;
2654 channel_layout = avctx->channel_layout;
2657 /* prepare audio output */
2658 if ((ret = audio_open(is, channel_layout, nb_channels, sample_rate, &is->audio_tgt)) < 0)
2660 is->audio_hw_buf_size = ret;
2661 is->audio_src = is->audio_tgt;
2662 is->audio_buf_size = 0;
2663 is->audio_buf_index = 0;
2665 /* init averaging filter */
2666 is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
2667 is->audio_diff_avg_count = 0;
2668 /* since we do not have a precise anough audio FIFO fullness,
2669 we correct audio sync only if larger than this threshold */
2670 is->audio_diff_threshold = (double)(is->audio_hw_buf_size) / is->audio_tgt.bytes_per_sec;
2672 is->audio_stream = stream_index;
2673 is->audio_st = ic->streams[stream_index];
2675 decoder_init(&is->auddec, avctx, &is->audioq, is->continue_read_thread);
2676 if ((is->ic->iformat->flags & (AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH | AVFMT_NO_BYTE_SEEK)) && !is->ic->iformat->read_seek) {
2677 is->auddec.start_pts = is->audio_st->start_time;
2678 is->auddec.start_pts_tb = is->audio_st->time_base;
2680 if ((ret = decoder_start(&is->auddec, audio_thread, is)) < 0)
2682 SDL_PauseAudioDevice(audio_dev, 0);
2684 case AVMEDIA_TYPE_VIDEO:
2685 is->video_stream = stream_index;
2686 is->video_st = ic->streams[stream_index];
2688 decoder_init(&is->viddec, avctx, &is->videoq, is->continue_read_thread);
2689 if ((ret = decoder_start(&is->viddec, video_thread, is)) < 0)
2691 is->queue_attachments_req = 1;
2693 case AVMEDIA_TYPE_SUBTITLE:
2694 is->subtitle_stream = stream_index;
2695 is->subtitle_st = ic->streams[stream_index];
2697 decoder_init(&is->subdec, avctx, &is->subtitleq, is->continue_read_thread);
2698 if ((ret = decoder_start(&is->subdec, subtitle_thread, is)) < 0)
2707 avcodec_free_context(&avctx);
2709 av_dict_free(&opts);
2714 static int decode_interrupt_cb(void *ctx)
2716 VideoState *is = ctx;
2717 return is->abort_request;
2720 static int stream_has_enough_packets(AVStream *st, int stream_id, PacketQueue *queue) {
2721 return stream_id < 0 ||
2722 queue->abort_request ||
2723 (st->disposition & AV_DISPOSITION_ATTACHED_PIC) ||
2724 queue->nb_packets > MIN_FRAMES && (!queue->duration || av_q2d(st->time_base) * queue->duration > 1.0);
2727 static int is_realtime(AVFormatContext *s)
2729 if( !strcmp(s->iformat->name, "rtp")
2730 || !strcmp(s->iformat->name, "rtsp")
2731 || !strcmp(s->iformat->name, "sdp")
2735 if(s->pb && ( !strncmp(s->url, "rtp:", 4)
2736 || !strncmp(s->url, "udp:", 4)
2743 /* this thread gets the stream from the disk or the network */
2744 static int read_thread(void *arg)
2746 VideoState *is = arg;
2747 AVFormatContext *ic = NULL;
2749 int st_index[AVMEDIA_TYPE_NB];
2750 AVPacket pkt1, *pkt = &pkt1;
2751 int64_t stream_start_time;
2752 int pkt_in_play_range = 0;
2753 AVDictionaryEntry *t;
2754 SDL_mutex *wait_mutex = SDL_CreateMutex();
2755 int scan_all_pmts_set = 0;
2759 av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError());
2760 ret = AVERROR(ENOMEM);
2764 memset(st_index, -1, sizeof(st_index));
2765 is->last_video_stream = is->video_stream = -1;
2766 is->last_audio_stream = is->audio_stream = -1;
2767 is->last_subtitle_stream = is->subtitle_stream = -1;
2770 ic = avformat_alloc_context();
2772 av_log(NULL, AV_LOG_FATAL, "Could not allocate context.\n");
2773 ret = AVERROR(ENOMEM);
2776 ic->interrupt_callback.callback = decode_interrupt_cb;
2777 ic->interrupt_callback.opaque = is;
2778 if (!av_dict_get(format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE)) {
2779 av_dict_set(&format_opts, "scan_all_pmts", "1", AV_DICT_DONT_OVERWRITE);
2780 scan_all_pmts_set = 1;
2782 err = avformat_open_input(&ic, is->filename, is->iformat, &format_opts);
2784 print_error(is->filename, err);
2788 if (scan_all_pmts_set)
2789 av_dict_set(&format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE);
2791 if ((t = av_dict_get(format_opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
2792 av_log(NULL, AV_LOG_ERROR, "Option %s not found.\n", t->key);
2793 ret = AVERROR_OPTION_NOT_FOUND;
2799 ic->flags |= AVFMT_FLAG_GENPTS;
2801 av_format_inject_global_side_data(ic);
2803 if (find_stream_info) {
2804 AVDictionary **opts = setup_find_stream_info_opts(ic, codec_opts);
2805 int orig_nb_streams = ic->nb_streams;
2807 err = avformat_find_stream_info(ic, opts);
2809 for (i = 0; i < orig_nb_streams; i++)
2810 av_dict_free(&opts[i]);
2814 av_log(NULL, AV_LOG_WARNING,
2815 "%s: could not find codec parameters\n", is->filename);
2822 ic->pb->eof_reached = 0; // FIXME hack, ffplay maybe should not use avio_feof() to test for the end
2824 if (seek_by_bytes < 0)
2825 seek_by_bytes = !!(ic->iformat->flags & AVFMT_TS_DISCONT) && strcmp("ogg", ic->iformat->name);
2827 is->max_frame_duration = (ic->iformat->flags & AVFMT_TS_DISCONT) ? 10.0 : 3600.0;
2829 if (!window_title && (t = av_dict_get(ic->metadata, "title", NULL, 0)))
2830 window_title = av_asprintf("%s - %s", t->value, input_filename);
2832 /* if seeking requested, we execute it */
2833 if (start_time != AV_NOPTS_VALUE) {
2836 timestamp = start_time;
2837 /* add the stream start time */
2838 if (ic->start_time != AV_NOPTS_VALUE)
2839 timestamp += ic->start_time;
2840 ret = avformat_seek_file(ic, -1, INT64_MIN, timestamp, INT64_MAX, 0);
2842 av_log(NULL, AV_LOG_WARNING, "%s: could not seek to position %0.3f\n",
2843 is->filename, (double)timestamp / AV_TIME_BASE);
2847 is->realtime = is_realtime(ic);
2850 av_dump_format(ic, 0, is->filename, 0);
2852 for (i = 0; i < ic->nb_streams; i++) {
2853 AVStream *st = ic->streams[i];
2854 enum AVMediaType type = st->codecpar->codec_type;
2855 st->discard = AVDISCARD_ALL;
2856 if (type >= 0 && wanted_stream_spec[type] && st_index[type] == -1)
2857 if (avformat_match_stream_specifier(ic, st, wanted_stream_spec[type]) > 0)
2860 for (i = 0; i < AVMEDIA_TYPE_NB; i++) {
2861 if (wanted_stream_spec[i] && st_index[i] == -1) {
2862 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));
2863 st_index[i] = INT_MAX;
2868 st_index[AVMEDIA_TYPE_VIDEO] =
2869 av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO,
2870 st_index[AVMEDIA_TYPE_VIDEO], -1, NULL, 0);
2872 st_index[AVMEDIA_TYPE_AUDIO] =
2873 av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO,
2874 st_index[AVMEDIA_TYPE_AUDIO],
2875 st_index[AVMEDIA_TYPE_VIDEO],
2877 if (!video_disable && !subtitle_disable)
2878 st_index[AVMEDIA_TYPE_SUBTITLE] =
2879 av_find_best_stream(ic, AVMEDIA_TYPE_SUBTITLE,
2880 st_index[AVMEDIA_TYPE_SUBTITLE],
2881 (st_index[AVMEDIA_TYPE_AUDIO] >= 0 ?
2882 st_index[AVMEDIA_TYPE_AUDIO] :
2883 st_index[AVMEDIA_TYPE_VIDEO]),
2886 is->show_mode = show_mode;
2887 if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) {
2888 AVStream *st = ic->streams[st_index[AVMEDIA_TYPE_VIDEO]];
2889 AVCodecParameters *codecpar = st->codecpar;
2890 AVRational sar = av_guess_sample_aspect_ratio(ic, st, NULL);
2891 if (codecpar->width)
2892 set_default_window_size(codecpar->width, codecpar->height, sar);
2895 /* open the streams */
2896 if (st_index[AVMEDIA_TYPE_AUDIO] >= 0) {
2897 stream_component_open(is, st_index[AVMEDIA_TYPE_AUDIO]);
2901 if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) {
2902 ret = stream_component_open(is, st_index[AVMEDIA_TYPE_VIDEO]);
2904 if (is->show_mode == SHOW_MODE_NONE)
2905 is->show_mode = ret >= 0 ? SHOW_MODE_VIDEO : SHOW_MODE_RDFT;
2907 if (st_index[AVMEDIA_TYPE_SUBTITLE] >= 0) {
2908 stream_component_open(is, st_index[AVMEDIA_TYPE_SUBTITLE]);
2911 if (is->video_stream < 0 && is->audio_stream < 0) {
2912 av_log(NULL, AV_LOG_FATAL, "Failed to open file '%s' or configure filtergraph\n",
2918 if (infinite_buffer < 0 && is->realtime)
2919 infinite_buffer = 1;
2922 if (is->abort_request)
2924 if (is->paused != is->last_paused) {
2925 is->last_paused = is->paused;
2927 is->read_pause_return = av_read_pause(ic);
2931 #if CONFIG_RTSP_DEMUXER || CONFIG_MMSH_PROTOCOL
2933 (!strcmp(ic->iformat->name, "rtsp") ||
2934 (ic->pb && !strncmp(input_filename, "mmsh:", 5)))) {
2935 /* wait 10 ms to avoid trying to get another packet */
2942 int64_t seek_target = is->seek_pos;
2943 int64_t seek_min = is->seek_rel > 0 ? seek_target - is->seek_rel + 2: INT64_MIN;
2944 int64_t seek_max = is->seek_rel < 0 ? seek_target - is->seek_rel - 2: INT64_MAX;
2945 // FIXME the +-2 is due to rounding being not done in the correct direction in generation
2946 // of the seek_pos/seek_rel variables
2948 ret = avformat_seek_file(is->ic, -1, seek_min, seek_target, seek_max, is->seek_flags);
2950 av_log(NULL, AV_LOG_ERROR,
2951 "%s: error while seeking\n", is->ic->url);
2953 if (is->audio_stream >= 0) {
2954 packet_queue_flush(&is->audioq);
2955 packet_queue_put(&is->audioq, &flush_pkt);
2957 if (is->subtitle_stream >= 0) {
2958 packet_queue_flush(&is->subtitleq);
2959 packet_queue_put(&is->subtitleq, &flush_pkt);
2961 if (is->video_stream >= 0) {
2962 packet_queue_flush(&is->videoq);
2963 packet_queue_put(&is->videoq, &flush_pkt);
2965 if (is->seek_flags & AVSEEK_FLAG_BYTE) {
2966 set_clock(&is->extclk, NAN, 0);
2968 set_clock(&is->extclk, seek_target / (double)AV_TIME_BASE, 0);
2972 is->queue_attachments_req = 1;
2975 step_to_next_frame(is);
2977 if (is->queue_attachments_req) {
2978 if (is->video_st && is->video_st->disposition & AV_DISPOSITION_ATTACHED_PIC) {
2979 AVPacket copy = { 0 };
2980 if ((ret = av_packet_ref(©, &is->video_st->attached_pic)) < 0)
2982 packet_queue_put(&is->videoq, ©);
2983 packet_queue_put_nullpacket(&is->videoq, is->video_stream);
2985 is->queue_attachments_req = 0;
2988 /* if the queue are full, no need to read more */
2989 if (infinite_buffer<1 &&
2990 (is->audioq.size + is->videoq.size + is->subtitleq.size > MAX_QUEUE_SIZE
2991 || (stream_has_enough_packets(is->audio_st, is->audio_stream, &is->audioq) &&
2992 stream_has_enough_packets(is->video_st, is->video_stream, &is->videoq) &&
2993 stream_has_enough_packets(is->subtitle_st, is->subtitle_stream, &is->subtitleq)))) {
2995 SDL_LockMutex(wait_mutex);
2996 SDL_CondWaitTimeout(is->continue_read_thread, wait_mutex, 10);
2997 SDL_UnlockMutex(wait_mutex);
3001 (!is->audio_st || (is->auddec.finished == is->audioq.serial && frame_queue_nb_remaining(&is->sampq) == 0)) &&
3002 (!is->video_st || (is->viddec.finished == is->videoq.serial && frame_queue_nb_remaining(&is->pictq) == 0))) {
3003 if (loop != 1 && (!loop || --loop)) {
3004 stream_seek(is, start_time != AV_NOPTS_VALUE ? start_time : 0, 0, 0);
3005 } else if (autoexit) {
3010 ret = av_read_frame(ic, pkt);
3012 if ((ret == AVERROR_EOF || avio_feof(ic->pb)) && !is->eof) {
3013 if (is->video_stream >= 0)
3014 packet_queue_put_nullpacket(&is->videoq, is->video_stream);
3015 if (is->audio_stream >= 0)
3016 packet_queue_put_nullpacket(&is->audioq, is->audio_stream);
3017 if (is->subtitle_stream >= 0)
3018 packet_queue_put_nullpacket(&is->subtitleq, is->subtitle_stream);
3021 if (ic->pb && ic->pb->error)
3023 SDL_LockMutex(wait_mutex);
3024 SDL_CondWaitTimeout(is->continue_read_thread, wait_mutex, 10);
3025 SDL_UnlockMutex(wait_mutex);
3030 /* check if packet is in play range specified by user, then queue, otherwise discard */
3031 stream_start_time = ic->streams[pkt->stream_index]->start_time;
3032 pkt_ts = pkt->pts == AV_NOPTS_VALUE ? pkt->dts : pkt->pts;
3033 pkt_in_play_range = duration == AV_NOPTS_VALUE ||
3034 (pkt_ts - (stream_start_time != AV_NOPTS_VALUE ? stream_start_time : 0)) *
3035 av_q2d(ic->streams[pkt->stream_index]->time_base) -
3036 (double)(start_time != AV_NOPTS_VALUE ? start_time : 0) / 1000000
3037 <= ((double)duration / 1000000);
3038 if (pkt->stream_index == is->audio_stream && pkt_in_play_range) {
3039 packet_queue_put(&is->audioq, pkt);
3040 } else if (pkt->stream_index == is->video_stream && pkt_in_play_range
3041 && !(is->video_st->disposition & AV_DISPOSITION_ATTACHED_PIC)) {
3042 packet_queue_put(&is->videoq, pkt);
3043 } else if (pkt->stream_index == is->subtitle_stream && pkt_in_play_range) {
3044 packet_queue_put(&is->subtitleq, pkt);
3046 av_packet_unref(pkt);
3053 avformat_close_input(&ic);
3058 event.type = FF_QUIT_EVENT;
3059 event.user.data1 = is;
3060 SDL_PushEvent(&event);
3062 SDL_DestroyMutex(wait_mutex);
3066 static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
3070 is = av_mallocz(sizeof(VideoState));
3073 is->filename = av_strdup(filename);
3076 is->iformat = iformat;
3080 /* start video display */
3081 if (frame_queue_init(&is->pictq, &is->videoq, VIDEO_PICTURE_QUEUE_SIZE, 1) < 0)
3083 if (frame_queue_init(&is->subpq, &is->subtitleq, SUBPICTURE_QUEUE_SIZE, 0) < 0)
3085 if (frame_queue_init(&is->sampq, &is->audioq, SAMPLE_QUEUE_SIZE, 1) < 0)
3088 if (packet_queue_init(&is->videoq) < 0 ||
3089 packet_queue_init(&is->audioq) < 0 ||
3090 packet_queue_init(&is->subtitleq) < 0)
3093 if (!(is->continue_read_thread = SDL_CreateCond())) {
3094 av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError());
3098 init_clock(&is->vidclk, &is->videoq.serial);
3099 init_clock(&is->audclk, &is->audioq.serial);
3100 init_clock(&is->extclk, &is->extclk.serial);
3101 is->audio_clock_serial = -1;
3102 if (startup_volume < 0)
3103 av_log(NULL, AV_LOG_WARNING, "-volume=%d < 0, setting to 0\n", startup_volume);
3104 if (startup_volume > 100)
3105 av_log(NULL, AV_LOG_WARNING, "-volume=%d > 100, setting to 100\n", startup_volume);
3106 startup_volume = av_clip(startup_volume, 0, 100);
3107 startup_volume = av_clip(SDL_MIX_MAXVOLUME * startup_volume / 100, 0, SDL_MIX_MAXVOLUME);
3108 is->audio_volume = startup_volume;
3110 is->av_sync_type = av_sync_type;
3111 is->read_tid = SDL_CreateThread(read_thread, "read_thread", is);
3112 if (!is->read_tid) {
3113 av_log(NULL, AV_LOG_FATAL, "SDL_CreateThread(): %s\n", SDL_GetError());
3121 static void stream_cycle_channel(VideoState *is, int codec_type)
3123 AVFormatContext *ic = is->ic;
3124 int start_index, stream_index;
3127 AVProgram *p = NULL;
3128 int nb_streams = is->ic->nb_streams;
3130 if (codec_type == AVMEDIA_TYPE_VIDEO) {
3131 start_index = is->last_video_stream;
3132 old_index = is->video_stream;
3133 } else if (codec_type == AVMEDIA_TYPE_AUDIO) {
3134 start_index = is->last_audio_stream;
3135 old_index = is->audio_stream;
3137 start_index = is->last_subtitle_stream;
3138 old_index = is->subtitle_stream;
3140 stream_index = start_index;
3142 if (codec_type != AVMEDIA_TYPE_VIDEO && is->video_stream != -1) {
3143 p = av_find_program_from_stream(ic, NULL, is->video_stream);
3145 nb_streams = p->nb_stream_indexes;
3146 for (start_index = 0; start_index < nb_streams; start_index++)
3147 if (p->stream_index[start_index] == stream_index)
3149 if (start_index == nb_streams)
3151 stream_index = start_index;
3156 if (++stream_index >= nb_streams)
3158 if (codec_type == AVMEDIA_TYPE_SUBTITLE)
3161 is->last_subtitle_stream = -1;
3164 if (start_index == -1)
3168 if (stream_index == start_index)
3170 st = is->ic->streams[p ? p->stream_index[stream_index] : stream_index];
3171 if (st->codecpar->codec_type == codec_type) {
3172 /* check that parameters are OK */
3173 switch (codec_type) {
3174 case AVMEDIA_TYPE_AUDIO:
3175 if (st->codecpar->sample_rate != 0 &&
3176 st->codecpar->channels != 0)
3179 case AVMEDIA_TYPE_VIDEO:
3180 case AVMEDIA_TYPE_SUBTITLE:
3188 if (p && stream_index != -1)
3189 stream_index = p->stream_index[stream_index];
3190 av_log(NULL, AV_LOG_INFO, "Switch %s stream from #%d to #%d\n",
3191 av_get_media_type_string(codec_type),
3195 stream_component_close(is, old_index);
3196 stream_component_open(is, stream_index);
3200 static void toggle_full_screen(VideoState *is)
3202 is_full_screen = !is_full_screen;
3203 SDL_SetWindowFullscreen(window, is_full_screen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
3206 static void toggle_audio_display(VideoState *is)
3208 int next = is->show_mode;
3210 next = (next + 1) % SHOW_MODE_NB;
3211 } while (next != is->show_mode && (next == SHOW_MODE_VIDEO && !is->video_st || next != SHOW_MODE_VIDEO && !is->audio_st));
3212 if (is->show_mode != next) {
3213 is->force_refresh = 1;
3214 is->show_mode = next;
3218 static void refresh_loop_wait_event(VideoState *is, SDL_Event *event) {
3219 double remaining_time = 0.0;
3221 while (!SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)) {
3222 if (!cursor_hidden && av_gettime_relative() - cursor_last_shown > CURSOR_HIDE_DELAY) {
3226 if (remaining_time > 0.0)
3227 av_usleep((int64_t)(remaining_time * 1000000.0));
3228 remaining_time = REFRESH_RATE;
3229 if (is->show_mode != SHOW_MODE_NONE && (!is->paused || is->force_refresh))
3230 video_refresh(is, &remaining_time);
3235 static void seek_chapter(VideoState *is, int incr)
3237 int64_t pos = get_master_clock(is) * AV_TIME_BASE;
3240 if (!is->ic->nb_chapters)
3243 /* find the current chapter */
3244 for (i = 0; i < is->ic->nb_chapters; i++) {
3245 AVChapter *ch = is->ic->chapters[i];
3246 if (av_compare_ts(pos, AV_TIME_BASE_Q, ch->start, ch->time_base) < 0) {
3254 if (i >= is->ic->nb_chapters)
3257 av_log(NULL, AV_LOG_VERBOSE, "Seeking to chapter %d.\n", i);
3258 stream_seek(is, av_rescale_q(is->ic->chapters[i]->start, is->ic->chapters[i]->time_base,
3259 AV_TIME_BASE_Q), 0, 0);
3262 /* handle an event sent by the GUI */
3263 static void event_loop(VideoState *cur_stream)
3266 double incr, pos, frac;
3270 refresh_loop_wait_event(cur_stream, &event);
3271 switch (event.type) {
3273 if (exit_on_keydown || event.key.keysym.sym == SDLK_ESCAPE || event.key.keysym.sym == SDLK_q) {
3274 do_exit(cur_stream);
3277 // If we don't yet have a window, skip all key events, because read_thread might still be initializing...
3278 if (!cur_stream->width)
3280 switch (event.key.keysym.sym) {
3282 toggle_full_screen(cur_stream);
3283 cur_stream->force_refresh = 1;
3287 toggle_pause(cur_stream);
3290 toggle_mute(cur_stream);
3292 case SDLK_KP_MULTIPLY:
3294 update_volume(cur_stream, 1, SDL_VOLUME_STEP);
3296 case SDLK_KP_DIVIDE:
3298 update_volume(cur_stream, -1, SDL_VOLUME_STEP);
3300 case SDLK_s: // S: Step to next frame
3301 step_to_next_frame(cur_stream);
3304 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_AUDIO);
3307 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_VIDEO);
3310 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_VIDEO);
3311 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_AUDIO);
3312 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_SUBTITLE);
3315 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_SUBTITLE);
3319 if (cur_stream->show_mode == SHOW_MODE_VIDEO && cur_stream->vfilter_idx < nb_vfilters - 1) {
3320 if (++cur_stream->vfilter_idx >= nb_vfilters)
3321 cur_stream->vfilter_idx = 0;
3323 cur_stream->vfilter_idx = 0;
3324 toggle_audio_display(cur_stream);
3327 toggle_audio_display(cur_stream);
3331 if (cur_stream->ic->nb_chapters <= 1) {
3335 seek_chapter(cur_stream, 1);
3338 if (cur_stream->ic->nb_chapters <= 1) {
3342 seek_chapter(cur_stream, -1);
3345 incr = seek_interval ? -seek_interval : -10.0;
3348 incr = seek_interval ? seek_interval : 10.0;
3356 if (seek_by_bytes) {
3358 if (pos < 0 && cur_stream->video_stream >= 0)
3359 pos = frame_queue_last_pos(&cur_stream->pictq);
3360 if (pos < 0 && cur_stream->audio_stream >= 0)
3361 pos = frame_queue_last_pos(&cur_stream->sampq);
3363 pos = avio_tell(cur_stream->ic->pb);
3364 if (cur_stream->ic->bit_rate)
3365 incr *= cur_stream->ic->bit_rate / 8.0;
3369 stream_seek(cur_stream, pos, incr, 1);
3371 pos = get_master_clock(cur_stream);
3373 pos = (double)cur_stream->seek_pos / AV_TIME_BASE;
3375 if (cur_stream->ic->start_time != AV_NOPTS_VALUE && pos < cur_stream->ic->start_time / (double)AV_TIME_BASE)
3376 pos = cur_stream->ic->start_time / (double)AV_TIME_BASE;
3377 stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), (int64_t)(incr * AV_TIME_BASE), 0);
3384 case SDL_MOUSEBUTTONDOWN:
3385 if (exit_on_mousedown) {
3386 do_exit(cur_stream);
3389 if (event.button.button == SDL_BUTTON_LEFT) {
3390 static int64_t last_mouse_left_click = 0;
3391 if (av_gettime_relative() - last_mouse_left_click <= 500000) {
3392 toggle_full_screen(cur_stream);
3393 cur_stream->force_refresh = 1;
3394 last_mouse_left_click = 0;
3396 last_mouse_left_click = av_gettime_relative();
3399 case SDL_MOUSEMOTION:
3400 if (cursor_hidden) {
3404 cursor_last_shown = av_gettime_relative();
3405 if (event.type == SDL_MOUSEBUTTONDOWN) {
3406 if (event.button.button != SDL_BUTTON_RIGHT)
3410 if (!(event.motion.state & SDL_BUTTON_RMASK))
3414 if (seek_by_bytes || cur_stream->ic->duration <= 0) {
3415 uint64_t size = avio_size(cur_stream->ic->pb);
3416 stream_seek(cur_stream, size*x/cur_stream->width, 0, 1);
3420 int tns, thh, tmm, tss;
3421 tns = cur_stream->ic->duration / 1000000LL;
3423 tmm = (tns % 3600) / 60;
3425 frac = x / cur_stream->width;
3428 mm = (ns % 3600) / 60;
3430 av_log(NULL, AV_LOG_INFO,
3431 "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
3432 hh, mm, ss, thh, tmm, tss);
3433 ts = frac * cur_stream->ic->duration;
3434 if (cur_stream->ic->start_time != AV_NOPTS_VALUE)
3435 ts += cur_stream->ic->start_time;
3436 stream_seek(cur_stream, ts, 0, 0);
3439 case SDL_WINDOWEVENT:
3440 switch (event.window.event) {
3441 case SDL_WINDOWEVENT_RESIZED:
3442 screen_width = cur_stream->width = event.window.data1;
3443 screen_height = cur_stream->height = event.window.data2;
3444 if (cur_stream->vis_texture) {
3445 SDL_DestroyTexture(cur_stream->vis_texture);
3446 cur_stream->vis_texture = NULL;
3448 case SDL_WINDOWEVENT_EXPOSED:
3449 cur_stream->force_refresh = 1;
3454 do_exit(cur_stream);
3462 static int opt_frame_size(void *optctx, const char *opt, const char *arg)
3464 av_log(NULL, AV_LOG_WARNING, "Option -s is deprecated, use -video_size.\n");
3465 return opt_default(NULL, "video_size", arg);
3468 static int opt_width(void *optctx, const char *opt, const char *arg)
3470 screen_width = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
3474 static int opt_height(void *optctx, const char *opt, const char *arg)
3476 screen_height = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
3480 static int opt_format(void *optctx, const char *opt, const char *arg)
3482 file_iformat = av_find_input_format(arg);
3483 if (!file_iformat) {
3484 av_log(NULL, AV_LOG_FATAL, "Unknown input format: %s\n", arg);
3485 return AVERROR(EINVAL);
3490 static int opt_frame_pix_fmt(void *optctx, const char *opt, const char *arg)
3492 av_log(NULL, AV_LOG_WARNING, "Option -pix_fmt is deprecated, use -pixel_format.\n");
3493 return opt_default(NULL, "pixel_format", arg);
3496 static int opt_sync(void *optctx, const char *opt, const char *arg)
3498 if (!strcmp(arg, "audio"))
3499 av_sync_type = AV_SYNC_AUDIO_MASTER;
3500 else if (!strcmp(arg, "video"))
3501 av_sync_type = AV_SYNC_VIDEO_MASTER;
3502 else if (!strcmp(arg, "ext"))
3503 av_sync_type = AV_SYNC_EXTERNAL_CLOCK;
3505 av_log(NULL, AV_LOG_ERROR, "Unknown value for %s: %s\n", opt, arg);
3511 static int opt_seek(void *optctx, const char *opt, const char *arg)
3513 start_time = parse_time_or_die(opt, arg, 1);
3517 static int opt_duration(void *optctx, const char *opt, const char *arg)
3519 duration = parse_time_or_die(opt, arg, 1);
3523 static int opt_show_mode(void *optctx, const char *opt, const char *arg)
3525 show_mode = !strcmp(arg, "video") ? SHOW_MODE_VIDEO :
3526 !strcmp(arg, "waves") ? SHOW_MODE_WAVES :
3527 !strcmp(arg, "rdft" ) ? SHOW_MODE_RDFT :
3528 parse_number_or_die(opt, arg, OPT_INT, 0, SHOW_MODE_NB-1);
3532 static void opt_input_file(void *optctx, const char *filename)
3534 if (input_filename) {
3535 av_log(NULL, AV_LOG_FATAL,
3536 "Argument '%s' provided as input filename, but '%s' was already specified.\n",
3537 filename, input_filename);
3540 if (!strcmp(filename, "-"))
3542 input_filename = filename;
3545 static int opt_codec(void *optctx, const char *opt, const char *arg)
3547 const char *spec = strchr(opt, ':');
3549 av_log(NULL, AV_LOG_ERROR,
3550 "No media specifier was specified in '%s' in option '%s'\n",
3552 return AVERROR(EINVAL);
3556 case 'a' : audio_codec_name = arg; break;
3557 case 's' : subtitle_codec_name = arg; break;
3558 case 'v' : video_codec_name = arg; break;
3560 av_log(NULL, AV_LOG_ERROR,
3561 "Invalid media specifier '%s' in option '%s'\n", spec, opt);
3562 return AVERROR(EINVAL);
3569 static const OptionDef options[] = {
3570 CMDUTILS_COMMON_OPTIONS
3571 { "x", HAS_ARG, { .func_arg = opt_width }, "force displayed width", "width" },
3572 { "y", HAS_ARG, { .func_arg = opt_height }, "force displayed height", "height" },
3573 { "s", HAS_ARG | OPT_VIDEO, { .func_arg = opt_frame_size }, "set frame size (WxH or abbreviation)", "size" },
3574 { "fs", OPT_BOOL, { &is_full_screen }, "force full screen" },
3575 { "an", OPT_BOOL, { &audio_disable }, "disable audio" },
3576 { "vn", OPT_BOOL, { &video_disable }, "disable video" },
3577 { "sn", OPT_BOOL, { &subtitle_disable }, "disable subtitling" },
3578 { "ast", OPT_STRING | HAS_ARG | OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_AUDIO] }, "select desired audio stream", "stream_specifier" },
3579 { "vst", OPT_STRING | HAS_ARG | OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_VIDEO] }, "select desired video stream", "stream_specifier" },
3580 { "sst", OPT_STRING | HAS_ARG | OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_SUBTITLE] }, "select desired subtitle stream", "stream_specifier" },
3581 { "ss", HAS_ARG, { .func_arg = opt_seek }, "seek to a given position in seconds", "pos" },
3582 { "t", HAS_ARG, { .func_arg = opt_duration }, "play \"duration\" seconds of audio/video", "duration" },
3583 { "bytes", OPT_INT | HAS_ARG, { &seek_by_bytes }, "seek by bytes 0=off 1=on -1=auto", "val" },
3584 { "seek_interval", OPT_FLOAT | HAS_ARG, { &seek_interval }, "set seek interval for left/right keys, in seconds", "seconds" },
3585 { "nodisp", OPT_BOOL, { &display_disable }, "disable graphical display" },
3586 { "noborder", OPT_BOOL, { &borderless }, "borderless window" },
3587 { "volume", OPT_INT | HAS_ARG, { &startup_volume}, "set startup volume 0=min 100=max", "volume" },
3588 { "f", HAS_ARG, { .func_arg = opt_format }, "force format", "fmt" },
3589 { "pix_fmt", HAS_ARG | OPT_EXPERT | OPT_VIDEO, { .func_arg = opt_frame_pix_fmt }, "set pixel format", "format" },
3590 { "stats", OPT_BOOL | OPT_EXPERT, { &show_status }, "show status", "" },
3591 { "fast", OPT_BOOL | OPT_EXPERT, { &fast }, "non spec compliant optimizations", "" },
3592 { "genpts", OPT_BOOL | OPT_EXPERT, { &genpts }, "generate pts", "" },
3593 { "drp", OPT_INT | HAS_ARG | OPT_EXPERT, { &decoder_reorder_pts }, "let decoder reorder pts 0=off 1=on -1=auto", ""},
3594 { "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, { &lowres }, "", "" },
3595 { "sync", HAS_ARG | OPT_EXPERT, { .func_arg = opt_sync }, "set audio-video sync. type (type=audio/video/ext)", "type" },
3596 { "autoexit", OPT_BOOL | OPT_EXPERT, { &autoexit }, "exit at the end", "" },
3597 { "exitonkeydown", OPT_BOOL | OPT_EXPERT, { &exit_on_keydown }, "exit on key down", "" },
3598 { "exitonmousedown", OPT_BOOL | OPT_EXPERT, { &exit_on_mousedown }, "exit on mouse down", "" },
3599 { "loop", OPT_INT | HAS_ARG | OPT_EXPERT, { &loop }, "set number of times the playback shall be looped", "loop count" },
3600 { "framedrop", OPT_BOOL | OPT_EXPERT, { &framedrop }, "drop frames when cpu is too slow", "" },
3601 { "infbuf", OPT_BOOL | OPT_EXPERT, { &infinite_buffer }, "don't limit the input buffer size (useful with realtime streams)", "" },
3602 { "window_title", OPT_STRING | HAS_ARG, { &window_title }, "set window title", "window title" },
3603 { "left", OPT_INT | HAS_ARG | OPT_EXPERT, { &screen_left }, "set the x position for the left of the window", "x pos" },
3604 { "top", OPT_INT | HAS_ARG | OPT_EXPERT, { &screen_top }, "set the y position for the top of the window", "y pos" },
3606 { "vf", OPT_EXPERT | HAS_ARG, { .func_arg = opt_add_vfilter }, "set video filters", "filter_graph" },
3607 { "af", OPT_STRING | HAS_ARG, { &afilters }, "set audio filters", "filter_graph" },
3609 { "rdftspeed", OPT_INT | HAS_ARG| OPT_AUDIO | OPT_EXPERT, { &rdftspeed }, "rdft speed", "msecs" },
3610 { "showmode", HAS_ARG, { .func_arg = opt_show_mode}, "select show mode (0 = video, 1 = waves, 2 = RDFT)", "mode" },
3611 { "default", HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, { .func_arg = opt_default }, "generic catch all option", "" },
3612 { "i", OPT_BOOL, { &dummy}, "read specified file", "input_file"},
3613 { "codec", HAS_ARG, { .func_arg = opt_codec}, "force decoder", "decoder_name" },
3614 { "acodec", HAS_ARG | OPT_STRING | OPT_EXPERT, { &audio_codec_name }, "force audio decoder", "decoder_name" },
3615 { "scodec", HAS_ARG | OPT_STRING | OPT_EXPERT, { &subtitle_codec_name }, "force subtitle decoder", "decoder_name" },
3616 { "vcodec", HAS_ARG | OPT_STRING | OPT_EXPERT, { &video_codec_name }, "force video decoder", "decoder_name" },
3617 { "autorotate", OPT_BOOL, { &autorotate }, "automatically rotate video", "" },
3618 { "find_stream_info", OPT_BOOL | OPT_INPUT | OPT_EXPERT, { &find_stream_info },
3619 "read and decode the streams to fill missing information with heuristics" },
3623 static void show_usage(void)
3625 av_log(NULL, AV_LOG_INFO, "Simple media player\n");
3626 av_log(NULL, AV_LOG_INFO, "usage: %s [options] input_file\n", program_name);
3627 av_log(NULL, AV_LOG_INFO, "\n");
3630 void show_help_default(const char *opt, const char *arg)
3632 av_log_set_callback(log_callback_help);
3634 show_help_options(options, "Main options:", 0, OPT_EXPERT, 0);
3635 show_help_options(options, "Advanced options:", OPT_EXPERT, 0, 0);
3637 show_help_children(avcodec_get_class(), AV_OPT_FLAG_DECODING_PARAM);
3638 show_help_children(avformat_get_class(), AV_OPT_FLAG_DECODING_PARAM);
3639 #if !CONFIG_AVFILTER
3640 show_help_children(sws_get_class(), AV_OPT_FLAG_ENCODING_PARAM);
3642 show_help_children(avfilter_get_class(), AV_OPT_FLAG_FILTERING_PARAM);
3644 printf("\nWhile playing:\n"
3646 "f toggle full screen\n"
3649 "9, 0 decrease and increase volume respectively\n"
3650 "/, * decrease and increase volume respectively\n"
3651 "a cycle audio channel in the current program\n"
3652 "v cycle video channel\n"
3653 "t cycle subtitle channel in the current program\n"
3655 "w cycle video filters or show modes\n"
3656 "s activate frame-step mode\n"
3657 "left/right seek backward/forward 10 seconds or to custom interval if -seek_interval is set\n"
3658 "down/up seek backward/forward 1 minute\n"
3659 "page down/page up seek backward/forward 10 minutes\n"
3660 "right mouse click seek to percentage in file corresponding to fraction of width\n"
3661 "left double-click toggle full screen\n"
3665 /* Called from the main */
3666 int main(int argc, char **argv)
3673 av_log_set_flags(AV_LOG_SKIP_REPEATED);
3674 parse_loglevel(argc, argv, options);
3676 /* register all codecs, demux and protocols */
3678 avdevice_register_all();
3680 avformat_network_init();
3684 signal(SIGINT , sigterm_handler); /* Interrupt (ANSI). */
3685 signal(SIGTERM, sigterm_handler); /* Termination (ANSI). */
3687 show_banner(argc, argv, options);
3689 parse_options(NULL, argc, argv, options, opt_input_file);
3691 if (!input_filename) {
3693 av_log(NULL, AV_LOG_FATAL, "An input file must be specified\n");
3694 av_log(NULL, AV_LOG_FATAL,
3695 "Use -h to get full help or, even better, run 'man %s'\n", program_name);
3699 if (display_disable) {
3702 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
3704 flags &= ~SDL_INIT_AUDIO;
3706 /* Try to work around an occasional ALSA buffer underflow issue when the
3707 * period size is NPOT due to ALSA resampling by forcing the buffer size. */
3708 if (!SDL_getenv("SDL_AUDIO_ALSA_SET_BUFFER_SIZE"))
3709 SDL_setenv("SDL_AUDIO_ALSA_SET_BUFFER_SIZE","1", 1);
3711 if (display_disable)
3712 flags &= ~SDL_INIT_VIDEO;
3713 if (SDL_Init (flags)) {
3714 av_log(NULL, AV_LOG_FATAL, "Could not initialize SDL - %s\n", SDL_GetError());
3715 av_log(NULL, AV_LOG_FATAL, "(Did you set the DISPLAY variable?)\n");
3719 SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
3720 SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
3722 av_init_packet(&flush_pkt);
3723 flush_pkt.data = (uint8_t *)&flush_pkt;
3725 if (!display_disable) {
3726 int flags = SDL_WINDOW_HIDDEN;
3728 flags |= SDL_WINDOW_BORDERLESS;
3730 flags |= SDL_WINDOW_RESIZABLE;
3731 window = SDL_CreateWindow(program_name, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, default_width, default_height, flags);
3732 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
3734 renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
3736 av_log(NULL, AV_LOG_WARNING, "Failed to initialize a hardware accelerated renderer: %s\n", SDL_GetError());
3737 renderer = SDL_CreateRenderer(window, -1, 0);
3740 if (!SDL_GetRendererInfo(renderer, &renderer_info))
3741 av_log(NULL, AV_LOG_VERBOSE, "Initialized %s renderer.\n", renderer_info.name);
3744 if (!window || !renderer || !renderer_info.num_texture_formats) {
3745 av_log(NULL, AV_LOG_FATAL, "Failed to create window or renderer: %s", SDL_GetError());
3750 is = stream_open(input_filename, file_iformat);
3752 av_log(NULL, AV_LOG_FATAL, "Failed to initialize VideoState!\n");