Statistics
| Branch: | Revision:

ffmpeg / ffplay.c @ 8a01fc47

History | View | Annotate | Download (56.6 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 01310af2 Fabrice Bellard
        if (is->video_st->codec.codec_id == CODEC_ID_RAWVIDEO) {
903 72ea344b Fabrice Bellard
            avpicture_fill((AVPicture *)frame, pkt->data, 
904 01310af2 Fabrice Bellard
                           is->video_st->codec.pix_fmt,
905
                           is->video_st->codec.width,
906
                           is->video_st->codec.height);
907 c6b1edc9 Michael Niedermayer
            frame->pict_type = FF_I_TYPE;
908
            if (output_picture2(is, frame, pts) < 0)
909 01310af2 Fabrice Bellard
                goto the_end;
910
        } else {
911 72ea344b Fabrice Bellard
            len1 = avcodec_decode_video(&is->video_st->codec, 
912
                                        frame, &got_picture, 
913
                                        pkt->data, pkt->size);
914 fb966f99 Michael Niedermayer
//            if (len1 < 0)
915
//                break;
916 72ea344b Fabrice Bellard
            if (got_picture) {
917
                if (output_picture2(is, frame, pts) < 0)
918
                    goto the_end;
919 01310af2 Fabrice Bellard
            }
920
        }
921
        av_free_packet(pkt);
922 bba04f1e Wolfgang Hesseler
        if (step) 
923
            if (cur_stream)
924
                stream_pause(cur_stream);
925 01310af2 Fabrice Bellard
    }
926
 the_end:
927 c6b1edc9 Michael Niedermayer
    av_free(frame);
928 01310af2 Fabrice Bellard
    return 0;
929
}
930
931
/* copy samples for viewing in editor window */
932
static void update_sample_display(VideoState *is, short *samples, int samples_size)
933
{
934
    int size, len, channels;
935
936
    channels = is->audio_st->codec.channels;
937
938
    size = samples_size / sizeof(short);
939
    while (size > 0) {
940
        len = SAMPLE_ARRAY_SIZE - is->sample_array_index;
941
        if (len > size)
942
            len = size;
943
        memcpy(is->sample_array + is->sample_array_index, samples, len * sizeof(short));
944
        samples += len;
945
        is->sample_array_index += len;
946
        if (is->sample_array_index >= SAMPLE_ARRAY_SIZE)
947
            is->sample_array_index = 0;
948
        size -= len;
949
    }
950
}
951
952
/* return the new audio buffer size (samples can be added or deleted
953
   to get better sync if video or external master clock) */
954
static int synchronize_audio(VideoState *is, short *samples, 
955 638c9d91 Fabrice Bellard
                             int samples_size1, double pts)
956 01310af2 Fabrice Bellard
{
957 638c9d91 Fabrice Bellard
    int n, samples_size;
958 01310af2 Fabrice Bellard
    double ref_clock;
959
    
960
    n = 2 * is->audio_st->codec.channels;
961 638c9d91 Fabrice Bellard
    samples_size = samples_size1;
962 01310af2 Fabrice Bellard
963
    /* if not master, then we try to remove or add samples to correct the clock */
964
    if (((is->av_sync_type == AV_SYNC_VIDEO_MASTER && is->video_st) ||
965 638c9d91 Fabrice Bellard
         is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
966
        double diff, avg_diff;
967 01310af2 Fabrice Bellard
        int wanted_size, min_size, max_size, nb_samples;
968 638c9d91 Fabrice Bellard
            
969
        ref_clock = get_master_clock(is);
970
        diff = get_audio_clock(is) - ref_clock;
971 01310af2 Fabrice Bellard
        
972 638c9d91 Fabrice Bellard
        if (diff < AV_NOSYNC_THRESHOLD) {
973
            is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum;
974
            if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {
975
                /* not enough measures to have a correct estimate */
976
                is->audio_diff_avg_count++;
977
            } else {
978
                /* estimate the A-V difference */
979
                avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef);
980
981
                if (fabs(avg_diff) >= is->audio_diff_threshold) {
982
                    wanted_size = samples_size + ((int)(diff * is->audio_st->codec.sample_rate) * n);
983
                    nb_samples = samples_size / n;
984
                
985
                    min_size = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
986
                    max_size = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
987
                    if (wanted_size < min_size)
988
                        wanted_size = min_size;
989
                    else if (wanted_size > max_size)
990
                        wanted_size = max_size;
991
                    
992
                    /* add or remove samples to correction the synchro */
993
                    if (wanted_size < samples_size) {
994
                        /* remove samples */
995
                        samples_size = wanted_size;
996
                    } else if (wanted_size > samples_size) {
997
                        uint8_t *samples_end, *q;
998
                        int nb;
999
                        
1000
                        /* add samples */
1001
                        nb = (samples_size - wanted_size);
1002
                        samples_end = (uint8_t *)samples + samples_size - n;
1003
                        q = samples_end + n;
1004
                        while (nb > 0) {
1005
                            memcpy(q, samples_end, n);
1006
                            q += n;
1007
                            nb -= n;
1008
                        }
1009
                        samples_size = wanted_size;
1010
                    }
1011
                }
1012
#if 0
1013
                printf("diff=%f adiff=%f sample_diff=%d apts=%0.3f vpts=%0.3f %f\n", 
1014
                       diff, avg_diff, samples_size - samples_size1, 
1015
                       is->audio_clock, is->video_clock, is->audio_diff_threshold);
1016
#endif
1017 01310af2 Fabrice Bellard
            }
1018 638c9d91 Fabrice Bellard
        } else {
1019
            /* too big difference : may be initial PTS errors, so
1020
               reset A-V filter */
1021
            is->audio_diff_avg_count = 0;
1022
            is->audio_diff_cum = 0;
1023 01310af2 Fabrice Bellard
        }
1024
    }
1025
1026
    return samples_size;
1027
}
1028
1029
/* decode one audio frame and returns its uncompressed size */
1030
static int audio_decode_frame(VideoState *is, uint8_t *audio_buf, double *pts_ptr)
1031
{
1032
    AVPacket *pkt = &is->audio_pkt;
1033 72ea344b Fabrice Bellard
    int n, len1, data_size;
1034 01310af2 Fabrice Bellard
    double pts;
1035
1036
    for(;;) {
1037 72ea344b Fabrice Bellard
        /* NOTE: the audio packet can contain several frames */
1038 01310af2 Fabrice Bellard
        while (is->audio_pkt_size > 0) {
1039
            len1 = avcodec_decode_audio(&is->audio_st->codec, 
1040
                                        (int16_t *)audio_buf, &data_size, 
1041
                                        is->audio_pkt_data, is->audio_pkt_size);
1042 72ea344b Fabrice Bellard
            if (len1 < 0) {
1043
                /* if error, we skip the frame */
1044
                is->audio_pkt_size = 0;
1045 01310af2 Fabrice Bellard
                break;
1046 72ea344b Fabrice Bellard
            }
1047
            
1048 01310af2 Fabrice Bellard
            is->audio_pkt_data += len1;
1049
            is->audio_pkt_size -= len1;
1050 72ea344b Fabrice Bellard
            if (data_size <= 0)
1051
                continue;
1052
            /* if no pts, then compute it */
1053
            pts = is->audio_clock;
1054
            *pts_ptr = pts;
1055
            n = 2 * is->audio_st->codec.channels;
1056
            is->audio_clock += (double)data_size / 
1057
                (double)(n * is->audio_st->codec.sample_rate);
1058 638c9d91 Fabrice Bellard
#if defined(DEBUG_SYNC)
1059 72ea344b Fabrice Bellard
            {
1060
                static double last_clock;
1061
                printf("audio: delay=%0.3f clock=%0.3f pts=%0.3f\n",
1062
                       is->audio_clock - last_clock,
1063
                       is->audio_clock, pts);
1064
                last_clock = is->audio_clock;
1065 01310af2 Fabrice Bellard
            }
1066 72ea344b Fabrice Bellard
#endif
1067
            return data_size;
1068 01310af2 Fabrice Bellard
        }
1069
1070 72ea344b Fabrice Bellard
        /* free the current packet */
1071
        if (pkt->data)
1072 01310af2 Fabrice Bellard
            av_free_packet(pkt);
1073 72ea344b Fabrice Bellard
        
1074
        if (is->paused || is->audioq.abort_request) {
1075
            return -1;
1076
        }
1077
        
1078 01310af2 Fabrice Bellard
        /* read next packet */
1079
        if (packet_queue_get(&is->audioq, pkt, 1) < 0)
1080
            return -1;
1081
        is->audio_pkt_data = pkt->data;
1082
        is->audio_pkt_size = pkt->size;
1083 72ea344b Fabrice Bellard
        
1084
        /* if update the audio clock with the pts */
1085
        if (pkt->pts != AV_NOPTS_VALUE) {
1086
            is->audio_clock = (double)pkt->pts / AV_TIME_BASE;
1087
        }
1088 01310af2 Fabrice Bellard
    }
1089
}
1090
1091 638c9d91 Fabrice Bellard
/* get the current audio output buffer size, in samples. With SDL, we
1092
   cannot have a precise information */
1093
static int audio_write_get_buf_size(VideoState *is)
1094 01310af2 Fabrice Bellard
{
1095 638c9d91 Fabrice Bellard
    return is->audio_hw_buf_size - is->audio_buf_index;
1096 01310af2 Fabrice Bellard
}
1097
1098
1099
/* prepare a new audio buffer */
1100
void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
1101
{
1102
    VideoState *is = opaque;
1103
    int audio_size, len1;
1104
    double pts;
1105
1106
    audio_callback_time = av_gettime();
1107
    
1108
    while (len > 0) {
1109
        if (is->audio_buf_index >= is->audio_buf_size) {
1110
           audio_size = audio_decode_frame(is, is->audio_buf, &pts);
1111
           if (audio_size < 0) {
1112
                /* if error, just output silence */
1113
               is->audio_buf_size = 1024;
1114
               memset(is->audio_buf, 0, is->audio_buf_size);
1115
           } else {
1116
               if (is->show_audio)
1117
                   update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
1118
               audio_size = synchronize_audio(is, (int16_t *)is->audio_buf, audio_size, 
1119
                                              pts);
1120
               is->audio_buf_size = audio_size;
1121
           }
1122
           is->audio_buf_index = 0;
1123
        }
1124
        len1 = is->audio_buf_size - is->audio_buf_index;
1125
        if (len1 > len)
1126
            len1 = len;
1127
        memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
1128
        len -= len1;
1129
        stream += len1;
1130
        is->audio_buf_index += len1;
1131
    }
1132
}
1133
1134
1135
/* open a given stream. Return 0 if OK */
1136
static int stream_component_open(VideoState *is, int stream_index)
1137
{
1138
    AVFormatContext *ic = is->ic;
1139
    AVCodecContext *enc;
1140
    AVCodec *codec;
1141
    SDL_AudioSpec wanted_spec, spec;
1142
1143
    if (stream_index < 0 || stream_index >= ic->nb_streams)
1144
        return -1;
1145
    enc = &ic->streams[stream_index]->codec;
1146
    
1147
    /* prepare audio output */
1148
    if (enc->codec_type == CODEC_TYPE_AUDIO) {
1149
        wanted_spec.freq = enc->sample_rate;
1150
        wanted_spec.format = AUDIO_S16SYS;
1151 638c9d91 Fabrice Bellard
        /* hack for AC3. XXX: suppress that */
1152
        if (enc->channels > 2)
1153
            enc->channels = 2;
1154 01310af2 Fabrice Bellard
        wanted_spec.channels = enc->channels;
1155
        wanted_spec.silence = 0;
1156 638c9d91 Fabrice Bellard
        wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
1157 01310af2 Fabrice Bellard
        wanted_spec.callback = sdl_audio_callback;
1158
        wanted_spec.userdata = is;
1159 638c9d91 Fabrice Bellard
        if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
1160
            fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());
1161 01310af2 Fabrice Bellard
            return -1;
1162 638c9d91 Fabrice Bellard
        }
1163 01310af2 Fabrice Bellard
        is->audio_hw_buf_size = spec.size;
1164
    }
1165
1166
    codec = avcodec_find_decoder(enc->codec_id);
1167 13d1512c Michael Niedermayer
    enc->debug_mv = debug_mv;
1168
    enc->debug = debug;
1169 6387c3e6 Michael Niedermayer
    enc->workaround_bugs = workaround_bugs;
1170 178fcca8 Michael Niedermayer
    enc->lowres = lowres;
1171 61846e9a Michael Niedermayer
    if(lowres) enc->flags |= CODEC_FLAG_EMU_EDGE;
1172 178fcca8 Michael Niedermayer
    enc->idct_algo= idct;
1173 6fc5b059 Michael Niedermayer
    if(fast) enc->flags2 |= CODEC_FLAG2_FAST;
1174 01310af2 Fabrice Bellard
    if (!codec ||
1175
        avcodec_open(enc, codec) < 0)
1176
        return -1;
1177 2450cff2 Fran├žois Revol
#if defined(HAVE_THREADS)
1178 c62c07d3 Michael Niedermayer
    if(thread_count>1)
1179
        avcodec_thread_init(enc, thread_count);
1180
#endif
1181
    enc->thread_count= thread_count;
1182 638c9d91 Fabrice Bellard
    switch(enc->codec_type) {
1183 01310af2 Fabrice Bellard
    case CODEC_TYPE_AUDIO:
1184
        is->audio_stream = stream_index;
1185
        is->audio_st = ic->streams[stream_index];
1186
        is->audio_buf_size = 0;
1187
        is->audio_buf_index = 0;
1188 638c9d91 Fabrice Bellard
1189
        /* init averaging filter */
1190
        is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
1191
        is->audio_diff_avg_count = 0;
1192
        /* since we do not have a precise anough audio fifo fullness,
1193
           we correct audio sync only if larger than this threshold */
1194
        is->audio_diff_threshold = 2.0 * SDL_AUDIO_BUFFER_SIZE / enc->sample_rate;
1195
1196 01310af2 Fabrice Bellard
        memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
1197
        packet_queue_init(&is->audioq);
1198
        SDL_PauseAudio(0);
1199
        break;
1200
    case CODEC_TYPE_VIDEO:
1201
        is->video_stream = stream_index;
1202
        is->video_st = ic->streams[stream_index];
1203
1204 638c9d91 Fabrice Bellard
        is->frame_last_delay = 40e-3;
1205
        is->frame_timer = (double)av_gettime() / 1000000.0;
1206
        is->video_current_pts_time = av_gettime();
1207
1208 01310af2 Fabrice Bellard
        packet_queue_init(&is->videoq);
1209
        is->video_tid = SDL_CreateThread(video_thread, is);
1210
        break;
1211
    default:
1212
        break;
1213
    }
1214
    return 0;
1215
}
1216
1217
static void stream_component_close(VideoState *is, int stream_index)
1218
{
1219
    AVFormatContext *ic = is->ic;
1220
    AVCodecContext *enc;
1221
    
1222
    enc = &ic->streams[stream_index]->codec;
1223
1224
    switch(enc->codec_type) {
1225
    case CODEC_TYPE_AUDIO:
1226
        packet_queue_abort(&is->audioq);
1227
1228
        SDL_CloseAudio();
1229
1230
        packet_queue_end(&is->audioq);
1231
        break;
1232
    case CODEC_TYPE_VIDEO:
1233
        packet_queue_abort(&is->videoq);
1234
1235
        /* note: we also signal this mutex to make sure we deblock the
1236
           video thread in all cases */
1237
        SDL_LockMutex(is->pictq_mutex);
1238
        SDL_CondSignal(is->pictq_cond);
1239
        SDL_UnlockMutex(is->pictq_mutex);
1240
1241
        SDL_WaitThread(is->video_tid, NULL);
1242
1243
        packet_queue_end(&is->videoq);
1244
        break;
1245
    default:
1246
        break;
1247
    }
1248
1249
    avcodec_close(enc);
1250
    switch(enc->codec_type) {
1251
    case CODEC_TYPE_AUDIO:
1252
        is->audio_st = NULL;
1253
        is->audio_stream = -1;
1254
        break;
1255
    case CODEC_TYPE_VIDEO:
1256
        is->video_st = NULL;
1257
        is->video_stream = -1;
1258
        break;
1259
    default:
1260
        break;
1261
    }
1262
}
1263
1264 d0526ecf Fabrice Bellard
void dump_stream_info(AVFormatContext *s)
1265
{
1266
    if (s->track != 0)
1267
        fprintf(stderr, "Track: %d\n", s->track);
1268
    if (s->title[0] != '\0')
1269
        fprintf(stderr, "Title: %s\n", s->title);
1270
    if (s->author[0] != '\0')
1271
        fprintf(stderr, "Author: %s\n", s->author);
1272
    if (s->album[0] != '\0')
1273
        fprintf(stderr, "Album: %s\n", s->album);
1274
    if (s->year != 0)
1275
        fprintf(stderr, "Year: %d\n", s->year);
1276
    if (s->genre[0] != '\0')
1277
        fprintf(stderr, "Genre: %s\n", s->genre);
1278
}
1279
1280 416e3508 Fabrice Bellard
/* since we have only one decoding thread, we can use a global
1281
   variable instead of a thread local variable */
1282
static VideoState *global_video_state;
1283
1284
static int decode_interrupt_cb(void)
1285
{
1286
    return (global_video_state && global_video_state->abort_request);
1287
}
1288 01310af2 Fabrice Bellard
1289
/* this thread gets the stream from the disk or the network */
1290
static int decode_thread(void *arg)
1291
{
1292
    VideoState *is = arg;
1293
    AVFormatContext *ic;
1294 72ea344b Fabrice Bellard
    int err, i, ret, video_index, audio_index, use_play;
1295 01310af2 Fabrice Bellard
    AVPacket pkt1, *pkt = &pkt1;
1296 61890b02 Fabrice Bellard
    AVFormatParameters params, *ap = &params;
1297 01310af2 Fabrice Bellard
1298
    video_index = -1;
1299
    audio_index = -1;
1300
    is->video_stream = -1;
1301
    is->audio_stream = -1;
1302
1303 416e3508 Fabrice Bellard
    global_video_state = is;
1304
    url_set_interrupt_cb(decode_interrupt_cb);
1305
1306 61890b02 Fabrice Bellard
    memset(ap, 0, sizeof(*ap));
1307
    ap->image_format = image_format;
1308 72ea344b Fabrice Bellard
    ap->initial_pause = 1; /* we force a pause when starting an RTSP
1309
                              stream */
1310
    
1311 61890b02 Fabrice Bellard
    err = av_open_input_file(&ic, is->filename, is->iformat, 0, ap);
1312 638c9d91 Fabrice Bellard
    if (err < 0) {
1313
        print_error(is->filename, err);
1314
        ret = -1;
1315
        goto fail;
1316
    }
1317 01310af2 Fabrice Bellard
    is->ic = ic;
1318 72ea344b Fabrice Bellard
#ifdef CONFIG_NETWORK
1319
    use_play = (ic->iformat == &rtsp_demux);
1320
#else
1321
    use_play = 0;
1322
#endif
1323
    if (!use_play) {
1324
        err = av_find_stream_info(ic);
1325
        if (err < 0) {
1326
            fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
1327
            ret = -1;
1328
            goto fail;
1329
        }
1330 638c9d91 Fabrice Bellard
    }
1331 72ea344b Fabrice Bellard
1332
    /* if seeking requested, we execute it */
1333
    if (start_time != AV_NOPTS_VALUE) {
1334
        int64_t timestamp;
1335
1336
        timestamp = start_time;
1337
        /* add the stream start time */
1338
        if (ic->start_time != AV_NOPTS_VALUE)
1339
            timestamp += ic->start_time;
1340 3ba1438d Michael Niedermayer
        ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
1341 72ea344b Fabrice Bellard
        if (ret < 0) {
1342
            fprintf(stderr, "%s: could not seek to position %0.3f\n", 
1343
                    is->filename, (double)timestamp / AV_TIME_BASE);
1344
        }
1345
    }
1346
1347
    /* now we can begin to play (RTSP stream only) */
1348
    av_read_play(ic);
1349
1350
    if (use_play) {
1351
        err = av_find_stream_info(ic);
1352
        if (err < 0) {
1353
            fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
1354
            ret = -1;
1355
            goto fail;
1356
        }
1357
    }
1358
1359 01310af2 Fabrice Bellard
    for(i = 0; i < ic->nb_streams; i++) {
1360
        AVCodecContext *enc = &ic->streams[i]->codec;
1361
        switch(enc->codec_type) {
1362
        case CODEC_TYPE_AUDIO:
1363
            if (audio_index < 0 && !audio_disable)
1364
                audio_index = i;
1365
            break;
1366
        case CODEC_TYPE_VIDEO:
1367
            if (video_index < 0 && !video_disable)
1368
                video_index = i;
1369
            break;
1370
        default:
1371
            break;
1372
        }
1373
    }
1374
    if (show_status) {
1375
        dump_format(ic, 0, is->filename, 0);
1376 d0526ecf Fabrice Bellard
        dump_stream_info(ic);
1377 01310af2 Fabrice Bellard
    }
1378
1379
    /* open the streams */
1380
    if (audio_index >= 0) {
1381
        stream_component_open(is, audio_index);
1382
    }
1383
1384
    if (video_index >= 0) {
1385
        stream_component_open(is, video_index);
1386
    } else {
1387
        if (!display_disable)
1388
            is->show_audio = 1;
1389
    }
1390
1391
    if (is->video_stream < 0 && is->audio_stream < 0) {
1392 638c9d91 Fabrice Bellard
        fprintf(stderr, "%s: could not open codecs\n", is->filename);
1393
        ret = -1;
1394 01310af2 Fabrice Bellard
        goto fail;
1395
    }
1396
1397
    for(;;) {
1398
        if (is->abort_request)
1399
            break;
1400 400738b1 Michael Niedermayer
#ifdef CONFIG_NETWORK
1401 416e3508 Fabrice Bellard
        if (is->paused != is->last_paused) {
1402
            is->last_paused = is->paused;
1403 72ea344b Fabrice Bellard
            if (is->paused)
1404
                av_read_pause(ic);
1405
            else
1406
                av_read_play(ic);
1407 416e3508 Fabrice Bellard
        }
1408
        if (is->paused && ic->iformat == &rtsp_demux) {
1409
            /* wait 10 ms to avoid trying to get another packet */
1410
            /* XXX: horrible */
1411
            SDL_Delay(10);
1412
            continue;
1413
        }
1414 400738b1 Michael Niedermayer
#endif
1415 72ea344b Fabrice Bellard
        if (is->seek_req) {
1416
            /* XXX: must lock decoder threads */
1417 3ba1438d Michael Niedermayer
            ret = av_seek_frame(is->ic, -1, is->seek_pos, is->seek_flags);
1418 72ea344b Fabrice Bellard
            if (ret < 0) {
1419
                fprintf(stderr, "%s: error while seeking\n", is->ic->filename);
1420 e6c0297f Michael Niedermayer
            }else{
1421
                if (is->audio_stream >= 0) {
1422
                    packet_queue_flush(&is->audioq);
1423
                }
1424
                if (is->video_stream >= 0) {
1425
                    packet_queue_flush(&is->videoq);
1426 93e1a0a9 Michael Niedermayer
                    avcodec_flush_buffers(&ic->streams[video_index]->codec);
1427 e6c0297f Michael Niedermayer
                }
1428 72ea344b Fabrice Bellard
            }
1429
            is->seek_req = 0;
1430
        }
1431 416e3508 Fabrice Bellard
1432 01310af2 Fabrice Bellard
        /* if the queue are full, no need to read more */
1433
        if (is->audioq.size > MAX_AUDIOQ_SIZE ||
1434 0c904df2 Michael Niedermayer
            is->videoq.size > MAX_VIDEOQ_SIZE || 
1435
            url_feof(&ic->pb)) {
1436 01310af2 Fabrice Bellard
            /* wait 10 ms */
1437
            SDL_Delay(10);
1438
            continue;
1439
        }
1440 72ea344b Fabrice Bellard
        ret = av_read_frame(ic, pkt);
1441 01310af2 Fabrice Bellard
        if (ret < 0) {
1442 6e1f8725 Roman Shaposhnik
            if (url_feof(&ic->pb) && url_ferror(&ic->pb) == 0) {
1443
                SDL_Delay(100); /* wait for user event */
1444
                continue;
1445
            } else
1446
                break;
1447 01310af2 Fabrice Bellard
        }
1448
        if (pkt->stream_index == is->audio_stream) {
1449
            packet_queue_put(&is->audioq, pkt);
1450
        } else if (pkt->stream_index == is->video_stream) {
1451
            packet_queue_put(&is->videoq, pkt);
1452
        } else {
1453
            av_free_packet(pkt);
1454
        }
1455
    }
1456
    /* wait until the end */
1457
    while (!is->abort_request) {
1458
        SDL_Delay(100);
1459
    }
1460
1461 638c9d91 Fabrice Bellard
    ret = 0;
1462 01310af2 Fabrice Bellard
 fail:
1463 416e3508 Fabrice Bellard
    /* disable interrupting */
1464
    global_video_state = NULL;
1465
1466 01310af2 Fabrice Bellard
    /* close each stream */
1467
    if (is->audio_stream >= 0)
1468
        stream_component_close(is, is->audio_stream);
1469
    if (is->video_stream >= 0)
1470
        stream_component_close(is, is->video_stream);
1471 638c9d91 Fabrice Bellard
    if (is->ic) {
1472
        av_close_input_file(is->ic);
1473
        is->ic = NULL; /* safety */
1474
    }
1475 416e3508 Fabrice Bellard
    url_set_interrupt_cb(NULL);
1476
1477 638c9d91 Fabrice Bellard
    if (ret != 0) {
1478
        SDL_Event event;
1479
        
1480
        event.type = FF_QUIT_EVENT;
1481
        event.user.data1 = is;
1482
        SDL_PushEvent(&event);
1483
    }
1484 01310af2 Fabrice Bellard
    return 0;
1485
}
1486
1487 638c9d91 Fabrice Bellard
static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
1488 01310af2 Fabrice Bellard
{
1489
    VideoState *is;
1490
1491
    is = av_mallocz(sizeof(VideoState));
1492
    if (!is)
1493
        return NULL;
1494
    pstrcpy(is->filename, sizeof(is->filename), filename);
1495 638c9d91 Fabrice Bellard
    is->iformat = iformat;
1496 01310af2 Fabrice Bellard
    if (screen) {
1497
        is->width = screen->w;
1498
        is->height = screen->h;
1499
    }
1500
    is->ytop = 0;
1501
    is->xleft = 0;
1502
1503
    /* start video display */
1504
    is->pictq_mutex = SDL_CreateMutex();
1505
    is->pictq_cond = SDL_CreateCond();
1506
1507
    /* add the refresh timer to draw the picture */
1508
    schedule_refresh(is, 40);
1509
1510 638c9d91 Fabrice Bellard
    is->av_sync_type = av_sync_type;
1511 01310af2 Fabrice Bellard
    is->parse_tid = SDL_CreateThread(decode_thread, is);
1512
    if (!is->parse_tid) {
1513
        av_free(is);
1514
        return NULL;
1515
    }
1516
    return is;
1517
}
1518
1519
static void stream_close(VideoState *is)
1520
{
1521
    VideoPicture *vp;
1522
    int i;
1523
    /* XXX: use a special url_shutdown call to abort parse cleanly */
1524
    is->abort_request = 1;
1525
    SDL_WaitThread(is->parse_tid, NULL);
1526
1527
    /* free all pictures */
1528
    for(i=0;i<VIDEO_PICTURE_QUEUE_SIZE; i++) {
1529
        vp = &is->pictq[i];
1530
        if (vp->bmp) {
1531
            SDL_FreeYUVOverlay(vp->bmp);
1532
            vp->bmp = NULL;
1533
        }
1534
    }
1535
    SDL_DestroyMutex(is->pictq_mutex);
1536
    SDL_DestroyCond(is->pictq_cond);
1537
}
1538
1539 638c9d91 Fabrice Bellard
void stream_cycle_channel(VideoState *is, int codec_type)
1540
{
1541
    AVFormatContext *ic = is->ic;
1542
    int start_index, stream_index;
1543
    AVStream *st;
1544
1545
    if (codec_type == CODEC_TYPE_VIDEO)
1546
        start_index = is->video_stream;
1547
    else
1548
        start_index = is->audio_stream;
1549
    if (start_index < 0)
1550
        return;
1551
    stream_index = start_index;
1552
    for(;;) {
1553
        if (++stream_index >= is->ic->nb_streams)
1554
            stream_index = 0;
1555
        if (stream_index == start_index)
1556
            return;
1557
        st = ic->streams[stream_index];
1558
        if (st->codec.codec_type == codec_type) {
1559
            /* check that parameters are OK */
1560
            switch(codec_type) {
1561
            case CODEC_TYPE_AUDIO:
1562
                if (st->codec.sample_rate != 0 &&
1563
                    st->codec.channels != 0)
1564
                    goto the_end;
1565
                break;
1566
            case CODEC_TYPE_VIDEO:
1567
                goto the_end;
1568
            default:
1569
                break;
1570
            }
1571
        }
1572
    }
1573
 the_end:
1574
    stream_component_close(is, start_index);
1575
    stream_component_open(is, stream_index);
1576
}
1577
1578
1579 01310af2 Fabrice Bellard
void toggle_full_screen(void)
1580
{
1581
    int w, h, flags;
1582
    is_full_screen = !is_full_screen;
1583
    if (!fs_screen_width) {
1584
        /* use default SDL method */
1585
        SDL_WM_ToggleFullScreen(screen);
1586
    } else {
1587
        /* use the recorded resolution */
1588
        flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
1589
        if (is_full_screen) {
1590
            w = fs_screen_width;
1591
            h = fs_screen_height;
1592
            flags |= SDL_FULLSCREEN;
1593
        } else {
1594
            w = screen_width;
1595
            h = screen_height;
1596
            flags |= SDL_RESIZABLE;
1597
        }
1598
        screen = SDL_SetVideoMode(w, h, 0, flags);
1599
        cur_stream->width = w;
1600
        cur_stream->height = h;
1601
    }
1602
}
1603
1604
void toggle_pause(void)
1605
{
1606
    if (cur_stream)
1607
        stream_pause(cur_stream);
1608 bba04f1e Wolfgang Hesseler
    step = 0;
1609
}
1610
1611
void step_to_next_frame(void)
1612
{
1613
    if (cur_stream) {
1614
        if (cur_stream->paused)
1615
            cur_stream->paused=0;
1616
        cur_stream->video_current_pts = get_video_clock(cur_stream);
1617
    }
1618
    step = 1;
1619 01310af2 Fabrice Bellard
}
1620
1621
void do_exit(void)
1622
{
1623
    if (cur_stream) {
1624
        stream_close(cur_stream);
1625
        cur_stream = NULL;
1626
    }
1627
    if (show_status)
1628
        printf("\n");
1629
    SDL_Quit();
1630
    exit(0);
1631
}
1632
1633
void toggle_audio_display(void)
1634
{
1635
    if (cur_stream) {
1636
        cur_stream->show_audio = !cur_stream->show_audio;
1637
    }
1638
}
1639
1640
/* handle an event sent by the GUI */
1641
void event_loop(void)
1642
{
1643
    SDL_Event event;
1644 a11d11aa Michel Bardiaux
    double incr, pos, frac;
1645 01310af2 Fabrice Bellard
1646
    for(;;) {
1647
        SDL_WaitEvent(&event);
1648
        switch(event.type) {
1649
        case SDL_KEYDOWN:
1650
            switch(event.key.keysym.sym) {
1651
            case SDLK_ESCAPE:
1652
            case SDLK_q:
1653
                do_exit();
1654
                break;
1655
            case SDLK_f:
1656
                toggle_full_screen();
1657
                break;
1658
            case SDLK_p:
1659
            case SDLK_SPACE:
1660
                toggle_pause();
1661
                break;
1662 bba04f1e Wolfgang Hesseler
            case SDLK_s: //S: Step to next frame
1663
                step_to_next_frame();
1664
                break;
1665 01310af2 Fabrice Bellard
            case SDLK_a:
1666 638c9d91 Fabrice Bellard
                if (cur_stream) 
1667
                    stream_cycle_channel(cur_stream, CODEC_TYPE_AUDIO);
1668
                break;
1669
            case SDLK_v:
1670
                if (cur_stream) 
1671
                    stream_cycle_channel(cur_stream, CODEC_TYPE_VIDEO);
1672
                break;
1673
            case SDLK_w:
1674 01310af2 Fabrice Bellard
                toggle_audio_display();
1675
                break;
1676 72ea344b Fabrice Bellard
            case SDLK_LEFT:
1677
                incr = -10.0;
1678
                goto do_seek;
1679
            case SDLK_RIGHT:
1680
                incr = 10.0;
1681
                goto do_seek;
1682
            case SDLK_UP:
1683
                incr = 60.0;
1684
                goto do_seek;
1685
            case SDLK_DOWN:
1686
                incr = -60.0;
1687
            do_seek:
1688
                if (cur_stream) {
1689
                    pos = get_master_clock(cur_stream);
1690
                    pos += incr;
1691 3ba1438d Michael Niedermayer
                    stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), incr);
1692 72ea344b Fabrice Bellard
                }
1693
                break;
1694 01310af2 Fabrice Bellard
            default:
1695
                break;
1696
            }
1697
            break;
1698 a11d11aa Michel Bardiaux
        case SDL_MOUSEBUTTONDOWN:
1699
            if (cur_stream) {
1700
                int ns, hh, mm, ss;
1701
                int tns, thh, tmm, tss;
1702
                tns = cur_stream->ic->duration/1000000LL;
1703
                thh = tns/3600;
1704
                tmm = (tns%3600)/60;
1705
                tss = (tns%60);
1706
                frac = (double)event.button.x/(double)cur_stream->width;
1707
                ns = frac*tns;
1708
                hh = ns/3600;
1709
                mm = (ns%3600)/60;
1710
                ss = (ns%60);
1711
                fprintf(stderr, "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d)       \n", frac*100,
1712
                        hh, mm, ss, thh, tmm, tss);
1713 3ba1438d Michael Niedermayer
                stream_seek(cur_stream, (int64_t)(cur_stream->ic->start_time+frac*cur_stream->ic->duration), 0);
1714 a11d11aa Michel Bardiaux
            }
1715
            break;
1716 01310af2 Fabrice Bellard
        case SDL_VIDEORESIZE:
1717
            if (cur_stream) {
1718
                screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0, 
1719
                                          SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL);
1720
                cur_stream->width = event.resize.w;
1721
                cur_stream->height = event.resize.h;
1722
            }
1723
            break;
1724
        case SDL_QUIT:
1725 638c9d91 Fabrice Bellard
        case FF_QUIT_EVENT:
1726 01310af2 Fabrice Bellard
            do_exit();
1727
            break;
1728
        case FF_ALLOC_EVENT:
1729
            alloc_picture(event.user.data1);
1730
            break;
1731
        case FF_REFRESH_EVENT:
1732
            video_refresh_timer(event.user.data1);
1733
            break;
1734
        default:
1735
            break;
1736
        }
1737
    }
1738
}
1739
1740
void opt_width(const char *arg)
1741
{
1742
    screen_width = atoi(arg);
1743
}
1744
1745
void opt_height(const char *arg)
1746
{
1747
    screen_height = atoi(arg);
1748
}
1749
1750
static void opt_format(const char *arg)
1751
{
1752
    file_iformat = av_find_input_format(arg);
1753
    if (!file_iformat) {
1754
        fprintf(stderr, "Unknown input format: %s\n", arg);
1755
        exit(1);
1756
    }
1757
}
1758 61890b02 Fabrice Bellard
1759
static void opt_image_format(const char *arg)
1760
{
1761
    AVImageFormat *f;
1762
    
1763
    for(f = first_image_format; f != NULL; f = f->next) {
1764
        if (!strcmp(arg, f->name))
1765
            break;
1766
    }
1767
    if (!f) {
1768
        fprintf(stderr, "Unknown image format: '%s'\n", arg);
1769
        exit(1);
1770
    }
1771
    image_format = f;
1772
}
1773
1774 400738b1 Michael Niedermayer
#ifdef CONFIG_NETWORK
1775 416e3508 Fabrice Bellard
void opt_rtp_tcp(void)
1776
{
1777
    /* only tcp protocol */
1778
    rtsp_default_protocols = (1 << RTSP_PROTOCOL_RTP_TCP);
1779
}
1780 400738b1 Michael Niedermayer
#endif
1781 416e3508 Fabrice Bellard
1782 638c9d91 Fabrice Bellard
void opt_sync(const char *arg)
1783
{
1784
    if (!strcmp(arg, "audio"))
1785
        av_sync_type = AV_SYNC_AUDIO_MASTER;
1786
    else if (!strcmp(arg, "video"))
1787
        av_sync_type = AV_SYNC_VIDEO_MASTER;
1788
    else if (!strcmp(arg, "ext"))
1789
        av_sync_type = AV_SYNC_EXTERNAL_CLOCK;
1790
    else
1791
        show_help();
1792
}
1793
1794 72ea344b Fabrice Bellard
void opt_seek(const char *arg)
1795
{
1796
    start_time = parse_date(arg, 1);
1797
}
1798
1799 e26a8335 Wolfgang Hesseler
static void opt_debug(const char *arg)
1800
{
1801
    debug = atoi(arg);
1802
}
1803
    
1804 0c9bbaec Wolfgang Hesseler
static void opt_vismv(const char *arg)
1805
{
1806
    debug_mv = atoi(arg);
1807
}
1808 c62c07d3 Michael Niedermayer
1809
static void opt_thread_count(const char *arg)
1810
{
1811
    thread_count= atoi(arg);
1812 2450cff2 Fran├žois Revol
#if !defined(HAVE_THREADS)
1813 c62c07d3 Michael Niedermayer
    fprintf(stderr, "Warning: not compiled with thread support, using thread emulation\n");
1814
#endif
1815
}
1816 0c9bbaec Wolfgang Hesseler
    
1817 01310af2 Fabrice Bellard
const OptionDef options[] = {
1818 e26a8335 Wolfgang Hesseler
    { "h", 0, {(void*)show_help}, "show help" },    
1819 01310af2 Fabrice Bellard
    { "x", HAS_ARG, {(void*)opt_width}, "force displayed width", "width" },
1820
    { "y", HAS_ARG, {(void*)opt_height}, "force displayed height", "height" },
1821 638c9d91 Fabrice Bellard
#if 0
1822
    /* disabled as SDL/X11 does not support it correctly on application launch */
1823
    { "fs", OPT_BOOL, {(void*)&is_full_screen}, "force full screen" },
1824
#endif
1825 01310af2 Fabrice Bellard
    { "an", OPT_BOOL, {(void*)&audio_disable}, "disable audio" },
1826
    { "vn", OPT_BOOL, {(void*)&video_disable}, "disable video" },
1827 72ea344b Fabrice Bellard
    { "ss", HAS_ARG, {(void*)&opt_seek}, "seek to a given position in seconds", "pos" },
1828 01310af2 Fabrice Bellard
    { "nodisp", OPT_BOOL, {(void*)&display_disable}, "disable graphical display" },
1829
    { "f", HAS_ARG, {(void*)opt_format}, "force format", "fmt" },
1830 61890b02 Fabrice Bellard
    { "img", HAS_ARG, {(void*)opt_image_format}, "force image format", "img_fmt" },
1831 01310af2 Fabrice Bellard
    { "stats", OPT_BOOL | OPT_EXPERT, {(void*)&show_status}, "show status", "" },
1832 e26a8335 Wolfgang Hesseler
    { "debug", HAS_ARG | OPT_EXPERT, {(void*)opt_debug}, "print specific debug info", "" },
1833 6387c3e6 Michael Niedermayer
    { "bug", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&workaround_bugs}, "workaround bugs", "" },
1834 0c9bbaec Wolfgang Hesseler
    { "vismv", HAS_ARG | OPT_EXPERT, {(void*)opt_vismv}, "visualize motion vectors", "" },
1835 6fc5b059 Michael Niedermayer
    { "fast", OPT_BOOL | OPT_EXPERT, {(void*)&fast}, "non spec compliant optimizations", "" },
1836 178fcca8 Michael Niedermayer
    { "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&lowres}, "", "" },
1837
    { "idct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&idct}, "set idct algo",  "algo" },
1838 400738b1 Michael Niedermayer
#ifdef CONFIG_NETWORK
1839 416e3508 Fabrice Bellard
    { "rtp_tcp", OPT_EXPERT, {(void*)&opt_rtp_tcp}, "force RTP/TCP protocol usage", "" },
1840 400738b1 Michael Niedermayer
#endif
1841 c62c07d3 Michael Niedermayer
    { "sync", HAS_ARG | OPT_EXPERT, {(void*)opt_sync}, "set audio-video sync. type (type=audio/video/ext)", "type" },
1842
    { "threads", HAS_ARG | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" },
1843 01310af2 Fabrice Bellard
    { NULL, },
1844
};
1845
1846
void show_help(void)
1847
{
1848 02d504a7 Fabrice Bellard
    printf("ffplay version " FFMPEG_VERSION ", Copyright (c) 2003 Fabrice Bellard\n"
1849
           "usage: ffplay [options] input_file\n"
1850 01310af2 Fabrice Bellard
           "Simple media player\n");
1851
    printf("\n");
1852 02d504a7 Fabrice Bellard
    show_help_options(options, "Main options:\n",
1853
                      OPT_EXPERT, 0);
1854
    show_help_options(options, "\nAdvanced options:\n",
1855
                      OPT_EXPERT, OPT_EXPERT);
1856 01310af2 Fabrice Bellard
    printf("\nWhile playing:\n"
1857
           "q, ESC              quit\n"
1858
           "f                   toggle full screen\n"
1859
           "p, SPC              pause\n"
1860 638c9d91 Fabrice Bellard
           "a                   cycle audio channel\n"
1861
           "v                   cycle video channel\n"
1862
           "w                   show audio waves\n"
1863 72ea344b Fabrice Bellard
           "left/right          seek backward/forward 10 seconds\n"
1864
           "down/up             seek backward/forward 1 minute\n"
1865 a11d11aa Michel Bardiaux
           "mouse click         seek to percentage in file corresponding to fraction of width\n"
1866 01310af2 Fabrice Bellard
           );
1867
    exit(1);
1868
}
1869
1870
void parse_arg_file(const char *filename)
1871
{
1872 e8d83e1c Michael Niedermayer
    if (!strcmp(filename, "-"))
1873
                    filename = "pipe:";
1874 01310af2 Fabrice Bellard
    input_filename = filename;
1875
}
1876
1877
/* Called from the main */
1878
int main(int argc, char **argv)
1879
{
1880 638c9d91 Fabrice Bellard
    int flags, w, h;
1881 01310af2 Fabrice Bellard
    
1882
    /* register all codecs, demux and protocols */
1883
    av_register_all();
1884
1885
    parse_options(argc, argv, options);
1886
1887
    if (!input_filename)
1888
        show_help();
1889
1890
    if (display_disable) {
1891
        video_disable = 1;
1892
    }
1893 31319a8c Fabrice Bellard
    flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
1894
#ifndef CONFIG_WIN32
1895
    flags |= SDL_INIT_EVENTTHREAD; /* Not supported on win32 */
1896
#endif
1897 01310af2 Fabrice Bellard
    if (SDL_Init (flags)) {
1898 05ab0b76 Glenn Maynard
        fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
1899 01310af2 Fabrice Bellard
        exit(1);
1900
    }
1901
1902
    if (!display_disable) {
1903
#ifdef HAVE_X11
1904
        /* save the screen resolution... SDL should allow full screen
1905
           by resizing the window */
1906
        {
1907
            Display *dpy;
1908
            dpy = XOpenDisplay(NULL);
1909
            if (dpy) {
1910
                fs_screen_width = DisplayWidth(dpy, DefaultScreen(dpy));
1911
                fs_screen_height = DisplayHeight(dpy, DefaultScreen(dpy));
1912
                XCloseDisplay(dpy);
1913
            }
1914
        }
1915
#endif
1916 638c9d91 Fabrice Bellard
        flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
1917
        if (is_full_screen && fs_screen_width) {
1918
            w = fs_screen_width;
1919
            h = fs_screen_height;
1920
            flags |= SDL_FULLSCREEN;
1921
        } else {
1922
            w = screen_width;
1923
            h = screen_height;
1924
            flags |= SDL_RESIZABLE;
1925
        }
1926
        screen = SDL_SetVideoMode(w, h, 0, flags);
1927
        if (!screen) {
1928
            fprintf(stderr, "SDL: could not set video mode - exiting\n");
1929
            exit(1);
1930
        }
1931
        SDL_WM_SetCaption("FFplay", "FFplay");
1932 01310af2 Fabrice Bellard
    }
1933
1934
    SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
1935
    SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
1936
    SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
1937
    SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
1938
1939 638c9d91 Fabrice Bellard
    cur_stream = stream_open(input_filename, file_iformat);
1940 01310af2 Fabrice Bellard
1941
    event_loop();
1942
1943
    /* never returns */
1944
1945
    return 0;
1946
}