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