Statistics
| Branch: | Revision:

ffmpeg / ffplay.c @ d7fb5a18

History | View | Annotate | Download (79.1 KB)

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

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