Statistics
| Branch: | Revision:

ffmpeg / ffplay.c @ 9bbf1a5c

History | View | Annotate | Download (79.8 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 16a59a7b Björn Axelsson
static int wanted_subtitle_stream= -1;
195 94b594c6 Steve L'Homme
static int seek_by_bytes;
196 01310af2 Fabrice Bellard
static int display_disable;
197
static int show_status;
198 638c9d91 Fabrice Bellard
static int av_sync_type = AV_SYNC_AUDIO_MASTER;
199 72ea344b Fabrice Bellard
static int64_t start_time = AV_NOPTS_VALUE;
200 e26a8335 Wolfgang Hesseler
static int debug = 0;
201 0c9bbaec Wolfgang Hesseler
static int debug_mv = 0;
202 bba04f1e Wolfgang Hesseler
static int step = 0;
203 c62c07d3 Michael Niedermayer
static int thread_count = 1;
204 6387c3e6 Michael Niedermayer
static int workaround_bugs = 1;
205 6fc5b059 Michael Niedermayer
static int fast = 0;
206 30bc6613 Michael Niedermayer
static int genpts = 0;
207 178fcca8 Michael Niedermayer
static int lowres = 0;
208
static int idct = FF_IDCT_AUTO;
209 8c3eba7c Michael Niedermayer
static enum AVDiscard skip_frame= AVDISCARD_DEFAULT;
210
static enum AVDiscard skip_idct= AVDISCARD_DEFAULT;
211
static enum AVDiscard skip_loop_filter= AVDISCARD_DEFAULT;
212 047599a4 Michael Niedermayer
static int error_recognition = FF_ER_CAREFUL;
213 1b51e051 Michael Niedermayer
static int error_concealment = 3;
214 5039185a Michael Niedermayer
static int decoder_reorder_pts= 0;
215 01310af2 Fabrice Bellard
216
/* current context */
217
static int is_full_screen;
218
static VideoState *cur_stream;
219 5e0257e3 Fabrice Bellard
static int64_t audio_callback_time;
220 01310af2 Fabrice Bellard
221 2c676c33 Diego Pettenò
static AVPacket flush_pkt;
222 39c6a118 Michael Niedermayer
223 01310af2 Fabrice Bellard
#define FF_ALLOC_EVENT   (SDL_USEREVENT)
224
#define FF_REFRESH_EVENT (SDL_USEREVENT + 1)
225 638c9d91 Fabrice Bellard
#define FF_QUIT_EVENT    (SDL_USEREVENT + 2)
226 01310af2 Fabrice Bellard
227 2c676c33 Diego Pettenò
static SDL_Surface *screen;
228 01310af2 Fabrice Bellard
229
/* packet queue handling */
230
static void packet_queue_init(PacketQueue *q)
231
{
232
    memset(q, 0, sizeof(PacketQueue));
233
    q->mutex = SDL_CreateMutex();
234
    q->cond = SDL_CreateCond();
235
}
236
237 72ea344b Fabrice Bellard
static void packet_queue_flush(PacketQueue *q)
238 01310af2 Fabrice Bellard
{
239
    AVPacketList *pkt, *pkt1;
240
241 687fae2b Ivan Wong
    SDL_LockMutex(q->mutex);
242 01310af2 Fabrice Bellard
    for(pkt = q->first_pkt; pkt != NULL; pkt = pkt1) {
243
        pkt1 = pkt->next;
244
        av_free_packet(&pkt->pkt);
245 da6c4573 Michael Niedermayer
        av_freep(&pkt);
246 01310af2 Fabrice Bellard
    }
247 72ea344b Fabrice Bellard
    q->last_pkt = NULL;
248
    q->first_pkt = NULL;
249
    q->nb_packets = 0;
250
    q->size = 0;
251 687fae2b Ivan Wong
    SDL_UnlockMutex(q->mutex);
252 72ea344b Fabrice Bellard
}
253
254
static void packet_queue_end(PacketQueue *q)
255
{
256
    packet_queue_flush(q);
257 01310af2 Fabrice Bellard
    SDL_DestroyMutex(q->mutex);
258
    SDL_DestroyCond(q->cond);
259
}
260
261
static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
262
{
263
    AVPacketList *pkt1;
264
265 72ea344b Fabrice Bellard
    /* duplicate the packet */
266 39c6a118 Michael Niedermayer
    if (pkt!=&flush_pkt && av_dup_packet(pkt) < 0)
267 72ea344b Fabrice Bellard
        return -1;
268 115329f1 Diego Biurrun
269 01310af2 Fabrice Bellard
    pkt1 = av_malloc(sizeof(AVPacketList));
270
    if (!pkt1)
271
        return -1;
272
    pkt1->pkt = *pkt;
273
    pkt1->next = NULL;
274
275 72ea344b Fabrice Bellard
276 01310af2 Fabrice Bellard
    SDL_LockMutex(q->mutex);
277
278
    if (!q->last_pkt)
279
280
        q->first_pkt = pkt1;
281
    else
282
        q->last_pkt->next = pkt1;
283
    q->last_pkt = pkt1;
284
    q->nb_packets++;
285
    q->size += pkt1->pkt.size;
286
    /* XXX: should duplicate packet data in DV case */
287
    SDL_CondSignal(q->cond);
288
289
    SDL_UnlockMutex(q->mutex);
290
    return 0;
291
}
292
293
static void packet_queue_abort(PacketQueue *q)
294
{
295
    SDL_LockMutex(q->mutex);
296
297
    q->abort_request = 1;
298 115329f1 Diego Biurrun
299 01310af2 Fabrice Bellard
    SDL_CondSignal(q->cond);
300
301
    SDL_UnlockMutex(q->mutex);
302
}
303
304
/* return < 0 if aborted, 0 if no packet and > 0 if packet.  */
305
static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
306
{
307
    AVPacketList *pkt1;
308
    int ret;
309
310
    SDL_LockMutex(q->mutex);
311
312
    for(;;) {
313
        if (q->abort_request) {
314
            ret = -1;
315
            break;
316
        }
317 115329f1 Diego Biurrun
318 01310af2 Fabrice Bellard
        pkt1 = q->first_pkt;
319
        if (pkt1) {
320
            q->first_pkt = pkt1->next;
321
            if (!q->first_pkt)
322
                q->last_pkt = NULL;
323
            q->nb_packets--;
324
            q->size -= pkt1->pkt.size;
325
            *pkt = pkt1->pkt;
326
            av_free(pkt1);
327
            ret = 1;
328
            break;
329
        } else if (!block) {
330
            ret = 0;
331
            break;
332
        } else {
333
            SDL_CondWait(q->cond, q->mutex);
334
        }
335
    }
336
    SDL_UnlockMutex(q->mutex);
337
    return ret;
338
}
339
340 115329f1 Diego Biurrun
static inline void fill_rectangle(SDL_Surface *screen,
341 01310af2 Fabrice Bellard
                                  int x, int y, int w, int h, int color)
342
{
343
    SDL_Rect rect;
344
    rect.x = x;
345
    rect.y = y;
346
    rect.w = w;
347
    rect.h = h;
348
    SDL_FillRect(screen, &rect, color);
349
}
350
351
#if 0
352
/* draw only the border of a rectangle */
353
void fill_border(VideoState *s, int x, int y, int w, int h, int color)
354
{
355
    int w1, w2, h1, h2;
356

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