00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #define _XOPEN_SOURCE 600
00023
00024 #include "config.h"
00025 #include <inttypes.h>
00026 #include <math.h>
00027 #include <limits.h>
00028 #include "libavutil/avstring.h"
00029 #include "libavutil/colorspace.h"
00030 #include "libavutil/pixdesc.h"
00031 #include "libavutil/imgutils.h"
00032 #include "libavutil/parseutils.h"
00033 #include "libavutil/samplefmt.h"
00034 #include "libavformat/avformat.h"
00035 #include "libavdevice/avdevice.h"
00036 #include "libswscale/swscale.h"
00037 #include "libavcodec/audioconvert.h"
00038 #include "libavcodec/opt.h"
00039 #include "libavcodec/avfft.h"
00040
00041 #if CONFIG_AVFILTER
00042 # include "libavfilter/avfilter.h"
00043 # include "libavfilter/avfiltergraph.h"
00044 #endif
00045
00046 #include "cmdutils.h"
00047
00048 #include <SDL.h>
00049 #include <SDL_thread.h>
00050
00051 #ifdef __MINGW32__
00052 #undef main
00053 #endif
00054
00055 #include <unistd.h>
00056 #include <assert.h>
00057
00058 const char program_name[] = "FFplay";
00059 const int program_birth_year = 2003;
00060
00061
00062
00063
00064 #define MAX_QUEUE_SIZE (15 * 1024 * 1024)
00065 #define MIN_AUDIOQ_SIZE (20 * 16 * 1024)
00066 #define MIN_FRAMES 5
00067
00068
00069
00070 #define SDL_AUDIO_BUFFER_SIZE 1024
00071
00072
00073 #define AV_SYNC_THRESHOLD 0.01
00074
00075 #define AV_NOSYNC_THRESHOLD 10.0
00076
00077 #define FRAME_SKIP_FACTOR 0.05
00078
00079
00080 #define SAMPLE_CORRECTION_PERCENT_MAX 10
00081
00082
00083 #define AUDIO_DIFF_AVG_NB 20
00084
00085
00086 #define SAMPLE_ARRAY_SIZE (2*65536)
00087
00088 static int sws_flags = SWS_BICUBIC;
00089
00090 typedef struct PacketQueue {
00091 AVPacketList *first_pkt, *last_pkt;
00092 int nb_packets;
00093 int size;
00094 int abort_request;
00095 SDL_mutex *mutex;
00096 SDL_cond *cond;
00097 } PacketQueue;
00098
00099 #define VIDEO_PICTURE_QUEUE_SIZE 2
00100 #define SUBPICTURE_QUEUE_SIZE 4
00101
00102 typedef struct VideoPicture {
00103 double pts;
00104 double target_clock;
00105 int64_t pos;
00106 SDL_Overlay *bmp;
00107 int width, height;
00108 int allocated;
00109 enum PixelFormat pix_fmt;
00110
00111 #if CONFIG_AVFILTER
00112 AVFilterBufferRef *picref;
00113 #endif
00114 } VideoPicture;
00115
00116 typedef struct SubPicture {
00117 double pts;
00118 AVSubtitle sub;
00119 } SubPicture;
00120
00121 enum {
00122 AV_SYNC_AUDIO_MASTER,
00123 AV_SYNC_VIDEO_MASTER,
00124 AV_SYNC_EXTERNAL_CLOCK,
00125 };
00126
00127 typedef struct VideoState {
00128 SDL_Thread *parse_tid;
00129 SDL_Thread *video_tid;
00130 SDL_Thread *refresh_tid;
00131 AVInputFormat *iformat;
00132 int no_background;
00133 int abort_request;
00134 int paused;
00135 int last_paused;
00136 int seek_req;
00137 int seek_flags;
00138 int64_t seek_pos;
00139 int64_t seek_rel;
00140 int read_pause_return;
00141 AVFormatContext *ic;
00142 int dtg_active_format;
00143
00144 int audio_stream;
00145
00146 int av_sync_type;
00147 double external_clock;
00148 int64_t external_clock_time;
00149
00150 double audio_clock;
00151 double audio_diff_cum;
00152 double audio_diff_avg_coef;
00153 double audio_diff_threshold;
00154 int audio_diff_avg_count;
00155 AVStream *audio_st;
00156 PacketQueue audioq;
00157 int audio_hw_buf_size;
00158
00159
00160 DECLARE_ALIGNED(16,uint8_t,audio_buf1)[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];
00161 DECLARE_ALIGNED(16,uint8_t,audio_buf2)[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];
00162 uint8_t *audio_buf;
00163 unsigned int audio_buf_size;
00164 int audio_buf_index;
00165 AVPacket audio_pkt_temp;
00166 AVPacket audio_pkt;
00167 enum AVSampleFormat audio_src_fmt;
00168 AVAudioConvert *reformat_ctx;
00169
00170 int show_audio;
00171 int16_t sample_array[SAMPLE_ARRAY_SIZE];
00172 int sample_array_index;
00173 int last_i_start;
00174 RDFTContext *rdft;
00175 int rdft_bits;
00176 FFTSample *rdft_data;
00177 int xpos;
00178
00179 SDL_Thread *subtitle_tid;
00180 int subtitle_stream;
00181 int subtitle_stream_changed;
00182 AVStream *subtitle_st;
00183 PacketQueue subtitleq;
00184 SubPicture subpq[SUBPICTURE_QUEUE_SIZE];
00185 int subpq_size, subpq_rindex, subpq_windex;
00186 SDL_mutex *subpq_mutex;
00187 SDL_cond *subpq_cond;
00188
00189 double frame_timer;
00190 double frame_last_pts;
00191 double frame_last_delay;
00192 double video_clock;
00193 int video_stream;
00194 AVStream *video_st;
00195 PacketQueue videoq;
00196 double video_current_pts;
00197 double video_current_pts_drift;
00198 int64_t video_current_pos;
00199 VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
00200 int pictq_size, pictq_rindex, pictq_windex;
00201 SDL_mutex *pictq_mutex;
00202 SDL_cond *pictq_cond;
00203 #if !CONFIG_AVFILTER
00204 struct SwsContext *img_convert_ctx;
00205 #endif
00206
00207
00208 char filename[1024];
00209 int width, height, xleft, ytop;
00210
00211 #if CONFIG_AVFILTER
00212 AVFilterContext *out_video_filter;
00213 #endif
00214
00215 float skip_frames;
00216 float skip_frames_index;
00217 int refresh;
00218 } VideoState;
00219
00220 static void show_help(void);
00221 static int audio_write_get_buf_size(VideoState *is);
00222
00223
00224 static AVInputFormat *file_iformat;
00225 static const char *input_filename;
00226 static const char *window_title;
00227 static int fs_screen_width;
00228 static int fs_screen_height;
00229 static int screen_width = 0;
00230 static int screen_height = 0;
00231 static int frame_width = 0;
00232 static int frame_height = 0;
00233 static enum PixelFormat frame_pix_fmt = PIX_FMT_NONE;
00234 static int audio_disable;
00235 static int video_disable;
00236 static int wanted_stream[AVMEDIA_TYPE_NB]={
00237 [AVMEDIA_TYPE_AUDIO]=-1,
00238 [AVMEDIA_TYPE_VIDEO]=-1,
00239 [AVMEDIA_TYPE_SUBTITLE]=-1,
00240 };
00241 static int seek_by_bytes=-1;
00242 static int display_disable;
00243 static int show_status = 1;
00244 static int av_sync_type = AV_SYNC_AUDIO_MASTER;
00245 static int64_t start_time = AV_NOPTS_VALUE;
00246 static int64_t duration = AV_NOPTS_VALUE;
00247 static int debug = 0;
00248 static int debug_mv = 0;
00249 static int step = 0;
00250 static int thread_count = 1;
00251 static int workaround_bugs = 1;
00252 static int fast = 0;
00253 static int genpts = 0;
00254 static int lowres = 0;
00255 static int idct = FF_IDCT_AUTO;
00256 static enum AVDiscard skip_frame= AVDISCARD_DEFAULT;
00257 static enum AVDiscard skip_idct= AVDISCARD_DEFAULT;
00258 static enum AVDiscard skip_loop_filter= AVDISCARD_DEFAULT;
00259 static int error_recognition = FF_ER_CAREFUL;
00260 static int error_concealment = 3;
00261 static int decoder_reorder_pts= -1;
00262 static int autoexit;
00263 static int exit_on_keydown;
00264 static int exit_on_mousedown;
00265 static int loop=1;
00266 static int framedrop=1;
00267
00268 static int rdftspeed=20;
00269 #if CONFIG_AVFILTER
00270 static char *vfilters = NULL;
00271 #endif
00272
00273
00274 static int is_full_screen;
00275 static VideoState *cur_stream;
00276 static int64_t audio_callback_time;
00277
00278 static AVPacket flush_pkt;
00279
00280 #define FF_ALLOC_EVENT (SDL_USEREVENT)
00281 #define FF_REFRESH_EVENT (SDL_USEREVENT + 1)
00282 #define FF_QUIT_EVENT (SDL_USEREVENT + 2)
00283
00284 static SDL_Surface *screen;
00285
00286 static int packet_queue_put(PacketQueue *q, AVPacket *pkt);
00287
00288
00289 static void packet_queue_init(PacketQueue *q)
00290 {
00291 memset(q, 0, sizeof(PacketQueue));
00292 q->mutex = SDL_CreateMutex();
00293 q->cond = SDL_CreateCond();
00294 packet_queue_put(q, &flush_pkt);
00295 }
00296
00297 static void packet_queue_flush(PacketQueue *q)
00298 {
00299 AVPacketList *pkt, *pkt1;
00300
00301 SDL_LockMutex(q->mutex);
00302 for(pkt = q->first_pkt; pkt != NULL; pkt = pkt1) {
00303 pkt1 = pkt->next;
00304 av_free_packet(&pkt->pkt);
00305 av_freep(&pkt);
00306 }
00307 q->last_pkt = NULL;
00308 q->first_pkt = NULL;
00309 q->nb_packets = 0;
00310 q->size = 0;
00311 SDL_UnlockMutex(q->mutex);
00312 }
00313
00314 static void packet_queue_end(PacketQueue *q)
00315 {
00316 packet_queue_flush(q);
00317 SDL_DestroyMutex(q->mutex);
00318 SDL_DestroyCond(q->cond);
00319 }
00320
00321 static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
00322 {
00323 AVPacketList *pkt1;
00324
00325
00326 if (pkt!=&flush_pkt && av_dup_packet(pkt) < 0)
00327 return -1;
00328
00329 pkt1 = av_malloc(sizeof(AVPacketList));
00330 if (!pkt1)
00331 return -1;
00332 pkt1->pkt = *pkt;
00333 pkt1->next = NULL;
00334
00335
00336 SDL_LockMutex(q->mutex);
00337
00338 if (!q->last_pkt)
00339
00340 q->first_pkt = pkt1;
00341 else
00342 q->last_pkt->next = pkt1;
00343 q->last_pkt = pkt1;
00344 q->nb_packets++;
00345 q->size += pkt1->pkt.size + sizeof(*pkt1);
00346
00347 SDL_CondSignal(q->cond);
00348
00349 SDL_UnlockMutex(q->mutex);
00350 return 0;
00351 }
00352
00353 static void packet_queue_abort(PacketQueue *q)
00354 {
00355 SDL_LockMutex(q->mutex);
00356
00357 q->abort_request = 1;
00358
00359 SDL_CondSignal(q->cond);
00360
00361 SDL_UnlockMutex(q->mutex);
00362 }
00363
00364
00365 static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
00366 {
00367 AVPacketList *pkt1;
00368 int ret;
00369
00370 SDL_LockMutex(q->mutex);
00371
00372 for(;;) {
00373 if (q->abort_request) {
00374 ret = -1;
00375 break;
00376 }
00377
00378 pkt1 = q->first_pkt;
00379 if (pkt1) {
00380 q->first_pkt = pkt1->next;
00381 if (!q->first_pkt)
00382 q->last_pkt = NULL;
00383 q->nb_packets--;
00384 q->size -= pkt1->pkt.size + sizeof(*pkt1);
00385 *pkt = pkt1->pkt;
00386 av_free(pkt1);
00387 ret = 1;
00388 break;
00389 } else if (!block) {
00390 ret = 0;
00391 break;
00392 } else {
00393 SDL_CondWait(q->cond, q->mutex);
00394 }
00395 }
00396 SDL_UnlockMutex(q->mutex);
00397 return ret;
00398 }
00399
00400 static inline void fill_rectangle(SDL_Surface *screen,
00401 int x, int y, int w, int h, int color)
00402 {
00403 SDL_Rect rect;
00404 rect.x = x;
00405 rect.y = y;
00406 rect.w = w;
00407 rect.h = h;
00408 SDL_FillRect(screen, &rect, color);
00409 }
00410
00411 #if 0
00412
00413 void fill_border(VideoState *s, int x, int y, int w, int h, int color)
00414 {
00415 int w1, w2, h1, h2;
00416
00417
00418 w1 = x;
00419 if (w1 < 0)
00420 w1 = 0;
00421 w2 = s->width - (x + w);
00422 if (w2 < 0)
00423 w2 = 0;
00424 h1 = y;
00425 if (h1 < 0)
00426 h1 = 0;
00427 h2 = s->height - (y + h);
00428 if (h2 < 0)
00429 h2 = 0;
00430 fill_rectangle(screen,
00431 s->xleft, s->ytop,
00432 w1, s->height,
00433 color);
00434 fill_rectangle(screen,
00435 s->xleft + s->width - w2, s->ytop,
00436 w2, s->height,
00437 color);
00438 fill_rectangle(screen,
00439 s->xleft + w1, s->ytop,
00440 s->width - w1 - w2, h1,
00441 color);
00442 fill_rectangle(screen,
00443 s->xleft + w1, s->ytop + s->height - h2,
00444 s->width - w1 - w2, h2,
00445 color);
00446 }
00447 #endif
00448
00449 #define ALPHA_BLEND(a, oldp, newp, s)\
00450 ((((oldp << s) * (255 - (a))) + (newp * (a))) / (255 << s))
00451
00452 #define RGBA_IN(r, g, b, a, s)\
00453 {\
00454 unsigned int v = ((const uint32_t *)(s))[0];\
00455 a = (v >> 24) & 0xff;\
00456 r = (v >> 16) & 0xff;\
00457 g = (v >> 8) & 0xff;\
00458 b = v & 0xff;\
00459 }
00460
00461 #define YUVA_IN(y, u, v, a, s, pal)\
00462 {\
00463 unsigned int val = ((const uint32_t *)(pal))[*(const uint8_t*)(s)];\
00464 a = (val >> 24) & 0xff;\
00465 y = (val >> 16) & 0xff;\
00466 u = (val >> 8) & 0xff;\
00467 v = val & 0xff;\
00468 }
00469
00470 #define YUVA_OUT(d, y, u, v, a)\
00471 {\
00472 ((uint32_t *)(d))[0] = (a << 24) | (y << 16) | (u << 8) | v;\
00473 }
00474
00475
00476 #define BPP 1
00477
00478 static void blend_subrect(AVPicture *dst, const AVSubtitleRect *rect, int imgw, int imgh)
00479 {
00480 int wrap, wrap3, width2, skip2;
00481 int y, u, v, a, u1, v1, a1, w, h;
00482 uint8_t *lum, *cb, *cr;
00483 const uint8_t *p;
00484 const uint32_t *pal;
00485 int dstx, dsty, dstw, dsth;
00486
00487 dstw = av_clip(rect->w, 0, imgw);
00488 dsth = av_clip(rect->h, 0, imgh);
00489 dstx = av_clip(rect->x, 0, imgw - dstw);
00490 dsty = av_clip(rect->y, 0, imgh - dsth);
00491 lum = dst->data[0] + dsty * dst->linesize[0];
00492 cb = dst->data[1] + (dsty >> 1) * dst->linesize[1];
00493 cr = dst->data[2] + (dsty >> 1) * dst->linesize[2];
00494
00495 width2 = ((dstw + 1) >> 1) + (dstx & ~dstw & 1);
00496 skip2 = dstx >> 1;
00497 wrap = dst->linesize[0];
00498 wrap3 = rect->pict.linesize[0];
00499 p = rect->pict.data[0];
00500 pal = (const uint32_t *)rect->pict.data[1];
00501
00502 if (dsty & 1) {
00503 lum += dstx;
00504 cb += skip2;
00505 cr += skip2;
00506
00507 if (dstx & 1) {
00508 YUVA_IN(y, u, v, a, p, pal);
00509 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00510 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
00511 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
00512 cb++;
00513 cr++;
00514 lum++;
00515 p += BPP;
00516 }
00517 for(w = dstw - (dstx & 1); w >= 2; w -= 2) {
00518 YUVA_IN(y, u, v, a, p, pal);
00519 u1 = u;
00520 v1 = v;
00521 a1 = a;
00522 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00523
00524 YUVA_IN(y, u, v, a, p + BPP, pal);
00525 u1 += u;
00526 v1 += v;
00527 a1 += a;
00528 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
00529 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
00530 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
00531 cb++;
00532 cr++;
00533 p += 2 * BPP;
00534 lum += 2;
00535 }
00536 if (w) {
00537 YUVA_IN(y, u, v, a, p, pal);
00538 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00539 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
00540 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
00541 p++;
00542 lum++;
00543 }
00544 p += wrap3 - dstw * BPP;
00545 lum += wrap - dstw - dstx;
00546 cb += dst->linesize[1] - width2 - skip2;
00547 cr += dst->linesize[2] - width2 - skip2;
00548 }
00549 for(h = dsth - (dsty & 1); h >= 2; h -= 2) {
00550 lum += dstx;
00551 cb += skip2;
00552 cr += skip2;
00553
00554 if (dstx & 1) {
00555 YUVA_IN(y, u, v, a, p, pal);
00556 u1 = u;
00557 v1 = v;
00558 a1 = a;
00559 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00560 p += wrap3;
00561 lum += wrap;
00562 YUVA_IN(y, u, v, a, p, pal);
00563 u1 += u;
00564 v1 += v;
00565 a1 += a;
00566 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00567 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
00568 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
00569 cb++;
00570 cr++;
00571 p += -wrap3 + BPP;
00572 lum += -wrap + 1;
00573 }
00574 for(w = dstw - (dstx & 1); w >= 2; w -= 2) {
00575 YUVA_IN(y, u, v, a, p, pal);
00576 u1 = u;
00577 v1 = v;
00578 a1 = a;
00579 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00580
00581 YUVA_IN(y, u, v, a, p + BPP, pal);
00582 u1 += u;
00583 v1 += v;
00584 a1 += a;
00585 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
00586 p += wrap3;
00587 lum += wrap;
00588
00589 YUVA_IN(y, u, v, a, p, pal);
00590 u1 += u;
00591 v1 += v;
00592 a1 += a;
00593 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00594
00595 YUVA_IN(y, u, v, a, p + BPP, pal);
00596 u1 += u;
00597 v1 += v;
00598 a1 += a;
00599 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
00600
00601 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 2);
00602 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 2);
00603
00604 cb++;
00605 cr++;
00606 p += -wrap3 + 2 * BPP;
00607 lum += -wrap + 2;
00608 }
00609 if (w) {
00610 YUVA_IN(y, u, v, a, p, pal);
00611 u1 = u;
00612 v1 = v;
00613 a1 = a;
00614 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00615 p += wrap3;
00616 lum += wrap;
00617 YUVA_IN(y, u, v, a, p, pal);
00618 u1 += u;
00619 v1 += v;
00620 a1 += a;
00621 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00622 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
00623 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
00624 cb++;
00625 cr++;
00626 p += -wrap3 + BPP;
00627 lum += -wrap + 1;
00628 }
00629 p += wrap3 + (wrap3 - dstw * BPP);
00630 lum += wrap + (wrap - dstw - dstx);
00631 cb += dst->linesize[1] - width2 - skip2;
00632 cr += dst->linesize[2] - width2 - skip2;
00633 }
00634
00635 if (h) {
00636 lum += dstx;
00637 cb += skip2;
00638 cr += skip2;
00639
00640 if (dstx & 1) {
00641 YUVA_IN(y, u, v, a, p, pal);
00642 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00643 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
00644 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
00645 cb++;
00646 cr++;
00647 lum++;
00648 p += BPP;
00649 }
00650 for(w = dstw - (dstx & 1); w >= 2; w -= 2) {
00651 YUVA_IN(y, u, v, a, p, pal);
00652 u1 = u;
00653 v1 = v;
00654 a1 = a;
00655 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00656
00657 YUVA_IN(y, u, v, a, p + BPP, pal);
00658 u1 += u;
00659 v1 += v;
00660 a1 += a;
00661 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
00662 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u, 1);
00663 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v, 1);
00664 cb++;
00665 cr++;
00666 p += 2 * BPP;
00667 lum += 2;
00668 }
00669 if (w) {
00670 YUVA_IN(y, u, v, a, p, pal);
00671 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00672 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
00673 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
00674 }
00675 }
00676 }
00677
00678 static void free_subpicture(SubPicture *sp)
00679 {
00680 avsubtitle_free(&sp->sub);
00681 }
00682
00683 static void video_image_display(VideoState *is)
00684 {
00685 VideoPicture *vp;
00686 SubPicture *sp;
00687 AVPicture pict;
00688 float aspect_ratio;
00689 int width, height, x, y;
00690 SDL_Rect rect;
00691 int i;
00692
00693 vp = &is->pictq[is->pictq_rindex];
00694 if (vp->bmp) {
00695 #if CONFIG_AVFILTER
00696 if (vp->picref->video->pixel_aspect.num == 0)
00697 aspect_ratio = 0;
00698 else
00699 aspect_ratio = av_q2d(vp->picref->video->pixel_aspect);
00700 #else
00701
00702
00703 if (is->video_st->sample_aspect_ratio.num)
00704 aspect_ratio = av_q2d(is->video_st->sample_aspect_ratio);
00705 else if (is->video_st->codec->sample_aspect_ratio.num)
00706 aspect_ratio = av_q2d(is->video_st->codec->sample_aspect_ratio);
00707 else
00708 aspect_ratio = 0;
00709 #endif
00710 if (aspect_ratio <= 0.0)
00711 aspect_ratio = 1.0;
00712 aspect_ratio *= (float)vp->width / (float)vp->height;
00713
00714 if (is->subtitle_st)
00715 {
00716 if (is->subpq_size > 0)
00717 {
00718 sp = &is->subpq[is->subpq_rindex];
00719
00720 if (vp->pts >= sp->pts + ((float) sp->sub.start_display_time / 1000))
00721 {
00722 SDL_LockYUVOverlay (vp->bmp);
00723
00724 pict.data[0] = vp->bmp->pixels[0];
00725 pict.data[1] = vp->bmp->pixels[2];
00726 pict.data[2] = vp->bmp->pixels[1];
00727
00728 pict.linesize[0] = vp->bmp->pitches[0];
00729 pict.linesize[1] = vp->bmp->pitches[2];
00730 pict.linesize[2] = vp->bmp->pitches[1];
00731
00732 for (i = 0; i < sp->sub.num_rects; i++)
00733 blend_subrect(&pict, sp->sub.rects[i],
00734 vp->bmp->w, vp->bmp->h);
00735
00736 SDL_UnlockYUVOverlay (vp->bmp);
00737 }
00738 }
00739 }
00740
00741
00742
00743 height = is->height;
00744 width = ((int)rint(height * aspect_ratio)) & ~1;
00745 if (width > is->width) {
00746 width = is->width;
00747 height = ((int)rint(width / aspect_ratio)) & ~1;
00748 }
00749 x = (is->width - width) / 2;
00750 y = (is->height - height) / 2;
00751 if (!is->no_background) {
00752
00753
00754 } else {
00755 is->no_background = 0;
00756 }
00757 rect.x = is->xleft + x;
00758 rect.y = is->ytop + y;
00759 rect.w = width;
00760 rect.h = height;
00761 SDL_DisplayYUVOverlay(vp->bmp, &rect);
00762 } else {
00763 #if 0
00764 fill_rectangle(screen,
00765 is->xleft, is->ytop, is->width, is->height,
00766 QERGB(0x00, 0x00, 0x00));
00767 #endif
00768 }
00769 }
00770
00771 static inline int compute_mod(int a, int b)
00772 {
00773 a = a % b;
00774 if (a >= 0)
00775 return a;
00776 else
00777 return a + b;
00778 }
00779
00780 static void video_audio_display(VideoState *s)
00781 {
00782 int i, i_start, x, y1, y, ys, delay, n, nb_display_channels;
00783 int ch, channels, h, h2, bgcolor, fgcolor;
00784 int16_t time_diff;
00785 int rdft_bits, nb_freq;
00786
00787 for(rdft_bits=1; (1<<rdft_bits)<2*s->height; rdft_bits++)
00788 ;
00789 nb_freq= 1<<(rdft_bits-1);
00790
00791
00792 channels = s->audio_st->codec->channels;
00793 nb_display_channels = channels;
00794 if (!s->paused) {
00795 int data_used= s->show_audio==1 ? s->width : (2*nb_freq);
00796 n = 2 * channels;
00797 delay = audio_write_get_buf_size(s);
00798 delay /= n;
00799
00800
00801
00802 if (audio_callback_time) {
00803 time_diff = av_gettime() - audio_callback_time;
00804 delay -= (time_diff * s->audio_st->codec->sample_rate) / 1000000;
00805 }
00806
00807 delay += 2*data_used;
00808 if (delay < data_used)
00809 delay = data_used;
00810
00811 i_start= x = compute_mod(s->sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE);
00812 if(s->show_audio==1){
00813 h= INT_MIN;
00814 for(i=0; i<1000; i+=channels){
00815 int idx= (SAMPLE_ARRAY_SIZE + x - i) % SAMPLE_ARRAY_SIZE;
00816 int a= s->sample_array[idx];
00817 int b= s->sample_array[(idx + 4*channels)%SAMPLE_ARRAY_SIZE];
00818 int c= s->sample_array[(idx + 5*channels)%SAMPLE_ARRAY_SIZE];
00819 int d= s->sample_array[(idx + 9*channels)%SAMPLE_ARRAY_SIZE];
00820 int score= a-d;
00821 if(h<score && (b^c)<0){
00822 h= score;
00823 i_start= idx;
00824 }
00825 }
00826 }
00827
00828 s->last_i_start = i_start;
00829 } else {
00830 i_start = s->last_i_start;
00831 }
00832
00833 bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
00834 if(s->show_audio==1){
00835 fill_rectangle(screen,
00836 s->xleft, s->ytop, s->width, s->height,
00837 bgcolor);
00838
00839 fgcolor = SDL_MapRGB(screen->format, 0xff, 0xff, 0xff);
00840
00841
00842 h = s->height / nb_display_channels;
00843
00844 h2 = (h * 9) / 20;
00845 for(ch = 0;ch < nb_display_channels; ch++) {
00846 i = i_start + ch;
00847 y1 = s->ytop + ch * h + (h / 2);
00848 for(x = 0; x < s->width; x++) {
00849 y = (s->sample_array[i] * h2) >> 15;
00850 if (y < 0) {
00851 y = -y;
00852 ys = y1 - y;
00853 } else {
00854 ys = y1;
00855 }
00856 fill_rectangle(screen,
00857 s->xleft + x, ys, 1, y,
00858 fgcolor);
00859 i += channels;
00860 if (i >= SAMPLE_ARRAY_SIZE)
00861 i -= SAMPLE_ARRAY_SIZE;
00862 }
00863 }
00864
00865 fgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0xff);
00866
00867 for(ch = 1;ch < nb_display_channels; ch++) {
00868 y = s->ytop + ch * h;
00869 fill_rectangle(screen,
00870 s->xleft, y, s->width, 1,
00871 fgcolor);
00872 }
00873 SDL_UpdateRect(screen, s->xleft, s->ytop, s->width, s->height);
00874 }else{
00875 nb_display_channels= FFMIN(nb_display_channels, 2);
00876 if(rdft_bits != s->rdft_bits){
00877 av_rdft_end(s->rdft);
00878 av_free(s->rdft_data);
00879 s->rdft = av_rdft_init(rdft_bits, DFT_R2C);
00880 s->rdft_bits= rdft_bits;
00881 s->rdft_data= av_malloc(4*nb_freq*sizeof(*s->rdft_data));
00882 }
00883 {
00884 FFTSample *data[2];
00885 for(ch = 0;ch < nb_display_channels; ch++) {
00886 data[ch] = s->rdft_data + 2*nb_freq*ch;
00887 i = i_start + ch;
00888 for(x = 0; x < 2*nb_freq; x++) {
00889 double w= (x-nb_freq)*(1.0/nb_freq);
00890 data[ch][x]= s->sample_array[i]*(1.0-w*w);
00891 i += channels;
00892 if (i >= SAMPLE_ARRAY_SIZE)
00893 i -= SAMPLE_ARRAY_SIZE;
00894 }
00895 av_rdft_calc(s->rdft, data[ch]);
00896 }
00897
00898 for(y=0; y<s->height; y++){
00899 double w= 1/sqrt(nb_freq);
00900 int a= sqrt(w*sqrt(data[0][2*y+0]*data[0][2*y+0] + data[0][2*y+1]*data[0][2*y+1]));
00901 int b= (nb_display_channels == 2 ) ? sqrt(w*sqrt(data[1][2*y+0]*data[1][2*y+0]
00902 + data[1][2*y+1]*data[1][2*y+1])) : a;
00903 a= FFMIN(a,255);
00904 b= FFMIN(b,255);
00905 fgcolor = SDL_MapRGB(screen->format, a, b, (a+b)/2);
00906
00907 fill_rectangle(screen,
00908 s->xpos, s->height-y, 1, 1,
00909 fgcolor);
00910 }
00911 }
00912 SDL_UpdateRect(screen, s->xpos, s->ytop, 1, s->height);
00913 s->xpos++;
00914 if(s->xpos >= s->width)
00915 s->xpos= s->xleft;
00916 }
00917 }
00918
00919 static int video_open(VideoState *is){
00920 int flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
00921 int w,h;
00922
00923 if(is_full_screen) flags |= SDL_FULLSCREEN;
00924 else flags |= SDL_RESIZABLE;
00925
00926 if (is_full_screen && fs_screen_width) {
00927 w = fs_screen_width;
00928 h = fs_screen_height;
00929 } else if(!is_full_screen && screen_width){
00930 w = screen_width;
00931 h = screen_height;
00932 #if CONFIG_AVFILTER
00933 }else if (is->out_video_filter && is->out_video_filter->inputs[0]){
00934 w = is->out_video_filter->inputs[0]->w;
00935 h = is->out_video_filter->inputs[0]->h;
00936 #else
00937 }else if (is->video_st && is->video_st->codec->width){
00938 w = is->video_st->codec->width;
00939 h = is->video_st->codec->height;
00940 #endif
00941 } else {
00942 w = 640;
00943 h = 480;
00944 }
00945 if(screen && is->width == screen->w && screen->w == w
00946 && is->height== screen->h && screen->h == h)
00947 return 0;
00948
00949 #ifndef __APPLE__
00950 screen = SDL_SetVideoMode(w, h, 0, flags);
00951 #else
00952
00953 screen = SDL_SetVideoMode(w, h, 24, flags);
00954 #endif
00955 if (!screen) {
00956 fprintf(stderr, "SDL: could not set video mode - exiting\n");
00957 return -1;
00958 }
00959 if (!window_title)
00960 window_title = input_filename;
00961 SDL_WM_SetCaption(window_title, window_title);
00962
00963 is->width = screen->w;
00964 is->height = screen->h;
00965
00966 return 0;
00967 }
00968
00969
00970 static void video_display(VideoState *is)
00971 {
00972 if(!screen)
00973 video_open(cur_stream);
00974 if (is->audio_st && is->show_audio)
00975 video_audio_display(is);
00976 else if (is->video_st)
00977 video_image_display(is);
00978 }
00979
00980 static int refresh_thread(void *opaque)
00981 {
00982 VideoState *is= opaque;
00983 while(!is->abort_request){
00984 SDL_Event event;
00985 event.type = FF_REFRESH_EVENT;
00986 event.user.data1 = opaque;
00987 if(!is->refresh){
00988 is->refresh=1;
00989 SDL_PushEvent(&event);
00990 }
00991 usleep(is->audio_st && is->show_audio ? rdftspeed*1000 : 5000);
00992 }
00993 return 0;
00994 }
00995
00996
00997 static double get_audio_clock(VideoState *is)
00998 {
00999 double pts;
01000 int hw_buf_size, bytes_per_sec;
01001 pts = is->audio_clock;
01002 hw_buf_size = audio_write_get_buf_size(is);
01003 bytes_per_sec = 0;
01004 if (is->audio_st) {
01005 bytes_per_sec = is->audio_st->codec->sample_rate *
01006 2 * is->audio_st->codec->channels;
01007 }
01008 if (bytes_per_sec)
01009 pts -= (double)hw_buf_size / bytes_per_sec;
01010 return pts;
01011 }
01012
01013
01014 static double get_video_clock(VideoState *is)
01015 {
01016 if (is->paused) {
01017 return is->video_current_pts;
01018 } else {
01019 return is->video_current_pts_drift + av_gettime() / 1000000.0;
01020 }
01021 }
01022
01023
01024 static double get_external_clock(VideoState *is)
01025 {
01026 int64_t ti;
01027 ti = av_gettime();
01028 return is->external_clock + ((ti - is->external_clock_time) * 1e-6);
01029 }
01030
01031
01032 static double get_master_clock(VideoState *is)
01033 {
01034 double val;
01035
01036 if (is->av_sync_type == AV_SYNC_VIDEO_MASTER) {
01037 if (is->video_st)
01038 val = get_video_clock(is);
01039 else
01040 val = get_audio_clock(is);
01041 } else if (is->av_sync_type == AV_SYNC_AUDIO_MASTER) {
01042 if (is->audio_st)
01043 val = get_audio_clock(is);
01044 else
01045 val = get_video_clock(is);
01046 } else {
01047 val = get_external_clock(is);
01048 }
01049 return val;
01050 }
01051
01052
01053 static void stream_seek(VideoState *is, int64_t pos, int64_t rel, int seek_by_bytes)
01054 {
01055 if (!is->seek_req) {
01056 is->seek_pos = pos;
01057 is->seek_rel = rel;
01058 is->seek_flags &= ~AVSEEK_FLAG_BYTE;
01059 if (seek_by_bytes)
01060 is->seek_flags |= AVSEEK_FLAG_BYTE;
01061 is->seek_req = 1;
01062 }
01063 }
01064
01065
01066 static void stream_pause(VideoState *is)
01067 {
01068 if (is->paused) {
01069 is->frame_timer += av_gettime() / 1000000.0 + is->video_current_pts_drift - is->video_current_pts;
01070 if(is->read_pause_return != AVERROR(ENOSYS)){
01071 is->video_current_pts = is->video_current_pts_drift + av_gettime() / 1000000.0;
01072 }
01073 is->video_current_pts_drift = is->video_current_pts - av_gettime() / 1000000.0;
01074 }
01075 is->paused = !is->paused;
01076 }
01077
01078 static double compute_target_time(double frame_current_pts, VideoState *is)
01079 {
01080 double delay, sync_threshold, diff;
01081
01082
01083 delay = frame_current_pts - is->frame_last_pts;
01084 if (delay <= 0 || delay >= 10.0) {
01085
01086 delay = is->frame_last_delay;
01087 } else {
01088 is->frame_last_delay = delay;
01089 }
01090 is->frame_last_pts = frame_current_pts;
01091
01092
01093 if (((is->av_sync_type == AV_SYNC_AUDIO_MASTER && is->audio_st) ||
01094 is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
01095
01096
01097 diff = get_video_clock(is) - get_master_clock(is);
01098
01099
01100
01101
01102 sync_threshold = FFMAX(AV_SYNC_THRESHOLD, delay);
01103 if (fabs(diff) < AV_NOSYNC_THRESHOLD) {
01104 if (diff <= -sync_threshold)
01105 delay = 0;
01106 else if (diff >= sync_threshold)
01107 delay = 2 * delay;
01108 }
01109 }
01110 is->frame_timer += delay;
01111 #if defined(DEBUG_SYNC)
01112 printf("video: delay=%0.3f actual_delay=%0.3f pts=%0.3f A-V=%f\n",
01113 delay, actual_delay, frame_current_pts, -diff);
01114 #endif
01115
01116 return is->frame_timer;
01117 }
01118
01119
01120 static void video_refresh_timer(void *opaque)
01121 {
01122 VideoState *is = opaque;
01123 VideoPicture *vp;
01124
01125 SubPicture *sp, *sp2;
01126
01127 if (is->video_st) {
01128 retry:
01129 if (is->pictq_size == 0) {
01130
01131 } else {
01132 double time= av_gettime()/1000000.0;
01133 double next_target;
01134
01135 vp = &is->pictq[is->pictq_rindex];
01136
01137 if(time < vp->target_clock)
01138 return;
01139
01140 is->video_current_pts = vp->pts;
01141 is->video_current_pts_drift = is->video_current_pts - time;
01142 is->video_current_pos = vp->pos;
01143 if(is->pictq_size > 1){
01144 VideoPicture *nextvp= &is->pictq[(is->pictq_rindex+1)%VIDEO_PICTURE_QUEUE_SIZE];
01145 assert(nextvp->target_clock >= vp->target_clock);
01146 next_target= nextvp->target_clock;
01147 }else{
01148 next_target= vp->target_clock + is->video_clock - vp->pts;
01149 }
01150 if(framedrop && time > next_target){
01151 is->skip_frames *= 1.0 + FRAME_SKIP_FACTOR;
01152 if(is->pictq_size > 1 || time > next_target + 0.5){
01153
01154 if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE)
01155 is->pictq_rindex = 0;
01156
01157 SDL_LockMutex(is->pictq_mutex);
01158 is->pictq_size--;
01159 SDL_CondSignal(is->pictq_cond);
01160 SDL_UnlockMutex(is->pictq_mutex);
01161 goto retry;
01162 }
01163 }
01164
01165 if(is->subtitle_st) {
01166 if (is->subtitle_stream_changed) {
01167 SDL_LockMutex(is->subpq_mutex);
01168
01169 while (is->subpq_size) {
01170 free_subpicture(&is->subpq[is->subpq_rindex]);
01171
01172
01173 if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
01174 is->subpq_rindex = 0;
01175
01176 is->subpq_size--;
01177 }
01178 is->subtitle_stream_changed = 0;
01179
01180 SDL_CondSignal(is->subpq_cond);
01181 SDL_UnlockMutex(is->subpq_mutex);
01182 } else {
01183 if (is->subpq_size > 0) {
01184 sp = &is->subpq[is->subpq_rindex];
01185
01186 if (is->subpq_size > 1)
01187 sp2 = &is->subpq[(is->subpq_rindex + 1) % SUBPICTURE_QUEUE_SIZE];
01188 else
01189 sp2 = NULL;
01190
01191 if ((is->video_current_pts > (sp->pts + ((float) sp->sub.end_display_time / 1000)))
01192 || (sp2 && is->video_current_pts > (sp2->pts + ((float) sp2->sub.start_display_time / 1000))))
01193 {
01194 free_subpicture(sp);
01195
01196
01197 if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
01198 is->subpq_rindex = 0;
01199
01200 SDL_LockMutex(is->subpq_mutex);
01201 is->subpq_size--;
01202 SDL_CondSignal(is->subpq_cond);
01203 SDL_UnlockMutex(is->subpq_mutex);
01204 }
01205 }
01206 }
01207 }
01208
01209
01210 if (!display_disable)
01211 video_display(is);
01212
01213
01214 if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE)
01215 is->pictq_rindex = 0;
01216
01217 SDL_LockMutex(is->pictq_mutex);
01218 is->pictq_size--;
01219 SDL_CondSignal(is->pictq_cond);
01220 SDL_UnlockMutex(is->pictq_mutex);
01221 }
01222 } else if (is->audio_st) {
01223
01224
01225
01226
01227
01228
01229 if (!display_disable)
01230 video_display(is);
01231 }
01232 if (show_status) {
01233 static int64_t last_time;
01234 int64_t cur_time;
01235 int aqsize, vqsize, sqsize;
01236 double av_diff;
01237
01238 cur_time = av_gettime();
01239 if (!last_time || (cur_time - last_time) >= 30000) {
01240 aqsize = 0;
01241 vqsize = 0;
01242 sqsize = 0;
01243 if (is->audio_st)
01244 aqsize = is->audioq.size;
01245 if (is->video_st)
01246 vqsize = is->videoq.size;
01247 if (is->subtitle_st)
01248 sqsize = is->subtitleq.size;
01249 av_diff = 0;
01250 if (is->audio_st && is->video_st)
01251 av_diff = get_audio_clock(is) - get_video_clock(is);
01252 printf("%7.2f A-V:%7.3f s:%3.1f aq=%5dKB vq=%5dKB sq=%5dB f=%"PRId64"/%"PRId64" \r",
01253 get_master_clock(is),
01254 av_diff,
01255 FFMAX(is->skip_frames-1, 0),
01256 aqsize / 1024,
01257 vqsize / 1024,
01258 sqsize,
01259 is->video_st ? is->video_st->codec->pts_correction_num_faulty_dts : 0,
01260 is->video_st ? is->video_st->codec->pts_correction_num_faulty_pts : 0);
01261 fflush(stdout);
01262 last_time = cur_time;
01263 }
01264 }
01265 }
01266
01267 static void stream_close(VideoState *is)
01268 {
01269 VideoPicture *vp;
01270 int i;
01271
01272 is->abort_request = 1;
01273 SDL_WaitThread(is->parse_tid, NULL);
01274 SDL_WaitThread(is->refresh_tid, NULL);
01275
01276
01277 for(i=0;i<VIDEO_PICTURE_QUEUE_SIZE; i++) {
01278 vp = &is->pictq[i];
01279 #if CONFIG_AVFILTER
01280 if (vp->picref) {
01281 avfilter_unref_buffer(vp->picref);
01282 vp->picref = NULL;
01283 }
01284 #endif
01285 if (vp->bmp) {
01286 SDL_FreeYUVOverlay(vp->bmp);
01287 vp->bmp = NULL;
01288 }
01289 }
01290 SDL_DestroyMutex(is->pictq_mutex);
01291 SDL_DestroyCond(is->pictq_cond);
01292 SDL_DestroyMutex(is->subpq_mutex);
01293 SDL_DestroyCond(is->subpq_cond);
01294 #if !CONFIG_AVFILTER
01295 if (is->img_convert_ctx)
01296 sws_freeContext(is->img_convert_ctx);
01297 #endif
01298 av_free(is);
01299 }
01300
01301 static void do_exit(void)
01302 {
01303 if (cur_stream) {
01304 stream_close(cur_stream);
01305 cur_stream = NULL;
01306 }
01307 uninit_opts();
01308 #if CONFIG_AVFILTER
01309 avfilter_uninit();
01310 #endif
01311 if (show_status)
01312 printf("\n");
01313 SDL_Quit();
01314 av_log(NULL, AV_LOG_QUIET, "");
01315 exit(0);
01316 }
01317
01318
01319
01320 static void alloc_picture(void *opaque)
01321 {
01322 VideoState *is = opaque;
01323 VideoPicture *vp;
01324
01325 vp = &is->pictq[is->pictq_windex];
01326
01327 if (vp->bmp)
01328 SDL_FreeYUVOverlay(vp->bmp);
01329
01330 #if CONFIG_AVFILTER
01331 if (vp->picref)
01332 avfilter_unref_buffer(vp->picref);
01333 vp->picref = NULL;
01334
01335 vp->width = is->out_video_filter->inputs[0]->w;
01336 vp->height = is->out_video_filter->inputs[0]->h;
01337 vp->pix_fmt = is->out_video_filter->inputs[0]->format;
01338 #else
01339 vp->width = is->video_st->codec->width;
01340 vp->height = is->video_st->codec->height;
01341 vp->pix_fmt = is->video_st->codec->pix_fmt;
01342 #endif
01343
01344 vp->bmp = SDL_CreateYUVOverlay(vp->width, vp->height,
01345 SDL_YV12_OVERLAY,
01346 screen);
01347 if (!vp->bmp || vp->bmp->pitches[0] < vp->width) {
01348
01349
01350 fprintf(stderr, "Error: the video system does not support an image\n"
01351 "size of %dx%d pixels. Try using -lowres or -vf \"scale=w:h\"\n"
01352 "to reduce the image size.\n", vp->width, vp->height );
01353 do_exit();
01354 }
01355
01356 SDL_LockMutex(is->pictq_mutex);
01357 vp->allocated = 1;
01358 SDL_CondSignal(is->pictq_cond);
01359 SDL_UnlockMutex(is->pictq_mutex);
01360 }
01361
01366 static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, int64_t pos)
01367 {
01368 VideoPicture *vp;
01369 int dst_pix_fmt;
01370 #if CONFIG_AVFILTER
01371 AVPicture pict_src;
01372 #endif
01373
01374 SDL_LockMutex(is->pictq_mutex);
01375
01376 if(is->pictq_size>=VIDEO_PICTURE_QUEUE_SIZE && !is->refresh)
01377 is->skip_frames= FFMAX(1.0 - FRAME_SKIP_FACTOR, is->skip_frames * (1.0-FRAME_SKIP_FACTOR));
01378
01379 while (is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE &&
01380 !is->videoq.abort_request) {
01381 SDL_CondWait(is->pictq_cond, is->pictq_mutex);
01382 }
01383 SDL_UnlockMutex(is->pictq_mutex);
01384
01385 if (is->videoq.abort_request)
01386 return -1;
01387
01388 vp = &is->pictq[is->pictq_windex];
01389
01390
01391 if (!vp->bmp ||
01392 #if CONFIG_AVFILTER
01393 vp->width != is->out_video_filter->inputs[0]->w ||
01394 vp->height != is->out_video_filter->inputs[0]->h) {
01395 #else
01396 vp->width != is->video_st->codec->width ||
01397 vp->height != is->video_st->codec->height) {
01398 #endif
01399 SDL_Event event;
01400
01401 vp->allocated = 0;
01402
01403
01404
01405 event.type = FF_ALLOC_EVENT;
01406 event.user.data1 = is;
01407 SDL_PushEvent(&event);
01408
01409
01410 SDL_LockMutex(is->pictq_mutex);
01411 while (!vp->allocated && !is->videoq.abort_request) {
01412 SDL_CondWait(is->pictq_cond, is->pictq_mutex);
01413 }
01414 SDL_UnlockMutex(is->pictq_mutex);
01415
01416 if (is->videoq.abort_request)
01417 return -1;
01418 }
01419
01420
01421 if (vp->bmp) {
01422 AVPicture pict;
01423 #if CONFIG_AVFILTER
01424 if(vp->picref)
01425 avfilter_unref_buffer(vp->picref);
01426 vp->picref = src_frame->opaque;
01427 #endif
01428
01429
01430 SDL_LockYUVOverlay (vp->bmp);
01431
01432 dst_pix_fmt = PIX_FMT_YUV420P;
01433 memset(&pict,0,sizeof(AVPicture));
01434 pict.data[0] = vp->bmp->pixels[0];
01435 pict.data[1] = vp->bmp->pixels[2];
01436 pict.data[2] = vp->bmp->pixels[1];
01437
01438 pict.linesize[0] = vp->bmp->pitches[0];
01439 pict.linesize[1] = vp->bmp->pitches[2];
01440 pict.linesize[2] = vp->bmp->pitches[1];
01441
01442 #if CONFIG_AVFILTER
01443 pict_src.data[0] = src_frame->data[0];
01444 pict_src.data[1] = src_frame->data[1];
01445 pict_src.data[2] = src_frame->data[2];
01446
01447 pict_src.linesize[0] = src_frame->linesize[0];
01448 pict_src.linesize[1] = src_frame->linesize[1];
01449 pict_src.linesize[2] = src_frame->linesize[2];
01450
01451
01452 av_picture_copy(&pict, &pict_src,
01453 vp->pix_fmt, vp->width, vp->height);
01454 #else
01455 sws_flags = av_get_int(sws_opts, "sws_flags", NULL);
01456 is->img_convert_ctx = sws_getCachedContext(is->img_convert_ctx,
01457 vp->width, vp->height, vp->pix_fmt, vp->width, vp->height,
01458 dst_pix_fmt, sws_flags, NULL, NULL, NULL);
01459 if (is->img_convert_ctx == NULL) {
01460 fprintf(stderr, "Cannot initialize the conversion context\n");
01461 exit(1);
01462 }
01463 sws_scale(is->img_convert_ctx, src_frame->data, src_frame->linesize,
01464 0, vp->height, pict.data, pict.linesize);
01465 #endif
01466
01467 SDL_UnlockYUVOverlay(vp->bmp);
01468
01469 vp->pts = pts;
01470 vp->pos = pos;
01471
01472
01473 if (++is->pictq_windex == VIDEO_PICTURE_QUEUE_SIZE)
01474 is->pictq_windex = 0;
01475 SDL_LockMutex(is->pictq_mutex);
01476 vp->target_clock= compute_target_time(vp->pts, is);
01477
01478 is->pictq_size++;
01479 SDL_UnlockMutex(is->pictq_mutex);
01480 }
01481 return 0;
01482 }
01483
01488 static int output_picture2(VideoState *is, AVFrame *src_frame, double pts1, int64_t pos)
01489 {
01490 double frame_delay, pts;
01491
01492 pts = pts1;
01493
01494 if (pts != 0) {
01495
01496 is->video_clock = pts;
01497 } else {
01498 pts = is->video_clock;
01499 }
01500
01501 frame_delay = av_q2d(is->video_st->codec->time_base);
01502
01503
01504 frame_delay += src_frame->repeat_pict * (frame_delay * 0.5);
01505 is->video_clock += frame_delay;
01506
01507 #if defined(DEBUG_SYNC) && 0
01508 printf("frame_type=%c clock=%0.3f pts=%0.3f\n",
01509 av_get_pict_type_char(src_frame->pict_type), pts, pts1);
01510 #endif
01511 return queue_picture(is, src_frame, pts, pos);
01512 }
01513
01514 static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacket *pkt)
01515 {
01516 int len1, got_picture, i;
01517
01518 if (packet_queue_get(&is->videoq, pkt, 1) < 0)
01519 return -1;
01520
01521 if (pkt->data == flush_pkt.data) {
01522 avcodec_flush_buffers(is->video_st->codec);
01523
01524 SDL_LockMutex(is->pictq_mutex);
01525
01526 for (i = 0; i < VIDEO_PICTURE_QUEUE_SIZE; i++) {
01527 is->pictq[i].target_clock= 0;
01528 }
01529 while (is->pictq_size && !is->videoq.abort_request) {
01530 SDL_CondWait(is->pictq_cond, is->pictq_mutex);
01531 }
01532 is->video_current_pos = -1;
01533 SDL_UnlockMutex(is->pictq_mutex);
01534
01535 is->frame_last_pts = AV_NOPTS_VALUE;
01536 is->frame_last_delay = 0;
01537 is->frame_timer = (double)av_gettime() / 1000000.0;
01538 is->skip_frames = 1;
01539 is->skip_frames_index = 0;
01540 return 0;
01541 }
01542
01543 len1 = avcodec_decode_video2(is->video_st->codec,
01544 frame, &got_picture,
01545 pkt);
01546
01547 if (got_picture) {
01548 if (decoder_reorder_pts == -1) {
01549 *pts = frame->best_effort_timestamp;
01550 } else if (decoder_reorder_pts) {
01551 *pts = frame->pkt_pts;
01552 } else {
01553 *pts = frame->pkt_dts;
01554 }
01555
01556 if (*pts == AV_NOPTS_VALUE) {
01557 *pts = 0;
01558 }
01559
01560 is->skip_frames_index += 1;
01561 if(is->skip_frames_index >= is->skip_frames){
01562 is->skip_frames_index -= FFMAX(is->skip_frames, 1.0);
01563 return 1;
01564 }
01565
01566 }
01567 return 0;
01568 }
01569
01570 #if CONFIG_AVFILTER
01571 typedef struct {
01572 VideoState *is;
01573 AVFrame *frame;
01574 int use_dr1;
01575 } FilterPriv;
01576
01577 static int input_get_buffer(AVCodecContext *codec, AVFrame *pic)
01578 {
01579 AVFilterContext *ctx = codec->opaque;
01580 AVFilterBufferRef *ref;
01581 int perms = AV_PERM_WRITE;
01582 int i, w, h, stride[4];
01583 unsigned edge;
01584
01585 if (codec->codec->capabilities & CODEC_CAP_NEG_LINESIZES)
01586 perms |= AV_PERM_NEG_LINESIZES;
01587
01588 if(pic->buffer_hints & FF_BUFFER_HINTS_VALID) {
01589 if(pic->buffer_hints & FF_BUFFER_HINTS_READABLE) perms |= AV_PERM_READ;
01590 if(pic->buffer_hints & FF_BUFFER_HINTS_PRESERVE) perms |= AV_PERM_PRESERVE;
01591 if(pic->buffer_hints & FF_BUFFER_HINTS_REUSABLE) perms |= AV_PERM_REUSE2;
01592 }
01593 if(pic->reference) perms |= AV_PERM_READ | AV_PERM_PRESERVE;
01594
01595 w = codec->width;
01596 h = codec->height;
01597 avcodec_align_dimensions2(codec, &w, &h, stride);
01598 edge = codec->flags & CODEC_FLAG_EMU_EDGE ? 0 : avcodec_get_edge_width();
01599 w += edge << 1;
01600 h += edge << 1;
01601
01602 if(!(ref = avfilter_get_video_buffer(ctx->outputs[0], perms, w, h)))
01603 return -1;
01604
01605 ref->video->w = codec->width;
01606 ref->video->h = codec->height;
01607 for(i = 0; i < 4; i ++) {
01608 unsigned hshift = (i == 1 || i == 2) ? av_pix_fmt_descriptors[ref->format].log2_chroma_w : 0;
01609 unsigned vshift = (i == 1 || i == 2) ? av_pix_fmt_descriptors[ref->format].log2_chroma_h : 0;
01610
01611 if (ref->data[i]) {
01612 ref->data[i] += (edge >> hshift) + ((edge * ref->linesize[i]) >> vshift);
01613 }
01614 pic->data[i] = ref->data[i];
01615 pic->linesize[i] = ref->linesize[i];
01616 }
01617 pic->opaque = ref;
01618 pic->age = INT_MAX;
01619 pic->type = FF_BUFFER_TYPE_USER;
01620 pic->reordered_opaque = codec->reordered_opaque;
01621 if(codec->pkt) pic->pkt_pts = codec->pkt->pts;
01622 else pic->pkt_pts = AV_NOPTS_VALUE;
01623 return 0;
01624 }
01625
01626 static void input_release_buffer(AVCodecContext *codec, AVFrame *pic)
01627 {
01628 memset(pic->data, 0, sizeof(pic->data));
01629 avfilter_unref_buffer(pic->opaque);
01630 }
01631
01632 static int input_reget_buffer(AVCodecContext *codec, AVFrame *pic)
01633 {
01634 AVFilterBufferRef *ref = pic->opaque;
01635
01636 if (pic->data[0] == NULL) {
01637 pic->buffer_hints |= FF_BUFFER_HINTS_READABLE;
01638 return codec->get_buffer(codec, pic);
01639 }
01640
01641 if ((codec->width != ref->video->w) || (codec->height != ref->video->h) ||
01642 (codec->pix_fmt != ref->format)) {
01643 av_log(codec, AV_LOG_ERROR, "Picture properties changed.\n");
01644 return -1;
01645 }
01646
01647 pic->reordered_opaque = codec->reordered_opaque;
01648 if(codec->pkt) pic->pkt_pts = codec->pkt->pts;
01649 else pic->pkt_pts = AV_NOPTS_VALUE;
01650 return 0;
01651 }
01652
01653 static int input_init(AVFilterContext *ctx, const char *args, void *opaque)
01654 {
01655 FilterPriv *priv = ctx->priv;
01656 AVCodecContext *codec;
01657 if(!opaque) return -1;
01658
01659 priv->is = opaque;
01660 codec = priv->is->video_st->codec;
01661 codec->opaque = ctx;
01662 if(codec->codec->capabilities & CODEC_CAP_DR1) {
01663 priv->use_dr1 = 1;
01664 codec->get_buffer = input_get_buffer;
01665 codec->release_buffer = input_release_buffer;
01666 codec->reget_buffer = input_reget_buffer;
01667 codec->thread_safe_callbacks = 1;
01668 }
01669
01670 priv->frame = avcodec_alloc_frame();
01671
01672 return 0;
01673 }
01674
01675 static void input_uninit(AVFilterContext *ctx)
01676 {
01677 FilterPriv *priv = ctx->priv;
01678 av_free(priv->frame);
01679 }
01680
01681 static int input_request_frame(AVFilterLink *link)
01682 {
01683 FilterPriv *priv = link->src->priv;
01684 AVFilterBufferRef *picref;
01685 int64_t pts = 0;
01686 AVPacket pkt;
01687 int ret;
01688
01689 while (!(ret = get_video_frame(priv->is, priv->frame, &pts, &pkt)))
01690 av_free_packet(&pkt);
01691 if (ret < 0)
01692 return -1;
01693
01694 if(priv->use_dr1) {
01695 picref = avfilter_ref_buffer(priv->frame->opaque, ~0);
01696 } else {
01697 picref = avfilter_get_video_buffer(link, AV_PERM_WRITE, link->w, link->h);
01698 av_image_copy(picref->data, picref->linesize,
01699 priv->frame->data, priv->frame->linesize,
01700 picref->format, link->w, link->h);
01701 }
01702 av_free_packet(&pkt);
01703
01704 picref->pts = pts;
01705 picref->pos = pkt.pos;
01706 picref->video->pixel_aspect = priv->is->video_st->codec->sample_aspect_ratio;
01707 avfilter_start_frame(link, picref);
01708 avfilter_draw_slice(link, 0, link->h, 1);
01709 avfilter_end_frame(link);
01710
01711 return 0;
01712 }
01713
01714 static int input_query_formats(AVFilterContext *ctx)
01715 {
01716 FilterPriv *priv = ctx->priv;
01717 enum PixelFormat pix_fmts[] = {
01718 priv->is->video_st->codec->pix_fmt, PIX_FMT_NONE
01719 };
01720
01721 avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts));
01722 return 0;
01723 }
01724
01725 static int input_config_props(AVFilterLink *link)
01726 {
01727 FilterPriv *priv = link->src->priv;
01728 AVCodecContext *c = priv->is->video_st->codec;
01729
01730 link->w = c->width;
01731 link->h = c->height;
01732 link->time_base = priv->is->video_st->time_base;
01733
01734 return 0;
01735 }
01736
01737 static AVFilter input_filter =
01738 {
01739 .name = "ffplay_input",
01740
01741 .priv_size = sizeof(FilterPriv),
01742
01743 .init = input_init,
01744 .uninit = input_uninit,
01745
01746 .query_formats = input_query_formats,
01747
01748 .inputs = (AVFilterPad[]) {{ .name = NULL }},
01749 .outputs = (AVFilterPad[]) {{ .name = "default",
01750 .type = AVMEDIA_TYPE_VIDEO,
01751 .request_frame = input_request_frame,
01752 .config_props = input_config_props, },
01753 { .name = NULL }},
01754 };
01755
01756 static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const char *vfilters)
01757 {
01758 char sws_flags_str[128];
01759 int ret;
01760 FFSinkContext ffsink_ctx = { .pix_fmt = PIX_FMT_YUV420P };
01761 AVFilterContext *filt_src = NULL, *filt_out = NULL;
01762 snprintf(sws_flags_str, sizeof(sws_flags_str), "flags=%d", sws_flags);
01763 graph->scale_sws_opts = av_strdup(sws_flags_str);
01764
01765 if ((ret = avfilter_graph_create_filter(&filt_src, &input_filter, "src",
01766 NULL, is, graph)) < 0)
01767 goto the_end;
01768 if ((ret = avfilter_graph_create_filter(&filt_out, &ffsink, "out",
01769 NULL, &ffsink_ctx, graph)) < 0)
01770 goto the_end;
01771
01772 if(vfilters) {
01773 AVFilterInOut *outputs = av_malloc(sizeof(AVFilterInOut));
01774 AVFilterInOut *inputs = av_malloc(sizeof(AVFilterInOut));
01775
01776 outputs->name = av_strdup("in");
01777 outputs->filter_ctx = filt_src;
01778 outputs->pad_idx = 0;
01779 outputs->next = NULL;
01780
01781 inputs->name = av_strdup("out");
01782 inputs->filter_ctx = filt_out;
01783 inputs->pad_idx = 0;
01784 inputs->next = NULL;
01785
01786 if ((ret = avfilter_graph_parse(graph, vfilters, inputs, outputs, NULL)) < 0)
01787 goto the_end;
01788 av_freep(&vfilters);
01789 } else {
01790 if ((ret = avfilter_link(filt_src, 0, filt_out, 0)) < 0)
01791 goto the_end;
01792 }
01793
01794 if ((ret = avfilter_graph_config(graph, NULL)) < 0)
01795 goto the_end;
01796
01797 is->out_video_filter = filt_out;
01798 the_end:
01799 return ret;
01800 }
01801
01802 #endif
01803
01804 static int video_thread(void *arg)
01805 {
01806 VideoState *is = arg;
01807 AVFrame *frame= avcodec_alloc_frame();
01808 int64_t pts_int;
01809 double pts;
01810 int ret;
01811
01812 #if CONFIG_AVFILTER
01813 AVFilterGraph *graph = avfilter_graph_alloc();
01814 AVFilterContext *filt_out = NULL;
01815 int64_t pos;
01816
01817 if ((ret = configure_video_filters(graph, is, vfilters)) < 0)
01818 goto the_end;
01819 filt_out = is->out_video_filter;
01820 #endif
01821
01822 for(;;) {
01823 #if !CONFIG_AVFILTER
01824 AVPacket pkt;
01825 #else
01826 AVFilterBufferRef *picref;
01827 AVRational tb;
01828 #endif
01829 while (is->paused && !is->videoq.abort_request)
01830 SDL_Delay(10);
01831 #if CONFIG_AVFILTER
01832 ret = get_filtered_video_frame(filt_out, frame, &picref, &tb);
01833 if (picref) {
01834 pts_int = picref->pts;
01835 pos = picref->pos;
01836 frame->opaque = picref;
01837 }
01838
01839 if (av_cmp_q(tb, is->video_st->time_base)) {
01840 av_unused int64_t pts1 = pts_int;
01841 pts_int = av_rescale_q(pts_int, tb, is->video_st->time_base);
01842 av_dlog(NULL, "video_thread(): "
01843 "tb:%d/%d pts:%"PRId64" -> tb:%d/%d pts:%"PRId64"\n",
01844 tb.num, tb.den, pts1,
01845 is->video_st->time_base.num, is->video_st->time_base.den, pts_int);
01846 }
01847 #else
01848 ret = get_video_frame(is, frame, &pts_int, &pkt);
01849 #endif
01850
01851 if (ret < 0) goto the_end;
01852
01853 if (!ret)
01854 continue;
01855
01856 pts = pts_int*av_q2d(is->video_st->time_base);
01857
01858 #if CONFIG_AVFILTER
01859 ret = output_picture2(is, frame, pts, pos);
01860 #else
01861 ret = output_picture2(is, frame, pts, pkt.pos);
01862 av_free_packet(&pkt);
01863 #endif
01864 if (ret < 0)
01865 goto the_end;
01866
01867 if (step)
01868 if (cur_stream)
01869 stream_pause(cur_stream);
01870 }
01871 the_end:
01872 #if CONFIG_AVFILTER
01873 avfilter_graph_free(&graph);
01874 #endif
01875 av_free(frame);
01876 return 0;
01877 }
01878
01879 static int subtitle_thread(void *arg)
01880 {
01881 VideoState *is = arg;
01882 SubPicture *sp;
01883 AVPacket pkt1, *pkt = &pkt1;
01884 int len1, got_subtitle;
01885 double pts;
01886 int i, j;
01887 int r, g, b, y, u, v, a;
01888
01889 for(;;) {
01890 while (is->paused && !is->subtitleq.abort_request) {
01891 SDL_Delay(10);
01892 }
01893 if (packet_queue_get(&is->subtitleq, pkt, 1) < 0)
01894 break;
01895
01896 if(pkt->data == flush_pkt.data){
01897 avcodec_flush_buffers(is->subtitle_st->codec);
01898 continue;
01899 }
01900 SDL_LockMutex(is->subpq_mutex);
01901 while (is->subpq_size >= SUBPICTURE_QUEUE_SIZE &&
01902 !is->subtitleq.abort_request) {
01903 SDL_CondWait(is->subpq_cond, is->subpq_mutex);
01904 }
01905 SDL_UnlockMutex(is->subpq_mutex);
01906
01907 if (is->subtitleq.abort_request)
01908 goto the_end;
01909
01910 sp = &is->subpq[is->subpq_windex];
01911
01912
01913
01914 pts = 0;
01915 if (pkt->pts != AV_NOPTS_VALUE)
01916 pts = av_q2d(is->subtitle_st->time_base)*pkt->pts;
01917
01918 len1 = avcodec_decode_subtitle2(is->subtitle_st->codec,
01919 &sp->sub, &got_subtitle,
01920 pkt);
01921
01922
01923 if (got_subtitle && sp->sub.format == 0) {
01924 sp->pts = pts;
01925
01926 for (i = 0; i < sp->sub.num_rects; i++)
01927 {
01928 for (j = 0; j < sp->sub.rects[i]->nb_colors; j++)
01929 {
01930 RGBA_IN(r, g, b, a, (uint32_t*)sp->sub.rects[i]->pict.data[1] + j);
01931 y = RGB_TO_Y_CCIR(r, g, b);
01932 u = RGB_TO_U_CCIR(r, g, b, 0);
01933 v = RGB_TO_V_CCIR(r, g, b, 0);
01934 YUVA_OUT((uint32_t*)sp->sub.rects[i]->pict.data[1] + j, y, u, v, a);
01935 }
01936 }
01937
01938
01939 if (++is->subpq_windex == SUBPICTURE_QUEUE_SIZE)
01940 is->subpq_windex = 0;
01941 SDL_LockMutex(is->subpq_mutex);
01942 is->subpq_size++;
01943 SDL_UnlockMutex(is->subpq_mutex);
01944 }
01945 av_free_packet(pkt);
01946
01947
01948
01949 }
01950 the_end:
01951 return 0;
01952 }
01953
01954
01955 static void update_sample_display(VideoState *is, short *samples, int samples_size)
01956 {
01957 int size, len, channels;
01958
01959 channels = is->audio_st->codec->channels;
01960
01961 size = samples_size / sizeof(short);
01962 while (size > 0) {
01963 len = SAMPLE_ARRAY_SIZE - is->sample_array_index;
01964 if (len > size)
01965 len = size;
01966 memcpy(is->sample_array + is->sample_array_index, samples, len * sizeof(short));
01967 samples += len;
01968 is->sample_array_index += len;
01969 if (is->sample_array_index >= SAMPLE_ARRAY_SIZE)
01970 is->sample_array_index = 0;
01971 size -= len;
01972 }
01973 }
01974
01975
01976
01977 static int synchronize_audio(VideoState *is, short *samples,
01978 int samples_size1, double pts)
01979 {
01980 int n, samples_size;
01981 double ref_clock;
01982
01983 n = 2 * is->audio_st->codec->channels;
01984 samples_size = samples_size1;
01985
01986
01987 if (((is->av_sync_type == AV_SYNC_VIDEO_MASTER && is->video_st) ||
01988 is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
01989 double diff, avg_diff;
01990 int wanted_size, min_size, max_size, nb_samples;
01991
01992 ref_clock = get_master_clock(is);
01993 diff = get_audio_clock(is) - ref_clock;
01994
01995 if (diff < AV_NOSYNC_THRESHOLD) {
01996 is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum;
01997 if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {
01998
01999 is->audio_diff_avg_count++;
02000 } else {
02001
02002 avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef);
02003
02004 if (fabs(avg_diff) >= is->audio_diff_threshold) {
02005 wanted_size = samples_size + ((int)(diff * is->audio_st->codec->sample_rate) * n);
02006 nb_samples = samples_size / n;
02007
02008 min_size = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
02009 max_size = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
02010 if (wanted_size < min_size)
02011 wanted_size = min_size;
02012 else if (wanted_size > max_size)
02013 wanted_size = max_size;
02014
02015
02016 if (wanted_size < samples_size) {
02017
02018 samples_size = wanted_size;
02019 } else if (wanted_size > samples_size) {
02020 uint8_t *samples_end, *q;
02021 int nb;
02022
02023
02024 nb = (samples_size - wanted_size);
02025 samples_end = (uint8_t *)samples + samples_size - n;
02026 q = samples_end + n;
02027 while (nb > 0) {
02028 memcpy(q, samples_end, n);
02029 q += n;
02030 nb -= n;
02031 }
02032 samples_size = wanted_size;
02033 }
02034 }
02035 #if 0
02036 printf("diff=%f adiff=%f sample_diff=%d apts=%0.3f vpts=%0.3f %f\n",
02037 diff, avg_diff, samples_size - samples_size1,
02038 is->audio_clock, is->video_clock, is->audio_diff_threshold);
02039 #endif
02040 }
02041 } else {
02042
02043
02044 is->audio_diff_avg_count = 0;
02045 is->audio_diff_cum = 0;
02046 }
02047 }
02048
02049 return samples_size;
02050 }
02051
02052
02053 static int audio_decode_frame(VideoState *is, double *pts_ptr)
02054 {
02055 AVPacket *pkt_temp = &is->audio_pkt_temp;
02056 AVPacket *pkt = &is->audio_pkt;
02057 AVCodecContext *dec= is->audio_st->codec;
02058 int n, len1, data_size;
02059 double pts;
02060
02061 for(;;) {
02062
02063 while (pkt_temp->size > 0) {
02064 data_size = sizeof(is->audio_buf1);
02065 len1 = avcodec_decode_audio3(dec,
02066 (int16_t *)is->audio_buf1, &data_size,
02067 pkt_temp);
02068 if (len1 < 0) {
02069
02070 pkt_temp->size = 0;
02071 break;
02072 }
02073
02074 pkt_temp->data += len1;
02075 pkt_temp->size -= len1;
02076 if (data_size <= 0)
02077 continue;
02078
02079 if (dec->sample_fmt != is->audio_src_fmt) {
02080 if (is->reformat_ctx)
02081 av_audio_convert_free(is->reformat_ctx);
02082 is->reformat_ctx= av_audio_convert_alloc(AV_SAMPLE_FMT_S16, 1,
02083 dec->sample_fmt, 1, NULL, 0);
02084 if (!is->reformat_ctx) {
02085 fprintf(stderr, "Cannot convert %s sample format to %s sample format\n",
02086 av_get_sample_fmt_name(dec->sample_fmt),
02087 av_get_sample_fmt_name(AV_SAMPLE_FMT_S16));
02088 break;
02089 }
02090 is->audio_src_fmt= dec->sample_fmt;
02091 }
02092
02093 if (is->reformat_ctx) {
02094 const void *ibuf[6]= {is->audio_buf1};
02095 void *obuf[6]= {is->audio_buf2};
02096 int istride[6]= {av_get_bits_per_sample_fmt(dec->sample_fmt)/8};
02097 int ostride[6]= {2};
02098 int len= data_size/istride[0];
02099 if (av_audio_convert(is->reformat_ctx, obuf, ostride, ibuf, istride, len)<0) {
02100 printf("av_audio_convert() failed\n");
02101 break;
02102 }
02103 is->audio_buf= is->audio_buf2;
02104
02105
02106 data_size= len*2;
02107 }else{
02108 is->audio_buf= is->audio_buf1;
02109 }
02110
02111
02112 pts = is->audio_clock;
02113 *pts_ptr = pts;
02114 n = 2 * dec->channels;
02115 is->audio_clock += (double)data_size /
02116 (double)(n * dec->sample_rate);
02117 #if defined(DEBUG_SYNC)
02118 {
02119 static double last_clock;
02120 printf("audio: delay=%0.3f clock=%0.3f pts=%0.3f\n",
02121 is->audio_clock - last_clock,
02122 is->audio_clock, pts);
02123 last_clock = is->audio_clock;
02124 }
02125 #endif
02126 return data_size;
02127 }
02128
02129
02130 if (pkt->data)
02131 av_free_packet(pkt);
02132
02133 if (is->paused || is->audioq.abort_request) {
02134 return -1;
02135 }
02136
02137
02138 if (packet_queue_get(&is->audioq, pkt, 1) < 0)
02139 return -1;
02140 if(pkt->data == flush_pkt.data){
02141 avcodec_flush_buffers(dec);
02142 continue;
02143 }
02144
02145 pkt_temp->data = pkt->data;
02146 pkt_temp->size = pkt->size;
02147
02148
02149 if (pkt->pts != AV_NOPTS_VALUE) {
02150 is->audio_clock = av_q2d(is->audio_st->time_base)*pkt->pts;
02151 }
02152 }
02153 }
02154
02155
02156
02157 static int audio_write_get_buf_size(VideoState *is)
02158 {
02159 return is->audio_buf_size - is->audio_buf_index;
02160 }
02161
02162
02163
02164 static void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
02165 {
02166 VideoState *is = opaque;
02167 int audio_size, len1;
02168 double pts;
02169
02170 audio_callback_time = av_gettime();
02171
02172 while (len > 0) {
02173 if (is->audio_buf_index >= is->audio_buf_size) {
02174 audio_size = audio_decode_frame(is, &pts);
02175 if (audio_size < 0) {
02176
02177 is->audio_buf = is->audio_buf1;
02178 is->audio_buf_size = 1024;
02179 memset(is->audio_buf, 0, is->audio_buf_size);
02180 } else {
02181 if (is->show_audio)
02182 update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
02183 audio_size = synchronize_audio(is, (int16_t *)is->audio_buf, audio_size,
02184 pts);
02185 is->audio_buf_size = audio_size;
02186 }
02187 is->audio_buf_index = 0;
02188 }
02189 len1 = is->audio_buf_size - is->audio_buf_index;
02190 if (len1 > len)
02191 len1 = len;
02192 memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
02193 len -= len1;
02194 stream += len1;
02195 is->audio_buf_index += len1;
02196 }
02197 }
02198
02199
02200 static int stream_component_open(VideoState *is, int stream_index)
02201 {
02202 AVFormatContext *ic = is->ic;
02203 AVCodecContext *avctx;
02204 AVCodec *codec;
02205 SDL_AudioSpec wanted_spec, spec;
02206
02207 if (stream_index < 0 || stream_index >= ic->nb_streams)
02208 return -1;
02209 avctx = ic->streams[stream_index]->codec;
02210
02211
02212 if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) {
02213 if (avctx->channels > 0) {
02214 avctx->request_channels = FFMIN(2, avctx->channels);
02215 } else {
02216 avctx->request_channels = 2;
02217 }
02218 }
02219
02220 codec = avcodec_find_decoder(avctx->codec_id);
02221 avctx->debug_mv = debug_mv;
02222 avctx->debug = debug;
02223 avctx->workaround_bugs = workaround_bugs;
02224 avctx->lowres = lowres;
02225 if(lowres) avctx->flags |= CODEC_FLAG_EMU_EDGE;
02226 avctx->idct_algo= idct;
02227 if(fast) avctx->flags2 |= CODEC_FLAG2_FAST;
02228 avctx->skip_frame= skip_frame;
02229 avctx->skip_idct= skip_idct;
02230 avctx->skip_loop_filter= skip_loop_filter;
02231 avctx->error_recognition= error_recognition;
02232 avctx->error_concealment= error_concealment;
02233 avctx->thread_count= thread_count;
02234
02235 set_context_opts(avctx, avcodec_opts[avctx->codec_type], 0, codec);
02236
02237 if (!codec ||
02238 avcodec_open(avctx, codec) < 0)
02239 return -1;
02240
02241
02242 if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) {
02243 wanted_spec.freq = avctx->sample_rate;
02244 wanted_spec.format = AUDIO_S16SYS;
02245 wanted_spec.channels = avctx->channels;
02246 wanted_spec.silence = 0;
02247 wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
02248 wanted_spec.callback = sdl_audio_callback;
02249 wanted_spec.userdata = is;
02250 if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
02251 fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());
02252 return -1;
02253 }
02254 is->audio_hw_buf_size = spec.size;
02255 is->audio_src_fmt= AV_SAMPLE_FMT_S16;
02256 }
02257
02258 ic->streams[stream_index]->discard = AVDISCARD_DEFAULT;
02259 switch(avctx->codec_type) {
02260 case AVMEDIA_TYPE_AUDIO:
02261 is->audio_stream = stream_index;
02262 is->audio_st = ic->streams[stream_index];
02263 is->audio_buf_size = 0;
02264 is->audio_buf_index = 0;
02265
02266
02267 is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
02268 is->audio_diff_avg_count = 0;
02269
02270
02271 is->audio_diff_threshold = 2.0 * SDL_AUDIO_BUFFER_SIZE / avctx->sample_rate;
02272
02273 memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
02274 packet_queue_init(&is->audioq);
02275 SDL_PauseAudio(0);
02276 break;
02277 case AVMEDIA_TYPE_VIDEO:
02278 is->video_stream = stream_index;
02279 is->video_st = ic->streams[stream_index];
02280
02281
02282
02283 packet_queue_init(&is->videoq);
02284 is->video_tid = SDL_CreateThread(video_thread, is);
02285 break;
02286 case AVMEDIA_TYPE_SUBTITLE:
02287 is->subtitle_stream = stream_index;
02288 is->subtitle_st = ic->streams[stream_index];
02289 packet_queue_init(&is->subtitleq);
02290
02291 is->subtitle_tid = SDL_CreateThread(subtitle_thread, is);
02292 break;
02293 default:
02294 break;
02295 }
02296 return 0;
02297 }
02298
02299 static void stream_component_close(VideoState *is, int stream_index)
02300 {
02301 AVFormatContext *ic = is->ic;
02302 AVCodecContext *avctx;
02303
02304 if (stream_index < 0 || stream_index >= ic->nb_streams)
02305 return;
02306 avctx = ic->streams[stream_index]->codec;
02307
02308 switch(avctx->codec_type) {
02309 case AVMEDIA_TYPE_AUDIO:
02310 packet_queue_abort(&is->audioq);
02311
02312 SDL_CloseAudio();
02313
02314 packet_queue_end(&is->audioq);
02315 if (is->reformat_ctx)
02316 av_audio_convert_free(is->reformat_ctx);
02317 is->reformat_ctx = NULL;
02318 break;
02319 case AVMEDIA_TYPE_VIDEO:
02320 packet_queue_abort(&is->videoq);
02321
02322
02323
02324 SDL_LockMutex(is->pictq_mutex);
02325 SDL_CondSignal(is->pictq_cond);
02326 SDL_UnlockMutex(is->pictq_mutex);
02327
02328 SDL_WaitThread(is->video_tid, NULL);
02329
02330 packet_queue_end(&is->videoq);
02331 break;
02332 case AVMEDIA_TYPE_SUBTITLE:
02333 packet_queue_abort(&is->subtitleq);
02334
02335
02336
02337 SDL_LockMutex(is->subpq_mutex);
02338 is->subtitle_stream_changed = 1;
02339
02340 SDL_CondSignal(is->subpq_cond);
02341 SDL_UnlockMutex(is->subpq_mutex);
02342
02343 SDL_WaitThread(is->subtitle_tid, NULL);
02344
02345 packet_queue_end(&is->subtitleq);
02346 break;
02347 default:
02348 break;
02349 }
02350
02351 ic->streams[stream_index]->discard = AVDISCARD_ALL;
02352 avcodec_close(avctx);
02353 switch(avctx->codec_type) {
02354 case AVMEDIA_TYPE_AUDIO:
02355 is->audio_st = NULL;
02356 is->audio_stream = -1;
02357 break;
02358 case AVMEDIA_TYPE_VIDEO:
02359 is->video_st = NULL;
02360 is->video_stream = -1;
02361 break;
02362 case AVMEDIA_TYPE_SUBTITLE:
02363 is->subtitle_st = NULL;
02364 is->subtitle_stream = -1;
02365 break;
02366 default:
02367 break;
02368 }
02369 }
02370
02371
02372
02373 static VideoState *global_video_state;
02374
02375 static int decode_interrupt_cb(void)
02376 {
02377 return (global_video_state && global_video_state->abort_request);
02378 }
02379
02380
02381 static int decode_thread(void *arg)
02382 {
02383 VideoState *is = arg;
02384 AVFormatContext *ic;
02385 int err, i, ret;
02386 int st_index[AVMEDIA_TYPE_NB];
02387 AVPacket pkt1, *pkt = &pkt1;
02388 AVFormatParameters params, *ap = ¶ms;
02389 int eof=0;
02390 int pkt_in_play_range = 0;
02391
02392 ic = avformat_alloc_context();
02393
02394 memset(st_index, -1, sizeof(st_index));
02395 is->video_stream = -1;
02396 is->audio_stream = -1;
02397 is->subtitle_stream = -1;
02398
02399 global_video_state = is;
02400 url_set_interrupt_cb(decode_interrupt_cb);
02401
02402 memset(ap, 0, sizeof(*ap));
02403
02404 ap->prealloced_context = 1;
02405 ap->width = frame_width;
02406 ap->height= frame_height;
02407 ap->time_base= (AVRational){1, 25};
02408 ap->pix_fmt = frame_pix_fmt;
02409
02410 set_context_opts(ic, avformat_opts, AV_OPT_FLAG_DECODING_PARAM, NULL);
02411
02412 err = av_open_input_file(&ic, is->filename, is->iformat, 0, ap);
02413 if (err < 0) {
02414 print_error(is->filename, err);
02415 ret = -1;
02416 goto fail;
02417 }
02418 is->ic = ic;
02419
02420 if(genpts)
02421 ic->flags |= AVFMT_FLAG_GENPTS;
02422
02423 err = av_find_stream_info(ic);
02424 if (err < 0) {
02425 fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
02426 ret = -1;
02427 goto fail;
02428 }
02429 if(ic->pb)
02430 ic->pb->eof_reached= 0;
02431
02432 if(seek_by_bytes<0)
02433 seek_by_bytes= !!(ic->iformat->flags & AVFMT_TS_DISCONT);
02434
02435
02436 if (start_time != AV_NOPTS_VALUE) {
02437 int64_t timestamp;
02438
02439 timestamp = start_time;
02440
02441 if (ic->start_time != AV_NOPTS_VALUE)
02442 timestamp += ic->start_time;
02443 ret = avformat_seek_file(ic, -1, INT64_MIN, timestamp, INT64_MAX, 0);
02444 if (ret < 0) {
02445 fprintf(stderr, "%s: could not seek to position %0.3f\n",
02446 is->filename, (double)timestamp / AV_TIME_BASE);
02447 }
02448 }
02449
02450 for (i = 0; i < ic->nb_streams; i++)
02451 ic->streams[i]->discard = AVDISCARD_ALL;
02452 if (!video_disable)
02453 st_index[AVMEDIA_TYPE_VIDEO] =
02454 av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO,
02455 wanted_stream[AVMEDIA_TYPE_VIDEO], -1, NULL, 0);
02456 if (!audio_disable)
02457 st_index[AVMEDIA_TYPE_AUDIO] =
02458 av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO,
02459 wanted_stream[AVMEDIA_TYPE_AUDIO],
02460 st_index[AVMEDIA_TYPE_VIDEO],
02461 NULL, 0);
02462 if (!video_disable)
02463 st_index[AVMEDIA_TYPE_SUBTITLE] =
02464 av_find_best_stream(ic, AVMEDIA_TYPE_SUBTITLE,
02465 wanted_stream[AVMEDIA_TYPE_SUBTITLE],
02466 (st_index[AVMEDIA_TYPE_AUDIO] >= 0 ?
02467 st_index[AVMEDIA_TYPE_AUDIO] :
02468 st_index[AVMEDIA_TYPE_VIDEO]),
02469 NULL, 0);
02470 if (show_status) {
02471 av_dump_format(ic, 0, is->filename, 0);
02472 }
02473
02474
02475 if (st_index[AVMEDIA_TYPE_AUDIO] >= 0) {
02476 stream_component_open(is, st_index[AVMEDIA_TYPE_AUDIO]);
02477 }
02478
02479 ret=-1;
02480 if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) {
02481 ret= stream_component_open(is, st_index[AVMEDIA_TYPE_VIDEO]);
02482 }
02483 is->refresh_tid = SDL_CreateThread(refresh_thread, is);
02484 if(ret<0) {
02485 if (!display_disable)
02486 is->show_audio = 2;
02487 }
02488
02489 if (st_index[AVMEDIA_TYPE_SUBTITLE] >= 0) {
02490 stream_component_open(is, st_index[AVMEDIA_TYPE_SUBTITLE]);
02491 }
02492
02493 if (is->video_stream < 0 && is->audio_stream < 0) {
02494 fprintf(stderr, "%s: could not open codecs\n", is->filename);
02495 ret = -1;
02496 goto fail;
02497 }
02498
02499 for(;;) {
02500 if (is->abort_request)
02501 break;
02502 if (is->paused != is->last_paused) {
02503 is->last_paused = is->paused;
02504 if (is->paused)
02505 is->read_pause_return= av_read_pause(ic);
02506 else
02507 av_read_play(ic);
02508 }
02509 #if CONFIG_RTSP_DEMUXER
02510 if (is->paused && !strcmp(ic->iformat->name, "rtsp")) {
02511
02512
02513 SDL_Delay(10);
02514 continue;
02515 }
02516 #endif
02517 if (is->seek_req) {
02518 int64_t seek_target= is->seek_pos;
02519 int64_t seek_min= is->seek_rel > 0 ? seek_target - is->seek_rel + 2: INT64_MIN;
02520 int64_t seek_max= is->seek_rel < 0 ? seek_target - is->seek_rel - 2: INT64_MAX;
02521
02522
02523
02524 ret = avformat_seek_file(is->ic, -1, seek_min, seek_target, seek_max, is->seek_flags);
02525 if (ret < 0) {
02526 fprintf(stderr, "%s: error while seeking\n", is->ic->filename);
02527 }else{
02528 if (is->audio_stream >= 0) {
02529 packet_queue_flush(&is->audioq);
02530 packet_queue_put(&is->audioq, &flush_pkt);
02531 }
02532 if (is->subtitle_stream >= 0) {
02533 packet_queue_flush(&is->subtitleq);
02534 packet_queue_put(&is->subtitleq, &flush_pkt);
02535 }
02536 if (is->video_stream >= 0) {
02537 packet_queue_flush(&is->videoq);
02538 packet_queue_put(&is->videoq, &flush_pkt);
02539 }
02540 }
02541 is->seek_req = 0;
02542 eof= 0;
02543 }
02544
02545
02546 if ( is->audioq.size + is->videoq.size + is->subtitleq.size > MAX_QUEUE_SIZE
02547 || ( (is->audioq .size > MIN_AUDIOQ_SIZE || is->audio_stream<0)
02548 && (is->videoq .nb_packets > MIN_FRAMES || is->video_stream<0)
02549 && (is->subtitleq.nb_packets > MIN_FRAMES || is->subtitle_stream<0))) {
02550
02551 SDL_Delay(10);
02552 continue;
02553 }
02554 if(eof) {
02555 if(is->video_stream >= 0){
02556 av_init_packet(pkt);
02557 pkt->data=NULL;
02558 pkt->size=0;
02559 pkt->stream_index= is->video_stream;
02560 packet_queue_put(&is->videoq, pkt);
02561 }
02562 SDL_Delay(10);
02563 if(is->audioq.size + is->videoq.size + is->subtitleq.size ==0){
02564 if(loop!=1 && (!loop || --loop)){
02565 stream_seek(cur_stream, start_time != AV_NOPTS_VALUE ? start_time : 0, 0, 0);
02566 }else if(autoexit){
02567 ret=AVERROR_EOF;
02568 goto fail;
02569 }
02570 }
02571 eof=0;
02572 continue;
02573 }
02574 ret = av_read_frame(ic, pkt);
02575 if (ret < 0) {
02576 if (ret == AVERROR_EOF || url_feof(ic->pb))
02577 eof=1;
02578 if (ic->pb && ic->pb->error)
02579 break;
02580 SDL_Delay(100);
02581 continue;
02582 }
02583
02584 pkt_in_play_range = duration == AV_NOPTS_VALUE ||
02585 (pkt->pts - ic->streams[pkt->stream_index]->start_time) *
02586 av_q2d(ic->streams[pkt->stream_index]->time_base) -
02587 (double)(start_time != AV_NOPTS_VALUE ? start_time : 0)/1000000
02588 <= ((double)duration/1000000);
02589 if (pkt->stream_index == is->audio_stream && pkt_in_play_range) {
02590 packet_queue_put(&is->audioq, pkt);
02591 } else if (pkt->stream_index == is->video_stream && pkt_in_play_range) {
02592 packet_queue_put(&is->videoq, pkt);
02593 } else if (pkt->stream_index == is->subtitle_stream && pkt_in_play_range) {
02594 packet_queue_put(&is->subtitleq, pkt);
02595 } else {
02596 av_free_packet(pkt);
02597 }
02598 }
02599
02600 while (!is->abort_request) {
02601 SDL_Delay(100);
02602 }
02603
02604 ret = 0;
02605 fail:
02606
02607 global_video_state = NULL;
02608
02609
02610 if (is->audio_stream >= 0)
02611 stream_component_close(is, is->audio_stream);
02612 if (is->video_stream >= 0)
02613 stream_component_close(is, is->video_stream);
02614 if (is->subtitle_stream >= 0)
02615 stream_component_close(is, is->subtitle_stream);
02616 if (is->ic) {
02617 av_close_input_file(is->ic);
02618 is->ic = NULL;
02619 }
02620 url_set_interrupt_cb(NULL);
02621
02622 if (ret != 0) {
02623 SDL_Event event;
02624
02625 event.type = FF_QUIT_EVENT;
02626 event.user.data1 = is;
02627 SDL_PushEvent(&event);
02628 }
02629 return 0;
02630 }
02631
02632 static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
02633 {
02634 VideoState *is;
02635
02636 is = av_mallocz(sizeof(VideoState));
02637 if (!is)
02638 return NULL;
02639 av_strlcpy(is->filename, filename, sizeof(is->filename));
02640 is->iformat = iformat;
02641 is->ytop = 0;
02642 is->xleft = 0;
02643
02644
02645 is->pictq_mutex = SDL_CreateMutex();
02646 is->pictq_cond = SDL_CreateCond();
02647
02648 is->subpq_mutex = SDL_CreateMutex();
02649 is->subpq_cond = SDL_CreateCond();
02650
02651 is->av_sync_type = av_sync_type;
02652 is->parse_tid = SDL_CreateThread(decode_thread, is);
02653 if (!is->parse_tid) {
02654 av_free(is);
02655 return NULL;
02656 }
02657 return is;
02658 }
02659
02660 static void stream_cycle_channel(VideoState *is, int codec_type)
02661 {
02662 AVFormatContext *ic = is->ic;
02663 int start_index, stream_index;
02664 AVStream *st;
02665
02666 if (codec_type == AVMEDIA_TYPE_VIDEO)
02667 start_index = is->video_stream;
02668 else if (codec_type == AVMEDIA_TYPE_AUDIO)
02669 start_index = is->audio_stream;
02670 else
02671 start_index = is->subtitle_stream;
02672 if (start_index < (codec_type == AVMEDIA_TYPE_SUBTITLE ? -1 : 0))
02673 return;
02674 stream_index = start_index;
02675 for(;;) {
02676 if (++stream_index >= is->ic->nb_streams)
02677 {
02678 if (codec_type == AVMEDIA_TYPE_SUBTITLE)
02679 {
02680 stream_index = -1;
02681 goto the_end;
02682 } else
02683 stream_index = 0;
02684 }
02685 if (stream_index == start_index)
02686 return;
02687 st = ic->streams[stream_index];
02688 if (st->codec->codec_type == codec_type) {
02689
02690 switch(codec_type) {
02691 case AVMEDIA_TYPE_AUDIO:
02692 if (st->codec->sample_rate != 0 &&
02693 st->codec->channels != 0)
02694 goto the_end;
02695 break;
02696 case AVMEDIA_TYPE_VIDEO:
02697 case AVMEDIA_TYPE_SUBTITLE:
02698 goto the_end;
02699 default:
02700 break;
02701 }
02702 }
02703 }
02704 the_end:
02705 stream_component_close(is, start_index);
02706 stream_component_open(is, stream_index);
02707 }
02708
02709
02710 static void toggle_full_screen(void)
02711 {
02712 is_full_screen = !is_full_screen;
02713 if (!fs_screen_width) {
02714
02715
02716 }
02717 video_open(cur_stream);
02718 }
02719
02720 static void toggle_pause(void)
02721 {
02722 if (cur_stream)
02723 stream_pause(cur_stream);
02724 step = 0;
02725 }
02726
02727 static void step_to_next_frame(void)
02728 {
02729 if (cur_stream) {
02730
02731 if (cur_stream->paused)
02732 stream_pause(cur_stream);
02733 }
02734 step = 1;
02735 }
02736
02737 static void toggle_audio_display(void)
02738 {
02739 if (cur_stream) {
02740 int bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
02741 cur_stream->show_audio = (cur_stream->show_audio + 1) % 3;
02742 fill_rectangle(screen,
02743 cur_stream->xleft, cur_stream->ytop, cur_stream->width, cur_stream->height,
02744 bgcolor);
02745 SDL_UpdateRect(screen, cur_stream->xleft, cur_stream->ytop, cur_stream->width, cur_stream->height);
02746 }
02747 }
02748
02749
02750 static void event_loop(void)
02751 {
02752 SDL_Event event;
02753 double incr, pos, frac;
02754
02755 for(;;) {
02756 double x;
02757 SDL_WaitEvent(&event);
02758 switch(event.type) {
02759 case SDL_KEYDOWN:
02760 if (exit_on_keydown) {
02761 do_exit();
02762 break;
02763 }
02764 switch(event.key.keysym.sym) {
02765 case SDLK_ESCAPE:
02766 case SDLK_q:
02767 do_exit();
02768 break;
02769 case SDLK_f:
02770 toggle_full_screen();
02771 break;
02772 case SDLK_p:
02773 case SDLK_SPACE:
02774 toggle_pause();
02775 break;
02776 case SDLK_s:
02777 step_to_next_frame();
02778 break;
02779 case SDLK_a:
02780 if (cur_stream)
02781 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_AUDIO);
02782 break;
02783 case SDLK_v:
02784 if (cur_stream)
02785 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_VIDEO);
02786 break;
02787 case SDLK_t:
02788 if (cur_stream)
02789 stream_cycle_channel(cur_stream, AVMEDIA_TYPE_SUBTITLE);
02790 break;
02791 case SDLK_w:
02792 toggle_audio_display();
02793 break;
02794 case SDLK_LEFT:
02795 incr = -10.0;
02796 goto do_seek;
02797 case SDLK_RIGHT:
02798 incr = 10.0;
02799 goto do_seek;
02800 case SDLK_UP:
02801 incr = 60.0;
02802 goto do_seek;
02803 case SDLK_DOWN:
02804 incr = -60.0;
02805 do_seek:
02806 if (cur_stream) {
02807 if (seek_by_bytes) {
02808 if (cur_stream->video_stream >= 0 && cur_stream->video_current_pos>=0){
02809 pos= cur_stream->video_current_pos;
02810 }else if(cur_stream->audio_stream >= 0 && cur_stream->audio_pkt.pos>=0){
02811 pos= cur_stream->audio_pkt.pos;
02812 }else
02813 pos = avio_tell(cur_stream->ic->pb);
02814 if (cur_stream->ic->bit_rate)
02815 incr *= cur_stream->ic->bit_rate / 8.0;
02816 else
02817 incr *= 180000.0;
02818 pos += incr;
02819 stream_seek(cur_stream, pos, incr, 1);
02820 } else {
02821 pos = get_master_clock(cur_stream);
02822 pos += incr;
02823 stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), (int64_t)(incr * AV_TIME_BASE), 0);
02824 }
02825 }
02826 break;
02827 default:
02828 break;
02829 }
02830 break;
02831 case SDL_MOUSEBUTTONDOWN:
02832 if (exit_on_mousedown) {
02833 do_exit();
02834 break;
02835 }
02836 case SDL_MOUSEMOTION:
02837 if(event.type ==SDL_MOUSEBUTTONDOWN){
02838 x= event.button.x;
02839 }else{
02840 if(event.motion.state != SDL_PRESSED)
02841 break;
02842 x= event.motion.x;
02843 }
02844 if (cur_stream) {
02845 if(seek_by_bytes || cur_stream->ic->duration<=0){
02846 uint64_t size= avio_size(cur_stream->ic->pb);
02847 stream_seek(cur_stream, size*x/cur_stream->width, 0, 1);
02848 }else{
02849 int64_t ts;
02850 int ns, hh, mm, ss;
02851 int tns, thh, tmm, tss;
02852 tns = cur_stream->ic->duration/1000000LL;
02853 thh = tns/3600;
02854 tmm = (tns%3600)/60;
02855 tss = (tns%60);
02856 frac = x/cur_stream->width;
02857 ns = frac*tns;
02858 hh = ns/3600;
02859 mm = (ns%3600)/60;
02860 ss = (ns%60);
02861 fprintf(stderr, "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
02862 hh, mm, ss, thh, tmm, tss);
02863 ts = frac*cur_stream->ic->duration;
02864 if (cur_stream->ic->start_time != AV_NOPTS_VALUE)
02865 ts += cur_stream->ic->start_time;
02866 stream_seek(cur_stream, ts, 0, 0);
02867 }
02868 }
02869 break;
02870 case SDL_VIDEORESIZE:
02871 if (cur_stream) {
02872 screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0,
02873 SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL);
02874 screen_width = cur_stream->width = event.resize.w;
02875 screen_height= cur_stream->height= event.resize.h;
02876 }
02877 break;
02878 case SDL_QUIT:
02879 case FF_QUIT_EVENT:
02880 do_exit();
02881 break;
02882 case FF_ALLOC_EVENT:
02883 video_open(event.user.data1);
02884 alloc_picture(event.user.data1);
02885 break;
02886 case FF_REFRESH_EVENT:
02887 video_refresh_timer(event.user.data1);
02888 cur_stream->refresh=0;
02889 break;
02890 default:
02891 break;
02892 }
02893 }
02894 }
02895
02896 static void opt_frame_size(const char *arg)
02897 {
02898 if (av_parse_video_size(&frame_width, &frame_height, arg) < 0) {
02899 fprintf(stderr, "Incorrect frame size\n");
02900 exit(1);
02901 }
02902 if ((frame_width % 2) != 0 || (frame_height % 2) != 0) {
02903 fprintf(stderr, "Frame size must be a multiple of 2\n");
02904 exit(1);
02905 }
02906 }
02907
02908 static int opt_width(const char *opt, const char *arg)
02909 {
02910 screen_width = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
02911 return 0;
02912 }
02913
02914 static int opt_height(const char *opt, const char *arg)
02915 {
02916 screen_height = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
02917 return 0;
02918 }
02919
02920 static void opt_format(const char *arg)
02921 {
02922 file_iformat = av_find_input_format(arg);
02923 if (!file_iformat) {
02924 fprintf(stderr, "Unknown input format: %s\n", arg);
02925 exit(1);
02926 }
02927 }
02928
02929 static void opt_frame_pix_fmt(const char *arg)
02930 {
02931 frame_pix_fmt = av_get_pix_fmt(arg);
02932 }
02933
02934 static int opt_sync(const char *opt, const char *arg)
02935 {
02936 if (!strcmp(arg, "audio"))
02937 av_sync_type = AV_SYNC_AUDIO_MASTER;
02938 else if (!strcmp(arg, "video"))
02939 av_sync_type = AV_SYNC_VIDEO_MASTER;
02940 else if (!strcmp(arg, "ext"))
02941 av_sync_type = AV_SYNC_EXTERNAL_CLOCK;
02942 else {
02943 fprintf(stderr, "Unknown value for %s: %s\n", opt, arg);
02944 exit(1);
02945 }
02946 return 0;
02947 }
02948
02949 static int opt_seek(const char *opt, const char *arg)
02950 {
02951 start_time = parse_time_or_die(opt, arg, 1);
02952 return 0;
02953 }
02954
02955 static int opt_duration(const char *opt, const char *arg)
02956 {
02957 duration = parse_time_or_die(opt, arg, 1);
02958 return 0;
02959 }
02960
02961 static int opt_debug(const char *opt, const char *arg)
02962 {
02963 av_log_set_level(99);
02964 debug = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
02965 return 0;
02966 }
02967
02968 static int opt_vismv(const char *opt, const char *arg)
02969 {
02970 debug_mv = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX);
02971 return 0;
02972 }
02973
02974 static int opt_thread_count(const char *opt, const char *arg)
02975 {
02976 thread_count= parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
02977 #if !HAVE_THREADS
02978 fprintf(stderr, "Warning: not compiled with thread support, using thread emulation\n");
02979 #endif
02980 return 0;
02981 }
02982
02983 static const OptionDef options[] = {
02984 #include "cmdutils_common_opts.h"
02985 { "x", HAS_ARG | OPT_FUNC2, {(void*)opt_width}, "force displayed width", "width" },
02986 { "y", HAS_ARG | OPT_FUNC2, {(void*)opt_height}, "force displayed height", "height" },
02987 { "s", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_size}, "set frame size (WxH or abbreviation)", "size" },
02988 { "fs", OPT_BOOL, {(void*)&is_full_screen}, "force full screen" },
02989 { "an", OPT_BOOL, {(void*)&audio_disable}, "disable audio" },
02990 { "vn", OPT_BOOL, {(void*)&video_disable}, "disable video" },
02991 { "ast", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_stream[AVMEDIA_TYPE_AUDIO]}, "select desired audio stream", "stream_number" },
02992 { "vst", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_stream[AVMEDIA_TYPE_VIDEO]}, "select desired video stream", "stream_number" },
02993 { "sst", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_stream[AVMEDIA_TYPE_SUBTITLE]}, "select desired subtitle stream", "stream_number" },
02994 { "ss", HAS_ARG | OPT_FUNC2, {(void*)&opt_seek}, "seek to a given position in seconds", "pos" },
02995 { "t", HAS_ARG | OPT_FUNC2, {(void*)&opt_duration}, "play \"duration\" seconds of audio/video", "duration" },
02996 { "bytes", OPT_INT | HAS_ARG, {(void*)&seek_by_bytes}, "seek by bytes 0=off 1=on -1=auto", "val" },
02997 { "nodisp", OPT_BOOL, {(void*)&display_disable}, "disable graphical display" },
02998 { "f", HAS_ARG, {(void*)opt_format}, "force format", "fmt" },
02999 { "pix_fmt", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_frame_pix_fmt}, "set pixel format", "format" },
03000 { "stats", OPT_BOOL | OPT_EXPERT, {(void*)&show_status}, "show status", "" },
03001 { "debug", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_debug}, "print specific debug info", "" },
03002 { "bug", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&workaround_bugs}, "workaround bugs", "" },
03003 { "vismv", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_vismv}, "visualize motion vectors", "" },
03004 { "fast", OPT_BOOL | OPT_EXPERT, {(void*)&fast}, "non spec compliant optimizations", "" },
03005 { "genpts", OPT_BOOL | OPT_EXPERT, {(void*)&genpts}, "generate pts", "" },
03006 { "drp", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&decoder_reorder_pts}, "let decoder reorder pts 0=off 1=on -1=auto", ""},
03007 { "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&lowres}, "", "" },
03008 { "skiploop", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_loop_filter}, "", "" },
03009 { "skipframe", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_frame}, "", "" },
03010 { "skipidct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_idct}, "", "" },
03011 { "idct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&idct}, "set idct algo", "algo" },
03012 { "er", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_recognition}, "set error detection threshold (0-4)", "threshold" },
03013 { "ec", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_concealment}, "set error concealment options", "bit_mask" },
03014 { "sync", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_sync}, "set audio-video sync. type (type=audio/video/ext)", "type" },
03015 { "threads", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" },
03016 { "autoexit", OPT_BOOL | OPT_EXPERT, {(void*)&autoexit}, "exit at the end", "" },
03017 { "exitonkeydown", OPT_BOOL | OPT_EXPERT, {(void*)&exit_on_keydown}, "exit on key down", "" },
03018 { "exitonmousedown", OPT_BOOL | OPT_EXPERT, {(void*)&exit_on_mousedown}, "exit on mouse down", "" },
03019 { "loop", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&loop}, "set number of times the playback shall be looped", "loop count" },
03020 { "framedrop", OPT_BOOL | OPT_EXPERT, {(void*)&framedrop}, "drop frames when cpu is too slow", "" },
03021 { "window_title", OPT_STRING | HAS_ARG, {(void*)&window_title}, "set window title", "window title" },
03022 #if CONFIG_AVFILTER
03023 { "vf", OPT_STRING | HAS_ARG, {(void*)&vfilters}, "video filters", "filter list" },
03024 #endif
03025 { "rdftspeed", OPT_INT | HAS_ARG| OPT_AUDIO | OPT_EXPERT, {(void*)&rdftspeed}, "rdft speed", "msecs" },
03026 { "default", OPT_FUNC2 | HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, {(void*)opt_default}, "generic catch all option", "" },
03027 { "i", OPT_DUMMY, {NULL}, "ffmpeg compatibility dummy option", ""},
03028 { NULL, },
03029 };
03030
03031 static void show_usage(void)
03032 {
03033 printf("Simple media player\n");
03034 printf("usage: ffplay [options] input_file\n");
03035 printf("\n");
03036 }
03037
03038 static void show_help(void)
03039 {
03040 av_log_set_callback(log_callback_help);
03041 show_usage();
03042 show_help_options(options, "Main options:\n",
03043 OPT_EXPERT, 0);
03044 show_help_options(options, "\nAdvanced options:\n",
03045 OPT_EXPERT, OPT_EXPERT);
03046 printf("\n");
03047 av_opt_show2(avcodec_opts[0], NULL,
03048 AV_OPT_FLAG_DECODING_PARAM, 0);
03049 printf("\n");
03050 av_opt_show2(avformat_opts, NULL,
03051 AV_OPT_FLAG_DECODING_PARAM, 0);
03052 #if !CONFIG_AVFILTER
03053 printf("\n");
03054 av_opt_show2(sws_opts, NULL,
03055 AV_OPT_FLAG_ENCODING_PARAM, 0);
03056 #endif
03057 printf("\nWhile playing:\n"
03058 "q, ESC quit\n"
03059 "f toggle full screen\n"
03060 "p, SPC pause\n"
03061 "a cycle audio channel\n"
03062 "v cycle video channel\n"
03063 "t cycle subtitle channel\n"
03064 "w show audio waves\n"
03065 "s activate frame-step mode\n"
03066 "left/right seek backward/forward 10 seconds\n"
03067 "down/up seek backward/forward 1 minute\n"
03068 "mouse click seek to percentage in file corresponding to fraction of width\n"
03069 );
03070 }
03071
03072 static void opt_input_file(const char *filename)
03073 {
03074 if (input_filename) {
03075 fprintf(stderr, "Argument '%s' provided as input filename, but '%s' was already specified.\n",
03076 filename, input_filename);
03077 exit(1);
03078 }
03079 if (!strcmp(filename, "-"))
03080 filename = "pipe:";
03081 input_filename = filename;
03082 }
03083
03084
03085 int main(int argc, char **argv)
03086 {
03087 int flags;
03088
03089 av_log_set_flags(AV_LOG_SKIP_REPEATED);
03090
03091
03092 avcodec_register_all();
03093 #if CONFIG_AVDEVICE
03094 avdevice_register_all();
03095 #endif
03096 #if CONFIG_AVFILTER
03097 avfilter_register_all();
03098 #endif
03099 av_register_all();
03100
03101 init_opts();
03102
03103 show_banner();
03104
03105 parse_options(argc, argv, options, opt_input_file);
03106
03107 if (!input_filename) {
03108 show_usage();
03109 fprintf(stderr, "An input file must be specified\n");
03110 fprintf(stderr, "Use -h to get full help or, even better, run 'man ffplay'\n");
03111 exit(1);
03112 }
03113
03114 if (display_disable) {
03115 video_disable = 1;
03116 }
03117 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
03118 #if !defined(__MINGW32__) && !defined(__APPLE__)
03119 flags |= SDL_INIT_EVENTTHREAD;
03120 #endif
03121 if (SDL_Init (flags)) {
03122 fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
03123 exit(1);
03124 }
03125
03126 if (!display_disable) {
03127 #if HAVE_SDL_VIDEO_SIZE
03128 const SDL_VideoInfo *vi = SDL_GetVideoInfo();
03129 fs_screen_width = vi->current_w;
03130 fs_screen_height = vi->current_h;
03131 #endif
03132 }
03133
03134 SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
03135 SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
03136 SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
03137
03138 av_init_packet(&flush_pkt);
03139 flush_pkt.data= "FLUSH";
03140
03141 cur_stream = stream_open(input_filename, file_iformat);
03142
03143 event_loop();
03144
03145
03146
03147 return 0;
03148 }