Statistics
| Branch: | Revision:

ffmpeg / ffplay.c @ 20b02bc6

History | View | Annotate | Download (56.1 KB)

1 01310af2 Fabrice Bellard
/*
2
 * FFplay : Simple Media Player based on the ffmpeg libraries
3
 * Copyright (c) 2003 Fabrice Bellard
4
 *
5
 * This library is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU Lesser General Public
7
 * License as published by the Free Software Foundation; either
8
 * version 2 of the License, or (at your option) any later version.
9
 *
10
 * This library is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 * Lesser General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Lesser General Public
16
 * License along with this library; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 */
19
#define HAVE_AV_CONFIG_H
20
#include "avformat.h"
21
22
#include "cmdutils.h"
23
24
#include <SDL.h>
25
#include <SDL_thread.h>
26
27 31319a8c Fabrice Bellard
#ifdef CONFIG_WIN32
28
#undef main /* We don't want SDL to override our main() */
29
#endif
30
31 01310af2 Fabrice Bellard
#if defined(__linux__)
32
#define HAVE_X11
33
#endif
34
35
#ifdef HAVE_X11
36
#include <X11/Xlib.h>
37
#endif
38
39 638c9d91 Fabrice Bellard
//#define DEBUG_SYNC
40
41 01310af2 Fabrice Bellard
#define MAX_VIDEOQ_SIZE (5 * 256 * 1024)
42
#define MAX_AUDIOQ_SIZE (5 * 16 * 1024)
43
44 638c9d91 Fabrice Bellard
/* SDL audio buffer size, in samples. Should be small to have precise
45
   A/V sync as SDL does not have hardware buffer fullness info. */
46
#define SDL_AUDIO_BUFFER_SIZE 1024
47
48
/* no AV sync correction is done if below the AV sync threshold */
49 7e0140cb Michael Niedermayer
#define AV_SYNC_THRESHOLD 0.01
50 638c9d91 Fabrice Bellard
/* no AV correction is done if too big error */
51
#define AV_NOSYNC_THRESHOLD 10.0
52
53
/* maximum audio speed change to get correct sync */
54
#define SAMPLE_CORRECTION_PERCENT_MAX 10
55
56
/* we use about AUDIO_DIFF_AVG_NB A-V differences to make the average */
57
#define AUDIO_DIFF_AVG_NB   20
58
59 01310af2 Fabrice Bellard
/* NOTE: the size must be big enough to compensate the hardware audio buffersize size */
60
#define SAMPLE_ARRAY_SIZE (2*65536)
61
62
typedef struct PacketQueue {
63
    AVPacketList *first_pkt, *last_pkt;
64
    int nb_packets;
65
    int size;
66
    int abort_request;
67
    SDL_mutex *mutex;
68
    SDL_cond *cond;
69
} PacketQueue;
70
71
#define VIDEO_PICTURE_QUEUE_SIZE 1
72
73
typedef struct VideoPicture {
74 638c9d91 Fabrice Bellard
    double pts; /* presentation time stamp for this picture */
75 01310af2 Fabrice Bellard
    SDL_Overlay *bmp;
76
    int width, height; /* source height & width */
77
    int allocated;
78
} VideoPicture;
79
80
enum {
81
    AV_SYNC_AUDIO_MASTER, /* default choice */
82
    AV_SYNC_VIDEO_MASTER,
83 638c9d91 Fabrice Bellard
    AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */
84 01310af2 Fabrice Bellard
};
85
86
typedef struct VideoState {
87
    SDL_Thread *parse_tid;
88
    SDL_Thread *video_tid;
89 638c9d91 Fabrice Bellard
    AVInputFormat *iformat;
90 01310af2 Fabrice Bellard
    int no_background;
91
    int abort_request;
92
    int paused;
93 416e3508 Fabrice Bellard
    int last_paused;
94 72ea344b Fabrice Bellard
    int seek_req;
95 3ba1438d Michael Niedermayer
    int seek_flags;
96 72ea344b Fabrice Bellard
    int64_t seek_pos;
97 01310af2 Fabrice Bellard
    AVFormatContext *ic;
98
    int dtg_active_format;
99
100
    int audio_stream;
101
    
102
    int av_sync_type;
103 638c9d91 Fabrice Bellard
    double external_clock; /* external clock base */
104
    int64_t external_clock_time;
105
    
106
    double audio_clock;
107
    double audio_diff_cum; /* used for AV difference average computation */
108
    double audio_diff_avg_coef;
109
    double audio_diff_threshold;
110
    int audio_diff_avg_count;
111 01310af2 Fabrice Bellard
    AVStream *audio_st;
112
    PacketQueue audioq;
113
    int audio_hw_buf_size;
114
    /* samples output by the codec. we reserve more space for avsync
115
       compensation */
116
    uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2]; 
117 7fea94ce Zdenek Kabelac
    unsigned int audio_buf_size; /* in bytes */
118 01310af2 Fabrice Bellard
    int audio_buf_index; /* in bytes */
119
    AVPacket audio_pkt;
120
    uint8_t *audio_pkt_data;
121
    int audio_pkt_size;
122
    
123
    int show_audio; /* if true, display audio samples */
124
    int16_t sample_array[SAMPLE_ARRAY_SIZE];
125
    int sample_array_index;
126 5e0257e3 Fabrice Bellard
    int last_i_start;
127 01310af2 Fabrice Bellard
    
128 638c9d91 Fabrice Bellard
    double frame_timer;
129
    double frame_last_pts;
130
    double frame_last_delay;
131
    double video_clock;
132 01310af2 Fabrice Bellard
    int video_stream;
133
    AVStream *video_st;
134
    PacketQueue videoq;
135 638c9d91 Fabrice Bellard
    double video_last_P_pts; /* pts of the last P picture (needed if B
136
                                frames are present) */
137
    double video_current_pts; /* current displayed pts (different from
138
                                 video_clock if frame fifos are used) */
139
    int64_t video_current_pts_time; /* time at which we updated
140
                                       video_current_pts - used to
141
                                       have running video pts */
142 01310af2 Fabrice Bellard
    VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
143
    int pictq_size, pictq_rindex, pictq_windex;
144
    SDL_mutex *pictq_mutex;
145
    SDL_cond *pictq_cond;
146
    
147
    //    QETimer *video_timer;
148
    char filename[1024];
149
    int width, height, xleft, ytop;
150
} VideoState;
151
152
void show_help(void);
153 638c9d91 Fabrice Bellard
static int audio_write_get_buf_size(VideoState *is);
154 01310af2 Fabrice Bellard
155
/* options specified by the user */
156
static AVInputFormat *file_iformat;
157 61890b02 Fabrice Bellard
static AVImageFormat *image_format;
158 01310af2 Fabrice Bellard
static const char *input_filename;
159
static int fs_screen_width;
160
static int fs_screen_height;
161
static int screen_width = 640;
162
static int screen_height = 480;
163
static int audio_disable;
164
static int video_disable;
165
static int display_disable;
166
static int show_status;
167 638c9d91 Fabrice Bellard
static int av_sync_type = AV_SYNC_AUDIO_MASTER;
168 72ea344b Fabrice Bellard
static int64_t start_time = AV_NOPTS_VALUE;
169 e26a8335 Wolfgang Hesseler
static int debug = 0;
170 0c9bbaec Wolfgang Hesseler
static int debug_mv = 0;
171 bba04f1e Wolfgang Hesseler
static int step = 0;
172 c62c07d3 Michael Niedermayer
static int thread_count = 1;
173 6387c3e6 Michael Niedermayer
static int workaround_bugs = 1;
174 6fc5b059 Michael Niedermayer
static int fast = 0;
175 178fcca8 Michael Niedermayer
static int lowres = 0;
176
static int idct = FF_IDCT_AUTO;
177 01310af2 Fabrice Bellard
178
/* current context */
179
static int is_full_screen;
180
static VideoState *cur_stream;
181 5e0257e3 Fabrice Bellard
static int64_t audio_callback_time;
182 01310af2 Fabrice Bellard
183
#define FF_ALLOC_EVENT   (SDL_USEREVENT)
184
#define FF_REFRESH_EVENT (SDL_USEREVENT + 1)
185 638c9d91 Fabrice Bellard
#define FF_QUIT_EVENT    (SDL_USEREVENT + 2)
186 01310af2 Fabrice Bellard
187
SDL_Surface *screen;
188
189
/* packet queue handling */
190
static void packet_queue_init(PacketQueue *q)
191
{
192
    memset(q, 0, sizeof(PacketQueue));
193
    q->mutex = SDL_CreateMutex();
194
    q->cond = SDL_CreateCond();
195
}
196
197 72ea344b Fabrice Bellard
static void packet_queue_flush(PacketQueue *q)
198 01310af2 Fabrice Bellard
{
199
    AVPacketList *pkt, *pkt1;
200
201
    for(pkt = q->first_pkt; pkt != NULL; pkt = pkt1) {
202
        pkt1 = pkt->next;
203
        av_free_packet(&pkt->pkt);
204 da6c4573 Michael Niedermayer
        av_freep(&pkt);
205 01310af2 Fabrice Bellard
    }
206 72ea344b Fabrice Bellard
    q->last_pkt = NULL;
207
    q->first_pkt = NULL;
208
    q->nb_packets = 0;
209
    q->size = 0;
210
}
211
212
static void packet_queue_end(PacketQueue *q)
213
{
214
    packet_queue_flush(q);
215 01310af2 Fabrice Bellard
    SDL_DestroyMutex(q->mutex);
216
    SDL_DestroyCond(q->cond);
217
}
218
219
static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
220
{
221
    AVPacketList *pkt1;
222
223 72ea344b Fabrice Bellard
    /* duplicate the packet */
224
    if (av_dup_packet(pkt) < 0)
225
        return -1;
226
    
227 01310af2 Fabrice Bellard
    pkt1 = av_malloc(sizeof(AVPacketList));
228
    if (!pkt1)
229
        return -1;
230
    pkt1->pkt = *pkt;
231
    pkt1->next = NULL;
232
233 72ea344b Fabrice Bellard
234 01310af2 Fabrice Bellard
    SDL_LockMutex(q->mutex);
235
236
    if (!q->last_pkt)
237
238
        q->first_pkt = pkt1;
239
    else
240
        q->last_pkt->next = pkt1;
241
    q->last_pkt = pkt1;
242
    q->nb_packets++;
243
    q->size += pkt1->pkt.size;
244
    /* XXX: should duplicate packet data in DV case */
245
    SDL_CondSignal(q->cond);
246
247
    SDL_UnlockMutex(q->mutex);
248
    return 0;
249
}
250
251
static void packet_queue_abort(PacketQueue *q)
252
{
253
    SDL_LockMutex(q->mutex);
254
255
    q->abort_request = 1;
256
    
257
    SDL_CondSignal(q->cond);
258
259
    SDL_UnlockMutex(q->mutex);
260
}
261
262
/* return < 0 if aborted, 0 if no packet and > 0 if packet.  */
263
static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
264
{
265
    AVPacketList *pkt1;
266
    int ret;
267
268
    SDL_LockMutex(q->mutex);
269
270
    for(;;) {
271
        if (q->abort_request) {
272
            ret = -1;
273
            break;
274
        }
275
            
276
        pkt1 = q->first_pkt;
277
        if (pkt1) {
278
            q->first_pkt = pkt1->next;
279
            if (!q->first_pkt)
280
                q->last_pkt = NULL;
281
            q->nb_packets--;
282
            q->size -= pkt1->pkt.size;
283
            *pkt = pkt1->pkt;
284
            av_free(pkt1);
285
            ret = 1;
286
            break;
287
        } else if (!block) {
288
            ret = 0;
289
            break;
290
        } else {
291
            SDL_CondWait(q->cond, q->mutex);
292
        }
293
    }
294
    SDL_UnlockMutex(q->mutex);
295
    return ret;
296
}
297
298
static inline void fill_rectangle(SDL_Surface *screen, 
299
                                  int x, int y, int w, int h, int color)
300
{
301
    SDL_Rect rect;
302
    rect.x = x;
303
    rect.y = y;
304
    rect.w = w;
305
    rect.h = h;
306
    SDL_FillRect(screen, &rect, color);
307
}
308
309
#if 0
310
/* draw only the border of a rectangle */
311
void fill_border(VideoState *s, int x, int y, int w, int h, int color)
312
{
313
    int w1, w2, h1, h2;
314

315
    /* fill the background */
316
    w1 = x;
317
    if (w1 < 0)
318
        w1 = 0;
319
    w2 = s->width - (x + w);
320
    if (w2 < 0)
321
        w2 = 0;
322
    h1 = y;
323
    if (h1 < 0)
324
        h1 = 0;
325
    h2 = s->height - (y + h);
326
    if (h2 < 0)
327
        h2 = 0;
328
    fill_rectangle(screen, 
329
                   s->xleft, s->ytop, 
330
                   w1, s->height, 
331
                   color);
332
    fill_rectangle(screen, 
333
                   s->xleft + s->width - w2, s->ytop, 
334
                   w2, s->height, 
335
                   color);
336
    fill_rectangle(screen, 
337
                   s->xleft + w1, s->ytop, 
338
                   s->width - w1 - w2, h1, 
339
                   color);
340
    fill_rectangle(screen, 
341
                   s->xleft + w1, s->ytop + s->height - h2,
342
                   s->width - w1 - w2, h2,
343
                   color);
344
}
345
#endif
346
347
static void video_image_display(VideoState *is)
348
{
349
    VideoPicture *vp;
350
    float aspect_ratio;
351
    int width, height, x, y;
352
    SDL_Rect rect;
353
354
    vp = &is->pictq[is->pictq_rindex];
355
    if (vp->bmp) {
356
        /* XXX: use variable in the frame */
357 72ea344b Fabrice Bellard
        if (is->video_st->codec.sample_aspect_ratio.num == 0) 
358
            aspect_ratio = 0;
359
        else
360
            aspect_ratio = av_q2d(is->video_st->codec.sample_aspect_ratio) 
361
                * is->video_st->codec.width / is->video_st->codec.height;;
362 01310af2 Fabrice Bellard
        if (aspect_ratio <= 0.0)
363
            aspect_ratio = (float)is->video_st->codec.width / 
364
                (float)is->video_st->codec.height;
365
        /* if an active format is indicated, then it overrides the
366
           mpeg format */
367
#if 0
368
        if (is->video_st->codec.dtg_active_format != is->dtg_active_format) {
369
            is->dtg_active_format = is->video_st->codec.dtg_active_format;
370
            printf("dtg_active_format=%d\n", is->dtg_active_format);
371
        }
372
#endif
373
#if 0
374
        switch(is->video_st->codec.dtg_active_format) {
375
        case FF_DTG_AFD_SAME:
376
        default:
377
            /* nothing to do */
378
            break;
379
        case FF_DTG_AFD_4_3:
380
            aspect_ratio = 4.0 / 3.0;
381
            break;
382
        case FF_DTG_AFD_16_9:
383
            aspect_ratio = 16.0 / 9.0;
384
            break;
385
        case FF_DTG_AFD_14_9:
386
            aspect_ratio = 14.0 / 9.0;
387
            break;
388
        case FF_DTG_AFD_4_3_SP_14_9:
389
            aspect_ratio = 14.0 / 9.0;
390
            break;
391
        case FF_DTG_AFD_16_9_SP_14_9:
392
            aspect_ratio = 14.0 / 9.0;
393
            break;
394
        case FF_DTG_AFD_SP_4_3:
395
            aspect_ratio = 4.0 / 3.0;
396
            break;
397
        }
398
#endif
399
400
        /* XXX: we suppose the screen has a 1.0 pixel ratio */
401
        height = is->height;
402
        width = ((int)rint(height * aspect_ratio)) & -3;
403
        if (width > is->width) {
404
            width = is->width;
405
            height = ((int)rint(width / aspect_ratio)) & -3;
406
        }
407
        x = (is->width - width) / 2;
408
        y = (is->height - height) / 2;
409
        if (!is->no_background) {
410
            /* fill the background */
411
            //            fill_border(is, x, y, width, height, QERGB(0x00, 0x00, 0x00));
412
        } else {
413
            is->no_background = 0;
414
        }
415
        rect.x = is->xleft + x;
416
        rect.y = is->xleft + y;
417
        rect.w = width;
418
        rect.h = height;
419
        SDL_DisplayYUVOverlay(vp->bmp, &rect);
420
    } else {
421
#if 0
422
        fill_rectangle(screen, 
423
                       is->xleft, is->ytop, is->width, is->height, 
424
                       QERGB(0x00, 0x00, 0x00));
425
#endif
426
    }
427
}
428
429
static inline int compute_mod(int a, int b)
430
{
431
    a = a % b;
432
    if (a >= 0) 
433
        return a;
434
    else
435
        return a + b;
436
}
437
438
static void video_audio_display(VideoState *s)
439
{
440
    int i, i_start, x, y1, y, ys, delay, n, nb_display_channels;
441
    int ch, channels, h, h2, bgcolor, fgcolor;
442
    int16_t time_diff;
443
    
444
    /* compute display index : center on currently output samples */
445
    channels = s->audio_st->codec.channels;
446
    nb_display_channels = channels;
447 5e0257e3 Fabrice Bellard
    if (!s->paused) {
448
        n = 2 * channels;
449
        delay = audio_write_get_buf_size(s);
450
        delay /= n;
451
        
452
        /* to be more precise, we take into account the time spent since
453
           the last buffer computation */
454
        if (audio_callback_time) {
455
            time_diff = av_gettime() - audio_callback_time;
456
            delay += (time_diff * s->audio_st->codec.sample_rate) / 1000000;
457
        }
458
        
459
        delay -= s->width / 2;
460
        if (delay < s->width)
461
            delay = s->width;
462
        i_start = compute_mod(s->sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE);
463
        s->last_i_start = i_start;
464
    } else {
465
        i_start = s->last_i_start;
466 01310af2 Fabrice Bellard
    }
467
468
    bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
469
    fill_rectangle(screen, 
470
                   s->xleft, s->ytop, s->width, s->height, 
471
                   bgcolor);
472
473
    fgcolor = SDL_MapRGB(screen->format, 0xff, 0xff, 0xff);
474
475
    /* total height for one channel */
476
    h = s->height / nb_display_channels;
477
    /* graph height / 2 */
478
    h2 = (h * 9) / 20;
479
    for(ch = 0;ch < nb_display_channels; ch++) {
480
        i = i_start + ch;
481
        y1 = s->ytop + ch * h + (h / 2); /* position of center line */
482
        for(x = 0; x < s->width; x++) {
483
            y = (s->sample_array[i] * h2) >> 15;
484
            if (y < 0) {
485
                y = -y;
486
                ys = y1 - y;
487
            } else {
488
                ys = y1;
489
            }
490
            fill_rectangle(screen, 
491
                           s->xleft + x, ys, 1, y, 
492
                           fgcolor);
493
            i += channels;
494
            if (i >= SAMPLE_ARRAY_SIZE)
495
                i -= SAMPLE_ARRAY_SIZE;
496
        }
497
    }
498
499
    fgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0xff);
500
501
    for(ch = 1;ch < nb_display_channels; ch++) {
502
        y = s->ytop + ch * h;
503
        fill_rectangle(screen, 
504
                       s->xleft, y, s->width, 1, 
505
                       fgcolor);
506
    }
507
    SDL_UpdateRect(screen, s->xleft, s->ytop, s->width, s->height);
508
}
509
510
/* display the current picture, if any */
511
static void video_display(VideoState *is)
512
{
513
    if (is->audio_st && is->show_audio) 
514
        video_audio_display(is);
515
    else if (is->video_st)
516
        video_image_display(is);
517
}
518
519
static Uint32 sdl_refresh_timer_cb(Uint32 interval, void *opaque)
520
{
521
    SDL_Event event;
522
    event.type = FF_REFRESH_EVENT;
523
    event.user.data1 = opaque;
524
    SDL_PushEvent(&event);
525
    return 0; /* 0 means stop timer */
526
}
527
528
/* schedule a video refresh in 'delay' ms */
529
static void schedule_refresh(VideoState *is, int delay)
530
{
531
    SDL_AddTimer(delay, sdl_refresh_timer_cb, is);
532
}
533
534 638c9d91 Fabrice Bellard
/* get the current audio clock value */
535
static double get_audio_clock(VideoState *is)
536
{
537
    double pts;
538
    int hw_buf_size, bytes_per_sec;
539
    pts = is->audio_clock;
540
    hw_buf_size = audio_write_get_buf_size(is);
541
    bytes_per_sec = 0;
542
    if (is->audio_st) {
543
        bytes_per_sec = is->audio_st->codec.sample_rate * 
544
            2 * is->audio_st->codec.channels;
545
    }
546
    if (bytes_per_sec)
547
        pts -= (double)hw_buf_size / bytes_per_sec;
548
    return pts;
549
}
550
551
/* get the current video clock value */
552
static double get_video_clock(VideoState *is)
553
{
554
    double delta;
555 04108619 Michael Niedermayer
    if (is->paused) {
556 72ea344b Fabrice Bellard
        delta = 0;
557
    } else {
558
        delta = (av_gettime() - is->video_current_pts_time) / 1000000.0;
559
    }
560 638c9d91 Fabrice Bellard
    return is->video_current_pts + delta;
561
}
562
563
/* get the current external clock value */
564
static double get_external_clock(VideoState *is)
565
{
566
    int64_t ti;
567
    ti = av_gettime();
568
    return is->external_clock + ((ti - is->external_clock_time) * 1e-6);
569
}
570
571
/* get the current master clock value */
572
static double get_master_clock(VideoState *is)
573
{
574
    double val;
575
576 72ea344b Fabrice Bellard
    if (is->av_sync_type == AV_SYNC_VIDEO_MASTER) {
577
        if (is->video_st)
578
            val = get_video_clock(is);
579
        else
580
            val = get_audio_clock(is);
581
    } else if (is->av_sync_type == AV_SYNC_AUDIO_MASTER) {
582
        if (is->audio_st)
583
            val = get_audio_clock(is);
584
        else
585
            val = get_video_clock(is);
586
    } else {
587 638c9d91 Fabrice Bellard
        val = get_external_clock(is);
588 72ea344b Fabrice Bellard
    }
589 638c9d91 Fabrice Bellard
    return val;
590
}
591
592 72ea344b Fabrice Bellard
/* seek in the stream */
593 3ba1438d Michael Niedermayer
static void stream_seek(VideoState *is, int64_t pos, int rel)
594 72ea344b Fabrice Bellard
{
595
    is->seek_pos = pos;
596
    is->seek_req = 1;
597 3ba1438d Michael Niedermayer
    is->seek_flags = rel < 0 ? AVSEEK_FLAG_BACKWARD : 0;
598 72ea344b Fabrice Bellard
}
599
600
/* pause or resume the video */
601
static void stream_pause(VideoState *is)
602
{
603
    is->paused = !is->paused;
604
    if (is->paused) {
605
        is->video_current_pts = get_video_clock(is);
606
    }
607
}
608
609 01310af2 Fabrice Bellard
/* called to display each frame */
610
static void video_refresh_timer(void *opaque)
611
{
612
    VideoState *is = opaque;
613
    VideoPicture *vp;
614 638c9d91 Fabrice Bellard
    double actual_delay, delay, sync_threshold, ref_clock, diff;
615
616 01310af2 Fabrice Bellard
617
    if (is->video_st) {
618
        if (is->pictq_size == 0) {
619
            /* if no picture, need to wait */
620 7e0140cb Michael Niedermayer
            schedule_refresh(is, 1);
621 01310af2 Fabrice Bellard
        } else {
622 638c9d91 Fabrice Bellard
            /* dequeue the picture */
623 01310af2 Fabrice Bellard
            vp = &is->pictq[is->pictq_rindex];
624 638c9d91 Fabrice Bellard
625
            /* update current video pts */
626
            is->video_current_pts = vp->pts;
627
            is->video_current_pts_time = av_gettime();
628
629
            /* compute nominal delay */
630
            delay = vp->pts - is->frame_last_pts;
631
            if (delay <= 0 || delay >= 1.0) {
632
                /* if incorrect delay, use previous one */
633
                delay = is->frame_last_delay;
634
            }
635
            is->frame_last_delay = delay;
636
            is->frame_last_pts = vp->pts;
637
638
            /* update delay to follow master synchronisation source */
639
            if (((is->av_sync_type == AV_SYNC_AUDIO_MASTER && is->audio_st) ||
640
                 is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
641
                /* if video is slave, we try to correct big delays by
642
                   duplicating or deleting a frame */
643
                ref_clock = get_master_clock(is);
644
                diff = vp->pts - ref_clock;
645
                
646
                /* skip or repeat frame. We take into account the
647
                   delay to compute the threshold. I still don't know
648
                   if it is the best guess */
649
                sync_threshold = AV_SYNC_THRESHOLD;
650
                if (delay > sync_threshold)
651
                    sync_threshold = delay;
652
                if (fabs(diff) < AV_NOSYNC_THRESHOLD) {
653
                    if (diff <= -sync_threshold)
654
                        delay = 0;
655
                    else if (diff >= sync_threshold)
656
                        delay = 2 * delay;
657
                }
658
            }
659
660
            is->frame_timer += delay;
661
            /* compute the REAL delay (we need to do that to avoid
662
               long term errors */
663
            actual_delay = is->frame_timer - (av_gettime() / 1000000.0);
664
            if (actual_delay < 0.010) {
665
                /* XXX: should skip picture */
666
                actual_delay = 0.010;
667
            }
668 01310af2 Fabrice Bellard
            /* launch timer for next picture */
669 638c9d91 Fabrice Bellard
            schedule_refresh(is, (int)(actual_delay * 1000 + 0.5));
670
671
#if defined(DEBUG_SYNC)
672
            printf("video: delay=%0.3f actual_delay=%0.3f pts=%0.3f A-V=%f\n", 
673
                   delay, actual_delay, vp->pts, -diff);
674
#endif
675 01310af2 Fabrice Bellard
676
            /* display picture */
677
            video_display(is);
678
            
679
            /* update queue size and signal for next picture */
680
            if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE)
681
                is->pictq_rindex = 0;
682
            
683
            SDL_LockMutex(is->pictq_mutex);
684
            is->pictq_size--;
685
            SDL_CondSignal(is->pictq_cond);
686
            SDL_UnlockMutex(is->pictq_mutex);
687
        }
688
    } else if (is->audio_st) {
689
        /* draw the next audio frame */
690
691
        schedule_refresh(is, 40);
692
693
        /* if only audio stream, then display the audio bars (better
694
           than nothing, just to test the implementation */
695
        
696
        /* display picture */
697
        video_display(is);
698
    } else {
699
        schedule_refresh(is, 100);
700
    }
701
    if (show_status) {
702
        static int64_t last_time;
703
        int64_t cur_time;
704
        int aqsize, vqsize;
705 638c9d91 Fabrice Bellard
        double av_diff;
706 01310af2 Fabrice Bellard
        
707
        cur_time = av_gettime();
708
        if (!last_time || (cur_time - last_time) >= 500 * 1000) {
709
            aqsize = 0;
710
            vqsize = 0;
711
            if (is->audio_st)
712
                aqsize = is->audioq.size;
713
            if (is->video_st)
714
                vqsize = is->videoq.size;
715 638c9d91 Fabrice Bellard
            av_diff = 0;
716
            if (is->audio_st && is->video_st)
717
                av_diff = get_audio_clock(is) - get_video_clock(is);
718
            printf("%7.2f A-V:%7.3f aq=%5dKB vq=%5dKB    \r", 
719
                   get_master_clock(is), av_diff, aqsize / 1024, vqsize / 1024);
720 01310af2 Fabrice Bellard
            fflush(stdout);
721
            last_time = cur_time;
722
        }
723
    }
724
}
725
726
/* allocate a picture (needs to do that in main thread to avoid
727
   potential locking problems */
728
static void alloc_picture(void *opaque)
729
{
730
    VideoState *is = opaque;
731
    VideoPicture *vp;
732
733
    vp = &is->pictq[is->pictq_windex];
734
735
    if (vp->bmp)
736
        SDL_FreeYUVOverlay(vp->bmp);
737
738 61890b02 Fabrice Bellard
#if 0
739 01310af2 Fabrice Bellard
    /* XXX: use generic function */
740 61890b02 Fabrice Bellard
    /* XXX: disable overlay if no hardware acceleration or if RGB format */
741 01310af2 Fabrice Bellard
    switch(is->video_st->codec.pix_fmt) {
742
    case PIX_FMT_YUV420P:
743
    case PIX_FMT_YUV422P:
744
    case PIX_FMT_YUV444P:
745
    case PIX_FMT_YUV422:
746
    case PIX_FMT_YUV410P:
747
    case PIX_FMT_YUV411P:
748
        is_yuv = 1;
749
        break;
750
    default:
751
        is_yuv = 0;
752
        break;
753
    }
754
#endif
755 61890b02 Fabrice Bellard
    vp->bmp = SDL_CreateYUVOverlay(is->video_st->codec.width,
756
                                   is->video_st->codec.height,
757
                                   SDL_YV12_OVERLAY, 
758
                                   screen);
759 01310af2 Fabrice Bellard
    vp->width = is->video_st->codec.width;
760
    vp->height = is->video_st->codec.height;
761
762
    SDL_LockMutex(is->pictq_mutex);
763
    vp->allocated = 1;
764
    SDL_CondSignal(is->pictq_cond);
765
    SDL_UnlockMutex(is->pictq_mutex);
766
}
767
768 638c9d91 Fabrice Bellard
static int queue_picture(VideoState *is, AVFrame *src_frame, double pts)
769 01310af2 Fabrice Bellard
{
770
    VideoPicture *vp;
771
    int dst_pix_fmt;
772
    AVPicture pict;
773
    
774
    /* wait until we have space to put a new picture */
775
    SDL_LockMutex(is->pictq_mutex);
776
    while (is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE &&
777
           !is->videoq.abort_request) {
778
        SDL_CondWait(is->pictq_cond, is->pictq_mutex);
779
    }
780
    SDL_UnlockMutex(is->pictq_mutex);
781
    
782
    if (is->videoq.abort_request)
783
        return -1;
784
785
    vp = &is->pictq[is->pictq_windex];
786
787
    /* alloc or resize hardware picture buffer */
788
    if (!vp->bmp || 
789
        vp->width != is->video_st->codec.width ||
790
        vp->height != is->video_st->codec.height) {
791
        SDL_Event event;
792
793
        vp->allocated = 0;
794
795
        /* the allocation must be done in the main thread to avoid
796
           locking problems */
797
        event.type = FF_ALLOC_EVENT;
798
        event.user.data1 = is;
799
        SDL_PushEvent(&event);
800
        
801
        /* wait until the picture is allocated */
802
        SDL_LockMutex(is->pictq_mutex);
803
        while (!vp->allocated && !is->videoq.abort_request) {
804
            SDL_CondWait(is->pictq_cond, is->pictq_mutex);
805
        }
806
        SDL_UnlockMutex(is->pictq_mutex);
807
808
        if (is->videoq.abort_request)
809
            return -1;
810
    }
811
812 638c9d91 Fabrice Bellard
    /* if the frame is not skipped, then display it */
813 01310af2 Fabrice Bellard
    if (vp->bmp) {
814
        /* get a pointer on the bitmap */
815
        SDL_LockYUVOverlay (vp->bmp);
816
817
        dst_pix_fmt = PIX_FMT_YUV420P;
818
        pict.data[0] = vp->bmp->pixels[0];
819
        pict.data[1] = vp->bmp->pixels[2];
820
        pict.data[2] = vp->bmp->pixels[1];
821
822
        pict.linesize[0] = vp->bmp->pitches[0];
823
        pict.linesize[1] = vp->bmp->pitches[2];
824
        pict.linesize[2] = vp->bmp->pitches[1];
825
        img_convert(&pict, dst_pix_fmt, 
826 638c9d91 Fabrice Bellard
                    (AVPicture *)src_frame, is->video_st->codec.pix_fmt, 
827 01310af2 Fabrice Bellard
                    is->video_st->codec.width, is->video_st->codec.height);
828
        /* update the bitmap content */
829
        SDL_UnlockYUVOverlay(vp->bmp);
830
831 638c9d91 Fabrice Bellard
        vp->pts = pts;
832 01310af2 Fabrice Bellard
833
        /* now we can update the picture count */
834
        if (++is->pictq_windex == VIDEO_PICTURE_QUEUE_SIZE)
835
            is->pictq_windex = 0;
836
        SDL_LockMutex(is->pictq_mutex);
837
        is->pictq_size++;
838
        SDL_UnlockMutex(is->pictq_mutex);
839
    }
840 638c9d91 Fabrice Bellard
    return 0;
841
}
842
843
/* compute the exact PTS for the picture if it is omitted in the stream */
844
static int output_picture2(VideoState *is, AVFrame *src_frame, double pts1)
845
{
846
    double frame_delay, pts;
847
    
848
    pts = pts1;
849
850 01310af2 Fabrice Bellard
    if (pts != 0) {
851 638c9d91 Fabrice Bellard
        /* update video clock with pts, if present */
852 01310af2 Fabrice Bellard
        is->video_clock = pts;
853
    } else {
854 72ea344b Fabrice Bellard
        pts = is->video_clock;
855
    }
856
    /* update video clock for next frame */
857
    frame_delay = (double)is->video_st->codec.frame_rate_base / 
858
        (double)is->video_st->codec.frame_rate;
859
    /* for MPEG2, the frame can be repeated, so we update the
860
       clock accordingly */
861
    if (src_frame->repeat_pict) {
862
        frame_delay += src_frame->repeat_pict * (frame_delay * 0.5);
863 01310af2 Fabrice Bellard
    }
864 72ea344b Fabrice Bellard
    is->video_clock += frame_delay;
865 638c9d91 Fabrice Bellard
866
#if defined(DEBUG_SYNC) && 0
867
    {
868
        int ftype;
869
        if (src_frame->pict_type == FF_B_TYPE)
870
            ftype = 'B';
871
        else if (src_frame->pict_type == FF_I_TYPE)
872
            ftype = 'I';
873
        else
874
            ftype = 'P';
875
        printf("frame_type=%c clock=%0.3f pts=%0.3f\n", 
876 72ea344b Fabrice Bellard
               ftype, pts, pts1);
877 638c9d91 Fabrice Bellard
    }
878
#endif
879 72ea344b Fabrice Bellard
    return queue_picture(is, src_frame, pts);
880 01310af2 Fabrice Bellard
}
881
882
static int video_thread(void *arg)
883
{
884
    VideoState *is = arg;
885
    AVPacket pkt1, *pkt = &pkt1;
886 72ea344b Fabrice Bellard
    int len1, got_picture;
887 c6b1edc9 Michael Niedermayer
    AVFrame *frame= avcodec_alloc_frame();
888 01310af2 Fabrice Bellard
    double pts;
889
890
    for(;;) {
891
        while (is->paused && !is->videoq.abort_request) {
892
            SDL_Delay(10);
893
        }
894
        if (packet_queue_get(&is->videoq, pkt, 1) < 0)
895
            break;
896 638c9d91 Fabrice Bellard
        /* NOTE: ipts is the PTS of the _first_ picture beginning in
897
           this packet, if any */
898 72ea344b Fabrice Bellard
        pts = 0;
899 61c1d8e2 Michael Niedermayer
        if (pkt->dts != AV_NOPTS_VALUE)
900
            pts = (double)pkt->dts / AV_TIME_BASE;
901 72ea344b Fabrice Bellard
902
            len1 = avcodec_decode_video(&is->video_st->codec, 
903
                                        frame, &got_picture, 
904
                                        pkt->data, pkt->size);
905 fb966f99 Michael Niedermayer
//            if (len1 < 0)
906
//                break;
907 72ea344b Fabrice Bellard
            if (got_picture) {
908
                if (output_picture2(is, frame, pts) < 0)
909
                    goto the_end;
910 01310af2 Fabrice Bellard
            }
911
        av_free_packet(pkt);
912 bba04f1e Wolfgang Hesseler
        if (step) 
913
            if (cur_stream)
914
                stream_pause(cur_stream);
915 01310af2 Fabrice Bellard
    }
916
 the_end:
917 c6b1edc9 Michael Niedermayer
    av_free(frame);
918 01310af2 Fabrice Bellard
    return 0;
919
}
920
921
/* copy samples for viewing in editor window */
922
static void update_sample_display(VideoState *is, short *samples, int samples_size)
923
{
924
    int size, len, channels;
925
926
    channels = is->audio_st->codec.channels;
927
928
    size = samples_size / sizeof(short);
929
    while (size > 0) {
930
        len = SAMPLE_ARRAY_SIZE - is->sample_array_index;
931
        if (len > size)
932
            len = size;
933
        memcpy(is->sample_array + is->sample_array_index, samples, len * sizeof(short));
934
        samples += len;
935
        is->sample_array_index += len;
936
        if (is->sample_array_index >= SAMPLE_ARRAY_SIZE)
937
            is->sample_array_index = 0;
938
        size -= len;
939
    }
940
}
941
942
/* return the new audio buffer size (samples can be added or deleted
943
   to get better sync if video or external master clock) */
944
static int synchronize_audio(VideoState *is, short *samples, 
945 638c9d91 Fabrice Bellard
                             int samples_size1, double pts)
946 01310af2 Fabrice Bellard
{
947 638c9d91 Fabrice Bellard
    int n, samples_size;
948 01310af2 Fabrice Bellard
    double ref_clock;
949
    
950
    n = 2 * is->audio_st->codec.channels;
951 638c9d91 Fabrice Bellard
    samples_size = samples_size1;
952 01310af2 Fabrice Bellard
953
    /* if not master, then we try to remove or add samples to correct the clock */
954
    if (((is->av_sync_type == AV_SYNC_VIDEO_MASTER && is->video_st) ||
955 638c9d91 Fabrice Bellard
         is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
956
        double diff, avg_diff;
957 01310af2 Fabrice Bellard
        int wanted_size, min_size, max_size, nb_samples;
958 638c9d91 Fabrice Bellard
            
959
        ref_clock = get_master_clock(is);
960
        diff = get_audio_clock(is) - ref_clock;
961 01310af2 Fabrice Bellard
        
962 638c9d91 Fabrice Bellard
        if (diff < AV_NOSYNC_THRESHOLD) {
963
            is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum;
964
            if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {
965
                /* not enough measures to have a correct estimate */
966
                is->audio_diff_avg_count++;
967
            } else {
968
                /* estimate the A-V difference */
969
                avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef);
970
971
                if (fabs(avg_diff) >= is->audio_diff_threshold) {
972
                    wanted_size = samples_size + ((int)(diff * is->audio_st->codec.sample_rate) * n);
973
                    nb_samples = samples_size / n;
974
                
975
                    min_size = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
976
                    max_size = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
977
                    if (wanted_size < min_size)
978
                        wanted_size = min_size;
979
                    else if (wanted_size > max_size)
980
                        wanted_size = max_size;
981
                    
982
                    /* add or remove samples to correction the synchro */
983
                    if (wanted_size < samples_size) {
984
                        /* remove samples */
985
                        samples_size = wanted_size;
986
                    } else if (wanted_size > samples_size) {
987
                        uint8_t *samples_end, *q;
988
                        int nb;
989
                        
990
                        /* add samples */
991
                        nb = (samples_size - wanted_size);
992
                        samples_end = (uint8_t *)samples + samples_size - n;
993
                        q = samples_end + n;
994
                        while (nb > 0) {
995
                            memcpy(q, samples_end, n);
996
                            q += n;
997
                            nb -= n;
998
                        }
999
                        samples_size = wanted_size;
1000
                    }
1001
                }
1002
#if 0
1003
                printf("diff=%f adiff=%f sample_diff=%d apts=%0.3f vpts=%0.3f %f\n", 
1004
                       diff, avg_diff, samples_size - samples_size1, 
1005
                       is->audio_clock, is->video_clock, is->audio_diff_threshold);
1006
#endif
1007 01310af2 Fabrice Bellard
            }
1008 638c9d91 Fabrice Bellard
        } else {
1009
            /* too big difference : may be initial PTS errors, so
1010
               reset A-V filter */
1011
            is->audio_diff_avg_count = 0;
1012
            is->audio_diff_cum = 0;
1013 01310af2 Fabrice Bellard
        }
1014
    }
1015
1016
    return samples_size;
1017
}
1018
1019
/* decode one audio frame and returns its uncompressed size */
1020
static int audio_decode_frame(VideoState *is, uint8_t *audio_buf, double *pts_ptr)
1021
{
1022
    AVPacket *pkt = &is->audio_pkt;
1023 72ea344b Fabrice Bellard
    int n, len1, data_size;
1024 01310af2 Fabrice Bellard
    double pts;
1025
1026
    for(;;) {
1027 72ea344b Fabrice Bellard
        /* NOTE: the audio packet can contain several frames */
1028 01310af2 Fabrice Bellard
        while (is->audio_pkt_size > 0) {
1029
            len1 = avcodec_decode_audio(&is->audio_st->codec, 
1030
                                        (int16_t *)audio_buf, &data_size, 
1031
                                        is->audio_pkt_data, is->audio_pkt_size);
1032 72ea344b Fabrice Bellard
            if (len1 < 0) {
1033
                /* if error, we skip the frame */
1034
                is->audio_pkt_size = 0;
1035 01310af2 Fabrice Bellard
                break;
1036 72ea344b Fabrice Bellard
            }
1037
            
1038 01310af2 Fabrice Bellard
            is->audio_pkt_data += len1;
1039
            is->audio_pkt_size -= len1;
1040 72ea344b Fabrice Bellard
            if (data_size <= 0)
1041
                continue;
1042
            /* if no pts, then compute it */
1043
            pts = is->audio_clock;
1044
            *pts_ptr = pts;
1045
            n = 2 * is->audio_st->codec.channels;
1046
            is->audio_clock += (double)data_size / 
1047
                (double)(n * is->audio_st->codec.sample_rate);
1048 638c9d91 Fabrice Bellard
#if defined(DEBUG_SYNC)
1049 72ea344b Fabrice Bellard
            {
1050
                static double last_clock;
1051
                printf("audio: delay=%0.3f clock=%0.3f pts=%0.3f\n",
1052
                       is->audio_clock - last_clock,
1053
                       is->audio_clock, pts);
1054
                last_clock = is->audio_clock;
1055 01310af2 Fabrice Bellard
            }
1056 72ea344b Fabrice Bellard
#endif
1057
            return data_size;
1058 01310af2 Fabrice Bellard
        }
1059
1060 72ea344b Fabrice Bellard
        /* free the current packet */
1061
        if (pkt->data)
1062 01310af2 Fabrice Bellard
            av_free_packet(pkt);
1063 72ea344b Fabrice Bellard
        
1064
        if (is->paused || is->audioq.abort_request) {
1065
            return -1;
1066
        }
1067
        
1068 01310af2 Fabrice Bellard
        /* read next packet */
1069
        if (packet_queue_get(&is->audioq, pkt, 1) < 0)
1070
            return -1;
1071
        is->audio_pkt_data = pkt->data;
1072
        is->audio_pkt_size = pkt->size;
1073 72ea344b Fabrice Bellard
        
1074
        /* if update the audio clock with the pts */
1075
        if (pkt->pts != AV_NOPTS_VALUE) {
1076
            is->audio_clock = (double)pkt->pts / AV_TIME_BASE;
1077
        }
1078 01310af2 Fabrice Bellard
    }
1079
}
1080
1081 638c9d91 Fabrice Bellard
/* get the current audio output buffer size, in samples. With SDL, we
1082
   cannot have a precise information */
1083
static int audio_write_get_buf_size(VideoState *is)
1084 01310af2 Fabrice Bellard
{
1085 638c9d91 Fabrice Bellard
    return is->audio_hw_buf_size - is->audio_buf_index;
1086 01310af2 Fabrice Bellard
}
1087
1088
1089
/* prepare a new audio buffer */
1090
void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
1091
{
1092
    VideoState *is = opaque;
1093
    int audio_size, len1;
1094
    double pts;
1095
1096
    audio_callback_time = av_gettime();
1097
    
1098
    while (len > 0) {
1099
        if (is->audio_buf_index >= is->audio_buf_size) {
1100
           audio_size = audio_decode_frame(is, is->audio_buf, &pts);
1101
           if (audio_size < 0) {
1102
                /* if error, just output silence */
1103
               is->audio_buf_size = 1024;
1104
               memset(is->audio_buf, 0, is->audio_buf_size);
1105
           } else {
1106
               if (is->show_audio)
1107
                   update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
1108
               audio_size = synchronize_audio(is, (int16_t *)is->audio_buf, audio_size, 
1109
                                              pts);
1110
               is->audio_buf_size = audio_size;
1111
           }
1112
           is->audio_buf_index = 0;
1113
        }
1114
        len1 = is->audio_buf_size - is->audio_buf_index;
1115
        if (len1 > len)
1116
            len1 = len;
1117
        memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
1118
        len -= len1;
1119
        stream += len1;
1120
        is->audio_buf_index += len1;
1121
    }
1122
}
1123
1124
1125
/* open a given stream. Return 0 if OK */
1126
static int stream_component_open(VideoState *is, int stream_index)
1127
{
1128
    AVFormatContext *ic = is->ic;
1129
    AVCodecContext *enc;
1130
    AVCodec *codec;
1131
    SDL_AudioSpec wanted_spec, spec;
1132
1133
    if (stream_index < 0 || stream_index >= ic->nb_streams)
1134
        return -1;
1135
    enc = &ic->streams[stream_index]->codec;
1136
    
1137
    /* prepare audio output */
1138
    if (enc->codec_type == CODEC_TYPE_AUDIO) {
1139
        wanted_spec.freq = enc->sample_rate;
1140
        wanted_spec.format = AUDIO_S16SYS;
1141 638c9d91 Fabrice Bellard
        /* hack for AC3. XXX: suppress that */
1142
        if (enc->channels > 2)
1143
            enc->channels = 2;
1144 01310af2 Fabrice Bellard
        wanted_spec.channels = enc->channels;
1145
        wanted_spec.silence = 0;
1146 638c9d91 Fabrice Bellard
        wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
1147 01310af2 Fabrice Bellard
        wanted_spec.callback = sdl_audio_callback;
1148
        wanted_spec.userdata = is;
1149 638c9d91 Fabrice Bellard
        if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
1150
            fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());
1151 01310af2 Fabrice Bellard
            return -1;
1152 638c9d91 Fabrice Bellard
        }
1153 01310af2 Fabrice Bellard
        is->audio_hw_buf_size = spec.size;
1154
    }
1155
1156
    codec = avcodec_find_decoder(enc->codec_id);
1157 13d1512c Michael Niedermayer
    enc->debug_mv = debug_mv;
1158
    enc->debug = debug;
1159 6387c3e6 Michael Niedermayer
    enc->workaround_bugs = workaround_bugs;
1160 178fcca8 Michael Niedermayer
    enc->lowres = lowres;
1161 61846e9a Michael Niedermayer
    if(lowres) enc->flags |= CODEC_FLAG_EMU_EDGE;
1162 178fcca8 Michael Niedermayer
    enc->idct_algo= idct;
1163 6fc5b059 Michael Niedermayer
    if(fast) enc->flags2 |= CODEC_FLAG2_FAST;
1164 01310af2 Fabrice Bellard
    if (!codec ||
1165
        avcodec_open(enc, codec) < 0)
1166
        return -1;
1167 2450cff2 Fran├žois Revol
#if defined(HAVE_THREADS)
1168 c62c07d3 Michael Niedermayer
    if(thread_count>1)
1169
        avcodec_thread_init(enc, thread_count);
1170
#endif
1171
    enc->thread_count= thread_count;
1172 638c9d91 Fabrice Bellard
    switch(enc->codec_type) {
1173 01310af2 Fabrice Bellard
    case CODEC_TYPE_AUDIO:
1174
        is->audio_stream = stream_index;
1175
        is->audio_st = ic->streams[stream_index];
1176
        is->audio_buf_size = 0;
1177
        is->audio_buf_index = 0;
1178 638c9d91 Fabrice Bellard
1179
        /* init averaging filter */
1180
        is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
1181
        is->audio_diff_avg_count = 0;
1182
        /* since we do not have a precise anough audio fifo fullness,
1183
           we correct audio sync only if larger than this threshold */
1184
        is->audio_diff_threshold = 2.0 * SDL_AUDIO_BUFFER_SIZE / enc->sample_rate;
1185
1186 01310af2 Fabrice Bellard
        memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
1187
        packet_queue_init(&is->audioq);
1188
        SDL_PauseAudio(0);
1189
        break;
1190
    case CODEC_TYPE_VIDEO:
1191
        is->video_stream = stream_index;
1192
        is->video_st = ic->streams[stream_index];
1193
1194 638c9d91 Fabrice Bellard
        is->frame_last_delay = 40e-3;
1195
        is->frame_timer = (double)av_gettime() / 1000000.0;
1196
        is->video_current_pts_time = av_gettime();
1197
1198 01310af2 Fabrice Bellard
        packet_queue_init(&is->videoq);
1199
        is->video_tid = SDL_CreateThread(video_thread, is);
1200
        break;
1201
    default:
1202
        break;
1203
    }
1204
    return 0;
1205
}
1206
1207
static void stream_component_close(VideoState *is, int stream_index)
1208
{
1209
    AVFormatContext *ic = is->ic;
1210
    AVCodecContext *enc;
1211
    
1212
    enc = &ic->streams[stream_index]->codec;
1213
1214
    switch(enc->codec_type) {
1215
    case CODEC_TYPE_AUDIO:
1216
        packet_queue_abort(&is->audioq);
1217
1218
        SDL_CloseAudio();
1219
1220
        packet_queue_end(&is->audioq);
1221
        break;
1222
    case CODEC_TYPE_VIDEO:
1223
        packet_queue_abort(&is->videoq);
1224
1225
        /* note: we also signal this mutex to make sure we deblock the
1226
           video thread in all cases */
1227
        SDL_LockMutex(is->pictq_mutex);
1228
        SDL_CondSignal(is->pictq_cond);
1229
        SDL_UnlockMutex(is->pictq_mutex);
1230
1231
        SDL_WaitThread(is->video_tid, NULL);
1232
1233
        packet_queue_end(&is->videoq);
1234
        break;
1235
    default:
1236
        break;
1237
    }
1238
1239
    avcodec_close(enc);
1240
    switch(enc->codec_type) {
1241
    case CODEC_TYPE_AUDIO:
1242
        is->audio_st = NULL;
1243
        is->audio_stream = -1;
1244
        break;
1245
    case CODEC_TYPE_VIDEO:
1246
        is->video_st = NULL;
1247
        is->video_stream = -1;
1248
        break;
1249
    default:
1250
        break;
1251
    }
1252
}
1253
1254 d0526ecf Fabrice Bellard
void dump_stream_info(AVFormatContext *s)
1255
{
1256
    if (s->track != 0)
1257
        fprintf(stderr, "Track: %d\n", s->track);
1258
    if (s->title[0] != '\0')
1259
        fprintf(stderr, "Title: %s\n", s->title);
1260
    if (s->author[0] != '\0')
1261
        fprintf(stderr, "Author: %s\n", s->author);
1262
    if (s->album[0] != '\0')
1263
        fprintf(stderr, "Album: %s\n", s->album);
1264
    if (s->year != 0)
1265
        fprintf(stderr, "Year: %d\n", s->year);
1266
    if (s->genre[0] != '\0')
1267
        fprintf(stderr, "Genre: %s\n", s->genre);
1268
}
1269
1270 416e3508 Fabrice Bellard
/* since we have only one decoding thread, we can use a global
1271
   variable instead of a thread local variable */
1272
static VideoState *global_video_state;
1273
1274
static int decode_interrupt_cb(void)
1275
{
1276
    return (global_video_state && global_video_state->abort_request);
1277
}
1278 01310af2 Fabrice Bellard
1279
/* this thread gets the stream from the disk or the network */
1280
static int decode_thread(void *arg)
1281
{
1282
    VideoState *is = arg;
1283
    AVFormatContext *ic;
1284 72ea344b Fabrice Bellard
    int err, i, ret, video_index, audio_index, use_play;
1285 01310af2 Fabrice Bellard
    AVPacket pkt1, *pkt = &pkt1;
1286 61890b02 Fabrice Bellard
    AVFormatParameters params, *ap = &params;
1287 01310af2 Fabrice Bellard
1288
    video_index = -1;
1289
    audio_index = -1;
1290
    is->video_stream = -1;
1291
    is->audio_stream = -1;
1292
1293 416e3508 Fabrice Bellard
    global_video_state = is;
1294
    url_set_interrupt_cb(decode_interrupt_cb);
1295
1296 61890b02 Fabrice Bellard
    memset(ap, 0, sizeof(*ap));
1297
    ap->image_format = image_format;
1298 72ea344b Fabrice Bellard
    ap->initial_pause = 1; /* we force a pause when starting an RTSP
1299
                              stream */
1300
    
1301 61890b02 Fabrice Bellard
    err = av_open_input_file(&ic, is->filename, is->iformat, 0, ap);
1302 638c9d91 Fabrice Bellard
    if (err < 0) {
1303
        print_error(is->filename, err);
1304
        ret = -1;
1305
        goto fail;
1306
    }
1307 01310af2 Fabrice Bellard
    is->ic = ic;
1308 72ea344b Fabrice Bellard
#ifdef CONFIG_NETWORK
1309
    use_play = (ic->iformat == &rtsp_demux);
1310
#else
1311
    use_play = 0;
1312
#endif
1313
    if (!use_play) {
1314
        err = av_find_stream_info(ic);
1315
        if (err < 0) {
1316
            fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
1317
            ret = -1;
1318
            goto fail;
1319
        }
1320 638c9d91 Fabrice Bellard
    }
1321 72ea344b Fabrice Bellard
1322
    /* if seeking requested, we execute it */
1323
    if (start_time != AV_NOPTS_VALUE) {
1324
        int64_t timestamp;
1325
1326
        timestamp = start_time;
1327
        /* add the stream start time */
1328
        if (ic->start_time != AV_NOPTS_VALUE)
1329
            timestamp += ic->start_time;
1330 3ba1438d Michael Niedermayer
        ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
1331 72ea344b Fabrice Bellard
        if (ret < 0) {
1332
            fprintf(stderr, "%s: could not seek to position %0.3f\n", 
1333
                    is->filename, (double)timestamp / AV_TIME_BASE);
1334
        }
1335
    }
1336
1337
    /* now we can begin to play (RTSP stream only) */
1338
    av_read_play(ic);
1339
1340
    if (use_play) {
1341
        err = av_find_stream_info(ic);
1342
        if (err < 0) {
1343
            fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
1344
            ret = -1;
1345
            goto fail;
1346
        }
1347
    }
1348
1349 01310af2 Fabrice Bellard
    for(i = 0; i < ic->nb_streams; i++) {
1350
        AVCodecContext *enc = &ic->streams[i]->codec;
1351
        switch(enc->codec_type) {
1352
        case CODEC_TYPE_AUDIO:
1353
            if (audio_index < 0 && !audio_disable)
1354
                audio_index = i;
1355
            break;
1356
        case CODEC_TYPE_VIDEO:
1357
            if (video_index < 0 && !video_disable)
1358
                video_index = i;
1359
            break;
1360
        default:
1361
            break;
1362
        }
1363
    }
1364
    if (show_status) {
1365
        dump_format(ic, 0, is->filename, 0);
1366 d0526ecf Fabrice Bellard
        dump_stream_info(ic);
1367 01310af2 Fabrice Bellard
    }
1368
1369
    /* open the streams */
1370
    if (audio_index >= 0) {
1371
        stream_component_open(is, audio_index);
1372
    }
1373
1374
    if (video_index >= 0) {
1375
        stream_component_open(is, video_index);
1376
    } else {
1377
        if (!display_disable)
1378
            is->show_audio = 1;
1379
    }
1380
1381
    if (is->video_stream < 0 && is->audio_stream < 0) {
1382 638c9d91 Fabrice Bellard
        fprintf(stderr, "%s: could not open codecs\n", is->filename);
1383
        ret = -1;
1384 01310af2 Fabrice Bellard
        goto fail;
1385
    }
1386
1387
    for(;;) {
1388
        if (is->abort_request)
1389
            break;
1390 400738b1 Michael Niedermayer
#ifdef CONFIG_NETWORK
1391 416e3508 Fabrice Bellard
        if (is->paused != is->last_paused) {
1392
            is->last_paused = is->paused;
1393 72ea344b Fabrice Bellard
            if (is->paused)
1394
                av_read_pause(ic);
1395
            else
1396
                av_read_play(ic);
1397 416e3508 Fabrice Bellard
        }
1398
        if (is->paused && ic->iformat == &rtsp_demux) {
1399
            /* wait 10 ms to avoid trying to get another packet */
1400
            /* XXX: horrible */
1401
            SDL_Delay(10);
1402
            continue;
1403
        }
1404 400738b1 Michael Niedermayer
#endif
1405 72ea344b Fabrice Bellard
        if (is->seek_req) {
1406
            /* XXX: must lock decoder threads */
1407 3ba1438d Michael Niedermayer
            ret = av_seek_frame(is->ic, -1, is->seek_pos, is->seek_flags);
1408 72ea344b Fabrice Bellard
            if (ret < 0) {
1409
                fprintf(stderr, "%s: error while seeking\n", is->ic->filename);
1410 e6c0297f Michael Niedermayer
            }else{
1411
                if (is->audio_stream >= 0) {
1412
                    packet_queue_flush(&is->audioq);
1413
                }
1414
                if (is->video_stream >= 0) {
1415
                    packet_queue_flush(&is->videoq);
1416 93e1a0a9 Michael Niedermayer
                    avcodec_flush_buffers(&ic->streams[video_index]->codec);
1417 e6c0297f Michael Niedermayer
                }
1418 72ea344b Fabrice Bellard
            }
1419
            is->seek_req = 0;
1420
        }
1421 416e3508 Fabrice Bellard
1422 01310af2 Fabrice Bellard
        /* if the queue are full, no need to read more */
1423
        if (is->audioq.size > MAX_AUDIOQ_SIZE ||
1424 0c904df2 Michael Niedermayer
            is->videoq.size > MAX_VIDEOQ_SIZE || 
1425
            url_feof(&ic->pb)) {
1426 01310af2 Fabrice Bellard
            /* wait 10 ms */
1427
            SDL_Delay(10);
1428
            continue;
1429
        }
1430 72ea344b Fabrice Bellard
        ret = av_read_frame(ic, pkt);
1431 01310af2 Fabrice Bellard
        if (ret < 0) {
1432 6e1f8725 Roman Shaposhnik
            if (url_feof(&ic->pb) && url_ferror(&ic->pb) == 0) {
1433
                SDL_Delay(100); /* wait for user event */
1434
                continue;
1435
            } else
1436
                break;
1437 01310af2 Fabrice Bellard
        }
1438
        if (pkt->stream_index == is->audio_stream) {
1439
            packet_queue_put(&is->audioq, pkt);
1440
        } else if (pkt->stream_index == is->video_stream) {
1441
            packet_queue_put(&is->videoq, pkt);
1442
        } else {
1443
            av_free_packet(pkt);
1444
        }
1445
    }
1446
    /* wait until the end */
1447
    while (!is->abort_request) {
1448
        SDL_Delay(100);
1449
    }
1450
1451 638c9d91 Fabrice Bellard
    ret = 0;
1452 01310af2 Fabrice Bellard
 fail:
1453 416e3508 Fabrice Bellard
    /* disable interrupting */
1454
    global_video_state = NULL;
1455
1456 01310af2 Fabrice Bellard
    /* close each stream */
1457
    if (is->audio_stream >= 0)
1458
        stream_component_close(is, is->audio_stream);
1459
    if (is->video_stream >= 0)
1460
        stream_component_close(is, is->video_stream);
1461 638c9d91 Fabrice Bellard
    if (is->ic) {
1462
        av_close_input_file(is->ic);
1463
        is->ic = NULL; /* safety */
1464
    }
1465 416e3508 Fabrice Bellard
    url_set_interrupt_cb(NULL);
1466
1467 638c9d91 Fabrice Bellard
    if (ret != 0) {
1468
        SDL_Event event;
1469
        
1470
        event.type = FF_QUIT_EVENT;
1471
        event.user.data1 = is;
1472
        SDL_PushEvent(&event);
1473
    }
1474 01310af2 Fabrice Bellard
    return 0;
1475
}
1476
1477 638c9d91 Fabrice Bellard
static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
1478 01310af2 Fabrice Bellard
{
1479
    VideoState *is;
1480
1481
    is = av_mallocz(sizeof(VideoState));
1482
    if (!is)
1483
        return NULL;
1484
    pstrcpy(is->filename, sizeof(is->filename), filename);
1485 638c9d91 Fabrice Bellard
    is->iformat = iformat;
1486 01310af2 Fabrice Bellard
    if (screen) {
1487
        is->width = screen->w;
1488
        is->height = screen->h;
1489
    }
1490
    is->ytop = 0;
1491
    is->xleft = 0;
1492
1493
    /* start video display */
1494
    is->pictq_mutex = SDL_CreateMutex();
1495
    is->pictq_cond = SDL_CreateCond();
1496
1497
    /* add the refresh timer to draw the picture */
1498
    schedule_refresh(is, 40);
1499
1500 638c9d91 Fabrice Bellard
    is->av_sync_type = av_sync_type;
1501 01310af2 Fabrice Bellard
    is->parse_tid = SDL_CreateThread(decode_thread, is);
1502
    if (!is->parse_tid) {
1503
        av_free(is);
1504
        return NULL;
1505
    }
1506
    return is;
1507
}
1508
1509
static void stream_close(VideoState *is)
1510
{
1511
    VideoPicture *vp;
1512
    int i;
1513
    /* XXX: use a special url_shutdown call to abort parse cleanly */
1514
    is->abort_request = 1;
1515
    SDL_WaitThread(is->parse_tid, NULL);
1516
1517
    /* free all pictures */
1518
    for(i=0;i<VIDEO_PICTURE_QUEUE_SIZE; i++) {
1519
        vp = &is->pictq[i];
1520
        if (vp->bmp) {
1521
            SDL_FreeYUVOverlay(vp->bmp);
1522
            vp->bmp = NULL;
1523
        }
1524
    }
1525
    SDL_DestroyMutex(is->pictq_mutex);
1526
    SDL_DestroyCond(is->pictq_cond);
1527
}
1528
1529 638c9d91 Fabrice Bellard
void stream_cycle_channel(VideoState *is, int codec_type)
1530
{
1531
    AVFormatContext *ic = is->ic;
1532
    int start_index, stream_index;
1533
    AVStream *st;
1534
1535
    if (codec_type == CODEC_TYPE_VIDEO)
1536
        start_index = is->video_stream;
1537
    else
1538
        start_index = is->audio_stream;
1539
    if (start_index < 0)
1540
        return;
1541
    stream_index = start_index;
1542
    for(;;) {
1543
        if (++stream_index >= is->ic->nb_streams)
1544
            stream_index = 0;
1545
        if (stream_index == start_index)
1546
            return;
1547
        st = ic->streams[stream_index];
1548
        if (st->codec.codec_type == codec_type) {
1549
            /* check that parameters are OK */
1550
            switch(codec_type) {
1551
            case CODEC_TYPE_AUDIO:
1552
                if (st->codec.sample_rate != 0 &&
1553
                    st->codec.channels != 0)
1554
                    goto the_end;
1555
                break;
1556
            case CODEC_TYPE_VIDEO:
1557
                goto the_end;
1558
            default:
1559
                break;
1560
            }
1561
        }
1562
    }
1563
 the_end:
1564
    stream_component_close(is, start_index);
1565
    stream_component_open(is, stream_index);
1566
}
1567
1568
1569 01310af2 Fabrice Bellard
void toggle_full_screen(void)
1570
{
1571
    int w, h, flags;
1572
    is_full_screen = !is_full_screen;
1573
    if (!fs_screen_width) {
1574
        /* use default SDL method */
1575
        SDL_WM_ToggleFullScreen(screen);
1576
    } else {
1577
        /* use the recorded resolution */
1578
        flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
1579
        if (is_full_screen) {
1580
            w = fs_screen_width;
1581
            h = fs_screen_height;
1582
            flags |= SDL_FULLSCREEN;
1583
        } else {
1584
            w = screen_width;
1585
            h = screen_height;
1586
            flags |= SDL_RESIZABLE;
1587
        }
1588
        screen = SDL_SetVideoMode(w, h, 0, flags);
1589
        cur_stream->width = w;
1590
        cur_stream->height = h;
1591
    }
1592
}
1593
1594
void toggle_pause(void)
1595
{
1596
    if (cur_stream)
1597
        stream_pause(cur_stream);
1598 bba04f1e Wolfgang Hesseler
    step = 0;
1599
}
1600
1601
void step_to_next_frame(void)
1602
{
1603
    if (cur_stream) {
1604
        if (cur_stream->paused)
1605
            cur_stream->paused=0;
1606
        cur_stream->video_current_pts = get_video_clock(cur_stream);
1607
    }
1608
    step = 1;
1609 01310af2 Fabrice Bellard
}
1610
1611
void do_exit(void)
1612
{
1613
    if (cur_stream) {
1614
        stream_close(cur_stream);
1615
        cur_stream = NULL;
1616
    }
1617
    if (show_status)
1618
        printf("\n");
1619
    SDL_Quit();
1620
    exit(0);
1621
}
1622
1623
void toggle_audio_display(void)
1624
{
1625
    if (cur_stream) {
1626
        cur_stream->show_audio = !cur_stream->show_audio;
1627
    }
1628
}
1629
1630
/* handle an event sent by the GUI */
1631
void event_loop(void)
1632
{
1633
    SDL_Event event;
1634 a11d11aa Michel Bardiaux
    double incr, pos, frac;
1635 01310af2 Fabrice Bellard
1636
    for(;;) {
1637
        SDL_WaitEvent(&event);
1638
        switch(event.type) {
1639
        case SDL_KEYDOWN:
1640
            switch(event.key.keysym.sym) {
1641
            case SDLK_ESCAPE:
1642
            case SDLK_q:
1643
                do_exit();
1644
                break;
1645
            case SDLK_f:
1646
                toggle_full_screen();
1647
                break;
1648
            case SDLK_p:
1649
            case SDLK_SPACE:
1650
                toggle_pause();
1651
                break;
1652 bba04f1e Wolfgang Hesseler
            case SDLK_s: //S: Step to next frame
1653
                step_to_next_frame();
1654
                break;
1655 01310af2 Fabrice Bellard
            case SDLK_a:
1656 638c9d91 Fabrice Bellard
                if (cur_stream) 
1657
                    stream_cycle_channel(cur_stream, CODEC_TYPE_AUDIO);
1658
                break;
1659
            case SDLK_v:
1660
                if (cur_stream) 
1661
                    stream_cycle_channel(cur_stream, CODEC_TYPE_VIDEO);
1662
                break;
1663
            case SDLK_w:
1664 01310af2 Fabrice Bellard
                toggle_audio_display();
1665
                break;
1666 72ea344b Fabrice Bellard
            case SDLK_LEFT:
1667
                incr = -10.0;
1668
                goto do_seek;
1669
            case SDLK_RIGHT:
1670
                incr = 10.0;
1671
                goto do_seek;
1672
            case SDLK_UP:
1673
                incr = 60.0;
1674
                goto do_seek;
1675
            case SDLK_DOWN:
1676
                incr = -60.0;
1677
            do_seek:
1678
                if (cur_stream) {
1679
                    pos = get_master_clock(cur_stream);
1680
                    pos += incr;
1681 3ba1438d Michael Niedermayer
                    stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), incr);
1682 72ea344b Fabrice Bellard
                }
1683
                break;
1684 01310af2 Fabrice Bellard
            default:
1685
                break;
1686
            }
1687
            break;
1688 a11d11aa Michel Bardiaux
        case SDL_MOUSEBUTTONDOWN:
1689
            if (cur_stream) {
1690
                int ns, hh, mm, ss;
1691
                int tns, thh, tmm, tss;
1692
                tns = cur_stream->ic->duration/1000000LL;
1693
                thh = tns/3600;
1694
                tmm = (tns%3600)/60;
1695
                tss = (tns%60);
1696
                frac = (double)event.button.x/(double)cur_stream->width;
1697
                ns = frac*tns;
1698
                hh = ns/3600;
1699
                mm = (ns%3600)/60;
1700
                ss = (ns%60);
1701
                fprintf(stderr, "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d)       \n", frac*100,
1702
                        hh, mm, ss, thh, tmm, tss);
1703 3ba1438d Michael Niedermayer
                stream_seek(cur_stream, (int64_t)(cur_stream->ic->start_time+frac*cur_stream->ic->duration), 0);
1704 a11d11aa Michel Bardiaux
            }
1705
            break;
1706 01310af2 Fabrice Bellard
        case SDL_VIDEORESIZE:
1707
            if (cur_stream) {
1708
                screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0, 
1709
                                          SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL);
1710
                cur_stream->width = event.resize.w;
1711
                cur_stream->height = event.resize.h;
1712
            }
1713
            break;
1714
        case SDL_QUIT:
1715 638c9d91 Fabrice Bellard
        case FF_QUIT_EVENT:
1716 01310af2 Fabrice Bellard
            do_exit();
1717
            break;
1718
        case FF_ALLOC_EVENT:
1719
            alloc_picture(event.user.data1);
1720
            break;
1721
        case FF_REFRESH_EVENT:
1722
            video_refresh_timer(event.user.data1);
1723
            break;
1724
        default:
1725
            break;
1726
        }
1727
    }
1728
}
1729
1730
void opt_width(const char *arg)
1731
{
1732
    screen_width = atoi(arg);
1733
}
1734
1735
void opt_height(const char *arg)
1736
{
1737
    screen_height = atoi(arg);
1738
}
1739
1740
static void opt_format(const char *arg)
1741
{
1742
    file_iformat = av_find_input_format(arg);
1743
    if (!file_iformat) {
1744
        fprintf(stderr, "Unknown input format: %s\n", arg);
1745
        exit(1);
1746
    }
1747
}
1748 61890b02 Fabrice Bellard
1749
static void opt_image_format(const char *arg)
1750
{
1751
    AVImageFormat *f;
1752
    
1753
    for(f = first_image_format; f != NULL; f = f->next) {
1754
        if (!strcmp(arg, f->name))
1755
            break;
1756
    }
1757
    if (!f) {
1758
        fprintf(stderr, "Unknown image format: '%s'\n", arg);
1759
        exit(1);
1760
    }
1761
    image_format = f;
1762
}
1763
1764 400738b1 Michael Niedermayer
#ifdef CONFIG_NETWORK
1765 416e3508 Fabrice Bellard
void opt_rtp_tcp(void)
1766
{
1767
    /* only tcp protocol */
1768
    rtsp_default_protocols = (1 << RTSP_PROTOCOL_RTP_TCP);
1769
}
1770 400738b1 Michael Niedermayer
#endif
1771 416e3508 Fabrice Bellard
1772 638c9d91 Fabrice Bellard
void opt_sync(const char *arg)
1773
{
1774
    if (!strcmp(arg, "audio"))
1775
        av_sync_type = AV_SYNC_AUDIO_MASTER;
1776
    else if (!strcmp(arg, "video"))
1777
        av_sync_type = AV_SYNC_VIDEO_MASTER;
1778
    else if (!strcmp(arg, "ext"))
1779
        av_sync_type = AV_SYNC_EXTERNAL_CLOCK;
1780
    else
1781
        show_help();
1782
}
1783
1784 72ea344b Fabrice Bellard
void opt_seek(const char *arg)
1785
{
1786
    start_time = parse_date(arg, 1);
1787
}
1788
1789 e26a8335 Wolfgang Hesseler
static void opt_debug(const char *arg)
1790
{
1791
    debug = atoi(arg);
1792
}
1793
    
1794 0c9bbaec Wolfgang Hesseler
static void opt_vismv(const char *arg)
1795
{
1796
    debug_mv = atoi(arg);
1797
}
1798 c62c07d3 Michael Niedermayer
1799
static void opt_thread_count(const char *arg)
1800
{
1801
    thread_count= atoi(arg);
1802 2450cff2 Fran├žois Revol
#if !defined(HAVE_THREADS)
1803 c62c07d3 Michael Niedermayer
    fprintf(stderr, "Warning: not compiled with thread support, using thread emulation\n");
1804
#endif
1805
}
1806 0c9bbaec Wolfgang Hesseler
    
1807 01310af2 Fabrice Bellard
const OptionDef options[] = {
1808 e26a8335 Wolfgang Hesseler
    { "h", 0, {(void*)show_help}, "show help" },    
1809 01310af2 Fabrice Bellard
    { "x", HAS_ARG, {(void*)opt_width}, "force displayed width", "width" },
1810
    { "y", HAS_ARG, {(void*)opt_height}, "force displayed height", "height" },
1811 638c9d91 Fabrice Bellard
#if 0
1812
    /* disabled as SDL/X11 does not support it correctly on application launch */
1813
    { "fs", OPT_BOOL, {(void*)&is_full_screen}, "force full screen" },
1814
#endif
1815 01310af2 Fabrice Bellard
    { "an", OPT_BOOL, {(void*)&audio_disable}, "disable audio" },
1816
    { "vn", OPT_BOOL, {(void*)&video_disable}, "disable video" },
1817 72ea344b Fabrice Bellard
    { "ss", HAS_ARG, {(void*)&opt_seek}, "seek to a given position in seconds", "pos" },
1818 01310af2 Fabrice Bellard
    { "nodisp", OPT_BOOL, {(void*)&display_disable}, "disable graphical display" },
1819
    { "f", HAS_ARG, {(void*)opt_format}, "force format", "fmt" },
1820 61890b02 Fabrice Bellard
    { "img", HAS_ARG, {(void*)opt_image_format}, "force image format", "img_fmt" },
1821 01310af2 Fabrice Bellard
    { "stats", OPT_BOOL | OPT_EXPERT, {(void*)&show_status}, "show status", "" },
1822 e26a8335 Wolfgang Hesseler
    { "debug", HAS_ARG | OPT_EXPERT, {(void*)opt_debug}, "print specific debug info", "" },
1823 6387c3e6 Michael Niedermayer
    { "bug", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&workaround_bugs}, "workaround bugs", "" },
1824 0c9bbaec Wolfgang Hesseler
    { "vismv", HAS_ARG | OPT_EXPERT, {(void*)opt_vismv}, "visualize motion vectors", "" },
1825 6fc5b059 Michael Niedermayer
    { "fast", OPT_BOOL | OPT_EXPERT, {(void*)&fast}, "non spec compliant optimizations", "" },
1826 178fcca8 Michael Niedermayer
    { "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&lowres}, "", "" },
1827
    { "idct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&idct}, "set idct algo",  "algo" },
1828 400738b1 Michael Niedermayer
#ifdef CONFIG_NETWORK
1829 416e3508 Fabrice Bellard
    { "rtp_tcp", OPT_EXPERT, {(void*)&opt_rtp_tcp}, "force RTP/TCP protocol usage", "" },
1830 400738b1 Michael Niedermayer
#endif
1831 c62c07d3 Michael Niedermayer
    { "sync", HAS_ARG | OPT_EXPERT, {(void*)opt_sync}, "set audio-video sync. type (type=audio/video/ext)", "type" },
1832
    { "threads", HAS_ARG | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" },
1833 01310af2 Fabrice Bellard
    { NULL, },
1834
};
1835
1836
void show_help(void)
1837
{
1838 02d504a7 Fabrice Bellard
    printf("ffplay version " FFMPEG_VERSION ", Copyright (c) 2003 Fabrice Bellard\n"
1839
           "usage: ffplay [options] input_file\n"
1840 01310af2 Fabrice Bellard
           "Simple media player\n");
1841
    printf("\n");
1842 02d504a7 Fabrice Bellard
    show_help_options(options, "Main options:\n",
1843
                      OPT_EXPERT, 0);
1844
    show_help_options(options, "\nAdvanced options:\n",
1845
                      OPT_EXPERT, OPT_EXPERT);
1846 01310af2 Fabrice Bellard
    printf("\nWhile playing:\n"
1847
           "q, ESC              quit\n"
1848
           "f                   toggle full screen\n"
1849
           "p, SPC              pause\n"
1850 638c9d91 Fabrice Bellard
           "a                   cycle audio channel\n"
1851
           "v                   cycle video channel\n"
1852
           "w                   show audio waves\n"
1853 72ea344b Fabrice Bellard
           "left/right          seek backward/forward 10 seconds\n"
1854
           "down/up             seek backward/forward 1 minute\n"
1855 a11d11aa Michel Bardiaux
           "mouse click         seek to percentage in file corresponding to fraction of width\n"
1856 01310af2 Fabrice Bellard
           );
1857
    exit(1);
1858
}
1859
1860
void parse_arg_file(const char *filename)
1861
{
1862 e8d83e1c Michael Niedermayer
    if (!strcmp(filename, "-"))
1863
                    filename = "pipe:";
1864 01310af2 Fabrice Bellard
    input_filename = filename;
1865
}
1866
1867
/* Called from the main */
1868
int main(int argc, char **argv)
1869
{
1870 638c9d91 Fabrice Bellard
    int flags, w, h;
1871 01310af2 Fabrice Bellard
    
1872
    /* register all codecs, demux and protocols */
1873
    av_register_all();
1874
1875
    parse_options(argc, argv, options);
1876
1877
    if (!input_filename)
1878
        show_help();
1879
1880
    if (display_disable) {
1881
        video_disable = 1;
1882
    }
1883 31319a8c Fabrice Bellard
    flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
1884
#ifndef CONFIG_WIN32
1885
    flags |= SDL_INIT_EVENTTHREAD; /* Not supported on win32 */
1886
#endif
1887 01310af2 Fabrice Bellard
    if (SDL_Init (flags)) {
1888 05ab0b76 Glenn Maynard
        fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
1889 01310af2 Fabrice Bellard
        exit(1);
1890
    }
1891
1892
    if (!display_disable) {
1893
#ifdef HAVE_X11
1894
        /* save the screen resolution... SDL should allow full screen
1895
           by resizing the window */
1896
        {
1897
            Display *dpy;
1898
            dpy = XOpenDisplay(NULL);
1899
            if (dpy) {
1900
                fs_screen_width = DisplayWidth(dpy, DefaultScreen(dpy));
1901
                fs_screen_height = DisplayHeight(dpy, DefaultScreen(dpy));
1902
                XCloseDisplay(dpy);
1903
            }
1904
        }
1905
#endif
1906 638c9d91 Fabrice Bellard
        flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
1907
        if (is_full_screen && fs_screen_width) {
1908
            w = fs_screen_width;
1909
            h = fs_screen_height;
1910
            flags |= SDL_FULLSCREEN;
1911
        } else {
1912
            w = screen_width;
1913
            h = screen_height;
1914
            flags |= SDL_RESIZABLE;
1915
        }
1916
        screen = SDL_SetVideoMode(w, h, 0, flags);
1917
        if (!screen) {
1918
            fprintf(stderr, "SDL: could not set video mode - exiting\n");
1919
            exit(1);
1920
        }
1921
        SDL_WM_SetCaption("FFplay", "FFplay");
1922 01310af2 Fabrice Bellard
    }
1923
1924
    SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
1925
    SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
1926
    SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
1927
    SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
1928
1929 638c9d91 Fabrice Bellard
    cur_stream = stream_open(input_filename, file_iformat);
1930 01310af2 Fabrice Bellard
1931
    event_loop();
1932
1933
    /* never returns */
1934
1935
    return 0;
1936
}