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