Statistics
| Branch: | Revision:

ffmpeg / ffplay.c @ cfc97077

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

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