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