00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <math.h>
00023 #include <limits.h>
00024 #include "avformat.h"
00025 #include "avdevice.h"
00026 #include "rtsp.h"
00027 #include "swscale.h"
00028 #include "avstring.h"
00029
00030 #include "version.h"
00031 #include "cmdutils.h"
00032
00033 #include <SDL.h>
00034 #include <SDL_thread.h>
00035
00036 #ifdef __MINGW32__
00037 #undef main
00038 #endif
00039
00040 #undef exit
00041
00042 static const char program_name[] = "FFplay";
00043 static const int program_birth_year = 2003;
00044
00045
00046
00047 #define MAX_VIDEOQ_SIZE (5 * 256 * 1024)
00048 #define MAX_AUDIOQ_SIZE (5 * 16 * 1024)
00049 #define MAX_SUBTITLEQ_SIZE (5 * 16 * 1024)
00050
00051
00052
00053 #define SDL_AUDIO_BUFFER_SIZE 1024
00054
00055
00056 #define AV_SYNC_THRESHOLD 0.01
00057
00058 #define AV_NOSYNC_THRESHOLD 10.0
00059
00060
00061 #define SAMPLE_CORRECTION_PERCENT_MAX 10
00062
00063
00064 #define AUDIO_DIFF_AVG_NB 20
00065
00066
00067 #define SAMPLE_ARRAY_SIZE (2*65536)
00068
00069 static int sws_flags = SWS_BICUBIC;
00070
00071 typedef struct PacketQueue {
00072 AVPacketList *first_pkt, *last_pkt;
00073 int nb_packets;
00074 int size;
00075 int abort_request;
00076 SDL_mutex *mutex;
00077 SDL_cond *cond;
00078 } PacketQueue;
00079
00080 #define VIDEO_PICTURE_QUEUE_SIZE 1
00081 #define SUBPICTURE_QUEUE_SIZE 4
00082
00083 typedef struct VideoPicture {
00084 double pts;
00085 SDL_Overlay *bmp;
00086 int width, height;
00087 int allocated;
00088 } VideoPicture;
00089
00090 typedef struct SubPicture {
00091 double pts;
00092 AVSubtitle sub;
00093 } SubPicture;
00094
00095 enum {
00096 AV_SYNC_AUDIO_MASTER,
00097 AV_SYNC_VIDEO_MASTER,
00098 AV_SYNC_EXTERNAL_CLOCK,
00099 };
00100
00101 typedef struct VideoState {
00102 SDL_Thread *parse_tid;
00103 SDL_Thread *video_tid;
00104 AVInputFormat *iformat;
00105 int no_background;
00106 int abort_request;
00107 int paused;
00108 int last_paused;
00109 int seek_req;
00110 int seek_flags;
00111 int64_t seek_pos;
00112 AVFormatContext *ic;
00113 int dtg_active_format;
00114
00115 int audio_stream;
00116
00117 int av_sync_type;
00118 double external_clock;
00119 int64_t external_clock_time;
00120
00121 double audio_clock;
00122 double audio_diff_cum;
00123 double audio_diff_avg_coef;
00124 double audio_diff_threshold;
00125 int audio_diff_avg_count;
00126 AVStream *audio_st;
00127 PacketQueue audioq;
00128 int audio_hw_buf_size;
00129
00130
00131 DECLARE_ALIGNED(16,uint8_t,audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2]);
00132 unsigned int audio_buf_size;
00133 int audio_buf_index;
00134 AVPacket audio_pkt;
00135 uint8_t *audio_pkt_data;
00136 int audio_pkt_size;
00137
00138 int show_audio;
00139 int16_t sample_array[SAMPLE_ARRAY_SIZE];
00140 int sample_array_index;
00141 int last_i_start;
00142
00143 SDL_Thread *subtitle_tid;
00144 int subtitle_stream;
00145 int subtitle_stream_changed;
00146 AVStream *subtitle_st;
00147 PacketQueue subtitleq;
00148 SubPicture subpq[SUBPICTURE_QUEUE_SIZE];
00149 int subpq_size, subpq_rindex, subpq_windex;
00150 SDL_mutex *subpq_mutex;
00151 SDL_cond *subpq_cond;
00152
00153 double frame_timer;
00154 double frame_last_pts;
00155 double frame_last_delay;
00156 double video_clock;
00157 int video_stream;
00158 AVStream *video_st;
00159 PacketQueue videoq;
00160 double video_current_pts;
00161 int64_t video_current_pts_time;
00162 VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
00163 int pictq_size, pictq_rindex, pictq_windex;
00164 SDL_mutex *pictq_mutex;
00165 SDL_cond *pictq_cond;
00166
00167
00168 char filename[1024];
00169 int width, height, xleft, ytop;
00170 } VideoState;
00171
00172 void show_help(void);
00173 static int audio_write_get_buf_size(VideoState *is);
00174
00175
00176 static AVInputFormat *file_iformat;
00177 static const char *input_filename;
00178 static int fs_screen_width;
00179 static int fs_screen_height;
00180 static int screen_width = 0;
00181 static int screen_height = 0;
00182 static int frame_width = 0;
00183 static int frame_height = 0;
00184 static enum PixelFormat frame_pix_fmt = PIX_FMT_NONE;
00185 static int audio_disable;
00186 static int video_disable;
00187 static int wanted_audio_stream= 0;
00188 static int wanted_video_stream= 0;
00189 static int seek_by_bytes;
00190 static int display_disable;
00191 static int show_status;
00192 static int av_sync_type = AV_SYNC_AUDIO_MASTER;
00193 static int64_t start_time = AV_NOPTS_VALUE;
00194 static int debug = 0;
00195 static int debug_mv = 0;
00196 static int step = 0;
00197 static int thread_count = 1;
00198 static int workaround_bugs = 1;
00199 static int fast = 0;
00200 static int genpts = 0;
00201 static int lowres = 0;
00202 static int idct = FF_IDCT_AUTO;
00203 static enum AVDiscard skip_frame= AVDISCARD_DEFAULT;
00204 static enum AVDiscard skip_idct= AVDISCARD_DEFAULT;
00205 static enum AVDiscard skip_loop_filter= AVDISCARD_DEFAULT;
00206 static int error_resilience = FF_ER_CAREFUL;
00207 static int error_concealment = 3;
00208 static int decoder_reorder_pts= 0;
00209
00210
00211 static int is_full_screen;
00212 static VideoState *cur_stream;
00213 static int64_t audio_callback_time;
00214
00215 AVPacket flush_pkt;
00216
00217 #define FF_ALLOC_EVENT (SDL_USEREVENT)
00218 #define FF_REFRESH_EVENT (SDL_USEREVENT + 1)
00219 #define FF_QUIT_EVENT (SDL_USEREVENT + 2)
00220
00221 SDL_Surface *screen;
00222
00223
00224 static void packet_queue_init(PacketQueue *q)
00225 {
00226 memset(q, 0, sizeof(PacketQueue));
00227 q->mutex = SDL_CreateMutex();
00228 q->cond = SDL_CreateCond();
00229 }
00230
00231 static void packet_queue_flush(PacketQueue *q)
00232 {
00233 AVPacketList *pkt, *pkt1;
00234
00235 SDL_LockMutex(q->mutex);
00236 for(pkt = q->first_pkt; pkt != NULL; pkt = pkt1) {
00237 pkt1 = pkt->next;
00238 av_free_packet(&pkt->pkt);
00239 av_freep(&pkt);
00240 }
00241 q->last_pkt = NULL;
00242 q->first_pkt = NULL;
00243 q->nb_packets = 0;
00244 q->size = 0;
00245 SDL_UnlockMutex(q->mutex);
00246 }
00247
00248 static void packet_queue_end(PacketQueue *q)
00249 {
00250 packet_queue_flush(q);
00251 SDL_DestroyMutex(q->mutex);
00252 SDL_DestroyCond(q->cond);
00253 }
00254
00255 static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
00256 {
00257 AVPacketList *pkt1;
00258
00259
00260 if (pkt!=&flush_pkt && av_dup_packet(pkt) < 0)
00261 return -1;
00262
00263 pkt1 = av_malloc(sizeof(AVPacketList));
00264 if (!pkt1)
00265 return -1;
00266 pkt1->pkt = *pkt;
00267 pkt1->next = NULL;
00268
00269
00270 SDL_LockMutex(q->mutex);
00271
00272 if (!q->last_pkt)
00273
00274 q->first_pkt = pkt1;
00275 else
00276 q->last_pkt->next = pkt1;
00277 q->last_pkt = pkt1;
00278 q->nb_packets++;
00279 q->size += pkt1->pkt.size;
00280
00281 SDL_CondSignal(q->cond);
00282
00283 SDL_UnlockMutex(q->mutex);
00284 return 0;
00285 }
00286
00287 static void packet_queue_abort(PacketQueue *q)
00288 {
00289 SDL_LockMutex(q->mutex);
00290
00291 q->abort_request = 1;
00292
00293 SDL_CondSignal(q->cond);
00294
00295 SDL_UnlockMutex(q->mutex);
00296 }
00297
00298
00299 static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
00300 {
00301 AVPacketList *pkt1;
00302 int ret;
00303
00304 SDL_LockMutex(q->mutex);
00305
00306 for(;;) {
00307 if (q->abort_request) {
00308 ret = -1;
00309 break;
00310 }
00311
00312 pkt1 = q->first_pkt;
00313 if (pkt1) {
00314 q->first_pkt = pkt1->next;
00315 if (!q->first_pkt)
00316 q->last_pkt = NULL;
00317 q->nb_packets--;
00318 q->size -= pkt1->pkt.size;
00319 *pkt = pkt1->pkt;
00320 av_free(pkt1);
00321 ret = 1;
00322 break;
00323 } else if (!block) {
00324 ret = 0;
00325 break;
00326 } else {
00327 SDL_CondWait(q->cond, q->mutex);
00328 }
00329 }
00330 SDL_UnlockMutex(q->mutex);
00331 return ret;
00332 }
00333
00334 static inline void fill_rectangle(SDL_Surface *screen,
00335 int x, int y, int w, int h, int color)
00336 {
00337 SDL_Rect rect;
00338 rect.x = x;
00339 rect.y = y;
00340 rect.w = w;
00341 rect.h = h;
00342 SDL_FillRect(screen, &rect, color);
00343 }
00344
00345 #if 0
00346
00347 void fill_border(VideoState *s, int x, int y, int w, int h, int color)
00348 {
00349 int w1, w2, h1, h2;
00350
00351
00352 w1 = x;
00353 if (w1 < 0)
00354 w1 = 0;
00355 w2 = s->width - (x + w);
00356 if (w2 < 0)
00357 w2 = 0;
00358 h1 = y;
00359 if (h1 < 0)
00360 h1 = 0;
00361 h2 = s->height - (y + h);
00362 if (h2 < 0)
00363 h2 = 0;
00364 fill_rectangle(screen,
00365 s->xleft, s->ytop,
00366 w1, s->height,
00367 color);
00368 fill_rectangle(screen,
00369 s->xleft + s->width - w2, s->ytop,
00370 w2, s->height,
00371 color);
00372 fill_rectangle(screen,
00373 s->xleft + w1, s->ytop,
00374 s->width - w1 - w2, h1,
00375 color);
00376 fill_rectangle(screen,
00377 s->xleft + w1, s->ytop + s->height - h2,
00378 s->width - w1 - w2, h2,
00379 color);
00380 }
00381 #endif
00382
00383
00384
00385 #define SCALEBITS 10
00386 #define ONE_HALF (1 << (SCALEBITS - 1))
00387 #define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5))
00388
00389 #define RGB_TO_Y_CCIR(r, g, b) \
00390 ((FIX(0.29900*219.0/255.0) * (r) + FIX(0.58700*219.0/255.0) * (g) + \
00391 FIX(0.11400*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS)
00392
00393 #define RGB_TO_U_CCIR(r1, g1, b1, shift)\
00394 (((- FIX(0.16874*224.0/255.0) * r1 - FIX(0.33126*224.0/255.0) * g1 + \
00395 FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
00396
00397 #define RGB_TO_V_CCIR(r1, g1, b1, shift)\
00398 (((FIX(0.50000*224.0/255.0) * r1 - FIX(0.41869*224.0/255.0) * g1 - \
00399 FIX(0.08131*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
00400
00401 #define ALPHA_BLEND(a, oldp, newp, s)\
00402 ((((oldp << s) * (255 - (a))) + (newp * (a))) / (255 << s))
00403
00404 #define RGBA_IN(r, g, b, a, s)\
00405 {\
00406 unsigned int v = ((const uint32_t *)(s))[0];\
00407 a = (v >> 24) & 0xff;\
00408 r = (v >> 16) & 0xff;\
00409 g = (v >> 8) & 0xff;\
00410 b = v & 0xff;\
00411 }
00412
00413 #define YUVA_IN(y, u, v, a, s, pal)\
00414 {\
00415 unsigned int val = ((const uint32_t *)(pal))[*(const uint8_t*)(s)];\
00416 a = (val >> 24) & 0xff;\
00417 y = (val >> 16) & 0xff;\
00418 u = (val >> 8) & 0xff;\
00419 v = val & 0xff;\
00420 }
00421
00422 #define YUVA_OUT(d, y, u, v, a)\
00423 {\
00424 ((uint32_t *)(d))[0] = (a << 24) | (y << 16) | (u << 8) | v;\
00425 }
00426
00427
00428 #define BPP 1
00429
00430 static void blend_subrect(AVPicture *dst, const AVSubtitleRect *rect, int imgw, int imgh)
00431 {
00432 int wrap, wrap3, width2, skip2;
00433 int y, u, v, a, u1, v1, a1, w, h;
00434 uint8_t *lum, *cb, *cr;
00435 const uint8_t *p;
00436 const uint32_t *pal;
00437 int dstx, dsty, dstw, dsth;
00438
00439 dstx = FFMIN(FFMAX(rect->x, 0), imgw);
00440 dstw = FFMIN(FFMAX(rect->w, 0), imgw - dstx);
00441 dsty = FFMIN(FFMAX(rect->y, 0), imgh);
00442 dsth = FFMIN(FFMAX(rect->h, 0), imgh - dsty);
00443 lum = dst->data[0] + dsty * dst->linesize[0];
00444 cb = dst->data[1] + (dsty >> 1) * dst->linesize[1];
00445 cr = dst->data[2] + (dsty >> 1) * dst->linesize[2];
00446
00447 width2 = (dstw + 1) >> 1;
00448 skip2 = dstx >> 1;
00449 wrap = dst->linesize[0];
00450 wrap3 = rect->linesize;
00451 p = rect->bitmap;
00452 pal = rect->rgba_palette;
00453
00454 if (dsty & 1) {
00455 lum += dstx;
00456 cb += skip2;
00457 cr += skip2;
00458
00459 if (dstx & 1) {
00460 YUVA_IN(y, u, v, a, p, pal);
00461 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00462 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
00463 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
00464 cb++;
00465 cr++;
00466 lum++;
00467 p += BPP;
00468 }
00469 for(w = dstw - (dstx & 1); w >= 2; w -= 2) {
00470 YUVA_IN(y, u, v, a, p, pal);
00471 u1 = u;
00472 v1 = v;
00473 a1 = a;
00474 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00475
00476 YUVA_IN(y, u, v, a, p + BPP, pal);
00477 u1 += u;
00478 v1 += v;
00479 a1 += a;
00480 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
00481 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
00482 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
00483 cb++;
00484 cr++;
00485 p += 2 * BPP;
00486 lum += 2;
00487 }
00488 if (w) {
00489 YUVA_IN(y, u, v, a, p, pal);
00490 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00491 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
00492 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
00493 }
00494 p += wrap3 + (wrap3 - dstw * BPP);
00495 lum += wrap + (wrap - dstw - dstx);
00496 cb += dst->linesize[1] - width2 - skip2;
00497 cr += dst->linesize[2] - width2 - skip2;
00498 }
00499 for(h = dsth - (dsty & 1); h >= 2; h -= 2) {
00500 lum += dstx;
00501 cb += skip2;
00502 cr += skip2;
00503
00504 if (dstx & 1) {
00505 YUVA_IN(y, u, v, a, p, pal);
00506 u1 = u;
00507 v1 = v;
00508 a1 = a;
00509 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00510 p += wrap3;
00511 lum += wrap;
00512 YUVA_IN(y, u, v, a, p, pal);
00513 u1 += u;
00514 v1 += v;
00515 a1 += a;
00516 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00517 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
00518 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
00519 cb++;
00520 cr++;
00521 p += -wrap3 + BPP;
00522 lum += -wrap + 1;
00523 }
00524 for(w = dstw - (dstx & 1); w >= 2; w -= 2) {
00525 YUVA_IN(y, u, v, a, p, pal);
00526 u1 = u;
00527 v1 = v;
00528 a1 = a;
00529 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00530
00531 YUVA_IN(y, u, v, a, p, pal);
00532 u1 += u;
00533 v1 += v;
00534 a1 += a;
00535 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
00536 p += wrap3;
00537 lum += wrap;
00538
00539 YUVA_IN(y, u, v, a, p, pal);
00540 u1 += u;
00541 v1 += v;
00542 a1 += a;
00543 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00544
00545 YUVA_IN(y, u, v, a, p, pal);
00546 u1 += u;
00547 v1 += v;
00548 a1 += a;
00549 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
00550
00551 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 2);
00552 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 2);
00553
00554 cb++;
00555 cr++;
00556 p += -wrap3 + 2 * BPP;
00557 lum += -wrap + 2;
00558 }
00559 if (w) {
00560 YUVA_IN(y, u, v, a, p, pal);
00561 u1 = u;
00562 v1 = v;
00563 a1 = a;
00564 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00565 p += wrap3;
00566 lum += wrap;
00567 YUVA_IN(y, u, v, a, p, pal);
00568 u1 += u;
00569 v1 += v;
00570 a1 += a;
00571 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00572 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
00573 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
00574 cb++;
00575 cr++;
00576 p += -wrap3 + BPP;
00577 lum += -wrap + 1;
00578 }
00579 p += wrap3 + (wrap3 - dstw * BPP);
00580 lum += wrap + (wrap - dstw - dstx);
00581 cb += dst->linesize[1] - width2 - skip2;
00582 cr += dst->linesize[2] - width2 - skip2;
00583 }
00584
00585 if (h) {
00586 lum += dstx;
00587 cb += skip2;
00588 cr += skip2;
00589
00590 if (dstx & 1) {
00591 YUVA_IN(y, u, v, a, p, pal);
00592 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00593 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
00594 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
00595 cb++;
00596 cr++;
00597 lum++;
00598 p += BPP;
00599 }
00600 for(w = dstw - (dstx & 1); w >= 2; w -= 2) {
00601 YUVA_IN(y, u, v, a, p, pal);
00602 u1 = u;
00603 v1 = v;
00604 a1 = a;
00605 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00606
00607 YUVA_IN(y, u, v, a, p + BPP, pal);
00608 u1 += u;
00609 v1 += v;
00610 a1 += a;
00611 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
00612 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u, 1);
00613 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v, 1);
00614 cb++;
00615 cr++;
00616 p += 2 * BPP;
00617 lum += 2;
00618 }
00619 if (w) {
00620 YUVA_IN(y, u, v, a, p, pal);
00621 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00622 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
00623 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
00624 }
00625 }
00626 }
00627
00628 static void free_subpicture(SubPicture *sp)
00629 {
00630 int i;
00631
00632 for (i = 0; i < sp->sub.num_rects; i++)
00633 {
00634 av_free(sp->sub.rects[i].bitmap);
00635 av_free(sp->sub.rects[i].rgba_palette);
00636 }
00637
00638 av_free(sp->sub.rects);
00639
00640 memset(&sp->sub, 0, sizeof(AVSubtitle));
00641 }
00642
00643 static void video_image_display(VideoState *is)
00644 {
00645 VideoPicture *vp;
00646 SubPicture *sp;
00647 AVPicture pict;
00648 float aspect_ratio;
00649 int width, height, x, y;
00650 SDL_Rect rect;
00651 int i;
00652
00653 vp = &is->pictq[is->pictq_rindex];
00654 if (vp->bmp) {
00655
00656 if (is->video_st->codec->sample_aspect_ratio.num == 0)
00657 aspect_ratio = 0;
00658 else
00659 aspect_ratio = av_q2d(is->video_st->codec->sample_aspect_ratio)
00660 * is->video_st->codec->width / is->video_st->codec->height;;
00661 if (aspect_ratio <= 0.0)
00662 aspect_ratio = (float)is->video_st->codec->width /
00663 (float)is->video_st->codec->height;
00664
00665
00666 #if 0
00667 if (is->video_st->codec->dtg_active_format != is->dtg_active_format) {
00668 is->dtg_active_format = is->video_st->codec->dtg_active_format;
00669 printf("dtg_active_format=%d\n", is->dtg_active_format);
00670 }
00671 #endif
00672 #if 0
00673 switch(is->video_st->codec->dtg_active_format) {
00674 case FF_DTG_AFD_SAME:
00675 default:
00676
00677 break;
00678 case FF_DTG_AFD_4_3:
00679 aspect_ratio = 4.0 / 3.0;
00680 break;
00681 case FF_DTG_AFD_16_9:
00682 aspect_ratio = 16.0 / 9.0;
00683 break;
00684 case FF_DTG_AFD_14_9:
00685 aspect_ratio = 14.0 / 9.0;
00686 break;
00687 case FF_DTG_AFD_4_3_SP_14_9:
00688 aspect_ratio = 14.0 / 9.0;
00689 break;
00690 case FF_DTG_AFD_16_9_SP_14_9:
00691 aspect_ratio = 14.0 / 9.0;
00692 break;
00693 case FF_DTG_AFD_SP_4_3:
00694 aspect_ratio = 4.0 / 3.0;
00695 break;
00696 }
00697 #endif
00698
00699 if (is->subtitle_st)
00700 {
00701 if (is->subpq_size > 0)
00702 {
00703 sp = &is->subpq[is->subpq_rindex];
00704
00705 if (vp->pts >= sp->pts + ((float) sp->sub.start_display_time / 1000))
00706 {
00707 SDL_LockYUVOverlay (vp->bmp);
00708
00709 pict.data[0] = vp->bmp->pixels[0];
00710 pict.data[1] = vp->bmp->pixels[2];
00711 pict.data[2] = vp->bmp->pixels[1];
00712
00713 pict.linesize[0] = vp->bmp->pitches[0];
00714 pict.linesize[1] = vp->bmp->pitches[2];
00715 pict.linesize[2] = vp->bmp->pitches[1];
00716
00717 for (i = 0; i < sp->sub.num_rects; i++)
00718 blend_subrect(&pict, &sp->sub.rects[i],
00719 vp->bmp->w, vp->bmp->h);
00720
00721 SDL_UnlockYUVOverlay (vp->bmp);
00722 }
00723 }
00724 }
00725
00726
00727
00728 height = is->height;
00729 width = ((int)rint(height * aspect_ratio)) & -3;
00730 if (width > is->width) {
00731 width = is->width;
00732 height = ((int)rint(width / aspect_ratio)) & -3;
00733 }
00734 x = (is->width - width) / 2;
00735 y = (is->height - height) / 2;
00736 if (!is->no_background) {
00737
00738
00739 } else {
00740 is->no_background = 0;
00741 }
00742 rect.x = is->xleft + x;
00743 rect.y = is->ytop + y;
00744 rect.w = width;
00745 rect.h = height;
00746 SDL_DisplayYUVOverlay(vp->bmp, &rect);
00747 } else {
00748 #if 0
00749 fill_rectangle(screen,
00750 is->xleft, is->ytop, is->width, is->height,
00751 QERGB(0x00, 0x00, 0x00));
00752 #endif
00753 }
00754 }
00755
00756 static inline int compute_mod(int a, int b)
00757 {
00758 a = a % b;
00759 if (a >= 0)
00760 return a;
00761 else
00762 return a + b;
00763 }
00764
00765 static void video_audio_display(VideoState *s)
00766 {
00767 int i, i_start, x, y1, y, ys, delay, n, nb_display_channels;
00768 int ch, channels, h, h2, bgcolor, fgcolor;
00769 int16_t time_diff;
00770
00771
00772 channels = s->audio_st->codec->channels;
00773 nb_display_channels = channels;
00774 if (!s->paused) {
00775 n = 2 * channels;
00776 delay = audio_write_get_buf_size(s);
00777 delay /= n;
00778
00779
00780
00781 if (audio_callback_time) {
00782 time_diff = av_gettime() - audio_callback_time;
00783 delay += (time_diff * s->audio_st->codec->sample_rate) / 1000000;
00784 }
00785
00786 delay -= s->width / 2;
00787 if (delay < s->width)
00788 delay = s->width;
00789
00790 i_start= x = compute_mod(s->sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE);
00791
00792 h= INT_MIN;
00793 for(i=0; i<1000; i+=channels){
00794 int idx= (SAMPLE_ARRAY_SIZE + x - i) % SAMPLE_ARRAY_SIZE;
00795 int a= s->sample_array[idx];
00796 int b= s->sample_array[(idx + 4*channels)%SAMPLE_ARRAY_SIZE];
00797 int c= s->sample_array[(idx + 5*channels)%SAMPLE_ARRAY_SIZE];
00798 int d= s->sample_array[(idx + 9*channels)%SAMPLE_ARRAY_SIZE];
00799 int score= a-d;
00800 if(h<score && (b^c)<0){
00801 h= score;
00802 i_start= idx;
00803 }
00804 }
00805
00806 s->last_i_start = i_start;
00807 } else {
00808 i_start = s->last_i_start;
00809 }
00810
00811 bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
00812 fill_rectangle(screen,
00813 s->xleft, s->ytop, s->width, s->height,
00814 bgcolor);
00815
00816 fgcolor = SDL_MapRGB(screen->format, 0xff, 0xff, 0xff);
00817
00818
00819 h = s->height / nb_display_channels;
00820
00821 h2 = (h * 9) / 20;
00822 for(ch = 0;ch < nb_display_channels; ch++) {
00823 i = i_start + ch;
00824 y1 = s->ytop + ch * h + (h / 2);
00825 for(x = 0; x < s->width; x++) {
00826 y = (s->sample_array[i] * h2) >> 15;
00827 if (y < 0) {
00828 y = -y;
00829 ys = y1 - y;
00830 } else {
00831 ys = y1;
00832 }
00833 fill_rectangle(screen,
00834 s->xleft + x, ys, 1, y,
00835 fgcolor);
00836 i += channels;
00837 if (i >= SAMPLE_ARRAY_SIZE)
00838 i -= SAMPLE_ARRAY_SIZE;
00839 }
00840 }
00841
00842 fgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0xff);
00843
00844 for(ch = 1;ch < nb_display_channels; ch++) {
00845 y = s->ytop + ch * h;
00846 fill_rectangle(screen,
00847 s->xleft, y, s->width, 1,
00848 fgcolor);
00849 }
00850 SDL_UpdateRect(screen, s->xleft, s->ytop, s->width, s->height);
00851 }
00852
00853 static int video_open(VideoState *is){
00854 int flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
00855 int w,h;
00856
00857 if(is_full_screen) flags |= SDL_FULLSCREEN;
00858 else flags |= SDL_RESIZABLE;
00859
00860 if (is_full_screen && fs_screen_width) {
00861 w = fs_screen_width;
00862 h = fs_screen_height;
00863 } else if(!is_full_screen && screen_width){
00864 w = screen_width;
00865 h = screen_height;
00866 }else if (is->video_st && is->video_st->codec->width){
00867 w = is->video_st->codec->width;
00868 h = is->video_st->codec->height;
00869 } else {
00870 w = 640;
00871 h = 480;
00872 }
00873 #ifndef __APPLE__
00874 screen = SDL_SetVideoMode(w, h, 0, flags);
00875 #else
00876
00877 screen = SDL_SetVideoMode(w, h, 24, flags);
00878 #endif
00879 if (!screen) {
00880 fprintf(stderr, "SDL: could not set video mode - exiting\n");
00881 return -1;
00882 }
00883 SDL_WM_SetCaption("FFplay", "FFplay");
00884
00885 is->width = screen->w;
00886 is->height = screen->h;
00887
00888 return 0;
00889 }
00890
00891
00892 static void video_display(VideoState *is)
00893 {
00894 if(!screen)
00895 video_open(cur_stream);
00896 if (is->audio_st && is->show_audio)
00897 video_audio_display(is);
00898 else if (is->video_st)
00899 video_image_display(is);
00900 }
00901
00902 static Uint32 sdl_refresh_timer_cb(Uint32 interval, void *opaque)
00903 {
00904 SDL_Event event;
00905 event.type = FF_REFRESH_EVENT;
00906 event.user.data1 = opaque;
00907 SDL_PushEvent(&event);
00908 return 0;
00909 }
00910
00911
00912 static void schedule_refresh(VideoState *is, int delay)
00913 {
00914 SDL_AddTimer(delay, sdl_refresh_timer_cb, is);
00915 }
00916
00917
00918 static double get_audio_clock(VideoState *is)
00919 {
00920 double pts;
00921 int hw_buf_size, bytes_per_sec;
00922 pts = is->audio_clock;
00923 hw_buf_size = audio_write_get_buf_size(is);
00924 bytes_per_sec = 0;
00925 if (is->audio_st) {
00926 bytes_per_sec = is->audio_st->codec->sample_rate *
00927 2 * is->audio_st->codec->channels;
00928 }
00929 if (bytes_per_sec)
00930 pts -= (double)hw_buf_size / bytes_per_sec;
00931 return pts;
00932 }
00933
00934
00935 static double get_video_clock(VideoState *is)
00936 {
00937 double delta;
00938 if (is->paused) {
00939 delta = 0;
00940 } else {
00941 delta = (av_gettime() - is->video_current_pts_time) / 1000000.0;
00942 }
00943 return is->video_current_pts + delta;
00944 }
00945
00946
00947 static double get_external_clock(VideoState *is)
00948 {
00949 int64_t ti;
00950 ti = av_gettime();
00951 return is->external_clock + ((ti - is->external_clock_time) * 1e-6);
00952 }
00953
00954
00955 static double get_master_clock(VideoState *is)
00956 {
00957 double val;
00958
00959 if (is->av_sync_type == AV_SYNC_VIDEO_MASTER) {
00960 if (is->video_st)
00961 val = get_video_clock(is);
00962 else
00963 val = get_audio_clock(is);
00964 } else if (is->av_sync_type == AV_SYNC_AUDIO_MASTER) {
00965 if (is->audio_st)
00966 val = get_audio_clock(is);
00967 else
00968 val = get_video_clock(is);
00969 } else {
00970 val = get_external_clock(is);
00971 }
00972 return val;
00973 }
00974
00975
00976 static void stream_seek(VideoState *is, int64_t pos, int rel)
00977 {
00978 if (!is->seek_req) {
00979 is->seek_pos = pos;
00980 is->seek_flags = rel < 0 ? AVSEEK_FLAG_BACKWARD : 0;
00981 if (seek_by_bytes)
00982 is->seek_flags |= AVSEEK_FLAG_BYTE;
00983 is->seek_req = 1;
00984 }
00985 }
00986
00987
00988 static void stream_pause(VideoState *is)
00989 {
00990 is->paused = !is->paused;
00991 if (!is->paused) {
00992 is->video_current_pts = get_video_clock(is);
00993 is->frame_timer += (av_gettime() - is->video_current_pts_time) / 1000000.0;
00994 }
00995 }
00996
00997
00998 static void video_refresh_timer(void *opaque)
00999 {
01000 VideoState *is = opaque;
01001 VideoPicture *vp;
01002 double actual_delay, delay, sync_threshold, ref_clock, diff;
01003
01004 SubPicture *sp, *sp2;
01005
01006 if (is->video_st) {
01007 if (is->pictq_size == 0) {
01008
01009 schedule_refresh(is, 1);
01010 } else {
01011
01012 vp = &is->pictq[is->pictq_rindex];
01013
01014
01015 is->video_current_pts = vp->pts;
01016 is->video_current_pts_time = av_gettime();
01017
01018
01019 delay = vp->pts - is->frame_last_pts;
01020 if (delay <= 0 || delay >= 2.0) {
01021
01022 delay = is->frame_last_delay;
01023 }
01024 is->frame_last_delay = delay;
01025 is->frame_last_pts = vp->pts;
01026
01027
01028 if (((is->av_sync_type == AV_SYNC_AUDIO_MASTER && is->audio_st) ||
01029 is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
01030
01031
01032 ref_clock = get_master_clock(is);
01033 diff = vp->pts - ref_clock;
01034
01035
01036
01037
01038 sync_threshold = AV_SYNC_THRESHOLD;
01039 if (delay > sync_threshold)
01040 sync_threshold = delay;
01041 if (fabs(diff) < AV_NOSYNC_THRESHOLD) {
01042 if (diff <= -sync_threshold)
01043 delay = 0;
01044 else if (diff >= sync_threshold)
01045 delay = 2 * delay;
01046 }
01047 }
01048
01049 is->frame_timer += delay;
01050
01051
01052 actual_delay = is->frame_timer - (av_gettime() / 1000000.0);
01053 if (actual_delay < 0.010) {
01054
01055 actual_delay = 0.010;
01056 }
01057
01058 schedule_refresh(is, (int)(actual_delay * 1000 + 0.5));
01059
01060 #if defined(DEBUG_SYNC)
01061 printf("video: delay=%0.3f actual_delay=%0.3f pts=%0.3f A-V=%f\n",
01062 delay, actual_delay, vp->pts, -diff);
01063 #endif
01064
01065 if(is->subtitle_st) {
01066 if (is->subtitle_stream_changed) {
01067 SDL_LockMutex(is->subpq_mutex);
01068
01069 while (is->subpq_size) {
01070 free_subpicture(&is->subpq[is->subpq_rindex]);
01071
01072
01073 if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
01074 is->subpq_rindex = 0;
01075
01076 is->subpq_size--;
01077 }
01078 is->subtitle_stream_changed = 0;
01079
01080 SDL_CondSignal(is->subpq_cond);
01081 SDL_UnlockMutex(is->subpq_mutex);
01082 } else {
01083 if (is->subpq_size > 0) {
01084 sp = &is->subpq[is->subpq_rindex];
01085
01086 if (is->subpq_size > 1)
01087 sp2 = &is->subpq[(is->subpq_rindex + 1) % SUBPICTURE_QUEUE_SIZE];
01088 else
01089 sp2 = NULL;
01090
01091 if ((is->video_current_pts > (sp->pts + ((float) sp->sub.end_display_time / 1000)))
01092 || (sp2 && is->video_current_pts > (sp2->pts + ((float) sp2->sub.start_display_time / 1000))))
01093 {
01094 free_subpicture(sp);
01095
01096
01097 if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
01098 is->subpq_rindex = 0;
01099
01100 SDL_LockMutex(is->subpq_mutex);
01101 is->subpq_size--;
01102 SDL_CondSignal(is->subpq_cond);
01103 SDL_UnlockMutex(is->subpq_mutex);
01104 }
01105 }
01106 }
01107 }
01108
01109
01110 video_display(is);
01111
01112
01113 if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE)
01114 is->pictq_rindex = 0;
01115
01116 SDL_LockMutex(is->pictq_mutex);
01117 is->pictq_size--;
01118 SDL_CondSignal(is->pictq_cond);
01119 SDL_UnlockMutex(is->pictq_mutex);
01120 }
01121 } else if (is->audio_st) {
01122
01123
01124 schedule_refresh(is, 40);
01125
01126
01127
01128
01129
01130 video_display(is);
01131 } else {
01132 schedule_refresh(is, 100);
01133 }
01134 if (show_status) {
01135 static int64_t last_time;
01136 int64_t cur_time;
01137 int aqsize, vqsize, sqsize;
01138 double av_diff;
01139
01140 cur_time = av_gettime();
01141 if (!last_time || (cur_time - last_time) >= 500 * 1000) {
01142 aqsize = 0;
01143 vqsize = 0;
01144 sqsize = 0;
01145 if (is->audio_st)
01146 aqsize = is->audioq.size;
01147 if (is->video_st)
01148 vqsize = is->videoq.size;
01149 if (is->subtitle_st)
01150 sqsize = is->subtitleq.size;
01151 av_diff = 0;
01152 if (is->audio_st && is->video_st)
01153 av_diff = get_audio_clock(is) - get_video_clock(is);
01154 printf("%7.2f A-V:%7.3f aq=%5dKB vq=%5dKB sq=%5dB \r",
01155 get_master_clock(is), av_diff, aqsize / 1024, vqsize / 1024, sqsize);
01156 fflush(stdout);
01157 last_time = cur_time;
01158 }
01159 }
01160 }
01161
01162
01163
01164 static void alloc_picture(void *opaque)
01165 {
01166 VideoState *is = opaque;
01167 VideoPicture *vp;
01168
01169 vp = &is->pictq[is->pictq_windex];
01170
01171 if (vp->bmp)
01172 SDL_FreeYUVOverlay(vp->bmp);
01173
01174 #if 0
01175
01176
01177 switch(is->video_st->codec->pix_fmt) {
01178 case PIX_FMT_YUV420P:
01179 case PIX_FMT_YUV422P:
01180 case PIX_FMT_YUV444P:
01181 case PIX_FMT_YUYV422:
01182 case PIX_FMT_YUV410P:
01183 case PIX_FMT_YUV411P:
01184 is_yuv = 1;
01185 break;
01186 default:
01187 is_yuv = 0;
01188 break;
01189 }
01190 #endif
01191 vp->bmp = SDL_CreateYUVOverlay(is->video_st->codec->width,
01192 is->video_st->codec->height,
01193 SDL_YV12_OVERLAY,
01194 screen);
01195 vp->width = is->video_st->codec->width;
01196 vp->height = is->video_st->codec->height;
01197
01198 SDL_LockMutex(is->pictq_mutex);
01199 vp->allocated = 1;
01200 SDL_CondSignal(is->pictq_cond);
01201 SDL_UnlockMutex(is->pictq_mutex);
01202 }
01203
01208 static int queue_picture(VideoState *is, AVFrame *src_frame, double pts)
01209 {
01210 VideoPicture *vp;
01211 int dst_pix_fmt;
01212 AVPicture pict;
01213 static struct SwsContext *img_convert_ctx;
01214
01215
01216 SDL_LockMutex(is->pictq_mutex);
01217 while (is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE &&
01218 !is->videoq.abort_request) {
01219 SDL_CondWait(is->pictq_cond, is->pictq_mutex);
01220 }
01221 SDL_UnlockMutex(is->pictq_mutex);
01222
01223 if (is->videoq.abort_request)
01224 return -1;
01225
01226 vp = &is->pictq[is->pictq_windex];
01227
01228
01229 if (!vp->bmp ||
01230 vp->width != is->video_st->codec->width ||
01231 vp->height != is->video_st->codec->height) {
01232 SDL_Event event;
01233
01234 vp->allocated = 0;
01235
01236
01237
01238 event.type = FF_ALLOC_EVENT;
01239 event.user.data1 = is;
01240 SDL_PushEvent(&event);
01241
01242
01243 SDL_LockMutex(is->pictq_mutex);
01244 while (!vp->allocated && !is->videoq.abort_request) {
01245 SDL_CondWait(is->pictq_cond, is->pictq_mutex);
01246 }
01247 SDL_UnlockMutex(is->pictq_mutex);
01248
01249 if (is->videoq.abort_request)
01250 return -1;
01251 }
01252
01253
01254 if (vp->bmp) {
01255
01256 SDL_LockYUVOverlay (vp->bmp);
01257
01258 dst_pix_fmt = PIX_FMT_YUV420P;
01259 pict.data[0] = vp->bmp->pixels[0];
01260 pict.data[1] = vp->bmp->pixels[2];
01261 pict.data[2] = vp->bmp->pixels[1];
01262
01263 pict.linesize[0] = vp->bmp->pitches[0];
01264 pict.linesize[1] = vp->bmp->pitches[2];
01265 pict.linesize[2] = vp->bmp->pitches[1];
01266 img_convert_ctx = sws_getCachedContext(img_convert_ctx,
01267 is->video_st->codec->width, is->video_st->codec->height,
01268 is->video_st->codec->pix_fmt,
01269 is->video_st->codec->width, is->video_st->codec->height,
01270 dst_pix_fmt, sws_flags, NULL, NULL, NULL);
01271 if (img_convert_ctx == NULL) {
01272 fprintf(stderr, "Cannot initialize the conversion context\n");
01273 exit(1);
01274 }
01275 sws_scale(img_convert_ctx, src_frame->data, src_frame->linesize,
01276 0, is->video_st->codec->height, pict.data, pict.linesize);
01277
01278 SDL_UnlockYUVOverlay(vp->bmp);
01279
01280 vp->pts = pts;
01281
01282
01283 if (++is->pictq_windex == VIDEO_PICTURE_QUEUE_SIZE)
01284 is->pictq_windex = 0;
01285 SDL_LockMutex(is->pictq_mutex);
01286 is->pictq_size++;
01287 SDL_UnlockMutex(is->pictq_mutex);
01288 }
01289 return 0;
01290 }
01291
01296 static int output_picture2(VideoState *is, AVFrame *src_frame, double pts1)
01297 {
01298 double frame_delay, pts;
01299
01300 pts = pts1;
01301
01302 if (pts != 0) {
01303
01304 is->video_clock = pts;
01305 } else {
01306 pts = is->video_clock;
01307 }
01308
01309 frame_delay = av_q2d(is->video_st->codec->time_base);
01310
01311
01312 frame_delay += src_frame->repeat_pict * (frame_delay * 0.5);
01313 is->video_clock += frame_delay;
01314
01315 #if defined(DEBUG_SYNC) && 0
01316 {
01317 int ftype;
01318 if (src_frame->pict_type == FF_B_TYPE)
01319 ftype = 'B';
01320 else if (src_frame->pict_type == FF_I_TYPE)
01321 ftype = 'I';
01322 else
01323 ftype = 'P';
01324 printf("frame_type=%c clock=%0.3f pts=%0.3f\n",
01325 ftype, pts, pts1);
01326 }
01327 #endif
01328 return queue_picture(is, src_frame, pts);
01329 }
01330
01331 static uint64_t global_video_pkt_pts= AV_NOPTS_VALUE;
01332
01333 static int my_get_buffer(struct AVCodecContext *c, AVFrame *pic){
01334 int ret= avcodec_default_get_buffer(c, pic);
01335 uint64_t *pts= av_malloc(sizeof(uint64_t));
01336 *pts= global_video_pkt_pts;
01337 pic->opaque= pts;
01338 return ret;
01339 }
01340
01341 static void my_release_buffer(struct AVCodecContext *c, AVFrame *pic){
01342 if(pic) av_freep(&pic->opaque);
01343 avcodec_default_release_buffer(c, pic);
01344 }
01345
01346 static int video_thread(void *arg)
01347 {
01348 VideoState *is = arg;
01349 AVPacket pkt1, *pkt = &pkt1;
01350 int len1, got_picture;
01351 AVFrame *frame= avcodec_alloc_frame();
01352 double pts;
01353
01354 for(;;) {
01355 while (is->paused && !is->videoq.abort_request) {
01356 SDL_Delay(10);
01357 }
01358 if (packet_queue_get(&is->videoq, pkt, 1) < 0)
01359 break;
01360
01361 if(pkt->data == flush_pkt.data){
01362 avcodec_flush_buffers(is->video_st->codec);
01363 continue;
01364 }
01365
01366
01367
01368 global_video_pkt_pts= pkt->pts;
01369 len1 = avcodec_decode_video(is->video_st->codec,
01370 frame, &got_picture,
01371 pkt->data, pkt->size);
01372
01373 if( (decoder_reorder_pts || pkt->dts == AV_NOPTS_VALUE)
01374 && frame->opaque && *(uint64_t*)frame->opaque != AV_NOPTS_VALUE)
01375 pts= *(uint64_t*)frame->opaque;
01376 else if(pkt->dts != AV_NOPTS_VALUE)
01377 pts= pkt->dts;
01378 else
01379 pts= 0;
01380 pts *= av_q2d(is->video_st->time_base);
01381
01382
01383
01384 if (got_picture) {
01385 if (output_picture2(is, frame, pts) < 0)
01386 goto the_end;
01387 }
01388 av_free_packet(pkt);
01389 if (step)
01390 if (cur_stream)
01391 stream_pause(cur_stream);
01392 }
01393 the_end:
01394 av_free(frame);
01395 return 0;
01396 }
01397
01398 static int subtitle_thread(void *arg)
01399 {
01400 VideoState *is = arg;
01401 SubPicture *sp;
01402 AVPacket pkt1, *pkt = &pkt1;
01403 int len1, got_subtitle;
01404 double pts;
01405 int i, j;
01406 int r, g, b, y, u, v, a;
01407
01408 for(;;) {
01409 while (is->paused && !is->subtitleq.abort_request) {
01410 SDL_Delay(10);
01411 }
01412 if (packet_queue_get(&is->subtitleq, pkt, 1) < 0)
01413 break;
01414
01415 if(pkt->data == flush_pkt.data){
01416 avcodec_flush_buffers(is->subtitle_st->codec);
01417 continue;
01418 }
01419 SDL_LockMutex(is->subpq_mutex);
01420 while (is->subpq_size >= SUBPICTURE_QUEUE_SIZE &&
01421 !is->subtitleq.abort_request) {
01422 SDL_CondWait(is->subpq_cond, is->subpq_mutex);
01423 }
01424 SDL_UnlockMutex(is->subpq_mutex);
01425
01426 if (is->subtitleq.abort_request)
01427 goto the_end;
01428
01429 sp = &is->subpq[is->subpq_windex];
01430
01431
01432
01433 pts = 0;
01434 if (pkt->pts != AV_NOPTS_VALUE)
01435 pts = av_q2d(is->subtitle_st->time_base)*pkt->pts;
01436
01437 len1 = avcodec_decode_subtitle(is->subtitle_st->codec,
01438 &sp->sub, &got_subtitle,
01439 pkt->data, pkt->size);
01440
01441
01442 if (got_subtitle && sp->sub.format == 0) {
01443 sp->pts = pts;
01444
01445 for (i = 0; i < sp->sub.num_rects; i++)
01446 {
01447 for (j = 0; j < sp->sub.rects[i].nb_colors; j++)
01448 {
01449 RGBA_IN(r, g, b, a, sp->sub.rects[i].rgba_palette + j);
01450 y = RGB_TO_Y_CCIR(r, g, b);
01451 u = RGB_TO_U_CCIR(r, g, b, 0);
01452 v = RGB_TO_V_CCIR(r, g, b, 0);
01453 YUVA_OUT(sp->sub.rects[i].rgba_palette + j, y, u, v, a);
01454 }
01455 }
01456
01457
01458 if (++is->subpq_windex == SUBPICTURE_QUEUE_SIZE)
01459 is->subpq_windex = 0;
01460 SDL_LockMutex(is->subpq_mutex);
01461 is->subpq_size++;
01462 SDL_UnlockMutex(is->subpq_mutex);
01463 }
01464 av_free_packet(pkt);
01465
01466
01467
01468 }
01469 the_end:
01470 return 0;
01471 }
01472
01473
01474 static void update_sample_display(VideoState *is, short *samples, int samples_size)
01475 {
01476 int size, len, channels;
01477
01478 channels = is->audio_st->codec->channels;
01479
01480 size = samples_size / sizeof(short);
01481 while (size > 0) {
01482 len = SAMPLE_ARRAY_SIZE - is->sample_array_index;
01483 if (len > size)
01484 len = size;
01485 memcpy(is->sample_array + is->sample_array_index, samples, len * sizeof(short));
01486 samples += len;
01487 is->sample_array_index += len;
01488 if (is->sample_array_index >= SAMPLE_ARRAY_SIZE)
01489 is->sample_array_index = 0;
01490 size -= len;
01491 }
01492 }
01493
01494
01495
01496 static int synchronize_audio(VideoState *is, short *samples,
01497 int samples_size1, double pts)
01498 {
01499 int n, samples_size;
01500 double ref_clock;
01501
01502 n = 2 * is->audio_st->codec->channels;
01503 samples_size = samples_size1;
01504
01505
01506 if (((is->av_sync_type == AV_SYNC_VIDEO_MASTER && is->video_st) ||
01507 is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
01508 double diff, avg_diff;
01509 int wanted_size, min_size, max_size, nb_samples;
01510
01511 ref_clock = get_master_clock(is);
01512 diff = get_audio_clock(is) - ref_clock;
01513
01514 if (diff < AV_NOSYNC_THRESHOLD) {
01515 is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum;
01516 if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {
01517
01518 is->audio_diff_avg_count++;
01519 } else {
01520
01521 avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef);
01522
01523 if (fabs(avg_diff) >= is->audio_diff_threshold) {
01524 wanted_size = samples_size + ((int)(diff * is->audio_st->codec->sample_rate) * n);
01525 nb_samples = samples_size / n;
01526
01527 min_size = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
01528 max_size = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
01529 if (wanted_size < min_size)
01530 wanted_size = min_size;
01531 else if (wanted_size > max_size)
01532 wanted_size = max_size;
01533
01534
01535 if (wanted_size < samples_size) {
01536
01537 samples_size = wanted_size;
01538 } else if (wanted_size > samples_size) {
01539 uint8_t *samples_end, *q;
01540 int nb;
01541
01542
01543 nb = (samples_size - wanted_size);
01544 samples_end = (uint8_t *)samples + samples_size - n;
01545 q = samples_end + n;
01546 while (nb > 0) {
01547 memcpy(q, samples_end, n);
01548 q += n;
01549 nb -= n;
01550 }
01551 samples_size = wanted_size;
01552 }
01553 }
01554 #if 0
01555 printf("diff=%f adiff=%f sample_diff=%d apts=%0.3f vpts=%0.3f %f\n",
01556 diff, avg_diff, samples_size - samples_size1,
01557 is->audio_clock, is->video_clock, is->audio_diff_threshold);
01558 #endif
01559 }
01560 } else {
01561
01562
01563 is->audio_diff_avg_count = 0;
01564 is->audio_diff_cum = 0;
01565 }
01566 }
01567
01568 return samples_size;
01569 }
01570
01571
01572 static int audio_decode_frame(VideoState *is, uint8_t *audio_buf, int buf_size, double *pts_ptr)
01573 {
01574 AVPacket *pkt = &is->audio_pkt;
01575 int n, len1, data_size;
01576 double pts;
01577
01578 for(;;) {
01579
01580 while (is->audio_pkt_size > 0) {
01581 data_size = buf_size;
01582 len1 = avcodec_decode_audio2(is->audio_st->codec,
01583 (int16_t *)audio_buf, &data_size,
01584 is->audio_pkt_data, is->audio_pkt_size);
01585 if (len1 < 0) {
01586
01587 is->audio_pkt_size = 0;
01588 break;
01589 }
01590
01591 is->audio_pkt_data += len1;
01592 is->audio_pkt_size -= len1;
01593 if (data_size <= 0)
01594 continue;
01595
01596 pts = is->audio_clock;
01597 *pts_ptr = pts;
01598 n = 2 * is->audio_st->codec->channels;
01599 is->audio_clock += (double)data_size /
01600 (double)(n * is->audio_st->codec->sample_rate);
01601 #if defined(DEBUG_SYNC)
01602 {
01603 static double last_clock;
01604 printf("audio: delay=%0.3f clock=%0.3f pts=%0.3f\n",
01605 is->audio_clock - last_clock,
01606 is->audio_clock, pts);
01607 last_clock = is->audio_clock;
01608 }
01609 #endif
01610 return data_size;
01611 }
01612
01613
01614 if (pkt->data)
01615 av_free_packet(pkt);
01616
01617 if (is->paused || is->audioq.abort_request) {
01618 return -1;
01619 }
01620
01621
01622 if (packet_queue_get(&is->audioq, pkt, 1) < 0)
01623 return -1;
01624 if(pkt->data == flush_pkt.data){
01625 avcodec_flush_buffers(is->audio_st->codec);
01626 continue;
01627 }
01628
01629 is->audio_pkt_data = pkt->data;
01630 is->audio_pkt_size = pkt->size;
01631
01632
01633 if (pkt->pts != AV_NOPTS_VALUE) {
01634 is->audio_clock = av_q2d(is->audio_st->time_base)*pkt->pts;
01635 }
01636 }
01637 }
01638
01639
01640
01641 static int audio_write_get_buf_size(VideoState *is)
01642 {
01643 return is->audio_buf_size - is->audio_buf_index;
01644 }
01645
01646
01647
01648 void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
01649 {
01650 VideoState *is = opaque;
01651 int audio_size, len1;
01652 double pts;
01653
01654 audio_callback_time = av_gettime();
01655
01656 while (len > 0) {
01657 if (is->audio_buf_index >= is->audio_buf_size) {
01658 audio_size = audio_decode_frame(is, is->audio_buf, sizeof(is->audio_buf), &pts);
01659 if (audio_size < 0) {
01660
01661 is->audio_buf_size = 1024;
01662 memset(is->audio_buf, 0, is->audio_buf_size);
01663 } else {
01664 if (is->show_audio)
01665 update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
01666 audio_size = synchronize_audio(is, (int16_t *)is->audio_buf, audio_size,
01667 pts);
01668 is->audio_buf_size = audio_size;
01669 }
01670 is->audio_buf_index = 0;
01671 }
01672 len1 = is->audio_buf_size - is->audio_buf_index;
01673 if (len1 > len)
01674 len1 = len;
01675 memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
01676 len -= len1;
01677 stream += len1;
01678 is->audio_buf_index += len1;
01679 }
01680 }
01681
01682
01683 static int stream_component_open(VideoState *is, int stream_index)
01684 {
01685 AVFormatContext *ic = is->ic;
01686 AVCodecContext *enc;
01687 AVCodec *codec;
01688 SDL_AudioSpec wanted_spec, spec;
01689
01690 if (stream_index < 0 || stream_index >= ic->nb_streams)
01691 return -1;
01692 enc = ic->streams[stream_index]->codec;
01693
01694
01695 if (enc->codec_type == CODEC_TYPE_AUDIO) {
01696 if (enc->channels > 0) {
01697 enc->request_channels = FFMIN(2, enc->channels);
01698 } else {
01699 enc->request_channels = 2;
01700 }
01701 }
01702
01703 codec = avcodec_find_decoder(enc->codec_id);
01704 enc->debug_mv = debug_mv;
01705 enc->debug = debug;
01706 enc->workaround_bugs = workaround_bugs;
01707 enc->lowres = lowres;
01708 if(lowres) enc->flags |= CODEC_FLAG_EMU_EDGE;
01709 enc->idct_algo= idct;
01710 if(fast) enc->flags2 |= CODEC_FLAG2_FAST;
01711 enc->skip_frame= skip_frame;
01712 enc->skip_idct= skip_idct;
01713 enc->skip_loop_filter= skip_loop_filter;
01714 enc->error_resilience= error_resilience;
01715 enc->error_concealment= error_concealment;
01716 if (!codec ||
01717 avcodec_open(enc, codec) < 0)
01718 return -1;
01719
01720
01721 if (enc->codec_type == CODEC_TYPE_AUDIO) {
01722 wanted_spec.freq = enc->sample_rate;
01723 wanted_spec.format = AUDIO_S16SYS;
01724 wanted_spec.channels = enc->channels;
01725 wanted_spec.silence = 0;
01726 wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
01727 wanted_spec.callback = sdl_audio_callback;
01728 wanted_spec.userdata = is;
01729 if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
01730 fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());
01731 return -1;
01732 }
01733 is->audio_hw_buf_size = spec.size;
01734 }
01735
01736 if(thread_count>1)
01737 avcodec_thread_init(enc, thread_count);
01738 enc->thread_count= thread_count;
01739 switch(enc->codec_type) {
01740 case CODEC_TYPE_AUDIO:
01741 is->audio_stream = stream_index;
01742 is->audio_st = ic->streams[stream_index];
01743 is->audio_buf_size = 0;
01744 is->audio_buf_index = 0;
01745
01746
01747 is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
01748 is->audio_diff_avg_count = 0;
01749
01750
01751 is->audio_diff_threshold = 2.0 * SDL_AUDIO_BUFFER_SIZE / enc->sample_rate;
01752
01753 memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
01754 packet_queue_init(&is->audioq);
01755 SDL_PauseAudio(0);
01756 break;
01757 case CODEC_TYPE_VIDEO:
01758 is->video_stream = stream_index;
01759 is->video_st = ic->streams[stream_index];
01760
01761 is->frame_last_delay = 40e-3;
01762 is->frame_timer = (double)av_gettime() / 1000000.0;
01763 is->video_current_pts_time = av_gettime();
01764
01765 packet_queue_init(&is->videoq);
01766 is->video_tid = SDL_CreateThread(video_thread, is);
01767
01768 enc-> get_buffer= my_get_buffer;
01769 enc->release_buffer= my_release_buffer;
01770 break;
01771 case CODEC_TYPE_SUBTITLE:
01772 is->subtitle_stream = stream_index;
01773 is->subtitle_st = ic->streams[stream_index];
01774 packet_queue_init(&is->subtitleq);
01775
01776 is->subtitle_tid = SDL_CreateThread(subtitle_thread, is);
01777 break;
01778 default:
01779 break;
01780 }
01781 return 0;
01782 }
01783
01784 static void stream_component_close(VideoState *is, int stream_index)
01785 {
01786 AVFormatContext *ic = is->ic;
01787 AVCodecContext *enc;
01788
01789 if (stream_index < 0 || stream_index >= ic->nb_streams)
01790 return;
01791 enc = ic->streams[stream_index]->codec;
01792
01793 switch(enc->codec_type) {
01794 case CODEC_TYPE_AUDIO:
01795 packet_queue_abort(&is->audioq);
01796
01797 SDL_CloseAudio();
01798
01799 packet_queue_end(&is->audioq);
01800 break;
01801 case CODEC_TYPE_VIDEO:
01802 packet_queue_abort(&is->videoq);
01803
01804
01805
01806 SDL_LockMutex(is->pictq_mutex);
01807 SDL_CondSignal(is->pictq_cond);
01808 SDL_UnlockMutex(is->pictq_mutex);
01809
01810 SDL_WaitThread(is->video_tid, NULL);
01811
01812 packet_queue_end(&is->videoq);
01813 break;
01814 case CODEC_TYPE_SUBTITLE:
01815 packet_queue_abort(&is->subtitleq);
01816
01817
01818
01819 SDL_LockMutex(is->subpq_mutex);
01820 is->subtitle_stream_changed = 1;
01821
01822 SDL_CondSignal(is->subpq_cond);
01823 SDL_UnlockMutex(is->subpq_mutex);
01824
01825 SDL_WaitThread(is->subtitle_tid, NULL);
01826
01827 packet_queue_end(&is->subtitleq);
01828 break;
01829 default:
01830 break;
01831 }
01832
01833 avcodec_close(enc);
01834 switch(enc->codec_type) {
01835 case CODEC_TYPE_AUDIO:
01836 is->audio_st = NULL;
01837 is->audio_stream = -1;
01838 break;
01839 case CODEC_TYPE_VIDEO:
01840 is->video_st = NULL;
01841 is->video_stream = -1;
01842 break;
01843 case CODEC_TYPE_SUBTITLE:
01844 is->subtitle_st = NULL;
01845 is->subtitle_stream = -1;
01846 break;
01847 default:
01848 break;
01849 }
01850 }
01851
01852 static void dump_stream_info(const AVFormatContext *s)
01853 {
01854 if (s->track != 0)
01855 fprintf(stderr, "Track: %d\n", s->track);
01856 if (s->title[0] != '\0')
01857 fprintf(stderr, "Title: %s\n", s->title);
01858 if (s->author[0] != '\0')
01859 fprintf(stderr, "Author: %s\n", s->author);
01860 if (s->copyright[0] != '\0')
01861 fprintf(stderr, "Copyright: %s\n", s->copyright);
01862 if (s->comment[0] != '\0')
01863 fprintf(stderr, "Comment: %s\n", s->comment);
01864 if (s->album[0] != '\0')
01865 fprintf(stderr, "Album: %s\n", s->album);
01866 if (s->year != 0)
01867 fprintf(stderr, "Year: %d\n", s->year);
01868 if (s->genre[0] != '\0')
01869 fprintf(stderr, "Genre: %s\n", s->genre);
01870 }
01871
01872
01873
01874 static VideoState *global_video_state;
01875
01876 static int decode_interrupt_cb(void)
01877 {
01878 return (global_video_state && global_video_state->abort_request);
01879 }
01880
01881
01882 static int decode_thread(void *arg)
01883 {
01884 VideoState *is = arg;
01885 AVFormatContext *ic;
01886 int err, i, ret, video_index, audio_index;
01887 AVPacket pkt1, *pkt = &pkt1;
01888 AVFormatParameters params, *ap = ¶ms;
01889
01890 video_index = -1;
01891 audio_index = -1;
01892 is->video_stream = -1;
01893 is->audio_stream = -1;
01894 is->subtitle_stream = -1;
01895
01896 global_video_state = is;
01897 url_set_interrupt_cb(decode_interrupt_cb);
01898
01899 memset(ap, 0, sizeof(*ap));
01900
01901 ap->width = frame_width;
01902 ap->height= frame_height;
01903 ap->time_base= (AVRational){1, 25};
01904 ap->pix_fmt = frame_pix_fmt;
01905
01906 err = av_open_input_file(&ic, is->filename, is->iformat, 0, ap);
01907 if (err < 0) {
01908 print_error(is->filename, err);
01909 ret = -1;
01910 goto fail;
01911 }
01912 is->ic = ic;
01913
01914 if(genpts)
01915 ic->flags |= AVFMT_FLAG_GENPTS;
01916
01917 err = av_find_stream_info(ic);
01918 if (err < 0) {
01919 fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
01920 ret = -1;
01921 goto fail;
01922 }
01923 if(ic->pb)
01924 ic->pb->eof_reached= 0;
01925
01926
01927 if (start_time != AV_NOPTS_VALUE) {
01928 int64_t timestamp;
01929
01930 timestamp = start_time;
01931
01932 if (ic->start_time != AV_NOPTS_VALUE)
01933 timestamp += ic->start_time;
01934 ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
01935 if (ret < 0) {
01936 fprintf(stderr, "%s: could not seek to position %0.3f\n",
01937 is->filename, (double)timestamp / AV_TIME_BASE);
01938 }
01939 }
01940
01941 for(i = 0; i < ic->nb_streams; i++) {
01942 AVCodecContext *enc = ic->streams[i]->codec;
01943 switch(enc->codec_type) {
01944 case CODEC_TYPE_AUDIO:
01945 if ((audio_index < 0 || wanted_audio_stream-- > 0) && !audio_disable)
01946 audio_index = i;
01947 break;
01948 case CODEC_TYPE_VIDEO:
01949 if ((video_index < 0 || wanted_video_stream-- > 0) && !video_disable)
01950 video_index = i;
01951 break;
01952 default:
01953 break;
01954 }
01955 }
01956 if (show_status) {
01957 dump_format(ic, 0, is->filename, 0);
01958 dump_stream_info(ic);
01959 }
01960
01961
01962 if (audio_index >= 0) {
01963 stream_component_open(is, audio_index);
01964 }
01965
01966 if (video_index >= 0) {
01967 stream_component_open(is, video_index);
01968 } else {
01969 if (!display_disable)
01970 is->show_audio = 1;
01971 }
01972
01973 if (is->video_stream < 0 && is->audio_stream < 0) {
01974 fprintf(stderr, "%s: could not open codecs\n", is->filename);
01975 ret = -1;
01976 goto fail;
01977 }
01978
01979 for(;;) {
01980 if (is->abort_request)
01981 break;
01982 if (is->paused != is->last_paused) {
01983 is->last_paused = is->paused;
01984 if (is->paused)
01985 av_read_pause(ic);
01986 else
01987 av_read_play(ic);
01988 }
01989 #if defined(CONFIG_RTSP_DEMUXER) || defined(CONFIG_MMSH_PROTOCOL)
01990 if (is->paused &&
01991 (!strcmp(ic->iformat->name, "rtsp") ||
01992 (ic->pb && !strcmp(url_fileno(ic->pb)->prot->name, "mmsh")))) {
01993
01994
01995 SDL_Delay(10);
01996 continue;
01997 }
01998 #endif
01999 if (is->seek_req) {
02000 int stream_index= -1;
02001 int64_t seek_target= is->seek_pos;
02002
02003 if (is-> video_stream >= 0) stream_index= is-> video_stream;
02004 else if(is-> audio_stream >= 0) stream_index= is-> audio_stream;
02005 else if(is->subtitle_stream >= 0) stream_index= is->subtitle_stream;
02006
02007 if(stream_index>=0){
02008 seek_target= av_rescale_q(seek_target, AV_TIME_BASE_Q, ic->streams[stream_index]->time_base);
02009 }
02010
02011 ret = av_seek_frame(is->ic, stream_index, seek_target, is->seek_flags);
02012 if (ret < 0) {
02013 fprintf(stderr, "%s: error while seeking\n", is->ic->filename);
02014 }else{
02015 if (is->audio_stream >= 0) {
02016 packet_queue_flush(&is->audioq);
02017 packet_queue_put(&is->audioq, &flush_pkt);
02018 }
02019 if (is->subtitle_stream >= 0) {
02020 packet_queue_flush(&is->subtitleq);
02021 packet_queue_put(&is->subtitleq, &flush_pkt);
02022 }
02023 if (is->video_stream >= 0) {
02024 packet_queue_flush(&is->videoq);
02025 packet_queue_put(&is->videoq, &flush_pkt);
02026 }
02027 }
02028 is->seek_req = 0;
02029 }
02030
02031
02032 if (is->audioq.size > MAX_AUDIOQ_SIZE ||
02033 is->videoq.size > MAX_VIDEOQ_SIZE ||
02034 is->subtitleq.size > MAX_SUBTITLEQ_SIZE ||
02035 url_feof(ic->pb)) {
02036
02037 SDL_Delay(10);
02038 continue;
02039 }
02040 ret = av_read_frame(ic, pkt);
02041 if (ret < 0) {
02042 if (url_ferror(ic->pb) == 0) {
02043 SDL_Delay(100);
02044 continue;
02045 } else
02046 break;
02047 }
02048 if (pkt->stream_index == is->audio_stream) {
02049 packet_queue_put(&is->audioq, pkt);
02050 } else if (pkt->stream_index == is->video_stream) {
02051 packet_queue_put(&is->videoq, pkt);
02052 } else if (pkt->stream_index == is->subtitle_stream) {
02053 packet_queue_put(&is->subtitleq, pkt);
02054 } else {
02055 av_free_packet(pkt);
02056 }
02057 }
02058
02059 while (!is->abort_request) {
02060 SDL_Delay(100);
02061 }
02062
02063 ret = 0;
02064 fail:
02065
02066 global_video_state = NULL;
02067
02068
02069 if (is->audio_stream >= 0)
02070 stream_component_close(is, is->audio_stream);
02071 if (is->video_stream >= 0)
02072 stream_component_close(is, is->video_stream);
02073 if (is->subtitle_stream >= 0)
02074 stream_component_close(is, is->subtitle_stream);
02075 if (is->ic) {
02076 av_close_input_file(is->ic);
02077 is->ic = NULL;
02078 }
02079 url_set_interrupt_cb(NULL);
02080
02081 if (ret != 0) {
02082 SDL_Event event;
02083
02084 event.type = FF_QUIT_EVENT;
02085 event.user.data1 = is;
02086 SDL_PushEvent(&event);
02087 }
02088 return 0;
02089 }
02090
02091 static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
02092 {
02093 VideoState *is;
02094
02095 is = av_mallocz(sizeof(VideoState));
02096 if (!is)
02097 return NULL;
02098 av_strlcpy(is->filename, filename, sizeof(is->filename));
02099 is->iformat = iformat;
02100 is->ytop = 0;
02101 is->xleft = 0;
02102
02103
02104 is->pictq_mutex = SDL_CreateMutex();
02105 is->pictq_cond = SDL_CreateCond();
02106
02107 is->subpq_mutex = SDL_CreateMutex();
02108 is->subpq_cond = SDL_CreateCond();
02109
02110
02111 schedule_refresh(is, 40);
02112
02113 is->av_sync_type = av_sync_type;
02114 is->parse_tid = SDL_CreateThread(decode_thread, is);
02115 if (!is->parse_tid) {
02116 av_free(is);
02117 return NULL;
02118 }
02119 return is;
02120 }
02121
02122 static void stream_close(VideoState *is)
02123 {
02124 VideoPicture *vp;
02125 int i;
02126
02127 is->abort_request = 1;
02128 SDL_WaitThread(is->parse_tid, NULL);
02129
02130
02131 for(i=0;i<VIDEO_PICTURE_QUEUE_SIZE; i++) {
02132 vp = &is->pictq[i];
02133 if (vp->bmp) {
02134 SDL_FreeYUVOverlay(vp->bmp);
02135 vp->bmp = NULL;
02136 }
02137 }
02138 SDL_DestroyMutex(is->pictq_mutex);
02139 SDL_DestroyCond(is->pictq_cond);
02140 SDL_DestroyMutex(is->subpq_mutex);
02141 SDL_DestroyCond(is->subpq_cond);
02142 }
02143
02144 static void stream_cycle_channel(VideoState *is, int codec_type)
02145 {
02146 AVFormatContext *ic = is->ic;
02147 int start_index, stream_index;
02148 AVStream *st;
02149
02150 if (codec_type == CODEC_TYPE_VIDEO)
02151 start_index = is->video_stream;
02152 else if (codec_type == CODEC_TYPE_AUDIO)
02153 start_index = is->audio_stream;
02154 else
02155 start_index = is->subtitle_stream;
02156 if (start_index < (codec_type == CODEC_TYPE_SUBTITLE ? -1 : 0))
02157 return;
02158 stream_index = start_index;
02159 for(;;) {
02160 if (++stream_index >= is->ic->nb_streams)
02161 {
02162 if (codec_type == CODEC_TYPE_SUBTITLE)
02163 {
02164 stream_index = -1;
02165 goto the_end;
02166 } else
02167 stream_index = 0;
02168 }
02169 if (stream_index == start_index)
02170 return;
02171 st = ic->streams[stream_index];
02172 if (st->codec->codec_type == codec_type) {
02173
02174 switch(codec_type) {
02175 case CODEC_TYPE_AUDIO:
02176 if (st->codec->sample_rate != 0 &&
02177 st->codec->channels != 0)
02178 goto the_end;
02179 break;
02180 case CODEC_TYPE_VIDEO:
02181 case CODEC_TYPE_SUBTITLE:
02182 goto the_end;
02183 default:
02184 break;
02185 }
02186 }
02187 }
02188 the_end:
02189 stream_component_close(is, start_index);
02190 stream_component_open(is, stream_index);
02191 }
02192
02193
02194 static void toggle_full_screen(void)
02195 {
02196 is_full_screen = !is_full_screen;
02197 if (!fs_screen_width) {
02198
02199
02200 }
02201 video_open(cur_stream);
02202 }
02203
02204 static void toggle_pause(void)
02205 {
02206 if (cur_stream)
02207 stream_pause(cur_stream);
02208 step = 0;
02209 }
02210
02211 static void step_to_next_frame(void)
02212 {
02213 if (cur_stream) {
02214
02215 if (cur_stream->paused)
02216 stream_pause(cur_stream);
02217 }
02218 step = 1;
02219 }
02220
02221 static void do_exit(void)
02222 {
02223 if (cur_stream) {
02224 stream_close(cur_stream);
02225 cur_stream = NULL;
02226 }
02227 if (show_status)
02228 printf("\n");
02229 SDL_Quit();
02230 exit(0);
02231 }
02232
02233 static void toggle_audio_display(void)
02234 {
02235 if (cur_stream) {
02236 cur_stream->show_audio = !cur_stream->show_audio;
02237 }
02238 }
02239
02240
02241 static void event_loop(void)
02242 {
02243 SDL_Event event;
02244 double incr, pos, frac;
02245
02246 for(;;) {
02247 SDL_WaitEvent(&event);
02248 switch(event.type) {
02249 case SDL_KEYDOWN:
02250 switch(event.key.keysym.sym) {
02251 case SDLK_ESCAPE:
02252 case SDLK_q:
02253 do_exit();
02254 break;
02255 case SDLK_f:
02256 toggle_full_screen();
02257 break;
02258 case SDLK_p:
02259 case SDLK_SPACE:
02260 toggle_pause();
02261 break;
02262 case SDLK_s:
02263 step_to_next_frame();
02264 break;
02265 case SDLK_a:
02266 if (cur_stream)
02267 stream_cycle_channel(cur_stream, CODEC_TYPE_AUDIO);
02268 break;
02269 case SDLK_v:
02270 if (cur_stream)
02271 stream_cycle_channel(cur_stream, CODEC_TYPE_VIDEO);
02272 break;
02273 case SDLK_t:
02274 if (cur_stream)
02275 stream_cycle_channel(cur_stream, CODEC_TYPE_SUBTITLE);
02276 break;
02277 case SDLK_w:
02278 toggle_audio_display();
02279 break;
02280 case SDLK_LEFT:
02281 incr = -10.0;
02282 goto do_seek;
02283 case SDLK_RIGHT:
02284 incr = 10.0;
02285 goto do_seek;
02286 case SDLK_UP:
02287 incr = 60.0;
02288 goto do_seek;
02289 case SDLK_DOWN:
02290 incr = -60.0;
02291 do_seek:
02292 if (cur_stream) {
02293 if (seek_by_bytes) {
02294 pos = url_ftell(cur_stream->ic->pb);
02295 if (cur_stream->ic->bit_rate)
02296 incr *= cur_stream->ic->bit_rate / 60.0;
02297 else
02298 incr *= 180000.0;
02299 pos += incr;
02300 stream_seek(cur_stream, pos, incr);
02301 } else {
02302 pos = get_master_clock(cur_stream);
02303 pos += incr;
02304 stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), incr);
02305 }
02306 }
02307 break;
02308 default:
02309 break;
02310 }
02311 break;
02312 case SDL_MOUSEBUTTONDOWN:
02313 if (cur_stream) {
02314 int ns, hh, mm, ss;
02315 int tns, thh, tmm, tss;
02316 tns = cur_stream->ic->duration/1000000LL;
02317 thh = tns/3600;
02318 tmm = (tns%3600)/60;
02319 tss = (tns%60);
02320 frac = (double)event.button.x/(double)cur_stream->width;
02321 ns = frac*tns;
02322 hh = ns/3600;
02323 mm = (ns%3600)/60;
02324 ss = (ns%60);
02325 fprintf(stderr, "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
02326 hh, mm, ss, thh, tmm, tss);
02327 stream_seek(cur_stream, (int64_t)(cur_stream->ic->start_time+frac*cur_stream->ic->duration), 0);
02328 }
02329 break;
02330 case SDL_VIDEORESIZE:
02331 if (cur_stream) {
02332 screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0,
02333 SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL);
02334 screen_width = cur_stream->width = event.resize.w;
02335 screen_height= cur_stream->height= event.resize.h;
02336 }
02337 break;
02338 case SDL_QUIT:
02339 case FF_QUIT_EVENT:
02340 do_exit();
02341 break;
02342 case FF_ALLOC_EVENT:
02343 video_open(event.user.data1);
02344 alloc_picture(event.user.data1);
02345 break;
02346 case FF_REFRESH_EVENT:
02347 video_refresh_timer(event.user.data1);
02348 break;
02349 default:
02350 break;
02351 }
02352 }
02353 }
02354
02355 static void opt_frame_size(const char *arg)
02356 {
02357 if (av_parse_video_frame_size(&frame_width, &frame_height, arg) < 0) {
02358 fprintf(stderr, "Incorrect frame size\n");
02359 exit(1);
02360 }
02361 if ((frame_width % 2) != 0 || (frame_height % 2) != 0) {
02362 fprintf(stderr, "Frame size must be a multiple of 2\n");
02363 exit(1);
02364 }
02365 }
02366
02367 static void opt_width(const char *arg)
02368 {
02369 screen_width = atoi(arg);
02370 if(screen_width<=0){
02371 fprintf(stderr, "invalid width\n");
02372 exit(1);
02373 }
02374 }
02375
02376 static void opt_height(const char *arg)
02377 {
02378 screen_height = atoi(arg);
02379 if(screen_height<=0){
02380 fprintf(stderr, "invalid height\n");
02381 exit(1);
02382 }
02383 }
02384
02385 static void opt_format(const char *arg)
02386 {
02387 file_iformat = av_find_input_format(arg);
02388 if (!file_iformat) {
02389 fprintf(stderr, "Unknown input format: %s\n", arg);
02390 exit(1);
02391 }
02392 }
02393
02394 static void opt_frame_pix_fmt(const char *arg)
02395 {
02396 frame_pix_fmt = avcodec_get_pix_fmt(arg);
02397 }
02398
02399 static void opt_sync(const char *arg)
02400 {
02401 if (!strcmp(arg, "audio"))
02402 av_sync_type = AV_SYNC_AUDIO_MASTER;
02403 else if (!strcmp(arg, "video"))
02404 av_sync_type = AV_SYNC_VIDEO_MASTER;
02405 else if (!strcmp(arg, "ext"))
02406 av_sync_type = AV_SYNC_EXTERNAL_CLOCK;
02407 else {
02408 show_help();
02409 exit(1);
02410 }
02411 }
02412
02413 static void opt_seek(const char *arg)
02414 {
02415 start_time = parse_date(arg, 1);
02416 if (start_time == INT64_MIN) {
02417 fprintf(stderr, "Invalid duration specification: %s\n", arg);
02418 exit(1);
02419 }
02420 }
02421
02422 static void opt_debug(const char *arg)
02423 {
02424 av_log_set_level(99);
02425 debug = atoi(arg);
02426 }
02427
02428 static void opt_vismv(const char *arg)
02429 {
02430 debug_mv = atoi(arg);
02431 }
02432
02433 static void opt_thread_count(const char *arg)
02434 {
02435 thread_count= atoi(arg);
02436 #if !defined(HAVE_THREADS)
02437 fprintf(stderr, "Warning: not compiled with thread support, using thread emulation\n");
02438 #endif
02439 }
02440
02441 static void opt_show_help(void)
02442 {
02443 show_help();
02444 exit(0);
02445 }
02446
02447 const OptionDef options[] = {
02448 { "h", 0, {(void*)opt_show_help}, "show help" },
02449 { "x", HAS_ARG, {(void*)opt_width}, "force displayed width", "width" },
02450 { "y", HAS_ARG, {(void*)opt_height}, "force displayed height", "height" },
02451 { "s", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_size}, "set frame size (WxH or abbreviation)", "size" },
02452 { "fs", OPT_BOOL, {(void*)&is_full_screen}, "force full screen" },
02453 { "an", OPT_BOOL, {(void*)&audio_disable}, "disable audio" },
02454 { "vn", OPT_BOOL, {(void*)&video_disable}, "disable video" },
02455 { "ast", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_audio_stream}, "", "" },
02456 { "vst", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_video_stream}, "", "" },
02457 { "ss", HAS_ARG, {(void*)&opt_seek}, "seek to a given position in seconds", "pos" },
02458 { "bytes", OPT_BOOL, {(void*)&seek_by_bytes}, "seek by bytes" },
02459 { "nodisp", OPT_BOOL, {(void*)&display_disable}, "disable graphical display" },
02460 { "f", HAS_ARG, {(void*)opt_format}, "force format", "fmt" },
02461 { "pix_fmt", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_frame_pix_fmt}, "set pixel format", "format" },
02462 { "stats", OPT_BOOL | OPT_EXPERT, {(void*)&show_status}, "show status", "" },
02463 { "debug", HAS_ARG | OPT_EXPERT, {(void*)opt_debug}, "print specific debug info", "" },
02464 { "bug", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&workaround_bugs}, "workaround bugs", "" },
02465 { "vismv", HAS_ARG | OPT_EXPERT, {(void*)opt_vismv}, "visualize motion vectors", "" },
02466 { "fast", OPT_BOOL | OPT_EXPERT, {(void*)&fast}, "non spec compliant optimizations", "" },
02467 { "genpts", OPT_BOOL | OPT_EXPERT, {(void*)&genpts}, "generate pts", "" },
02468 { "drp", OPT_BOOL |OPT_EXPERT, {(void*)&decoder_reorder_pts}, "let decoder reorder pts", ""},
02469 { "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&lowres}, "", "" },
02470 { "skiploop", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_loop_filter}, "", "" },
02471 { "skipframe", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_frame}, "", "" },
02472 { "skipidct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_idct}, "", "" },
02473 { "idct", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&idct}, "set idct algo", "algo" },
02474 { "er", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_resilience}, "set error detection threshold (0-4)", "threshold" },
02475 { "ec", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&error_concealment}, "set error concealment options", "bit_mask" },
02476 { "sync", HAS_ARG | OPT_EXPERT, {(void*)opt_sync}, "set audio-video sync. type (type=audio/video/ext)", "type" },
02477 { "threads", HAS_ARG | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" },
02478 { NULL, },
02479 };
02480
02481 void show_help(void)
02482 {
02483 printf("usage: ffplay [options] input_file\n"
02484 "Simple media player\n");
02485 printf("\n");
02486 show_help_options(options, "Main options:\n",
02487 OPT_EXPERT, 0);
02488 show_help_options(options, "\nAdvanced options:\n",
02489 OPT_EXPERT, OPT_EXPERT);
02490 printf("\nWhile playing:\n"
02491 "q, ESC quit\n"
02492 "f toggle full screen\n"
02493 "p, SPC pause\n"
02494 "a cycle audio channel\n"
02495 "v cycle video channel\n"
02496 "t cycle subtitle channel\n"
02497 "w show audio waves\n"
02498 "left/right seek backward/forward 10 seconds\n"
02499 "down/up seek backward/forward 1 minute\n"
02500 "mouse click seek to percentage in file corresponding to fraction of width\n"
02501 );
02502 }
02503
02504 void opt_input_file(const char *filename)
02505 {
02506 if (!strcmp(filename, "-"))
02507 filename = "pipe:";
02508 input_filename = filename;
02509 }
02510
02511
02512 int main(int argc, char **argv)
02513 {
02514 int flags;
02515
02516
02517 avcodec_register_all();
02518 avdevice_register_all();
02519 av_register_all();
02520
02521 show_banner(program_name, program_birth_year);
02522
02523 parse_options(argc, argv, options, opt_input_file);
02524
02525 if (!input_filename) {
02526 show_help();
02527 exit(1);
02528 }
02529
02530 if (display_disable) {
02531 video_disable = 1;
02532 }
02533 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
02534 #if !defined(__MINGW32__) && !defined(__APPLE__)
02535 flags |= SDL_INIT_EVENTTHREAD;
02536 #endif
02537 if (SDL_Init (flags)) {
02538 fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
02539 exit(1);
02540 }
02541
02542 if (!display_disable) {
02543 #ifdef HAVE_SDL_VIDEO_SIZE
02544 const SDL_VideoInfo *vi = SDL_GetVideoInfo();
02545 fs_screen_width = vi->current_w;
02546 fs_screen_height = vi->current_h;
02547 #endif
02548 }
02549
02550 SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
02551 SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
02552 SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
02553 SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
02554
02555 av_init_packet(&flush_pkt);
02556 flush_pkt.data= "FLUSH";
02557
02558 cur_stream = stream_open(input_filename, file_iformat);
02559
02560 event_loop();
02561
02562
02563
02564 return 0;
02565 }