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