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