FFmpeg
Loading...
Searching...
No Matches
ffplay.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2003 Fabrice Bellard
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21/**
22 * @file
23 * simple media player based on the FFmpeg libraries
24 */
25
26#include "config.h"
27#include "config_components.h"
28#include <math.h>
29#include <limits.h>
30#include <signal.h>
31#include <stdint.h>
32
34#include "libavutil/avstring.h"
37#include "libavutil/mem.h"
38#include "libavutil/pixdesc.h"
39#include "libavutil/dict.h"
40#include "libavutil/fifo.h"
42#include "libavutil/samplefmt.h"
43#include "libavutil/time.h"
44#include "libavutil/bprint.h"
45#include "libavcodec/bsf.h"
48#include "libswscale/swscale.h"
49#include "libavutil/opt.h"
50#include "libavutil/tx.h"
52
56
57#include <SDL.h>
58#include <SDL_thread.h>
59
60#include "cmdutils.h"
61#include "ffplay_renderer.h"
62#include "opt_common.h"
63
64const char program_name[] = "ffplay";
65const int program_birth_year = 2003;
66
67#define MAX_QUEUE_SIZE (15 * 1024 * 1024)
68#define MIN_FRAMES 25
69#define EXTERNAL_CLOCK_MIN_FRAMES 2
70#define EXTERNAL_CLOCK_MAX_FRAMES 10
71
72/* Minimum SDL audio buffer size, in samples. */
73#define SDL_AUDIO_MIN_BUFFER_SIZE 512
74/* Calculate actual buffer size keeping in mind not cause too frequent audio callbacks */
75#define SDL_AUDIO_MAX_CALLBACKS_PER_SEC 30
76
77/* Step size for volume control in dB */
78#define SDL_VOLUME_STEP (0.75)
79
80/* no AV sync correction is done if below the minimum AV sync threshold */
81#define AV_SYNC_THRESHOLD_MIN 0.04
82/* AV sync correction is done if above the maximum AV sync threshold */
83#define AV_SYNC_THRESHOLD_MAX 0.1
84/* If a frame duration is longer than this, it will not be duplicated to compensate AV sync */
85#define AV_SYNC_FRAMEDUP_THRESHOLD 0.1
86/* no AV correction is done if too big error */
87#define AV_NOSYNC_THRESHOLD 10.0
88
89/* maximum audio speed change to get correct sync */
90#define SAMPLE_CORRECTION_PERCENT_MAX 10
91
92/* external clock speed adjustment constants for realtime sources based on buffer fullness */
93#define EXTERNAL_CLOCK_SPEED_MIN 0.900
94#define EXTERNAL_CLOCK_SPEED_MAX 1.010
95#define EXTERNAL_CLOCK_SPEED_STEP 0.001
96
97/* we use about AUDIO_DIFF_AVG_NB A-V differences to make the average */
98#define AUDIO_DIFF_AVG_NB 20
99
100/* polls for possible required screen refresh at least this often, should be less than 1/fps */
101#define REFRESH_RATE 0.01
102
103/* NOTE: the size must be big enough to compensate the hardware audio buffersize size */
104/* TODO: We assume that a decoded and resampled frame fits into this buffer */
105#define SAMPLE_ARRAY_SIZE (8 * 65536)
106
107#define CURSOR_HIDE_DELAY 1000000
108
109#define CHAPTER_LIST_FADE_TIME 250000
110#define CHAPTER_LIST_HOLD_TIME 500000
111#define CHAPTER_LIST_ROWS 7
112
113enum {
120};
121
122typedef struct ChapterSortKey {
123 int key;
126
127typedef struct ChapterRow {
128 int index;
129 const char *artist;
130 const char *title;
132} ChapterRow;
133
134/* what lies under a window position: the row and the sort button, -1 for none, and whether it is inside the list at all */
135typedef struct ChapterListHit {
137 int row;
141
142#define USE_ONEPASS_SUBTITLE_RENDER 1
143
148
159
160#define VIDEO_PICTURE_QUEUE_SIZE 3
161#define SUBPICTURE_QUEUE_SIZE 16
162#define SAMPLE_QUEUE_SIZE 9
163#define FRAME_QUEUE_SIZE FFMAX(SAMPLE_QUEUE_SIZE, FFMAX(VIDEO_PICTURE_QUEUE_SIZE, SUBPICTURE_QUEUE_SIZE))
164
172
173typedef struct Clock {
174 double pts; /* clock base */
175 double pts_drift; /* clock base minus time at which we updated the clock */
177 double speed;
178 int serial; /* clock is based on a packet with this serial */
180 int *queue_serial; /* pointer to the current packet queue serial, used for obsolete clock detection */
181} Clock;
182
183typedef struct FrameData {
185} FrameData;
186
187/* Common struct for handling all types of decoded data and allocated render buffers. */
188typedef struct Frame {
192 double pts; /* presentation timestamp for the frame */
193 double duration; /* estimated duration of the frame */
194 int64_t pos; /* byte position of the frame in the input file */
195 int width;
201} Frame;
202
215
221
226
233
234enum {
235 AV_SYNC_AUDIO_MASTER, /* default choice */
237 AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */
238};
239
240typedef struct Decoder {
252 SDL_Thread *decoder_tid;
253} Decoder;
254
255typedef struct VideoState {
256 SDL_Thread *read_tid;
270
274
278
282
284
286
289 double audio_diff_cum; /* used for AV difference average computation */
296 uint8_t *audio_buf;
297 uint8_t *audio_buf1;
298 unsigned int audio_buf_size; /* in bytes */
299 unsigned int audio_buf1_size;
300 int audio_buf_index; /* in bytes */
303 int muted;
310
320 float *real_data;
322 int xpos;
325 SDL_Texture *vis_texture;
326 SDL_Texture *sub_texture;
327 SDL_Texture *vid_texture;
328 SDL_Texture *chapter_texture;
329 SDL_Rect chapter_rect;
345
349
356 double max_frame_duration; // maximum duration of a frame - above this, we consider the jump a timestamp discontinuity
358 int eof;
359
360 char *filename;
362 int step;
363
365 AVFilterContext *in_video_filter; // the first filter in the video chain
366 AVFilterContext *out_video_filter; // the last filter in the video chain
367 AVFilterContext *in_audio_filter; // the first filter in the audio chain
368 AVFilterContext *out_audio_filter; // the last filter in the audio chain
369 AVFilterGraph *agraph; // audio filter graph
370
372
374} VideoState;
375
376/* options specified by the user */
378static const char *input_filename;
379static const char *window_title;
380static int default_width = 640;
381static int default_height = 480;
382static int screen_width = 0;
383static int screen_height = 0;
384static int screen_left = SDL_WINDOWPOS_CENTERED;
385static int screen_top = SDL_WINDOWPOS_CENTERED;
386static int audio_disable;
387static int video_disable;
389static const char* wanted_stream_spec[AVMEDIA_TYPE_NB] = {0};
390static int seek_by_bytes = -1;
391static float seek_interval = 10;
393static int borderless;
394static int alwaysontop;
395static int startup_volume = 100;
396static int show_status = -1;
400static int fast = 0;
401static int genpts = 0;
402static int lowres = 0;
403static int decoder_reorder_pts = -1;
404static int autoexit;
407static int loop = 1;
408static int framedrop = -1;
409static int infinite_buffer = -1;
410static enum ShowMode show_mode = SHOW_MODE_NONE;
411/* the columns the chapter list is sorted by, the most recently clicked first */
415static const char *audio_codec_name;
416static const char *subtitle_codec_name;
417static const char *video_codec_name;
418double rdftspeed = 0.02;
420static int cursor_hidden = 0;
421static const char **vfilters_list = NULL;
422static int nb_vfilters = 0;
423static char *afilters = NULL;
424static int autorotate = 1;
425static int find_stream_info = 1;
426static int filter_nbthreads = 0;
427static int enable_vulkan = 0;
428static char *vulkan_params = NULL;
429static char *video_background = NULL;
430static const char *hwaccel = NULL;
431
432/* current context */
433static int is_full_screen;
435
436#define FF_QUIT_EVENT (SDL_USEREVENT + 2)
437
438static volatile sig_atomic_t received_sigterm = 0;
439static volatile int received_nb_signals = 0;
440static int exit_status = 0;
441
442static SDL_Window *window;
443static SDL_Renderer *renderer;
444static SDL_RendererInfo renderer_info = {0};
445static SDL_AudioDeviceID audio_dev;
446
448
453 { AV_PIX_FMT_RGB8, SDL_PIXELFORMAT_RGB332 },
454 { AV_PIX_FMT_RGB444, SDL_PIXELFORMAT_RGB444 },
455 { AV_PIX_FMT_RGB555, SDL_PIXELFORMAT_RGB555 },
456 { AV_PIX_FMT_BGR555, SDL_PIXELFORMAT_BGR555 },
457 { AV_PIX_FMT_RGB565, SDL_PIXELFORMAT_RGB565 },
458 { AV_PIX_FMT_BGR565, SDL_PIXELFORMAT_BGR565 },
459 { AV_PIX_FMT_RGB24, SDL_PIXELFORMAT_RGB24 },
460 { AV_PIX_FMT_BGR24, SDL_PIXELFORMAT_BGR24 },
461 { AV_PIX_FMT_0RGB32, SDL_PIXELFORMAT_RGB888 },
462 { AV_PIX_FMT_0BGR32, SDL_PIXELFORMAT_BGR888 },
463 { AV_PIX_FMT_NE(RGB0, 0BGR), SDL_PIXELFORMAT_RGBX8888 },
464 { AV_PIX_FMT_NE(BGR0, 0RGB), SDL_PIXELFORMAT_BGRX8888 },
465 { AV_PIX_FMT_RGB32, SDL_PIXELFORMAT_ARGB8888 },
466 { AV_PIX_FMT_RGB32_1, SDL_PIXELFORMAT_RGBA8888 },
467 { AV_PIX_FMT_BGR32, SDL_PIXELFORMAT_ABGR8888 },
468 { AV_PIX_FMT_BGR32_1, SDL_PIXELFORMAT_BGRA8888 },
469 { AV_PIX_FMT_YUV420P, SDL_PIXELFORMAT_IYUV },
470 { AV_PIX_FMT_YUYV422, SDL_PIXELFORMAT_YUY2 },
471 { AV_PIX_FMT_UYVY422, SDL_PIXELFORMAT_UYVY },
473
474static int opt_add_vfilter(void *optctx, const char *opt, const char *arg)
475{
477 if (ret < 0)
478 return ret;
479
481 if (!vfilters_list[nb_vfilters - 1])
482 return AVERROR(ENOMEM);
483
484 return 0;
485}
486
487static inline
488int cmp_audio_fmts(enum AVSampleFormat fmt1, int64_t channel_count1,
489 enum AVSampleFormat fmt2, int64_t channel_count2)
490{
491 /* If channel count == 1, planar and non-planar formats are the same */
492 if (channel_count1 == 1 && channel_count2 == 1)
494 else
495 return channel_count1 != channel_count2 || fmt1 != fmt2;
496}
497
499{
500 MyAVPacketList pkt1;
501 int ret;
502
503 if (q->abort_request)
504 return -1;
505
506
507 pkt1.pkt = pkt;
508 pkt1.serial = q->serial;
509
510 ret = av_fifo_write(q->pkt_list, &pkt1, 1);
511 if (ret < 0)
512 return ret;
513 q->nb_packets++;
514 q->size += pkt1.pkt->size + sizeof(pkt1);
515 q->duration += pkt1.pkt->duration;
516 /* XXX: should duplicate packet data in DV case */
517 SDL_CondSignal(q->cond);
518 return 0;
519}
520
522{
523 AVPacket *pkt1;
524 int ret;
525
526 pkt1 = av_packet_alloc();
527 if (!pkt1) {
529 return -1;
530 }
531 av_packet_move_ref(pkt1, pkt);
532
533 SDL_LockMutex(q->mutex);
534 ret = packet_queue_put_private(q, pkt1);
535 SDL_UnlockMutex(q->mutex);
536
537 if (ret < 0)
538 av_packet_free(&pkt1);
539
540 return ret;
541}
542
543static int packet_queue_put_nullpacket(PacketQueue *q, AVPacket *pkt, int stream_index)
544{
545 pkt->stream_index = stream_index;
546 return packet_queue_put(q, pkt);
547}
548
549/* packet queue handling */
551{
552 memset(q, 0, sizeof(PacketQueue));
554 if (!q->pkt_list)
555 return AVERROR(ENOMEM);
556 q->mutex = SDL_CreateMutex();
557 if (!q->mutex) {
558 av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError());
559 return AVERROR(ENOMEM);
560 }
561 q->cond = SDL_CreateCond();
562 if (!q->cond) {
563 av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError());
564 return AVERROR(ENOMEM);
565 }
566 q->abort_request = 1;
567 return 0;
568}
569
571{
572 MyAVPacketList pkt1;
573
574 SDL_LockMutex(q->mutex);
575 while (av_fifo_read(q->pkt_list, &pkt1, 1) >= 0)
576 av_packet_free(&pkt1.pkt);
577 q->nb_packets = 0;
578 q->size = 0;
579 q->duration = 0;
580 q->serial++;
581 SDL_UnlockMutex(q->mutex);
582}
583
585{
588 SDL_DestroyMutex(q->mutex);
589 SDL_DestroyCond(q->cond);
590}
591
593{
594 SDL_LockMutex(q->mutex);
595
596 q->abort_request = 1;
597
598 SDL_CondSignal(q->cond);
599
600 SDL_UnlockMutex(q->mutex);
601}
602
604{
605 SDL_LockMutex(q->mutex);
606 q->abort_request = 0;
607 q->serial++;
608 SDL_UnlockMutex(q->mutex);
609}
610
611/* return < 0 if aborted, 0 if no packet and > 0 if packet. */
612static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block, int *serial)
613{
614 MyAVPacketList pkt1;
615 int ret;
616
617 SDL_LockMutex(q->mutex);
618
619 for (;;) {
620 if (q->abort_request) {
621 ret = -1;
622 break;
623 }
624
625 if (av_fifo_read(q->pkt_list, &pkt1, 1) >= 0) {
626 q->nb_packets--;
627 q->size -= pkt1.pkt->size + sizeof(pkt1);
628 q->duration -= pkt1.pkt->duration;
630 if (serial)
631 *serial = pkt1.serial;
632 av_packet_free(&pkt1.pkt);
633 ret = 1;
634 break;
635 } else if (!block) {
636 ret = 0;
637 break;
638 } else {
639 SDL_CondWait(q->cond, q->mutex);
640 }
641 }
642 SDL_UnlockMutex(q->mutex);
643 return ret;
644}
645
646static int decoder_init(Decoder *d, AVCodecContext *avctx, PacketQueue *queue, SDL_cond *empty_queue_cond) {
647 memset(d, 0, sizeof(Decoder));
648 d->pkt = av_packet_alloc();
649 if (!d->pkt)
650 return AVERROR(ENOMEM);
651 d->avctx = avctx;
652 d->queue = queue;
653 d->empty_queue_cond = empty_queue_cond;
655 d->pkt_serial = -1;
656 return 0;
657}
658
660 int ret = AVERROR(EAGAIN);
661
662 for (;;) {
663 if (d->queue->serial == d->pkt_serial) {
664 do {
665 if (d->queue->abort_request)
666 return -1;
667
668 switch (d->avctx->codec_type) {
671 if (ret >= 0) {
672 if (decoder_reorder_pts == -1) {
673 frame->pts = frame->best_effort_timestamp;
674 } else if (!decoder_reorder_pts) {
675 frame->pts = frame->pkt_dts;
676 }
677 }
678 break;
681 if (ret >= 0) {
682 AVRational tb = (AVRational){1, frame->sample_rate};
683 if (frame->pts != AV_NOPTS_VALUE)
684 frame->pts = av_rescale_q(frame->pts, d->avctx->pkt_timebase, tb);
685 else if (d->next_pts != AV_NOPTS_VALUE)
686 frame->pts = av_rescale_q(d->next_pts, d->next_pts_tb, tb);
687 if (frame->pts != AV_NOPTS_VALUE) {
688 d->next_pts = frame->pts + frame->nb_samples;
689 d->next_pts_tb = tb;
690 }
691 }
692 break;
693 }
694 if (ret == AVERROR_EOF) {
695 d->finished = d->pkt_serial;
697 return 0;
698 }
699 if (ret >= 0)
700 return 1;
701 } while (ret != AVERROR(EAGAIN));
702 }
703
704 do {
705 if (d->queue->nb_packets == 0)
706 SDL_CondSignal(d->empty_queue_cond);
707 if (d->packet_pending) {
708 d->packet_pending = 0;
709 } else {
710 int old_serial = d->pkt_serial;
711 if (packet_queue_get(d->queue, d->pkt, 1, &d->pkt_serial) < 0)
712 return -1;
713 if (old_serial != d->pkt_serial) {
715 d->finished = 0;
716 d->next_pts = d->start_pts;
718 }
719 }
720 if (d->queue->serial == d->pkt_serial)
721 break;
723 } while (1);
724
726 int got_frame = 0;
727 ret = avcodec_decode_subtitle2(d->avctx, sub, &got_frame, d->pkt);
728 if (ret < 0) {
729 ret = AVERROR(EAGAIN);
730 } else {
731 if (got_frame && !d->pkt->data) {
732 d->packet_pending = 1;
733 }
734 ret = got_frame ? 0 : (d->pkt->data ? AVERROR(EAGAIN) : AVERROR_EOF);
735 }
737 } else {
738 if (d->pkt->buf && !d->pkt->opaque_ref) {
739 FrameData *fd;
740
741 d->pkt->opaque_ref = av_buffer_allocz(sizeof(*fd));
742 if (!d->pkt->opaque_ref)
743 return AVERROR(ENOMEM);
744 fd = (FrameData*)d->pkt->opaque_ref->data;
745 fd->pkt_pos = d->pkt->pos;
746 }
747
748 if (avcodec_send_packet(d->avctx, d->pkt) == AVERROR(EAGAIN)) {
749 av_log(d->avctx, AV_LOG_ERROR, "Receive_frame and send_packet both returned EAGAIN, which is an API violation.\n");
750 d->packet_pending = 1;
751 } else {
753 }
754 }
755 }
756}
757
758static void decoder_destroy(Decoder *d) {
759 av_packet_free(&d->pkt);
761}
762
764{
766 avsubtitle_free(&vp->sub);
767}
768
769static int frame_queue_init(FrameQueue *f, PacketQueue *pktq, int max_size, int keep_last)
770{
771 int i;
772 memset(f, 0, sizeof(FrameQueue));
773 if (!(f->mutex = SDL_CreateMutex())) {
774 av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError());
775 return AVERROR(ENOMEM);
776 }
777 if (!(f->cond = SDL_CreateCond())) {
778 av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError());
779 return AVERROR(ENOMEM);
780 }
781 f->pktq = pktq;
782 f->max_size = FFMIN(max_size, FRAME_QUEUE_SIZE);
783 f->keep_last = !!keep_last;
784 for (i = 0; i < f->max_size; i++)
785 if (!(f->queue[i].frame = av_frame_alloc()))
786 return AVERROR(ENOMEM);
787 return 0;
788}
789
791{
792 int i;
793 for (i = 0; i < f->max_size; i++) {
794 Frame *vp = &f->queue[i];
796 av_frame_free(&vp->frame);
797 }
798 SDL_DestroyMutex(f->mutex);
799 SDL_DestroyCond(f->cond);
800}
801
803{
804 SDL_LockMutex(f->mutex);
805 SDL_CondSignal(f->cond);
806 SDL_UnlockMutex(f->mutex);
807}
808
810{
811 return &f->queue[(f->rindex + f->rindex_shown) % f->max_size];
812}
813
815{
816 return &f->queue[(f->rindex + f->rindex_shown + 1) % f->max_size];
817}
818
820{
821 return &f->queue[f->rindex];
822}
823
825{
826 /* wait until we have space to put a new frame */
827 SDL_LockMutex(f->mutex);
828 while (f->size >= f->max_size &&
829 !f->pktq->abort_request) {
830 SDL_CondWait(f->cond, f->mutex);
831 }
832 SDL_UnlockMutex(f->mutex);
833
834 if (f->pktq->abort_request)
835 return NULL;
836
837 return &f->queue[f->windex];
838}
839
841{
842 /* wait until we have a readable a new frame */
843 SDL_LockMutex(f->mutex);
844 while (f->size - f->rindex_shown <= 0 &&
845 !f->pktq->abort_request) {
846 SDL_CondWait(f->cond, f->mutex);
847 }
848 SDL_UnlockMutex(f->mutex);
849
850 if (f->pktq->abort_request)
851 return NULL;
852
853 return &f->queue[(f->rindex + f->rindex_shown) % f->max_size];
854}
855
857{
858 if (++f->windex == f->max_size)
859 f->windex = 0;
860 SDL_LockMutex(f->mutex);
861 f->size++;
862 SDL_CondSignal(f->cond);
863 SDL_UnlockMutex(f->mutex);
864}
865
867{
868 if (f->keep_last && !f->rindex_shown) {
869 f->rindex_shown = 1;
870 return;
871 }
872 frame_queue_unref_item(&f->queue[f->rindex]);
873 if (++f->rindex == f->max_size)
874 f->rindex = 0;
875 SDL_LockMutex(f->mutex);
876 f->size--;
877 SDL_CondSignal(f->cond);
878 SDL_UnlockMutex(f->mutex);
879}
880
881/* return the number of undisplayed frames in the queue */
883{
884 return f->size - f->rindex_shown;
885}
886
887/* return last shown position */
889{
890 Frame *fp = &f->queue[f->rindex];
891 if (f->rindex_shown && fp->serial == f->pktq->serial)
892 return fp->pos;
893 else
894 return -1;
895}
896
897static void decoder_abort(Decoder *d, FrameQueue *fq)
898{
901 SDL_WaitThread(d->decoder_tid, NULL);
902 d->decoder_tid = NULL;
904}
905
906static inline void fill_rectangle(int x, int y, int w, int h)
907{
908 SDL_Rect rect;
909 rect.x = x;
910 rect.y = y;
911 rect.w = w;
912 rect.h = h;
913 if (w && h)
914 SDL_RenderFillRect(renderer, &rect);
915}
916
917static int realloc_texture(SDL_Texture **texture, Uint32 new_format, int new_width, int new_height, SDL_BlendMode blendmode, int init_texture)
918{
919 Uint32 format;
920 int access, w, h;
921 if (!*texture || SDL_QueryTexture(*texture, &format, &access, &w, &h) < 0 || new_width != w || new_height != h || new_format != format) {
922 void *pixels;
923 int pitch;
924 if (*texture)
925 SDL_DestroyTexture(*texture);
926 if (!(*texture = SDL_CreateTexture(renderer, new_format, SDL_TEXTUREACCESS_STREAMING, new_width, new_height)))
927 return -1;
928 if (SDL_SetTextureBlendMode(*texture, blendmode) < 0)
929 return -1;
930 if (init_texture) {
931 if (SDL_LockTexture(*texture, NULL, &pixels, &pitch) < 0)
932 return -1;
933 memset(pixels, 0, pitch * new_height);
934 SDL_UnlockTexture(*texture);
935 }
936 av_log(NULL, AV_LOG_VERBOSE, "Created %dx%d texture with %s.\n", new_width, new_height, SDL_GetPixelFormatName(new_format));
937 }
938 return 0;
939}
940
941static void calculate_display_rect(SDL_Rect *rect,
942 int scr_xleft, int scr_ytop, int scr_width, int scr_height,
943 int pic_width, int pic_height, AVRational pic_sar)
944{
945 AVRational aspect_ratio = pic_sar;
946 int64_t width, height, x, y;
947
948 if (av_cmp_q(aspect_ratio, av_make_q(0, 1)) <= 0)
949 aspect_ratio = av_make_q(1, 1);
950
951 aspect_ratio = av_mul_q(aspect_ratio, av_make_q(pic_width, pic_height));
952
953 /* XXX: we suppose the screen has a 1.0 pixel ratio */
954 height = scr_height;
955 width = av_rescale(height, aspect_ratio.num, aspect_ratio.den) & ~1;
956 if (width > scr_width) {
957 width = scr_width;
958 height = av_rescale(width, aspect_ratio.den, aspect_ratio.num) & ~1;
959 }
960 x = (scr_width - width) / 2;
961 y = (scr_height - height) / 2;
962 rect->x = scr_xleft + x;
963 rect->y = scr_ytop + y;
964 rect->w = FFMAX((int)width, 1);
965 rect->h = FFMAX((int)height, 1);
966}
967
968static void get_sdl_pix_fmt_and_blendmode(int format, Uint32 *sdl_pix_fmt, SDL_BlendMode *sdl_blendmode)
969{
970 int i;
971 *sdl_blendmode = SDL_BLENDMODE_NONE;
972 *sdl_pix_fmt = SDL_PIXELFORMAT_UNKNOWN;
973 if (format == AV_PIX_FMT_RGB32 ||
977 *sdl_blendmode = SDL_BLENDMODE_BLEND;
978 for (i = 0; i < FF_ARRAY_ELEMS(sdl_texture_format_map); i++) {
980 *sdl_pix_fmt = sdl_texture_format_map[i].texture_fmt;
981 return;
982 }
983 }
984}
985
986static int upload_texture(SDL_Texture **tex, AVFrame *frame)
987{
988 int ret = 0;
989 Uint32 sdl_pix_fmt;
990 SDL_BlendMode sdl_blendmode;
991 get_sdl_pix_fmt_and_blendmode(frame->format, &sdl_pix_fmt, &sdl_blendmode);
992 if (realloc_texture(tex, sdl_pix_fmt == SDL_PIXELFORMAT_UNKNOWN ? SDL_PIXELFORMAT_ARGB8888 : sdl_pix_fmt, frame->width, frame->height, sdl_blendmode, 0) < 0)
993 return -1;
994 switch (sdl_pix_fmt) {
995 case SDL_PIXELFORMAT_IYUV:
996 if (frame->linesize[0] > 0 && frame->linesize[1] > 0 && frame->linesize[2] > 0) {
997 ret = SDL_UpdateYUVTexture(*tex, NULL, frame->data[0], frame->linesize[0],
998 frame->data[1], frame->linesize[1],
999 frame->data[2], frame->linesize[2]);
1000 } else if (frame->linesize[0] < 0 && frame->linesize[1] < 0 && frame->linesize[2] < 0) {
1001 ret = SDL_UpdateYUVTexture(*tex, NULL, frame->data[0] + frame->linesize[0] * (frame->height - 1), -frame->linesize[0],
1002 frame->data[1] + frame->linesize[1] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[1],
1003 frame->data[2] + frame->linesize[2] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[2]);
1004 } else {
1005 av_log(NULL, AV_LOG_ERROR, "Mixed negative and positive linesizes are not supported.\n");
1006 return -1;
1007 }
1008 break;
1009 default:
1010 if (frame->linesize[0] < 0) {
1011 ret = SDL_UpdateTexture(*tex, NULL, frame->data[0] + frame->linesize[0] * (frame->height - 1), -frame->linesize[0]);
1012 } else {
1013 ret = SDL_UpdateTexture(*tex, NULL, frame->data[0], frame->linesize[0]);
1014 }
1015 break;
1016 }
1017 return ret;
1018}
1019
1025
1030
1032{
1033#if SDL_VERSION_ATLEAST(2,0,8)
1034 SDL_YUV_CONVERSION_MODE mode = SDL_YUV_CONVERSION_AUTOMATIC;
1035 if (frame && (frame->format == AV_PIX_FMT_YUV420P || frame->format == AV_PIX_FMT_YUYV422 || frame->format == AV_PIX_FMT_UYVY422)) {
1036 if (frame->color_range == AVCOL_RANGE_JPEG)
1037 mode = SDL_YUV_CONVERSION_JPEG;
1038 else if (frame->colorspace == AVCOL_SPC_BT709)
1039 mode = SDL_YUV_CONVERSION_BT709;
1040 else if (frame->colorspace == AVCOL_SPC_BT470BG || frame->colorspace == AVCOL_SPC_SMPTE170M)
1041 mode = SDL_YUV_CONVERSION_BT601;
1042 }
1043 SDL_SetYUVConversionMode(mode); /* FIXME: no support for linear transfer */
1044#endif
1045}
1046
1048{
1049 const int tile_size = VIDEO_BACKGROUND_TILE_SIZE;
1050 SDL_Rect *rect = &is->render_params.target_rect;
1051 SDL_BlendMode blendMode;
1052
1053 if (!SDL_GetTextureBlendMode(is->vid_texture, &blendMode) && blendMode == SDL_BLENDMODE_BLEND) {
1054 switch (is->render_params.video_background_type) {
1056 SDL_SetRenderDrawColor(renderer, 237, 237, 237, 255);
1057 fill_rectangle(rect->x, rect->y, rect->w, rect->h);
1058 SDL_SetRenderDrawColor(renderer, 222, 222, 222, 255);
1059 for (int x = 0; x < rect->w; x += tile_size * 2)
1060 fill_rectangle(rect->x + x, rect->y, FFMIN(tile_size, rect->w - x), rect->h);
1061 for (int y = 0; y < rect->h; y += tile_size * 2)
1062 fill_rectangle(rect->x, rect->y + y, rect->w, FFMIN(tile_size, rect->h - y));
1063 SDL_SetRenderDrawColor(renderer, 237, 237, 237, 255);
1064 for (int y = 0; y < rect->h; y += tile_size * 2) {
1065 int h = FFMIN(tile_size, rect->h - y);
1066 for (int x = 0; x < rect->w; x += tile_size * 2)
1067 fill_rectangle(x + rect->x, y + rect->y, FFMIN(tile_size, rect->w - x), h);
1068 }
1069 break;
1071 const uint8_t *c = is->render_params.video_background_color;
1072 SDL_SetRenderDrawColor(renderer, c[0], c[1], c[2], c[3]);
1073 fill_rectangle(rect->x, rect->y, rect->w, rect->h);
1074 break;
1075 }
1077 SDL_SetTextureBlendMode(is->vid_texture, SDL_BLENDMODE_NONE);
1078 break;
1079 }
1080 }
1081}
1082
1083static int current_chapter(VideoState *is);
1084static void seek_chapter(VideoState *is, int i);
1085
1087{
1088 double alpha = (now - is->chapter_fade_start) / (double)CHAPTER_LIST_FADE_TIME;
1089
1090 if (!is->chapter_texture)
1091 return 0;
1092 if (!is->chapter_pinned)
1093 alpha = FFMIN(alpha, 1 - (now - is->chapter_last_input - CHAPTER_LIST_HOLD_TIME) / (double)CHAPTER_LIST_FADE_TIME);
1094 return av_clipd(alpha, 0, 1);
1095}
1096
1097static const char *chapter_tag(const AVChapter *chapter, const char *key)
1098{
1099 const AVDictionaryEntry *tag = av_dict_get(chapter->metadata, key, NULL, 0);
1100
1101 return tag ? tag->value : "";
1102}
1103
1104/* case-insensitive, with missing tags after all others */
1105static int compare_tags(const char *a, const char *b)
1106{
1107 return !*a != !*b ? !*a - !*b : av_strcasecmp(a, b);
1108}
1109
1110/* the rank of a chapter in the shuffled order for the current seed */
1111static uint32_t shuffle_rank(int index)
1112{
1113 uint32_t rank = (index + 1) * 0x9E3779B1u ^ chapter_shuffle_seed * 0x85EBCA77u;
1114
1115 rank ^= rank >> 15;
1116 rank *= 0x2C1B3C6Du;
1117 return rank ^ rank >> 12;
1118}
1119
1120static int compare_chapter_rows(const void *a, const void *b)
1121{
1122 const ChapterRow *ra = a, *rb = b;
1123
1124 for (int i = 0; i < CHAPTER_SORT_NB; i++) {
1125 int cmp;
1126
1127 switch (chapter_sort[i].key) {
1128 case CHAPTER_SORT_ARTIST: cmp = compare_tags(ra->artist, rb->artist); break;
1129 case CHAPTER_SORT_TITLE: cmp = compare_tags(ra->title, rb->title); break;
1130 case CHAPTER_SORT_LENGTH: cmp = FFDIFFSIGN(ra->length, rb->length); break;
1131 case CHAPTER_SORT_SHUFFLE: cmp = FFDIFFSIGN(shuffle_rank(ra->index), shuffle_rank(rb->index)); break;
1132 default: cmp = ra->index - rb->index; break;
1133 }
1134 if (cmp)
1135 return chapter_sort[i].descending ? -cmp : cmp;
1136 }
1137 return 0;
1138}
1139
1140/* a column clicked again flips its order, any other becomes the first key ahead of the previous ones;
1141 * the shuffle button instead steps its seed by the side it was clicked on */
1142static void chapter_sort_by(int key, int seed_step)
1143{
1144 int i = 0;
1145
1146 while (chapter_sort[i].key != key)
1147 i++;
1149 chapter_shuffle_seed += seed_step;
1150 else if (i == 0)
1151 chapter_sort[0].descending ^= 1;
1152 if (i == 0)
1153 return;
1154 memmove(&chapter_sort[1], &chapter_sort[0], i * sizeof(*chapter_sort));
1155 chapter_sort[0] = (ChapterSortKey){ key, 0 };
1156}
1157
1158/* rebuilds the rows matching the search in the current sort order, keeping the selected chapter selected */
1160{
1161 int selected = is->nb_chapter_rows ? is->chapter_rows[is->chapter_selected].index : 0;
1162 ChapterRow *rows = av_realloc_array(is->chapter_rows, is->ic->nb_chapters, sizeof(*rows));
1163
1164 if (!rows)
1165 return AVERROR(ENOMEM);
1166 is->chapter_rows = rows;
1167 is->nb_chapter_rows = 0;
1168 for (int i = 0; i < is->ic->nb_chapters; i++) {
1169 AVChapter *chapter = is->ic->chapters[i];
1170 ChapterRow row = { i, chapter_tag(chapter, "artist"), chapter_tag(chapter, "title"), -1 };
1171
1172 if (chapter->end != AV_NOPTS_VALUE && chapter->end > chapter->start &&
1173 (uint64_t)chapter->end - chapter->start <= INT64_MAX)
1174 row.length = av_rescale_q(chapter->end - chapter->start, chapter->time_base, AV_TIME_BASE_Q);
1175 if (av_stristr(row.artist, is->chapter_search) || av_stristr(row.title, is->chapter_search))
1176 is->chapter_rows[is->nb_chapter_rows++] = row;
1177 }
1178 qsort(is->chapter_rows, is->nb_chapter_rows, sizeof(*is->chapter_rows), compare_chapter_rows);
1179 is->chapter_selected = 0;
1180 for (int row = 0; row < is->nb_chapter_rows; row++)
1181 if (is->chapter_rows[row].index == selected)
1182 is->chapter_selected = row;
1183 return 0;
1184}
1185
1186static const struct {
1187 const char *label;
1190 [CHAPTER_SORT_NUMBER] = { "#", 5 },
1191 [CHAPTER_SORT_ARTIST] = { "Artist", 8 },
1192 [CHAPTER_SORT_TITLE] = { "Title", 7 },
1193 [CHAPTER_SORT_LENGTH] = { "Duration", 10 },
1194 [CHAPTER_SORT_SHUFFLE] = { "Shuffle", 14 },
1196
1197#define CHAPTER_LIST_EVENT "Dialogue: 0:00:00.00,9999:00:00.00,"
1198
1199static void bprint_chapter_box(AVBPrint *script, const char *style, int x, int y, int w, int h)
1200{
1201 av_bprintf(script, CHAPTER_LIST_EVENT "%s,{\\pos(%d,%d)\\p1}m 0 0 l %d 0 %d %d 0 %d{\\p0}\n", style, x, y, w, w, h, h);
1202}
1203
1204/* a text cell cut off at the right and bottom of its column, with the characters libass would read as tags or line breaks blanked */
1205static void bprint_chapter_cell(AVBPrint *script, const char *style, int x, int y, int right, int bottom, const char *text)
1206{
1207 av_bprintf(script, CHAPTER_LIST_EVENT "%s,{\\pos(%d,%d)\\clip(0,0,%d,%d)}", style, x, y, right, bottom);
1208 for (; *text; text++)
1209 av_bprint_chars(script, strchr("{}\\\r\n", *text) ? ' ' : *text, 1);
1210 av_bprint_chars(script, '\n', 1);
1211}
1212
1218
1219/* button widths are in half font sizes, a quarter apart, wrapping onto further lines when the panel is too narrow */
1221{
1223 int x, y;
1224
1225 l.font = FFMAX(is->height / 30, 12);
1226 l.line = l.font * 9 / 4;
1227 l.width = FFMIN(FFMAX(is->width * 3 / 5, l.font * 26), is->width - l.font * 2);
1228 x = y = l.font / 2;
1229 for (int b = 0; b < CHAPTER_SORT_NB; b++) {
1230 int w = sort_buttons[b].width * l.font / 2;
1231
1232 if (x > l.font / 2 && x + w > l.width - l.font / 2) {
1233 x = l.font / 2;
1234 y += l.font * 3 / 2;
1235 }
1236 l.button_x[b] = x;
1237 l.button_y[b] = y;
1238 x += w + l.font / 4;
1239 }
1240 /* the search field follows the buttons, or takes its own line when they leave it less than 8 em */
1241 if (x + l.font * 8 > l.width - l.font / 2) {
1242 x = l.font / 2;
1243 y += l.font * 3 / 2;
1244 }
1245 l.search_x = x;
1246 l.search_y = y;
1247 l.rows_y = is->chapter_pinned ? y + l.font * 3 / 2 : l.button_y[CHAPTER_SORT_NB - 1] + l.font * 3 / 2;
1248 l.canvas_h = FFMIN(y + l.font * 2 + CHAPTER_LIST_ROWS * l.line, is->height - l.font * 2);
1249 l.nb_rows = FFMIN(is->nb_chapter_rows, FFMAX(1, (l.canvas_h - l.rows_y - l.font / 2) / l.line));
1250 l.first = av_clip(is->chapter_selected - l.nb_rows / 2, 0, is->nb_chapter_rows - l.nb_rows);
1251 l.height = l.rows_y + l.nb_rows * l.line + l.font / 2;
1252 l.text_x = l.font * 3;
1253 l.text_right = l.width - l.font * 11 / 2;
1254 l.length_x = l.width - l.font * 5 / 2;
1255 l.detail_x = l.width - l.font * 5 / 4;
1256 l.canvas_w = is->width - l.font * 2;
1257 return l;
1258}
1259
1261{
1262 ChapterListHit hit = { 0, -1, -1, 0 };
1263 int line;
1264
1265 x -= l->font;
1266 y -= l->font;
1267 if (x < 0 || y < 0 || x >= l->width || y >= FFMIN(l->height, l->canvas_h))
1268 return hit;
1269 hit.inside = 1;
1270 line = (y - l->rows_y) / l->line;
1271 if (y >= l->rows_y && line < l->nb_rows) {
1272 hit.row = l->first + line;
1273 hit.detail = x >= l->width - l->font * 2;
1274 }
1275 for (int b = 0; b < FF_ARRAY_ELEMS(sort_buttons); b++)
1276 if (x >= l->button_x[b] && x < l->button_x[b] + sort_buttons[b].width * l->font / 2 &&
1277 y >= l->button_y[b] && y < l->button_y[b] + l->font * 5 / 4)
1278 hit.button = b;
1279 return hit;
1280}
1281
1282/* a circle outline drawn as four bezier arcs around a center */
1283static void bprint_chapter_ring(AVBPrint *script, int cx, int cy, int r)
1284{
1285 int k = r * 552 / 1000;
1286
1287 av_bprintf(script, CHAPTER_LIST_EVENT "Ring,{\\an5\\pos(%d,%d)\\p1}m 0 %d b 0 %d %d 0 %d 0 b %d 0 %d %d %d %d "
1288 "b %d %d %d %d %d %d b %d %d 0 %d 0 %d{\\p0}\n",
1289 cx, cy, r, r - k, r - k, r, r + k, 2 * r, r - k, 2 * r, r, 2 * r, r + k, r + k, 2 * r, r, 2 * r,
1290 r - k, 2 * r, r + k, r);
1291}
1292
1293/* the metadata of the chapter whose symbol the mouse is over, as a popup beside the list or over its rows when the window is narrow */
1294static void bprint_chapter_details(VideoState *is, AVBPrint *script, const ChapterListLayout *l)
1295{
1296 const AVChapter *chapter = is->ic->chapters[is->chapter_rows[is->chapter_hover.row].index];
1297 const AVDictionaryEntry *tag = NULL;
1298 int beside = l->canvas_w - l->width >= l->font * 12;
1299 int height = FFMIN(av_dict_count(chapter->metadata) * l->font + l->font / 2, is->chapter_rect.h);
1300 int x = beside ? l->width + l->font / 2 : l->text_x;
1301 int right = beside ? l->canvas_w : l->length_x - l->font / 2;
1302 int y = av_clip(l->rows_y + (is->chapter_hover.row - l->first) * l->line, 0, is->chapter_rect.h - height);
1303
1304 if (!av_dict_count(chapter->metadata))
1305 return;
1306 bprint_chapter_box(script, "Popup", x, y, right - x, height);
1307 for (int i = 0; (tag = av_dict_iterate(chapter->metadata, tag)); i++) {
1308 int line_y = y + l->font / 4 + i * l->font;
1309
1310 bprint_chapter_cell(script, "Detail", x + l->font / 2, line_y, x + l->font * 7, y + height, tag->key);
1311 bprint_chapter_cell(script, "Detail", x + l->font * 15 / 2, line_y, right - l->font / 4, y + height, tag->value);
1312 }
1313}
1314
1315static void chapter_list_script(VideoState *is, AVBPrint *script)
1316{
1318
1319 is->chapter_hover = chapter_list_hit(is, &l, is->chapter_mouse_x, is->chapter_mouse_y);
1320 is->chapter_rect = (SDL_Rect){ l.font, l.font, l.canvas_w, l.canvas_h };
1321 av_bprintf(script,
1322 "[Script Info]\nScriptType: v4.00+\nPlayResX: %d\nPlayResY: %d\nWrapStyle: 2\nYCbCr Matrix: None\n\n"
1323 "[V4+ Styles]\n"
1324 "Format: Name, Fontname, Fontsize, PrimaryColour, OutlineColour, Bold, Outline, Alignment\n"
1325 "Style: Panel,Sans,%d,&H40000000,&H40000000,0,0,7\n"
1326 "Style: Button,Sans,%d,&H80FFFFFF,&H80FFFFFF,0,0,7\n"
1327 "Style: Row,Sans,%d,&H00FFFFFF,&H00000000,0,%d,7\n"
1328 "Style: Selected,Sans,%d,&H0080D0FF,&H00000000,-1,%d,7\n"
1329 "Style: Artist,Sans,%d,&H00C0C0C0,&H00000000,0,%d,7\n"
1330 "Style: ArtistSelected,Sans,%d,&H0080D0FF,&H00000000,-1,%d,7\n"
1331 "Style: Playing,Sans,%d,&H00FFFFFF,&H00FFFFFF,0,0,7\n"
1332 "Style: Hint,Sans,%d,&H00A0A0A0,&H00000000,0,%d,7\n"
1333 "Style: Hover,Sans,%d,&HC8FFFFFF,&HC8FFFFFF,0,0,7\n"
1334 "Style: ButtonHover,Sans,%d,&H50FFFFFF,&H50FFFFFF,0,0,7\n"
1335 "Style: Ring,Sans,%d,&HFF000000,&H00A0A0A0,0,%d,7\n"
1336 "Style: Popup,Sans,%d,&H20000000,&H20000000,0,0,7\n"
1337 "Style: Detail,Sans,%d,&H00FFFFFF,&H00000000,0,%d,7\n\n"
1338 "[Events]\nFormat: Start, End, Style, Text\n",
1339 is->chapter_rect.w, is->chapter_rect.h, l.font, l.font, l.font, l.font / 16 + 1, l.font, l.font / 16 + 1,
1340 l.font * 4 / 5, l.font / 16 + 1, l.font * 4 / 5, l.font / 16 + 1, l.font, l.font, l.font / 16 + 1, l.font, l.font,
1341 l.font, l.font / 16 + 1, l.font, l.font * 4 / 5, l.font / 16 + 1);
1342 bprint_chapter_box(script, "Panel", 0, 0, l.width, l.height);
1343 if (is->chapter_pinned)
1344 bprint_chapter_cell(script, *is->chapter_search ? "Row" : "Hint", l.search_x, l.search_y, l.length_x,
1345 l.search_y + l.font * 3 / 2, *is->chapter_search ? is->chapter_search : "type to search");
1346 for (int b = 0; b < FF_ARRAY_ELEMS(sort_buttons); b++) {
1347 int x = l.button_x[b], y = l.button_y[b], w = sort_buttons[b].width * l.font / 2;
1348
1349 bprint_chapter_box(script, b == is->chapter_hover.button ? "ButtonHover" : "Button", x, y, w, l.font * 5 / 4);
1350 av_bprintf(script, CHAPTER_LIST_EVENT "%s,{\\an5\\pos(%d,%d)}", chapter_sort[0].key == b ? "Selected" : "Row",
1351 x + w / 2, y + l.font * 5 / 8);
1352 if (b == CHAPTER_SORT_SHUFFLE)
1353 av_bprintf(script, "\xe2\x97\x82 %s %d \xe2\x96\xb8\n", sort_buttons[b].label, chapter_shuffle_seed);
1354 else
1355 av_bprintf(script, "%s%s\n", sort_buttons[b].label,
1356 chapter_sort[0].key != b ? "" : chapter_sort[0].descending ? " \xe2\x96\xbc" : " \xe2\x96\xb2");
1357 }
1358 is->chapter_playing = current_chapter(is);
1359 for (int r = l.first; r < l.first + l.nb_rows; r++) {
1360 const ChapterRow *row = &is->chapter_rows[r];
1361 const char *style = r == is->chapter_selected ? "Selected" : "Row";
1362 int y = l.rows_y + (r - l.first) * l.line;
1363 int64_t seconds;
1364
1365 if (r == is->chapter_hover.row)
1366 bprint_chapter_box(script, "Hover", 0, y, l.width, l.line);
1367 if (row->index == is->chapter_playing)
1368 bprint_chapter_box(script, "Playing", 0, y, l.font / 6, l.line);
1369 av_bprintf(script, CHAPTER_LIST_EVENT "%s,{\\an6\\pos(%d,%d)}%d\n", style, l.font * 5 / 2, y + l.line / 2, row->index + 1);
1370 bprint_chapter_cell(script, style, l.text_x, y + l.font / 8, l.text_right, y + l.line, row->title);
1371 bprint_chapter_cell(script, r == is->chapter_selected ? "ArtistSelected" : "Artist", l.text_x, y + l.font * 5 / 4,
1372 l.text_right, y + l.line, row->artist);
1373 bprint_chapter_ring(script, l.detail_x, y + l.line / 2, l.font * 9 / 20);
1374 av_bprintf(script, CHAPTER_LIST_EVENT "Hint,{\\an5\\pos(%d,%d)}i\n", l.detail_x, y + l.line / 2);
1375 if (row->length < 0)
1376 continue;
1377 seconds = (row->length + AV_TIME_BASE / 2) / AV_TIME_BASE;
1378 av_bprintf(script, CHAPTER_LIST_EVENT "%s,{\\an6\\pos(%d,%d)}", style, l.length_x, y + l.line / 2);
1379 if (seconds >= 3600)
1380 av_bprintf(script, "%d:%02d:%02d\n", (int)(seconds / 3600), (int)(seconds / 60 % 60), (int)(seconds % 60));
1381 else
1382 av_bprintf(script, "%d:%02d\n", (int)(seconds / 60), (int)(seconds % 60));
1383 }
1384 if (is->chapter_hover.detail)
1385 bprint_chapter_details(is, script, &l);
1386}
1387
1388static int chapter_list_configure(VideoState *is, const char *script)
1389{
1390 const AVFilter *ass_filter = avfilter_get_by_name("ass");
1391 AVFilterContext *source, *ass;
1392 char source_args[64];
1393 int ret;
1394
1395 if (!ass_filter) {
1396 static int reported;
1397
1398 if (!reported++)
1399 av_log(NULL, AV_LOG_ERROR, "The chapter list needs the ass filter, which this build lacks\n");
1401 }
1402 avfilter_graph_free(&is->chapter_graph);
1403 if (!(is->chapter_graph = avfilter_graph_alloc()))
1404 return AVERROR(ENOMEM);
1405 snprintf(source_args, sizeof(source_args), "color=black@0:rate=1:size=%dx%d", is->chapter_rect.w, is->chapter_rect.h);
1406 ass = avfilter_graph_alloc_filter(is->chapter_graph, ass_filter, "ass");
1407 is->chapter_sink = avfilter_graph_alloc_filter(is->chapter_graph, avfilter_get_by_name("buffersink"), "sink");
1408 if (!ass || !is->chapter_sink)
1409 return AVERROR(ENOMEM);
1410 if ((ret = avfilter_graph_create_filter(&source, avfilter_get_by_name("color"), "source", source_args, NULL, is->chapter_graph)) < 0 ||
1411 (ret = av_opt_set(ass, "script", script, AV_OPT_SEARCH_CHILDREN)) < 0 ||
1412 (ret = av_opt_set_int(ass, "alpha", 1, AV_OPT_SEARCH_CHILDREN)) < 0 ||
1413 (ret = avfilter_init_str(ass, NULL)) < 0 ||
1414 (ret = av_opt_set_array(is->chapter_sink, "pixel_formats", AV_OPT_SEARCH_CHILDREN, 0, 1, AV_OPT_TYPE_PIXEL_FMT,
1415 &(enum AVPixelFormat){ AV_PIX_FMT_RGB32 })) < 0 ||
1416 (ret = avfilter_init_str(is->chapter_sink, NULL)) < 0 ||
1417 (ret = avfilter_link(source, 0, ass, 0)) < 0 ||
1418 (ret = avfilter_link(ass, 0, is->chapter_sink, 0)) < 0)
1419 return ret;
1420 return avfilter_graph_config(is->chapter_graph, NULL);
1421}
1422
1424{
1425 AVBPrint script;
1427 void *pixels;
1428 int pitch, ret;
1429
1430 if (!frame)
1431 return AVERROR(ENOMEM);
1432 is->chapter_render_pending = 0;
1434 chapter_list_script(is, &script);
1435 if (!av_bprint_is_complete(&script))
1436 ret = AVERROR(ENOMEM);
1437 else if (is->chapter_graph)
1438 ret = avfilter_graph_send_command(is->chapter_graph, "ass", "script", script.str, NULL, 0, 0);
1439 else
1440 ret = chapter_list_configure(is, script.str);
1441 if (ret >= 0)
1442 ret = av_buffersink_get_frame(is->chapter_sink, frame);
1443 if (ret >= 0 && (realloc_texture(&is->chapter_texture, SDL_PIXELFORMAT_ARGB8888, frame->width, frame->height, SDL_BLENDMODE_BLEND, 0) < 0 ||
1444 SDL_LockTexture(is->chapter_texture, NULL, &pixels, &pitch) < 0))
1445 ret = AVERROR_EXTERNAL;
1446 if (ret >= 0) {
1448
1449 /* the ass filter composites onto the transparent canvas with premultiplied alpha, SDL blends straight alpha */
1450 for (int y = 0; y < frame->height; y++) {
1451 const uint8_t *src = frame->data[0] + y * frame->linesize[0];
1452 uint8_t *dst = (uint8_t *)pixels + y * pitch;
1453
1454 for (int x = 0; x < frame->width * 4; x += 4)
1455 for (int c = 0; c < 4; c++)
1456 dst[x + c] = c == alpha || !src[x + alpha] ? src[x + c] : FFMIN(src[x + c] * 255 / src[x + alpha], 255);
1457 }
1458 SDL_UnlockTexture(is->chapter_texture);
1459 is->force_refresh = 1;
1460 }
1461 if (ret < 0) {
1462 if (ret != AVERROR_FILTER_NOT_FOUND)
1463 av_log(NULL, AV_LOG_ERROR, "Could not render the chapter list: %s\n", av_err2str(ret));
1464 avfilter_graph_free(&is->chapter_graph);
1465 if (is->chapter_texture)
1466 SDL_DestroyTexture(is->chapter_texture);
1467 is->chapter_texture = NULL;
1468 is->chapter_pinned = 0;
1469 SDL_StopTextInput();
1470 }
1472 av_bprint_finalize(&script, NULL);
1473 return ret;
1474}
1475
1476/* shows the list with the chapter selected, or with the selection kept when no row shows it */
1477static void chapter_list_show(VideoState *is, int chapter)
1478{
1480
1482 return;
1483 for (int row = 0; row < is->nb_chapter_rows; row++)
1484 if (is->chapter_rows[row].index == chapter)
1485 is->chapter_selected = row;
1486 is->chapter_fade_start = now - chapter_list_alpha(is, now) * CHAPTER_LIST_FADE_TIME;
1487 is->chapter_last_input = now;
1489}
1490
1492{
1493 if (is->nb_chapter_rows)
1494 chapter_list_show(is, is->chapter_rows[av_clip(is->chapter_selected + delta, 0, is->nb_chapter_rows - 1)].index);
1495}
1496
1498{
1500}
1501
1502/* appends the typed text to the search, or erases its last character when nothing was typed */
1503static void chapter_list_search(VideoState *is, const char *typed)
1504{
1505 int len = strlen(is->chapter_search);
1506
1507 if (typed) {
1508 if (len + strlen(typed) < sizeof(is->chapter_search))
1509 av_strlcat(is->chapter_search, typed, sizeof(is->chapter_search));
1510 } else if (len) {
1511 while (len > 0 && (is->chapter_search[--len] & 0xC0) == 0x80)
1512 ;
1513 is->chapter_search[len] = 0;
1514 }
1517}
1518
1519static void chapter_list_pin(VideoState *is, int pinned)
1520{
1521 if (!renderer)
1522 return;
1523 is->chapter_pinned = pinned;
1524 if (pinned) {
1526 is->chapter_pinned = !!is->chapter_texture;
1527 if (is->chapter_pinned)
1528 SDL_StartTextInput();
1529 } else {
1530 SDL_StopTextInput();
1531 is->chapter_last_input = av_gettime_relative() - CHAPTER_LIST_HOLD_TIME;
1532 is->chapter_search[0] = 0;
1535 }
1536}
1537
1538/* keys while the list is pinned; typed characters arrive as text input instead */
1539static void chapter_list_key(VideoState *is, SDL_Keycode key)
1540{
1541 switch (key) {
1542 case SDLK_ESCAPE: chapter_list_pin(is, 0); break;
1543 case SDLK_UP: chapter_list_move(is, -1); break;
1544 case SDLK_DOWN: chapter_list_move(is, 1); break;
1545 case SDLK_PAGEUP: seek_chapter(is, current_chapter(is) + 1); break;
1546 case SDLK_PAGEDOWN: seek_chapter(is, current_chapter(is) - 1); break;
1547 case SDLK_BACKSPACE: chapter_list_search(is, NULL); break;
1548 case SDLK_RETURN:
1549 case SDLK_KP_ENTER:
1550 if (is->nb_chapter_rows)
1551 seek_chapter(is, is->chapter_rows[is->chapter_selected].index);
1552 break;
1553 }
1554}
1555
1556/* keeps the mouse position for the next render and asks for one when what a visible list points at changed;
1557 * the render waits until the pending events are handled, so a sweep across the list renders once */
1558static void chapter_list_hover(VideoState *is, int x, int y)
1559{
1561 ChapterListHit hit;
1562
1563 is->chapter_mouse_x = x;
1564 is->chapter_mouse_y = y;
1566 return;
1568 hit = chapter_list_hit(is, &l, x, y);
1569 if (hit.row != is->chapter_hover.row || hit.button != is->chapter_hover.button || hit.detail != is->chapter_hover.detail)
1570 is->chapter_render_pending = 1;
1571}
1572
1573/* seeks to the entry under a click or sorts by the button under it, returns whether the click hit the list at all */
1574static int chapter_list_click(VideoState *is, int x, int y)
1575{
1577 ChapterListHit hit = chapter_list_hit(is, &l, x, y);
1578
1579 if (hit.row >= 0 && !hit.detail)
1580 seek_chapter(is, is->chapter_rows[hit.row].index);
1581 if (hit.button >= 0) {
1582 int button_w = sort_buttons[hit.button].width * l.font / 2;
1583
1584 chapter_sort_by(hit.button, (x - l.font - l.button_x[hit.button]) * 2 < button_w ? -1 : 1);
1585 chapter_list_show(is, -1);
1586 }
1587 return hit.inside;
1588}
1589
1591{
1593
1594 is->chapter_drawn_alpha = alpha;
1595 if (alpha > 0 && is->chapter_texture) {
1596 SDL_SetTextureAlphaMod(is->chapter_texture, alpha * 255);
1597 SDL_RenderCopy(renderer, is->chapter_texture, NULL, &is->chapter_rect);
1598 }
1599}
1600
1602{
1603 Frame *vp;
1604 Frame *sp = NULL;
1605 SDL_Rect *rect = &is->render_params.target_rect;
1606
1607 vp = frame_queue_peek_last(&is->pictq);
1608 calculate_display_rect(rect, is->xleft, is->ytop, is->width, is->height, vp->width, vp->height, vp->sar);
1609 if (vk_renderer) {
1610 vk_renderer_display(vk_renderer, vp->frame, &is->render_params);
1611 return;
1612 }
1613
1614 if (is->subtitle_st) {
1615 if (frame_queue_nb_remaining(&is->subpq) > 0) {
1616 sp = frame_queue_peek(&is->subpq);
1617
1618 if (vp->pts >= sp->pts + ((float) sp->sub.start_display_time / 1000)) {
1619 if (!sp->uploaded) {
1620 uint8_t* pixels[4];
1621 int pitch[4];
1622 int i;
1623 if (!sp->width || !sp->height) {
1624 sp->width = vp->width;
1625 sp->height = vp->height;
1626 }
1627 if (realloc_texture(&is->sub_texture, SDL_PIXELFORMAT_ARGB8888, sp->width, sp->height, SDL_BLENDMODE_BLEND, 1) < 0)
1628 return;
1629
1630 for (i = 0; i < sp->sub.num_rects; i++) {
1631 AVSubtitleRect *sub_rect = sp->sub.rects[i];
1632
1633 sub_rect->x = av_clip(sub_rect->x, 0, sp->width );
1634 sub_rect->y = av_clip(sub_rect->y, 0, sp->height);
1635 sub_rect->w = av_clip(sub_rect->w, 0, sp->width - sub_rect->x);
1636 sub_rect->h = av_clip(sub_rect->h, 0, sp->height - sub_rect->y);
1637
1638 is->sub_convert_ctx = sws_getCachedContext(is->sub_convert_ctx,
1639 sub_rect->w, sub_rect->h, AV_PIX_FMT_PAL8,
1640 sub_rect->w, sub_rect->h, AV_PIX_FMT_BGRA,
1641 0, NULL, NULL, NULL);
1642 if (!is->sub_convert_ctx) {
1643 av_log(NULL, AV_LOG_FATAL, "Cannot initialize the conversion context\n");
1644 return;
1645 }
1646 if (!SDL_LockTexture(is->sub_texture, (SDL_Rect *)sub_rect, (void **)pixels, pitch)) {
1647 sws_scale(is->sub_convert_ctx, (const uint8_t * const *)sub_rect->data, sub_rect->linesize,
1648 0, sub_rect->h, pixels, pitch);
1649 SDL_UnlockTexture(is->sub_texture);
1650 }
1651 }
1652 sp->uploaded = 1;
1653 }
1654 } else
1655 sp = NULL;
1656 }
1657 }
1658
1660
1661 if (!vp->uploaded) {
1662 if (upload_texture(&is->vid_texture, vp->frame) < 0) {
1664 return;
1665 }
1666 vp->uploaded = 1;
1667 vp->flip_v = vp->frame->linesize[0] < 0;
1668 }
1669
1671 SDL_RenderCopyEx(renderer, is->vid_texture, NULL, rect, 0, NULL, vp->flip_v ? SDL_FLIP_VERTICAL : 0);
1673 if (sp) {
1674#if USE_ONEPASS_SUBTITLE_RENDER
1675 SDL_RenderCopy(renderer, is->sub_texture, NULL, rect);
1676#else
1677 int i;
1678 double xratio = (double)rect->w / (double)sp->width;
1679 double yratio = (double)rect->h / (double)sp->height;
1680 for (i = 0; i < sp->sub.num_rects; i++) {
1681 SDL_Rect *sub_rect = (SDL_Rect*)sp->sub.rects[i];
1682 SDL_Rect target = {.x = rect.x + sub_rect->x * xratio,
1683 .y = rect.y + sub_rect->y * yratio,
1684 .w = sub_rect->w * xratio,
1685 .h = sub_rect->h * yratio};
1686 SDL_RenderCopy(renderer, is->sub_texture, sub_rect, &target);
1687 }
1688#endif
1689 }
1690}
1691
1692static inline int compute_mod(int a, int b)
1693{
1694 return a < 0 ? a%b + b : a%b;
1695}
1696
1698{
1699 int i, i_start, x, y1, y, ys, delay, n, nb_display_channels;
1700 int ch, channels, h, h2;
1701 int64_t time_diff;
1702 int rdft_bits, nb_freq;
1703
1704 for (rdft_bits = 1; (1 << rdft_bits) < 2 * s->height; rdft_bits++)
1705 ;
1706 nb_freq = 1 << (rdft_bits - 1);
1707
1708 /* compute display index : center on currently output samples */
1709 channels = s->audio_tgt.ch_layout.nb_channels;
1710 nb_display_channels = channels;
1711 if (!s->paused) {
1712 int data_used= s->show_mode == SHOW_MODE_WAVES ? s->width : (2*nb_freq);
1713 n = 2 * channels;
1714 delay = s->audio_write_buf_size;
1715 delay /= n;
1716
1717 /* to be more precise, we take into account the time spent since
1718 the last buffer computation */
1719 if (audio_callback_time) {
1721 delay -= (time_diff * s->audio_tgt.freq) / 1000000;
1722 }
1723
1724 delay += 2 * data_used;
1725 if (delay < data_used)
1726 delay = data_used;
1727
1728 i_start= x = compute_mod(s->sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE);
1729 if (s->show_mode == SHOW_MODE_WAVES) {
1730 h = INT_MIN;
1731 for (i = 0; i < 1000; i += channels) {
1732 int idx = (SAMPLE_ARRAY_SIZE + x - i) % SAMPLE_ARRAY_SIZE;
1733 int a = s->sample_array[idx];
1734 int b = s->sample_array[(idx + 4 * channels) % SAMPLE_ARRAY_SIZE];
1735 int c = s->sample_array[(idx + 5 * channels) % SAMPLE_ARRAY_SIZE];
1736 int d = s->sample_array[(idx + 9 * channels) % SAMPLE_ARRAY_SIZE];
1737 int score = a - d;
1738 if (h < score && (b ^ c) < 0) {
1739 h = score;
1740 i_start = idx;
1741 }
1742 }
1743 }
1744
1745 s->last_i_start = i_start;
1746 } else {
1747 i_start = s->last_i_start;
1748 }
1749
1750 if (s->show_mode == SHOW_MODE_WAVES) {
1751 SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
1752
1753 /* total height for one channel */
1754 h = s->height / nb_display_channels;
1755 /* graph height / 2 */
1756 h2 = (h * 9) / 20;
1757 for (ch = 0; ch < nb_display_channels; ch++) {
1758 i = i_start + ch;
1759 y1 = s->ytop + ch * h + (h / 2); /* position of center line */
1760 for (x = 0; x < s->width; x++) {
1761 y = (s->sample_array[i] * h2) >> 15;
1762 if (y < 0) {
1763 y = -y;
1764 ys = y1 - y;
1765 } else {
1766 ys = y1;
1767 }
1768 fill_rectangle(s->xleft + x, ys, 1, y);
1769 i += channels;
1770 if (i >= SAMPLE_ARRAY_SIZE)
1772 }
1773 }
1774
1775 SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
1776
1777 for (ch = 1; ch < nb_display_channels; ch++) {
1778 y = s->ytop + ch * h;
1779 fill_rectangle(s->xleft, y, s->width, 1);
1780 }
1781 } else {
1782 int err = 0;
1783 if (realloc_texture(&s->vis_texture, SDL_PIXELFORMAT_ARGB8888, s->width, s->height, SDL_BLENDMODE_NONE, 1) < 0)
1784 return;
1785
1786 if (s->xpos >= s->width)
1787 s->xpos = 0;
1788 nb_display_channels= FFMIN(nb_display_channels, 2);
1789 if (rdft_bits != s->rdft_bits) {
1790 const float rdft_scale = 1.0;
1791 av_tx_uninit(&s->rdft);
1792 av_freep(&s->real_data);
1793 av_freep(&s->rdft_data);
1794 s->rdft_bits = rdft_bits;
1795 s->real_data = av_malloc_array(nb_freq, 4 *sizeof(*s->real_data));
1796 s->rdft_data = av_malloc_array(nb_freq + 1, 2 *sizeof(*s->rdft_data));
1797 err = av_tx_init(&s->rdft, &s->rdft_fn, AV_TX_FLOAT_RDFT,
1798 0, 1 << rdft_bits, &rdft_scale, 0);
1799 }
1800 if (err < 0 || !s->rdft_data) {
1801 av_log(NULL, AV_LOG_ERROR, "Failed to allocate buffers for RDFT, switching to waves display\n");
1802 s->show_mode = SHOW_MODE_WAVES;
1803 } else {
1804 float *data_in[2];
1805 AVComplexFloat *data[2];
1806 SDL_Rect rect = {.x = s->xpos, .y = 0, .w = 1, .h = s->height};
1807 uint32_t *pixels;
1808 int pitch;
1809 for (ch = 0; ch < nb_display_channels; ch++) {
1810 data_in[ch] = s->real_data + 2 * nb_freq * ch;
1811 data[ch] = s->rdft_data + nb_freq * ch;
1812 i = i_start + ch;
1813 for (x = 0; x < 2 * nb_freq; x++) {
1814 double w = (x-nb_freq) * (1.0 / nb_freq);
1815 data_in[ch][x] = s->sample_array[i] * (1.0 - w * w);
1816 i += channels;
1817 if (i >= SAMPLE_ARRAY_SIZE)
1819 }
1820 s->rdft_fn(s->rdft, data[ch], data_in[ch], sizeof(float));
1821 data[ch][0].im = data[ch][nb_freq].re;
1822 data[ch][nb_freq].re = 0;
1823 }
1824 /* Least efficient way to do this, we should of course
1825 * directly access it but it is more than fast enough. */
1826 if (!SDL_LockTexture(s->vis_texture, &rect, (void **)&pixels, &pitch)) {
1827 pitch >>= 2;
1828 pixels += pitch * s->height;
1829 for (y = 0; y < s->height; y++) {
1830 double w = 1 / sqrt(nb_freq);
1831 int a = sqrt(w * sqrt(data[0][y].re * data[0][y].re + data[0][y].im * data[0][y].im));
1832 int b = (nb_display_channels == 2 ) ? sqrt(w * hypot(data[1][y].re, data[1][y].im))
1833 : a;
1834 a = FFMIN(a, 255);
1835 b = FFMIN(b, 255);
1836 pixels -= pitch;
1837 *pixels = (a << 16) + (b << 8) + ((a+b) >> 1);
1838 }
1839 SDL_UnlockTexture(s->vis_texture);
1840 }
1841 SDL_RenderCopy(renderer, s->vis_texture, NULL, NULL);
1842 }
1843 if (!s->paused)
1844 s->xpos++;
1845 }
1846}
1847
1848static void uninit_bsf_graph(AVFormatContext *ic, int stream_index)
1849{
1850 FormatContext *ici = ic->opaque;
1851 Stream *sti;
1852 StreamGroup *stgi;
1853
1854 if (stream_index >= ici->nb_streams)
1855 return;
1856
1857 sti = ici->streams[stream_index];
1858 sti->filter = NULL;
1859
1860 stgi = sti->group;
1861 if (stgi) {
1862 av_bsf_graph_free(&stgi->graph);
1863 stgi->sink = NULL;
1864
1865 for (int i = 0; i < stgi->stg->nb_streams; i++) {
1866 ici->streams[stgi->stg->streams[i]->index]->filter = NULL;
1867 ici->streams[stgi->stg->streams[i]->index]->group = NULL;
1868 }
1869 }
1870 sti->group = stgi;
1871}
1872
1873static void stream_component_close(VideoState *is, int stream_index)
1874{
1875 AVFormatContext *ic = is->ic;
1876
1877 AVCodecParameters *codecpar;
1878
1879 if (stream_index < 0 || stream_index >= ic->nb_streams)
1880 return;
1881 codecpar = ic->streams[stream_index]->codecpar;
1882
1883 uninit_bsf_graph(ic, stream_index);
1884
1885 switch (codecpar->codec_type) {
1886 case AVMEDIA_TYPE_AUDIO:
1887 decoder_abort(&is->auddec, &is->sampq);
1888 SDL_CloseAudioDevice(audio_dev);
1889 decoder_destroy(&is->auddec);
1890 swr_free(&is->swr_ctx);
1891 av_freep(&is->audio_buf1);
1892 is->audio_buf1_size = 0;
1893 is->audio_buf = NULL;
1894
1895 if (is->rdft) {
1896 av_tx_uninit(&is->rdft);
1897 av_freep(&is->real_data);
1898 av_freep(&is->rdft_data);
1899 is->rdft = NULL;
1900 is->rdft_bits = 0;
1901 }
1902 break;
1903 case AVMEDIA_TYPE_VIDEO:
1904 decoder_abort(&is->viddec, &is->pictq);
1905 decoder_destroy(&is->viddec);
1906 break;
1908 decoder_abort(&is->subdec, &is->subpq);
1909 decoder_destroy(&is->subdec);
1910 break;
1911 default:
1912 break;
1913 }
1914
1915 ic->streams[stream_index]->discard = AVDISCARD_ALL;
1916 switch (codecpar->codec_type) {
1917 case AVMEDIA_TYPE_AUDIO:
1918 is->audio_st = NULL;
1919 is->audio_stream = -1;
1920 break;
1921 case AVMEDIA_TYPE_VIDEO:
1922 is->video_st = NULL;
1923 is->video_stream = -1;
1924 break;
1926 is->subtitle_st = NULL;
1927 is->subtitle_stream = -1;
1928 break;
1929 default:
1930 break;
1931 }
1932}
1933
1935{
1936 /* XXX: use a special url_shutdown call to abort parse cleanly */
1937 is->abort_request = 1;
1938 SDL_WaitThread(is->read_tid, NULL);
1939
1940 /* close each stream */
1941 if (is->audio_stream >= 0)
1942 stream_component_close(is, is->audio_stream);
1943 if (is->video_stream >= 0)
1944 stream_component_close(is, is->video_stream);
1945 if (is->subtitle_stream >= 0)
1946 stream_component_close(is, is->subtitle_stream);
1947
1948 if (is->ic) {
1949 FormatContext *ici = is->ic->opaque;
1950 for (int i = 0; i < ici->nb_streams; i++)
1951 av_freep(&ici->streams[i]);
1952 av_freep(&ici->streams);
1953 for (int i = 0; i < ici->nb_stream_groups; i++)
1954 av_freep(&ici->stream_groups[i]);
1955 av_freep(&ici->stream_groups);
1956 av_freep(&is->ic->opaque);
1957 }
1958
1960
1961 packet_queue_destroy(&is->videoq);
1962 packet_queue_destroy(&is->audioq);
1963 packet_queue_destroy(&is->subtitleq);
1964
1965 /* free all pictures */
1966 frame_queue_destroy(&is->pictq);
1967 frame_queue_destroy(&is->sampq);
1968 frame_queue_destroy(&is->subpq);
1969 SDL_DestroyCond(is->continue_read_thread);
1970 sws_freeContext(is->sub_convert_ctx);
1971 av_free(is->filename);
1972 if (is->vis_texture)
1973 SDL_DestroyTexture(is->vis_texture);
1974 if (is->vid_texture)
1975 SDL_DestroyTexture(is->vid_texture);
1976 if (is->sub_texture)
1977 SDL_DestroyTexture(is->sub_texture);
1978 if (is->chapter_texture)
1979 SDL_DestroyTexture(is->chapter_texture);
1980 avfilter_graph_free(&is->chapter_graph);
1981 av_freep(&is->chapter_rows);
1982 av_free(is);
1983}
1984
1985static void do_exit(VideoState *is)
1986{
1987 if (is) {
1989 }
1990 if (renderer)
1991 SDL_DestroyRenderer(renderer);
1992 if (vk_renderer)
1994 if (window)
1995 SDL_DestroyWindow(window);
1996 uninit_opts();
1997 for (int i = 0; i < nb_vfilters; i++)
2005 if (show_status)
2006 printf("\n");
2007 SDL_Quit();
2008 av_log(NULL, AV_LOG_QUIET, "%s", "");
2009 exit(exit_status);
2010}
2011
2012static void sigterm_handler(int sig)
2013{
2015 if (++received_nb_signals > 3)
2016 exit(123);
2017}
2018
2020{
2021 SDL_Rect rect;
2022 int max_width = screen_width ? screen_width : INT_MAX;
2023 int max_height = screen_height ? screen_height : INT_MAX;
2024 if (max_width == INT_MAX && max_height == INT_MAX)
2025 max_height = height;
2026 calculate_display_rect(&rect, 0, 0, max_width, max_height, width, height, sar);
2029}
2030
2032{
2033 int w,h;
2034
2037
2038 if (!window_title)
2040 SDL_SetWindowTitle(window, window_title);
2041
2042 SDL_SetWindowSize(window, w, h);
2043 SDL_SetWindowPosition(window, screen_left, screen_top);
2044 if (is_full_screen)
2045 SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
2046 SDL_ShowWindow(window);
2047
2048 is->width = w;
2049 is->height = h;
2050
2051 return 0;
2052}
2053
2054/* display the current picture, if any */
2056{
2057 if (!is->width)
2058 video_open(is);
2059
2060 SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
2061 SDL_RenderClear(renderer);
2062 if (is->audio_st && is->show_mode != SHOW_MODE_VIDEO)
2064 else if (is->video_st)
2067 SDL_RenderPresent(renderer);
2068}
2069
2070static double get_clock(Clock *c)
2071{
2072 if (*c->queue_serial != c->serial)
2073 return NAN;
2074 if (c->paused) {
2075 return c->pts;
2076 } else {
2077 double time = av_gettime_relative() / 1000000.0;
2078 return c->pts_drift + time - (time - c->last_updated) * (1.0 - c->speed);
2079 }
2080}
2081
2082static void set_clock_at(Clock *c, double pts, int serial, double time)
2083{
2084 c->pts = pts;
2085 c->last_updated = time;
2086 c->pts_drift = c->pts - time;
2087 c->serial = serial;
2088}
2089
2090static void set_clock(Clock *c, double pts, int serial)
2091{
2092 double time = av_gettime_relative() / 1000000.0;
2093 set_clock_at(c, pts, serial, time);
2094}
2095
2096static void set_clock_speed(Clock *c, double speed)
2097{
2098 set_clock(c, get_clock(c), c->serial);
2099 c->speed = speed;
2100}
2101
2102static void init_clock(Clock *c, int *queue_serial)
2103{
2104 c->speed = 1.0;
2105 c->paused = 0;
2106 c->queue_serial = queue_serial;
2107 set_clock(c, NAN, -1);
2108}
2109
2110static void sync_clock_to_slave(Clock *c, Clock *slave)
2111{
2112 double clock = get_clock(c);
2113 double slave_clock = get_clock(slave);
2114 if (!isnan(slave_clock) && (isnan(clock) || fabs(clock - slave_clock) > AV_NOSYNC_THRESHOLD))
2115 set_clock(c, slave_clock, slave->serial);
2116}
2117
2119 if (is->av_sync_type == AV_SYNC_VIDEO_MASTER) {
2120 if (is->video_st)
2121 return AV_SYNC_VIDEO_MASTER;
2122 else
2123 return AV_SYNC_AUDIO_MASTER;
2124 } else if (is->av_sync_type == AV_SYNC_AUDIO_MASTER) {
2125 if (is->audio_st)
2126 return AV_SYNC_AUDIO_MASTER;
2127 else
2129 } else {
2131 }
2132}
2133
2134/* get the current master clock value */
2136{
2137 double val;
2138
2139 switch (get_master_sync_type(is)) {
2141 val = get_clock(&is->vidclk);
2142 break;
2144 val = get_clock(&is->audclk);
2145 break;
2146 default:
2147 val = get_clock(&is->extclk);
2148 break;
2149 }
2150 return val;
2151}
2152
2154 if (is->video_stream >= 0 && is->videoq.nb_packets <= EXTERNAL_CLOCK_MIN_FRAMES ||
2155 is->audio_stream >= 0 && is->audioq.nb_packets <= EXTERNAL_CLOCK_MIN_FRAMES) {
2157 } else if ((is->video_stream < 0 || is->videoq.nb_packets > EXTERNAL_CLOCK_MAX_FRAMES) &&
2158 (is->audio_stream < 0 || is->audioq.nb_packets > EXTERNAL_CLOCK_MAX_FRAMES)) {
2160 } else {
2161 double speed = is->extclk.speed;
2162 if (speed != 1.0)
2163 set_clock_speed(&is->extclk, speed + EXTERNAL_CLOCK_SPEED_STEP * (1.0 - speed) / fabs(1.0 - speed));
2164 }
2165}
2166
2167/* seek in the stream */
2168static void stream_seek(VideoState *is, int64_t pos, int64_t rel, int by_bytes)
2169{
2170 if (!is->seek_req) {
2171 is->seek_pos = pos;
2172 is->seek_rel = rel;
2173 is->seek_flags &= ~AVSEEK_FLAG_BYTE;
2174 if (by_bytes)
2175 is->seek_flags |= AVSEEK_FLAG_BYTE;
2176 is->seek_req = 1;
2177 SDL_CondSignal(is->continue_read_thread);
2178 }
2179}
2180
2181/* pause or resume the video */
2183{
2184 if (is->paused) {
2185 is->frame_timer += av_gettime_relative() / 1000000.0 - is->vidclk.last_updated;
2186 if (is->read_pause_return != AVERROR(ENOSYS)) {
2187 is->vidclk.paused = 0;
2188 }
2189 set_clock(&is->vidclk, get_clock(&is->vidclk), is->vidclk.serial);
2190 }
2191 set_clock(&is->extclk, get_clock(&is->extclk), is->extclk.serial);
2192 is->paused = is->audclk.paused = is->vidclk.paused = is->extclk.paused = !is->paused;
2193}
2194
2196{
2198 is->step = 0;
2199}
2200
2202{
2203 is->muted = !is->muted;
2204}
2205
2206static void update_volume(VideoState *is, int sign, double step)
2207{
2208 double volume_level = is->audio_volume ? (20 * log(is->audio_volume / (double)SDL_MIX_MAXVOLUME) / log(10)) : -1000.0;
2209 int new_volume = lrint(SDL_MIX_MAXVOLUME * pow(10.0, (volume_level + sign * step) / 20.0));
2210 is->audio_volume = av_clip(is->audio_volume == new_volume ? (is->audio_volume + sign) : new_volume, 0, SDL_MIX_MAXVOLUME);
2211}
2212
2214{
2215 /* if the stream is paused unpause it, then step */
2216 if (is->paused)
2218 is->step = 1;
2219}
2220
2221static double compute_target_delay(double delay, VideoState *is)
2222{
2223 double sync_threshold, diff = 0;
2224
2225 /* update delay to follow master synchronisation source */
2227 /* if video is slave, we try to correct big delays by
2228 duplicating or deleting a frame */
2229 diff = get_clock(&is->vidclk) - get_master_clock(is);
2230
2231 /* skip or repeat frame. We take into account the
2232 delay to compute the threshold. I still don't know
2233 if it is the best guess */
2234 sync_threshold = FFMAX(AV_SYNC_THRESHOLD_MIN, FFMIN(AV_SYNC_THRESHOLD_MAX, delay));
2235 if (!isnan(diff) && fabs(diff) < is->max_frame_duration) {
2236 if (diff <= -sync_threshold)
2237 delay = FFMAX(0, delay + diff);
2238 else if (diff >= sync_threshold && delay > AV_SYNC_FRAMEDUP_THRESHOLD)
2239 delay = delay + diff;
2240 else if (diff >= sync_threshold)
2241 delay = 2 * delay;
2242 }
2243 }
2244
2245 av_log(NULL, AV_LOG_TRACE, "video: delay=%0.3f A-V=%f\n",
2246 delay, -diff);
2247
2248 return delay;
2249}
2250
2251static double vp_duration(VideoState *is, Frame *vp, Frame *nextvp) {
2252 if (vp->serial == nextvp->serial) {
2253 double duration = nextvp->pts - vp->pts;
2254 if (isnan(duration) || duration <= 0 || duration > is->max_frame_duration)
2255 return vp->duration;
2256 else
2257 return duration;
2258 } else {
2259 return 0.0;
2260 }
2261}
2262
2263static void update_video_pts(VideoState *is, double pts, int serial)
2264{
2265 /* update current video pts */
2266 set_clock(&is->vidclk, pts, serial);
2267 sync_clock_to_slave(&is->extclk, &is->vidclk);
2268}
2269
2270/* called to display each frame */
2271static void video_refresh(void *opaque, double *remaining_time)
2272{
2273 VideoState *is = opaque;
2274 double time;
2275
2276 Frame *sp, *sp2;
2277
2278 if (!is->paused && get_master_sync_type(is) == AV_SYNC_EXTERNAL_CLOCK && is->realtime)
2280
2281 if (!display_disable && is->show_mode != SHOW_MODE_VIDEO && is->audio_st) {
2282 time = av_gettime_relative() / 1000000.0;
2283 if (is->force_refresh || is->last_vis_time + rdftspeed < time) {
2285 is->last_vis_time = time;
2286 }
2287 *remaining_time = FFMIN(*remaining_time, is->last_vis_time + rdftspeed - time);
2288 }
2289
2290 if (is->video_st) {
2291retry:
2292 if (frame_queue_nb_remaining(&is->pictq) == 0) {
2293 // nothing to do, no picture to display in the queue
2294 } else {
2295 double last_duration, duration, delay;
2296 Frame *vp, *lastvp;
2297
2298 /* dequeue the picture */
2299 lastvp = frame_queue_peek_last(&is->pictq);
2300 vp = frame_queue_peek(&is->pictq);
2301
2302 if (vp->serial != is->videoq.serial) {
2303 frame_queue_next(&is->pictq);
2304 goto retry;
2305 }
2306
2307 if (lastvp->serial != vp->serial)
2308 is->frame_timer = av_gettime_relative() / 1000000.0;
2309
2310 if (is->paused)
2311 goto display;
2312
2313 /* compute nominal last_duration */
2314 last_duration = vp_duration(is, lastvp, vp);
2315 delay = compute_target_delay(last_duration, is);
2316
2317 time= av_gettime_relative()/1000000.0;
2318 if (time < is->frame_timer + delay) {
2319 *remaining_time = FFMIN(is->frame_timer + delay - time, *remaining_time);
2320 goto display;
2321 }
2322
2323 is->frame_timer += delay;
2324 if (delay > 0 && time - is->frame_timer > AV_SYNC_THRESHOLD_MAX)
2325 is->frame_timer = time;
2326
2327 SDL_LockMutex(is->pictq.mutex);
2328 if (!isnan(vp->pts))
2329 update_video_pts(is, vp->pts, vp->serial);
2330 SDL_UnlockMutex(is->pictq.mutex);
2331
2332 if (frame_queue_nb_remaining(&is->pictq) > 1) {
2333 Frame *nextvp = frame_queue_peek_next(&is->pictq);
2334 duration = vp_duration(is, vp, nextvp);
2335 if(!is->step && (framedrop>0 || (framedrop && get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER)) && time > is->frame_timer + duration){
2336 is->frame_drops_late++;
2337 frame_queue_next(&is->pictq);
2338 goto retry;
2339 }
2340 }
2341
2342 if (is->subtitle_st) {
2343 while (frame_queue_nb_remaining(&is->subpq) > 0) {
2344 sp = frame_queue_peek(&is->subpq);
2345
2346 if (frame_queue_nb_remaining(&is->subpq) > 1)
2347 sp2 = frame_queue_peek_next(&is->subpq);
2348 else
2349 sp2 = NULL;
2350
2351 if (sp->serial != is->subtitleq.serial
2352 || (is->vidclk.pts > (sp->pts + ((float) sp->sub.end_display_time / 1000)))
2353 || (sp2 && is->vidclk.pts > (sp2->pts + ((float) sp2->sub.start_display_time / 1000))))
2354 {
2355 if (sp->uploaded) {
2356 int i;
2357 for (i = 0; i < sp->sub.num_rects; i++) {
2358 AVSubtitleRect *sub_rect = sp->sub.rects[i];
2359 uint8_t *pixels;
2360 int pitch, j;
2361
2362 if (!SDL_LockTexture(is->sub_texture, (SDL_Rect *)sub_rect, (void **)&pixels, &pitch)) {
2363 for (j = 0; j < sub_rect->h; j++, pixels += pitch)
2364 memset(pixels, 0, sub_rect->w << 2);
2365 SDL_UnlockTexture(is->sub_texture);
2366 }
2367 }
2368 }
2369 frame_queue_next(&is->subpq);
2370 } else {
2371 break;
2372 }
2373 }
2374 }
2375
2376 frame_queue_next(&is->pictq);
2377 is->force_refresh = 1;
2378
2379 if (is->step && !is->paused)
2381 }
2382display:
2383 /* display picture */
2384 if (!display_disable && is->force_refresh && is->show_mode == SHOW_MODE_VIDEO && is->pictq.rindex_shown)
2386 }
2387 is->force_refresh = 0;
2388 if (show_status) {
2389 AVBPrint buf;
2390 static int64_t last_time;
2391 int64_t cur_time;
2392 int aqsize, vqsize, sqsize;
2393 double av_diff;
2394
2395 cur_time = av_gettime_relative();
2396 if (!last_time || (cur_time - last_time) >= 30000) {
2397 aqsize = 0;
2398 vqsize = 0;
2399 sqsize = 0;
2400 if (is->audio_st)
2401 aqsize = is->audioq.size;
2402 if (is->video_st)
2403 vqsize = is->videoq.size;
2404 if (is->subtitle_st)
2405 sqsize = is->subtitleq.size;
2406 av_diff = 0;
2407 if (is->audio_st && is->video_st)
2408 av_diff = get_clock(&is->audclk) - get_clock(&is->vidclk);
2409 else if (is->video_st)
2410 av_diff = get_master_clock(is) - get_clock(&is->vidclk);
2411 else if (is->audio_st)
2412 av_diff = get_master_clock(is) - get_clock(&is->audclk);
2413
2415 av_bprintf(&buf,
2416 "%7.2f %s:%7.3f fd=%4d aq=%5dKB vq=%5dKB sq=%5dB \r",
2418 (is->audio_st && is->video_st) ? "A-V" : (is->video_st ? "M-V" : (is->audio_st ? "M-A" : " ")),
2419 av_diff,
2420 is->frame_drops_early + is->frame_drops_late,
2421 aqsize / 1024,
2422 vqsize / 1024,
2423 sqsize);
2424
2426 fprintf(stderr, "%s", buf.str);
2427 else
2428 av_log(NULL, AV_LOG_INFO, "%s", buf.str);
2429
2430 fflush(stderr);
2431 av_bprint_finalize(&buf, NULL);
2432
2433 last_time = cur_time;
2434 }
2435 }
2436}
2437
2438static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, double duration, int64_t pos, int serial)
2439{
2440 Frame *vp;
2441
2442#if defined(DEBUG_SYNC)
2443 printf("frame_type=%c pts=%0.3f\n",
2445#endif
2446
2447 if (!(vp = frame_queue_peek_writable(&is->pictq)))
2448 return -1;
2449
2450 vp->sar = src_frame->sample_aspect_ratio;
2451 vp->uploaded = 0;
2452
2453 vp->width = src_frame->width;
2454 vp->height = src_frame->height;
2455 vp->format = src_frame->format;
2456
2457 vp->pts = pts;
2458 vp->duration = duration;
2459 vp->pos = pos;
2460 vp->serial = serial;
2461
2462 set_default_window_size(vp->width, vp->height, vp->sar);
2463
2464 av_frame_move_ref(vp->frame, src_frame);
2465 frame_queue_push(&is->pictq);
2466 return 0;
2467}
2468
2470{
2471 int got_picture;
2472
2473 if ((got_picture = decoder_decode_frame(&is->viddec, frame, NULL)) < 0)
2474 return -1;
2475
2476 if (got_picture) {
2477 double dpts = NAN;
2478
2479 if (frame->pts != AV_NOPTS_VALUE)
2480 dpts = av_q2d(is->video_st->time_base) * frame->pts;
2481
2482 frame->sample_aspect_ratio = av_guess_sample_aspect_ratio(is->ic, is->video_st, frame);
2483
2485 if (frame->pts != AV_NOPTS_VALUE) {
2486 double diff = dpts - get_master_clock(is);
2487 if (!isnan(diff) && fabs(diff) < AV_NOSYNC_THRESHOLD &&
2488 diff - is->frame_last_filter_delay < 0 &&
2489 is->viddec.pkt_serial == is->vidclk.serial &&
2490 is->videoq.nb_packets) {
2491 is->frame_drops_early++;
2493 got_picture = 0;
2494 }
2495 }
2496 }
2497 }
2498
2499 return got_picture;
2500}
2501
2502static int configure_filtergraph(AVFilterGraph *graph, const char *filtergraph,
2503 AVFilterContext *source_ctx, AVFilterContext *sink_ctx)
2504{
2505 int ret, i;
2506 int nb_filters = graph->nb_filters;
2508
2509 if (filtergraph) {
2512 if (!outputs || !inputs) {
2513 ret = AVERROR(ENOMEM);
2514 goto fail;
2515 }
2516
2517 outputs->name = av_strdup("in");
2518 outputs->filter_ctx = source_ctx;
2519 outputs->pad_idx = 0;
2520 outputs->next = NULL;
2521
2522 inputs->name = av_strdup("out");
2523 inputs->filter_ctx = sink_ctx;
2524 inputs->pad_idx = 0;
2525 inputs->next = NULL;
2526
2527 if ((ret = avfilter_graph_parse_ptr(graph, filtergraph, &inputs, &outputs, NULL)) < 0)
2528 goto fail;
2529 } else {
2530 if ((ret = avfilter_link(source_ctx, 0, sink_ctx, 0)) < 0)
2531 goto fail;
2532 }
2533
2534 /* Reorder the filters to ensure that inputs of the custom filters are merged first */
2535 for (i = 0; i < graph->nb_filters - nb_filters; i++)
2536 FFSWAP(AVFilterContext*, graph->filters[i], graph->filters[i + nb_filters]);
2537
2538 ret = avfilter_graph_config(graph, NULL);
2539fail:
2542 return ret;
2543}
2544
2545static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const char *vfilters, AVFrame *frame)
2546{
2548 char sws_flags_str[512] = "";
2549 int ret;
2550 AVFilterContext *filt_src = NULL, *filt_out = NULL, *last_filter = NULL;
2551 AVCodecParameters *codecpar = is->video_st->codecpar;
2552 AVRational fr = av_guess_frame_rate(is->ic, is->video_st, NULL);
2553 const AVDictionaryEntry *e = NULL;
2554 int nb_pix_fmts = 0;
2555 int i, j;
2557
2558 if (!par)
2559 return AVERROR(ENOMEM);
2560
2561 for (i = 0; i < renderer_info.num_texture_formats; i++) {
2562 for (j = 0; j < FF_ARRAY_ELEMS(sdl_texture_format_map); j++) {
2563 if (renderer_info.texture_formats[i] == sdl_texture_format_map[j].texture_fmt) {
2564 pix_fmts[nb_pix_fmts++] = sdl_texture_format_map[j].format;
2565 break;
2566 }
2567 }
2568 }
2569
2570 while ((e = av_dict_iterate(sws_dict, e))) {
2571 if (!strcmp(e->key, "sws_flags")) {
2572 av_strlcatf(sws_flags_str, sizeof(sws_flags_str), "%s=%s:", "flags", e->value);
2573 } else
2574 av_strlcatf(sws_flags_str, sizeof(sws_flags_str), "%s=%s:", e->key, e->value);
2575 }
2576 if (strlen(sws_flags_str))
2577 sws_flags_str[strlen(sws_flags_str)-1] = '\0';
2578
2579 graph->scale_sws_opts = av_strdup(sws_flags_str);
2580
2581
2582 filt_src = avfilter_graph_alloc_filter(graph, avfilter_get_by_name("buffer"),
2583 "ffplay_buffer");
2584 if (!filt_src) {
2585 ret = AVERROR(ENOMEM);
2586 goto fail;
2587 }
2588
2589 par->format = frame->format;
2590 par->time_base = is->video_st->time_base;
2591 par->width = frame->width;
2592 par->height = frame->height;
2594 par->color_space = frame->colorspace;
2595 par->color_range = frame->color_range;
2596 par->alpha_mode = frame->alpha_mode;
2597 par->frame_rate = fr;
2598 par->hw_frames_ctx = frame->hw_frames_ctx;
2599 ret = av_buffersrc_parameters_set(filt_src, par);
2600 if (ret < 0)
2601 goto fail;
2602
2603 ret = avfilter_init_dict(filt_src, NULL);
2604 if (ret < 0)
2605 goto fail;
2606
2607 filt_out = avfilter_graph_alloc_filter(graph, avfilter_get_by_name("buffersink"),
2608 "ffplay_buffersink");
2609 if (!filt_out) {
2610 ret = AVERROR(ENOMEM);
2611 goto fail;
2612 }
2613
2614 if ((ret = av_opt_set_array(filt_out, "pixel_formats", AV_OPT_SEARCH_CHILDREN,
2615 0, nb_pix_fmts, AV_OPT_TYPE_PIXEL_FMT, pix_fmts)) < 0)
2616 goto fail;
2617 if (!vk_renderer &&
2618 (ret = av_opt_set_array(filt_out, "colorspaces", AV_OPT_SEARCH_CHILDREN,
2621 goto fail;
2622
2623 if ((ret = av_opt_set_array(filt_out, "alphamodes", AV_OPT_SEARCH_CHILDREN,
2626 goto fail;
2627
2628 ret = avfilter_init_dict(filt_out, NULL);
2629 if (ret < 0)
2630 goto fail;
2631
2632 last_filter = filt_out;
2633
2634/* Note: this macro adds a filter before the lastly added filter, so the
2635 * processing order of the filters is in reverse */
2636#define INSERT_FILT(name, arg) do { \
2637 AVFilterContext *filt_ctx; \
2638 \
2639 ret = avfilter_graph_create_filter(&filt_ctx, \
2640 avfilter_get_by_name(name), \
2641 "ffplay_" name, arg, NULL, graph); \
2642 if (ret < 0) \
2643 goto fail; \
2644 \
2645 ret = avfilter_link(filt_ctx, 0, last_filter, 0); \
2646 if (ret < 0) \
2647 goto fail; \
2648 \
2649 last_filter = filt_ctx; \
2650} while (0)
2651
2652 if (autorotate) {
2653 double theta = 0.0;
2654 int32_t *displaymatrix = NULL;
2656 if (sd)
2657 displaymatrix = (int32_t *)sd->data;
2658 if (!displaymatrix) {
2659 const AVPacketSideData *psd = av_packet_side_data_get(is->video_st->codecpar->coded_side_data,
2660 is->video_st->codecpar->nb_coded_side_data,
2662 if (psd)
2663 displaymatrix = (int32_t *)psd->data;
2664 }
2665 theta = get_rotation(displaymatrix);
2666
2667 if (fabs(theta - 90) < 1.0) {
2668 INSERT_FILT("transpose", displaymatrix[3] > 0 ? "cclock_flip" : "clock");
2669 } else if (fabs(theta - 180) < 1.0) {
2670 if (displaymatrix[0] < 0)
2671 INSERT_FILT("hflip", NULL);
2672 if (displaymatrix[4] < 0)
2673 INSERT_FILT("vflip", NULL);
2674 } else if (fabs(theta - 270) < 1.0) {
2675 INSERT_FILT("transpose", displaymatrix[3] < 0 ? "clock_flip" : "cclock");
2676 } else if (fabs(theta) > 1.0) {
2677 char rotate_buf[64];
2678 snprintf(rotate_buf, sizeof(rotate_buf), "%f*PI/180", theta);
2679 INSERT_FILT("rotate", rotate_buf);
2680 } else {
2681 if (displaymatrix && displaymatrix[4] < 0)
2682 INSERT_FILT("vflip", NULL);
2683 }
2684 }
2685
2686 if ((ret = configure_filtergraph(graph, vfilters, filt_src, last_filter)) < 0)
2687 goto fail;
2688
2689 is->in_video_filter = filt_src;
2690 is->out_video_filter = filt_out;
2691
2692fail:
2693 av_freep(&par);
2694 return ret;
2695}
2696
2697static int configure_audio_filters(VideoState *is, const char *afilters, int force_output_format)
2698{
2699 AVFilterContext *filt_asrc = NULL, *filt_asink = NULL;
2700 char aresample_swr_opts[512] = "";
2701 const AVDictionaryEntry *e = NULL;
2702 AVBPrint bp;
2703 char asrc_args[256];
2704 int ret;
2705
2706 avfilter_graph_free(&is->agraph);
2707 if (!(is->agraph = avfilter_graph_alloc()))
2708 return AVERROR(ENOMEM);
2709 is->agraph->nb_threads = filter_nbthreads;
2710
2712
2713 while ((e = av_dict_iterate(swr_opts, e)))
2714 av_strlcatf(aresample_swr_opts, sizeof(aresample_swr_opts), "%s=%s:", e->key, e->value);
2715 if (strlen(aresample_swr_opts))
2716 aresample_swr_opts[strlen(aresample_swr_opts)-1] = '\0';
2717 av_opt_set(is->agraph, "aresample_swr_opts", aresample_swr_opts, 0);
2718
2719 av_channel_layout_describe_bprint(&is->audio_filter_src.ch_layout, &bp);
2720
2721 ret = snprintf(asrc_args, sizeof(asrc_args),
2722 "sample_rate=%d:sample_fmt=%s:time_base=%d/%d:channel_layout=%s",
2723 is->audio_filter_src.freq, av_get_sample_fmt_name(is->audio_filter_src.fmt),
2724 1, is->audio_filter_src.freq, bp.str);
2725
2726 ret = avfilter_graph_create_filter(&filt_asrc,
2727 avfilter_get_by_name("abuffer"), "ffplay_abuffer",
2728 asrc_args, NULL, is->agraph);
2729 if (ret < 0)
2730 goto end;
2731
2732 filt_asink = avfilter_graph_alloc_filter(is->agraph, avfilter_get_by_name("abuffersink"),
2733 "ffplay_abuffersink");
2734 if (!filt_asink) {
2735 ret = AVERROR(ENOMEM);
2736 goto end;
2737 }
2738
2739 if ((ret = av_opt_set(filt_asink, "sample_formats", "s16", AV_OPT_SEARCH_CHILDREN)) < 0)
2740 goto end;
2741
2742 if (force_output_format) {
2743 if ((ret = av_opt_set_array(filt_asink, "channel_layouts", AV_OPT_SEARCH_CHILDREN,
2744 0, 1, AV_OPT_TYPE_CHLAYOUT, &is->audio_tgt.ch_layout)) < 0)
2745 goto end;
2746 if ((ret = av_opt_set_array(filt_asink, "samplerates", AV_OPT_SEARCH_CHILDREN,
2747 0, 1, AV_OPT_TYPE_INT, &is->audio_tgt.freq)) < 0)
2748 goto end;
2749 }
2750
2751 ret = avfilter_init_dict(filt_asink, NULL);
2752 if (ret < 0)
2753 goto end;
2754
2755 if ((ret = configure_filtergraph(is->agraph, afilters, filt_asrc, filt_asink)) < 0)
2756 goto end;
2757
2758 is->in_audio_filter = filt_asrc;
2759 is->out_audio_filter = filt_asink;
2760
2761end:
2762 if (ret < 0)
2763 avfilter_graph_free(&is->agraph);
2765
2766 return ret;
2767}
2768
2769static int audio_thread(void *arg)
2770{
2771 VideoState *is = arg;
2773 Frame *af;
2774 int last_serial = -1;
2775 int reconfigure;
2776 int got_frame = 0;
2777 AVRational tb;
2778 int ret = 0;
2779
2780 if (!frame)
2781 return AVERROR(ENOMEM);
2782
2783 do {
2784 if ((got_frame = decoder_decode_frame(&is->auddec, frame, NULL)) < 0)
2785 goto the_end;
2786
2787 if (got_frame) {
2788 tb = (AVRational){1, frame->sample_rate};
2789
2790 reconfigure =
2791 cmp_audio_fmts(is->audio_filter_src.fmt, is->audio_filter_src.ch_layout.nb_channels,
2792 frame->format, frame->ch_layout.nb_channels) ||
2793 av_channel_layout_compare(&is->audio_filter_src.ch_layout, &frame->ch_layout) ||
2794 is->audio_filter_src.freq != frame->sample_rate ||
2795 is->auddec.pkt_serial != last_serial;
2796
2797 if (reconfigure) {
2798 char buf1[1024], buf2[1024];
2799 av_channel_layout_describe(&is->audio_filter_src.ch_layout, buf1, sizeof(buf1));
2800 av_channel_layout_describe(&frame->ch_layout, buf2, sizeof(buf2));
2802 "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",
2803 is->audio_filter_src.freq, is->audio_filter_src.ch_layout.nb_channels, av_get_sample_fmt_name(is->audio_filter_src.fmt), buf1, last_serial,
2804 frame->sample_rate, frame->ch_layout.nb_channels, av_get_sample_fmt_name(frame->format), buf2, is->auddec.pkt_serial);
2805
2806 is->audio_filter_src.fmt = frame->format;
2807 ret = av_channel_layout_copy(&is->audio_filter_src.ch_layout, &frame->ch_layout);
2808 if (ret < 0)
2809 goto the_end;
2810 is->audio_filter_src.freq = frame->sample_rate;
2811 last_serial = is->auddec.pkt_serial;
2812
2813 if ((ret = configure_audio_filters(is, afilters, 1)) < 0)
2814 goto the_end;
2815 }
2816
2817 if ((ret = av_buffersrc_add_frame(is->in_audio_filter, frame)) < 0)
2818 goto the_end;
2819
2820 while ((ret = av_buffersink_get_frame_flags(is->out_audio_filter, frame, 0)) >= 0) {
2821 FrameData *fd = frame->opaque_ref ? (FrameData*)frame->opaque_ref->data : NULL;
2822 tb = av_buffersink_get_time_base(is->out_audio_filter);
2823 if (!(af = frame_queue_peek_writable(&is->sampq)))
2824 goto the_end;
2825
2826 af->pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb);
2827 af->pos = fd ? fd->pkt_pos : -1;
2828 af->serial = is->auddec.pkt_serial;
2829 af->duration = av_q2d((AVRational){frame->nb_samples, frame->sample_rate});
2830
2832 frame_queue_push(&is->sampq);
2833
2834 if (is->audioq.serial != is->auddec.pkt_serial)
2835 break;
2836 }
2837 if (ret == AVERROR_EOF)
2838 is->auddec.finished = is->auddec.pkt_serial;
2839 }
2840 } while (ret >= 0 || ret == AVERROR(EAGAIN) || ret == AVERROR_EOF);
2841 the_end:
2842 avfilter_graph_free(&is->agraph);
2844 return ret;
2845}
2846
2847static int decoder_start(Decoder *d, int (*fn)(void *), const char *thread_name, void* arg)
2848{
2850 d->decoder_tid = SDL_CreateThread(fn, thread_name, arg);
2851 if (!d->decoder_tid) {
2852 av_log(NULL, AV_LOG_ERROR, "SDL_CreateThread(): %s\n", SDL_GetError());
2853 return AVERROR(ENOMEM);
2854 }
2855 return 0;
2856}
2857
2858static int video_thread(void *arg)
2859{
2860 VideoState *is = arg;
2862 double pts;
2863 double duration;
2864 int ret;
2865 AVRational tb = is->video_st->time_base;
2866 AVRational frame_rate = av_guess_frame_rate(is->ic, is->video_st, NULL);
2867
2868 AVFilterGraph *graph = NULL;
2869 AVFilterContext *filt_out = NULL, *filt_in = NULL;
2870 int last_w = 0;
2871 int last_h = 0;
2872 enum AVPixelFormat last_format = -2;
2873 int last_serial = -1;
2874 int last_vfilter_idx = 0;
2875
2876 if (!frame)
2877 return AVERROR(ENOMEM);
2878
2879 for (;;) {
2880 ret = get_video_frame(is, frame);
2881 if (ret < 0)
2882 goto the_end;
2883 if (!ret)
2884 continue;
2885
2886 if ( last_w != frame->width
2887 || last_h != frame->height
2888 || last_format != frame->format
2889 || last_serial != is->viddec.pkt_serial
2890 || last_vfilter_idx != is->vfilter_idx) {
2892 "Video frame changed from size:%dx%d format:%s serial:%d to size:%dx%d format:%s serial:%d\n",
2893 last_w, last_h,
2894 (const char *)av_x_if_null(av_get_pix_fmt_name(last_format), "none"), last_serial,
2895 frame->width, frame->height,
2896 (const char *)av_x_if_null(av_get_pix_fmt_name(frame->format), "none"), is->viddec.pkt_serial);
2897 avfilter_graph_free(&graph);
2898 graph = avfilter_graph_alloc();
2899 if (!graph) {
2900 ret = AVERROR(ENOMEM);
2901 goto the_end;
2902 }
2904 if ((ret = configure_video_filters(graph, is, vfilters_list ? vfilters_list[is->vfilter_idx] : NULL, frame)) < 0) {
2905 SDL_Event event;
2906 event.type = FF_QUIT_EVENT;
2907 event.user.data1 = is;
2908 SDL_PushEvent(&event);
2909 goto the_end;
2910 }
2911 filt_in = is->in_video_filter;
2912 filt_out = is->out_video_filter;
2913 last_w = frame->width;
2914 last_h = frame->height;
2915 last_format = frame->format;
2916 last_serial = is->viddec.pkt_serial;
2917 last_vfilter_idx = is->vfilter_idx;
2918 frame_rate = av_buffersink_get_frame_rate(filt_out);
2919 }
2920
2921 ret = av_buffersrc_add_frame(filt_in, frame);
2922 if (ret < 0)
2923 goto the_end;
2924
2925 while (ret >= 0) {
2926 FrameData *fd;
2927
2928 is->frame_last_returned_time = av_gettime_relative() / 1000000.0;
2929
2930 ret = av_buffersink_get_frame_flags(filt_out, frame, 0);
2931 if (ret < 0) {
2932 if (ret == AVERROR_EOF)
2933 is->viddec.finished = is->viddec.pkt_serial;
2934 ret = 0;
2935 break;
2936 }
2937
2938 fd = frame->opaque_ref ? (FrameData*)frame->opaque_ref->data : NULL;
2939
2940 is->frame_last_filter_delay = av_gettime_relative() / 1000000.0 - is->frame_last_returned_time;
2941 if (fabs(is->frame_last_filter_delay) > AV_NOSYNC_THRESHOLD / 10.0)
2942 is->frame_last_filter_delay = 0;
2943 tb = av_buffersink_get_time_base(filt_out);
2944 duration = (frame_rate.num && frame_rate.den ? av_q2d((AVRational){frame_rate.den, frame_rate.num}) : 0);
2945 pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb);
2946 ret = queue_picture(is, frame, pts, duration, fd ? fd->pkt_pos : -1, is->viddec.pkt_serial);
2948 if (is->videoq.serial != is->viddec.pkt_serial)
2949 break;
2950 }
2951
2952 if (ret < 0)
2953 goto the_end;
2954 }
2955 the_end:
2956 avfilter_graph_free(&graph);
2958 return 0;
2959}
2960
2961static int subtitle_thread(void *arg)
2962{
2963 VideoState *is = arg;
2964 Frame *sp;
2965 int got_subtitle;
2966 double pts;
2967
2968 for (;;) {
2969 if (!(sp = frame_queue_peek_writable(&is->subpq)))
2970 return 0;
2971
2972 if ((got_subtitle = decoder_decode_frame(&is->subdec, NULL, &sp->sub)) < 0)
2973 break;
2974
2975 pts = 0;
2976
2977 if (got_subtitle && sp->sub.format == 0) {
2978 if (sp->sub.pts != AV_NOPTS_VALUE)
2979 pts = sp->sub.pts / (double)AV_TIME_BASE;
2980 sp->pts = pts;
2981 sp->serial = is->subdec.pkt_serial;
2982 sp->width = is->subdec.avctx->width;
2983 sp->height = is->subdec.avctx->height;
2984 sp->uploaded = 0;
2985
2986 /* now we can update the picture count */
2987 frame_queue_push(&is->subpq);
2988 } else if (got_subtitle) {
2989 avsubtitle_free(&sp->sub);
2990 }
2991 }
2992 return 0;
2993}
2994
2995/* copy samples for viewing in editor window */
2996static void update_sample_display(VideoState *is, short *samples, int samples_size)
2997{
2998 int size, len;
2999
3000 size = samples_size / sizeof(short);
3001 while (size > 0) {
3002 len = SAMPLE_ARRAY_SIZE - is->sample_array_index;
3003 if (len > size)
3004 len = size;
3005 memcpy(is->sample_array + is->sample_array_index, samples, len * sizeof(short));
3006 samples += len;
3007 is->sample_array_index += len;
3008 if (is->sample_array_index >= SAMPLE_ARRAY_SIZE)
3009 is->sample_array_index = 0;
3010 size -= len;
3011 }
3012}
3013
3014/* return the wanted number of samples to get better sync if sync_type is video
3015 * or external master clock */
3016static int synchronize_audio(VideoState *is, int nb_samples)
3017{
3018 int wanted_nb_samples = nb_samples;
3019
3020 /* if not master, then we try to remove or add samples to correct the clock */
3022 double diff, avg_diff;
3023 int min_nb_samples, max_nb_samples;
3024
3025 diff = get_clock(&is->audclk) - get_master_clock(is);
3026
3027 if (!isnan(diff) && fabs(diff) < AV_NOSYNC_THRESHOLD) {
3028 is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum;
3029 if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {
3030 /* not enough measures to have a correct estimate */
3031 is->audio_diff_avg_count++;
3032 } else {
3033 /* estimate the A-V difference */
3034 avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef);
3035
3036 if (fabs(avg_diff) >= is->audio_diff_threshold) {
3037 wanted_nb_samples = nb_samples + (int)(diff * is->audio_src.freq);
3038 min_nb_samples = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX) / 100));
3039 max_nb_samples = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX) / 100));
3040 wanted_nb_samples = av_clip(wanted_nb_samples, min_nb_samples, max_nb_samples);
3041 }
3042 av_log(NULL, AV_LOG_TRACE, "diff=%f adiff=%f sample_diff=%d apts=%0.3f %f\n",
3043 diff, avg_diff, wanted_nb_samples - nb_samples,
3044 is->audio_clock, is->audio_diff_threshold);
3045 }
3046 } else {
3047 /* too big difference : may be initial PTS errors, so
3048 reset A-V filter */
3049 is->audio_diff_avg_count = 0;
3050 is->audio_diff_cum = 0;
3051 }
3052 }
3053
3054 return wanted_nb_samples;
3055}
3056
3057/**
3058 * Decode one audio frame and return its uncompressed size.
3059 *
3060 * The processed audio frame is decoded, converted if required, and
3061 * stored in is->audio_buf, with size in bytes given by the return
3062 * value.
3063 */
3065{
3066 int data_size, resampled_data_size;
3067 av_unused double audio_clock0;
3068 int wanted_nb_samples;
3069 Frame *af;
3070
3071 if (is->paused)
3072 return -1;
3073
3074 do {
3075#if defined(_WIN32)
3076 while (frame_queue_nb_remaining(&is->sampq) == 0) {
3077 if ((av_gettime_relative() - audio_callback_time) > 1000000LL * is->audio_hw_buf_size / is->audio_tgt.bytes_per_sec / 2)
3078 return -1;
3079 av_usleep (1000);
3080 }
3081#endif
3082 if (!(af = frame_queue_peek_readable(&is->sampq)))
3083 return -1;
3084 frame_queue_next(&is->sampq);
3085 } while (af->serial != is->audioq.serial);
3086
3088 af->frame->nb_samples,
3089 af->frame->format, 1);
3090
3091 wanted_nb_samples = synchronize_audio(is, af->frame->nb_samples);
3092
3093 if (af->frame->format != is->audio_src.fmt ||
3094 av_channel_layout_compare(&af->frame->ch_layout, &is->audio_src.ch_layout) ||
3095 af->frame->sample_rate != is->audio_src.freq ||
3096 (wanted_nb_samples != af->frame->nb_samples && !is->swr_ctx)) {
3097 int ret;
3098 swr_free(&is->swr_ctx);
3099 ret = swr_alloc_set_opts2(&is->swr_ctx,
3100 &is->audio_tgt.ch_layout, is->audio_tgt.fmt, is->audio_tgt.freq,
3101 &af->frame->ch_layout, af->frame->format, af->frame->sample_rate,
3102 0, NULL);
3103 if (ret < 0 || swr_init(is->swr_ctx) < 0) {
3105 "Cannot create sample rate converter for conversion of %d Hz %s %d channels to %d Hz %s %d channels!\n",
3107 is->audio_tgt.freq, av_get_sample_fmt_name(is->audio_tgt.fmt), is->audio_tgt.ch_layout.nb_channels);
3108 swr_free(&is->swr_ctx);
3109 return -1;
3110 }
3111 if (av_channel_layout_copy(&is->audio_src.ch_layout, &af->frame->ch_layout) < 0)
3112 return -1;
3113 is->audio_src.freq = af->frame->sample_rate;
3114 is->audio_src.fmt = af->frame->format;
3115 }
3116
3117 if (is->swr_ctx) {
3118 const uint8_t **in = (const uint8_t **)af->frame->extended_data;
3119 uint8_t **out = &is->audio_buf1;
3120 int out_count = (int64_t)wanted_nb_samples * is->audio_tgt.freq / af->frame->sample_rate + 256;
3121 int out_size = av_samples_get_buffer_size(NULL, is->audio_tgt.ch_layout.nb_channels, out_count, is->audio_tgt.fmt, 0);
3122 int len2;
3123 if (out_size < 0) {
3124 av_log(NULL, AV_LOG_ERROR, "av_samples_get_buffer_size() failed\n");
3125 return -1;
3126 }
3127 if (wanted_nb_samples != af->frame->nb_samples) {
3128 if (swr_set_compensation(is->swr_ctx, (wanted_nb_samples - af->frame->nb_samples) * is->audio_tgt.freq / af->frame->sample_rate,
3129 wanted_nb_samples * is->audio_tgt.freq / af->frame->sample_rate) < 0) {
3130 av_log(NULL, AV_LOG_ERROR, "swr_set_compensation() failed\n");
3131 return -1;
3132 }
3133 }
3134 av_fast_malloc(&is->audio_buf1, &is->audio_buf1_size, out_size);
3135 if (!is->audio_buf1)
3136 return AVERROR(ENOMEM);
3137 len2 = swr_convert(is->swr_ctx, out, out_count, in, af->frame->nb_samples);
3138 if (len2 < 0) {
3139 av_log(NULL, AV_LOG_ERROR, "swr_convert() failed\n");
3140 return -1;
3141 }
3142 if (len2 == out_count) {
3143 av_log(NULL, AV_LOG_WARNING, "audio buffer is probably too small\n");
3144 if (swr_init(is->swr_ctx) < 0)
3145 swr_free(&is->swr_ctx);
3146 }
3147 is->audio_buf = is->audio_buf1;
3148 resampled_data_size = len2 * is->audio_tgt.ch_layout.nb_channels * av_get_bytes_per_sample(is->audio_tgt.fmt);
3149 } else {
3150 is->audio_buf = af->frame->data[0];
3151 resampled_data_size = data_size;
3152 }
3153
3154 audio_clock0 = is->audio_clock;
3155 /* update the audio clock with the pts */
3156 if (!isnan(af->pts))
3157 is->audio_clock = af->pts + (double) af->frame->nb_samples / af->frame->sample_rate;
3158 else
3159 is->audio_clock = NAN;
3160 is->audio_clock_serial = af->serial;
3161#ifdef DEBUG
3162 {
3163 static double last_clock;
3164 printf("audio: delay=%0.3f clock=%0.3f clock0=%0.3f\n",
3165 is->audio_clock - last_clock,
3166 is->audio_clock, audio_clock0);
3167 last_clock = is->audio_clock;
3168 }
3169#endif
3170 return resampled_data_size;
3171}
3172
3173/* prepare a new audio buffer */
3174static void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
3175{
3176 VideoState *is = opaque;
3177 int audio_size, len1;
3178
3180
3181 while (len > 0) {
3182 if (is->audio_buf_index >= is->audio_buf_size) {
3183 audio_size = audio_decode_frame(is);
3184 if (audio_size < 0) {
3185 /* if error, just output silence */
3186 is->audio_buf = NULL;
3187 is->audio_buf_size = SDL_AUDIO_MIN_BUFFER_SIZE / is->audio_tgt.frame_size * is->audio_tgt.frame_size;
3188 } else {
3189 if (is->show_mode != SHOW_MODE_VIDEO)
3190 update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
3191 is->audio_buf_size = audio_size;
3192 }
3193 is->audio_buf_index = 0;
3194 }
3195 len1 = is->audio_buf_size - is->audio_buf_index;
3196 if (len1 > len)
3197 len1 = len;
3198 if (!is->muted && is->audio_buf && is->audio_volume == SDL_MIX_MAXVOLUME)
3199 memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
3200 else {
3201 memset(stream, 0, len1);
3202 if (!is->muted && is->audio_buf)
3203 SDL_MixAudioFormat(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, AUDIO_S16SYS, len1, is->audio_volume);
3204 }
3205 len -= len1;
3206 stream += len1;
3207 is->audio_buf_index += len1;
3208 }
3209 is->audio_write_buf_size = is->audio_buf_size - is->audio_buf_index;
3210 /* Let's assume the audio driver that is used by SDL has two periods. */
3211 if (!isnan(is->audio_clock)) {
3212 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);
3213 sync_clock_to_slave(&is->extclk, &is->audclk);
3214 }
3215}
3216
3217static int audio_open(void *opaque, AVChannelLayout *wanted_channel_layout, int wanted_sample_rate, struct AudioParams *audio_hw_params)
3218{
3219 SDL_AudioSpec wanted_spec, spec;
3220 const char *env;
3221 static const int next_nb_channels[] = {0, 0, 1, 6, 2, 6, 4, 6};
3222 static const int next_sample_rates[] = {0, 44100, 48000, 96000, 192000};
3223 int next_sample_rate_idx = FF_ARRAY_ELEMS(next_sample_rates) - 1;
3224 int wanted_nb_channels = wanted_channel_layout->nb_channels;
3225
3226 env = SDL_getenv("SDL_AUDIO_CHANNELS");
3227 if (env) {
3228 wanted_nb_channels = atoi(env);
3229 av_channel_layout_uninit(wanted_channel_layout);
3230 av_channel_layout_default(wanted_channel_layout, wanted_nb_channels);
3231 }
3232 if (wanted_channel_layout->order != AV_CHANNEL_ORDER_NATIVE) {
3233 av_channel_layout_uninit(wanted_channel_layout);
3234 av_channel_layout_default(wanted_channel_layout, wanted_nb_channels);
3235 }
3236 wanted_nb_channels = wanted_channel_layout->nb_channels;
3237 wanted_spec.channels = wanted_nb_channels;
3238 wanted_spec.freq = wanted_sample_rate;
3239 if (wanted_spec.freq <= 0 || wanted_spec.channels <= 0) {
3240 av_log(NULL, AV_LOG_ERROR, "Invalid sample rate or channel count!\n");
3241 return -1;
3242 }
3243 while (next_sample_rate_idx && next_sample_rates[next_sample_rate_idx] >= wanted_spec.freq)
3244 next_sample_rate_idx--;
3245 wanted_spec.format = AUDIO_S16SYS;
3246 wanted_spec.silence = 0;
3247 wanted_spec.samples = FFMAX(SDL_AUDIO_MIN_BUFFER_SIZE, 2 << av_log2(wanted_spec.freq / SDL_AUDIO_MAX_CALLBACKS_PER_SEC));
3248 wanted_spec.callback = sdl_audio_callback;
3249 wanted_spec.userdata = opaque;
3250 while (!(audio_dev = SDL_OpenAudioDevice(NULL, 0, &wanted_spec, &spec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE | SDL_AUDIO_ALLOW_CHANNELS_CHANGE))) {
3251 av_log(NULL, AV_LOG_WARNING, "SDL_OpenAudio (%d channels, %d Hz): %s\n",
3252 wanted_spec.channels, wanted_spec.freq, SDL_GetError());
3253 wanted_spec.channels = next_nb_channels[FFMIN(7, wanted_spec.channels)];
3254 if (!wanted_spec.channels) {
3255 wanted_spec.freq = next_sample_rates[next_sample_rate_idx--];
3256 wanted_spec.channels = wanted_nb_channels;
3257 if (!wanted_spec.freq) {
3259 "No more combinations to try, audio open failed\n");
3260 return -1;
3261 }
3262 }
3263 av_channel_layout_default(wanted_channel_layout, wanted_spec.channels);
3264 }
3265 if (spec.format != AUDIO_S16SYS) {
3267 "SDL advised audio format %d is not supported!\n", spec.format);
3268 return -1;
3269 }
3270 if (spec.channels != wanted_spec.channels) {
3271 av_channel_layout_uninit(wanted_channel_layout);
3272 av_channel_layout_default(wanted_channel_layout, spec.channels);
3273 if (wanted_channel_layout->order != AV_CHANNEL_ORDER_NATIVE) {
3275 "SDL advised channel count %d is not supported!\n", spec.channels);
3276 return -1;
3277 }
3278 }
3279
3280 audio_hw_params->fmt = AV_SAMPLE_FMT_S16;
3281 audio_hw_params->freq = spec.freq;
3282 if (av_channel_layout_copy(&audio_hw_params->ch_layout, wanted_channel_layout) < 0)
3283 return -1;
3284 audio_hw_params->frame_size = av_samples_get_buffer_size(NULL, audio_hw_params->ch_layout.nb_channels, 1, audio_hw_params->fmt, 1);
3285 audio_hw_params->bytes_per_sec = av_samples_get_buffer_size(NULL, audio_hw_params->ch_layout.nb_channels, audio_hw_params->freq, audio_hw_params->fmt, 1);
3286 if (audio_hw_params->bytes_per_sec <= 0 || audio_hw_params->frame_size <= 0) {
3287 av_log(NULL, AV_LOG_ERROR, "av_samples_get_buffer_size failed\n");
3288 return -1;
3289 }
3290 return spec.size;
3291}
3292
3293static int create_hwaccel(AVBufferRef **device_ctx)
3294{
3295 enum AVHWDeviceType type;
3296 int ret;
3297 AVBufferRef *vk_dev;
3298
3299 *device_ctx = NULL;
3300
3301 if (!hwaccel)
3302 return 0;
3303
3306 return AVERROR(ENOTSUP);
3307
3308 if (!vk_renderer) {
3309 av_log(NULL, AV_LOG_ERROR, "Vulkan renderer is not available\n");
3310 return AVERROR(ENOTSUP);
3311 }
3312
3313 ret = vk_renderer_get_hw_dev(vk_renderer, &vk_dev);
3314 if (ret < 0)
3315 return ret;
3316
3317 ret = av_hwdevice_ctx_create_derived(device_ctx, type, vk_dev, 0);
3318 if (!ret)
3319 return 0;
3320
3321 if (ret != AVERROR(ENOSYS))
3322 return ret;
3323
3324 av_log(NULL, AV_LOG_WARNING, "Derive %s from vulkan not supported.\n", hwaccel);
3325 ret = av_hwdevice_ctx_create(device_ctx, type, NULL, NULL, 0);
3326 return ret;
3327}
3328
3329static int init_lcevc_graph(AVFormatContext *ic, int stream_index)
3330{
3331 FormatContext *ici = ic->opaque;
3332 StreamGroup *stgi = ici->streams[stream_index]->group;
3333 AVStreamGroup *stg = stgi->stg;
3334 const AVBitStreamFilter *filter, *lcevc_filter = av_bsf_get_by_name("lcevc_merge");
3336 int ret;
3337
3338 stgi->graph = av_bsf_graph_alloc();
3339 if (!stgi->graph)
3340 return AVERROR(ENOMEM);
3341
3343 AVStream *base_st = ic->streams[stream_index];
3344 AVStream *lcevc_st = stg->streams[lcevc->el_index];
3345 Stream *lcevc_sti = ici->streams[lcevc_st->index];
3346 Stream *base_sti = ici->streams[stream_index];
3347
3348 filter = av_bsf_get_by_name("source");
3349 ret = av_bsf_graph_alloc_filter(&base_sti->filter, filter, "lcevc_merge_base", stgi->graph);
3350 if (ret < 0)
3351 return ret;
3352 av_opt_set_q(base_sti->filter->priv_data, "time_base", base_st->time_base, 0);
3353 ret = av_bsf_source_parameters_set(base_sti->filter, base_st->codecpar);
3354 if (ret < 0)
3355 return ret;
3356
3357 ret = av_bsf_graph_alloc_filter(&lcevc_sti->filter, filter, "lcevc_merge_enhancement", stgi->graph);
3358 if (ret < 0)
3359 return ret;
3360 av_opt_set_q(lcevc_sti->filter->priv_data, "time_base", lcevc_st->time_base, 0);
3361 ret = av_bsf_source_parameters_set(lcevc_sti->filter, lcevc_st->codecpar);
3362 if (ret < 0)
3363 return ret;
3364
3365 ret = av_bsf_graph_alloc_filter(&lcevc_merge, lcevc_filter, "lcevc_merge", stgi->graph);
3366 if (ret < 0)
3367 return ret;
3368
3369 filter = av_bsf_get_by_name("sink");
3370 ret = av_bsf_graph_alloc_filter(&stgi->sink, filter, "lcevc_merge_sink", stgi->graph);
3371 if (ret < 0)
3372 return ret;
3373
3374 ret = av_bsf_init_dict(base_sti->filter, NULL);
3375 if (ret < 0)
3376 return ret;
3377 ret = av_bsf_init_dict(lcevc_sti->filter, NULL);
3378 if (ret < 0)
3379 return ret;
3381 if (ret < 0)
3382 return ret;
3383 ret = av_bsf_init_dict(stgi->sink, NULL);
3384 if (ret < 0)
3385 return ret;
3386
3387 ret = av_bsf_link(base_sti->filter, 0, lcevc_merge, 0);
3388 if (ret < 0)
3389 return ret;
3390 ret = av_bsf_link(lcevc_sti->filter, 0, lcevc_merge, 1);
3391 if (ret < 0)
3392 return ret;
3393 ret = av_bsf_link(lcevc_merge, 0, stgi->sink, 0);
3394 if (ret < 0)
3395 return ret;
3396
3397 ret = av_bsf_graph_config(stgi->graph, NULL);
3398 if (ret < 0)
3399 return ret;
3400
3401 lcevc_st->discard = AVDISCARD_DEFAULT;
3402 lcevc_sti->group = stgi;
3403
3404 return 0;
3405}
3406
3407/* open a given stream. Return 0 if OK */
3408static int stream_component_open(VideoState *is, int stream_index)
3409{
3410 AVFormatContext *ic = is->ic;
3411 FormatContext *ici = ic->opaque;
3412 AVCodecContext *avctx;
3413 const AVCodec *codec;
3414 const char *forced_codec_name = NULL;
3416 int sample_rate;
3417 AVChannelLayout ch_layout = { 0 };
3418 int ret = 0;
3419 int stream_lowres = lowres;
3420
3421 if (stream_index < 0 || stream_index >= ic->nb_streams)
3422 return -1;
3423
3425 if (!avctx)
3426 return AVERROR(ENOMEM);
3427
3428 ret = avcodec_parameters_to_context(avctx, ic->streams[stream_index]->codecpar);
3429 if (ret < 0)
3430 goto fail;
3431 avctx->pkt_timebase = ic->streams[stream_index]->time_base;
3432
3433 codec = avcodec_find_decoder(avctx->codec_id);
3434
3435 switch(avctx->codec_type){
3436 case AVMEDIA_TYPE_AUDIO : is->last_audio_stream = stream_index; forced_codec_name = audio_codec_name; break;
3437 case AVMEDIA_TYPE_SUBTITLE: is->last_subtitle_stream = stream_index; forced_codec_name = subtitle_codec_name; break;
3438 case AVMEDIA_TYPE_VIDEO : is->last_video_stream = stream_index; forced_codec_name = video_codec_name; break;
3439 }
3440 if (forced_codec_name)
3441 codec = avcodec_find_decoder_by_name(forced_codec_name);
3442 if (!codec) {
3443 if (forced_codec_name) av_log(NULL, AV_LOG_WARNING,
3444 "No codec could be found with name '%s'\n", forced_codec_name);
3446 "No decoder could be found for codec %s\n", avcodec_get_name(avctx->codec_id));
3447 ret = AVERROR(EINVAL);
3448 goto fail;
3449 }
3450
3451 avctx->codec_id = codec->id;
3452 if (stream_lowres > codec->max_lowres) {
3453 av_log(avctx, AV_LOG_WARNING, "The maximum value for lowres supported by the decoder is %d\n",
3454 codec->max_lowres);
3455 stream_lowres = codec->max_lowres;
3456 }
3457 avctx->lowres = stream_lowres;
3458
3459 if (fast)
3460 avctx->flags2 |= AV_CODEC_FLAG2_FAST;
3461
3462 ret = filter_codec_opts(codec_opts, avctx->codec_id, ic,
3463 ic->streams[stream_index], codec, &opts, NULL);
3464 if (ret < 0)
3465 goto fail;
3466
3467 if (!av_dict_get(opts, "threads", NULL, 0))
3468 av_dict_set(&opts, "threads", "auto", 0);
3469 if (stream_lowres)
3470 av_dict_set_int(&opts, "lowres", stream_lowres, 0);
3471
3472 av_dict_set(&opts, "flags", "+copy_opaque", AV_DICT_MULTIKEY);
3473
3474 if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) {
3475 ret = create_hwaccel(&avctx->hw_device_ctx);
3476 if (ret < 0)
3477 goto fail;
3478 }
3479
3480 if ((ret = avcodec_open2(avctx, codec, &opts)) < 0) {
3481 goto fail;
3482 }
3483 ret = check_avoptions(opts);
3484 if (ret < 0)
3485 goto fail;
3486
3487 is->eof = 0;
3488 ic->streams[stream_index]->discard = AVDISCARD_DEFAULT;
3489 switch (avctx->codec_type) {
3490 case AVMEDIA_TYPE_AUDIO:
3491 {
3492 AVFilterContext *sink;
3493
3494 is->audio_filter_src.freq = avctx->sample_rate;
3495 ret = av_channel_layout_copy(&is->audio_filter_src.ch_layout, &avctx->ch_layout);
3496 if (ret < 0)
3497 goto fail;
3498 is->audio_filter_src.fmt = avctx->sample_fmt;
3499 if ((ret = configure_audio_filters(is, afilters, 0)) < 0)
3500 goto fail;
3501 sink = is->out_audio_filter;
3502 sample_rate = av_buffersink_get_sample_rate(sink);
3503 ret = av_buffersink_get_ch_layout(sink, &ch_layout);
3504 if (ret < 0)
3505 goto fail;
3506 }
3507
3508 /* prepare audio output */
3509 if ((ret = audio_open(is, &ch_layout, sample_rate, &is->audio_tgt)) < 0)
3510 goto fail;
3511 is->audio_hw_buf_size = ret;
3512 is->audio_src = is->audio_tgt;
3513 is->audio_buf_size = 0;
3514 is->audio_buf_index = 0;
3515
3516 /* init averaging filter */
3517 is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
3518 is->audio_diff_avg_count = 0;
3519 /* since we do not have a precise anough audio FIFO fullness,
3520 we correct audio sync only if larger than this threshold */
3521 is->audio_diff_threshold = (double)(is->audio_hw_buf_size) / is->audio_tgt.bytes_per_sec;
3522
3523 is->audio_stream = stream_index;
3524 is->audio_st = ic->streams[stream_index];
3525
3526 if ((ret = decoder_init(&is->auddec, avctx, &is->audioq, is->continue_read_thread)) < 0)
3527 goto fail;
3528 if (is->ic->iformat->flags & AVFMT_NOTIMESTAMPS) {
3529 is->auddec.start_pts = is->audio_st->start_time;
3530 is->auddec.start_pts_tb = is->audio_st->time_base;
3531 }
3532 if ((ret = decoder_start(&is->auddec, audio_thread, "audio_decoder", is)) < 0)
3533 goto out;
3534 SDL_PauseAudioDevice(audio_dev, 0);
3535 break;
3536 case AVMEDIA_TYPE_VIDEO:
3537 is->video_stream = stream_index;
3538 is->video_st = ic->streams[stream_index];
3539
3540 if (ici->streams[stream_index]->group) {
3541 if ((ret = init_lcevc_graph(ic, stream_index)) < 0)
3542 goto fail;
3543 }
3544 if ((ret = decoder_init(&is->viddec, avctx, &is->videoq, is->continue_read_thread)) < 0)
3545 goto fail;
3546 if ((ret = decoder_start(&is->viddec, video_thread, "video_decoder", is)) < 0)
3547 goto out;
3548 is->queue_attachments_req = 1;
3549 break;
3551 is->subtitle_stream = stream_index;
3552 is->subtitle_st = ic->streams[stream_index];
3553
3554 if ((ret = decoder_init(&is->subdec, avctx, &is->subtitleq, is->continue_read_thread)) < 0)
3555 goto fail;
3556 if ((ret = decoder_start(&is->subdec, subtitle_thread, "subtitle_decoder", is)) < 0)
3557 goto out;
3558 break;
3559 default:
3560 break;
3561 }
3562 goto out;
3563
3564fail:
3565 avcodec_free_context(&avctx);
3566out:
3567 av_channel_layout_uninit(&ch_layout);
3569
3570 return ret;
3571}
3572
3573static int decode_interrupt_cb(void *ctx)
3574{
3575 VideoState *is = ctx;
3576 return is->abort_request;
3577}
3578
3579static int stream_has_enough_packets(AVStream *st, int stream_id, PacketQueue *queue) {
3580 return stream_id < 0 ||
3581 queue->abort_request ||
3583 queue->nb_packets > MIN_FRAMES && (!queue->duration || av_q2d(st->time_base) * queue->duration > 1.0);
3584}
3585
3587{
3588 if( !strcmp(s->iformat->name, "rtp")
3589 || !strcmp(s->iformat->name, "rtsp")
3590 || !strcmp(s->iformat->name, "sdp")
3591 )
3592 return 1;
3593
3594 if(s->pb && ( !strncmp(s->url, "rtp:", 4)
3595 || !strncmp(s->url, "udp:", 4)
3596 )
3597 )
3598 return 1;
3599 return 0;
3600}
3601
3603 Stream *sti, AVPacket *pkt)
3604{
3605 StreamGroup *stgi = sti->group;
3606 AVBitStreamFilterContext *source = sti->filter;
3607 int ret;
3608
3610 if (ret < 0) {
3611 if (pkt)
3613 av_log(NULL, AV_LOG_ERROR, "Error submitting a packet for filtering: %s\n",
3614 av_err2str(ret));
3615 return ret;
3616 }
3617
3618 while (1) {
3619 ret = av_bsf_sink_get_packet(stgi->sink, pkt, 0);
3620 if (ret == AVERROR(EAGAIN))
3621 return 0;
3622 else if (ret < 0) {
3623 if (ret != AVERROR_EOF)
3625 "Error applying bitstream filters to a packet: %s\n",
3626 av_err2str(ret));
3627 return ret;
3628 }
3629 pkt->time_base = av_bsf_sink_get_time_base(stgi->sink);
3630 packet_queue_put(&is->videoq, pkt);
3631 }
3632
3633 return 0;
3634}
3635
3637{
3638 FormatContext *ici = ic->opaque;
3639 int ret;
3640
3641 for (unsigned i = 0; i < ic->nb_streams; i++) {
3642 Stream *sti = ici->streams[i];
3643 StreamGroup *stgi = sti->group;
3644
3645 if (!stgi || !stgi->graph)
3646 continue;
3647
3648 ret = do_bsf_graph(ic, is, sti, NULL);
3649 ret = (ret == AVERROR_EOF) ? 0 : (ret < 0) ? ret : AVERROR_BUG;
3650 if (ret < 0) {
3651 av_log(NULL, AV_LOG_ERROR, "Error flushing BSFs: %s\n",
3652 av_err2str(ret));
3653 return ret;
3654 }
3655 }
3656
3657 return 0;
3658}
3659
3660/* this thread gets the stream from the disk or the network */
3661static int read_thread(void *arg)
3662{
3663 VideoState *is = arg;
3664 AVFormatContext *ic = NULL;
3665 FormatContext *ici = NULL;
3666 int err, i, ret;
3667 int st_index[AVMEDIA_TYPE_NB];
3668 AVPacket *pkt = NULL;
3669 int64_t stream_start_time;
3670 char metadata_description[96];
3671 int pkt_in_play_range = 0;
3672 const AVDictionaryEntry *t;
3673 SDL_mutex *wait_mutex = SDL_CreateMutex();
3674 int scan_all_pmts_set = 0;
3675 int64_t pkt_ts;
3676
3677 if (!wait_mutex) {
3678 av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError());
3679 ret = AVERROR(ENOMEM);
3680 goto fail;
3681 }
3682
3683 memset(st_index, -1, sizeof(st_index));
3684 is->eof = 0;
3685
3686 pkt = av_packet_alloc();
3687 if (!pkt) {
3688 av_log(NULL, AV_LOG_FATAL, "Could not allocate packet.\n");
3689 ret = AVERROR(ENOMEM);
3690 goto fail;
3691 }
3693 if (!ic) {
3694 av_log(NULL, AV_LOG_FATAL, "Could not allocate context.\n");
3695 ret = AVERROR(ENOMEM);
3696 goto fail;
3697 }
3698 ic->opaque = av_mallocz(sizeof(FormatContext));
3699 if (!ic->opaque) {
3700 av_log(NULL, AV_LOG_FATAL, "Could not allocate internal context.\n");
3701 ret = AVERROR(ENOMEM);
3702 goto fail;
3703 }
3706 if (!av_dict_get(format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE)) {
3707 av_dict_set(&format_opts, "scan_all_pmts", "1", AV_DICT_DONT_OVERWRITE);
3708 scan_all_pmts_set = 1;
3709 }
3710 err = avformat_open_input(&ic, is->filename, is->iformat, &format_opts);
3711 if (err < 0) {
3712 print_error(is->filename, err);
3713 ret = -1;
3714 goto fail;
3715 }
3716 if (scan_all_pmts_set)
3717 av_dict_set(&format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE);
3719
3721 if (ret < 0)
3722 goto fail;
3723 is->ic = ic;
3724
3725 if (genpts)
3726 ic->flags |= AVFMT_FLAG_GENPTS;
3727
3728 if (find_stream_info) {
3730 int orig_nb_streams = ic->nb_streams;
3731
3733 if (err < 0) {
3735 "Error setting up avformat_find_stream_info() options\n");
3736 ret = err;
3737 goto fail;
3738 }
3739
3741
3742 for (i = 0; i < orig_nb_streams; i++)
3743 av_dict_free(&opts[i]);
3744 av_freep(&opts);
3745
3746 if (err < 0) {
3748 "%s: could not find codec parameters\n", is->filename);
3749 ret = -1;
3750 goto fail;
3751 }
3752 }
3753
3754 if (ic->pb)
3755 ic->pb->eof_reached = 0; // FIXME hack, ffplay maybe should not use avio_feof() to test for the end
3756
3757 if (seek_by_bytes < 0)
3759 !!(ic->iformat->flags & AVFMT_TS_DISCONT) &&
3760 strcmp("ogg", ic->iformat->name);
3761
3762 is->max_frame_duration = (ic->iformat->flags & AVFMT_TS_DISCONT) ? 10.0 : 3600.0;
3763
3764 if (!window_title && (t = av_dict_get(ic->metadata, "title", NULL, 0)))
3765 window_title = av_asprintf("%s - %s", t->value, input_filename);
3766
3767 /* if seeking requested, we execute it */
3768 if (start_time != AV_NOPTS_VALUE) {
3769 int64_t timestamp;
3770
3771 timestamp = start_time;
3772 /* add the stream start time */
3773 if (ic->start_time != AV_NOPTS_VALUE)
3774 timestamp += ic->start_time;
3775 ret = avformat_seek_file(ic, -1, INT64_MIN, timestamp, INT64_MAX, 0);
3776 if (ret < 0) {
3777 av_log(NULL, AV_LOG_WARNING, "%s: could not seek to position %0.3f\n",
3778 is->filename, (double)timestamp / AV_TIME_BASE);
3779 }
3780 }
3781
3782 is->realtime = is_realtime(ic);
3783
3784 if (show_status) {
3785 fprintf(stderr, "\x1b[2K\r");
3786 av_dump_format(ic, 0, is->filename, 0);
3787 }
3788
3789 ici = ic->opaque;
3790 ici->streams = av_calloc(ic->nb_streams, sizeof(*ici->streams));
3791 if (!ici->streams) {
3792 av_log(NULL, AV_LOG_FATAL, "Could not allocate internal streams context.\n");
3793 ret = AVERROR(ENOMEM);
3794 goto fail;
3795 }
3796 ici->nb_streams = ic->nb_streams;
3797 for (i = 0; i < ic->nb_streams; i++) {
3798 AVStream *st = ic->streams[i];
3799 enum AVMediaType type = st->codecpar->codec_type;
3800 ici->streams[i] = av_mallocz(sizeof(Stream));
3801 if (!ici->streams[i]) {
3802 av_log(NULL, AV_LOG_FATAL, "Could not allocate internal stream context.\n");
3803 ret = AVERROR(ENOMEM);
3804 goto fail;
3805 }
3806 st->discard = AVDISCARD_ALL;
3807 if (type >= 0 && wanted_stream_spec[type] && st_index[type] == -1)
3809 st_index[type] = i;
3810 // Clear all pre-existing metadata update flags to avoid printing
3811 // initial metadata as update.
3813 }
3814 ici->stream_groups = av_calloc(ic->nb_stream_groups, sizeof(*ici->stream_groups));
3815 if (!ici->stream_groups) {
3816 av_log(NULL, AV_LOG_FATAL, "Could not allocate internal stream groups context.\n");
3817 ret = AVERROR(ENOMEM);
3818 goto fail;
3819 }
3821 for (i = 0; i < ic->nb_stream_groups; i++) {
3822 AVStreamGroup *stg = ic->stream_groups[i];
3823
3824 ici->stream_groups[i] = av_mallocz(sizeof(*ici->stream_groups[i]));
3825 if (!ici->stream_groups[i]) {
3826 av_log(NULL, AV_LOG_FATAL, "Could not allocate internal stream group.\n");
3827 ret = AVERROR(ENOMEM);
3828 goto fail;
3829 }
3830 ici->stream_groups[i]->stg = stg;
3831
3833 continue;
3834 if (!av_bsf_get_by_name("lcevc_merge") || stg->nb_streams != 2)
3835 continue;
3836
3838 const AVStream *base_st = ic->streams[stg->streams[!lcevc->el_index]->index];
3839 Stream *base_sti = ici->streams[base_st->index];
3840
3841 base_sti->group = ici->stream_groups[i];
3842 }
3844 for (i = 0; i < AVMEDIA_TYPE_NB; i++) {
3845 if (wanted_stream_spec[i] && st_index[i] == -1) {
3846 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));
3847 st_index[i] = INT_MAX;
3848 }
3849 }
3850
3851 if (!video_disable)
3852 st_index[AVMEDIA_TYPE_VIDEO] =
3854 st_index[AVMEDIA_TYPE_VIDEO], -1, NULL, 0);
3855 if (!audio_disable)
3856 st_index[AVMEDIA_TYPE_AUDIO] =
3858 st_index[AVMEDIA_TYPE_AUDIO],
3859 st_index[AVMEDIA_TYPE_VIDEO],
3860 NULL, 0);
3862 st_index[AVMEDIA_TYPE_SUBTITLE] =
3864 st_index[AVMEDIA_TYPE_SUBTITLE],
3865 (st_index[AVMEDIA_TYPE_AUDIO] >= 0 ?
3866 st_index[AVMEDIA_TYPE_AUDIO] :
3867 st_index[AVMEDIA_TYPE_VIDEO]),
3868 NULL, 0);
3869
3870 is->show_mode = show_mode;
3871 if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) {
3872 AVStream *st = ic->streams[st_index[AVMEDIA_TYPE_VIDEO]];
3873 AVCodecParameters *codecpar = st->codecpar;
3875 if (codecpar->width)
3876 set_default_window_size(codecpar->width, codecpar->height, sar);
3877 }
3878
3879 /* open the streams */
3880 if (st_index[AVMEDIA_TYPE_AUDIO] >= 0) {
3882 }
3883
3884 ret = -1;
3885 if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) {
3887 }
3888 if (is->show_mode == SHOW_MODE_NONE)
3889 is->show_mode = ret >= 0 ? SHOW_MODE_VIDEO : SHOW_MODE_RDFT;
3890
3891 if (st_index[AVMEDIA_TYPE_SUBTITLE] >= 0) {
3893 }
3894
3895 if (is->video_stream < 0 && is->audio_stream < 0) {
3896 av_log(NULL, AV_LOG_FATAL, "Failed to open file '%s' or configure filtergraph\n",
3897 is->filename);
3898 ret = -1;
3899 goto fail;
3900 }
3901
3902 if (infinite_buffer < 0 && is->realtime)
3903 infinite_buffer = 1;
3904
3905 for (;;) {
3906 if (is->abort_request)
3907 break;
3908 if (is->paused != is->last_paused) {
3909 is->last_paused = is->paused;
3910 if (is->paused)
3911 is->read_pause_return = av_read_pause(ic);
3912 else
3913 av_read_play(ic);
3914 }
3915#if CONFIG_RTSP_DEMUXER || CONFIG_MMSH_PROTOCOL
3916 if (is->paused &&
3917 (!strcmp(ic->iformat->name, "rtsp") ||
3918 (ic->pb && !strncmp(input_filename, "mmsh:", 5)))) {
3919 /* wait 10 ms to avoid trying to get another packet */
3920 /* XXX: horrible */
3921 SDL_Delay(10);
3922 continue;
3923 }
3924#endif
3925 if (is->seek_req) {
3926 int64_t seek_target = is->seek_pos;
3927 int64_t seek_min = is->seek_rel > 0 ? seek_target - is->seek_rel + 2: INT64_MIN;
3928 int64_t seek_max = is->seek_rel < 0 ? seek_target - is->seek_rel - 2: INT64_MAX;
3929// FIXME the +-2 is due to rounding being not done in the correct direction in generation
3930// of the seek_pos/seek_rel variables
3931
3932 ret = avformat_seek_file(is->ic, -1, seek_min, seek_target, seek_max, is->seek_flags);
3933 if (ret < 0) {
3935 "%s: error while seeking\n", is->ic->url);
3936 } else {
3937 if (is->audio_stream >= 0)
3938 packet_queue_flush(&is->audioq);
3939 if (is->subtitle_stream >= 0)
3940 packet_queue_flush(&is->subtitleq);
3941 if (is->video_stream >= 0) {
3942 packet_queue_flush(&is->videoq);
3943 uninit_bsf_graph(is->ic, is->video_stream);
3944 if (ici->streams[is->video_stream]->group) {
3945 if ((ret = init_lcevc_graph(is->ic, is->video_stream)) < 0)
3946 goto fail;
3947 }
3948 }
3949 if (is->seek_flags & AVSEEK_FLAG_BYTE) {
3950 set_clock(&is->extclk, NAN, 0);
3951 } else {
3952 set_clock(&is->extclk, seek_target / (double)AV_TIME_BASE, 0);
3953 }
3954 }
3955 is->seek_req = 0;
3956 is->queue_attachments_req = 1;
3957 is->eof = 0;
3958 if (is->paused)
3960 }
3961 if (is->queue_attachments_req) {
3962 if (is->video_st && is->video_st->disposition & AV_DISPOSITION_ATTACHED_PIC) {
3963 if ((ret = av_packet_ref(pkt, &is->video_st->attached_pic)) < 0)
3964 goto fail;
3965 packet_queue_put(&is->videoq, pkt);
3966 packet_queue_put_nullpacket(&is->videoq, pkt, is->video_stream);
3967 }
3968 is->queue_attachments_req = 0;
3969 }
3970
3971 /* if the queue are full, no need to read more */
3972 if (infinite_buffer<1 &&
3973 (is->audioq.size + is->videoq.size + is->subtitleq.size > MAX_QUEUE_SIZE
3974 || (stream_has_enough_packets(is->audio_st, is->audio_stream, &is->audioq) &&
3975 stream_has_enough_packets(is->video_st, is->video_stream, &is->videoq) &&
3976 stream_has_enough_packets(is->subtitle_st, is->subtitle_stream, &is->subtitleq)))) {
3977 /* wait 10 ms */
3978 SDL_LockMutex(wait_mutex);
3979 SDL_CondWaitTimeout(is->continue_read_thread, wait_mutex, 10);
3980 SDL_UnlockMutex(wait_mutex);
3981 continue;
3982 }
3983 if (!is->paused &&
3984 (!is->audio_st || (is->auddec.finished == is->audioq.serial && frame_queue_nb_remaining(&is->sampq) == 0)) &&
3985 (!is->video_st || (is->viddec.finished == is->videoq.serial && frame_queue_nb_remaining(&is->pictq) == 0))) {
3986 if (loop != 1 && (!loop || --loop)) {
3988 } else if (autoexit) {
3989 ret = AVERROR_EOF;
3990 goto fail;
3991 }
3992 }
3993 ret = av_read_frame(ic, pkt);
3994 if (ret < 0) {
3995 if ((ret == AVERROR_EOF || avio_feof(ic->pb)) && !is->eof) {
3996 if (is->video_stream >= 0) {
3997 ret = do_bsf_flush(ic, is);
3998 if (ret < 0)
3999 goto fail;
4000 packet_queue_put_nullpacket(&is->videoq, pkt, is->video_stream);
4001 }
4002 if (is->audio_stream >= 0)
4003 packet_queue_put_nullpacket(&is->audioq, pkt, is->audio_stream);
4004 if (is->subtitle_stream >= 0)
4005 packet_queue_put_nullpacket(&is->subtitleq, pkt, is->subtitle_stream);
4006 is->eof = 1;
4007 }
4008 if (ic->pb && ic->pb->error) {
4009 if (autoexit)
4010 goto fail;
4011 else
4012 break;
4013 }
4014 SDL_LockMutex(wait_mutex);
4015 SDL_CondWaitTimeout(is->continue_read_thread, wait_mutex, 10);
4016 SDL_UnlockMutex(wait_mutex);
4017 continue;
4018 } else {
4019 is->eof = 0;
4020 }
4021
4022 if (show_status) {
4024 fprintf(stderr, "\x1b[2K\r");
4026 "\r New metadata", " ", AV_LOG_INFO);
4027 }
4028 if (ic->streams[pkt->stream_index]->event_flags &
4030 fprintf(stderr, "\x1b[2K\r");
4031 snprintf(metadata_description,
4032 sizeof(metadata_description),
4033 "\r New metadata for stream %d",
4034 pkt->stream_index);
4035 dump_dictionary(NULL, ic->streams[pkt->stream_index]->metadata,
4036 metadata_description, " ", AV_LOG_INFO);
4037 }
4038 }
4041
4042 /* check if packet is in play range specified by user, then queue, otherwise discard */
4043 stream_start_time = ic->streams[pkt->stream_index]->start_time;
4044 pkt_ts = pkt->pts == AV_NOPTS_VALUE ? pkt->dts : pkt->pts;
4045 pkt_in_play_range = duration == AV_NOPTS_VALUE ||
4046 (pkt_ts - (stream_start_time != AV_NOPTS_VALUE ? stream_start_time : 0)) *
4047 av_q2d(ic->streams[pkt->stream_index]->time_base) -
4048 (double)(start_time != AV_NOPTS_VALUE ? start_time : 0) / 1000000
4049 <= ((double)duration / 1000000);
4050 if (pkt->stream_index == is->audio_stream && pkt_in_play_range) {
4051 packet_queue_put(&is->audioq, pkt);
4052 } else if (pkt->stream_index == is->video_stream && pkt_in_play_range
4053 && !(is->video_st->disposition & AV_DISPOSITION_ATTACHED_PIC)) {
4054 Stream *sti = ici->streams[is->video_stream];
4055 StreamGroup *stgi = sti->group;
4056 if (stgi && stgi->graph) {
4057 ret = do_bsf_graph(ic, is, sti, pkt);
4058 if (ret < 0)
4059 goto fail;
4060 } else
4061 packet_queue_put(&is->videoq, pkt);
4062 } else if (pkt->stream_index == is->subtitle_stream && pkt_in_play_range) {
4063 packet_queue_put(&is->subtitleq, pkt);
4064 } else {
4065 Stream *sti = ici->streams[pkt->stream_index];
4066 StreamGroup *stgi = sti->group;
4067 if (stgi && stgi->graph) {
4068 ret = do_bsf_graph(ic, is, sti, pkt);
4069 if (ret < 0)
4070 goto fail;
4071 }
4073 }
4074 }
4075
4076 ret = 0;
4077 fail:
4078 if (ic && !is->ic) {
4079 av_freep(&ic->opaque);
4081 }
4082
4084 if (ret != 0) {
4085 SDL_Event event;
4086
4087 event.type = FF_QUIT_EVENT;
4088 event.user.data1 = is;
4089 SDL_PushEvent(&event);
4090 }
4091 SDL_DestroyMutex(wait_mutex);
4092 return 0;
4093}
4094
4095static VideoState *stream_open(const char *filename,
4096 const AVInputFormat *iformat)
4097{
4098 VideoState *is;
4099
4100 is = av_mallocz(sizeof(VideoState));
4101 if (!is)
4102 return NULL;
4103 is->last_video_stream = is->video_stream = -1;
4104 is->last_audio_stream = is->audio_stream = -1;
4105 is->last_subtitle_stream = is->subtitle_stream = -1;
4106 is->filename = av_strdup(filename);
4107 if (!is->filename)
4108 goto fail;
4109 is->iformat = iformat;
4110 is->ytop = 0;
4111 is->xleft = 0;
4112
4113 /* start video display */
4114 if (frame_queue_init(&is->pictq, &is->videoq, VIDEO_PICTURE_QUEUE_SIZE, 1) < 0)
4115 goto fail;
4116 if (frame_queue_init(&is->subpq, &is->subtitleq, SUBPICTURE_QUEUE_SIZE, 0) < 0)
4117 goto fail;
4118 if (frame_queue_init(&is->sampq, &is->audioq, SAMPLE_QUEUE_SIZE, 1) < 0)
4119 goto fail;
4120
4121 if (packet_queue_init(&is->videoq) < 0 ||
4122 packet_queue_init(&is->audioq) < 0 ||
4123 packet_queue_init(&is->subtitleq) < 0)
4124 goto fail;
4125
4126 if (!(is->continue_read_thread = SDL_CreateCond())) {
4127 av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError());
4128 goto fail;
4129 }
4130
4131 init_clock(&is->vidclk, &is->videoq.serial);
4132 init_clock(&is->audclk, &is->audioq.serial);
4133 init_clock(&is->extclk, &is->extclk.serial);
4134 is->audio_clock_serial = -1;
4135 if (startup_volume < 0)
4136 av_log(NULL, AV_LOG_WARNING, "-volume=%d < 0, setting to 0\n", startup_volume);
4137 if (startup_volume > 100)
4138 av_log(NULL, AV_LOG_WARNING, "-volume=%d > 100, setting to 100\n", startup_volume);
4139 if (video_background) {
4140 if (!strcmp(video_background, "none")) {
4141 is->render_params.video_background_type = VIDEO_BACKGROUND_NONE;
4142 } else if (strcmp(video_background, "tiles")) {
4143 if (av_parse_color(is->render_params.video_background_color, video_background, -1, NULL) >= 0)
4144 is->render_params.video_background_type = VIDEO_BACKGROUND_COLOR;
4145 else
4146 goto fail;
4147 }
4148 }
4150 startup_volume = av_clip(SDL_MIX_MAXVOLUME * startup_volume / 100, 0, SDL_MIX_MAXVOLUME);
4151 is->audio_volume = startup_volume;
4152 is->muted = 0;
4153 is->av_sync_type = av_sync_type;
4154 is->read_tid = SDL_CreateThread(read_thread, "read_thread", is);
4155 if (!is->read_tid) {
4156 av_log(NULL, AV_LOG_FATAL, "SDL_CreateThread(): %s\n", SDL_GetError());
4157fail:
4159 return NULL;
4160 }
4161 return is;
4162}
4163
4165{
4166 AVFormatContext *ic = is->ic;
4167 int start_index, stream_index;
4168 int old_index;
4169 AVStream *st;
4170 AVProgram *p = NULL;
4171 int nb_streams = is->ic->nb_streams;
4172
4174 start_index = is->last_video_stream;
4175 old_index = is->video_stream;
4176 } else if (codec_type == AVMEDIA_TYPE_AUDIO) {
4177 start_index = is->last_audio_stream;
4178 old_index = is->audio_stream;
4179 } else {
4180 start_index = is->last_subtitle_stream;
4181 old_index = is->subtitle_stream;
4182 }
4183 stream_index = start_index;
4184
4185 if (codec_type != AVMEDIA_TYPE_VIDEO && is->video_stream != -1) {
4186 p = av_find_program_from_stream(ic, NULL, is->video_stream);
4187 if (p) {
4188 nb_streams = p->nb_stream_indexes;
4189 for (start_index = 0; start_index < nb_streams; start_index++)
4190 if (p->stream_index[start_index] == stream_index)
4191 break;
4192 if (start_index == nb_streams)
4193 start_index = -1;
4194 stream_index = start_index;
4195 }
4196 }
4197
4198 for (;;) {
4199 if (++stream_index >= nb_streams)
4200 {
4202 {
4203 stream_index = -1;
4204 is->last_subtitle_stream = -1;
4205 goto the_end;
4206 }
4207 if (start_index == -1)
4208 return;
4209 stream_index = 0;
4210 }
4211 if (stream_index == start_index)
4212 return;
4213 st = is->ic->streams[p ? p->stream_index[stream_index] : stream_index];
4214 if (st->codecpar->codec_type == codec_type) {
4215 /* check that parameters are OK */
4216 switch (codec_type) {
4217 case AVMEDIA_TYPE_AUDIO:
4218 if (st->codecpar->sample_rate != 0 &&
4219 st->codecpar->ch_layout.nb_channels != 0)
4220 goto the_end;
4221 break;
4222 case AVMEDIA_TYPE_VIDEO:
4224 goto the_end;
4225 default:
4226 break;
4227 }
4228 }
4229 }
4230 the_end:
4231 if (p && stream_index != -1)
4232 stream_index = p->stream_index[stream_index];
4233 av_log(NULL, AV_LOG_INFO, "Switch %s stream from #%d to #%d\n",
4235 old_index,
4236 stream_index);
4237
4238 stream_component_close(is, old_index);
4239 stream_component_open(is, stream_index);
4240}
4241
4242
4244{
4246 SDL_SetWindowFullscreen(window, is_full_screen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
4247}
4248
4250{
4251 int next = is->show_mode;
4252 do {
4253 next = (next + 1) % SHOW_MODE_NB;
4254 } while (next != is->show_mode && (next == SHOW_MODE_VIDEO && !is->video_st || next != SHOW_MODE_VIDEO && !is->audio_st));
4255 if (is->show_mode != next) {
4256 is->force_refresh = 1;
4257 is->show_mode = next;
4258 }
4259}
4260
4261static void refresh_loop_wait_event(VideoState *is, SDL_Event *event) {
4262 double remaining_time = 0.0;
4263 SDL_PumpEvents();
4264 while (!SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)) {
4265 if (received_sigterm) {
4266 exit_status = 123;
4267 do_exit(is);
4268 }
4270 SDL_ShowCursor(0);
4271 cursor_hidden = 1;
4272 }
4273 if (remaining_time > 0.0)
4274 av_usleep((int64_t)(remaining_time * 1000000.0));
4275 remaining_time = REFRESH_RATE;
4276 if (is->chapter_render_pending || (chapter_list_visible(is) && current_chapter(is) != is->chapter_playing))
4278 if (chapter_list_alpha(is, av_gettime_relative()) != is->chapter_drawn_alpha)
4279 is->force_refresh = 1;
4280 if (is->show_mode != SHOW_MODE_NONE && (!is->paused || is->force_refresh))
4281 video_refresh(is, &remaining_time);
4282 SDL_PumpEvents();
4283 }
4284}
4285
4286/* index of the chapter containing the current playback position, -1 before the first one */
4288{
4290 int i;
4291
4292 for (i = 0; i < is->ic->nb_chapters; i++) {
4293 AVChapter *ch = is->ic->chapters[i];
4294 if (av_compare_ts(pos, AV_TIME_BASE_Q, ch->start, ch->time_base) < 0)
4295 break;
4296 }
4297 return i - 1;
4298}
4299
4300static void seek_chapter(VideoState *is, int i)
4301{
4302 i = FFMAX(i, 0);
4303 chapter_list_show(is, FFMIN(i, is->ic->nb_chapters - 1));
4304 if (i >= is->ic->nb_chapters)
4305 return;
4306
4307 av_log(NULL, AV_LOG_VERBOSE, "Seeking to chapter %d.\n", i);
4308 stream_seek(is, av_rescale_q(is->ic->chapters[i]->start, is->ic->chapters[i]->time_base,
4309 AV_TIME_BASE_Q), 0, 0);
4310}
4311
4312/* handle an event sent by the GUI */
4313static void event_loop(VideoState *cur_stream)
4314{
4315 SDL_Event event;
4316 double incr, pos, frac;
4317
4318 for (;;) {
4319 double x;
4320 refresh_loop_wait_event(cur_stream, &event);
4321 switch (event.type) {
4322 case SDL_KEYDOWN:
4323 if (exit_on_keydown || (!cur_stream->chapter_pinned &&
4324 (event.key.keysym.sym == SDLK_ESCAPE || event.key.keysym.sym == SDLK_q))) {
4325 do_exit(cur_stream);
4326 break;
4327 }
4328 // If we don't yet have a window, skip all key events, because read_thread might still be initializing...
4329 if (!cur_stream->width)
4330 continue;
4331 if (cur_stream->chapter_pinned) {
4332 chapter_list_key(cur_stream, event.key.keysym.sym);
4333 break;
4334 }
4335 switch (event.key.keysym.sym) {
4336 case SDLK_f:
4337 toggle_full_screen(cur_stream);
4338 cur_stream->force_refresh = 1;
4339 break;
4340 case SDLK_p:
4341 case SDLK_SPACE:
4342 toggle_pause(cur_stream);
4343 break;
4344 case SDLK_m:
4345 toggle_mute(cur_stream);
4346 break;
4347 case SDLK_KP_MULTIPLY:
4348 case SDLK_0:
4349 update_volume(cur_stream, 1, SDL_VOLUME_STEP);
4350 break;
4351 case SDLK_KP_DIVIDE:
4352 case SDLK_9:
4353 update_volume(cur_stream, -1, SDL_VOLUME_STEP);
4354 break;
4355 case SDLK_s: // S: Step to next frame
4356 step_to_next_frame(cur_stream);
4357 break;
4358 case SDLK_a:
4360 break;
4361 case SDLK_v:
4363 break;
4364 case SDLK_c:
4368 break;
4369 case SDLK_t:
4371 break;
4372 case SDLK_l:
4373 cur_stream->chapter_pin_requested = cur_stream->ic->nb_chapters > 0;
4374 break;
4375 case SDLK_RETURN:
4376 case SDLK_KP_ENTER:
4377 if (chapter_list_visible(cur_stream) && cur_stream->nb_chapter_rows)
4378 seek_chapter(cur_stream, cur_stream->chapter_rows[cur_stream->chapter_selected].index);
4379 break;
4380 case SDLK_w:
4381 if (cur_stream->show_mode == SHOW_MODE_VIDEO && cur_stream->vfilter_idx < nb_vfilters - 1) {
4382 if (++cur_stream->vfilter_idx >= nb_vfilters)
4383 cur_stream->vfilter_idx = 0;
4384 } else {
4385 cur_stream->vfilter_idx = 0;
4386 toggle_audio_display(cur_stream);
4387 }
4388 break;
4389 case SDLK_PAGEUP:
4390 if (cur_stream->ic->nb_chapters <= 1) {
4391 incr = 600.0;
4392 goto do_seek;
4393 }
4394 seek_chapter(cur_stream, current_chapter(cur_stream) + 1);
4395 break;
4396 case SDLK_PAGEDOWN:
4397 if (cur_stream->ic->nb_chapters <= 1) {
4398 incr = -600.0;
4399 goto do_seek;
4400 }
4401 seek_chapter(cur_stream, current_chapter(cur_stream) - 1);
4402 break;
4403 case SDLK_LEFT:
4404 incr = seek_interval ? -seek_interval : -10.0;
4405 goto do_seek;
4406 case SDLK_RIGHT:
4407 incr = seek_interval ? seek_interval : 10.0;
4408 goto do_seek;
4409 case SDLK_UP:
4410 incr = 60.0;
4411 goto do_seek;
4412 case SDLK_DOWN:
4413 incr = -60.0;
4414 do_seek:
4415 if (seek_by_bytes) {
4416 pos = -1;
4418 pos = frame_queue_last_pos(&cur_stream->pictq);
4420 pos = frame_queue_last_pos(&cur_stream->sampq);
4421 if (pos < 0)
4422 pos = avio_tell(cur_stream->ic->pb);
4423 if (cur_stream->ic->bit_rate)
4424 incr *= cur_stream->ic->bit_rate / 8.0;
4425 else
4426 incr *= 180000.0;
4427 pos += incr;
4428 stream_seek(cur_stream, pos, incr, 1);
4429 } else {
4430 pos = get_master_clock(cur_stream);
4431 if (isnan(pos))
4432 pos = (double)cur_stream->seek_pos / AV_TIME_BASE;
4433 pos += incr;
4434 if (cur_stream->ic->start_time != AV_NOPTS_VALUE && pos < cur_stream->ic->start_time / (double)AV_TIME_BASE)
4435 pos = cur_stream->ic->start_time / (double)AV_TIME_BASE;
4436 stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), (int64_t)(incr * AV_TIME_BASE), 0);
4437 }
4438 break;
4439 default:
4440 break;
4441 }
4442 break;
4443 case SDL_KEYUP:
4444 /* on the release of a press made while unpinned, so that the key's own text input does not start the search */
4445 if (event.key.keysym.sym == SDLK_l && cur_stream->chapter_pin_requested)
4446 chapter_list_pin(cur_stream, 1);
4447 cur_stream->chapter_pin_requested = 0;
4448 break;
4449 case SDL_TEXTINPUT:
4450 if (cur_stream->chapter_pinned)
4451 chapter_list_search(cur_stream, event.text.text);
4452 break;
4453 case SDL_MOUSEWHEEL:
4454 if (chapter_list_visible(cur_stream))
4455 chapter_list_move(cur_stream, -event.wheel.y);
4456 break;
4457 case SDL_MOUSEBUTTONDOWN:
4458 if (exit_on_mousedown) {
4459 do_exit(cur_stream);
4460 break;
4461 }
4462 if (event.button.button == SDL_BUTTON_LEFT && chapter_list_visible(cur_stream) &&
4463 chapter_list_click(cur_stream, event.button.x, event.button.y))
4464 break;
4465 if (event.button.button == SDL_BUTTON_LEFT) {
4466 static int64_t last_mouse_left_click = 0;
4467 if (av_gettime_relative() - last_mouse_left_click <= 500000) {
4468 toggle_full_screen(cur_stream);
4469 cur_stream->force_refresh = 1;
4470 last_mouse_left_click = 0;
4471 } else {
4472 last_mouse_left_click = av_gettime_relative();
4473 }
4474 }
4476 case SDL_MOUSEMOTION:
4477 if (cursor_hidden) {
4478 SDL_ShowCursor(1);
4479 cursor_hidden = 0;
4480 }
4482 if (event.type == SDL_MOUSEMOTION)
4483 chapter_list_hover(cur_stream, event.motion.x, event.motion.y);
4484 if (event.type == SDL_MOUSEBUTTONDOWN) {
4485 if (event.button.button != SDL_BUTTON_RIGHT)
4486 break;
4487 x = event.button.x;
4488 } else {
4489 if (!(event.motion.state & SDL_BUTTON_RMASK))
4490 break;
4491 x = event.motion.x;
4492 }
4493 if (seek_by_bytes || cur_stream->ic->duration <= 0) {
4494 uint64_t size = avio_size(cur_stream->ic->pb);
4495 stream_seek(cur_stream, size*x/cur_stream->width, 0, 1);
4496 } else {
4497 int64_t ts;
4498 int ns, hh, mm, ss;
4499 int tns, thh, tmm, tss;
4500 tns = cur_stream->ic->duration / 1000000LL;
4501 thh = tns / 3600;
4502 tmm = (tns % 3600) / 60;
4503 tss = (tns % 60);
4504 frac = x / cur_stream->width;
4505 ns = frac * tns;
4506 hh = ns / 3600;
4507 mm = (ns % 3600) / 60;
4508 ss = (ns % 60);
4510 "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
4511 hh, mm, ss, thh, tmm, tss);
4512 ts = frac * cur_stream->ic->duration;
4513 if (cur_stream->ic->start_time != AV_NOPTS_VALUE)
4514 ts += cur_stream->ic->start_time;
4515 stream_seek(cur_stream, ts, 0, 0);
4516 }
4517 break;
4518 case SDL_WINDOWEVENT:
4519 switch (event.window.event) {
4520 case SDL_WINDOWEVENT_LEAVE:
4521 chapter_list_hover(cur_stream, -1, -1);
4522 break;
4523 case SDL_WINDOWEVENT_SIZE_CHANGED:
4524 screen_width = cur_stream->width = event.window.data1;
4525 screen_height = cur_stream->height = event.window.data2;
4526 if (cur_stream->vis_texture) {
4527 SDL_DestroyTexture(cur_stream->vis_texture);
4528 cur_stream->vis_texture = NULL;
4529 }
4530 avfilter_graph_free(&cur_stream->chapter_graph);
4531 if (cur_stream->chapter_texture)
4532 chapter_list_render(cur_stream);
4533 if (vk_renderer)
4536 case SDL_WINDOWEVENT_EXPOSED:
4537 cur_stream->force_refresh = 1;
4538 }
4539 break;
4540 case SDL_QUIT:
4541 case FF_QUIT_EVENT:
4542 do_exit(cur_stream);
4543 break;
4544 default:
4545 break;
4546 }
4547 }
4548}
4549
4550static int opt_width(void *optctx, const char *opt, const char *arg)
4551{
4552 double num;
4553 int ret = parse_number(opt, arg, OPT_TYPE_INT64, 1, INT_MAX, &num);
4554 if (ret < 0)
4555 return ret;
4556
4557 screen_width = num;
4558 return 0;
4559}
4560
4561static int opt_height(void *optctx, const char *opt, const char *arg)
4562{
4563 double num;
4564 int ret = parse_number(opt, arg, OPT_TYPE_INT64, 1, INT_MAX, &num);
4565 if (ret < 0)
4566 return ret;
4567
4568 screen_height = num;
4569 return 0;
4570}
4571
4572static int opt_format(void *optctx, const char *opt, const char *arg)
4573{
4575 if (!file_iformat) {
4576 av_log(NULL, AV_LOG_FATAL, "Unknown input format: %s\n", arg);
4577 return AVERROR(EINVAL);
4578 }
4579 return 0;
4580}
4581
4582static int opt_sync(void *optctx, const char *opt, const char *arg)
4583{
4584 if (!strcmp(arg, "audio"))
4586 else if (!strcmp(arg, "video"))
4588 else if (!strcmp(arg, "ext"))
4590 else {
4591 av_log(NULL, AV_LOG_ERROR, "Unknown value for %s: %s\n", opt, arg);
4592 exit(1);
4593 }
4594 return 0;
4595}
4596
4597static int opt_show_mode(void *optctx, const char *opt, const char *arg)
4598{
4599 show_mode = !strcmp(arg, "video") ? SHOW_MODE_VIDEO :
4600 !strcmp(arg, "waves") ? SHOW_MODE_WAVES :
4601 !strcmp(arg, "rdft" ) ? SHOW_MODE_RDFT : SHOW_MODE_NONE;
4602
4603 if (show_mode == SHOW_MODE_NONE) {
4604 double num;
4605 int ret = parse_number(opt, arg, OPT_TYPE_INT, 0, SHOW_MODE_NB-1, &num);
4606 if (ret < 0)
4607 return ret;
4608 show_mode = num;
4609 }
4610 return 0;
4611}
4612
4613static int opt_input_file(void *optctx, const char *filename)
4614{
4615 if (input_filename) {
4617 "Argument '%s' provided as input filename, but '%s' was already specified.\n",
4618 filename, input_filename);
4619 return AVERROR(EINVAL);
4620 }
4621 if (!strcmp(filename, "-"))
4622 filename = "fd:";
4623 input_filename = av_strdup(filename);
4624 if (!input_filename)
4625 return AVERROR(ENOMEM);
4626
4627 return 0;
4628}
4629
4630static int opt_codec(void *optctx, const char *opt, const char *arg)
4631{
4632 const char *spec = strchr(opt, ':');
4633 const char **name;
4634 if (!spec) {
4636 "No media specifier was specified in '%s' in option '%s'\n",
4637 arg, opt);
4638 return AVERROR(EINVAL);
4639 }
4640 spec++;
4641
4642 switch (spec[0]) {
4643 case 'a' : name = &audio_codec_name; break;
4644 case 's' : name = &subtitle_codec_name; break;
4645 case 'v' : name = &video_codec_name; break;
4646 default:
4648 "Invalid media specifier '%s' in option '%s'\n", spec, opt);
4649 return AVERROR(EINVAL);
4650 }
4651
4652 av_freep(name);
4653 *name = av_strdup(arg);
4654 return *name ? 0 : AVERROR(ENOMEM);
4655}
4656
4657static int dummy;
4658
4659static const OptionDef options[] = {
4661 { "x", OPT_TYPE_FUNC, OPT_FUNC_ARG, { .func_arg = opt_width }, "force displayed width", "width" },
4662 { "y", OPT_TYPE_FUNC, OPT_FUNC_ARG, { .func_arg = opt_height }, "force displayed height", "height" },
4663 { "fs", OPT_TYPE_BOOL, 0, { &is_full_screen }, "force full screen" },
4664 { "an", OPT_TYPE_BOOL, 0, { &audio_disable }, "disable audio" },
4665 { "vn", OPT_TYPE_BOOL, 0, { &video_disable }, "disable video" },
4666 { "sn", OPT_TYPE_BOOL, 0, { &subtitle_disable }, "disable subtitling" },
4667 { "ast", OPT_TYPE_STRING, OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_AUDIO] }, "select desired audio stream", "stream_specifier" },
4668 { "vst", OPT_TYPE_STRING, OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_VIDEO] }, "select desired video stream", "stream_specifier" },
4669 { "sst", OPT_TYPE_STRING, OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_SUBTITLE] }, "select desired subtitle stream", "stream_specifier" },
4670 { "ss", OPT_TYPE_TIME, 0, { &start_time }, "seek to a given position in seconds", "pos" },
4671 { "t", OPT_TYPE_TIME, 0, { &duration }, "play \"duration\" seconds of audio/video", "duration" },
4672 { "bytes", OPT_TYPE_INT, 0, { &seek_by_bytes }, "seek by bytes 0=off 1=on -1=auto", "val" },
4673 { "seek_interval", OPT_TYPE_FLOAT, 0, { &seek_interval }, "set seek interval for left/right keys, in seconds", "seconds" },
4674 { "nodisp", OPT_TYPE_BOOL, 0, { &display_disable }, "disable graphical display" },
4675 { "noborder", OPT_TYPE_BOOL, 0, { &borderless }, "borderless window" },
4676 { "alwaysontop", OPT_TYPE_BOOL, 0, { &alwaysontop }, "window always on top" },
4677 { "volume", OPT_TYPE_INT, 0, { &startup_volume}, "set startup volume 0=min 100=max", "volume" },
4678 { "f", OPT_TYPE_FUNC, OPT_FUNC_ARG, { .func_arg = opt_format }, "force format", "fmt" },
4679 { "stats", OPT_TYPE_BOOL, OPT_EXPERT, { &show_status }, "show status", "" },
4680 { "fast", OPT_TYPE_BOOL, OPT_EXPERT, { &fast }, "non spec compliant optimizations", "" },
4681 { "genpts", OPT_TYPE_BOOL, OPT_EXPERT, { &genpts }, "generate pts", "" },
4682 { "drp", OPT_TYPE_INT, OPT_EXPERT, { &decoder_reorder_pts }, "let decoder reorder pts 0=off 1=on -1=auto", ""},
4683 { "lowres", OPT_TYPE_INT, OPT_EXPERT, { &lowres }, "", "" },
4684 { "sync", OPT_TYPE_FUNC, OPT_FUNC_ARG | OPT_EXPERT, { .func_arg = opt_sync }, "set audio-video sync. type (type=audio/video/ext)", "type" },
4685 { "autoexit", OPT_TYPE_BOOL, OPT_EXPERT, { &autoexit }, "exit at the end", "" },
4686 { "exitonkeydown", OPT_TYPE_BOOL, OPT_EXPERT, { &exit_on_keydown }, "exit on key down", "" },
4687 { "exitonmousedown", OPT_TYPE_BOOL, OPT_EXPERT, { &exit_on_mousedown }, "exit on mouse down", "" },
4688 { "loop", OPT_TYPE_INT, OPT_EXPERT, { &loop }, "set number of times the playback shall be looped", "loop count" },
4689 { "framedrop", OPT_TYPE_BOOL, OPT_EXPERT, { &framedrop }, "drop frames when cpu is too slow", "" },
4690 { "infbuf", OPT_TYPE_BOOL, OPT_EXPERT, { &infinite_buffer }, "don't limit the input buffer size (useful with realtime streams)", "" },
4691 { "window_title", OPT_TYPE_STRING, 0, { &window_title }, "set window title", "window title" },
4692 { "left", OPT_TYPE_INT, OPT_EXPERT, { &screen_left }, "set the x position for the left of the window", "x pos" },
4693 { "top", OPT_TYPE_INT, OPT_EXPERT, { &screen_top }, "set the y position for the top of the window", "y pos" },
4694 { "vf", OPT_TYPE_FUNC, OPT_FUNC_ARG | OPT_EXPERT, { .func_arg = opt_add_vfilter }, "set video filters", "filter_graph" },
4695 { "af", OPT_TYPE_STRING, 0, { &afilters }, "set audio filters", "filter_graph" },
4696 { "rdftspeed", OPT_TYPE_INT, OPT_AUDIO | OPT_EXPERT, { &rdftspeed }, "rdft speed", "msecs" },
4697 { "showmode", OPT_TYPE_FUNC, OPT_FUNC_ARG, { .func_arg = opt_show_mode}, "select show mode (0 = video, 1 = waves, 2 = RDFT)", "mode" },
4698 { "i", OPT_TYPE_BOOL, 0, { &dummy}, "read specified file", "input_file"},
4699 { "codec", OPT_TYPE_FUNC, OPT_FUNC_ARG, { .func_arg = opt_codec}, "force decoder", "decoder_name" },
4700 { "acodec", OPT_TYPE_STRING, OPT_EXPERT, { &audio_codec_name }, "force audio decoder", "decoder_name" },
4701 { "scodec", OPT_TYPE_STRING, OPT_EXPERT, { &subtitle_codec_name }, "force subtitle decoder", "decoder_name" },
4702 { "vcodec", OPT_TYPE_STRING, OPT_EXPERT, { &video_codec_name }, "force video decoder", "decoder_name" },
4703 { "autorotate", OPT_TYPE_BOOL, 0, { &autorotate }, "automatically rotate video", "" },
4704 { "find_stream_info", OPT_TYPE_BOOL, OPT_INPUT | OPT_EXPERT, { &find_stream_info },
4705 "read and decode the streams to fill missing information with heuristics" },
4706 { "filter_threads", OPT_TYPE_INT, OPT_EXPERT, { &filter_nbthreads }, "number of filter threads per graph" },
4707 { "enable_vulkan", OPT_TYPE_BOOL, 0, { &enable_vulkan }, "enable vulkan renderer" },
4708 { "vulkan_params", OPT_TYPE_STRING, OPT_EXPERT, { &vulkan_params }, "vulkan configuration using a list of key=value pairs separated by ':'" },
4709 { "video_bg", OPT_TYPE_STRING, OPT_EXPERT, { &video_background }, "set video background for transparent videos" },
4710 { "hwaccel", OPT_TYPE_STRING, OPT_EXPERT, { &hwaccel }, "use HW accelerated decoding" },
4711 { NULL, },
4712};
4713
4714static void show_usage(void)
4715{
4716 av_log(NULL, AV_LOG_INFO, "Simple media player\n");
4717 av_log(NULL, AV_LOG_INFO, "usage: %s [options] input_file\n", program_name);
4718 av_log(NULL, AV_LOG_INFO, "\n");
4719}
4720
4721void show_help_default(const char *opt, const char *arg)
4722{
4724 show_usage();
4725 show_help_options(options, "Main options:", 0, OPT_EXPERT);
4726 show_help_options(options, "Advanced options:", OPT_EXPERT, 0);
4727 printf("\n");
4731 printf("\nWhile playing:\n"
4732 "q, ESC quit\n"
4733 "f toggle full screen\n"
4734 "p, SPC pause\n"
4735 "m toggle mute\n"
4736 "9, 0 decrease and increase volume respectively\n"
4737 "/, * decrease and increase volume respectively\n"
4738 "a cycle audio channel in the current program\n"
4739 "v cycle video channel\n"
4740 "t cycle subtitle channel in the current program\n"
4741 "c cycle program\n"
4742 "w cycle video filters or show modes\n"
4743 "s activate frame-step mode\n"
4744 "left/right seek backward/forward by 10 seconds or a custom interval if -seek_interval is set\n"
4745 "down/up seek backward/forward 1 minute\n"
4746 "page down/page up seek to previous/next chapter or backward/forward 10 minutes if no chapters\n"
4747 "l keep the chapter list on screen; typing then filters it, down/up move its selection and escape closes it\n"
4748 "enter seek to the chapter selected in the chapter list while it is shown\n"
4749 "mouse wheel move the chapter list selection while it is shown\n"
4750 "left click seek to the clicked chapter list entry, or sort the list by the clicked column, again to flip it;\n"
4751 " the left half of the shuffle button lowers its seed, the right half raises it\n"
4752 "mouse over (i) show the metadata of that chapter list entry\n"
4753 "right mouse click seek to percentage in file corresponding to fraction of width\n"
4754 "left double-click toggle full screen\n"
4755 );
4756}
4757
4758/* Called from the main */
4759int main(int argc, char **argv)
4760{
4761 int flags, ret;
4762 VideoState *is;
4763
4764 init_dynload();
4765
4767 parse_loglevel(argc, argv, options);
4768
4769 /* register all codecs, demux and protocols */
4770#if CONFIG_AVDEVICE
4772#endif
4774
4775 signal(SIGINT , sigterm_handler); /* Interrupt (ANSI). */
4776 signal(SIGTERM, sigterm_handler); /* Termination (ANSI). */
4777
4778 show_banner(argc, argv, options);
4779
4780 ret = parse_options(NULL, argc, argv, options, opt_input_file);
4781 if (ret < 0)
4782 exit(ret == AVERROR_EXIT ? 0 : 1);
4783
4784 if (!input_filename) {
4785 show_usage();
4786 av_log(NULL, AV_LOG_FATAL, "An input file must be specified\n");
4788 "Use -h to get full help or, even better, run 'man %s'\n", program_name);
4789 exit(1);
4790 }
4791
4792 if (display_disable) {
4793 video_disable = 1;
4794 }
4795 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
4796 if (audio_disable)
4797 flags &= ~SDL_INIT_AUDIO;
4798 if (display_disable)
4799 flags &= ~SDL_INIT_VIDEO;
4800 if (SDL_Init (flags)) {
4801 av_log(NULL, AV_LOG_FATAL, "Could not initialize SDL - %s\n", SDL_GetError());
4802 av_log(NULL, AV_LOG_FATAL, "(Did you set the DISPLAY variable?)\n");
4803 exit(1);
4804 }
4805
4806 SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
4807 SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
4808
4809 if (!display_disable) {
4810 int flags = SDL_WINDOW_HIDDEN;
4811 if (alwaysontop)
4812#if SDL_VERSION_ATLEAST(2,0,5)
4813 flags |= SDL_WINDOW_ALWAYS_ON_TOP;
4814#else
4815 av_log(NULL, AV_LOG_WARNING, "Your SDL version doesn't support SDL_WINDOW_ALWAYS_ON_TOP. Feature will be inactive.\n");
4816#endif
4817 if (borderless)
4818 flags |= SDL_WINDOW_BORDERLESS;
4819 else
4820 flags |= SDL_WINDOW_RESIZABLE;
4821
4822#ifdef SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR
4823 SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0");
4824#endif
4825 if (hwaccel && !enable_vulkan) {
4826 av_log(NULL, AV_LOG_INFO, "Enable vulkan renderer to support hwaccel %s\n", hwaccel);
4827 enable_vulkan = 1;
4828 }
4829 if (enable_vulkan) {
4831 if (vk_renderer) {
4832#if SDL_VERSION_ATLEAST(2, 0, 6)
4833 flags |= SDL_WINDOW_VULKAN;
4834#endif
4835 } else {
4836 av_log(NULL, AV_LOG_WARNING, "Doesn't support vulkan renderer, fallback to SDL renderer\n");
4837 enable_vulkan = 0;
4838 }
4839 }
4840 window = SDL_CreateWindow(program_name, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, default_width, default_height, flags);
4841 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
4842 if (!window) {
4843 av_log(NULL, AV_LOG_FATAL, "Failed to create window: %s", SDL_GetError());
4844 do_exit(NULL);
4845 }
4846
4847 if (vk_renderer) {
4848 AVDictionary *dict = NULL;
4849
4850 if (vulkan_params) {
4851 int ret = av_dict_parse_string(&dict, vulkan_params, "=", ":", 0);
4852 if (ret < 0) {
4853 av_log(NULL, AV_LOG_FATAL, "Failed to parse, %s\n", vulkan_params);
4854 do_exit(NULL);
4855 }
4856 }
4858 av_dict_free(&dict);
4859 if (ret < 0) {
4860 av_log(NULL, AV_LOG_FATAL, "Failed to create vulkan renderer, %s\n", av_err2str(ret));
4861 do_exit(NULL);
4862 }
4863 } else {
4864 renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
4865 if (!renderer) {
4866 av_log(NULL, AV_LOG_WARNING, "Failed to initialize a hardware accelerated renderer: %s\n", SDL_GetError());
4867 renderer = SDL_CreateRenderer(window, -1, 0);
4868 }
4869 if (renderer) {
4870 if (!SDL_GetRendererInfo(renderer, &renderer_info))
4871 av_log(NULL, AV_LOG_VERBOSE, "Initialized %s renderer.\n", renderer_info.name);
4872 }
4873 if (!renderer || !renderer_info.num_texture_formats) {
4874 av_log(NULL, AV_LOG_FATAL, "Failed to create window or renderer: %s", SDL_GetError());
4875 do_exit(NULL);
4876 }
4877 }
4878 }
4879
4881 if (!is) {
4882 av_log(NULL, AV_LOG_FATAL, "Failed to initialize VideoState!\n");
4883 do_exit(NULL);
4884 }
4885
4886 event_loop(is);
4887
4888 /* never returns */
4889
4890 return 0;
4891}
#define fn(a)
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:87
static double val(void *priv, double ch)
Definition aeval.c:77
static const AVFilterPad inputs[]
Definition af_aap.c:299
static const AVFilterPad outputs[]
Definition af_aap.c:310
static const char *const format[]
Definition af_aiir.c:445
static FILE * out
static int out_size
static AVFormatContext * ctx
static AVDictionary * opts
channels
Definition aptx.h:31
int32_t
Main libavdevice API header.
Main libavfilter public API header.
int av_find_best_stream(AVFormatContext *ic, enum AVMediaType type, int wanted_stream_nb, int related_stream, const AVCodec **decoder_ret, int flags)
Definition avformat.c:505
Main libavformat public API header.
#define AVFMT_EVENT_FLAG_METADATA_UPDATED
Definition avformat.h:1729
@ AV_STREAM_GROUP_PARAMS_LCEVC
Definition avformat.h:1153
#define AVFMT_TS_DISCONT
Format allows timestamp discontinuities.
Definition avformat.h:502
#define AVFMT_NO_BYTE_SEEK
Format does not allow seeking by bytes.
Definition avformat.h:508
#define AVFMT_FLAG_GENPTS
Generate missing pts even if it requires parsing future frames.
Definition avformat.h:1487
#define AVSEEK_FLAG_BYTE
seeking based on position in bytes
Definition avformat.h:2619
#define AVSTREAM_EVENT_FLAG_METADATA_UPDATED
Definition avformat.h:886
#define AV_DISPOSITION_ATTACHED_PIC
The stream is stored in the file as an attached picture/"cover art" (e.g.
Definition avformat.h:694
#define AVFMT_NOTIMESTAMPS
Format does not need / have any timestamps.
Definition avformat.h:500
int64_t avio_size(AVIOContext *s)
Get the filesize.
Definition aviobuf.c:326
int avio_feof(AVIOContext *s)
Similar to feof() but also returns nonzero on read errors.
Definition aviobuf.c:349
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition avio.h:494
char * av_asprintf(const char *fmt,...)
Definition avstring.c:115
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
Definition avstring.c:103
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition bprint.c:121
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition bprint.c:68
AVBPrint public header.
#define AV_BPRINT_SIZE_UNLIMITED
#define AV_BPRINT_SIZE_AUTOMATIC
memory buffer sink API for audio and video
Memory buffer source API.
#define is(width, name, range_min, range_max, subs,...)
Definition cbs_h264.c:78
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define f(width, name)
Definition cbs_vp8.c:236
#define ss(width, name, subs,...)
Definition cbs_vp9.c:202
#define s(width, name)
Definition cbs_vp9.c:198
Public libavutil channel layout APIs header.
void show_help_children(const AVClass *class, int flags)
Show help for all options with given flags in class and all its children.
Definition cmdutils.c:138
void init_dynload(void)
Initialize dynamic library loading.
Definition cmdutils.c:73
int check_avoptions(AVDictionary *m)
Definition cmdutils.c:1603
void dump_dictionary(void *ctx, const AVDictionary *m, const char *name, const char *indent, int log_level)
This does the same as libavformat/dump.c corresponding function and should probably be kept in sync w...
Definition cmdutils.c:1614
AVDictionary * swr_opts
Definition cmdutils.c:55
void parse_loglevel(int argc, char **argv, const OptionDef *options)
Find the '-loglevel' option in the command line args and apply it.
Definition cmdutils.c:554
void show_help_options(const OptionDef *options, const char *msg, int req_flags, int rej_flags)
Print help for all options matching specified flags.
Definition cmdutils.c:105
void log_callback_help(void *ptr, int level, const char *fmt, va_list vl)
Trivial log callback.
Definition cmdutils.c:68
AVDictionary * format_opts
Definition cmdutils.c:56
int parse_options(void *optctx, int argc, char **argv, const OptionDef *options, int(*parse_arg_function)(void *, const char *))
Parse the command line arguments.
Definition cmdutils.c:418
int filter_codec_opts(const AVDictionary *opts, enum AVCodecID codec_id, AVFormatContext *s, AVStream *st, const AVCodec *codec, AVDictionary **dst, AVDictionary **opts_used)
Filter out options for given codec.
Definition cmdutils.c:1421
void remove_avoptions(AVDictionary **a, AVDictionary *b)
Definition cmdutils.c:1594
AVDictionary * codec_opts
Definition cmdutils.c:56
void uninit_opts(void)
Uninitialize the cmdutils option system, in particular free the *_opts contexts and their contents.
Definition cmdutils.c:60
double get_rotation(const int32_t *displaymatrix)
Definition cmdutils.c:1551
int setup_find_stream_info_opts(AVFormatContext *s, AVDictionary *local_codec_opts, AVDictionary ***dst)
Setup AVCodecContext options for avformat_find_stream_info().
Definition cmdutils.c:1489
int parse_number(const char *context, const char *numstr, enum OptionType type, double min, double max, double *dst)
Parse a string and return its corresponding value as a double.
Definition cmdutils.c:82
AVDictionary * sws_dict
Definition cmdutils.c:54
const char program_name[]
program name, defined by the program for show_version().
Definition ffmpeg.c:89
#define OPT_FUNC_ARG
Definition cmdutils.h:205
#define OPT_INPUT
Definition cmdutils.h:237
static void print_error(const char *filename, int err)
Print an error message to stderr, indicating filename and a human readable description of the error c...
Definition cmdutils.h:472
@ OPT_TYPE_BOOL
Definition cmdutils.h:82
@ OPT_TYPE_STRING
Definition cmdutils.h:83
@ OPT_TYPE_INT64
Definition cmdutils.h:85
@ OPT_TYPE_INT
Definition cmdutils.h:84
@ OPT_TYPE_TIME
Definition cmdutils.h:88
@ OPT_TYPE_FUNC
Definition cmdutils.h:81
@ OPT_TYPE_FLOAT
Definition cmdutils.h:86
void show_banner(int argc, char **argv, const OptionDef *options)
Print the program banner to stderr.
Definition opt_common.c:240
#define GROW_ARRAY(array, nb_elems)
Definition cmdutils.h:536
#define OPT_AUDIO
Definition cmdutils.h:213
#define OPT_EXPERT
Definition cmdutils.h:211
const int program_birth_year
program birth year, defined by the program for show_banner()
Definition ffmpeg.c:90
int avcodec_parameters_to_context(AVCodecContext *codec, const AVCodecParameters *par)
Definition codec_par.c:206
#define av_clipd
Definition common.h:148
#define AV_CEIL_RSHIFT(a, b)
Definition common.h:60
#define av_clip
Definition common.h:100
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
__device__ int printf(const char *,...)
static __device__ float fabs(float a)
static int16_t block[64]
Definition dct.c:125
static AVPacket * pkt
static AVStream * video_stream
static AVStream * audio_stream
static AVFrame * frame
Public dictionary API.
int main
Definition dovi_rpuenc.c:38
int8_t exp
Definition eval.c:76
static volatile int received_sigterm
Definition ffmpeg.c:141
static int decode_interrupt_cb(void *ctx)
Definition ffmpeg.c:317
static volatile int received_nb_signals
Definition ffmpeg.c:142
static void sigterm_handler(int sig)
Definition ffmpeg.c:148
char * filter_nbthreads
Definition ffmpeg_opt.c:73
const char * key
static void show_usage(void)
Definition ffplay.c:4714
static char * vulkan_params
Definition ffplay.c:428
static VideoState * stream_open(const char *filename, const AVInputFormat *iformat)
Definition ffplay.c:4095
static double compute_target_delay(double delay, VideoState *is)
Definition ffplay.c:2221
#define SDL_AUDIO_MAX_CALLBACKS_PER_SEC
Definition ffplay.c:75
static int default_height
Definition ffplay.c:381
static char * video_background
Definition ffplay.c:429
static int autorotate
Definition ffplay.c:424
static int screen_left
Definition ffplay.c:384
static int is_realtime(AVFormatContext *s)
Definition ffplay.c:3586
static void frame_queue_destroy(FrameQueue *f)
Definition ffplay.c:790
static int audio_open(void *opaque, AVChannelLayout *wanted_channel_layout, int wanted_sample_rate, struct AudioParams *audio_hw_params)
Definition ffplay.c:3217
static int chapter_list_click(VideoState *is, int x, int y)
Definition ffplay.c:1574
static int packet_queue_put_nullpacket(PacketQueue *q, AVPacket *pkt, int stream_index)
Definition ffplay.c:543
static int decoder_decode_frame(Decoder *d, AVFrame *frame, AVSubtitle *sub)
Definition ffplay.c:659
static void chapter_list_search(VideoState *is, const char *typed)
Definition ffplay.c:1503
static const char * hwaccel
Definition ffplay.c:430
#define CHAPTER_LIST_ROWS
Definition ffplay.c:111
static Frame * frame_queue_peek_writable(FrameQueue *f)
Definition ffplay.c:824
static int default_width
Definition ffplay.c:380
static int video_open(VideoState *is)
Definition ffplay.c:2031
static int current_chapter(VideoState *is)
Definition ffplay.c:4287
static int infinite_buffer
Definition ffplay.c:409
static void draw_video_background(VideoState *is)
Definition ffplay.c:1047
static void do_exit(VideoState *is)
Definition ffplay.c:1985
static int is_full_screen
Definition ffplay.c:433
static ChapterListHit chapter_list_hit(VideoState *is, const ChapterListLayout *l, int x, int y)
Definition ffplay.c:1260
static int64_t duration
Definition ffplay.c:399
static int upload_texture(SDL_Texture **tex, AVFrame *frame)
Definition ffplay.c:986
static void set_clock_at(Clock *c, double pts, int serial, double time)
Definition ffplay.c:2082
static void stream_toggle_pause(VideoState *is)
Definition ffplay.c:2182
static void chapter_list_hover(VideoState *is, int x, int y)
Definition ffplay.c:1558
static SDL_AudioDeviceID audio_dev
Definition ffplay.c:445
static double get_master_clock(VideoState *is)
Definition ffplay.c:2135
static double vp_duration(VideoState *is, Frame *vp, Frame *nextvp)
Definition ffplay.c:2251
static int display_disable
Definition ffplay.c:392
static uint32_t shuffle_rank(int index)
Definition ffplay.c:1111
static int compare_tags(const char *a, const char *b)
Definition ffplay.c:1105
static void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
Definition ffplay.c:3174
#define EXTERNAL_CLOCK_MAX_FRAMES
Definition ffplay.c:70
static int audio_decode_frame(VideoState *is)
Decode one audio frame and return its uncompressed size.
Definition ffplay.c:3064
static void event_loop(VideoState *cur_stream)
Definition ffplay.c:4313
static int opt_format(void *optctx, const char *opt, const char *arg)
Definition ffplay.c:4572
static double chapter_list_alpha(VideoState *is, int64_t now)
Definition ffplay.c:1086
#define EXTERNAL_CLOCK_SPEED_STEP
Definition ffplay.c:95
static const AVInputFormat * file_iformat
Definition ffplay.c:377
static int video_disable
Definition ffplay.c:387
#define AV_SYNC_THRESHOLD_MAX
Definition ffplay.c:83
static int find_stream_info
Definition ffplay.c:425
#define SAMPLE_QUEUE_SIZE
Definition ffplay.c:162
static int screen_height
Definition ffplay.c:383
#define MIN_FRAMES
Definition ffplay.c:68
static Frame * frame_queue_peek(FrameQueue *f)
Definition ffplay.c:809
static const char * chapter_tag(const AVChapter *chapter, const char *key)
Definition ffplay.c:1097
static int opt_codec(void *optctx, const char *opt, const char *arg)
Definition ffplay.c:4630
static Frame * frame_queue_peek_next(FrameQueue *f)
Definition ffplay.c:814
static const char ** vfilters_list
Definition ffplay.c:421
static int genpts
Definition ffplay.c:401
static int get_master_sync_type(VideoState *is)
Definition ffplay.c:2118
static void video_image_display(VideoState *is)
Definition ffplay.c:1601
static int compare_chapter_rows(const void *a, const void *b)
Definition ffplay.c:1120
static Frame * frame_queue_peek_readable(FrameQueue *f)
Definition ffplay.c:840
static int decoder_reorder_pts
Definition ffplay.c:403
static int subtitle_disable
Definition ffplay.c:388
static ChapterListLayout chapter_list_layout(VideoState *is)
Definition ffplay.c:1220
static const struct @171016013232041267156014171031267212062350175105 sort_buttons[CHAPTER_SORT_NB]
static void packet_queue_destroy(PacketQueue *q)
Definition ffplay.c:584
static int nb_vfilters
Definition ffplay.c:422
static void set_clock(Clock *c, double pts, int serial)
Definition ffplay.c:2090
static int av_sync_type
Definition ffplay.c:397
static int init_lcevc_graph(AVFormatContext *ic, int stream_index)
Definition ffplay.c:3329
static int borderless
Definition ffplay.c:393
static int startup_volume
Definition ffplay.c:395
static void toggle_mute(VideoState *is)
Definition ffplay.c:2201
static void frame_queue_next(FrameQueue *f)
Definition ffplay.c:866
static int chapter_list_update_rows(VideoState *is)
Definition ffplay.c:1159
static void fill_rectangle(int x, int y, int w, int h)
Definition ffplay.c:906
static void stream_seek(VideoState *is, int64_t pos, int64_t rel, int by_bytes)
Definition ffplay.c:2168
#define EXTERNAL_CLOCK_SPEED_MAX
Definition ffplay.c:94
static void chapter_list_script(VideoState *is, AVBPrint *script)
Definition ffplay.c:1315
static int opt_input_file(void *optctx, const char *filename)
Definition ffplay.c:4613
@ AV_SYNC_AUDIO_MASTER
Definition ffplay.c:235
@ AV_SYNC_EXTERNAL_CLOCK
Definition ffplay.c:237
@ AV_SYNC_VIDEO_MASTER
Definition ffplay.c:236
static const char * video_codec_name
Definition ffplay.c:417
#define SAMPLE_ARRAY_SIZE
Definition ffplay.c:105
static const char * input_filename
Definition ffplay.c:378
static void video_display(VideoState *is)
Definition ffplay.c:2055
static void packet_queue_abort(PacketQueue *q)
Definition ffplay.c:592
static void update_volume(VideoState *is, int sign, double step)
Definition ffplay.c:2206
static void toggle_audio_display(VideoState *is)
Definition ffplay.c:4249
#define SDL_VOLUME_STEP
Definition ffplay.c:78
#define MAX_QUEUE_SIZE
Definition ffplay.c:67
static void refresh_loop_wait_event(VideoState *is, SDL_Event *event)
Definition ffplay.c:4261
static enum AVColorSpace sdl_supported_color_spaces[]
Definition ffplay.c:1020
static enum ShowMode show_mode
Definition ffplay.c:410
static void bprint_chapter_ring(AVBPrint *script, int cx, int cy, int r)
Definition ffplay.c:1283
static int show_status
Definition ffplay.c:396
static int subtitle_thread(void *arg)
Definition ffplay.c:2961
static int frame_queue_nb_remaining(FrameQueue *f)
Definition ffplay.c:882
static const char * window_title
Definition ffplay.c:379
static int get_video_frame(VideoState *is, AVFrame *frame)
Definition ffplay.c:2469
static enum AVAlphaMode sdl_supported_alpha_modes[]
Definition ffplay.c:1026
static void video_audio_display(VideoState *s)
Definition ffplay.c:1697
static int decoder_start(Decoder *d, int(*fn)(void *), const char *thread_name, void *arg)
Definition ffplay.c:2847
static void decoder_abort(Decoder *d, FrameQueue *fq)
Definition ffplay.c:897
static int64_t frame_queue_last_pos(FrameQueue *f)
Definition ffplay.c:888
static void update_video_pts(VideoState *is, double pts, int serial)
Definition ffplay.c:2263
static int autoexit
Definition ffplay.c:404
static int64_t audio_callback_time
Definition ffplay.c:434
static void chapter_list_key(VideoState *is, SDL_Keycode key)
Definition ffplay.c:1539
static const char * audio_codec_name
Definition ffplay.c:415
static ChapterSortKey chapter_sort[CHAPTER_SORT_NB]
Definition ffplay.c:412
@ CHAPTER_SORT_NB
Definition ffplay.c:119
@ CHAPTER_SORT_LENGTH
Definition ffplay.c:117
@ CHAPTER_SORT_NUMBER
Definition ffplay.c:114
@ CHAPTER_SORT_ARTIST
Definition ffplay.c:115
@ CHAPTER_SORT_TITLE
Definition ffplay.c:116
@ CHAPTER_SORT_SHUFFLE
Definition ffplay.c:118
static int dummy
Definition ffplay.c:4657
static float seek_interval
Definition ffplay.c:391
static int packet_queue_init(PacketQueue *q)
Definition ffplay.c:550
static Frame * frame_queue_peek_last(FrameQueue *f)
Definition ffplay.c:819
static char * afilters
Definition ffplay.c:423
#define SUBPICTURE_QUEUE_SIZE
Definition ffplay.c:161
static const struct TextureFormatEntry sdl_texture_format_map[]
static void set_default_window_size(int width, int height, AVRational sar)
Definition ffplay.c:2019
#define INSERT_FILT(name, arg)
static int frame_queue_init(FrameQueue *f, PacketQueue *pktq, int max_size, int keep_last)
Definition ffplay.c:769
void show_help_default(const char *opt, const char *arg)
Per-fftool specific help handler.
Definition ffplay.c:4721
static void frame_queue_unref_item(Frame *vp)
Definition ffplay.c:763
static void init_clock(Clock *c, int *queue_serial)
Definition ffplay.c:2102
static void chapter_list_move(VideoState *is, int delta)
Definition ffplay.c:1491
static int opt_show_mode(void *optctx, const char *opt, const char *arg)
Definition ffplay.c:4597
static int compute_mod(int a, int b)
Definition ffplay.c:1692
static int opt_sync(void *optctx, const char *opt, const char *arg)
Definition ffplay.c:4582
#define CHAPTER_LIST_EVENT
Definition ffplay.c:1197
static int do_bsf_flush(AVFormatContext *ic, VideoState *is)
Definition ffplay.c:3636
#define EXTERNAL_CLOCK_SPEED_MIN
Definition ffplay.c:93
static void bprint_chapter_box(AVBPrint *script, const char *style, int x, int y, int w, int h)
Definition ffplay.c:1199
static void stream_cycle_channel(VideoState *is, int codec_type)
Definition ffplay.c:4164
static int exit_status
Definition ffplay.c:440
static SDL_Renderer * renderer
Definition ffplay.c:443
#define CHAPTER_LIST_FADE_TIME
Definition ffplay.c:109
static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block, int *serial)
Definition ffplay.c:612
#define AUDIO_DIFF_AVG_NB
Definition ffplay.c:98
static void frame_queue_push(FrameQueue *f)
Definition ffplay.c:856
static int decode_interrupt_cb(void *ctx)
Definition ffplay.c:3573
static int chapter_list_configure(VideoState *is, const char *script)
Definition ffplay.c:1388
static int decoder_init(Decoder *d, AVCodecContext *avctx, PacketQueue *queue, SDL_cond *empty_queue_cond)
Definition ffplay.c:646
static int audio_thread(void *arg)
Definition ffplay.c:2769
static int configure_audio_filters(VideoState *is, const char *afilters, int force_output_format)
Definition ffplay.c:2697
static int64_t cursor_last_shown
Definition ffplay.c:419
static int lowres
Definition ffplay.c:402
static int fast
Definition ffplay.c:400
#define SDL_AUDIO_MIN_BUFFER_SIZE
Definition ffplay.c:73
static int configure_filtergraph(AVFilterGraph *graph, const char *filtergraph, AVFilterContext *source_ctx, AVFilterContext *sink_ctx)
Definition ffplay.c:2502
static void chapter_list_show(VideoState *is, int chapter)
Definition ffplay.c:1477
static void stream_close(VideoState *is)
Definition ffplay.c:1934
static int video_thread(void *arg)
Definition ffplay.c:2858
static int exit_on_mousedown
Definition ffplay.c:406
static int screen_width
Definition ffplay.c:382
#define AV_SYNC_THRESHOLD_MIN
Definition ffplay.c:81
static SDL_Window * window
Definition ffplay.c:442
static void decoder_destroy(Decoder *d)
Definition ffplay.c:758
static int chapter_list_render(VideoState *is)
Definition ffplay.c:1423
static int do_bsf_graph(AVFormatContext *ic, VideoState *is, Stream *sti, AVPacket *pkt)
Definition ffplay.c:3602
static int stream_component_open(VideoState *is, int stream_index)
Definition ffplay.c:3408
static void stream_component_close(VideoState *is, int stream_index)
Definition ffplay.c:1873
static int framedrop
Definition ffplay.c:408
static void uninit_bsf_graph(AVFormatContext *ic, int stream_index)
Definition ffplay.c:1848
const char * label
Definition ffplay.c:1187
static int seek_by_bytes
Definition ffplay.c:390
static void packet_queue_flush(PacketQueue *q)
Definition ffplay.c:570
#define REFRESH_RATE
Definition ffplay.c:101
static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const char *vfilters, AVFrame *frame)
Definition ffplay.c:2545
static int packet_queue_put_private(PacketQueue *q, AVPacket *pkt)
Definition ffplay.c:498
static void chapter_sort_by(int key, int seed_step)
Definition ffplay.c:1142
#define FF_QUIT_EVENT
Definition ffplay.c:436
#define CURSOR_HIDE_DELAY
Definition ffplay.c:107
static int screen_top
Definition ffplay.c:385
static int opt_width(void *optctx, const char *opt, const char *arg)
Definition ffplay.c:4550
static void packet_queue_start(PacketQueue *q)
Definition ffplay.c:603
static void get_sdl_pix_fmt_and_blendmode(int format, Uint32 *sdl_pix_fmt, SDL_BlendMode *sdl_blendmode)
Definition ffplay.c:968
static SDL_RendererInfo renderer_info
Definition ffplay.c:444
static void step_to_next_frame(VideoState *is)
Definition ffplay.c:2213
static int chapter_shuffle_seed
Definition ffplay.c:414
static int chapter_list_visible(VideoState *is)
Definition ffplay.c:1497
static void toggle_pause(VideoState *is)
Definition ffplay.c:2195
static void seek_chapter(VideoState *is, int i)
Definition ffplay.c:4300
static int opt_height(void *optctx, const char *opt, const char *arg)
Definition ffplay.c:4561
#define EXTERNAL_CLOCK_MIN_FRAMES
Definition ffplay.c:69
#define AV_NOSYNC_THRESHOLD
Definition ffplay.c:87
static void update_sample_display(VideoState *is, short *samples, int samples_size)
Definition ffplay.c:2996
static int cmp_audio_fmts(enum AVSampleFormat fmt1, int64_t channel_count1, enum AVSampleFormat fmt2, int64_t channel_count2)
Definition ffplay.c:488
static int exit_on_keydown
Definition ffplay.c:405
#define FRAME_QUEUE_SIZE
Definition ffplay.c:163
static int realloc_texture(SDL_Texture **texture, Uint32 new_format, int new_width, int new_height, SDL_BlendMode blendmode, int init_texture)
Definition ffplay.c:917
static int loop
Definition ffplay.c:407
static int opt_add_vfilter(void *optctx, const char *opt, const char *arg)
Definition ffplay.c:474
static int create_hwaccel(AVBufferRef **device_ctx)
Definition ffplay.c:3293
static void video_refresh(void *opaque, double *remaining_time)
Definition ffplay.c:2271
static void frame_queue_signal(FrameQueue *f)
Definition ffplay.c:802
static int enable_vulkan
Definition ffplay.c:427
static double get_clock(Clock *c)
Definition ffplay.c:2070
static int cursor_hidden
Definition ffplay.c:420
#define SAMPLE_CORRECTION_PERCENT_MAX
Definition ffplay.c:90
static const char * subtitle_codec_name
Definition ffplay.c:416
#define VIDEO_PICTURE_QUEUE_SIZE
Definition ffplay.c:160
static int alwaysontop
Definition ffplay.c:394
static void set_clock_speed(Clock *c, double speed)
Definition ffplay.c:2096
static void chapter_list_draw(VideoState *is)
Definition ffplay.c:1590
static void calculate_display_rect(SDL_Rect *rect, int scr_xleft, int scr_ytop, int scr_width, int scr_height, int pic_width, int pic_height, AVRational pic_sar)
Definition ffplay.c:941
static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, double duration, int64_t pos, int serial)
Definition ffplay.c:2438
static int audio_disable
Definition ffplay.c:386
static void check_external_clock_speed(VideoState *is)
Definition ffplay.c:2153
static void sync_clock_to_slave(Clock *c, Clock *slave)
Definition ffplay.c:2110
static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
Definition ffplay.c:521
double rdftspeed
Definition ffplay.c:418
static void toggle_full_screen(VideoState *is)
Definition ffplay.c:4243
#define CHAPTER_LIST_HOLD_TIME
Definition ffplay.c:110
static void chapter_list_pin(VideoState *is, int pinned)
Definition ffplay.c:1519
static const char * wanted_stream_spec[AVMEDIA_TYPE_NB]
Definition ffplay.c:389
static int stream_has_enough_packets(AVStream *st, int stream_id, PacketQueue *queue)
Definition ffplay.c:3579
#define AV_SYNC_FRAMEDUP_THRESHOLD
Definition ffplay.c:85
static void sigterm_handler(int sig)
Definition ffplay.c:2012
static int synchronize_audio(VideoState *is, int nb_samples)
Definition ffplay.c:3016
static int read_thread(void *arg)
Definition ffplay.c:3661
static VkRenderer * vk_renderer
Definition ffplay.c:447
static void bprint_chapter_details(VideoState *is, AVBPrint *script, const ChapterListLayout *l)
Definition ffplay.c:1294
static void set_sdl_yuv_conversion_mode(AVFrame *frame)
Definition ffplay.c:1031
static int64_t start_time
Definition ffplay.c:398
static void bprint_chapter_cell(AVBPrint *script, const char *style, int x, int y, int right, int bottom, const char *text)
Definition ffplay.c:1205
int vk_renderer_create(VkRenderer *renderer, SDL_Window *window, AVDictionary *opt)
int vk_renderer_display(VkRenderer *renderer, AVFrame *frame, RenderParams *render_params)
VkRenderer * vk_get_renderer(void)
int vk_renderer_get_hw_dev(VkRenderer *renderer, AVBufferRef **dev)
int vk_renderer_resize(VkRenderer *renderer, int width, int height)
void vk_renderer_destroy(VkRenderer *renderer)
#define VIDEO_BACKGROUND_TILE_SIZE
@ VIDEO_BACKGROUND_TILES
@ VIDEO_BACKGROUND_NONE
@ VIDEO_BACKGROUND_COLOR
static const AVInputFormat * iformat
Definition ffprobe.c:346
static unsigned int nb_streams
Definition ffprobe.c:353
A generic FIFO API.
#define fail
Definition test.h:479
#define AV_OPT_FLAG_FILTERING_PARAM
A generic parameter which can be set by the user for filtering.
Definition opt.h:380
#define AV_OPT_FLAG_DECODING_PARAM
A generic parameter which can be set by the user for demuxing or decoding.
Definition opt.h:355
@ AV_OPT_TYPE_PIXEL_FMT
Underlying C type is enum AVPixelFormat.
Definition opt.h:306
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition opt.h:258
@ AV_OPT_TYPE_CHLAYOUT
Underlying C type is AVChannelLayout.
Definition opt.h:330
const AVBitStreamFilter * av_bsf_get_by_name(const char *name)
int av_bsf_sink_get_packet(AVBitStreamFilterContext *ctx, AVPacket *pkt, int flags)
Get a packet with filtered data from sink and put it in packet.
Definition sink.c:52
AVRational av_bsf_sink_get_time_base(const AVBitStreamFilterContext *ctx)
Definition sink.c:126
int av_bsf_source_parameters_set(AVBitStreamFilterContext *ctx, const AVCodecParameters *par)
Initialize the source filter with the provided parameters.
Definition source.c:46
av_warn_unused_result int av_bsf_source_add_packet(AVBitStreamFilterContext *ctx, AVPacket *pkt, int flags)
Add a packet to the buffer source.
Definition source.c:67
@ AV_BSF_SOURCE_FLAG_PUSH
Immediately push the packet to the output.
Definition bsf.h:594
int av_bsf_init_dict(AVBitStreamFilterContext *ctx, AVDictionary **options)
Initialize a filter with the supplied dictionary of options.
AVBitStreamFilterGraph * av_bsf_graph_alloc(void)
Allocate a filter graph.
Definition bsfgraph.c:48
int av_bsf_link(AVBitStreamFilterContext *src, unsigned srcpad, AVBitStreamFilterContext *dst, unsigned dstpad)
Link two filters together.
int av_bsf_graph_config(AVBitStreamFilterGraph *graphctx, void *log_ctx)
Check validity and configure all the links and formats in the graph.
Definition bsfgraph.c:294
void av_bsf_graph_free(AVBitStreamFilterGraph **graph)
Free a graph, destroy its links, and set *graph to NULL.
Definition bsfgraph.c:93
int av_bsf_graph_alloc_filter(AVBitStreamFilterContext **filt_ctx, const AVBitStreamFilter *filter, const char *name, AVBitStreamFilterGraph *graph)
Create a new filter instance in a filter graph.
Definition bsfgraph.c:139
int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options)
Initialize the AVCodecContext to use the given AVCodec.
Definition avcodec.c:144
#define AV_CODEC_FLAG2_FAST
Allow non spec compliant speedup tricks.
Definition avcodec.h:337
const AVClass * avcodec_get_class(void)
Get the AVClass for AVCodecContext.
Definition options.c:184
AVCodecContext * avcodec_alloc_context3(const AVCodec *codec)
Allocate an AVCodecContext and set its fields to default values.
Definition options.c:149
const AVCodec * avcodec_find_decoder(enum AVCodecID id)
Find a registered decoder with a matching codec ID.
Definition allcodecs.c:994
const AVCodec * avcodec_find_decoder_by_name(const char *name)
Find a registered decoder with the specified name.
Definition allcodecs.c:1022
void avsubtitle_free(AVSubtitle *sub)
Free all allocated data in the given subtitle struct.
Definition avcodec.c:421
const char * avcodec_get_name(enum AVCodecID id)
Get the name of a codec.
Definition utils.c:421
void avcodec_free_context(AVCodecContext **avctx)
Free the codec context and everything associated with it and write NULL to the provided pointer.
Definition options.c:164
int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame)
Alias for avcodec_receive_frame_flags(avctx, frame, 0).
Definition avcodec.c:720
int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt)
Supply raw packet data as input to a decoder.
Definition decode.c:734
int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, int *got_sub_ptr, const AVPacket *avpkt)
Decode a subtitle message.
Definition decode.c:939
@ AVDISCARD_ALL
discard all
Definition defs.h:246
@ AVDISCARD_DEFAULT
discard useless packets like 0 size packets in avi
Definition defs.h:241
void avcodec_flush_buffers(AVCodecContext *avctx)
Reset the internal codec state / flush internal buffers.
Definition avcodec.c:389
const AVPacketSideData * av_packet_side_data_get(const AVPacketSideData *sd, int nb_sd, enum AVPacketSideDataType type)
Get side information from a side data array.
Definition packet.c:570
@ AV_PKT_DATA_DISPLAYMATRIX
This side data contains a 3x3 transformation matrix describing an affine transformation that needs to...
Definition packet.h:105
void av_packet_free(AVPacket **pkt)
Free the packet, if the packet is reference counted, it will be unreferenced first.
Definition packet.c:74
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition packet.c:434
void av_packet_move_ref(AVPacket *dst, AVPacket *src)
Move every field in src to dst and reset src.
Definition packet.c:491
AVPacket * av_packet_alloc(void)
Allocate an AVPacket and set its fields to default values.
Definition packet.c:63
int av_packet_ref(AVPacket *dst, const AVPacket *src)
Setup a new reference to the data described by a given packet.
Definition packet.c:442
FF_VISIBILITY_POP_HIDDEN av_cold void avdevice_register_all(void)
Initialize libavdevice and register all the input and output devices.
Definition alldevices.c:67
int avformat_network_deinit(void)
Undo the initialization done by avformat_network_init.
Definition utils.c:589
int avformat_network_init(void)
Do global initialization of network libraries.
Definition utils.c:577
AVFormatContext * avformat_alloc_context(void)
Allocate an AVFormatContext.
Definition options.c:165
const AVClass * avformat_get_class(void)
Get the AVClass for AVFormatContext.
Definition options.c:193
const AVInputFormat * av_find_input_format(const char *short_name)
Find AVInputFormat based on the short name of the input format.
Definition format.c:146
AVProgram * av_find_program_from_stream(AVFormatContext *ic, AVProgram *last, int s)
Find the programs which belong to a given stream.
Definition avformat.c:454
int av_read_pause(AVFormatContext *s)
Pause a network-based stream (e.g.
int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
Seek to timestamp ts.
Definition seek.c:664
int av_read_frame(AVFormatContext *s, AVPacket *pkt)
Return the next frame of a stream.
Definition demux.c:1588
int av_read_play(AVFormatContext *s)
Start playing a network-based stream (e.g.
int avformat_open_input(AVFormatContext **ps, const char *url, const AVInputFormat *fmt, AVDictionary **options)
Open an input stream and read the header.
Definition demux.c:231
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
Read packets of a media file to get stream information.
Definition demux.c:2616
void avformat_close_input(AVFormatContext **s)
Close an opened input AVFormatContext.
Definition demux.c:377
AVRational av_guess_frame_rate(AVFormatContext *format, AVStream *st, AVFrame *frame)
Guess the frame rate, based on both the container and codec information.
Definition avformat.c:814
int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec)
Check if the stream st contained in s is matched by the stream specifier spec.
Definition avformat.c:745
void av_dump_format(AVFormatContext *ic, int index, const char *url, int is_output)
Print detailed information about the input or output format, such as duration, bitrate,...
Definition dump.c:852
AVRational av_guess_sample_aspect_ratio(AVFormatContext *format, AVStream *stream, AVFrame *frame)
Guess the sample aspect ratio of a frame, based on both the stream and the frame aspect ratio.
Definition avformat.c:791
int av_buffersink_get_sample_rate(const AVFilterContext *ctx)
AVRational av_buffersink_get_frame_rate(const AVFilterContext *ctx)
Definition buffersink.c:254
int av_buffersink_get_ch_layout(const AVFilterContext *ctx, AVChannelLayout *out)
Definition buffersink.c:274
AVRational av_buffersink_get_time_base(const AVFilterContext *ctx)
int attribute_align_arg av_buffersink_get_frame(AVFilterContext *ctx, AVFrame *frame)
Get a frame with filtered data from sink and put it in frame.
Definition buffersink.c:74
int attribute_align_arg av_buffersink_get_frame_flags(AVFilterContext *ctx, AVFrame *frame, int flags)
Get a frame with filtered data from sink and put it in frame.
Definition buffersink.c:135
int av_buffersrc_parameters_set(AVFilterContext *ctx, AVBufferSrcParameters *param)
Initialize the buffersrc or abuffersrc filter with the provided parameters.
Definition buffersrc.c:122
int attribute_align_arg av_buffersrc_add_frame(AVFilterContext *ctx, AVFrame *frame)
Add a frame to the buffer source.
Definition buffersrc.c:191
AVBufferSrcParameters * av_buffersrc_parameters_alloc(void)
Allocate a new AVBufferSrcParameters instance.
Definition buffersrc.c:108
int avfilter_init_str(AVFilterContext *filter, const char *args)
Initialize a filter with the supplied parameters.
Definition avfilter.c:960
int avfilter_graph_config(AVFilterGraph *graphctx, void *log_ctx)
Check validity and configure all the links and formats in the graph.
const AVFilter * avfilter_get_by_name(const char *name)
Get a filter definition matching the given name.
Definition allfilters.c:655
void avfilter_inout_free(AVFilterInOut **inout)
Free the supplied list of AVFilterInOut and set *inout to NULL.
Definition graphparser.c:76
int avfilter_graph_parse_ptr(AVFilterGraph *graph, const char *filters, AVFilterInOut **inputs, AVFilterInOut **outputs, void *log_ctx)
Add a graph described by a string to a graph.
AVFilterContext * avfilter_graph_alloc_filter(AVFilterGraph *graph, const AVFilter *filter, const char *name)
Create a new filter instance in a filter graph.
void avfilter_graph_free(AVFilterGraph **graph)
Free a graph, destroy its links, and set *graph to NULL.
int avfilter_init_dict(AVFilterContext *ctx, AVDictionary **options)
Initialize a filter with the supplied dictionary of options.
Definition avfilter.c:919
int avfilter_graph_send_command(AVFilterGraph *graph, const char *target, const char *cmd, const char *arg, char *res, int res_len, int flags)
Send a command to one or more filter instances.
int avfilter_link(AVFilterContext *src, unsigned srcpad, AVFilterContext *dst, unsigned dstpad)
Link two filters together.
Definition avfilter.c:149
int avfilter_graph_create_filter(AVFilterContext **filt_ctx, const AVFilter *filt, const char *name, const char *args, void *opaque, AVFilterGraph *graph_ctx)
A convenience wrapper that allocates and initializes a filter in a single step.
const AVClass * avfilter_get_class(void)
Definition avfilter.c:1663
AVFilterInOut * avfilter_inout_alloc(void)
Allocate a single AVFilterInOut entry.
Definition graphparser.c:71
AVFilterGraph * avfilter_graph_alloc(void)
Allocate a filter graph.
void av_channel_layout_default(AVChannelLayout *ch_layout, int nb_channels)
Get the default channel layout for a given number of channels.
int av_channel_layout_describe_bprint(const AVChannelLayout *channel_layout, AVBPrint *bp)
bprint variant of av_channel_layout_describe().
int av_channel_layout_compare(const AVChannelLayout *chl, const AVChannelLayout *chl1)
Check whether two channel layouts are semantically the same, i.e.
void av_channel_layout_uninit(AVChannelLayout *channel_layout)
Free any allocated data in the channel layout and reset the channel count to 0.
int av_channel_layout_describe(const AVChannelLayout *channel_layout, char *buf, size_t buf_size)
Get a human-readable string describing the channel layout properties.
int av_channel_layout_copy(AVChannelLayout *dst, const AVChannelLayout *src)
Make a copy of a channel layout.
@ AV_CHANNEL_ORDER_NATIVE
The native channel order, i.e.
static int av_bprint_is_complete(const AVBPrint *buf)
Test if the print buffer is complete (not truncated).
Definition bprint.h:218
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition bprint.c:234
void av_bprint_chars(AVBPrint *buf, char c, unsigned n)
Append char c n times to a print buffer.
Definition bprint.c:129
AVBufferRef * av_buffer_allocz(size_t size)
Same as av_buffer_alloc(), except the returned buffer will be initialized to zero.
Definition buffer.c:94
#define AV_DICT_MULTIKEY
Allow to store several equal keys in the dictionary.
Definition dict.h:84
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition dict.c:233
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
Definition dict.c:60
const AVDictionaryEntry * av_dict_iterate(const AVDictionary *m, const AVDictionaryEntry *prev)
Iterate over a dictionary.
Definition dict.c:42
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition dict.c:86
#define AV_DICT_DONT_OVERWRITE
Don't overwrite existing entries.
Definition dict.h:81
int av_dict_parse_string(AVDictionary **pm, const char *str, const char *key_val_sep, const char *pairs_sep, int flags)
Parse the key/value pairs list and add the parsed entries to a dictionary.
Definition dict.c:210
int av_dict_count(const AVDictionary *m)
Get number of entries in dictionary.
Definition dict.c:37
#define AV_DICT_MATCH_CASE
Only get an entry with exact-case key match.
Definition dict.h:74
int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags)
Convenience wrapper for av_dict_set() that converts the value to a string and stores it.
Definition dict.c:177
#define AVERROR_FILTER_NOT_FOUND
Filter not found.
Definition error.h:60
#define AVERROR_EXIT
Immediate exit was requested; the called function should not be restarted.
Definition error.h:58
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition error.h:59
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition error.h:52
#define AVERROR_EOF
End of file.
Definition error.h:57
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition error.h:122
#define AVERROR(e)
Definition error.h:45
AVFifo * av_fifo_alloc2(size_t nb_elems, size_t elem_size, unsigned int flags)
Allocate and initialize an AVFifo with a given element size.
Definition fifo.c:47
void av_fifo_freep2(AVFifo **f)
Free an AVFifo and reset pointer to NULL.
Definition fifo.c:286
#define AV_FIFO_FLAG_AUTO_GROW
Automatically resize the FIFO on writes, so that the data fits.
Definition fifo.h:63
int av_fifo_write(AVFifo *f, const void *buf, size_t nb_elems)
Write data into a FIFO.
Definition fifo.c:188
int av_fifo_read(AVFifo *f, void *buf, size_t nb_elems)
Read data from a FIFO.
Definition fifo.c:240
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition frame.c:496
AVFrameSideData * av_frame_get_side_data(const AVFrame *frame, enum AVFrameSideDataType type)
Definition frame.c:659
void av_frame_move_ref(AVFrame *dst, AVFrame *src)
Move everything contained in src to dst and reset src.
Definition frame.c:523
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition frame.c:64
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition frame.c:52
@ AV_FRAME_DATA_DISPLAYMATRIX
This side data contains a 3x3 transformation matrix describing an affine transformation that needs to...
Definition frame.h:85
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition log.h:236
#define AV_LOG_QUIET
Print no output.
Definition log.h:192
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_FATAL
Something went wrong and recovery is not possible.
Definition log.h:204
#define AV_LOG_VERBOSE
Detailed information.
Definition log.h:226
#define AV_LOG_INFO
Standard information.
Definition log.h:221
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
void av_log_set_callback(void(*callback)(void *, int, const char *, va_list))
Set the logging callback.
Definition log.c:491
#define AV_LOG_SKIP_REPEATED
Skip repeated messages, this requires the user app to use av_log() instead of (f)printf as the 2 woul...
Definition log.h:400
int av_log_get_level(void)
Get the current log level.
Definition log.c:471
void av_log_set_flags(int arg)
Definition log.c:481
AVRational av_mul_q(AVRational b, AVRational c)
Multiply two rationals.
Definition rational.c:80
static AVRational av_make_q(int num, int den)
Create an AVRational.
Definition rational.h:71
static double av_q2d(AVRational a)
Convert an AVRational to a double.
Definition rational.h:104
static int av_cmp_q(AVRational a, AVRational b)
Compare two rationals.
Definition rational.h:89
int av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b)
Compare two timestamps each in its own time base.
int64_t av_rescale(int64_t a, int64_t b, int64_t c)
Rescale a 64-bit integer with rounding to nearest.
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size)
Allocate a buffer, reusing the given one if large enough.
Definition mem.c:661
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
Definition mem.c:318
const char * av_get_media_type_string(enum AVMediaType media_type)
Return a string describing the media_type enum, NULL if media_type is unknown.
Definition utils.c:28
AVMediaType
Definition avutil.h:198
static void * av_x_if_null(const void *p, const void *x)
Return x default pointer in case p is NULL.
Definition avutil.h:311
@ AVMEDIA_TYPE_AUDIO
Definition avutil.h:201
@ AVMEDIA_TYPE_NB
Definition avutil.h:205
@ AVMEDIA_TYPE_SUBTITLE
Definition avutil.h:203
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
char av_get_picture_type_char(enum AVPictureType pict_type)
Return a single letter to describe the given picture type pict_type.
Definition utils.c:40
int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt)
Return number of bytes per sample.
Definition samplefmt.c:109
enum AVSampleFormat av_get_packed_sample_fmt(enum AVSampleFormat sample_fmt)
Get the packed alternative form of the given sample format.
Definition samplefmt.c:78
int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples, enum AVSampleFormat sample_fmt, int align)
Get the required buffer size for the given audio parameters.
Definition samplefmt.c:122
const char * av_get_sample_fmt_name(enum AVSampleFormat sample_fmt)
Return the name of sample_fmt, or NULL if sample_fmt is not recognized.
Definition samplefmt.c:52
AVSampleFormat
Audio sample formats.
Definition samplefmt.h:55
@ AV_SAMPLE_FMT_S16
signed 16 bits
Definition samplefmt.h:58
size_t av_strlcat(char *dst, const char *src, size_t size)
Append the string src to the string dst, but to a total length of no more than size - 1 bytes,...
Definition avstring.c:95
char * av_stristr(const char *s1, const char *s2)
Locate the first case-independent occurrence in the string haystack of the string needle.
Definition avstring.c:58
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition avstring.c:208
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition avutil.h:247
#define AV_TIME_BASE
Internal time base represented as integer.
Definition avutil.h:253
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition avutil.h:263
SwsContext * sws_getCachedContext(SwsContext *context, int srcW, int srcH, enum AVPixelFormat srcFormat, int dstW, int dstH, enum AVPixelFormat dstFormat, int flags, SwsFilter *srcFilter, SwsFilter *dstFilter, const double *param)
Check if context can be reused, otherwise reallocate a new one.
Definition utils.c:2340
int attribute_align_arg sws_scale(SwsContext *sws, const uint8_t *const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[])
swscale wrapper, so we don't need to export the SwsContext.
Definition swscale.c:1638
void sws_freeContext(SwsContext *swsContext)
Free the swscaler context swsContext.
Definition utils.c:2259
int swr_alloc_set_opts2(struct SwrContext **ps, const AVChannelLayout *out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate, const AVChannelLayout *in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate, int log_offset, void *log_ctx)
Allocate SwrContext if needed and set/reset common parameters.
Definition swresample.c:54
av_cold void swr_free(SwrContext **ss)
Free the given SwrContext and set the pointer to NULL.
Definition swresample.c:137
int swr_set_compensation(struct SwrContext *s, int sample_delta, int compensation_distance)
Activate resampling compensation ("soft" compensation).
Definition swresample.c:931
int attribute_align_arg swr_convert(struct SwrContext *s, uint8_t *const *out_arg, int out_count, const uint8_t *const *in_arg, int in_count)
Convert audio.
Definition swresample.c:743
av_cold int swr_init(struct SwrContext *s)
Initialize context after user parameters have been set.
Definition swresample.c:156
#define AV_OPT_SEARCH_CHILDREN
Search in possible children of the given object first.
Definition opt.h:604
int av_opt_set_int(void *obj, const char *name, int64_t val, int search_flags)
Definition opt.c:938
int av_opt_set_q(void *obj, const char *name, AVRational val, int search_flags)
Definition opt.c:948
int av_opt_set_array(void *obj, const char *name, int search_flags, unsigned int start_elem, unsigned int nb_elems, enum AVOptionType val_type, const void *val)
Add, replace, or remove elements for an array option.
Definition opt.c:2351
int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
Definition opt.c:891
int index
Definition gxfenc.c:90
int a
int av_hwdevice_ctx_create(AVBufferRef **pdevice_ref, enum AVHWDeviceType type, const char *device, AVDictionary *opts, int flags)
Open a device of the specified type and create an AVHWDeviceContext for it.
Definition hwcontext.c:615
int av_hwdevice_ctx_create_derived(AVBufferRef **dst_ref_ptr, enum AVHWDeviceType type, AVBufferRef *src_ref, int flags)
Create a new device of the specified type from an existing device.
Definition hwcontext.c:718
enum AVHWDeviceType av_hwdevice_find_type_by_name(const char *name)
Look up an AVHWDeviceType by name.
Definition hwcontext.c:110
AVHWDeviceType
Definition hwcontext.h:27
@ AV_HWDEVICE_TYPE_NONE
Definition hwcontext.h:28
cl_device_type type
static const int16_t alpha[]
Definition ilbcdata.h:55
#define r
Definition input.c:42
#define b
Definition input.c:43
#define av_log2
Definition intmath.h:84
static int lcevc_merge(FFPacketSync *fs)
Definition lcevc_merge.c:85
const char * arg
Definition jacosubdec.c:65
Macro definitions for various function/variable attributes.
#define av_fallthrough
Definition attributes.h:67
#define av_unused
Definition attributes.h:164
static enum AVPixelFormat pix_fmts[]
Definition libkvazaar.c:296
uint8_t w
Definition llvidencdsp.c:39
#define FFSWAP(type, a, b)
Definition macros.h:52
#define FFMIN(a, b)
Definition macros.h:49
#define FFMAX(a, b)
Definition macros.h:47
#define FFDIFFSIGN(x, y)
Comparator.
Definition macros.h:45
#define NAN
void * av_calloc(size_t nmemb, size_t size)
Definition mem.c:370
Memory handling functions.
static av_always_inline int cmp(MPVEncContext *const s, const int x, const int y, const int subx, const int suby, const int size, const int h, int ref_index, int src_index, me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags)
compares a block (either a full macroblock or a partition thereof) against a proposed motion-compensa...
Definition motion_est.c:263
uint32_t tag
Definition movenc.c:2127
const char data[16]
Definition mxf.c:149
#define av_strdup(s)
Definition ops_static.c:55
AVOptions.
#define CMDUTILS_COMMON_OPTIONS
Definition opt_common.h:199
int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen, void *log_ctx)
Put the RGBA values that correspond to color_string in rgba_color.
Definition parseutils.c:359
misc parsing utilities
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
Definition pixdesc.c:3380
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3460
#define AV_PIX_FMT_0RGB32
Definition pixfmt.h:521
@ AVCOL_RANGE_JPEG
Full range content.
Definition pixfmt.h:783
#define AV_PIX_FMT_BGR555
Definition pixfmt.h:538
AVAlphaMode
Correlation between the alpha channel and color values.
Definition pixfmt.h:816
@ AVALPHA_MODE_STRAIGHT
Alpha channel is independent of color values.
Definition pixfmt.h:819
@ AVALPHA_MODE_UNSPECIFIED
Unknown alpha handling, or no alpha channel.
Definition pixfmt.h:817
#define AV_PIX_FMT_BGR32
Definition pixfmt.h:519
AVPixelFormat
Pixel format.
Definition pixfmt.h:71
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition pixfmt.h:75
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition pixfmt.h:73
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition pixfmt.h:102
@ AV_PIX_FMT_UYVY422
packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
Definition pixfmt.h:88
@ AV_PIX_FMT_RGB8
packed RGB 3:3:2, 8bpp, (msb)3R 3G 2B(lsb)
Definition pixfmt.h:93
@ AV_PIX_FMT_YUYV422
packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
Definition pixfmt.h:74
@ AV_PIX_FMT_PAL8
8 bits with AV_PIX_FMT_RGB32 palette
Definition pixfmt.h:84
@ AV_PIX_FMT_BGR24
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition pixfmt.h:76
#define AV_PIX_FMT_RGB32_1
Definition pixfmt.h:518
#define AV_PIX_FMT_BGR32_1
Definition pixfmt.h:520
#define AV_PIX_FMT_BGR565
Definition pixfmt.h:537
#define AV_PIX_FMT_RGB565
Definition pixfmt.h:532
#define AV_PIX_FMT_RGB444
Definition pixfmt.h:534
#define AV_PIX_FMT_NE(be, le)
Definition pixfmt.h:514
#define AV_PIX_FMT_0BGR32
Definition pixfmt.h:522
#define AV_PIX_FMT_RGB32
Definition pixfmt.h:517
#define AV_PIX_FMT_RGB555
Definition pixfmt.h:533
AVColorSpace
YUV colorspace type.
Definition pixfmt.h:706
@ AVCOL_SPC_BT709
also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / derived in SMPTE RP 177 Annex B
Definition pixfmt.h:708
@ AVCOL_SPC_BT470BG
also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601
Definition pixfmt.h:712
@ AVCOL_SPC_SMPTE170M
also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC / functionally identical to above
Definition pixfmt.h:713
const char * name
Definition qsvenc.c:142
enum AVMediaType codec_type
Definition rtp.c:37
static volatile sig_atomic_t sig
Definition signal.c:48
#define FF_ARRAY_ELEMS(a)
unsigned int pos
Definition spdifenc.c:431
An instance of a filter.
Definition bsf.h:347
void * priv_data
Opaque filter-specific private data.
Definition bsf.h:375
A reference to a data buffer.
Definition buffer.h:82
uint8_t * data
The data buffer.
Definition buffer.h:90
This structure contains the parameters describing the frames that will be passed to this filter.
Definition buffersrc.h:73
AVRational frame_rate
Video only, the frame rate of the input video.
Definition buffersrc.h:100
enum AVColorRange color_range
Definition buffersrc.h:122
int format
video: the pixel format, value corresponds to enum AVPixelFormat audio: the sample format,...
Definition buffersrc.h:78
int width
Video only, the display dimensions of the input frames.
Definition buffersrc.h:87
enum AVColorSpace color_space
Video only, the YUV colorspace and range.
Definition buffersrc.h:121
enum AVAlphaMode alpha_mode
Video only, the alpha mode.
Definition buffersrc.h:130
AVRational time_base
The timebase to be used for the timestamps on the input frames.
Definition buffersrc.h:82
AVBufferRef * hw_frames_ctx
Video with a hwaccel pixel format only.
Definition buffersrc.h:106
AVRational sample_aspect_ratio
Video only, the sample (pixel) aspect ratio.
Definition buffersrc.h:92
An AVChannelLayout holds information about the channel layout of audio data.
enum AVChannelOrder order
Channel order used in this layout.
int nb_channels
Number of channels in this layout.
int64_t start
Definition avformat.h:1297
AVDictionary * metadata
Definition avformat.h:1298
int64_t end
chapter start/end time in time_base units
Definition avformat.h:1297
AVRational time_base
time base in which the start/end timestamps are specified
Definition avformat.h:1296
main external API structure.
Definition avcodec.h:443
AVChannelLayout ch_layout
Audio channel layout.
Definition avcodec.h:1055
int flags2
AV_CODEC_FLAG2_*.
Definition avcodec.h:507
enum AVSampleFormat sample_fmt
audio sample format
Definition avcodec.h:1047
AVRational pkt_timebase
Timebase in which pkt_dts/pts and AVPacket.dts/pts are expressed.
Definition avcodec.h:554
enum AVMediaType codec_type
Definition avcodec.h:451
int sample_rate
samples per second
Definition avcodec.h:1040
AVBufferRef * hw_device_ctx
A reference to the AVHWDeviceContext describing the device which will be used by a hardware encoder/d...
Definition avcodec.h:1494
enum AVCodecID codec_id
Definition avcodec.h:453
int lowres
low resolution decoding, 1-> 1/2 size, 2->1/4 size
Definition avcodec.h:1707
This struct describes the properties of an encoded stream.
Definition codec_par.h:49
int height
The height of the video frame in pixels.
Definition codec_par.h:150
AVChannelLayout ch_layout
The channel layout and number of channels.
Definition codec_par.h:207
int width
The width of the video frame in pixels.
Definition codec_par.h:143
enum AVMediaType codec_type
General type of the encoded data.
Definition codec_par.h:53
AVRational sample_aspect_ratio
The aspect ratio (width/height) which a single pixel should have when displayed.
Definition codec_par.h:161
int sample_rate
The number of audio samples per second.
Definition codec_par.h:213
AVCodec.
Definition codec.h:175
enum AVCodecID id
Definition codec.h:189
uint8_t max_lowres
maximum value for lowres supported by the decoder
Definition codec.h:195
int offset
Number of elements before the component of the first pixel.
Definition pixdesc.h:46
char * key
Definition dict.h:91
char * value
Definition dict.h:92
Definition fifo.c:35
An instance of a filter.
Definition avfilter.h:273
unsigned nb_filters
Definition avfilter.h:564
char * scale_sws_opts
sws options to use for the auto-inserted scale filters
Definition avfilter.h:566
AVFilterContext ** filters
Definition avfilter.h:563
int nb_threads
Maximum number of threads used by filters in this graph.
Definition avfilter.h:587
A linked-list of the inputs/outputs of the filter chain.
Definition avfilter.h:718
Filter definition.
Definition avfilter.h:215
Format I/O context.
Definition avformat.h:1335
int event_flags
Flags indicating events happening on the file, a combination of AVFMT_EVENT_FLAG_*.
Definition avformat.h:1722
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
Definition avformat.h:1391
AVStreamGroup ** stream_groups
A list of all stream groups in the file.
Definition avformat.h:1422
AVIOContext * pb
I/O context.
Definition avformat.h:1377
int64_t start_time
Position of the first frame of the component, in AV_TIME_BASE fractional seconds.
Definition avformat.h:1460
AVDictionary * metadata
Metadata that applies to the whole file.
Definition avformat.h:1582
int flags
Flags modifying the (de)muxer behaviour.
Definition avformat.h:1486
AVIOInterruptCB interrupt_callback
Custom interrupt callbacks for the I/O layer.
Definition avformat.h:1620
const struct AVInputFormat * iformat
The input container format.
Definition avformat.h:1347
unsigned int nb_chapters
Number of chapters in AVChapter array.
Definition avformat.h:1435
void * opaque
User data.
Definition avformat.h:1914
int64_t bit_rate
Total stream bitrate in bit/s, 0 if not available.
Definition avformat.h:1477
unsigned int nb_stream_groups
Number of elements in AVFormatContext.stream_groups.
Definition avformat.h:1410
AVStream ** streams
A list of all streams in the file.
Definition avformat.h:1403
int64_t duration
Duration of the stream, in AV_TIME_BASE fractional seconds.
Definition avformat.h:1470
Structure to hold side data for an AVFrame.
Definition frame.h:327
uint8_t * data
Definition frame.h:329
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
int nb_samples
number of audio samples (per channel) described by this frame
Definition frame.h:552
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition frame.h:493
int width
Definition frame.h:544
int height
Definition frame.h:544
AVRational sample_aspect_ratio
Sample aspect ratio for the video frame, 0/1 if unknown/unspecified.
Definition frame.h:569
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition frame.h:517
int sample_rate
Sample rate of the audio data.
Definition frame.h:635
AVChannelLayout ch_layout
Channel layout of the audio data.
Definition frame.h:815
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames,...
Definition frame.h:559
enum AVPictureType pict_type
Picture type of the frame.
Definition frame.h:564
uint8_t ** extended_data
pointers to the data planes/channels.
Definition frame.h:533
int eof_reached
true if was unable to read due to error or eof
Definition avio.h:238
int error
contains the error code or 0 if no error happened
Definition avio.h:239
void * opaque
Definition avio.h:61
int(* callback)(void *)
Definition avio.h:60
int flags
Can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_EXPERIMENTAL, AVFMT_SHOW_IDS,...
Definition avformat.h:587
const char * name
A comma separated list of short names for the format.
Definition avformat.h:572
This structure stores auxiliary information for decoding, presenting, or otherwise processing the cod...
Definition packet.h:424
uint8_t * data
Definition packet.h:425
This structure stores compressed data.
Definition packet.h:580
AVBufferRef * buf
A reference to the reference-counted buffer where the packet data is stored.
Definition packet.h:586
int size
Definition packet.h:604
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition packet.h:621
AVBufferRef * opaque_ref
AVBufferRef for free use by the API user.
Definition packet.h:639
uint8_t * data
Definition packet.h:603
int64_t pos
byte position in stream, -1 if unknown
Definition packet.h:623
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
Definition pixdesc.h:105
New fields can be added to the end with minor version bumps.
Definition avformat.h:1259
Rational number (pair of numerator and denominator).
Definition rational.h:58
int num
Numerator.
Definition rational.h:59
int den
Denominator.
Definition rational.h:60
AVStreamGroupLayeredVideo is meant to define the relation between a base layer video stream and a sep...
Definition avformat.h:1095
unsigned int el_index
Index of the enhancement layer stream in AVStreamGroup.
Definition avformat.h:1104
union AVStreamGroup::@166361102046003066253145020066347265153020354020 params
Group type-specific parameters.
enum AVStreamGroupParamsType type
Group type.
Definition avformat.h:1188
unsigned int nb_streams
Number of elements in AVStreamGroup.streams.
Definition avformat.h:1223
AVStream ** streams
A list of streams in the group.
Definition avformat.h:1236
struct AVStreamGroupLayeredVideo * layered_video
Definition avformat.h:1197
Stream structure.
Definition avformat.h:768
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition avformat.h:791
enum AVDiscard discard
Selects which packets can be discarded at will and do not need to be demuxed.
Definition avformat.h:839
AVDictionary * metadata
Definition avformat.h:848
int index
stream index in AVFormatContext
Definition avformat.h:774
int64_t start_time
Decoding: pts of the first frame of the stream in presentation order, in stream time base.
Definition avformat.h:817
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
Definition avformat.h:807
int event_flags
Flags indicating events happening on the stream, a combination of AVSTREAM_EVENT_FLAG_*.
Definition avformat.h:879
int disposition
Stream disposition - a combination of AV_DISPOSITION_* flags.
Definition avformat.h:837
int x
top left corner of pict, undefined when pict is not set
Definition avcodec.h:2076
int w
width of pict, undefined when pict is not set
Definition avcodec.h:2078
uint8_t * data[4]
data+linesize for the bitmap of this subtitle.
Definition avcodec.h:2086
int y
top left corner of pict, undefined when pict is not set
Definition avcodec.h:2077
int linesize[4]
Definition avcodec.h:2087
int h
height of pict, undefined when pict is not set
Definition avcodec.h:2079
uint16_t format
Definition avcodec.h:2103
uint32_t start_display_time
Definition avcodec.h:2104
uint32_t end_display_time
Definition avcodec.h:2105
unsigned num_rects
Definition avcodec.h:2106
AVSubtitleRect ** rects
Definition avcodec.h:2107
int64_t pts
Same as packet pts, in AV_TIME_BASE.
Definition avcodec.h:2108
int bytes_per_sec
Definition ffplay.c:170
int frame_size
Definition ffplay.c:169
enum AVSampleFormat fmt
Definition ffplay.c:168
AVChannelLayout ch_layout
Definition ffplay.c:167
int button_y[CHAPTER_SORT_NB]
Definition ffplay.c:1215
int button_x[CHAPTER_SORT_NB]
Definition ffplay.c:1215
int index
Definition ffplay.c:128
const char * artist
Definition ffplay.c:129
int64_t length
Definition ffplay.c:131
const char * title
Definition ffplay.c:130
int serial
Definition ffplay.c:178
double pts
Definition ffplay.c:174
double pts_drift
Definition ffplay.c:175
double last_updated
Definition ffplay.c:176
int paused
Definition ffplay.c:179
double speed
Definition ffplay.c:177
int * queue_serial
Definition ffplay.c:180
SDL_cond * empty_queue_cond
Definition ffplay.c:247
int64_t start_pts
Definition ffplay.c:248
int64_t next_pts
Definition ffplay.c:250
PacketQueue * queue
Definition ffplay.c:242
int packet_pending
Definition ffplay.c:246
int finished
Definition ffplay.c:245
SDL_Thread * decoder_tid
Definition ffplay.c:252
AVCodecContext * avctx
Definition ffplay.c:243
AVRational next_pts_tb
Definition ffplay.c:251
AVRational start_pts_tb
Definition ffplay.c:249
int pkt_serial
Definition ffplay.c:244
AVPacket * pkt
Definition ffplay.c:241
Stream ** streams
Definition ffplay.c:228
int nb_stream_groups
Definition ffplay.c:231
int nb_streams
Definition ffplay.c:229
StreamGroup ** stream_groups
Definition ffplay.c:230
int64_t pkt_pos
Definition ffplay.c:184
SDL_mutex * mutex
Definition ffplay.c:211
SDL_cond * cond
Definition ffplay.c:212
int keep_last
Definition ffplay.c:209
PacketQueue * pktq
Definition ffplay.c:213
int rindex
Definition ffplay.c:205
int size
Definition ffplay.c:207
int rindex_shown
Definition ffplay.c:210
Frame queue[FRAME_QUEUE_SIZE]
Definition ffplay.c:204
int windex
Definition ffplay.c:206
int max_size
Definition ffplay.c:208
int width
Definition ffplay.c:195
AVRational sar
Definition ffplay.c:198
int uploaded
Definition ffplay.c:199
AVFrame * frame
Definition ffplay.c:189
double duration
Definition ffplay.c:193
int serial
Definition ffplay.c:191
int height
Definition ffplay.c:196
int64_t pos
Definition ffplay.c:194
AVSubtitle sub
Definition ffplay.c:190
int format
Definition ffplay.c:197
double pts
Definition ffplay.c:192
int flip_v
Definition ffplay.c:200
AVPacket * pkt
Definition ffplay.c:145
int serial
Definition ffplay.c:155
AVFifo * pkt_list
Definition ffplay.c:150
SDL_mutex * mutex
Definition ffplay.c:156
SDL_cond * cond
Definition ffplay.c:157
int64_t duration
Definition ffplay.c:153
int abort_request
Definition ffplay.c:154
int nb_packets
Definition ffplay.c:151
Definition cms.c:66
AVBitStreamFilterContext * sink
Definition ffplay.c:219
AVBitStreamFilterGraph * graph
Definition ffplay.c:218
AVStreamGroup * stg
Definition ffplay.c:217
StreamGroup * group
Definition ffplay.c:223
AVBitStreamFilterContext * filter
Definition ffplay.c:224
The libswresample context.
Main external API structure.
Definition swscale.h:227
enum AVPixelFormat format
Definition ffplay.c:450
int chapter_pin_requested
Definition ffplay.c:341
AVFilterContext * out_video_filter
Definition ffplay.c:366
float * real_data
Definition ffplay.c:320
AVFilterContext * chapter_sink
Definition ffplay.c:331
int last_i_start
Definition ffplay.c:316
struct AudioParams audio_src
Definition ffplay.c:304
int xpos
Definition ffplay.c:322
AVFilterGraph * agraph
Definition ffplay.c:369
int height
Definition ffplay.c:361
int last_paused
Definition ffplay.c:261
int16_t sample_array[SAMPLE_ARRAY_SIZE]
Definition ffplay.c:314
int chapter_playing
Definition ffplay.c:336
Decoder auddec
Definition ffplay.c:279
AVTXContext * rdft
Definition ffplay.c:317
int abort_request
Definition ffplay.c:258
int width
Definition ffplay.c:361
int chapter_mouse_y
Definition ffplay.c:337
SDL_Rect chapter_rect
Definition ffplay.c:329
int subtitle_stream
Definition ffplay.c:346
int av_sync_type
Definition ffplay.c:285
RenderParams render_params
Definition ffplay.c:324
int xleft
Definition ffplay.c:361
SDL_Texture * chapter_texture
Definition ffplay.c:328
SDL_Texture * vid_texture
Definition ffplay.c:327
int nb_chapter_rows
Definition ffplay.c:333
unsigned int audio_buf_size
Definition ffplay.c:298
int64_t chapter_fade_start
Definition ffplay.c:342
int vfilter_idx
Definition ffplay.c:364
enum VideoState::ShowMode show_mode
int audio_stream
Definition ffplay.c:283
int paused
Definition ffplay.c:260
int audio_volume
Definition ffplay.c:302
AVStream * video_st
Definition ffplay.c:354
struct AudioParams audio_tgt
Definition ffplay.c:306
Clock audclk
Definition ffplay.c:271
AVStream * audio_st
Definition ffplay.c:293
double audio_diff_cum
Definition ffplay.c:289
int rdft_bits
Definition ffplay.c:319
const AVInputFormat * iformat
Definition ffplay.c:257
double audio_diff_threshold
Definition ffplay.c:291
int read_pause_return
Definition ffplay.c:267
Clock extclk
Definition ffplay.c:273
double audio_diff_avg_coef
Definition ffplay.c:290
AVFilterContext * out_audio_filter
Definition ffplay.c:368
Decoder subdec
Definition ffplay.c:281
int sample_array_index
Definition ffplay.c:315
int frame_drops_late
Definition ffplay.c:309
int audio_buf_index
Definition ffplay.c:300
double frame_timer
Definition ffplay.c:350
int64_t seek_pos
Definition ffplay.c:265
double max_frame_duration
Definition ffplay.c:356
double frame_last_returned_time
Definition ffplay.c:351
int chapter_selected
Definition ffplay.c:335
struct SwrContext * swr_ctx
Definition ffplay.c:307
SDL_Texture * vis_texture
Definition ffplay.c:325
int step
Definition ffplay.c:362
int chapter_pinned
Definition ffplay.c:340
int frame_drops_early
Definition ffplay.c:308
struct AudioParams audio_filter_src
Definition ffplay.c:305
int audio_hw_buf_size
Definition ffplay.c:295
SDL_cond * continue_read_thread
Definition ffplay.c:373
int ytop
Definition ffplay.c:361
FrameQueue subpq
Definition ffplay.c:276
int chapter_render_pending
Definition ffplay.c:339
AVFormatContext * ic
Definition ffplay.c:268
@ SHOW_MODE_VIDEO
Definition ffplay.c:312
@ SHOW_MODE_NONE
Definition ffplay.c:312
@ SHOW_MODE_RDFT
Definition ffplay.c:312
@ SHOW_MODE_NB
Definition ffplay.c:312
@ SHOW_MODE_WAVES
Definition ffplay.c:312
Decoder viddec
Definition ffplay.c:280
AVComplexFloat * rdft_data
Definition ffplay.c:321
int audio_diff_avg_count
Definition ffplay.c:292
FrameQueue pictq
Definition ffplay.c:275
uint8_t * audio_buf1
Definition ffplay.c:297
ChapterListHit chapter_hover
Definition ffplay.c:338
char * filename
Definition ffplay.c:360
int last_subtitle_stream
Definition ffplay.c:371
AVFilterGraph * chapter_graph
Definition ffplay.c:330
int64_t chapter_last_input
Definition ffplay.c:343
PacketQueue subtitleq
Definition ffplay.c:348
double chapter_drawn_alpha
Definition ffplay.c:344
int realtime
Definition ffplay.c:269
int video_stream
Definition ffplay.c:353
int muted
Definition ffplay.c:303
int force_refresh
Definition ffplay.c:259
char chapter_search[64]
Definition ffplay.c:334
int seek_flags
Definition ffplay.c:264
double frame_last_filter_delay
Definition ffplay.c:352
int last_video_stream
Definition ffplay.c:371
int audio_clock_serial
Definition ffplay.c:288
int chapter_mouse_x
Definition ffplay.c:337
AVStream * subtitle_st
Definition ffplay.c:347
unsigned int audio_buf1_size
Definition ffplay.c:299
av_tx_fn rdft_fn
Definition ffplay.c:318
struct SwsContext * sub_convert_ctx
Definition ffplay.c:357
int last_audio_stream
Definition ffplay.c:371
double last_vis_time
Definition ffplay.c:323
int64_t seek_rel
Definition ffplay.c:266
PacketQueue audioq
Definition ffplay.c:294
AVFilterContext * in_video_filter
Definition ffplay.c:365
ChapterRow * chapter_rows
Definition ffplay.c:332
PacketQueue videoq
Definition ffplay.c:355
int audio_write_buf_size
Definition ffplay.c:301
double audio_clock
Definition ffplay.c:287
int seek_req
Definition ffplay.c:263
int queue_attachments_req
Definition ffplay.c:262
SDL_Thread * read_tid
Definition ffplay.c:256
SDL_Texture * sub_texture
Definition ffplay.c:326
uint8_t * audio_buf
Definition ffplay.c:296
int eof
Definition ffplay.c:358
FrameQueue sampq
Definition ffplay.c:277
AVFilterContext * in_audio_filter
Definition ffplay.c:367
Clock vidclk
Definition ffplay.c:272
Definition swscale.c:71
int w
Definition f_ebur128.c:78
int y
Definition f_ebur128.c:78
int h
Definition f_ebur128.c:78
int x
Definition f_ebur128.c:78
libswresample public header
external API header
#define lrint
Definition tablegen.h:53
#define av_free(p)
#define av_malloc_array(a, b)
#define av_mallocz(s)
#define av_freep(p)
#define av_log(a,...)
void(* filter)(uint8_t *src, ptrdiff_t stride, int qscale)
Definition h263dsp.c:29
#define src
Definition vp8dsp.c:248
#define height
Definition dsp.h:89
#define width
Definition dsp.h:89
int av_usleep(unsigned usec)
Sleep for a period of time.
Definition time.c:93
int64_t av_gettime_relative(void)
Get the current time in microseconds since some unspecified starting point.
Definition time.c:57
static int64_t pts
int size
av_cold void av_tx_uninit(AVTXContext **ctx)
Frees a context and sets *ctx to NULL, does nothing when *ctx == NULL.
Definition tx.c:295
av_cold int av_tx_init(AVTXContext **ctx, av_tx_fn *tx, enum AVTXType type, int inv, int len, const void *scale, uint64_t flags)
Initialize a transform context with the given configuration (i)MDCTs with an odd length are currently...
Definition tx.c:903
@ AV_TX_FLOAT_RDFT
Real to complex and complex to real DFTs.
Definition tx.h:90
void(* av_tx_fn)(AVTXContext *s, void *out, void *in, ptrdiff_t stride)
Function pointer to a function to perform the transform.
Definition tx.h:151
static av_always_inline int diff(const struct color_info *a, const struct color_info *b, const int trans_thresh)
float delta
int len
static double c[64]