Statistics
| Branch: | Revision:

ffmpeg / ffplay.c @ 61dbf4e5

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

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