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