Statistics
| Branch: | Revision:

ffmpeg / ffplay.c @ 7d9beec7

History | View | Annotate | Download (79 KB)

1 01310af2 Fabrice Bellard
/*
2
 * FFplay : Simple Media Player based on the ffmpeg libraries
3
 * Copyright (c) 2003 Fabrice Bellard
4
 *
5 b78e7197 Diego Biurrun
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8 01310af2 Fabrice Bellard
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10 b78e7197 Diego Biurrun
 * version 2.1 of the License, or (at your option) any later version.
11 01310af2 Fabrice Bellard
 *
12 b78e7197 Diego Biurrun
 * FFmpeg is distributed in the hope that it will be useful,
13 01310af2 Fabrice Bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18 b78e7197 Diego Biurrun
 * License along with FFmpeg; if not, write to the Free Software
19 5509bffa Diego Biurrun
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 01310af2 Fabrice Bellard
 */
21 364a9607 Diego Biurrun
22 0f4e8165 Ronald S. Bultje
#include <math.h>
23
#include <limits.h>
24 245976da Diego Biurrun
#include "libavutil/avstring.h"
25
#include "libavformat/avformat.h"
26
#include "libavformat/rtsp.h"
27
#include "libavdevice/avdevice.h"
28
#include "libswscale/swscale.h"
29 5a4476e2 Peter Ross
#include "libavcodec/audioconvert.h"
30 a7e6312b Stefano Sabatini
#include "libavcodec/colorspace.h"
31 e43d7a18 Michael Niedermayer
#include "libavcodec/opt.h"
32 01310af2 Fabrice Bellard
33
#include "cmdutils.h"
34
35
#include <SDL.h>
36
#include <SDL_thread.h>
37
38 2f30a81d Diego Biurrun
#ifdef __MINGW32__
39 31319a8c Fabrice Bellard
#undef main /* We don't want SDL to override our main() */
40
#endif
41
42 c367d067 Michael Niedermayer
#undef exit
43
44 64555bd9 Michael Niedermayer
const char program_name[] = "FFplay";
45 ea9c581f Stefano Sabatini
const int program_birth_year = 2003;
46 4cfac5bc Stefano Sabatini
47 638c9d91 Fabrice Bellard
//#define DEBUG_SYNC
48
49 01310af2 Fabrice Bellard
#define MAX_VIDEOQ_SIZE (5 * 256 * 1024)
50
#define MAX_AUDIOQ_SIZE (5 * 16 * 1024)
51 72ce053b Ian Caulfield
#define MAX_SUBTITLEQ_SIZE (5 * 16 * 1024)
52 01310af2 Fabrice Bellard
53 638c9d91 Fabrice Bellard
/* SDL audio buffer size, in samples. Should be small to have precise
54
   A/V sync as SDL does not have hardware buffer fullness info. */
55
#define SDL_AUDIO_BUFFER_SIZE 1024
56
57
/* no AV sync correction is done if below the AV sync threshold */
58 7e0140cb Michael Niedermayer
#define AV_SYNC_THRESHOLD 0.01
59 638c9d91 Fabrice Bellard
/* no AV correction is done if too big error */
60
#define AV_NOSYNC_THRESHOLD 10.0
61
62
/* maximum audio speed change to get correct sync */
63
#define SAMPLE_CORRECTION_PERCENT_MAX 10
64
65
/* we use about AUDIO_DIFF_AVG_NB A-V differences to make the average */
66
#define AUDIO_DIFF_AVG_NB   20
67
68 01310af2 Fabrice Bellard
/* NOTE: the size must be big enough to compensate the hardware audio buffersize size */
69
#define SAMPLE_ARRAY_SIZE (2*65536)
70
71 03ae87a3 Luca Abeni
static int sws_flags = SWS_BICUBIC;
72
73 01310af2 Fabrice Bellard
typedef struct PacketQueue {
74
    AVPacketList *first_pkt, *last_pkt;
75
    int nb_packets;
76
    int size;
77
    int abort_request;
78
    SDL_mutex *mutex;
79
    SDL_cond *cond;
80
} PacketQueue;
81
82
#define VIDEO_PICTURE_QUEUE_SIZE 1
83 72ce053b Ian Caulfield
#define SUBPICTURE_QUEUE_SIZE 4
84 01310af2 Fabrice Bellard
85
typedef struct VideoPicture {
86 267e9dfa Michael Niedermayer
    double pts;                                  ///<presentation time stamp for this picture
87 01310af2 Fabrice Bellard
    SDL_Overlay *bmp;
88
    int width, height; /* source height & width */
89
    int allocated;
90
} VideoPicture;
91
92 72ce053b Ian Caulfield
typedef struct SubPicture {
93
    double pts; /* presentation time stamp for this picture */
94
    AVSubtitle sub;
95
} SubPicture;
96
97 01310af2 Fabrice Bellard
enum {
98
    AV_SYNC_AUDIO_MASTER, /* default choice */
99
    AV_SYNC_VIDEO_MASTER,
100 638c9d91 Fabrice Bellard
    AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */
101 01310af2 Fabrice Bellard
};
102
103
typedef struct VideoState {
104
    SDL_Thread *parse_tid;
105
    SDL_Thread *video_tid;
106 638c9d91 Fabrice Bellard
    AVInputFormat *iformat;
107 01310af2 Fabrice Bellard
    int no_background;
108
    int abort_request;
109
    int paused;
110 416e3508 Fabrice Bellard
    int last_paused;
111 72ea344b Fabrice Bellard
    int seek_req;
112 3ba1438d Michael Niedermayer
    int seek_flags;
113 72ea344b Fabrice Bellard
    int64_t seek_pos;
114 4ed29207 Michael Niedermayer
    int64_t seek_rel;
115 01310af2 Fabrice Bellard
    AVFormatContext *ic;
116
    int dtg_active_format;
117
118
    int audio_stream;
119 115329f1 Diego Biurrun
120 01310af2 Fabrice Bellard
    int av_sync_type;
121 638c9d91 Fabrice Bellard
    double external_clock; /* external clock base */
122
    int64_t external_clock_time;
123 115329f1 Diego Biurrun
124 638c9d91 Fabrice Bellard
    double audio_clock;
125
    double audio_diff_cum; /* used for AV difference average computation */
126
    double audio_diff_avg_coef;
127
    double audio_diff_threshold;
128
    int audio_diff_avg_count;
129 01310af2 Fabrice Bellard
    AVStream *audio_st;
130
    PacketQueue audioq;
131
    int audio_hw_buf_size;
132
    /* samples output by the codec. we reserve more space for avsync
133
       compensation */
134 5a4476e2 Peter Ross
    DECLARE_ALIGNED(16,uint8_t,audio_buf1[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2]);
135
    DECLARE_ALIGNED(16,uint8_t,audio_buf2[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2]);
136
    uint8_t *audio_buf;
137 7fea94ce Zdenek Kabelac
    unsigned int audio_buf_size; /* in bytes */
138 01310af2 Fabrice Bellard
    int audio_buf_index; /* in bytes */
139 bea18375 Thilo Borgmann
    AVPacket audio_pkt_temp;
140 01310af2 Fabrice Bellard
    AVPacket audio_pkt;
141 5a4476e2 Peter Ross
    enum SampleFormat audio_src_fmt;
142
    AVAudioConvert *reformat_ctx;
143 115329f1 Diego Biurrun
144 01310af2 Fabrice Bellard
    int show_audio; /* if true, display audio samples */
145
    int16_t sample_array[SAMPLE_ARRAY_SIZE];
146
    int sample_array_index;
147 5e0257e3 Fabrice Bellard
    int last_i_start;
148 115329f1 Diego Biurrun
149 72ce053b Ian Caulfield
    SDL_Thread *subtitle_tid;
150
    int subtitle_stream;
151
    int subtitle_stream_changed;
152
    AVStream *subtitle_st;
153
    PacketQueue subtitleq;
154
    SubPicture subpq[SUBPICTURE_QUEUE_SIZE];
155
    int subpq_size, subpq_rindex, subpq_windex;
156
    SDL_mutex *subpq_mutex;
157
    SDL_cond *subpq_cond;
158 115329f1 Diego Biurrun
159 638c9d91 Fabrice Bellard
    double frame_timer;
160
    double frame_last_pts;
161
    double frame_last_delay;
162 115329f1 Diego Biurrun
    double video_clock;                          ///<pts of last decoded frame / predicted pts of next decoded frame
163 01310af2 Fabrice Bellard
    int video_stream;
164
    AVStream *video_st;
165
    PacketQueue videoq;
166 267e9dfa Michael Niedermayer
    double video_current_pts;                    ///<current displayed pts (different from video_clock if frame fifos are used)
167
    int64_t video_current_pts_time;              ///<time (av_gettime) at which we updated video_current_pts - used to have running video pts
168 01310af2 Fabrice Bellard
    VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
169
    int pictq_size, pictq_rindex, pictq_windex;
170
    SDL_mutex *pictq_mutex;
171
    SDL_cond *pictq_cond;
172 3ac56e28 Martin Storsjö
    struct SwsContext *img_convert_ctx;
173 115329f1 Diego Biurrun
174 01310af2 Fabrice Bellard
    //    QETimer *video_timer;
175
    char filename[1024];
176
    int width, height, xleft, ytop;
177
} VideoState;
178
179 358061f6 Diego Pettenò
static void show_help(void);
180 638c9d91 Fabrice Bellard
static int audio_write_get_buf_size(VideoState *is);
181 01310af2 Fabrice Bellard
182
/* options specified by the user */
183
static AVInputFormat *file_iformat;
184
static const char *input_filename;
185
static int fs_screen_width;
186
static int fs_screen_height;
187 fccb19e3 Michael Niedermayer
static int screen_width = 0;
188
static int screen_height = 0;
189 e4b89522 Limin Wang
static int frame_width = 0;
190
static int frame_height = 0;
191
static enum PixelFormat frame_pix_fmt = PIX_FMT_NONE;
192 01310af2 Fabrice Bellard
static int audio_disable;
193
static int video_disable;
194 a8062103 Michael Niedermayer
static int wanted_audio_stream= 0;
195 4d8243d3 Michael Niedermayer
static int wanted_video_stream= 0;
196 16a59a7b Björn Axelsson
static int wanted_subtitle_stream= -1;
197 94b594c6 Steve L'Homme
static int seek_by_bytes;
198 01310af2 Fabrice Bellard
static int display_disable;
199
static int show_status;
200 638c9d91 Fabrice Bellard
static int av_sync_type = AV_SYNC_AUDIO_MASTER;
201 72ea344b Fabrice Bellard
static int64_t start_time = AV_NOPTS_VALUE;
202 e26a8335 Wolfgang Hesseler
static int debug = 0;
203 0c9bbaec Wolfgang Hesseler
static int debug_mv = 0;
204 bba04f1e Wolfgang Hesseler
static int step = 0;
205 c62c07d3 Michael Niedermayer
static int thread_count = 1;
206 6387c3e6 Michael Niedermayer
static int workaround_bugs = 1;
207 6fc5b059 Michael Niedermayer
static int fast = 0;
208 30bc6613 Michael Niedermayer
static int genpts = 0;
209 178fcca8 Michael Niedermayer
static int lowres = 0;
210
static int idct = FF_IDCT_AUTO;
211 8c3eba7c Michael Niedermayer
static enum AVDiscard skip_frame= AVDISCARD_DEFAULT;
212
static enum AVDiscard skip_idct= AVDISCARD_DEFAULT;
213
static enum AVDiscard skip_loop_filter= AVDISCARD_DEFAULT;
214 047599a4 Michael Niedermayer
static int error_recognition = FF_ER_CAREFUL;
215 1b51e051 Michael Niedermayer
static int error_concealment = 3;
216 5039185a Michael Niedermayer
static int decoder_reorder_pts= 0;
217 01310af2 Fabrice Bellard
218
/* current context */
219
static int is_full_screen;
220
static VideoState *cur_stream;
221 5e0257e3 Fabrice Bellard
static int64_t audio_callback_time;
222 01310af2 Fabrice Bellard
223 2c676c33 Diego Pettenò
static AVPacket flush_pkt;
224 39c6a118 Michael Niedermayer
225 01310af2 Fabrice Bellard
#define FF_ALLOC_EVENT   (SDL_USEREVENT)
226
#define FF_REFRESH_EVENT (SDL_USEREVENT + 1)
227 638c9d91 Fabrice Bellard
#define FF_QUIT_EVENT    (SDL_USEREVENT + 2)
228 01310af2 Fabrice Bellard
229 2c676c33 Diego Pettenò
static SDL_Surface *screen;
230 01310af2 Fabrice Bellard
231
/* packet queue handling */
232
static void packet_queue_init(PacketQueue *q)
233
{
234
    memset(q, 0, sizeof(PacketQueue));
235
    q->mutex = SDL_CreateMutex();
236
    q->cond = SDL_CreateCond();
237
}
238
239 72ea344b Fabrice Bellard
static void packet_queue_flush(PacketQueue *q)
240 01310af2 Fabrice Bellard
{
241
    AVPacketList *pkt, *pkt1;
242
243 687fae2b Ivan Wong
    SDL_LockMutex(q->mutex);
244 01310af2 Fabrice Bellard
    for(pkt = q->first_pkt; pkt != NULL; pkt = pkt1) {
245
        pkt1 = pkt->next;
246
        av_free_packet(&pkt->pkt);
247 da6c4573 Michael Niedermayer
        av_freep(&pkt);
248 01310af2 Fabrice Bellard
    }
249 72ea344b Fabrice Bellard
    q->last_pkt = NULL;
250
    q->first_pkt = NULL;
251
    q->nb_packets = 0;
252
    q->size = 0;
253 687fae2b Ivan Wong
    SDL_UnlockMutex(q->mutex);
254 72ea344b Fabrice Bellard
}
255
256
static void packet_queue_end(PacketQueue *q)
257
{
258
    packet_queue_flush(q);
259 01310af2 Fabrice Bellard
    SDL_DestroyMutex(q->mutex);
260
    SDL_DestroyCond(q->cond);
261
}
262
263
static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
264
{
265
    AVPacketList *pkt1;
266
267 72ea344b Fabrice Bellard
    /* duplicate the packet */
268 39c6a118 Michael Niedermayer
    if (pkt!=&flush_pkt && av_dup_packet(pkt) < 0)
269 72ea344b Fabrice Bellard
        return -1;
270 115329f1 Diego Biurrun
271 01310af2 Fabrice Bellard
    pkt1 = av_malloc(sizeof(AVPacketList));
272
    if (!pkt1)
273
        return -1;
274
    pkt1->pkt = *pkt;
275
    pkt1->next = NULL;
276
277 72ea344b Fabrice Bellard
278 01310af2 Fabrice Bellard
    SDL_LockMutex(q->mutex);
279
280
    if (!q->last_pkt)
281
282
        q->first_pkt = pkt1;
283
    else
284
        q->last_pkt->next = pkt1;
285
    q->last_pkt = pkt1;
286
    q->nb_packets++;
287 7b776589 Aurelien Jacobs
    q->size += pkt1->pkt.size + sizeof(*pkt1);
288 01310af2 Fabrice Bellard
    /* XXX: should duplicate packet data in DV case */
289
    SDL_CondSignal(q->cond);
290
291
    SDL_UnlockMutex(q->mutex);
292
    return 0;
293
}
294
295
static void packet_queue_abort(PacketQueue *q)
296
{
297
    SDL_LockMutex(q->mutex);
298
299
    q->abort_request = 1;
300 115329f1 Diego Biurrun
301 01310af2 Fabrice Bellard
    SDL_CondSignal(q->cond);
302
303
    SDL_UnlockMutex(q->mutex);
304
}
305
306
/* return < 0 if aborted, 0 if no packet and > 0 if packet.  */
307
static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
308
{
309
    AVPacketList *pkt1;
310
    int ret;
311
312
    SDL_LockMutex(q->mutex);
313
314
    for(;;) {
315
        if (q->abort_request) {
316
            ret = -1;
317
            break;
318
        }
319 115329f1 Diego Biurrun
320 01310af2 Fabrice Bellard
        pkt1 = q->first_pkt;
321
        if (pkt1) {
322
            q->first_pkt = pkt1->next;
323
            if (!q->first_pkt)
324
                q->last_pkt = NULL;
325
            q->nb_packets--;
326 7b776589 Aurelien Jacobs
            q->size -= pkt1->pkt.size + sizeof(*pkt1);
327 01310af2 Fabrice Bellard
            *pkt = pkt1->pkt;
328
            av_free(pkt1);
329
            ret = 1;
330
            break;
331
        } else if (!block) {
332
            ret = 0;
333
            break;
334
        } else {
335
            SDL_CondWait(q->cond, q->mutex);
336
        }
337
    }
338
    SDL_UnlockMutex(q->mutex);
339
    return ret;
340
}
341
342 115329f1 Diego Biurrun
static inline void fill_rectangle(SDL_Surface *screen,
343 01310af2 Fabrice Bellard
                                  int x, int y, int w, int h, int color)
344
{
345
    SDL_Rect rect;
346
    rect.x = x;
347
    rect.y = y;
348
    rect.w = w;
349
    rect.h = h;
350
    SDL_FillRect(screen, &rect, color);
351
}
352
353
#if 0
354
/* draw only the border of a rectangle */
355
void fill_border(VideoState *s, int x, int y, int w, int h, int color)
356
{
357
    int w1, w2, h1, h2;
358

359
    /* fill the background */
360
    w1 = x;
361
    if (w1 < 0)
362
        w1 = 0;
363
    w2 = s->width - (x + w);
364
    if (w2 < 0)
365
        w2 = 0;
366
    h1 = y;
367
    if (h1 < 0)
368
        h1 = 0;
369
    h2 = s->height - (y + h);
370
    if (h2 < 0)
371
        h2 = 0;
372 115329f1 Diego Biurrun
    fill_rectangle(screen,
373
                   s->xleft, s->ytop,
374
                   w1, s->height,
375 01310af2 Fabrice Bellard
                   color);
376 115329f1 Diego Biurrun
    fill_rectangle(screen,
377
                   s->xleft + s->width - w2, s->ytop,
378
                   w2, s->height,
379 01310af2 Fabrice Bellard
                   color);
380 115329f1 Diego Biurrun
    fill_rectangle(screen,
381
                   s->xleft + w1, s->ytop,
382
                   s->width - w1 - w2, h1,
383 01310af2 Fabrice Bellard
                   color);
384 115329f1 Diego Biurrun
    fill_rectangle(screen,
385 01310af2 Fabrice Bellard
                   s->xleft + w1, s->ytop + s->height - h2,
386
                   s->width - w1 - w2, h2,
387
                   color);
388
}
389
#endif
390
391 72ce053b Ian Caulfield
#define ALPHA_BLEND(a, oldp, newp, s)\
392
((((oldp << s) * (255 - (a))) + (newp * (a))) / (255 << s))
393
394
#define RGBA_IN(r, g, b, a, s)\
395
{\
396
    unsigned int v = ((const uint32_t *)(s))[0];\
397
    a = (v >> 24) & 0xff;\
398
    r = (v >> 16) & 0xff;\
399
    g = (v >> 8) & 0xff;\
400
    b = v & 0xff;\
401
}
402
403
#define YUVA_IN(y, u, v, a, s, pal)\
404
{\
405 57cf99f2 Reimar Döffinger
    unsigned int val = ((const uint32_t *)(pal))[*(const uint8_t*)(s)];\
406 72ce053b Ian Caulfield
    a = (val >> 24) & 0xff;\
407
    y = (val >> 16) & 0xff;\
408
    u = (val >> 8) & 0xff;\
409
    v = val & 0xff;\
410
}
411
412
#define YUVA_OUT(d, y, u, v, a)\
413
{\
414
    ((uint32_t *)(d))[0] = (a << 24) | (y << 16) | (u << 8) | v;\
415
}
416
417
418
#define BPP 1
419
420 0a8cd696 Reimar Döffinger
static void blend_subrect(AVPicture *dst, const AVSubtitleRect *rect, int imgw, int imgh)
421 72ce053b Ian Caulfield
{
422
    int wrap, wrap3, width2, skip2;
423
    int y, u, v, a, u1, v1, a1, w, h;
424
    uint8_t *lum, *cb, *cr;
425
    const uint8_t *p;
426
    const uint32_t *pal;
427 9cb5a11e Reimar Döffinger
    int dstx, dsty, dstw, dsth;
428
429 7cf9c6ae Michael Niedermayer
    dstw = av_clip(rect->w, 0, imgw);
430
    dsth = av_clip(rect->h, 0, imgh);
431
    dstx = av_clip(rect->x, 0, imgw - dstw);
432
    dsty = av_clip(rect->y, 0, imgh - dsth);
433 9cb5a11e Reimar Döffinger
    lum = dst->data[0] + dsty * dst->linesize[0];
434
    cb = dst->data[1] + (dsty >> 1) * dst->linesize[1];
435
    cr = dst->data[2] + (dsty >> 1) * dst->linesize[2];
436
437 f54b31b9 Björn Axelsson
    width2 = ((dstw + 1) >> 1) + (dstx & ~dstw & 1);
438 9cb5a11e Reimar Döffinger
    skip2 = dstx >> 1;
439 72ce053b Ian Caulfield
    wrap = dst->linesize[0];
440 25b4c651 Michael Niedermayer
    wrap3 = rect->pict.linesize[0];
441
    p = rect->pict.data[0];
442
    pal = (const uint32_t *)rect->pict.data[1];  /* Now in YCrCb! */
443 115329f1 Diego Biurrun
444 9cb5a11e Reimar Döffinger
    if (dsty & 1) {
445
        lum += dstx;
446 72ce053b Ian Caulfield
        cb += skip2;
447
        cr += skip2;
448 115329f1 Diego Biurrun
449 9cb5a11e Reimar Döffinger
        if (dstx & 1) {
450 72ce053b Ian Caulfield
            YUVA_IN(y, u, v, a, p, pal);
451
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
452
            cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
453
            cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
454
            cb++;
455
            cr++;
456
            lum++;
457
            p += BPP;
458
        }
459 9cb5a11e Reimar Döffinger
        for(w = dstw - (dstx & 1); w >= 2; w -= 2) {
460 72ce053b Ian Caulfield
            YUVA_IN(y, u, v, a, p, pal);
461
            u1 = u;
462
            v1 = v;
463
            a1 = a;
464
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
465
466
            YUVA_IN(y, u, v, a, p + BPP, pal);
467
            u1 += u;
468
            v1 += v;
469
            a1 += a;
470
            lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
471
            cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
472
            cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
473
            cb++;
474
            cr++;
475
            p += 2 * BPP;
476
            lum += 2;
477
        }
478
        if (w) {
479
            YUVA_IN(y, u, v, a, p, pal);
480
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
481
            cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
482
            cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
483 676ef505 Björn Axelsson
            p++;
484
            lum++;
485 72ce053b Ian Caulfield
        }
486 4606a059 Björn Axelsson
        p += wrap3 - dstw * BPP;
487
        lum += wrap - dstw - dstx;
488 72ce053b Ian Caulfield
        cb += dst->linesize[1] - width2 - skip2;
489
        cr += dst->linesize[2] - width2 - skip2;
490
    }
491 9cb5a11e Reimar Döffinger
    for(h = dsth - (dsty & 1); h >= 2; h -= 2) {
492
        lum += dstx;
493 72ce053b Ian Caulfield
        cb += skip2;
494
        cr += skip2;
495 115329f1 Diego Biurrun
496 9cb5a11e Reimar Döffinger
        if (dstx & 1) {
497 72ce053b Ian Caulfield
            YUVA_IN(y, u, v, a, p, pal);
498
            u1 = u;
499
            v1 = v;
500
            a1 = a;
501
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
502
            p += wrap3;
503
            lum += wrap;
504
            YUVA_IN(y, u, v, a, p, pal);
505
            u1 += u;
506
            v1 += v;
507
            a1 += a;
508
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
509
            cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
510
            cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
511
            cb++;
512
            cr++;
513
            p += -wrap3 + BPP;
514
            lum += -wrap + 1;
515
        }
516 9cb5a11e Reimar Döffinger
        for(w = dstw - (dstx & 1); w >= 2; w -= 2) {
517 72ce053b Ian Caulfield
            YUVA_IN(y, u, v, a, p, pal);
518
            u1 = u;
519
            v1 = v;
520
            a1 = a;
521
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
522
523 f8ca63e8 Björn Axelsson
            YUVA_IN(y, u, v, a, p + BPP, pal);
524 72ce053b Ian Caulfield
            u1 += u;
525
            v1 += v;
526
            a1 += a;
527
            lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
528
            p += wrap3;
529
            lum += wrap;
530
531
            YUVA_IN(y, u, v, a, p, pal);
532
            u1 += u;
533
            v1 += v;
534
            a1 += a;
535
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
536
537 f8ca63e8 Björn Axelsson
            YUVA_IN(y, u, v, a, p + BPP, pal);
538 72ce053b Ian Caulfield
            u1 += u;
539
            v1 += v;
540
            a1 += a;
541
            lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
542
543
            cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 2);
544
            cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 2);
545
546
            cb++;
547
            cr++;
548
            p += -wrap3 + 2 * BPP;
549
            lum += -wrap + 2;
550
        }
551
        if (w) {
552
            YUVA_IN(y, u, v, a, p, pal);
553
            u1 = u;
554
            v1 = v;
555
            a1 = a;
556
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
557
            p += wrap3;
558
            lum += wrap;
559
            YUVA_IN(y, u, v, a, p, pal);
560
            u1 += u;
561
            v1 += v;
562
            a1 += a;
563
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
564
            cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
565
            cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
566
            cb++;
567
            cr++;
568
            p += -wrap3 + BPP;
569
            lum += -wrap + 1;
570
        }
571 9cb5a11e Reimar Döffinger
        p += wrap3 + (wrap3 - dstw * BPP);
572
        lum += wrap + (wrap - dstw - dstx);
573 72ce053b Ian Caulfield
        cb += dst->linesize[1] - width2 - skip2;
574
        cr += dst->linesize[2] - width2 - skip2;
575
    }
576
    /* handle odd height */
577
    if (h) {
578 9cb5a11e Reimar Döffinger
        lum += dstx;
579 72ce053b Ian Caulfield
        cb += skip2;
580
        cr += skip2;
581 115329f1 Diego Biurrun
582 9cb5a11e Reimar Döffinger
        if (dstx & 1) {
583 72ce053b Ian Caulfield
            YUVA_IN(y, u, v, a, p, pal);
584
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
585
            cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
586
            cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
587
            cb++;
588
            cr++;
589
            lum++;
590
            p += BPP;
591
        }
592 9cb5a11e Reimar Döffinger
        for(w = dstw - (dstx & 1); w >= 2; w -= 2) {
593 72ce053b Ian Caulfield
            YUVA_IN(y, u, v, a, p, pal);
594
            u1 = u;
595
            v1 = v;
596
            a1 = a;
597
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
598
599
            YUVA_IN(y, u, v, a, p + BPP, pal);
600
            u1 += u;
601
            v1 += v;
602
            a1 += a;
603
            lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
604
            cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u, 1);
605
            cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v, 1);
606
            cb++;
607
            cr++;
608
            p += 2 * BPP;
609
            lum += 2;
610
        }
611
        if (w) {
612
            YUVA_IN(y, u, v, a, p, pal);
613
            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
614
            cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
615
            cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
616
        }
617
    }
618
}
619
620
static void free_subpicture(SubPicture *sp)
621
{
622
    int i;
623 115329f1 Diego Biurrun
624 72ce053b Ian Caulfield
    for (i = 0; i < sp->sub.num_rects; i++)
625
    {
626 25b4c651 Michael Niedermayer
        av_freep(&sp->sub.rects[i]->pict.data[0]);
627
        av_freep(&sp->sub.rects[i]->pict.data[1]);
628 db4fac64 Michael Niedermayer
        av_freep(&sp->sub.rects[i]);
629 72ce053b Ian Caulfield
    }
630 115329f1 Diego Biurrun
631 72ce053b Ian Caulfield
    av_free(sp->sub.rects);
632 115329f1 Diego Biurrun
633 72ce053b Ian Caulfield
    memset(&sp->sub, 0, sizeof(AVSubtitle));
634
}
635
636 01310af2 Fabrice Bellard
static void video_image_display(VideoState *is)
637
{
638
    VideoPicture *vp;
639 72ce053b Ian Caulfield
    SubPicture *sp;
640
    AVPicture pict;
641 01310af2 Fabrice Bellard
    float aspect_ratio;
642
    int width, height, x, y;
643
    SDL_Rect rect;
644 72ce053b Ian Caulfield
    int i;
645 01310af2 Fabrice Bellard
646
    vp = &is->pictq[is->pictq_rindex];
647
    if (vp->bmp) {
648
        /* XXX: use variable in the frame */
649 c30a4489 Aurelien Jacobs
        if (is->video_st->sample_aspect_ratio.num)
650
            aspect_ratio = av_q2d(is->video_st->sample_aspect_ratio);
651
        else if (is->video_st->codec->sample_aspect_ratio.num)
652
            aspect_ratio = av_q2d(is->video_st->codec->sample_aspect_ratio);
653 72ea344b Fabrice Bellard
        else
654 c30a4489 Aurelien Jacobs
            aspect_ratio = 0;
655 01310af2 Fabrice Bellard
        if (aspect_ratio <= 0.0)
656 c30a4489 Aurelien Jacobs
            aspect_ratio = 1.0;
657
        aspect_ratio *= (float)is->video_st->codec->width / is->video_st->codec->height;
658 01310af2 Fabrice Bellard
        /* if an active format is indicated, then it overrides the
659
           mpeg format */
660
#if 0
661 01f4895c Michael Niedermayer
        if (is->video_st->codec->dtg_active_format != is->dtg_active_format) {
662
            is->dtg_active_format = is->video_st->codec->dtg_active_format;
663 01310af2 Fabrice Bellard
            printf("dtg_active_format=%d\n", is->dtg_active_format);
664
        }
665
#endif
666
#if 0
667 01f4895c Michael Niedermayer
        switch(is->video_st->codec->dtg_active_format) {
668 01310af2 Fabrice Bellard
        case FF_DTG_AFD_SAME:
669
        default:
670
            /* nothing to do */
671
            break;
672
        case FF_DTG_AFD_4_3:
673
            aspect_ratio = 4.0 / 3.0;
674
            break;
675
        case FF_DTG_AFD_16_9:
676
            aspect_ratio = 16.0 / 9.0;
677
            break;
678
        case FF_DTG_AFD_14_9:
679
            aspect_ratio = 14.0 / 9.0;
680
            break;
681
        case FF_DTG_AFD_4_3_SP_14_9:
682
            aspect_ratio = 14.0 / 9.0;
683
            break;
684
        case FF_DTG_AFD_16_9_SP_14_9:
685
            aspect_ratio = 14.0 / 9.0;
686
            break;
687
        case FF_DTG_AFD_SP_4_3:
688
            aspect_ratio = 4.0 / 3.0;
689
            break;
690
        }
691
#endif
692
693 72ce053b Ian Caulfield
        if (is->subtitle_st)
694
        {
695
            if (is->subpq_size > 0)
696
            {
697
                sp = &is->subpq[is->subpq_rindex];
698
699
                if (vp->pts >= sp->pts + ((float) sp->sub.start_display_time / 1000))
700
                {
701
                    SDL_LockYUVOverlay (vp->bmp);
702
703
                    pict.data[0] = vp->bmp->pixels[0];
704
                    pict.data[1] = vp->bmp->pixels[2];
705
                    pict.data[2] = vp->bmp->pixels[1];
706
707
                    pict.linesize[0] = vp->bmp->pitches[0];
708
                    pict.linesize[1] = vp->bmp->pitches[2];
709
                    pict.linesize[2] = vp->bmp->pitches[1];
710
711
                    for (i = 0; i < sp->sub.num_rects; i++)
712 db4fac64 Michael Niedermayer
                        blend_subrect(&pict, sp->sub.rects[i],
713 0a8cd696 Reimar Döffinger
                                      vp->bmp->w, vp->bmp->h);
714 72ce053b Ian Caulfield
715
                    SDL_UnlockYUVOverlay (vp->bmp);
716
                }
717
            }
718
        }
719
720
721 01310af2 Fabrice Bellard
        /* XXX: we suppose the screen has a 1.0 pixel ratio */
722
        height = is->height;
723 bb6c34e5 Michael Niedermayer
        width = ((int)rint(height * aspect_ratio)) & ~1;
724 01310af2 Fabrice Bellard
        if (width > is->width) {
725
            width = is->width;
726 bb6c34e5 Michael Niedermayer
            height = ((int)rint(width / aspect_ratio)) & ~1;
727 01310af2 Fabrice Bellard
        }
728
        x = (is->width - width) / 2;
729
        y = (is->height - height) / 2;
730
        if (!is->no_background) {
731
            /* fill the background */
732
            //            fill_border(is, x, y, width, height, QERGB(0x00, 0x00, 0x00));
733
        } else {
734
            is->no_background = 0;
735
        }
736
        rect.x = is->xleft + x;
737 2f6547fb Baptiste Coudurier
        rect.y = is->ytop  + y;
738 01310af2 Fabrice Bellard
        rect.w = width;
739
        rect.h = height;
740
        SDL_DisplayYUVOverlay(vp->bmp, &rect);
741
    } else {
742
#if 0
743 115329f1 Diego Biurrun
        fill_rectangle(screen,
744
                       is->xleft, is->ytop, is->width, is->height,
745 01310af2 Fabrice Bellard
                       QERGB(0x00, 0x00, 0x00));
746
#endif
747
    }
748
}
749
750
static inline int compute_mod(int a, int b)
751
{
752
    a = a % b;
753 115329f1 Diego Biurrun
    if (a >= 0)
754 01310af2 Fabrice Bellard
        return a;
755
    else
756
        return a + b;
757
}
758
759
static void video_audio_display(VideoState *s)
760
{
761
    int i, i_start, x, y1, y, ys, delay, n, nb_display_channels;
762
    int ch, channels, h, h2, bgcolor, fgcolor;
763
    int16_t time_diff;
764 115329f1 Diego Biurrun
765 01310af2 Fabrice Bellard
    /* compute display index : center on currently output samples */
766 01f4895c Michael Niedermayer
    channels = s->audio_st->codec->channels;
767 01310af2 Fabrice Bellard
    nb_display_channels = channels;
768 5e0257e3 Fabrice Bellard
    if (!s->paused) {
769
        n = 2 * channels;
770
        delay = audio_write_get_buf_size(s);
771
        delay /= n;
772 115329f1 Diego Biurrun
773 5e0257e3 Fabrice Bellard
        /* to be more precise, we take into account the time spent since
774
           the last buffer computation */
775
        if (audio_callback_time) {
776
            time_diff = av_gettime() - audio_callback_time;
777 01f4895c Michael Niedermayer
            delay += (time_diff * s->audio_st->codec->sample_rate) / 1000000;
778 5e0257e3 Fabrice Bellard
        }
779 115329f1 Diego Biurrun
780 5e0257e3 Fabrice Bellard
        delay -= s->width / 2;
781
        if (delay < s->width)
782
            delay = s->width;
783 ac50bcc8 Michael Niedermayer
784
        i_start= x = compute_mod(s->sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE);
785
786
        h= INT_MIN;
787
        for(i=0; i<1000; i+=channels){
788
            int idx= (SAMPLE_ARRAY_SIZE + x - i) % SAMPLE_ARRAY_SIZE;
789
            int a= s->sample_array[idx];
790
            int b= s->sample_array[(idx + 4*channels)%SAMPLE_ARRAY_SIZE];
791
            int c= s->sample_array[(idx + 5*channels)%SAMPLE_ARRAY_SIZE];
792
            int d= s->sample_array[(idx + 9*channels)%SAMPLE_ARRAY_SIZE];
793
            int score= a-d;
794
            if(h<score && (b^c)<0){
795
                h= score;
796
                i_start= idx;
797
            }
798
        }
799
800 5e0257e3 Fabrice Bellard
        s->last_i_start = i_start;
801
    } else {
802
        i_start = s->last_i_start;
803 01310af2 Fabrice Bellard
    }
804
805
    bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
806 115329f1 Diego Biurrun
    fill_rectangle(screen,
807
                   s->xleft, s->ytop, s->width, s->height,
808 01310af2 Fabrice Bellard
                   bgcolor);
809
810
    fgcolor = SDL_MapRGB(screen->format, 0xff, 0xff, 0xff);
811
812
    /* total height for one channel */
813
    h = s->height / nb_display_channels;
814
    /* graph height / 2 */
815
    h2 = (h * 9) / 20;
816
    for(ch = 0;ch < nb_display_channels; ch++) {
817
        i = i_start + ch;
818
        y1 = s->ytop + ch * h + (h / 2); /* position of center line */
819
        for(x = 0; x < s->width; x++) {
820
            y = (s->sample_array[i] * h2) >> 15;
821
            if (y < 0) {
822
                y = -y;
823
                ys = y1 - y;
824
            } else {
825
                ys = y1;
826
            }
827 115329f1 Diego Biurrun
            fill_rectangle(screen,
828
                           s->xleft + x, ys, 1, y,
829 01310af2 Fabrice Bellard
                           fgcolor);
830
            i += channels;
831
            if (i >= SAMPLE_ARRAY_SIZE)
832
                i -= SAMPLE_ARRAY_SIZE;
833
        }
834
    }
835
836
    fgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0xff);
837
838
    for(ch = 1;ch < nb_display_channels; ch++) {
839
        y = s->ytop + ch * h;
840 115329f1 Diego Biurrun
        fill_rectangle(screen,
841
                       s->xleft, y, s->width, 1,
842 01310af2 Fabrice Bellard
                       fgcolor);
843
    }
844
    SDL_UpdateRect(screen, s->xleft, s->ytop, s->width, s->height);
845
}
846
847 990c8438 Michael Niedermayer
static int video_open(VideoState *is){
848
    int flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
849
    int w,h;
850
851 fb84155b Michael Niedermayer
    if(is_full_screen) flags |= SDL_FULLSCREEN;
852
    else               flags |= SDL_RESIZABLE;
853
854 990c8438 Michael Niedermayer
    if (is_full_screen && fs_screen_width) {
855
        w = fs_screen_width;
856
        h = fs_screen_height;
857 fb84155b Michael Niedermayer
    } else if(!is_full_screen && screen_width){
858
        w = screen_width;
859
        h = screen_height;
860
    }else if (is->video_st && is->video_st->codec->width){
861
        w = is->video_st->codec->width;
862
        h = is->video_st->codec->height;
863 990c8438 Michael Niedermayer
    } else {
864 fb84155b Michael Niedermayer
        w = 640;
865
        h = 480;
866 990c8438 Michael Niedermayer
    }
867 c97f5402 Diego Biurrun
#ifndef __APPLE__
868 990c8438 Michael Niedermayer
    screen = SDL_SetVideoMode(w, h, 0, flags);
869
#else
870
    /* setting bits_per_pixel = 0 or 32 causes blank video on OS X */
871
    screen = SDL_SetVideoMode(w, h, 24, flags);
872
#endif
873
    if (!screen) {
874
        fprintf(stderr, "SDL: could not set video mode - exiting\n");
875
        return -1;
876
    }
877
    SDL_WM_SetCaption("FFplay", "FFplay");
878
879
    is->width = screen->w;
880
    is->height = screen->h;
881
882
    return 0;
883
}
884 8c982c5d Michael Niedermayer
885 01310af2 Fabrice Bellard
/* display the current picture, if any */
886
static void video_display(VideoState *is)
887
{
888 8c982c5d Michael Niedermayer
    if(!screen)
889
        video_open(cur_stream);
890 115329f1 Diego Biurrun
    if (is->audio_st && is->show_audio)
891 01310af2 Fabrice Bellard
        video_audio_display(is);
892
    else if (is->video_st)
893
        video_image_display(is);
894
}
895
896
static Uint32 sdl_refresh_timer_cb(Uint32 interval, void *opaque)
897
{
898
    SDL_Event event;
899
    event.type = FF_REFRESH_EVENT;
900
    event.user.data1 = opaque;
901
    SDL_PushEvent(&event);
902
    return 0; /* 0 means stop timer */
903
}
904
905
/* schedule a video refresh in 'delay' ms */
906
static void schedule_refresh(VideoState *is, int delay)
907
{
908 cc1f91d7 Michael Niedermayer
    if(!delay) delay=1; //SDL seems to be buggy when the delay is 0
909 01310af2 Fabrice Bellard
    SDL_AddTimer(delay, sdl_refresh_timer_cb, is);
910
}
911
912 638c9d91 Fabrice Bellard
/* get the current audio clock value */
913
static double get_audio_clock(VideoState *is)
914
{
915
    double pts;
916
    int hw_buf_size, bytes_per_sec;
917
    pts = is->audio_clock;
918
    hw_buf_size = audio_write_get_buf_size(is);
919
    bytes_per_sec = 0;
920
    if (is->audio_st) {
921 115329f1 Diego Biurrun
        bytes_per_sec = is->audio_st->codec->sample_rate *
922 01f4895c Michael Niedermayer
            2 * is->audio_st->codec->channels;
923 638c9d91 Fabrice Bellard
    }
924
    if (bytes_per_sec)
925
        pts -= (double)hw_buf_size / bytes_per_sec;
926
    return pts;
927
}
928
929
/* get the current video clock value */
930
static double get_video_clock(VideoState *is)
931
{
932
    double delta;
933 04108619 Michael Niedermayer
    if (is->paused) {
934 72ea344b Fabrice Bellard
        delta = 0;
935
    } else {
936
        delta = (av_gettime() - is->video_current_pts_time) / 1000000.0;
937
    }
938 638c9d91 Fabrice Bellard
    return is->video_current_pts + delta;
939
}
940
941
/* get the current external clock value */
942
static double get_external_clock(VideoState *is)
943
{
944
    int64_t ti;
945
    ti = av_gettime();
946
    return is->external_clock + ((ti - is->external_clock_time) * 1e-6);
947
}
948
949
/* get the current master clock value */
950
static double get_master_clock(VideoState *is)
951
{
952
    double val;
953
954 72ea344b Fabrice Bellard
    if (is->av_sync_type == AV_SYNC_VIDEO_MASTER) {
955
        if (is->video_st)
956
            val = get_video_clock(is);
957
        else
958
            val = get_audio_clock(is);
959
    } else if (is->av_sync_type == AV_SYNC_AUDIO_MASTER) {
960
        if (is->audio_st)
961
            val = get_audio_clock(is);
962
        else
963
            val = get_video_clock(is);
964
    } else {
965 638c9d91 Fabrice Bellard
        val = get_external_clock(is);
966 72ea344b Fabrice Bellard
    }
967 638c9d91 Fabrice Bellard
    return val;
968
}
969
970 72ea344b Fabrice Bellard
/* seek in the stream */
971 4ed29207 Michael Niedermayer
static void stream_seek(VideoState *is, int64_t pos, int64_t rel)
972 72ea344b Fabrice Bellard
{
973 687fae2b Ivan Wong
    if (!is->seek_req) {
974
        is->seek_pos = pos;
975 4ed29207 Michael Niedermayer
        is->seek_rel = rel;
976 94b594c6 Steve L'Homme
        if (seek_by_bytes)
977
            is->seek_flags |= AVSEEK_FLAG_BYTE;
978 687fae2b Ivan Wong
        is->seek_req = 1;
979
    }
980 72ea344b Fabrice Bellard
}
981
982
/* pause or resume the video */
983
static void stream_pause(VideoState *is)
984
{
985
    is->paused = !is->paused;
986 917fa192 Michael McConnell
    if (!is->paused) {
987 72ea344b Fabrice Bellard
        is->video_current_pts = get_video_clock(is);
988 917fa192 Michael McConnell
        is->frame_timer += (av_gettime() - is->video_current_pts_time) / 1000000.0;
989 72ea344b Fabrice Bellard
    }
990
}
991
992 49410784 Tomer Barletz
static double compute_frame_delay(double frame_current_pts, VideoState *is)
993
{
994
    double actual_delay, delay, sync_threshold, ref_clock, diff;
995
996
    /* compute nominal delay */
997
    delay = frame_current_pts - is->frame_last_pts;
998
    if (delay <= 0 || delay >= 10.0) {
999
        /* if incorrect delay, use previous one */
1000
        delay = is->frame_last_delay;
1001 443658fd Tomer Barletz
    } else {
1002 712de377 Benoit Fouet
        is->frame_last_delay = delay;
1003 443658fd Tomer Barletz
    }
1004 49410784 Tomer Barletz
    is->frame_last_pts = frame_current_pts;
1005
1006
    /* update delay to follow master synchronisation source */
1007
    if (((is->av_sync_type == AV_SYNC_AUDIO_MASTER && is->audio_st) ||
1008
         is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
1009
        /* if video is slave, we try to correct big delays by
1010
           duplicating or deleting a frame */
1011
        ref_clock = get_master_clock(is);
1012
        diff = frame_current_pts - ref_clock;
1013
1014
        /* skip or repeat frame. We take into account the
1015
           delay to compute the threshold. I still don't know
1016
           if it is the best guess */
1017
        sync_threshold = FFMAX(AV_SYNC_THRESHOLD, delay);
1018
        if (fabs(diff) < AV_NOSYNC_THRESHOLD) {
1019
            if (diff <= -sync_threshold)
1020
                delay = 0;
1021
            else if (diff >= sync_threshold)
1022
                delay = 2 * delay;
1023
        }
1024
    }
1025
1026
    is->frame_timer += delay;
1027
    /* compute the REAL delay (we need to do that to avoid
1028
       long term errors */
1029
    actual_delay = is->frame_timer - (av_gettime() / 1000000.0);
1030
    if (actual_delay < 0.010) {
1031
        /* XXX: should skip picture */
1032
        actual_delay = 0.010;
1033
    }
1034
1035 eecc17a7 Tomer Barletz
#if defined(DEBUG_SYNC)
1036
    printf("video: delay=%0.3f actual_delay=%0.3f pts=%0.3f A-V=%f\n",
1037
            delay, actual_delay, frame_current_pts, -diff);
1038
#endif
1039
1040 49410784 Tomer Barletz
    return actual_delay;
1041
}
1042
1043 01310af2 Fabrice Bellard
/* called to display each frame */
1044
static void video_refresh_timer(void *opaque)
1045
{
1046
    VideoState *is = opaque;
1047
    VideoPicture *vp;
1048 638c9d91 Fabrice Bellard
1049 72ce053b Ian Caulfield
    SubPicture *sp, *sp2;
1050 01310af2 Fabrice Bellard
1051
    if (is->video_st) {
1052
        if (is->pictq_size == 0) {
1053
            /* if no picture, need to wait */
1054 7e0140cb Michael Niedermayer
            schedule_refresh(is, 1);
1055 01310af2 Fabrice Bellard
        } else {
1056 638c9d91 Fabrice Bellard
            /* dequeue the picture */
1057 01310af2 Fabrice Bellard
            vp = &is->pictq[is->pictq_rindex];
1058 638c9d91 Fabrice Bellard
1059
            /* update current video pts */
1060
            is->video_current_pts = vp->pts;
1061
            is->video_current_pts_time = av_gettime();
1062
1063 01310af2 Fabrice Bellard
            /* launch timer for next picture */
1064 49410784 Tomer Barletz
            schedule_refresh(is, (int)(compute_frame_delay(vp->pts, is) * 1000 + 0.5));
1065 638c9d91 Fabrice Bellard
1066 72ce053b Ian Caulfield
            if(is->subtitle_st) {
1067
                if (is->subtitle_stream_changed) {
1068
                    SDL_LockMutex(is->subpq_mutex);
1069 115329f1 Diego Biurrun
1070 72ce053b Ian Caulfield
                    while (is->subpq_size) {
1071
                        free_subpicture(&is->subpq[is->subpq_rindex]);
1072 115329f1 Diego Biurrun
1073 72ce053b Ian Caulfield
                        /* update queue size and signal for next picture */
1074
                        if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
1075
                            is->subpq_rindex = 0;
1076 115329f1 Diego Biurrun
1077 72ce053b Ian Caulfield
                        is->subpq_size--;
1078
                    }
1079
                    is->subtitle_stream_changed = 0;
1080
1081
                    SDL_CondSignal(is->subpq_cond);
1082
                    SDL_UnlockMutex(is->subpq_mutex);
1083
                } else {
1084
                    if (is->subpq_size > 0) {
1085
                        sp = &is->subpq[is->subpq_rindex];
1086
1087
                        if (is->subpq_size > 1)
1088
                            sp2 = &is->subpq[(is->subpq_rindex + 1) % SUBPICTURE_QUEUE_SIZE];
1089
                        else
1090
                            sp2 = NULL;
1091
1092
                        if ((is->video_current_pts > (sp->pts + ((float) sp->sub.end_display_time / 1000)))
1093
                                || (sp2 && is->video_current_pts > (sp2->pts + ((float) sp2->sub.start_display_time / 1000))))
1094
                        {
1095
                            free_subpicture(sp);
1096
1097
                            /* update queue size and signal for next picture */
1098
                            if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
1099
                                is->subpq_rindex = 0;
1100
1101
                            SDL_LockMutex(is->subpq_mutex);
1102
                            is->subpq_size--;
1103
                            SDL_CondSignal(is->subpq_cond);
1104
                            SDL_UnlockMutex(is->subpq_mutex);
1105
                        }
1106
                    }
1107
                }
1108
            }
1109
1110 01310af2 Fabrice Bellard
            /* display picture */
1111
            video_display(is);
1112 115329f1 Diego Biurrun
1113 01310af2 Fabrice Bellard
            /* update queue size and signal for next picture */
1114
            if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE)
1115
                is->pictq_rindex = 0;
1116 115329f1 Diego Biurrun
1117 01310af2 Fabrice Bellard
            SDL_LockMutex(is->pictq_mutex);
1118
            is->pictq_size--;
1119
            SDL_CondSignal(is->pictq_cond);
1120
            SDL_UnlockMutex(is->pictq_mutex);
1121
        }
1122
    } else if (is->audio_st) {
1123
        /* draw the next audio frame */
1124
1125
        schedule_refresh(is, 40);
1126
1127
        /* if only audio stream, then display the audio bars (better
1128
           than nothing, just to test the implementation */
1129 115329f1 Diego Biurrun
1130 01310af2 Fabrice Bellard
        /* display picture */
1131
        video_display(is);
1132
    } else {
1133
        schedule_refresh(is, 100);
1134
    }
1135
    if (show_status) {
1136
        static int64_t last_time;
1137
        int64_t cur_time;
1138 72ce053b Ian Caulfield
        int aqsize, vqsize, sqsize;
1139 638c9d91 Fabrice Bellard
        double av_diff;
1140 115329f1 Diego Biurrun
1141 01310af2 Fabrice Bellard
        cur_time = av_gettime();
1142
        if (!last_time || (cur_time - last_time) >= 500 * 1000) {
1143
            aqsize = 0;
1144
            vqsize = 0;
1145 72ce053b Ian Caulfield
            sqsize = 0;
1146 01310af2 Fabrice Bellard
            if (is->audio_st)
1147
                aqsize = is->audioq.size;
1148
            if (is->video_st)
1149
                vqsize = is->videoq.size;
1150 72ce053b Ian Caulfield
            if (is->subtitle_st)
1151
                sqsize = is->subtitleq.size;
1152 638c9d91 Fabrice Bellard
            av_diff = 0;
1153
            if (is->audio_st && is->video_st)
1154
                av_diff = get_audio_clock(is) - get_video_clock(is);
1155 115329f1 Diego Biurrun
            printf("%7.2f A-V:%7.3f aq=%5dKB vq=%5dKB sq=%5dB    \r",
1156 72ce053b Ian Caulfield
                   get_master_clock(is), av_diff, aqsize / 1024, vqsize / 1024, sqsize);
1157 01310af2 Fabrice Bellard
            fflush(stdout);
1158
            last_time = cur_time;
1159
        }
1160
    }
1161
}
1162
1163
/* allocate a picture (needs to do that in main thread to avoid
1164
   potential locking problems */
1165
static void alloc_picture(void *opaque)
1166
{
1167
    VideoState *is = opaque;
1168
    VideoPicture *vp;
1169
1170
    vp = &is->pictq[is->pictq_windex];
1171
1172
    if (vp->bmp)
1173
        SDL_FreeYUVOverlay(vp->bmp);
1174
1175 61890b02 Fabrice Bellard
#if 0
1176 01310af2 Fabrice Bellard
    /* XXX: use generic function */
1177 61890b02 Fabrice Bellard
    /* XXX: disable overlay if no hardware acceleration or if RGB format */
1178 01f4895c Michael Niedermayer
    switch(is->video_st->codec->pix_fmt) {
1179 01310af2 Fabrice Bellard
    case PIX_FMT_YUV420P:
1180
    case PIX_FMT_YUV422P:
1181
    case PIX_FMT_YUV444P:
1182 71e445fc Diego Biurrun
    case PIX_FMT_YUYV422:
1183 01310af2 Fabrice Bellard
    case PIX_FMT_YUV410P:
1184
    case PIX_FMT_YUV411P:
1185
        is_yuv = 1;
1186
        break;
1187
    default:
1188
        is_yuv = 0;
1189
        break;
1190
    }
1191
#endif
1192 01f4895c Michael Niedermayer
    vp->bmp = SDL_CreateYUVOverlay(is->video_st->codec->width,
1193
                                   is->video_st->codec->height,
1194 115329f1 Diego Biurrun
                                   SDL_YV12_OVERLAY,
1195 61890b02 Fabrice Bellard
                                   screen);
1196 01f4895c Michael Niedermayer
    vp->width = is->video_st->codec->width;
1197
    vp->height = is->video_st->codec->height;
1198 01310af2 Fabrice Bellard
1199
    SDL_LockMutex(is->pictq_mutex);
1200
    vp->allocated = 1;
1201
    SDL_CondSignal(is->pictq_cond);
1202
    SDL_UnlockMutex(is->pictq_mutex);
1203
}
1204
1205 267e9dfa Michael Niedermayer
/**
1206
 *
1207
 * @param pts the dts of the pkt / pts of the frame and guessed if not known
1208
 */
1209 638c9d91 Fabrice Bellard
static int queue_picture(VideoState *is, AVFrame *src_frame, double pts)
1210 01310af2 Fabrice Bellard
{
1211
    VideoPicture *vp;
1212
    int dst_pix_fmt;
1213 115329f1 Diego Biurrun
1214 01310af2 Fabrice Bellard
    /* wait until we have space to put a new picture */
1215
    SDL_LockMutex(is->pictq_mutex);
1216
    while (is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE &&
1217
           !is->videoq.abort_request) {
1218
        SDL_CondWait(is->pictq_cond, is->pictq_mutex);
1219
    }
1220
    SDL_UnlockMutex(is->pictq_mutex);
1221 115329f1 Diego Biurrun
1222 01310af2 Fabrice Bellard
    if (is->videoq.abort_request)
1223
        return -1;
1224
1225
    vp = &is->pictq[is->pictq_windex];
1226
1227
    /* alloc or resize hardware picture buffer */
1228 115329f1 Diego Biurrun
    if (!vp->bmp ||
1229 01f4895c Michael Niedermayer
        vp->width != is->video_st->codec->width ||
1230
        vp->height != is->video_st->codec->height) {
1231 01310af2 Fabrice Bellard
        SDL_Event event;
1232
1233
        vp->allocated = 0;
1234
1235
        /* the allocation must be done in the main thread to avoid
1236
           locking problems */
1237
        event.type = FF_ALLOC_EVENT;
1238
        event.user.data1 = is;
1239
        SDL_PushEvent(&event);
1240 115329f1 Diego Biurrun
1241 01310af2 Fabrice Bellard
        /* wait until the picture is allocated */
1242
        SDL_LockMutex(is->pictq_mutex);
1243
        while (!vp->allocated && !is->videoq.abort_request) {
1244
            SDL_CondWait(is->pictq_cond, is->pictq_mutex);
1245
        }
1246
        SDL_UnlockMutex(is->pictq_mutex);
1247
1248
        if (is->videoq.abort_request)
1249
            return -1;
1250
    }
1251
1252 638c9d91 Fabrice Bellard
    /* if the frame is not skipped, then display it */
1253 01310af2 Fabrice Bellard
    if (vp->bmp) {
1254 fbf1b885 avcoder
        AVPicture pict;
1255
1256 01310af2 Fabrice Bellard
        /* get a pointer on the bitmap */
1257
        SDL_LockYUVOverlay (vp->bmp);
1258
1259
        dst_pix_fmt = PIX_FMT_YUV420P;
1260 fbf1b885 avcoder
        memset(&pict,0,sizeof(AVPicture));
1261 01310af2 Fabrice Bellard
        pict.data[0] = vp->bmp->pixels[0];
1262
        pict.data[1] = vp->bmp->pixels[2];
1263
        pict.data[2] = vp->bmp->pixels[1];
1264
1265
        pict.linesize[0] = vp->bmp->pitches[0];
1266
        pict.linesize[1] = vp->bmp->pitches[2];
1267
        pict.linesize[2] = vp->bmp->pitches[1];
1268 e43d7a18 Michael Niedermayer
        sws_flags = av_get_int(sws_opts, "sws_flags", NULL);
1269 3ac56e28 Martin Storsjö
        is->img_convert_ctx = sws_getCachedContext(is->img_convert_ctx,
1270 feb7bc67 Alex Beregszaszi
            is->video_st->codec->width, is->video_st->codec->height,
1271
            is->video_st->codec->pix_fmt,
1272
            is->video_st->codec->width, is->video_st->codec->height,
1273
            dst_pix_fmt, sws_flags, NULL, NULL, NULL);
1274 3ac56e28 Martin Storsjö
        if (is->img_convert_ctx == NULL) {
1275 26ba8235 Alex Beregszaszi
            fprintf(stderr, "Cannot initialize the conversion context\n");
1276
            exit(1);
1277
        }
1278 3ac56e28 Martin Storsjö
        sws_scale(is->img_convert_ctx, src_frame->data, src_frame->linesize,
1279 03ae87a3 Luca Abeni
                  0, is->video_st->codec->height, pict.data, pict.linesize);
1280 01310af2 Fabrice Bellard
        /* update the bitmap content */
1281
        SDL_UnlockYUVOverlay(vp->bmp);
1282
1283 638c9d91 Fabrice Bellard
        vp->pts = pts;
1284 01310af2 Fabrice Bellard
1285
        /* now we can update the picture count */
1286
        if (++is->pictq_windex == VIDEO_PICTURE_QUEUE_SIZE)
1287
            is->pictq_windex = 0;
1288
        SDL_LockMutex(is->pictq_mutex);
1289
        is->pictq_size++;
1290
        SDL_UnlockMutex(is->pictq_mutex);
1291
    }
1292 638c9d91 Fabrice Bellard
    return 0;
1293
}
1294
1295 115329f1 Diego Biurrun
/**
1296
 * compute the exact PTS for the picture if it is omitted in the stream
1297 267e9dfa Michael Niedermayer
 * @param pts1 the dts of the pkt / pts of the frame
1298
 */
1299 638c9d91 Fabrice Bellard
static int output_picture2(VideoState *is, AVFrame *src_frame, double pts1)
1300
{
1301
    double frame_delay, pts;
1302 115329f1 Diego Biurrun
1303 638c9d91 Fabrice Bellard
    pts = pts1;
1304
1305 01310af2 Fabrice Bellard
    if (pts != 0) {
1306 638c9d91 Fabrice Bellard
        /* update video clock with pts, if present */
1307 01310af2 Fabrice Bellard
        is->video_clock = pts;
1308
    } else {
1309 72ea344b Fabrice Bellard
        pts = is->video_clock;
1310
    }
1311
    /* update video clock for next frame */
1312 01f4895c Michael Niedermayer
    frame_delay = av_q2d(is->video_st->codec->time_base);
1313 72ea344b Fabrice Bellard
    /* for MPEG2, the frame can be repeated, so we update the
1314
       clock accordingly */
1315 267e9dfa Michael Niedermayer
    frame_delay += src_frame->repeat_pict * (frame_delay * 0.5);
1316 72ea344b Fabrice Bellard
    is->video_clock += frame_delay;
1317 638c9d91 Fabrice Bellard
1318
#if defined(DEBUG_SYNC) && 0
1319
    {
1320
        int ftype;
1321
        if (src_frame->pict_type == FF_B_TYPE)
1322
            ftype = 'B';
1323
        else if (src_frame->pict_type == FF_I_TYPE)
1324
            ftype = 'I';
1325
        else
1326
            ftype = 'P';
1327 115329f1 Diego Biurrun
        printf("frame_type=%c clock=%0.3f pts=%0.3f\n",
1328 72ea344b Fabrice Bellard
               ftype, pts, pts1);
1329 638c9d91 Fabrice Bellard
    }
1330
#endif
1331 72ea344b Fabrice Bellard
    return queue_picture(is, src_frame, pts);
1332 01310af2 Fabrice Bellard
}
1333
1334
static int video_thread(void *arg)
1335
{
1336
    VideoState *is = arg;
1337
    AVPacket pkt1, *pkt = &pkt1;
1338 72ea344b Fabrice Bellard
    int len1, got_picture;
1339 c6b1edc9 Michael Niedermayer
    AVFrame *frame= avcodec_alloc_frame();
1340 01310af2 Fabrice Bellard
    double pts;
1341
1342
    for(;;) {
1343
        while (is->paused && !is->videoq.abort_request) {
1344
            SDL_Delay(10);
1345
        }
1346
        if (packet_queue_get(&is->videoq, pkt, 1) < 0)
1347
            break;
1348 39c6a118 Michael Niedermayer
1349
        if(pkt->data == flush_pkt.data){
1350
            avcodec_flush_buffers(is->video_st->codec);
1351
            continue;
1352
        }
1353
1354 638c9d91 Fabrice Bellard
        /* NOTE: ipts is the PTS of the _first_ picture beginning in
1355
           this packet, if any */
1356 7fb262b5 Michael Niedermayer
        is->video_st->codec->reordered_opaque= pkt->pts;
1357 bea18375 Thilo Borgmann
        len1 = avcodec_decode_video2(is->video_st->codec,
1358 620e8baf Michael Niedermayer
                                    frame, &got_picture,
1359 bea18375 Thilo Borgmann
                                    pkt);
1360 620e8baf Michael Niedermayer
1361
        if(   (decoder_reorder_pts || pkt->dts == AV_NOPTS_VALUE)
1362 7fb262b5 Michael Niedermayer
           && frame->reordered_opaque != AV_NOPTS_VALUE)
1363
            pts= frame->reordered_opaque;
1364 620e8baf Michael Niedermayer
        else if(pkt->dts != AV_NOPTS_VALUE)
1365
            pts= pkt->dts;
1366
        else
1367
            pts= 0;
1368
        pts *= av_q2d(is->video_st->time_base);
1369 5039185a Michael Niedermayer
1370 fb966f99 Michael Niedermayer
//            if (len1 < 0)
1371
//                break;
1372 620e8baf Michael Niedermayer
        if (got_picture) {
1373
            if (output_picture2(is, frame, pts) < 0)
1374
                goto the_end;
1375
        }
1376 01310af2 Fabrice Bellard
        av_free_packet(pkt);
1377 115329f1 Diego Biurrun
        if (step)
1378 bba04f1e Wolfgang Hesseler
            if (cur_stream)
1379
                stream_pause(cur_stream);
1380 01310af2 Fabrice Bellard
    }
1381
 the_end:
1382 c6b1edc9 Michael Niedermayer
    av_free(frame);
1383 01310af2 Fabrice Bellard
    return 0;
1384
}
1385
1386 72ce053b Ian Caulfield
static int subtitle_thread(void *arg)
1387
{
1388
    VideoState *is = arg;
1389
    SubPicture *sp;
1390
    AVPacket pkt1, *pkt = &pkt1;
1391
    int len1, got_subtitle;
1392
    double pts;
1393
    int i, j;
1394
    int r, g, b, y, u, v, a;
1395
1396
    for(;;) {
1397
        while (is->paused && !is->subtitleq.abort_request) {
1398
            SDL_Delay(10);
1399
        }
1400
        if (packet_queue_get(&is->subtitleq, pkt, 1) < 0)
1401
            break;
1402 115329f1 Diego Biurrun
1403 39c6a118 Michael Niedermayer
        if(pkt->data == flush_pkt.data){
1404
            avcodec_flush_buffers(is->subtitle_st->codec);
1405
            continue;
1406
        }
1407 72ce053b Ian Caulfield
        SDL_LockMutex(is->subpq_mutex);
1408
        while (is->subpq_size >= SUBPICTURE_QUEUE_SIZE &&
1409
               !is->subtitleq.abort_request) {
1410
            SDL_CondWait(is->subpq_cond, is->subpq_mutex);
1411
        }
1412
        SDL_UnlockMutex(is->subpq_mutex);
1413 115329f1 Diego Biurrun
1414 72ce053b Ian Caulfield
        if (is->subtitleq.abort_request)
1415
            goto the_end;
1416 115329f1 Diego Biurrun
1417 72ce053b Ian Caulfield
        sp = &is->subpq[is->subpq_windex];
1418
1419
       /* NOTE: ipts is the PTS of the _first_ picture beginning in
1420
           this packet, if any */
1421
        pts = 0;
1422
        if (pkt->pts != AV_NOPTS_VALUE)
1423
            pts = av_q2d(is->subtitle_st->time_base)*pkt->pts;
1424
1425 bea18375 Thilo Borgmann
        len1 = avcodec_decode_subtitle2(is->subtitle_st->codec,
1426 115329f1 Diego Biurrun
                                    &sp->sub, &got_subtitle,
1427 bea18375 Thilo Borgmann
                                    pkt);
1428 72ce053b Ian Caulfield
//            if (len1 < 0)
1429
//                break;
1430
        if (got_subtitle && sp->sub.format == 0) {
1431
            sp->pts = pts;
1432 115329f1 Diego Biurrun
1433 72ce053b Ian Caulfield
            for (i = 0; i < sp->sub.num_rects; i++)
1434
            {
1435 db4fac64 Michael Niedermayer
                for (j = 0; j < sp->sub.rects[i]->nb_colors; j++)
1436 72ce053b Ian Caulfield
                {
1437 25b4c651 Michael Niedermayer
                    RGBA_IN(r, g, b, a, (uint32_t*)sp->sub.rects[i]->pict.data[1] + j);
1438 72ce053b Ian Caulfield
                    y = RGB_TO_Y_CCIR(r, g, b);
1439
                    u = RGB_TO_U_CCIR(r, g, b, 0);
1440
                    v = RGB_TO_V_CCIR(r, g, b, 0);
1441 25b4c651 Michael Niedermayer
                    YUVA_OUT((uint32_t*)sp->sub.rects[i]->pict.data[1] + j, y, u, v, a);
1442 72ce053b Ian Caulfield
                }
1443
            }
1444
1445
            /* now we can update the picture count */
1446
            if (++is->subpq_windex == SUBPICTURE_QUEUE_SIZE)
1447
                is->subpq_windex = 0;
1448
            SDL_LockMutex(is->subpq_mutex);
1449
            is->subpq_size++;
1450
            SDL_UnlockMutex(is->subpq_mutex);
1451
        }
1452
        av_free_packet(pkt);
1453 115329f1 Diego Biurrun
//        if (step)
1454 72ce053b Ian Caulfield
//            if (cur_stream)
1455
//                stream_pause(cur_stream);
1456
    }
1457
 the_end:
1458
    return 0;
1459
}
1460
1461 01310af2 Fabrice Bellard
/* copy samples for viewing in editor window */
1462
static void update_sample_display(VideoState *is, short *samples, int samples_size)
1463
{
1464
    int size, len, channels;
1465
1466 01f4895c Michael Niedermayer
    channels = is->audio_st->codec->channels;
1467 01310af2 Fabrice Bellard
1468
    size = samples_size / sizeof(short);
1469
    while (size > 0) {
1470
        len = SAMPLE_ARRAY_SIZE - is->sample_array_index;
1471
        if (len > size)
1472
            len = size;
1473
        memcpy(is->sample_array + is->sample_array_index, samples, len * sizeof(short));
1474
        samples += len;
1475
        is->sample_array_index += len;
1476
        if (is->sample_array_index >= SAMPLE_ARRAY_SIZE)
1477
            is->sample_array_index = 0;
1478
        size -= len;
1479
    }
1480
}
1481
1482
/* return the new audio buffer size (samples can be added or deleted
1483
   to get better sync if video or external master clock) */
1484 115329f1 Diego Biurrun
static int synchronize_audio(VideoState *is, short *samples,
1485 638c9d91 Fabrice Bellard
                             int samples_size1, double pts)
1486 01310af2 Fabrice Bellard
{
1487 638c9d91 Fabrice Bellard
    int n, samples_size;
1488 01310af2 Fabrice Bellard
    double ref_clock;
1489 115329f1 Diego Biurrun
1490 01f4895c Michael Niedermayer
    n = 2 * is->audio_st->codec->channels;
1491 638c9d91 Fabrice Bellard
    samples_size = samples_size1;
1492 01310af2 Fabrice Bellard
1493
    /* if not master, then we try to remove or add samples to correct the clock */
1494
    if (((is->av_sync_type == AV_SYNC_VIDEO_MASTER && is->video_st) ||
1495 638c9d91 Fabrice Bellard
         is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
1496
        double diff, avg_diff;
1497 01310af2 Fabrice Bellard
        int wanted_size, min_size, max_size, nb_samples;
1498 115329f1 Diego Biurrun
1499 638c9d91 Fabrice Bellard
        ref_clock = get_master_clock(is);
1500
        diff = get_audio_clock(is) - ref_clock;
1501 115329f1 Diego Biurrun
1502 638c9d91 Fabrice Bellard
        if (diff < AV_NOSYNC_THRESHOLD) {
1503
            is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum;
1504
            if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {
1505
                /* not enough measures to have a correct estimate */
1506
                is->audio_diff_avg_count++;
1507
            } else {
1508
                /* estimate the A-V difference */
1509
                avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef);
1510
1511
                if (fabs(avg_diff) >= is->audio_diff_threshold) {
1512 01f4895c Michael Niedermayer
                    wanted_size = samples_size + ((int)(diff * is->audio_st->codec->sample_rate) * n);
1513 638c9d91 Fabrice Bellard
                    nb_samples = samples_size / n;
1514 115329f1 Diego Biurrun
1515 638c9d91 Fabrice Bellard
                    min_size = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
1516
                    max_size = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
1517
                    if (wanted_size < min_size)
1518
                        wanted_size = min_size;
1519
                    else if (wanted_size > max_size)
1520
                        wanted_size = max_size;
1521 115329f1 Diego Biurrun
1522 638c9d91 Fabrice Bellard
                    /* add or remove samples to correction the synchro */
1523
                    if (wanted_size < samples_size) {
1524
                        /* remove samples */
1525
                        samples_size = wanted_size;
1526
                    } else if (wanted_size > samples_size) {
1527
                        uint8_t *samples_end, *q;
1528
                        int nb;
1529 115329f1 Diego Biurrun
1530 638c9d91 Fabrice Bellard
                        /* add samples */
1531
                        nb = (samples_size - wanted_size);
1532
                        samples_end = (uint8_t *)samples + samples_size - n;
1533
                        q = samples_end + n;
1534
                        while (nb > 0) {
1535
                            memcpy(q, samples_end, n);
1536
                            q += n;
1537
                            nb -= n;
1538
                        }
1539
                        samples_size = wanted_size;
1540
                    }
1541
                }
1542
#if 0
1543 115329f1 Diego Biurrun
                printf("diff=%f adiff=%f sample_diff=%d apts=%0.3f vpts=%0.3f %f\n",
1544
                       diff, avg_diff, samples_size - samples_size1,
1545 638c9d91 Fabrice Bellard
                       is->audio_clock, is->video_clock, is->audio_diff_threshold);
1546
#endif
1547 01310af2 Fabrice Bellard
            }
1548 638c9d91 Fabrice Bellard
        } else {
1549
            /* too big difference : may be initial PTS errors, so
1550
               reset A-V filter */
1551
            is->audio_diff_avg_count = 0;
1552
            is->audio_diff_cum = 0;
1553 01310af2 Fabrice Bellard
        }
1554
    }
1555
1556
    return samples_size;
1557
}
1558
1559
/* decode one audio frame and returns its uncompressed size */
1560 5a4476e2 Peter Ross
static int audio_decode_frame(VideoState *is, double *pts_ptr)
1561 01310af2 Fabrice Bellard
{
1562 bea18375 Thilo Borgmann
    AVPacket *pkt_temp = &is->audio_pkt_temp;
1563 01310af2 Fabrice Bellard
    AVPacket *pkt = &is->audio_pkt;
1564 abdff646 Peter Ross
    AVCodecContext *dec= is->audio_st->codec;
1565 72ea344b Fabrice Bellard
    int n, len1, data_size;
1566 01310af2 Fabrice Bellard
    double pts;
1567
1568
    for(;;) {
1569 72ea344b Fabrice Bellard
        /* NOTE: the audio packet can contain several frames */
1570 bea18375 Thilo Borgmann
        while (pkt_temp->size > 0) {
1571 5a4476e2 Peter Ross
            data_size = sizeof(is->audio_buf1);
1572 bea18375 Thilo Borgmann
            len1 = avcodec_decode_audio3(dec,
1573 5a4476e2 Peter Ross
                                        (int16_t *)is->audio_buf1, &data_size,
1574 bea18375 Thilo Borgmann
                                        pkt_temp);
1575 72ea344b Fabrice Bellard
            if (len1 < 0) {
1576
                /* if error, we skip the frame */
1577 bea18375 Thilo Borgmann
                pkt_temp->size = 0;
1578 01310af2 Fabrice Bellard
                break;
1579 72ea344b Fabrice Bellard
            }
1580 115329f1 Diego Biurrun
1581 bea18375 Thilo Borgmann
            pkt_temp->data += len1;
1582
            pkt_temp->size -= len1;
1583 72ea344b Fabrice Bellard
            if (data_size <= 0)
1584
                continue;
1585 5a4476e2 Peter Ross
1586
            if (dec->sample_fmt != is->audio_src_fmt) {
1587
                if (is->reformat_ctx)
1588
                    av_audio_convert_free(is->reformat_ctx);
1589
                is->reformat_ctx= av_audio_convert_alloc(SAMPLE_FMT_S16, 1,
1590
                                                         dec->sample_fmt, 1, NULL, 0);
1591
                if (!is->reformat_ctx) {
1592
                    fprintf(stderr, "Cannot convert %s sample format to %s sample format\n",
1593
                        avcodec_get_sample_fmt_name(dec->sample_fmt),
1594
                        avcodec_get_sample_fmt_name(SAMPLE_FMT_S16));
1595
                        break;
1596
                }
1597
                is->audio_src_fmt= dec->sample_fmt;
1598
            }
1599
1600
            if (is->reformat_ctx) {
1601
                const void *ibuf[6]= {is->audio_buf1};
1602
                void *obuf[6]= {is->audio_buf2};
1603
                int istride[6]= {av_get_bits_per_sample_format(dec->sample_fmt)/8};
1604
                int ostride[6]= {2};
1605
                int len= data_size/istride[0];
1606
                if (av_audio_convert(is->reformat_ctx, obuf, ostride, ibuf, istride, len)<0) {
1607
                    printf("av_audio_convert() failed\n");
1608
                    break;
1609
                }
1610
                is->audio_buf= is->audio_buf2;
1611
                /* FIXME: existing code assume that data_size equals framesize*channels*2
1612
                          remove this legacy cruft */
1613
                data_size= len*2;
1614
            }else{
1615
                is->audio_buf= is->audio_buf1;
1616
            }
1617
1618 72ea344b Fabrice Bellard
            /* if no pts, then compute it */
1619
            pts = is->audio_clock;
1620
            *pts_ptr = pts;
1621 abdff646 Peter Ross
            n = 2 * dec->channels;
1622 115329f1 Diego Biurrun
            is->audio_clock += (double)data_size /
1623 abdff646 Peter Ross
                (double)(n * dec->sample_rate);
1624 638c9d91 Fabrice Bellard
#if defined(DEBUG_SYNC)
1625 72ea344b Fabrice Bellard
            {
1626
                static double last_clock;
1627
                printf("audio: delay=%0.3f clock=%0.3f pts=%0.3f\n",
1628
                       is->audio_clock - last_clock,
1629
                       is->audio_clock, pts);
1630
                last_clock = is->audio_clock;
1631 01310af2 Fabrice Bellard
            }
1632 72ea344b Fabrice Bellard
#endif
1633
            return data_size;
1634 01310af2 Fabrice Bellard
        }
1635
1636 72ea344b Fabrice Bellard
        /* free the current packet */
1637
        if (pkt->data)
1638 01310af2 Fabrice Bellard
            av_free_packet(pkt);
1639 115329f1 Diego Biurrun
1640 72ea344b Fabrice Bellard
        if (is->paused || is->audioq.abort_request) {
1641
            return -1;
1642
        }
1643 115329f1 Diego Biurrun
1644 01310af2 Fabrice Bellard
        /* read next packet */
1645
        if (packet_queue_get(&is->audioq, pkt, 1) < 0)
1646
            return -1;
1647 39c6a118 Michael Niedermayer
        if(pkt->data == flush_pkt.data){
1648 abdff646 Peter Ross
            avcodec_flush_buffers(dec);
1649 39c6a118 Michael Niedermayer
            continue;
1650
        }
1651
1652 bea18375 Thilo Borgmann
        pkt_temp->data = pkt->data;
1653
        pkt_temp->size = pkt->size;
1654 115329f1 Diego Biurrun
1655 72ea344b Fabrice Bellard
        /* if update the audio clock with the pts */
1656
        if (pkt->pts != AV_NOPTS_VALUE) {
1657 c0df9d75 Michael Niedermayer
            is->audio_clock = av_q2d(is->audio_st->time_base)*pkt->pts;
1658 72ea344b Fabrice Bellard
        }
1659 01310af2 Fabrice Bellard
    }
1660
}
1661
1662 638c9d91 Fabrice Bellard
/* get the current audio output buffer size, in samples. With SDL, we
1663
   cannot have a precise information */
1664
static int audio_write_get_buf_size(VideoState *is)
1665 01310af2 Fabrice Bellard
{
1666 b09b580b Ryan Martell
    return is->audio_buf_size - is->audio_buf_index;
1667 01310af2 Fabrice Bellard
}
1668
1669
1670
/* prepare a new audio buffer */
1671 358061f6 Diego Pettenò
static void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
1672 01310af2 Fabrice Bellard
{
1673
    VideoState *is = opaque;
1674
    int audio_size, len1;
1675
    double pts;
1676
1677
    audio_callback_time = av_gettime();
1678 115329f1 Diego Biurrun
1679 01310af2 Fabrice Bellard
    while (len > 0) {
1680
        if (is->audio_buf_index >= is->audio_buf_size) {
1681 5a4476e2 Peter Ross
           audio_size = audio_decode_frame(is, &pts);
1682 01310af2 Fabrice Bellard
           if (audio_size < 0) {
1683
                /* if error, just output silence */
1684 1a1078fa Baptiste Coudurier
               is->audio_buf = is->audio_buf1;
1685 01310af2 Fabrice Bellard
               is->audio_buf_size = 1024;
1686
               memset(is->audio_buf, 0, is->audio_buf_size);
1687
           } else {
1688
               if (is->show_audio)
1689
                   update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
1690 115329f1 Diego Biurrun
               audio_size = synchronize_audio(is, (int16_t *)is->audio_buf, audio_size,
1691 01310af2 Fabrice Bellard
                                              pts);
1692
               is->audio_buf_size = audio_size;
1693
           }
1694
           is->audio_buf_index = 0;
1695
        }
1696
        len1 = is->audio_buf_size - is->audio_buf_index;
1697
        if (len1 > len)
1698
            len1 = len;
1699
        memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
1700
        len -= len1;
1701
        stream += len1;
1702
        is->audio_buf_index += len1;
1703
    }
1704
}
1705
1706
/* open a given stream. Return 0 if OK */
1707
static int stream_component_open(VideoState *is, int stream_index)
1708
{
1709
    AVFormatContext *ic = is->ic;
1710
    AVCodecContext *enc;
1711
    AVCodec *codec;
1712
    SDL_AudioSpec wanted_spec, spec;
1713
1714
    if (stream_index < 0 || stream_index >= ic->nb_streams)
1715
        return -1;
1716 01f4895c Michael Niedermayer
    enc = ic->streams[stream_index]->codec;
1717 115329f1 Diego Biurrun
1718 01310af2 Fabrice Bellard
    /* prepare audio output */
1719
    if (enc->codec_type == CODEC_TYPE_AUDIO) {
1720 51b73087 Justin Ruggles
        if (enc->channels > 0) {
1721
            enc->request_channels = FFMIN(2, enc->channels);
1722 94eadc8b Andreas Öman
        } else {
1723 51b73087 Justin Ruggles
            enc->request_channels = 2;
1724 638c9d91 Fabrice Bellard
        }
1725 01310af2 Fabrice Bellard
    }
1726
1727
    codec = avcodec_find_decoder(enc->codec_id);
1728 13d1512c Michael Niedermayer
    enc->debug_mv = debug_mv;
1729
    enc->debug = debug;
1730 6387c3e6 Michael Niedermayer
    enc->workaround_bugs = workaround_bugs;
1731 178fcca8 Michael Niedermayer
    enc->lowres = lowres;
1732 61846e9a Michael Niedermayer
    if(lowres) enc->flags |= CODEC_FLAG_EMU_EDGE;
1733 178fcca8 Michael Niedermayer
    enc->idct_algo= idct;
1734 6fc5b059 Michael Niedermayer
    if(fast) enc->flags2 |= CODEC_FLAG2_FAST;
1735 8c3eba7c Michael Niedermayer
    enc->skip_frame= skip_frame;
1736
    enc->skip_idct= skip_idct;
1737
    enc->skip_loop_filter= skip_loop_filter;
1738 047599a4 Michael Niedermayer
    enc->error_recognition= error_recognition;
1739 1b51e051 Michael Niedermayer
    enc->error_concealment= error_concealment;
1740 e43d7a18 Michael Niedermayer
1741 636f1c4c Stefano Sabatini
    set_context_opts(enc, avcodec_opts[enc->codec_type], 0);
1742 e43d7a18 Michael Niedermayer
1743 01310af2 Fabrice Bellard
    if (!codec ||
1744
        avcodec_open(enc, codec) < 0)
1745
        return -1;
1746 51b73087 Justin Ruggles
1747
    /* prepare audio output */
1748
    if (enc->codec_type == CODEC_TYPE_AUDIO) {
1749
        wanted_spec.freq = enc->sample_rate;
1750
        wanted_spec.format = AUDIO_S16SYS;
1751
        wanted_spec.channels = enc->channels;
1752
        wanted_spec.silence = 0;
1753
        wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
1754
        wanted_spec.callback = sdl_audio_callback;
1755
        wanted_spec.userdata = is;
1756
        if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
1757
            fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());
1758
            return -1;
1759
        }
1760
        is->audio_hw_buf_size = spec.size;
1761 5a4476e2 Peter Ross
        is->audio_src_fmt= SAMPLE_FMT_S16;
1762 51b73087 Justin Ruggles
    }
1763
1764 c62c07d3 Michael Niedermayer
    if(thread_count>1)
1765
        avcodec_thread_init(enc, thread_count);
1766
    enc->thread_count= thread_count;
1767 3f3fe38d Ronald S. Bultje
    ic->streams[stream_index]->discard = AVDISCARD_DEFAULT;
1768 638c9d91 Fabrice Bellard
    switch(enc->codec_type) {
1769 01310af2 Fabrice Bellard
    case CODEC_TYPE_AUDIO:
1770
        is->audio_stream = stream_index;
1771
        is->audio_st = ic->streams[stream_index];
1772
        is->audio_buf_size = 0;
1773
        is->audio_buf_index = 0;
1774 638c9d91 Fabrice Bellard
1775
        /* init averaging filter */
1776
        is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
1777
        is->audio_diff_avg_count = 0;
1778
        /* since we do not have a precise anough audio fifo fullness,
1779
           we correct audio sync only if larger than this threshold */
1780
        is->audio_diff_threshold = 2.0 * SDL_AUDIO_BUFFER_SIZE / enc->sample_rate;
1781
1782 01310af2 Fabrice Bellard
        memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
1783
        packet_queue_init(&is->audioq);
1784 bb270c08 Diego Biurrun
        SDL_PauseAudio(0);
1785 01310af2 Fabrice Bellard
        break;
1786
    case CODEC_TYPE_VIDEO:
1787
        is->video_stream = stream_index;
1788
        is->video_st = ic->streams[stream_index];
1789
1790 638c9d91 Fabrice Bellard
        is->frame_last_delay = 40e-3;
1791
        is->frame_timer = (double)av_gettime() / 1000000.0;
1792
        is->video_current_pts_time = av_gettime();
1793
1794 01310af2 Fabrice Bellard
        packet_queue_init(&is->videoq);
1795
        is->video_tid = SDL_CreateThread(video_thread, is);
1796
        break;
1797 72ce053b Ian Caulfield
    case CODEC_TYPE_SUBTITLE:
1798
        is->subtitle_stream = stream_index;
1799
        is->subtitle_st = ic->streams[stream_index];
1800
        packet_queue_init(&is->subtitleq);
1801 115329f1 Diego Biurrun
1802 72ce053b Ian Caulfield
        is->subtitle_tid = SDL_CreateThread(subtitle_thread, is);
1803
        break;
1804 01310af2 Fabrice Bellard
    default:
1805
        break;
1806
    }
1807
    return 0;
1808
}
1809
1810
static void stream_component_close(VideoState *is, int stream_index)
1811
{
1812
    AVFormatContext *ic = is->ic;
1813
    AVCodecContext *enc;
1814 115329f1 Diego Biurrun
1815 72ce053b Ian Caulfield
    if (stream_index < 0 || stream_index >= ic->nb_streams)
1816
        return;
1817 01f4895c Michael Niedermayer
    enc = ic->streams[stream_index]->codec;
1818 01310af2 Fabrice Bellard
1819
    switch(enc->codec_type) {
1820
    case CODEC_TYPE_AUDIO:
1821
        packet_queue_abort(&is->audioq);
1822
1823
        SDL_CloseAudio();
1824
1825
        packet_queue_end(&is->audioq);
1826 5a4476e2 Peter Ross
        if (is->reformat_ctx)
1827
            av_audio_convert_free(is->reformat_ctx);
1828 01310af2 Fabrice Bellard
        break;
1829
    case CODEC_TYPE_VIDEO:
1830
        packet_queue_abort(&is->videoq);
1831
1832
        /* note: we also signal this mutex to make sure we deblock the
1833
           video thread in all cases */
1834
        SDL_LockMutex(is->pictq_mutex);
1835
        SDL_CondSignal(is->pictq_cond);
1836
        SDL_UnlockMutex(is->pictq_mutex);
1837
1838
        SDL_WaitThread(is->video_tid, NULL);
1839
1840
        packet_queue_end(&is->videoq);
1841
        break;
1842 72ce053b Ian Caulfield
    case CODEC_TYPE_SUBTITLE:
1843
        packet_queue_abort(&is->subtitleq);
1844 115329f1 Diego Biurrun
1845 72ce053b Ian Caulfield
        /* note: we also signal this mutex to make sure we deblock the
1846
           video thread in all cases */
1847
        SDL_LockMutex(is->subpq_mutex);
1848
        is->subtitle_stream_changed = 1;
1849 115329f1 Diego Biurrun
1850 72ce053b Ian Caulfield
        SDL_CondSignal(is->subpq_cond);
1851
        SDL_UnlockMutex(is->subpq_mutex);
1852
1853
        SDL_WaitThread(is->subtitle_tid, NULL);
1854
1855
        packet_queue_end(&is->subtitleq);
1856
        break;
1857 01310af2 Fabrice Bellard
    default:
1858
        break;
1859
    }
1860
1861 3f3fe38d Ronald S. Bultje
    ic->streams[stream_index]->discard = AVDISCARD_ALL;
1862 01310af2 Fabrice Bellard
    avcodec_close(enc);
1863
    switch(enc->codec_type) {
1864
    case CODEC_TYPE_AUDIO:
1865
        is->audio_st = NULL;
1866
        is->audio_stream = -1;
1867
        break;
1868
    case CODEC_TYPE_VIDEO:
1869
        is->video_st = NULL;
1870
        is->video_stream = -1;
1871
        break;
1872 72ce053b Ian Caulfield
    case CODEC_TYPE_SUBTITLE:
1873
        is->subtitle_st = NULL;
1874
        is->subtitle_stream = -1;
1875
        break;
1876 01310af2 Fabrice Bellard
    default:
1877
        break;
1878
    }
1879
}
1880
1881 7b49ce2e Stefan Huehner
static void dump_stream_info(const AVFormatContext *s)
1882 d0526ecf Fabrice Bellard
{
1883 f7554a99 Aurelien Jacobs
    AVMetadataTag *tag = NULL;
1884
    while ((tag=av_metadata_get(s->metadata,"",tag,AV_METADATA_IGNORE_SUFFIX)))
1885
        fprintf(stderr, "%s: %s\n", tag->key, tag->value);
1886 d0526ecf Fabrice Bellard
}
1887
1888 416e3508 Fabrice Bellard
/* since we have only one decoding thread, we can use a global
1889
   variable instead of a thread local variable */
1890
static VideoState *global_video_state;
1891
1892
static int decode_interrupt_cb(void)
1893
{
1894
    return (global_video_state && global_video_state->abort_request);
1895
}
1896 01310af2 Fabrice Bellard
1897
/* this thread gets the stream from the disk or the network */
1898
static int decode_thread(void *arg)
1899
{
1900
    VideoState *is = arg;
1901
    AVFormatContext *ic;
1902 16a59a7b Björn Axelsson
    int err, i, ret, video_index, audio_index, subtitle_index;
1903 01310af2 Fabrice Bellard
    AVPacket pkt1, *pkt = &pkt1;
1904 61890b02 Fabrice Bellard
    AVFormatParameters params, *ap = &params;
1905 75bb7b0a Michael Niedermayer
    int eof=0;
1906 01310af2 Fabrice Bellard
1907
    video_index = -1;
1908
    audio_index = -1;
1909 16a59a7b Björn Axelsson
    subtitle_index = -1;
1910 01310af2 Fabrice Bellard
    is->video_stream = -1;
1911
    is->audio_stream = -1;
1912 72ce053b Ian Caulfield
    is->subtitle_stream = -1;
1913 01310af2 Fabrice Bellard
1914 416e3508 Fabrice Bellard
    global_video_state = is;
1915
    url_set_interrupt_cb(decode_interrupt_cb);
1916
1917 61890b02 Fabrice Bellard
    memset(ap, 0, sizeof(*ap));
1918 115329f1 Diego Biurrun
1919 e4b89522 Limin Wang
    ap->width = frame_width;
1920
    ap->height= frame_height;
1921 7e042912 Michael Niedermayer
    ap->time_base= (AVRational){1, 25};
1922 e4b89522 Limin Wang
    ap->pix_fmt = frame_pix_fmt;
1923 7e042912 Michael Niedermayer
1924 61890b02 Fabrice Bellard
    err = av_open_input_file(&ic, is->filename, is->iformat, 0, ap);
1925 638c9d91 Fabrice Bellard
    if (err < 0) {
1926
        print_error(is->filename, err);
1927
        ret = -1;
1928
        goto fail;
1929
    }
1930 01310af2 Fabrice Bellard
    is->ic = ic;
1931 30bc6613 Michael Niedermayer
1932
    if(genpts)
1933
        ic->flags |= AVFMT_FLAG_GENPTS;
1934
1935 24c07998 Luca Abeni
    err = av_find_stream_info(ic);
1936
    if (err < 0) {
1937
        fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
1938
        ret = -1;
1939
        goto fail;
1940
    }
1941 899681cd Björn Axelsson
    if(ic->pb)
1942
        ic->pb->eof_reached= 0; //FIXME hack, ffplay maybe should not use url_feof() to test for the end
1943 72ea344b Fabrice Bellard
1944
    /* if seeking requested, we execute it */
1945
    if (start_time != AV_NOPTS_VALUE) {
1946
        int64_t timestamp;
1947
1948
        timestamp = start_time;
1949
        /* add the stream start time */
1950
        if (ic->start_time != AV_NOPTS_VALUE)
1951
            timestamp += ic->start_time;
1952 4ed29207 Michael Niedermayer
        ret = avformat_seek_file(ic, -1, INT64_MIN, timestamp, INT64_MAX, 0);
1953 72ea344b Fabrice Bellard
        if (ret < 0) {
1954 115329f1 Diego Biurrun
            fprintf(stderr, "%s: could not seek to position %0.3f\n",
1955 72ea344b Fabrice Bellard
                    is->filename, (double)timestamp / AV_TIME_BASE);
1956
        }
1957
    }
1958
1959 01310af2 Fabrice Bellard
    for(i = 0; i < ic->nb_streams; i++) {
1960 01f4895c Michael Niedermayer
        AVCodecContext *enc = ic->streams[i]->codec;
1961 3f3fe38d Ronald S. Bultje
        ic->streams[i]->discard = AVDISCARD_ALL;
1962 01310af2 Fabrice Bellard
        switch(enc->codec_type) {
1963
        case CODEC_TYPE_AUDIO:
1964 5dbb63fe Stefano Sabatini
            if (wanted_audio_stream-- >= 0 && !audio_disable)
1965 01310af2 Fabrice Bellard
                audio_index = i;
1966
            break;
1967
        case CODEC_TYPE_VIDEO:
1968 5dbb63fe Stefano Sabatini
            if (wanted_video_stream-- >= 0 && !video_disable)
1969 01310af2 Fabrice Bellard
                video_index = i;
1970
            break;
1971 16a59a7b Björn Axelsson
        case CODEC_TYPE_SUBTITLE:
1972 5ad4f0d4 Stefano Sabatini
            if (wanted_subtitle_stream-- >= 0 && !video_disable)
1973 16a59a7b Björn Axelsson
                subtitle_index = i;
1974
            break;
1975 01310af2 Fabrice Bellard
        default:
1976
            break;
1977
        }
1978
    }
1979
    if (show_status) {
1980
        dump_format(ic, 0, is->filename, 0);
1981 d0526ecf Fabrice Bellard
        dump_stream_info(ic);
1982 01310af2 Fabrice Bellard
    }
1983
1984
    /* open the streams */
1985
    if (audio_index >= 0) {
1986
        stream_component_open(is, audio_index);
1987
    }
1988
1989
    if (video_index >= 0) {
1990
        stream_component_open(is, video_index);
1991
    } else {
1992
        if (!display_disable)
1993
            is->show_audio = 1;
1994
    }
1995
1996 16a59a7b Björn Axelsson
    if (subtitle_index >= 0) {
1997
        stream_component_open(is, subtitle_index);
1998
    }
1999
2000 01310af2 Fabrice Bellard
    if (is->video_stream < 0 && is->audio_stream < 0) {
2001 638c9d91 Fabrice Bellard
        fprintf(stderr, "%s: could not open codecs\n", is->filename);
2002
        ret = -1;
2003 01310af2 Fabrice Bellard
        goto fail;
2004
    }
2005
2006
    for(;;) {
2007
        if (is->abort_request)
2008
            break;
2009 416e3508 Fabrice Bellard
        if (is->paused != is->last_paused) {
2010
            is->last_paused = is->paused;
2011 72ea344b Fabrice Bellard
            if (is->paused)
2012
                av_read_pause(ic);
2013
            else
2014
                av_read_play(ic);
2015 416e3508 Fabrice Bellard
        }
2016 2f642393 Aurelien Jacobs
#if CONFIG_RTSP_DEMUXER
2017
        if (is->paused && !strcmp(ic->iformat->name, "rtsp")) {
2018 416e3508 Fabrice Bellard
            /* wait 10 ms to avoid trying to get another packet */
2019
            /* XXX: horrible */
2020
            SDL_Delay(10);
2021
            continue;
2022
        }
2023 400738b1 Michael Niedermayer
#endif
2024 72ea344b Fabrice Bellard
        if (is->seek_req) {
2025 8e606cc8 Michael Niedermayer
            int64_t seek_target= is->seek_pos;
2026 4ed29207 Michael Niedermayer
            int64_t seek_min= is->seek_rel > 0 ? seek_target - is->seek_rel + 2: INT64_MIN;
2027
            int64_t seek_max= is->seek_rel < 0 ? seek_target - is->seek_rel - 2: INT64_MAX;
2028
//FIXME the +-2 is due to rounding being not done in the correct direction in generation
2029
//      of the seek_pos/seek_rel variables
2030 8e606cc8 Michael Niedermayer
2031 4ed29207 Michael Niedermayer
            ret = avformat_seek_file(is->ic, -1, seek_min, seek_target, seek_max, is->seek_flags);
2032 72ea344b Fabrice Bellard
            if (ret < 0) {
2033
                fprintf(stderr, "%s: error while seeking\n", is->ic->filename);
2034 e6c0297f Michael Niedermayer
            }else{
2035
                if (is->audio_stream >= 0) {
2036
                    packet_queue_flush(&is->audioq);
2037 39c6a118 Michael Niedermayer
                    packet_queue_put(&is->audioq, &flush_pkt);
2038 e6c0297f Michael Niedermayer
                }
2039 72ce053b Ian Caulfield
                if (is->subtitle_stream >= 0) {
2040
                    packet_queue_flush(&is->subtitleq);
2041 39c6a118 Michael Niedermayer
                    packet_queue_put(&is->subtitleq, &flush_pkt);
2042 72ce053b Ian Caulfield
                }
2043 e6c0297f Michael Niedermayer
                if (is->video_stream >= 0) {
2044
                    packet_queue_flush(&is->videoq);
2045 39c6a118 Michael Niedermayer
                    packet_queue_put(&is->videoq, &flush_pkt);
2046 e6c0297f Michael Niedermayer
                }
2047 72ea344b Fabrice Bellard
            }
2048
            is->seek_req = 0;
2049 e45aeb38 Michael Niedermayer
            eof= 0;
2050 72ea344b Fabrice Bellard
        }
2051 416e3508 Fabrice Bellard
2052 01310af2 Fabrice Bellard
        /* if the queue are full, no need to read more */
2053
        if (is->audioq.size > MAX_AUDIOQ_SIZE ||
2054 115329f1 Diego Biurrun
            is->videoq.size > MAX_VIDEOQ_SIZE ||
2055 600a331c Michael Niedermayer
            is->subtitleq.size > MAX_SUBTITLEQ_SIZE) {
2056 01310af2 Fabrice Bellard
            /* wait 10 ms */
2057
            SDL_Delay(10);
2058
            continue;
2059
        }
2060 75bb7b0a Michael Niedermayer
        if(url_feof(ic->pb) || eof) {
2061 9dc41767 Michael Niedermayer
            if(is->video_stream >= 0){
2062 26534fe8 Michael Niedermayer
                av_init_packet(pkt);
2063
                pkt->data=NULL;
2064
                pkt->size=0;
2065
                pkt->stream_index= is->video_stream;
2066
                packet_queue_put(&is->videoq, pkt);
2067 9dc41767 Michael Niedermayer
            }
2068 b4083171 Michael Niedermayer
            SDL_Delay(10);
2069 600a331c Michael Niedermayer
            continue;
2070
        }
2071 72ea344b Fabrice Bellard
        ret = av_read_frame(ic, pkt);
2072 01310af2 Fabrice Bellard
        if (ret < 0) {
2073 75bb7b0a Michael Niedermayer
            if (ret == AVERROR_EOF)
2074
                eof=1;
2075
            if (url_ferror(ic->pb))
2076 bb270c08 Diego Biurrun
                break;
2077 75bb7b0a Michael Niedermayer
            SDL_Delay(100); /* wait for user event */
2078
            continue;
2079 01310af2 Fabrice Bellard
        }
2080
        if (pkt->stream_index == is->audio_stream) {
2081
            packet_queue_put(&is->audioq, pkt);
2082
        } else if (pkt->stream_index == is->video_stream) {
2083
            packet_queue_put(&is->videoq, pkt);
2084 72ce053b Ian Caulfield
        } else if (pkt->stream_index == is->subtitle_stream) {
2085
            packet_queue_put(&is->subtitleq, pkt);
2086 01310af2 Fabrice Bellard
        } else {
2087
            av_free_packet(pkt);
2088
        }
2089
    }
2090
    /* wait until the end */
2091
    while (!is->abort_request) {
2092
        SDL_Delay(100);
2093
    }
2094
2095 638c9d91 Fabrice Bellard
    ret = 0;
2096 01310af2 Fabrice Bellard
 fail:
2097 416e3508 Fabrice Bellard
    /* disable interrupting */
2098
    global_video_state = NULL;
2099
2100 01310af2 Fabrice Bellard
    /* close each stream */
2101
    if (is->audio_stream >= 0)
2102
        stream_component_close(is, is->audio_stream);
2103
    if (is->video_stream >= 0)
2104
        stream_component_close(is, is->video_stream);
2105 72ce053b Ian Caulfield
    if (is->subtitle_stream >= 0)
2106
        stream_component_close(is, is->subtitle_stream);
2107 638c9d91 Fabrice Bellard
    if (is->ic) {
2108
        av_close_input_file(is->ic);
2109
        is->ic = NULL; /* safety */
2110
    }
2111 416e3508 Fabrice Bellard
    url_set_interrupt_cb(NULL);
2112
2113 638c9d91 Fabrice Bellard
    if (ret != 0) {
2114
        SDL_Event event;
2115 115329f1 Diego Biurrun
2116 638c9d91 Fabrice Bellard
        event.type = FF_QUIT_EVENT;
2117
        event.user.data1 = is;
2118
        SDL_PushEvent(&event);
2119
    }
2120 01310af2 Fabrice Bellard
    return 0;
2121
}
2122
2123 638c9d91 Fabrice Bellard
static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
2124 01310af2 Fabrice Bellard
{
2125
    VideoState *is;
2126
2127
    is = av_mallocz(sizeof(VideoState));
2128
    if (!is)
2129
        return NULL;
2130 f7d78f36 Måns Rullgård
    av_strlcpy(is->filename, filename, sizeof(is->filename));
2131 638c9d91 Fabrice Bellard
    is->iformat = iformat;
2132 01310af2 Fabrice Bellard
    is->ytop = 0;
2133
    is->xleft = 0;
2134
2135
    /* start video display */
2136
    is->pictq_mutex = SDL_CreateMutex();
2137
    is->pictq_cond = SDL_CreateCond();
2138 115329f1 Diego Biurrun
2139 72ce053b Ian Caulfield
    is->subpq_mutex = SDL_CreateMutex();
2140
    is->subpq_cond = SDL_CreateCond();
2141 115329f1 Diego Biurrun
2142 01310af2 Fabrice Bellard
    /* add the refresh timer to draw the picture */
2143
    schedule_refresh(is, 40);
2144
2145 638c9d91 Fabrice Bellard
    is->av_sync_type = av_sync_type;
2146 01310af2 Fabrice Bellard
    is->parse_tid = SDL_CreateThread(decode_thread, is);
2147
    if (!is->parse_tid) {
2148
        av_free(is);
2149
        return NULL;
2150
    }
2151
    return is;
2152
}
2153
2154
static void stream_close(VideoState *is)
2155
{
2156
    VideoPicture *vp;
2157
    int i;
2158
    /* XXX: use a special url_shutdown call to abort parse cleanly */
2159
    is->abort_request = 1;
2160
    SDL_WaitThread(is->parse_tid, NULL);
2161
2162
    /* free all pictures */
2163
    for(i=0;i<VIDEO_PICTURE_QUEUE_SIZE; i++) {
2164
        vp = &is->pictq[i];
2165
        if (vp->bmp) {
2166
            SDL_FreeYUVOverlay(vp->bmp);
2167
            vp->bmp = NULL;
2168
        }
2169
    }
2170
    SDL_DestroyMutex(is->pictq_mutex);
2171
    SDL_DestroyCond(is->pictq_cond);
2172 72ce053b Ian Caulfield
    SDL_DestroyMutex(is->subpq_mutex);
2173
    SDL_DestroyCond(is->subpq_cond);
2174 3ac56e28 Martin Storsjö
    if (is->img_convert_ctx)
2175
        sws_freeContext(is->img_convert_ctx);
2176 7c5ab145 Martin Storsjö
    av_free(is);
2177 01310af2 Fabrice Bellard
}
2178
2179 7b49ce2e Stefan Huehner
static void stream_cycle_channel(VideoState *is, int codec_type)
2180 638c9d91 Fabrice Bellard
{
2181
    AVFormatContext *ic = is->ic;
2182
    int start_index, stream_index;
2183
    AVStream *st;
2184
2185
    if (codec_type == CODEC_TYPE_VIDEO)
2186
        start_index = is->video_stream;
2187 72ce053b Ian Caulfield
    else if (codec_type == CODEC_TYPE_AUDIO)
2188 638c9d91 Fabrice Bellard
        start_index = is->audio_stream;
2189 72ce053b Ian Caulfield
    else
2190
        start_index = is->subtitle_stream;
2191
    if (start_index < (codec_type == CODEC_TYPE_SUBTITLE ? -1 : 0))
2192 638c9d91 Fabrice Bellard
        return;
2193
    stream_index = start_index;
2194
    for(;;) {
2195
        if (++stream_index >= is->ic->nb_streams)
2196 72ce053b Ian Caulfield
        {
2197
            if (codec_type == CODEC_TYPE_SUBTITLE)
2198
            {
2199
                stream_index = -1;
2200
                goto the_end;
2201
            } else
2202
                stream_index = 0;
2203
        }
2204 638c9d91 Fabrice Bellard
        if (stream_index == start_index)
2205
            return;
2206
        st = ic->streams[stream_index];
2207 01f4895c Michael Niedermayer
        if (st->codec->codec_type == codec_type) {
2208 638c9d91 Fabrice Bellard
            /* check that parameters are OK */
2209
            switch(codec_type) {
2210
            case CODEC_TYPE_AUDIO:
2211 01f4895c Michael Niedermayer
                if (st->codec->sample_rate != 0 &&
2212
                    st->codec->channels != 0)
2213 638c9d91 Fabrice Bellard
                    goto the_end;
2214
                break;
2215
            case CODEC_TYPE_VIDEO:
2216 72ce053b Ian Caulfield
            case CODEC_TYPE_SUBTITLE:
2217 638c9d91 Fabrice Bellard
                goto the_end;
2218
            default:
2219
                break;
2220
            }
2221
        }
2222
    }
2223
 the_end:
2224
    stream_component_close(is, start_index);
2225
    stream_component_open(is, stream_index);
2226
}
2227
2228
2229 7b49ce2e Stefan Huehner
static void toggle_full_screen(void)
2230 01310af2 Fabrice Bellard
{
2231
    is_full_screen = !is_full_screen;
2232 29f3b38a Måns Rullgård
    if (!fs_screen_width) {
2233
        /* use default SDL method */
2234 fb84155b Michael Niedermayer
//        SDL_WM_ToggleFullScreen(screen);
2235 01310af2 Fabrice Bellard
    }
2236 fb84155b Michael Niedermayer
    video_open(cur_stream);
2237 01310af2 Fabrice Bellard
}
2238
2239 7b49ce2e Stefan Huehner
static void toggle_pause(void)
2240 01310af2 Fabrice Bellard
{
2241
    if (cur_stream)
2242
        stream_pause(cur_stream);
2243 bba04f1e Wolfgang Hesseler
    step = 0;
2244
}
2245
2246 7b49ce2e Stefan Huehner
static void step_to_next_frame(void)
2247 bba04f1e Wolfgang Hesseler
{
2248
    if (cur_stream) {
2249 19cc524a Craig Nicol
        /* if the stream is paused unpause it, then step */
2250 bba04f1e Wolfgang Hesseler
        if (cur_stream->paused)
2251 19cc524a Craig Nicol
            stream_pause(cur_stream);
2252 bba04f1e Wolfgang Hesseler
    }
2253
    step = 1;
2254 01310af2 Fabrice Bellard
}
2255
2256 7b49ce2e Stefan Huehner
static void do_exit(void)
2257 01310af2 Fabrice Bellard
{
2258 7c5ab145 Martin Storsjö
    int i;
2259 01310af2 Fabrice Bellard
    if (cur_stream) {
2260
        stream_close(cur_stream);
2261
        cur_stream = NULL;
2262
    }
2263 7c5ab145 Martin Storsjö
    for (i = 0; i < CODEC_TYPE_NB; i++)
2264
        av_free(avcodec_opts[i]);
2265
    av_free(avformat_opts);
2266
    av_free(sws_opts);
2267 01310af2 Fabrice Bellard
    if (show_status)
2268
        printf("\n");
2269
    SDL_Quit();
2270
    exit(0);
2271
}
2272
2273 7b49ce2e Stefan Huehner
static void toggle_audio_display(void)
2274 01310af2 Fabrice Bellard
{
2275
    if (cur_stream) {
2276
        cur_stream->show_audio = !cur_stream->show_audio;
2277
    }
2278
}
2279
2280
/* handle an event sent by the GUI */
2281 7b49ce2e Stefan Huehner
static void event_loop(void)
2282 01310af2 Fabrice Bellard
{
2283
    SDL_Event event;
2284 a11d11aa Michel Bardiaux
    double incr, pos, frac;
2285 01310af2 Fabrice Bellard
2286
    for(;;) {
2287
        SDL_WaitEvent(&event);
2288
        switch(event.type) {
2289
        case SDL_KEYDOWN:
2290
            switch(event.key.keysym.sym) {
2291
            case SDLK_ESCAPE:
2292
            case SDLK_q:
2293
                do_exit();
2294
                break;
2295
            case SDLK_f:
2296
                toggle_full_screen();
2297
                break;
2298
            case SDLK_p:
2299
            case SDLK_SPACE:
2300
                toggle_pause();
2301
                break;
2302 bba04f1e Wolfgang Hesseler
            case SDLK_s: //S: Step to next frame
2303
                step_to_next_frame();
2304
                break;
2305 01310af2 Fabrice Bellard
            case SDLK_a:
2306 115329f1 Diego Biurrun
                if (cur_stream)
2307 638c9d91 Fabrice Bellard
                    stream_cycle_channel(cur_stream, CODEC_TYPE_AUDIO);
2308
                break;
2309
            case SDLK_v:
2310 115329f1 Diego Biurrun
                if (cur_stream)
2311 638c9d91 Fabrice Bellard
                    stream_cycle_channel(cur_stream, CODEC_TYPE_VIDEO);
2312
                break;
2313 72ce053b Ian Caulfield
            case SDLK_t:
2314 115329f1 Diego Biurrun
                if (cur_stream)
2315 72ce053b Ian Caulfield
                    stream_cycle_channel(cur_stream, CODEC_TYPE_SUBTITLE);
2316
                break;
2317 638c9d91 Fabrice Bellard
            case SDLK_w:
2318 01310af2 Fabrice Bellard
                toggle_audio_display();
2319
                break;
2320 72ea344b Fabrice Bellard
            case SDLK_LEFT:
2321
                incr = -10.0;
2322
                goto do_seek;
2323
            case SDLK_RIGHT:
2324
                incr = 10.0;
2325
                goto do_seek;
2326
            case SDLK_UP:
2327
                incr = 60.0;
2328
                goto do_seek;
2329
            case SDLK_DOWN:
2330
                incr = -60.0;
2331
            do_seek:
2332
                if (cur_stream) {
2333 94b594c6 Steve L'Homme
                    if (seek_by_bytes) {
2334 899681cd Björn Axelsson
                        pos = url_ftell(cur_stream->ic->pb);
2335 94b594c6 Steve L'Homme
                        if (cur_stream->ic->bit_rate)
2336
                            incr *= cur_stream->ic->bit_rate / 60.0;
2337
                        else
2338
                            incr *= 180000.0;
2339
                        pos += incr;
2340
                        stream_seek(cur_stream, pos, incr);
2341
                    } else {
2342
                        pos = get_master_clock(cur_stream);
2343
                        pos += incr;
2344 4ed29207 Michael Niedermayer
                        stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), (int64_t)(incr * AV_TIME_BASE));
2345 94b594c6 Steve L'Homme
                    }
2346 72ea344b Fabrice Bellard
                }
2347
                break;
2348 01310af2 Fabrice Bellard
            default:
2349
                break;
2350
            }
2351
            break;
2352 a11d11aa Michel Bardiaux
        case SDL_MOUSEBUTTONDOWN:
2353 bb270c08 Diego Biurrun
            if (cur_stream) {
2354 c2b4c859 Baptiste Coudurier
                int64_t ts;
2355 bb270c08 Diego Biurrun
                int ns, hh, mm, ss;
2356
                int tns, thh, tmm, tss;
2357
                tns = cur_stream->ic->duration/1000000LL;
2358
                thh = tns/3600;
2359
                tmm = (tns%3600)/60;
2360
                tss = (tns%60);
2361
                frac = (double)event.button.x/(double)cur_stream->width;
2362
                ns = frac*tns;
2363
                hh = ns/3600;
2364
                mm = (ns%3600)/60;
2365
                ss = (ns%60);
2366
                fprintf(stderr, "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d)       \n", frac*100,
2367
                        hh, mm, ss, thh, tmm, tss);
2368 c2b4c859 Baptiste Coudurier
                ts = frac*cur_stream->ic->duration;
2369
                if (cur_stream->ic->start_time != AV_NOPTS_VALUE)
2370
                    ts += cur_stream->ic->start_time;
2371
                stream_seek(cur_stream, ts, 0);
2372 bb270c08 Diego Biurrun
            }
2373
            break;
2374 01310af2 Fabrice Bellard
        case SDL_VIDEORESIZE:
2375
            if (cur_stream) {
2376 115329f1 Diego Biurrun
                screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0,
2377 01310af2 Fabrice Bellard
                                          SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL);
2378 c57d3469 Michael Niedermayer
                screen_width = cur_stream->width = event.resize.w;
2379
                screen_height= cur_stream->height= event.resize.h;
2380 01310af2 Fabrice Bellard
            }
2381
            break;
2382
        case SDL_QUIT:
2383 638c9d91 Fabrice Bellard
        case FF_QUIT_EVENT:
2384 01310af2 Fabrice Bellard
            do_exit();
2385
            break;
2386
        case FF_ALLOC_EVENT:
2387 fccb19e3 Michael Niedermayer
            video_open(event.user.data1);
2388 01310af2 Fabrice Bellard
            alloc_picture(event.user.data1);
2389
            break;
2390
        case FF_REFRESH_EVENT:
2391
            video_refresh_timer(event.user.data1);
2392
            break;
2393
        default:
2394
            break;
2395
        }
2396
    }
2397
}
2398
2399 e4b89522 Limin Wang
static void opt_frame_size(const char *arg)
2400
{
2401 b33ece16 Stefano Sabatini
    if (av_parse_video_frame_size(&frame_width, &frame_height, arg) < 0) {
2402 e4b89522 Limin Wang
        fprintf(stderr, "Incorrect frame size\n");
2403
        exit(1);
2404
    }
2405
    if ((frame_width % 2) != 0 || (frame_height % 2) != 0) {
2406
        fprintf(stderr, "Frame size must be a multiple of 2\n");
2407
        exit(1);
2408
    }
2409
}
2410
2411 a5b3b5f6 Stefano Sabatini
static int opt_width(const char *opt, const char *arg)
2412 01310af2 Fabrice Bellard
{
2413 a5b3b5f6 Stefano Sabatini
    screen_width = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
2414
    return 0;
2415 01310af2 Fabrice Bellard
}
2416
2417 a5b3b5f6 Stefano Sabatini
static int opt_height(const char *opt, const char *arg)
2418 01310af2 Fabrice Bellard
{
2419 a5b3b5f6 Stefano Sabatini
    screen_height = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
2420
    return 0;
2421 01310af2 Fabrice Bellard
}
2422
2423
static void opt_format(const char *arg)
2424
{
2425
    file_iformat = av_find_input_format(arg);
2426
    if (!file_iformat) {
2427
        fprintf(stderr, "Unknown input format: %s\n", arg);
2428
        exit(1);
2429
    }
2430
}
2431 61890b02 Fabrice Bellard
2432 e4b89522 Limin Wang
static void opt_frame_pix_fmt(const char *arg)
2433
{
2434
    frame_pix_fmt = avcodec_get_pix_fmt(arg);
2435
}
2436
2437 b81d6235 Stefano Sabatini
static int opt_sync(const char *opt, const char *arg)
2438 638c9d91 Fabrice Bellard
{
2439
    if (!strcmp(arg, "audio"))
2440
        av_sync_type = AV_SYNC_AUDIO_MASTER;
2441
    else if (!strcmp(arg, "video"))
2442
        av_sync_type = AV_SYNC_VIDEO_MASTER;
2443
    else if (!strcmp(arg, "ext"))
2444
        av_sync_type = AV_SYNC_EXTERNAL_CLOCK;
2445 aab1b7e5 Stefano Sabatini
    else {
2446 b81d6235 Stefano Sabatini
        fprintf(stderr, "Unknown value for %s: %s\n", opt, arg);
2447 aab1b7e5 Stefano Sabatini
        exit(1);
2448
    }
2449 b81d6235 Stefano Sabatini
    return 0;
2450 638c9d91 Fabrice Bellard
}
2451
2452 e11bc2c6 Stefano Sabatini
static int opt_seek(const char *opt, const char *arg)
2453 72ea344b Fabrice Bellard
{
2454 e11bc2c6 Stefano Sabatini
    start_time = parse_time_or_die(opt, arg, 1);
2455
    return 0;
2456 72ea344b Fabrice Bellard
}
2457
2458 a5b3b5f6 Stefano Sabatini
static int opt_debug(const char *opt, const char *arg)
2459 e26a8335 Wolfgang Hesseler
{
2460 a309073b Måns Rullgård
    av_log_set_level(99);
2461 a5b3b5f6 Stefano Sabatini
    debug = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
2462
    return 0;
2463 e26a8335 Wolfgang Hesseler
}
2464 115329f1 Diego Biurrun
2465 a5b3b5f6 Stefano Sabatini
static int opt_vismv(const char *opt, const char *arg)
2466 0c9bbaec Wolfgang Hesseler
{
2467 a5b3b5f6 Stefano Sabatini
    debug_mv = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX);
2468
    return 0;
2469 0c9bbaec Wolfgang Hesseler
}
2470 c62c07d3 Michael Niedermayer
2471 a5b3b5f6 Stefano Sabatini
static int opt_thread_count(const char *opt, const char *arg)
2472 c62c07d3 Michael Niedermayer
{
2473 a5b3b5f6 Stefano Sabatini
    thread_count= parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
2474 b250f9c6 Aurelien Jacobs
#if !HAVE_THREADS
2475 c62c07d3 Michael Niedermayer
    fprintf(stderr, "Warning: not compiled with thread support, using thread emulation\n");
2476
#endif
2477 a5b3b5f6 Stefano Sabatini
    return 0;
2478 c62c07d3 Michael Niedermayer
}
2479 115329f1 Diego Biurrun
2480 358061f6 Diego Pettenò
static const OptionDef options[] = {
2481 20176cbc Michael Niedermayer
    { "h", OPT_EXIT, {(void*)show_help}, "show help" },
2482
    { "version", OPT_EXIT, {(void*)show_version}, "show version" },
2483 8fdea204 Stefano Sabatini
    { "L", OPT_EXIT, {(void*)show_license}, "show license" },
2484 a28b7ed4 Stefano Sabatini
    { "formats", OPT_EXIT, {(void*)show_formats}, "show available formats, codecs, protocols, ..." },
2485 a5b3b5f6 Stefano Sabatini
    { "x", HAS_ARG | OPT_FUNC2, {(void*)opt_width}, "force displayed width", "width" },
2486
    { "y", HAS_ARG | OPT_FUNC2, {(void*)opt_height}, "force displayed height", "height" },
2487 e4b89522 Limin Wang
    { "s", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_size}, "set frame size (WxH or abbreviation)", "size" },
2488 638c9d91 Fabrice Bellard
    { "fs", OPT_BOOL, {(void*)&is_full_screen}, "force full screen" },
2489 01310af2 Fabrice Bellard
    { "an", OPT_BOOL, {(void*)&audio_disable}, "disable audio" },
2490
    { "vn", OPT_BOOL, {(void*)&video_disable}, "disable video" },
2491 4b037567 Stefano Sabatini
    { "ast", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_audio_stream}, "select desired audio stream", "stream_number" },
2492
    { "vst", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_video_stream}, "select desired video stream", "stream_number" },
2493
    { "sst", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_subtitle_stream}, "select desired subtitle stream", "stream_number" },
2494 e11bc2c6 Stefano Sabatini
    { "ss", HAS_ARG | OPT_FUNC2, {(void*)&opt_seek}, "seek to a given position in seconds", "pos" },
2495 94b594c6 Steve L'Homme
    { "bytes", OPT_BOOL, {(void*)&seek_by_bytes}, "seek by bytes" },
2496 01310af2 Fabrice Bellard
    { "nodisp", OPT_BOOL, {(void*)&display_disable}, "disable graphical display" },
2497
    { "f", HAS_ARG, {(void*)opt_format}, "force format", "fmt" },
2498 e4b89522 Limin Wang
    { "pix_fmt", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_frame_pix_fmt}, "set pixel format", "format" },
2499 01310af2 Fabrice Bellard
    { "stats", OPT_BOOL | OPT_EXPERT, {(void*)&show_status}, "show status", "" },
2500 a5b3b5f6 Stefano Sabatini
    { "debug", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_debug}, "print specific debug info", "" },
2501 6387c3e6 Michael Niedermayer
    { "bug", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&workaround_bugs}, "workaround bugs", "" },
2502 a5b3b5f6 Stefano Sabatini
    { "vismv", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_vismv}, "visualize motion vectors", "" },
2503 6fc5b059 Michael Niedermayer
    { "fast", OPT_BOOL | OPT_EXPERT, {(void*)&fast}, "non spec compliant optimizations", "" },
2504 30bc6613 Michael Niedermayer
    { "genpts", OPT_BOOL | OPT_EXPERT, {(void*)&genpts}, "generate pts", "" },
2505 5039185a Michael Niedermayer
    { "drp", OPT_BOOL |OPT_EXPERT, {(void*)&decoder_reorder_pts}, "let decoder reorder pts", ""},
2506 178fcca8 Michael Niedermayer
    { "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&lowres}, "", "" },
2507 8c3eba7c Michael Niedermayer
    { "skiploop", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_loop_filter}, "", "" },
2508
    { "skipframe", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_frame}, "", "" },
2509
    { "skipidct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_idct}, "", "" },
2510 178fcca8 Michael Niedermayer
    { "idct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&idct}, "set idct algo",  "algo" },
2511 047599a4 Michael Niedermayer
    { "er", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_recognition}, "set error detection threshold (0-4)",  "threshold" },
2512 1b51e051 Michael Niedermayer
    { "ec", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_concealment}, "set error concealment options",  "bit_mask" },
2513 b81d6235 Stefano Sabatini
    { "sync", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_sync}, "set audio-video sync. type (type=audio/video/ext)", "type" },
2514 a5b3b5f6 Stefano Sabatini
    { "threads", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" },
2515 e43d7a18 Michael Niedermayer
    { "default", OPT_FUNC2 | HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, {(void*)opt_default}, "generic catch all option", "" },
2516 01310af2 Fabrice Bellard
    { NULL, },
2517
};
2518
2519 358061f6 Diego Pettenò
static void show_help(void)
2520 01310af2 Fabrice Bellard
{
2521 9c5755ee Stefano Sabatini
    printf("usage: ffplay [options] input_file\n"
2522 01310af2 Fabrice Bellard
           "Simple media player\n");
2523
    printf("\n");
2524 02d504a7 Fabrice Bellard
    show_help_options(options, "Main options:\n",
2525
                      OPT_EXPERT, 0);
2526
    show_help_options(options, "\nAdvanced options:\n",
2527
                      OPT_EXPERT, OPT_EXPERT);
2528 01310af2 Fabrice Bellard
    printf("\nWhile playing:\n"
2529
           "q, ESC              quit\n"
2530
           "f                   toggle full screen\n"
2531
           "p, SPC              pause\n"
2532 638c9d91 Fabrice Bellard
           "a                   cycle audio channel\n"
2533
           "v                   cycle video channel\n"
2534 72ce053b Ian Caulfield
           "t                   cycle subtitle channel\n"
2535 638c9d91 Fabrice Bellard
           "w                   show audio waves\n"
2536 72ea344b Fabrice Bellard
           "left/right          seek backward/forward 10 seconds\n"
2537
           "down/up             seek backward/forward 1 minute\n"
2538 a11d11aa Michel Bardiaux
           "mouse click         seek to percentage in file corresponding to fraction of width\n"
2539 01310af2 Fabrice Bellard
           );
2540
}
2541
2542 358061f6 Diego Pettenò
static void opt_input_file(const char *filename)
2543 01310af2 Fabrice Bellard
{
2544 e8d83e1c Michael Niedermayer
    if (!strcmp(filename, "-"))
2545 9fcfc0b7 Diego Biurrun
        filename = "pipe:";
2546 01310af2 Fabrice Bellard
    input_filename = filename;
2547
}
2548
2549
/* Called from the main */
2550
int main(int argc, char **argv)
2551
{
2552 e43d7a18 Michael Niedermayer
    int flags, i;
2553 115329f1 Diego Biurrun
2554 01310af2 Fabrice Bellard
    /* register all codecs, demux and protocols */
2555 c721d803 Luca Abeni
    avcodec_register_all();
2556
    avdevice_register_all();
2557 01310af2 Fabrice Bellard
    av_register_all();
2558
2559 e43d7a18 Michael Niedermayer
    for(i=0; i<CODEC_TYPE_NB; i++){
2560 636f1c4c Stefano Sabatini
        avcodec_opts[i]= avcodec_alloc_context2(i);
2561 e43d7a18 Michael Niedermayer
    }
2562 8e2fd8e1 Stefano Sabatini
    avformat_opts = avformat_alloc_context();
2563 e43d7a18 Michael Niedermayer
    sws_opts = sws_getContext(16,16,0, 16,16,0, sws_flags, NULL,NULL,NULL);
2564
2565 ea9c581f Stefano Sabatini
    show_banner();
2566 4cfac5bc Stefano Sabatini
2567 f5da5c93 Stefano Sabatini
    parse_options(argc, argv, options, opt_input_file);
2568 01310af2 Fabrice Bellard
2569 aab1b7e5 Stefano Sabatini
    if (!input_filename) {
2570 7a7da6b4 Stefano Sabatini
        fprintf(stderr, "An input file must be specified\n");
2571 aab1b7e5 Stefano Sabatini
        exit(1);
2572
    }
2573 01310af2 Fabrice Bellard
2574
    if (display_disable) {
2575
        video_disable = 1;
2576
    }
2577 31319a8c Fabrice Bellard
    flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
2578 c97f5402 Diego Biurrun
#if !defined(__MINGW32__) && !defined(__APPLE__)
2579
    flags |= SDL_INIT_EVENTTHREAD; /* Not supported on Windows or Mac OS X */
2580 31319a8c Fabrice Bellard
#endif
2581 01310af2 Fabrice Bellard
    if (SDL_Init (flags)) {
2582 05ab0b76 Glenn Maynard
        fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
2583 01310af2 Fabrice Bellard
        exit(1);
2584
    }
2585
2586
    if (!display_disable) {
2587 b250f9c6 Aurelien Jacobs
#if HAVE_SDL_VIDEO_SIZE
2588 3ef17d62 Måns Rullgård
        const SDL_VideoInfo *vi = SDL_GetVideoInfo();
2589
        fs_screen_width = vi->current_w;
2590
        fs_screen_height = vi->current_h;
2591 29f3b38a Måns Rullgård
#endif
2592 01310af2 Fabrice Bellard
    }
2593
2594
    SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
2595
    SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
2596
    SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
2597
    SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
2598
2599 39c6a118 Michael Niedermayer
    av_init_packet(&flush_pkt);
2600
    flush_pkt.data= "FLUSH";
2601
2602 638c9d91 Fabrice Bellard
    cur_stream = stream_open(input_filename, file_iformat);
2603 01310af2 Fabrice Bellard
2604
    event_loop();
2605
2606
    /* never returns */
2607
2608
    return 0;
2609
}