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