ffplay.c

Go to the documentation of this file.
00001 /*
00002  * FFplay : Simple Media Player based on the ffmpeg libraries
00003  * Copyright (c) 2003 Fabrice Bellard
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00022 #include <math.h>
00023 #include <limits.h>
00024 #include "libavutil/avstring.h"
00025 #include "libavformat/avformat.h"
00026 #include "libavformat/rtsp.h"
00027 #include "libavdevice/avdevice.h"
00028 #include "libswscale/swscale.h"
00029 
00030 #include "cmdutils.h"
00031 
00032 #include <SDL.h>
00033 #include <SDL_thread.h>
00034 
00035 #ifdef __MINGW32__
00036 #undef main /* We don't want SDL to override our main() */
00037 #endif
00038 
00039 #undef exit
00040 
00041 const char program_name[] = "FFplay";
00042 const int program_birth_year = 2003;
00043 
00044 //#define DEBUG_SYNC
00045 
00046 #define MAX_VIDEOQ_SIZE (5 * 256 * 1024)
00047 #define MAX_AUDIOQ_SIZE (5 * 16 * 1024)
00048 #define MAX_SUBTITLEQ_SIZE (5 * 16 * 1024)
00049 
00050 /* SDL audio buffer size, in samples. Should be small to have precise
00051    A/V sync as SDL does not have hardware buffer fullness info. */
00052 #define SDL_AUDIO_BUFFER_SIZE 1024
00053 
00054 /* no AV sync correction is done if below the AV sync threshold */
00055 #define AV_SYNC_THRESHOLD 0.01
00056 /* no AV correction is done if too big error */
00057 #define AV_NOSYNC_THRESHOLD 10.0
00058 
00059 /* maximum audio speed change to get correct sync */
00060 #define SAMPLE_CORRECTION_PERCENT_MAX 10
00061 
00062 /* we use about AUDIO_DIFF_AVG_NB A-V differences to make the average */
00063 #define AUDIO_DIFF_AVG_NB   20
00064 
00065 /* NOTE: the size must be big enough to compensate the hardware audio buffersize size */
00066 #define SAMPLE_ARRAY_SIZE (2*65536)
00067 
00068 static int sws_flags = SWS_BICUBIC;
00069 
00070 typedef struct PacketQueue {
00071     AVPacketList *first_pkt, *last_pkt;
00072     int nb_packets;
00073     int size;
00074     int abort_request;
00075     SDL_mutex *mutex;
00076     SDL_cond *cond;
00077 } PacketQueue;
00078 
00079 #define VIDEO_PICTURE_QUEUE_SIZE 1
00080 #define SUBPICTURE_QUEUE_SIZE 4
00081 
00082 typedef struct VideoPicture {
00083     double pts;                                  ///<presentation time stamp for this picture
00084     SDL_Overlay *bmp;
00085     int width, height; /* source height & width */
00086     int allocated;
00087 } VideoPicture;
00088 
00089 typedef struct SubPicture {
00090     double pts; /* presentation time stamp for this picture */
00091     AVSubtitle sub;
00092 } SubPicture;
00093 
00094 enum {
00095     AV_SYNC_AUDIO_MASTER, /* default choice */
00096     AV_SYNC_VIDEO_MASTER,
00097     AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */
00098 };
00099 
00100 typedef struct VideoState {
00101     SDL_Thread *parse_tid;
00102     SDL_Thread *video_tid;
00103     AVInputFormat *iformat;
00104     int no_background;
00105     int abort_request;
00106     int paused;
00107     int last_paused;
00108     int seek_req;
00109     int seek_flags;
00110     int64_t seek_pos;
00111     AVFormatContext *ic;
00112     int dtg_active_format;
00113 
00114     int audio_stream;
00115 
00116     int av_sync_type;
00117     double external_clock; /* external clock base */
00118     int64_t external_clock_time;
00119 
00120     double audio_clock;
00121     double audio_diff_cum; /* used for AV difference average computation */
00122     double audio_diff_avg_coef;
00123     double audio_diff_threshold;
00124     int audio_diff_avg_count;
00125     AVStream *audio_st;
00126     PacketQueue audioq;
00127     int audio_hw_buf_size;
00128     /* samples output by the codec. we reserve more space for avsync
00129        compensation */
00130     DECLARE_ALIGNED(16,uint8_t,audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2]);
00131     unsigned int audio_buf_size; /* in bytes */
00132     int audio_buf_index; /* in bytes */
00133     AVPacket audio_pkt;
00134     uint8_t *audio_pkt_data;
00135     int audio_pkt_size;
00136 
00137     int show_audio; /* if true, display audio samples */
00138     int16_t sample_array[SAMPLE_ARRAY_SIZE];
00139     int sample_array_index;
00140     int last_i_start;
00141 
00142     SDL_Thread *subtitle_tid;
00143     int subtitle_stream;
00144     int subtitle_stream_changed;
00145     AVStream *subtitle_st;
00146     PacketQueue subtitleq;
00147     SubPicture subpq[SUBPICTURE_QUEUE_SIZE];
00148     int subpq_size, subpq_rindex, subpq_windex;
00149     SDL_mutex *subpq_mutex;
00150     SDL_cond *subpq_cond;
00151 
00152     double frame_timer;
00153     double frame_last_pts;
00154     double frame_last_delay;
00155     double video_clock;                          ///<pts of last decoded frame / predicted pts of next decoded frame
00156     int video_stream;
00157     AVStream *video_st;
00158     PacketQueue videoq;
00159     double video_current_pts;                    ///<current displayed pts (different from video_clock if frame fifos are used)
00160     int64_t video_current_pts_time;              ///<time (av_gettime) at which we updated video_current_pts - used to have running video pts
00161     VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
00162     int pictq_size, pictq_rindex, pictq_windex;
00163     SDL_mutex *pictq_mutex;
00164     SDL_cond *pictq_cond;
00165 
00166     //    QETimer *video_timer;
00167     char filename[1024];
00168     int width, height, xleft, ytop;
00169 } VideoState;
00170 
00171 static void show_help(void);
00172 static int audio_write_get_buf_size(VideoState *is);
00173 
00174 /* options specified by the user */
00175 static AVInputFormat *file_iformat;
00176 static const char *input_filename;
00177 static int fs_screen_width;
00178 static int fs_screen_height;
00179 static int screen_width = 0;
00180 static int screen_height = 0;
00181 static int frame_width = 0;
00182 static int frame_height = 0;
00183 static enum PixelFormat frame_pix_fmt = PIX_FMT_NONE;
00184 static int audio_disable;
00185 static int video_disable;
00186 static int wanted_audio_stream= 0;
00187 static int wanted_video_stream= 0;
00188 static int seek_by_bytes;
00189 static int display_disable;
00190 static int show_status;
00191 static int av_sync_type = AV_SYNC_AUDIO_MASTER;
00192 static int64_t start_time = AV_NOPTS_VALUE;
00193 static int debug = 0;
00194 static int debug_mv = 0;
00195 static int step = 0;
00196 static int thread_count = 1;
00197 static int workaround_bugs = 1;
00198 static int fast = 0;
00199 static int genpts = 0;
00200 static int lowres = 0;
00201 static int idct = FF_IDCT_AUTO;
00202 static enum AVDiscard skip_frame= AVDISCARD_DEFAULT;
00203 static enum AVDiscard skip_idct= AVDISCARD_DEFAULT;
00204 static enum AVDiscard skip_loop_filter= AVDISCARD_DEFAULT;
00205 static int error_resilience = FF_ER_CAREFUL;
00206 static int error_concealment = 3;
00207 static int decoder_reorder_pts= 0;
00208 
00209 /* current context */
00210 static int is_full_screen;
00211 static VideoState *cur_stream;
00212 static int64_t audio_callback_time;
00213 
00214 AVPacket flush_pkt;
00215 
00216 #define FF_ALLOC_EVENT   (SDL_USEREVENT)
00217 #define FF_REFRESH_EVENT (SDL_USEREVENT + 1)
00218 #define FF_QUIT_EVENT    (SDL_USEREVENT + 2)
00219 
00220 SDL_Surface *screen;
00221 
00222 /* packet queue handling */
00223 static void packet_queue_init(PacketQueue *q)
00224 {
00225     memset(q, 0, sizeof(PacketQueue));
00226     q->mutex = SDL_CreateMutex();
00227     q->cond = SDL_CreateCond();
00228 }
00229 
00230 static void packet_queue_flush(PacketQueue *q)
00231 {
00232     AVPacketList *pkt, *pkt1;
00233 
00234     SDL_LockMutex(q->mutex);
00235     for(pkt = q->first_pkt; pkt != NULL; pkt = pkt1) {
00236         pkt1 = pkt->next;
00237         av_free_packet(&pkt->pkt);
00238         av_freep(&pkt);
00239     }
00240     q->last_pkt = NULL;
00241     q->first_pkt = NULL;
00242     q->nb_packets = 0;
00243     q->size = 0;
00244     SDL_UnlockMutex(q->mutex);
00245 }
00246 
00247 static void packet_queue_end(PacketQueue *q)
00248 {
00249     packet_queue_flush(q);
00250     SDL_DestroyMutex(q->mutex);
00251     SDL_DestroyCond(q->cond);
00252 }
00253 
00254 static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
00255 {
00256     AVPacketList *pkt1;
00257 
00258     /* duplicate the packet */
00259     if (pkt!=&flush_pkt && av_dup_packet(pkt) < 0)
00260         return -1;
00261 
00262     pkt1 = av_malloc(sizeof(AVPacketList));
00263     if (!pkt1)
00264         return -1;
00265     pkt1->pkt = *pkt;
00266     pkt1->next = NULL;
00267 
00268 
00269     SDL_LockMutex(q->mutex);
00270 
00271     if (!q->last_pkt)
00272 
00273         q->first_pkt = pkt1;
00274     else
00275         q->last_pkt->next = pkt1;
00276     q->last_pkt = pkt1;
00277     q->nb_packets++;
00278     q->size += pkt1->pkt.size;
00279     /* XXX: should duplicate packet data in DV case */
00280     SDL_CondSignal(q->cond);
00281 
00282     SDL_UnlockMutex(q->mutex);
00283     return 0;
00284 }
00285 
00286 static void packet_queue_abort(PacketQueue *q)
00287 {
00288     SDL_LockMutex(q->mutex);
00289 
00290     q->abort_request = 1;
00291 
00292     SDL_CondSignal(q->cond);
00293 
00294     SDL_UnlockMutex(q->mutex);
00295 }
00296 
00297 /* return < 0 if aborted, 0 if no packet and > 0 if packet.  */
00298 static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
00299 {
00300     AVPacketList *pkt1;
00301     int ret;
00302 
00303     SDL_LockMutex(q->mutex);
00304 
00305     for(;;) {
00306         if (q->abort_request) {
00307             ret = -1;
00308             break;
00309         }
00310 
00311         pkt1 = q->first_pkt;
00312         if (pkt1) {
00313             q->first_pkt = pkt1->next;
00314             if (!q->first_pkt)
00315                 q->last_pkt = NULL;
00316             q->nb_packets--;
00317             q->size -= pkt1->pkt.size;
00318             *pkt = pkt1->pkt;
00319             av_free(pkt1);
00320             ret = 1;
00321             break;
00322         } else if (!block) {
00323             ret = 0;
00324             break;
00325         } else {
00326             SDL_CondWait(q->cond, q->mutex);
00327         }
00328     }
00329     SDL_UnlockMutex(q->mutex);
00330     return ret;
00331 }
00332 
00333 static inline void fill_rectangle(SDL_Surface *screen,
00334                                   int x, int y, int w, int h, int color)
00335 {
00336     SDL_Rect rect;
00337     rect.x = x;
00338     rect.y = y;
00339     rect.w = w;
00340     rect.h = h;
00341     SDL_FillRect(screen, &rect, color);
00342 }
00343 
00344 #if 0
00345 /* draw only the border of a rectangle */
00346 void fill_border(VideoState *s, int x, int y, int w, int h, int color)
00347 {
00348     int w1, w2, h1, h2;
00349 
00350     /* fill the background */
00351     w1 = x;
00352     if (w1 < 0)
00353         w1 = 0;
00354     w2 = s->width - (x + w);
00355     if (w2 < 0)
00356         w2 = 0;
00357     h1 = y;
00358     if (h1 < 0)
00359         h1 = 0;
00360     h2 = s->height - (y + h);
00361     if (h2 < 0)
00362         h2 = 0;
00363     fill_rectangle(screen,
00364                    s->xleft, s->ytop,
00365                    w1, s->height,
00366                    color);
00367     fill_rectangle(screen,
00368                    s->xleft + s->width - w2, s->ytop,
00369                    w2, s->height,
00370                    color);
00371     fill_rectangle(screen,
00372                    s->xleft + w1, s->ytop,
00373                    s->width - w1 - w2, h1,
00374                    color);
00375     fill_rectangle(screen,
00376                    s->xleft + w1, s->ytop + s->height - h2,
00377                    s->width - w1 - w2, h2,
00378                    color);
00379 }
00380 #endif
00381 
00382 
00383 
00384 #define SCALEBITS 10
00385 #define ONE_HALF  (1 << (SCALEBITS - 1))
00386 #define FIX(x)    ((int) ((x) * (1<<SCALEBITS) + 0.5))
00387 
00388 #define RGB_TO_Y_CCIR(r, g, b) \
00389 ((FIX(0.29900*219.0/255.0) * (r) + FIX(0.58700*219.0/255.0) * (g) + \
00390   FIX(0.11400*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS)
00391 
00392 #define RGB_TO_U_CCIR(r1, g1, b1, shift)\
00393 (((- FIX(0.16874*224.0/255.0) * r1 - FIX(0.33126*224.0/255.0) * g1 +         \
00394      FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
00395 
00396 #define RGB_TO_V_CCIR(r1, g1, b1, shift)\
00397 (((FIX(0.50000*224.0/255.0) * r1 - FIX(0.41869*224.0/255.0) * g1 -           \
00398    FIX(0.08131*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
00399 
00400 #define ALPHA_BLEND(a, oldp, newp, s)\
00401 ((((oldp << s) * (255 - (a))) + (newp * (a))) / (255 << s))
00402 
00403 #define RGBA_IN(r, g, b, a, s)\
00404 {\
00405     unsigned int v = ((const uint32_t *)(s))[0];\
00406     a = (v >> 24) & 0xff;\
00407     r = (v >> 16) & 0xff;\
00408     g = (v >> 8) & 0xff;\
00409     b = v & 0xff;\
00410 }
00411 
00412 #define YUVA_IN(y, u, v, a, s, pal)\
00413 {\
00414     unsigned int val = ((const uint32_t *)(pal))[*(const uint8_t*)(s)];\
00415     a = (val >> 24) & 0xff;\
00416     y = (val >> 16) & 0xff;\
00417     u = (val >> 8) & 0xff;\
00418     v = val & 0xff;\
00419 }
00420 
00421 #define YUVA_OUT(d, y, u, v, a)\
00422 {\
00423     ((uint32_t *)(d))[0] = (a << 24) | (y << 16) | (u << 8) | v;\
00424 }
00425 
00426 
00427 #define BPP 1
00428 
00429 static void blend_subrect(AVPicture *dst, const AVSubtitleRect *rect, int imgw, int imgh)
00430 {
00431     int wrap, wrap3, width2, skip2;
00432     int y, u, v, a, u1, v1, a1, w, h;
00433     uint8_t *lum, *cb, *cr;
00434     const uint8_t *p;
00435     const uint32_t *pal;
00436     int dstx, dsty, dstw, dsth;
00437 
00438     dstx = FFMIN(FFMAX(rect->x, 0), imgw);
00439     dstw = FFMIN(FFMAX(rect->w, 0), imgw - dstx);
00440     dsty = FFMIN(FFMAX(rect->y, 0), imgh);
00441     dsth = FFMIN(FFMAX(rect->h, 0), imgh - dsty);
00442     lum = dst->data[0] + dsty * dst->linesize[0];
00443     cb = dst->data[1] + (dsty >> 1) * dst->linesize[1];
00444     cr = dst->data[2] + (dsty >> 1) * dst->linesize[2];
00445 
00446     width2 = (dstw + 1) >> 1;
00447     skip2 = dstx >> 1;
00448     wrap = dst->linesize[0];
00449     wrap3 = rect->linesize;
00450     p = rect->bitmap;
00451     pal = rect->rgba_palette;  /* Now in YCrCb! */
00452 
00453     if (dsty & 1) {
00454         lum += dstx;
00455         cb += skip2;
00456         cr += skip2;
00457 
00458         if (dstx & 1) {
00459             YUVA_IN(y, u, v, a, p, pal);
00460             lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00461             cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
00462             cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
00463             cb++;
00464             cr++;
00465             lum++;
00466             p += BPP;
00467         }
00468         for(w = dstw - (dstx & 1); w >= 2; w -= 2) {
00469             YUVA_IN(y, u, v, a, p, pal);
00470             u1 = u;
00471             v1 = v;
00472             a1 = a;
00473             lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00474 
00475             YUVA_IN(y, u, v, a, p + BPP, pal);
00476             u1 += u;
00477             v1 += v;
00478             a1 += a;
00479             lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
00480             cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
00481             cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
00482             cb++;
00483             cr++;
00484             p += 2 * BPP;
00485             lum += 2;
00486         }
00487         if (w) {
00488             YUVA_IN(y, u, v, a, p, pal);
00489             lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00490             cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
00491             cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
00492         }
00493         p += wrap3 + (wrap3 - dstw * BPP);
00494         lum += wrap + (wrap - dstw - dstx);
00495         cb += dst->linesize[1] - width2 - skip2;
00496         cr += dst->linesize[2] - width2 - skip2;
00497     }
00498     for(h = dsth - (dsty & 1); h >= 2; h -= 2) {
00499         lum += dstx;
00500         cb += skip2;
00501         cr += skip2;
00502 
00503         if (dstx & 1) {
00504             YUVA_IN(y, u, v, a, p, pal);
00505             u1 = u;
00506             v1 = v;
00507             a1 = a;
00508             lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00509             p += wrap3;
00510             lum += wrap;
00511             YUVA_IN(y, u, v, a, p, pal);
00512             u1 += u;
00513             v1 += v;
00514             a1 += a;
00515             lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00516             cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
00517             cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
00518             cb++;
00519             cr++;
00520             p += -wrap3 + BPP;
00521             lum += -wrap + 1;
00522         }
00523         for(w = dstw - (dstx & 1); w >= 2; w -= 2) {
00524             YUVA_IN(y, u, v, a, p, pal);
00525             u1 = u;
00526             v1 = v;
00527             a1 = a;
00528             lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00529 
00530             YUVA_IN(y, u, v, a, p, pal);
00531             u1 += u;
00532             v1 += v;
00533             a1 += a;
00534             lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
00535             p += wrap3;
00536             lum += wrap;
00537 
00538             YUVA_IN(y, u, v, a, p, pal);
00539             u1 += u;
00540             v1 += v;
00541             a1 += a;
00542             lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00543 
00544             YUVA_IN(y, u, v, a, p, pal);
00545             u1 += u;
00546             v1 += v;
00547             a1 += a;
00548             lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
00549 
00550             cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 2);
00551             cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 2);
00552 
00553             cb++;
00554             cr++;
00555             p += -wrap3 + 2 * BPP;
00556             lum += -wrap + 2;
00557         }
00558         if (w) {
00559             YUVA_IN(y, u, v, a, p, pal);
00560             u1 = u;
00561             v1 = v;
00562             a1 = a;
00563             lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00564             p += wrap3;
00565             lum += wrap;
00566             YUVA_IN(y, u, v, a, p, pal);
00567             u1 += u;
00568             v1 += v;
00569             a1 += a;
00570             lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00571             cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
00572             cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
00573             cb++;
00574             cr++;
00575             p += -wrap3 + BPP;
00576             lum += -wrap + 1;
00577         }
00578         p += wrap3 + (wrap3 - dstw * BPP);
00579         lum += wrap + (wrap - dstw - dstx);
00580         cb += dst->linesize[1] - width2 - skip2;
00581         cr += dst->linesize[2] - width2 - skip2;
00582     }
00583     /* handle odd height */
00584     if (h) {
00585         lum += dstx;
00586         cb += skip2;
00587         cr += skip2;
00588 
00589         if (dstx & 1) {
00590             YUVA_IN(y, u, v, a, p, pal);
00591             lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00592             cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
00593             cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
00594             cb++;
00595             cr++;
00596             lum++;
00597             p += BPP;
00598         }
00599         for(w = dstw - (dstx & 1); w >= 2; w -= 2) {
00600             YUVA_IN(y, u, v, a, p, pal);
00601             u1 = u;
00602             v1 = v;
00603             a1 = a;
00604             lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00605 
00606             YUVA_IN(y, u, v, a, p + BPP, pal);
00607             u1 += u;
00608             v1 += v;
00609             a1 += a;
00610             lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
00611             cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u, 1);
00612             cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v, 1);
00613             cb++;
00614             cr++;
00615             p += 2 * BPP;
00616             lum += 2;
00617         }
00618         if (w) {
00619             YUVA_IN(y, u, v, a, p, pal);
00620             lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00621             cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
00622             cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
00623         }
00624     }
00625 }
00626 
00627 static void free_subpicture(SubPicture *sp)
00628 {
00629     int i;
00630 
00631     for (i = 0; i < sp->sub.num_rects; i++)
00632     {
00633         av_free(sp->sub.rects[i].bitmap);
00634         av_free(sp->sub.rects[i].rgba_palette);
00635     }
00636 
00637     av_free(sp->sub.rects);
00638 
00639     memset(&sp->sub, 0, sizeof(AVSubtitle));
00640 }
00641 
00642 static void video_image_display(VideoState *is)
00643 {
00644     VideoPicture *vp;
00645     SubPicture *sp;
00646     AVPicture pict;
00647     float aspect_ratio;
00648     int width, height, x, y;
00649     SDL_Rect rect;
00650     int i;
00651 
00652     vp = &is->pictq[is->pictq_rindex];
00653     if (vp->bmp) {
00654         /* XXX: use variable in the frame */
00655         if (is->video_st->codec->sample_aspect_ratio.num == 0)
00656             aspect_ratio = 0;
00657         else
00658             aspect_ratio = av_q2d(is->video_st->codec->sample_aspect_ratio)
00659                 * is->video_st->codec->width / is->video_st->codec->height;
00660         if (aspect_ratio <= 0.0)
00661             aspect_ratio = (float)is->video_st->codec->width /
00662                 (float)is->video_st->codec->height;
00663         /* if an active format is indicated, then it overrides the
00664            mpeg format */
00665 #if 0
00666         if (is->video_st->codec->dtg_active_format != is->dtg_active_format) {
00667             is->dtg_active_format = is->video_st->codec->dtg_active_format;
00668             printf("dtg_active_format=%d\n", is->dtg_active_format);
00669         }
00670 #endif
00671 #if 0
00672         switch(is->video_st->codec->dtg_active_format) {
00673         case FF_DTG_AFD_SAME:
00674         default:
00675             /* nothing to do */
00676             break;
00677         case FF_DTG_AFD_4_3:
00678             aspect_ratio = 4.0 / 3.0;
00679             break;
00680         case FF_DTG_AFD_16_9:
00681             aspect_ratio = 16.0 / 9.0;
00682             break;
00683         case FF_DTG_AFD_14_9:
00684             aspect_ratio = 14.0 / 9.0;
00685             break;
00686         case FF_DTG_AFD_4_3_SP_14_9:
00687             aspect_ratio = 14.0 / 9.0;
00688             break;
00689         case FF_DTG_AFD_16_9_SP_14_9:
00690             aspect_ratio = 14.0 / 9.0;
00691             break;
00692         case FF_DTG_AFD_SP_4_3:
00693             aspect_ratio = 4.0 / 3.0;
00694             break;
00695         }
00696 #endif
00697 
00698         if (is->subtitle_st)
00699         {
00700             if (is->subpq_size > 0)
00701             {
00702                 sp = &is->subpq[is->subpq_rindex];
00703 
00704                 if (vp->pts >= sp->pts + ((float) sp->sub.start_display_time / 1000))
00705                 {
00706                     SDL_LockYUVOverlay (vp->bmp);
00707 
00708                     pict.data[0] = vp->bmp->pixels[0];
00709                     pict.data[1] = vp->bmp->pixels[2];
00710                     pict.data[2] = vp->bmp->pixels[1];
00711 
00712                     pict.linesize[0] = vp->bmp->pitches[0];
00713                     pict.linesize[1] = vp->bmp->pitches[2];
00714                     pict.linesize[2] = vp->bmp->pitches[1];
00715 
00716                     for (i = 0; i < sp->sub.num_rects; i++)
00717                         blend_subrect(&pict, &sp->sub.rects[i],
00718                                       vp->bmp->w, vp->bmp->h);
00719 
00720                     SDL_UnlockYUVOverlay (vp->bmp);
00721                 }
00722             }
00723         }
00724 
00725 
00726         /* XXX: we suppose the screen has a 1.0 pixel ratio */
00727         height = is->height;
00728         width = ((int)rint(height * aspect_ratio)) & -3;
00729         if (width > is->width) {
00730             width = is->width;
00731             height = ((int)rint(width / aspect_ratio)) & -3;
00732         }
00733         x = (is->width - width) / 2;
00734         y = (is->height - height) / 2;
00735         if (!is->no_background) {
00736             /* fill the background */
00737             //            fill_border(is, x, y, width, height, QERGB(0x00, 0x00, 0x00));
00738         } else {
00739             is->no_background = 0;
00740         }
00741         rect.x = is->xleft + x;
00742         rect.y = is->ytop  + y;
00743         rect.w = width;
00744         rect.h = height;
00745         SDL_DisplayYUVOverlay(vp->bmp, &rect);
00746     } else {
00747 #if 0
00748         fill_rectangle(screen,
00749                        is->xleft, is->ytop, is->width, is->height,
00750                        QERGB(0x00, 0x00, 0x00));
00751 #endif
00752     }
00753 }
00754 
00755 static inline int compute_mod(int a, int b)
00756 {
00757     a = a % b;
00758     if (a >= 0)
00759         return a;
00760     else
00761         return a + b;
00762 }
00763 
00764 static void video_audio_display(VideoState *s)
00765 {
00766     int i, i_start, x, y1, y, ys, delay, n, nb_display_channels;
00767     int ch, channels, h, h2, bgcolor, fgcolor;
00768     int16_t time_diff;
00769 
00770     /* compute display index : center on currently output samples */
00771     channels = s->audio_st->codec->channels;
00772     nb_display_channels = channels;
00773     if (!s->paused) {
00774         n = 2 * channels;
00775         delay = audio_write_get_buf_size(s);
00776         delay /= n;
00777 
00778         /* to be more precise, we take into account the time spent since
00779            the last buffer computation */
00780         if (audio_callback_time) {
00781             time_diff = av_gettime() - audio_callback_time;
00782             delay += (time_diff * s->audio_st->codec->sample_rate) / 1000000;
00783         }
00784 
00785         delay -= s->width / 2;
00786         if (delay < s->width)
00787             delay = s->width;
00788 
00789         i_start= x = compute_mod(s->sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE);
00790 
00791         h= INT_MIN;
00792         for(i=0; i<1000; i+=channels){
00793             int idx= (SAMPLE_ARRAY_SIZE + x - i) % SAMPLE_ARRAY_SIZE;
00794             int a= s->sample_array[idx];
00795             int b= s->sample_array[(idx + 4*channels)%SAMPLE_ARRAY_SIZE];
00796             int c= s->sample_array[(idx + 5*channels)%SAMPLE_ARRAY_SIZE];
00797             int d= s->sample_array[(idx + 9*channels)%SAMPLE_ARRAY_SIZE];
00798             int score= a-d;
00799             if(h<score && (b^c)<0){
00800                 h= score;
00801                 i_start= idx;
00802             }
00803         }
00804 
00805         s->last_i_start = i_start;
00806     } else {
00807         i_start = s->last_i_start;
00808     }
00809 
00810     bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
00811     fill_rectangle(screen,
00812                    s->xleft, s->ytop, s->width, s->height,
00813                    bgcolor);
00814 
00815     fgcolor = SDL_MapRGB(screen->format, 0xff, 0xff, 0xff);
00816 
00817     /* total height for one channel */
00818     h = s->height / nb_display_channels;
00819     /* graph height / 2 */
00820     h2 = (h * 9) / 20;
00821     for(ch = 0;ch < nb_display_channels; ch++) {
00822         i = i_start + ch;
00823         y1 = s->ytop + ch * h + (h / 2); /* position of center line */
00824         for(x = 0; x < s->width; x++) {
00825             y = (s->sample_array[i] * h2) >> 15;
00826             if (y < 0) {
00827                 y = -y;
00828                 ys = y1 - y;
00829             } else {
00830                 ys = y1;
00831             }
00832             fill_rectangle(screen,
00833                            s->xleft + x, ys, 1, y,
00834                            fgcolor);
00835             i += channels;
00836             if (i >= SAMPLE_ARRAY_SIZE)
00837                 i -= SAMPLE_ARRAY_SIZE;
00838         }
00839     }
00840 
00841     fgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0xff);
00842 
00843     for(ch = 1;ch < nb_display_channels; ch++) {
00844         y = s->ytop + ch * h;
00845         fill_rectangle(screen,
00846                        s->xleft, y, s->width, 1,
00847                        fgcolor);
00848     }
00849     SDL_UpdateRect(screen, s->xleft, s->ytop, s->width, s->height);
00850 }
00851 
00852 static int video_open(VideoState *is){
00853     int flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
00854     int w,h;
00855 
00856     if(is_full_screen) flags |= SDL_FULLSCREEN;
00857     else               flags |= SDL_RESIZABLE;
00858 
00859     if (is_full_screen && fs_screen_width) {
00860         w = fs_screen_width;
00861         h = fs_screen_height;
00862     } else if(!is_full_screen && screen_width){
00863         w = screen_width;
00864         h = screen_height;
00865     }else if (is->video_st && is->video_st->codec->width){
00866         w = is->video_st->codec->width;
00867         h = is->video_st->codec->height;
00868     } else {
00869         w = 640;
00870         h = 480;
00871     }
00872 #ifndef __APPLE__
00873     screen = SDL_SetVideoMode(w, h, 0, flags);
00874 #else
00875     /* setting bits_per_pixel = 0 or 32 causes blank video on OS X */
00876     screen = SDL_SetVideoMode(w, h, 24, flags);
00877 #endif
00878     if (!screen) {
00879         fprintf(stderr, "SDL: could not set video mode - exiting\n");
00880         return -1;
00881     }
00882     SDL_WM_SetCaption("FFplay", "FFplay");
00883 
00884     is->width = screen->w;
00885     is->height = screen->h;
00886 
00887     return 0;
00888 }
00889 
00890 /* display the current picture, if any */
00891 static void video_display(VideoState *is)
00892 {
00893     if(!screen)
00894         video_open(cur_stream);
00895     if (is->audio_st && is->show_audio)
00896         video_audio_display(is);
00897     else if (is->video_st)
00898         video_image_display(is);
00899 }
00900 
00901 static Uint32 sdl_refresh_timer_cb(Uint32 interval, void *opaque)
00902 {
00903     SDL_Event event;
00904     event.type = FF_REFRESH_EVENT;
00905     event.user.data1 = opaque;
00906     SDL_PushEvent(&event);
00907     return 0; /* 0 means stop timer */
00908 }
00909 
00910 /* schedule a video refresh in 'delay' ms */
00911 static void schedule_refresh(VideoState *is, int delay)
00912 {
00913     SDL_AddTimer(delay, sdl_refresh_timer_cb, is);
00914 }
00915 
00916 /* get the current audio clock value */
00917 static double get_audio_clock(VideoState *is)
00918 {
00919     double pts;
00920     int hw_buf_size, bytes_per_sec;
00921     pts = is->audio_clock;
00922     hw_buf_size = audio_write_get_buf_size(is);
00923     bytes_per_sec = 0;
00924     if (is->audio_st) {
00925         bytes_per_sec = is->audio_st->codec->sample_rate *
00926             2 * is->audio_st->codec->channels;
00927     }
00928     if (bytes_per_sec)
00929         pts -= (double)hw_buf_size / bytes_per_sec;
00930     return pts;
00931 }
00932 
00933 /* get the current video clock value */
00934 static double get_video_clock(VideoState *is)
00935 {
00936     double delta;
00937     if (is->paused) {
00938         delta = 0;
00939     } else {
00940         delta = (av_gettime() - is->video_current_pts_time) / 1000000.0;
00941     }
00942     return is->video_current_pts + delta;
00943 }
00944 
00945 /* get the current external clock value */
00946 static double get_external_clock(VideoState *is)
00947 {
00948     int64_t ti;
00949     ti = av_gettime();
00950     return is->external_clock + ((ti - is->external_clock_time) * 1e-6);
00951 }
00952 
00953 /* get the current master clock value */
00954 static double get_master_clock(VideoState *is)
00955 {
00956     double val;
00957 
00958     if (is->av_sync_type == AV_SYNC_VIDEO_MASTER) {
00959         if (is->