Skip to content
Snippets Groups Projects
ffplay.c 73.7 KiB
Newer Older
Fabrice Bellard's avatar
Fabrice Bellard committed
/*
 * FFplay : Simple Media Player based on the ffmpeg libraries
 * Copyright (c) 2003 Fabrice Bellard
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#define HAVE_AV_CONFIG_H
#include "avformat.h"

#include "cmdutils.h"

#include <SDL.h>
#include <SDL_thread.h>

#ifdef CONFIG_WIN32
#undef main /* We don't want SDL to override our main() */
#endif

#ifdef CONFIG_OS2
#define INCL_DOS
 #include <os2.h>
 #include <stdio.h>
 
 void MorphToPM()
 {
   PPIB pib;
   PTIB tib;
 
   DosGetInfoBlocks(&tib, &pib);
 
   // Change flag from VIO to PM:
   if (pib->pib_ultype==2) pib->pib_ultype = 3;
 }
#endif

Fabrice Bellard's avatar
Fabrice Bellard committed
#if defined(__linux__)
#define HAVE_X11
#endif

#ifdef HAVE_X11
#include <X11/Xlib.h>
#endif

Fabrice Bellard's avatar
Fabrice Bellard committed
#define MAX_VIDEOQ_SIZE (5 * 256 * 1024)
#define MAX_AUDIOQ_SIZE (5 * 16 * 1024)
#define MAX_SUBTITLEQ_SIZE (5 * 16 * 1024)
/* SDL audio buffer size, in samples. Should be small to have precise
   A/V sync as SDL does not have hardware buffer fullness info. */
#define SDL_AUDIO_BUFFER_SIZE 1024

/* no AV sync correction is done if below the AV sync threshold */
#define AV_SYNC_THRESHOLD 0.01
/* no AV correction is done if too big error */
#define AV_NOSYNC_THRESHOLD 10.0

/* maximum audio speed change to get correct sync */
#define SAMPLE_CORRECTION_PERCENT_MAX 10

/* we use about AUDIO_DIFF_AVG_NB A-V differences to make the average */
#define AUDIO_DIFF_AVG_NB   20

Fabrice Bellard's avatar
Fabrice Bellard committed
/* NOTE: the size must be big enough to compensate the hardware audio buffersize size */
#define SAMPLE_ARRAY_SIZE (2*65536)

typedef struct PacketQueue {
    AVPacketList *first_pkt, *last_pkt;
    int nb_packets;
    int size;
    int abort_request;
    SDL_mutex *mutex;
    SDL_cond *cond;
} PacketQueue;

#define VIDEO_PICTURE_QUEUE_SIZE 1
Fabrice Bellard's avatar
Fabrice Bellard committed

typedef struct VideoPicture {
    double pts; /* presentation time stamp for this picture */
Fabrice Bellard's avatar
Fabrice Bellard committed
    SDL_Overlay *bmp;
    int width, height; /* source height & width */
    int allocated;
} VideoPicture;

typedef struct SubPicture {
    double pts; /* presentation time stamp for this picture */
    AVSubtitle sub;
} SubPicture;

Fabrice Bellard's avatar
Fabrice Bellard committed
enum {
    AV_SYNC_AUDIO_MASTER, /* default choice */
    AV_SYNC_VIDEO_MASTER,
    AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */
Fabrice Bellard's avatar
Fabrice Bellard committed
};

typedef struct VideoState {
    SDL_Thread *parse_tid;
    SDL_Thread *video_tid;
Fabrice Bellard's avatar
Fabrice Bellard committed
    int no_background;
    int abort_request;
    int paused;
Fabrice Bellard's avatar
Fabrice Bellard committed
    int seek_req;
    int seek_flags;
Fabrice Bellard's avatar
Fabrice Bellard committed
    int64_t seek_pos;
Fabrice Bellard's avatar
Fabrice Bellard committed
    AVFormatContext *ic;
    int dtg_active_format;

    int audio_stream;
    
    int av_sync_type;
    double external_clock; /* external clock base */
    int64_t external_clock_time;
    
    double audio_clock;
    double audio_diff_cum; /* used for AV difference average computation */
    double audio_diff_avg_coef;
    double audio_diff_threshold;
    int audio_diff_avg_count;
Fabrice Bellard's avatar
Fabrice Bellard committed
    AVStream *audio_st;
    PacketQueue audioq;
    int audio_hw_buf_size;
    /* samples output by the codec. we reserve more space for avsync
       compensation */
    uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2]; 
    unsigned int audio_buf_size; /* in bytes */
Fabrice Bellard's avatar
Fabrice Bellard committed
    int audio_buf_index; /* in bytes */
    AVPacket audio_pkt;
    uint8_t *audio_pkt_data;
    int audio_pkt_size;
    
    int show_audio; /* if true, display audio samples */
    int16_t sample_array[SAMPLE_ARRAY_SIZE];
    int sample_array_index;
    int last_i_start;
    SDL_Thread *subtitle_tid;
    int subtitle_stream;
    int subtitle_stream_changed;
    AVStream *subtitle_st;
    PacketQueue subtitleq;
    SubPicture subpq[SUBPICTURE_QUEUE_SIZE];
    int subpq_size, subpq_rindex, subpq_windex;
    SDL_mutex *subpq_mutex;
    SDL_cond *subpq_cond;
        
    double frame_timer;
    double frame_last_pts;
    double frame_last_delay;
    double video_clock;
Fabrice Bellard's avatar
Fabrice Bellard committed
    int video_stream;
    AVStream *video_st;
    PacketQueue videoq;
    double video_last_P_pts; /* pts of the last P picture (needed if B
                                frames are present) */
    double video_current_pts; /* current displayed pts (different from
                                 video_clock if frame fifos are used) */
    int64_t video_current_pts_time; /* time at which we updated
                                       video_current_pts - used to
                                       have running video pts */
Fabrice Bellard's avatar
Fabrice Bellard committed
    VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
    int pictq_size, pictq_rindex, pictq_windex;
    SDL_mutex *pictq_mutex;
    SDL_cond *pictq_cond;
    
    SDL_mutex *video_decoder_mutex;
    SDL_mutex *audio_decoder_mutex;
Fabrice Bellard's avatar
Fabrice Bellard committed
    //    QETimer *video_timer;
    char filename[1024];
    int width, height, xleft, ytop;
} VideoState;

void show_help(void);
static int audio_write_get_buf_size(VideoState *is);
Fabrice Bellard's avatar
Fabrice Bellard committed

/* options specified by the user */
static AVInputFormat *file_iformat;
Fabrice Bellard's avatar
Fabrice Bellard committed
static const char *input_filename;
static int fs_screen_width;
static int fs_screen_height;
static int screen_width = 640;
static int screen_height = 480;
Loading
Loading full blame...