00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00037 #endif
00038
00039 #undef exit
00040
00041 const char program_name[] = "FFplay";
00042 const int program_birth_year = 2003;
00043
00044
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
00051
00052 #define SDL_AUDIO_BUFFER_SIZE 1024
00053
00054
00055 #define AV_SYNC_THRESHOLD 0.01
00056
00057 #define AV_NOSYNC_THRESHOLD 10.0
00058
00059
00060 #define SAMPLE_CORRECTION_PERCENT_MAX 10
00061
00062
00063 #define AUDIO_DIFF_AVG_NB 20
00064
00065
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;
00084 SDL_Overlay *bmp;
00085 int width, height;
00086 int allocated;
00087 } VideoPicture;
00088
00089 typedef struct SubPicture {
00090 double pts;
00091 AVSubtitle sub;
00092 } SubPicture;
00093
00094 enum {
00095 AV_SYNC_AUDIO_MASTER,
00096 AV_SYNC_VIDEO_MASTER,
00097 AV_SYNC_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;
00118 int64_t external_clock_time;
00119
00120 double audio_clock;
00121 double audio_diff_cum;
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
00129
00130 DECLARE_ALIGNED(16,uint8_t,audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2]);
00131 unsigned int audio_buf_size;
00132 int audio_buf_index;
00133 AVPacket audio_pkt;
00134 uint8_t *audio_pkt_data;
00135 int audio_pkt_size;
00136
00137 int show_audio;
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;
00156 int video_stream;
00157 AVStream *video_st;
00158 PacketQueue videoq;
00159 double video_current_pts;
00160 int64_t video_current_pts_time;
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
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
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
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
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
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
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
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
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
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;
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
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
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
00664
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
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
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
00737
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
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
00779
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
00818 h = s->height / nb_display_channels;
00819
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);
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
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
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;
00908 }
00909
00910
00911 static void schedule_refresh(VideoState *is, int delay)
00912 {
00913 SDL_AddTimer(delay, sdl_refresh_timer_cb, is);
00914 }
00915
00916
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
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
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
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->