⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ffplay.c

📁 F:图像处理资料264264书籍ffmpeg-0.4.9-pre1VideoStream.rar 一个视频解压缩源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * 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#if defined(__linux__)#define HAVE_X11#endif#ifdef HAVE_X11#include <X11/Xlib.h>#endif//#define DEBUG_SYNC#define MAX_VIDEOQ_SIZE (5 * 256 * 1024)#define MAX_AUDIOQ_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/* 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 1typedef struct VideoPicture {    double pts; /* presentation time stamp for this picture */    SDL_Overlay *bmp;    int width, height; /* source height & width */    int allocated;} VideoPicture;enum {    AV_SYNC_AUDIO_MASTER, /* default choice */    AV_SYNC_VIDEO_MASTER,    AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */};typedef struct VideoState {    SDL_Thread *parse_tid;    SDL_Thread *video_tid;    AVInputFormat *iformat;    int no_background;    int abort_request;    int paused;    int last_paused;    int seek_req;    int64_t seek_pos;    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;    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];     int audio_buf_size; /* in bytes */    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;        double frame_timer;    double frame_last_pts;    double frame_last_delay;    double video_clock;    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 */    VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];    int pictq_size, pictq_rindex, pictq_windex;    SDL_mutex *pictq_mutex;    SDL_cond *pictq_cond;        //    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);/* options specified by the user */static AVInputFormat *file_iformat;static AVImageFormat *image_format;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;static int audio_disable;static int video_disable;static int display_disable;static int show_status;static int av_sync_type = AV_SYNC_AUDIO_MASTER;static int64_t start_time = AV_NOPTS_VALUE;static int debug = 0;static int debug_mv = 0;static int step = 0;static int thread_count = 1;static int workaround_bugs = 1;/* current context */static int is_full_screen;static VideoState *cur_stream;static int64_t audio_callback_time;#define FF_ALLOC_EVENT   (SDL_USEREVENT)#define FF_REFRESH_EVENT (SDL_USEREVENT + 1)#define FF_QUIT_EVENT    (SDL_USEREVENT + 2)SDL_Surface *screen;/* packet queue handling */static void packet_queue_init(PacketQueue *q){    memset(q, 0, sizeof(PacketQueue));    q->mutex = SDL_CreateMutex();    q->cond = SDL_CreateCond();}static void packet_queue_flush(PacketQueue *q){    AVPacketList *pkt, *pkt1;    for(pkt = q->first_pkt; pkt != NULL; pkt = pkt1) {        pkt1 = pkt->next;        av_free_packet(&pkt->pkt);    }    q->last_pkt = NULL;    q->first_pkt = NULL;    q->nb_packets = 0;    q->size = 0;}static void packet_queue_end(PacketQueue *q){    packet_queue_flush(q);    SDL_DestroyMutex(q->mutex);    SDL_DestroyCond(q->cond);}static int packet_queue_put(PacketQueue *q, AVPacket *pkt){    AVPacketList *pkt1;    /* duplicate the packet */    if (av_dup_packet(pkt) < 0)        return -1;        pkt1 = av_malloc(sizeof(AVPacketList));    if (!pkt1)        return -1;    pkt1->pkt = *pkt;    pkt1->next = NULL;    SDL_LockMutex(q->mutex);    if (!q->last_pkt)        q->first_pkt = pkt1;    else        q->last_pkt->next = pkt1;    q->last_pkt = pkt1;    q->nb_packets++;    q->size += pkt1->pkt.size;    /* XXX: should duplicate packet data in DV case */    SDL_CondSignal(q->cond);    SDL_UnlockMutex(q->mutex);    return 0;}static void packet_queue_abort(PacketQueue *q){    SDL_LockMutex(q->mutex);    q->abort_request = 1;        SDL_CondSignal(q->cond);    SDL_UnlockMutex(q->mutex);}/* return < 0 if aborted, 0 if no packet and > 0 if packet.  */static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block){    AVPacketList *pkt1;    int ret;    SDL_LockMutex(q->mutex);    for(;;) {        if (q->abort_request) {            ret = -1;            break;        }                    pkt1 = q->first_pkt;        if (pkt1) {            q->first_pkt = pkt1->next;            if (!q->first_pkt)                q->last_pkt = NULL;            q->nb_packets--;            q->size -= pkt1->pkt.size;            *pkt = pkt1->pkt;            av_free(pkt1);            ret = 1;            break;        } else if (!block) {            ret = 0;            break;        } else {            SDL_CondWait(q->cond, q->mutex);        }    }    SDL_UnlockMutex(q->mutex);    return ret;}static inline void fill_rectangle(SDL_Surface *screen,                                   int x, int y, int w, int h, int color){    SDL_Rect rect;    rect.x = x;    rect.y = y;    rect.w = w;    rect.h = h;    SDL_FillRect(screen, &rect, color);}#if 0/* draw only the border of a rectangle */void fill_border(VideoState *s, int x, int y, int w, int h, int color){    int w1, w2, h1, h2;    /* fill the background */    w1 = x;    if (w1 < 0)        w1 = 0;    w2 = s->width - (x + w);    if (w2 < 0)        w2 = 0;    h1 = y;    if (h1 < 0)        h1 = 0;    h2 = s->height - (y + h);    if (h2 < 0)        h2 = 0;    fill_rectangle(screen,                    s->xleft, s->ytop,                    w1, s->height,                    color);    fill_rectangle(screen,                    s->xleft + s->width - w2, s->ytop,                    w2, s->height,                    color);    fill_rectangle(screen,                    s->xleft + w1, s->ytop,                    s->width - w1 - w2, h1,                    color);    fill_rectangle(screen,                    s->xleft + w1, s->ytop + s->height - h2,                   s->width - w1 - w2, h2,                   color);}#endifstatic void video_image_display(VideoState *is){    VideoPicture *vp;    float aspect_ratio;    int width, height, x, y;    SDL_Rect rect;    vp = &is->pictq[is->pictq_rindex];    if (vp->bmp) {        /* XXX: use variable in the frame */        if (is->video_st->codec.sample_aspect_ratio.num == 0)             aspect_ratio = 0;        else            aspect_ratio = av_q2d(is->video_st->codec.sample_aspect_ratio)                 * is->video_st->codec.width / is->video_st->codec.height;;        if (aspect_ratio <= 0.0)            aspect_ratio = (float)is->video_st->codec.width /                 (float)is->video_st->codec.height;        /* if an active format is indicated, then it overrides the           mpeg format */#if 0        if (is->video_st->codec.dtg_active_format != is->dtg_active_format) {            is->dtg_active_format = is->video_st->codec.dtg_active_format;            printf("dtg_active_format=%d\n", is->dtg_active_format);        }#endif#if 0        switch(is->video_st->codec.dtg_active_format) {        case FF_DTG_AFD_SAME:        default:            /* nothing to do */            break;        case FF_DTG_AFD_4_3:            aspect_ratio = 4.0 / 3.0;            break;        case FF_DTG_AFD_16_9:            aspect_ratio = 16.0 / 9.0;            break;        case FF_DTG_AFD_14_9:            aspect_ratio = 14.0 / 9.0;            break;        case FF_DTG_AFD_4_3_SP_14_9:            aspect_ratio = 14.0 / 9.0;            break;        case FF_DTG_AFD_16_9_SP_14_9:            aspect_ratio = 14.0 / 9.0;            break;        case FF_DTG_AFD_SP_4_3:            aspect_ratio = 4.0 / 3.0;            break;        }#endif        /* XXX: we suppose the screen has a 1.0 pixel ratio */        height = is->height;        width = ((int)rint(height * aspect_ratio)) & -3;        if (width > is->width) {            width = is->width;            height = ((int)rint(width / aspect_ratio)) & -3;        }        x = (is->width - width) / 2;        y = (is->height - height) / 2;        if (!is->no_background) {            /* fill the background */            //            fill_border(is, x, y, width, height, QERGB(0x00, 0x00, 0x00));        } else {            is->no_background = 0;        }        rect.x = is->xleft + x;        rect.y = is->xleft + y;        rect.w = width;        rect.h = height;        SDL_DisplayYUVOverlay(vp->bmp, &rect);    } else {#if 0        fill_rectangle(screen,                        is->xleft, is->ytop, is->width, is->height,                        QERGB(0x00, 0x00, 0x00));#endif    }}static inline int compute_mod(int a, int b){    a = a % b;    if (a >= 0)         return a;    else        return a + b;}static void video_audio_display(VideoState *s){    int i, i_start, x, y1, y, ys, delay, n, nb_display_channels;    int ch, channels, h, h2, bgcolor, fgcolor;    int16_t time_diff;        /* compute display index : center on currently output samples */    channels = s->audio_st->codec.channels;    nb_display_channels = channels;    if (!s->paused) {        n = 2 * channels;        delay = audio_write_get_buf_size(s);        delay /= n;                /* to be more precise, we take into account the time spent since           the last buffer computation */        if (audio_callback_time) {            time_diff = av_gettime() - audio_callback_time;            delay += (time_diff * s->audio_st->codec.sample_rate) / 1000000;        }                delay -= s->width / 2;        if (delay < s->width)            delay = s->width;        i_start = compute_mod(s->sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE);        s->last_i_start = i_start;    } else {        i_start = s->last_i_start;    }    bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);    fill_rectangle(screen,                    s->xleft, s->ytop, s->width, s->height,                    bgcolor);    fgcolor = SDL_MapRGB(screen->format, 0xff, 0xff, 0xff);    /* total height for one channel */    h = s->height / nb_display_channels;    /* graph height / 2 */    h2 = (h * 9) / 20;    for(ch = 0;ch < nb_display_channels; ch++) {        i = i_start + ch;        y1 = s->ytop + ch * h + (h / 2); /* position of center line */        for(x = 0; x < s->width; x++) {            y = (s->sample_array[i] * h2) >> 15;            if (y < 0) {                y = -y;                ys = y1 - y;            } else {                ys = y1;            }            fill_rectangle(screen, 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -