]> git.sesse.net Git - ffmpeg/blobdiff - ffplay.c
ensure that the aspect ratio is spec compliant
[ffmpeg] / ffplay.c
index bc53a8c1fb84f24e7730f105fad31894e92dd182..5d0ff1c7bfa16d2d2b66c4779e88353c7b01afc7 100644 (file)
--- a/ffplay.c
+++ b/ffplay.c
@@ -19,6 +19,8 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <math.h>
+#include <limits.h>
 #include "avformat.h"
 #include "swscale.h"
 #include "avstring.h"
 #undef main /* We don't want SDL to override our main() */
 #endif
 
-#ifdef CONFIG_OS2
-#define INCL_DOS
- #include <os2.h>
- #include <stdio.h>
-
- void MorphToPM()
- {
-   PPIB pib;
-   PTIB tib;
-
-   DosGetInfoBlocks(&tib, &pib);
-
-   // Change flag from VIO to PM:
-   if (pib->pib_ultype==2) pib->pib_ultype = 3;
- }
-#endif
-
 #undef exit
 
 //#define DEBUG_SYNC
@@ -195,6 +180,7 @@ static enum PixelFormat frame_pix_fmt = PIX_FMT_NONE;
 static int audio_disable;
 static int video_disable;
 static int wanted_audio_stream= 0;
+static int wanted_video_stream= 0;
 static int seek_by_bytes;
 static int display_disable;
 static int show_status;
@@ -421,7 +407,7 @@ void fill_border(VideoState *s, int x, int y, int w, int h, int color)
 
 #define YUVA_IN(y, u, v, a, s, pal)\
 {\
-    unsigned int val = ((const uint32_t *)(pal))[*(const uint8_t*)s];\
+    unsigned int val = ((const uint32_t *)(pal))[*(const uint8_t*)(s)];\
     a = (val >> 24) & 0xff;\
     y = (val >> 16) & 0xff;\
     u = (val >> 8) & 0xff;\
@@ -436,31 +422,36 @@ void fill_border(VideoState *s, int x, int y, int w, int h, int color)
 
 #define BPP 1
 
-static void blend_subrect(AVPicture *dst, const AVSubtitleRect *rect)
+static void blend_subrect(AVPicture *dst, const AVSubtitleRect *rect, int imgw, int imgh)
 {
     int wrap, wrap3, width2, skip2;
     int y, u, v, a, u1, v1, a1, w, h;
     uint8_t *lum, *cb, *cr;
     const uint8_t *p;
     const uint32_t *pal;
-
-    lum = dst->data[0] + rect->y * dst->linesize[0];
-    cb = dst->data[1] + (rect->y >> 1) * dst->linesize[1];
-    cr = dst->data[2] + (rect->y >> 1) * dst->linesize[2];
-
-    width2 = (rect->w + 1) >> 1;
-    skip2 = rect->x >> 1;
+    int dstx, dsty, dstw, dsth;
+
+    dstx = FFMIN(FFMAX(rect->x, 0), imgw);
+    dstw = FFMIN(FFMAX(rect->w, 0), imgw - dstx);
+    dsty = FFMIN(FFMAX(rect->y, 0), imgh);
+    dsth = FFMIN(FFMAX(rect->h, 0), imgh - dsty);
+    lum = dst->data[0] + dsty * dst->linesize[0];
+    cb = dst->data[1] + (dsty >> 1) * dst->linesize[1];
+    cr = dst->data[2] + (dsty >> 1) * dst->linesize[2];
+
+    width2 = (dstw + 1) >> 1;
+    skip2 = dstx >> 1;
     wrap = dst->linesize[0];
     wrap3 = rect->linesize;
     p = rect->bitmap;
     pal = rect->rgba_palette;  /* Now in YCrCb! */
 
-    if (rect->y & 1) {
-        lum += rect->x;
+    if (dsty & 1) {
+        lum += dstx;
         cb += skip2;
         cr += skip2;
 
-        if (rect->x & 1) {
+        if (dstx & 1) {
             YUVA_IN(y, u, v, a, p, pal);
             lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
             cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
@@ -470,7 +461,7 @@ static void blend_subrect(AVPicture *dst, const AVSubtitleRect *rect)
             lum++;
             p += BPP;
         }
-        for(w = rect->w - (rect->x & 1); w >= 2; w -= 2) {
+        for(w = dstw - (dstx & 1); w >= 2; w -= 2) {
             YUVA_IN(y, u, v, a, p, pal);
             u1 = u;
             v1 = v;
@@ -495,17 +486,17 @@ static void blend_subrect(AVPicture *dst, const AVSubtitleRect *rect)
             cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
             cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
         }
-        p += wrap3 + (wrap3 - rect->w * BPP);
-        lum += wrap + (wrap - rect->w - rect->x);
+        p += wrap3 + (wrap3 - dstw * BPP);
+        lum += wrap + (wrap - dstw - dstx);
         cb += dst->linesize[1] - width2 - skip2;
         cr += dst->linesize[2] - width2 - skip2;
     }
-    for(h = rect->h - (rect->y & 1); h >= 2; h -= 2) {
-        lum += rect->x;
+    for(h = dsth - (dsty & 1); h >= 2; h -= 2) {
+        lum += dstx;
         cb += skip2;
         cr += skip2;
 
-        if (rect->x & 1) {
+        if (dstx & 1) {
             YUVA_IN(y, u, v, a, p, pal);
             u1 = u;
             v1 = v;
@@ -525,7 +516,7 @@ static void blend_subrect(AVPicture *dst, const AVSubtitleRect *rect)
             p += -wrap3 + BPP;
             lum += -wrap + 1;
         }
-        for(w = rect->w - (rect->x & 1); w >= 2; w -= 2) {
+        for(w = dstw - (dstx & 1); w >= 2; w -= 2) {
             YUVA_IN(y, u, v, a, p, pal);
             u1 = u;
             v1 = v;
@@ -580,18 +571,18 @@ static void blend_subrect(AVPicture *dst, const AVSubtitleRect *rect)
             p += -wrap3 + BPP;
             lum += -wrap + 1;
         }
-        p += wrap3 + (wrap3 - rect->w * BPP);
-        lum += wrap + (wrap - rect->w - rect->x);
+        p += wrap3 + (wrap3 - dstw * BPP);
+        lum += wrap + (wrap - dstw - dstx);
         cb += dst->linesize[1] - width2 - skip2;
         cr += dst->linesize[2] - width2 - skip2;
     }
     /* handle odd height */
     if (h) {
-        lum += rect->x;
+        lum += dstx;
         cb += skip2;
         cr += skip2;
 
-        if (rect->x & 1) {
+        if (dstx & 1) {
             YUVA_IN(y, u, v, a, p, pal);
             lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
             cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
@@ -601,7 +592,7 @@ static void blend_subrect(AVPicture *dst, const AVSubtitleRect *rect)
             lum++;
             p += BPP;
         }
-        for(w = rect->w - (rect->x & 1); w >= 2; w -= 2) {
+        for(w = dstw - (dstx & 1); w >= 2; w -= 2) {
             YUVA_IN(y, u, v, a, p, pal);
             u1 = u;
             v1 = v;
@@ -719,7 +710,8 @@ static void video_image_display(VideoState *is)
                     pict.linesize[2] = vp->bmp->pitches[1];
 
                     for (i = 0; i < sp->sub.num_rects; i++)
-                        blend_subrect(&pict, &sp->sub.rects[i]);
+                        blend_subrect(&pict, &sp->sub.rects[i],
+                                      vp->bmp->w, vp->bmp->h);
 
                     SDL_UnlockYUVOverlay (vp->bmp);
                 }
@@ -1266,15 +1258,14 @@ static int queue_picture(VideoState *is, AVFrame *src_frame, double pts)
         pict.linesize[0] = vp->bmp->pitches[0];
         pict.linesize[1] = vp->bmp->pitches[2];
         pict.linesize[2] = vp->bmp->pitches[1];
+        img_convert_ctx = sws_getCachedContext(img_convert_ctx,
+            is->video_st->codec->width, is->video_st->codec->height,
+            is->video_st->codec->pix_fmt,
+            is->video_st->codec->width, is->video_st->codec->height,
+            dst_pix_fmt, sws_flags, NULL, NULL, NULL);
         if (img_convert_ctx == NULL) {
-            img_convert_ctx = sws_getContext(is->video_st->codec->width,
-                    is->video_st->codec->height, is->video_st->codec->pix_fmt,
-                    is->video_st->codec->width, is->video_st->codec->height,
-                    dst_pix_fmt, sws_flags, NULL, NULL, NULL);
-            if (img_convert_ctx == NULL) {
-                fprintf(stderr, "Cannot initialize the conversion context\n");
-                exit(1);
-            }
+            fprintf(stderr, "Cannot initialize the conversion context\n");
+            exit(1);
         }
         sws_scale(img_convert_ctx, src_frame->data, src_frame->linesize,
                   0, is->video_st->codec->height, pict.data, pict.linesize);
@@ -1963,7 +1954,7 @@ static int decode_thread(void *arg)
                 audio_index = i;
             break;
         case CODEC_TYPE_VIDEO:
-            if (video_index < 0 && !video_disable)
+            if ((video_index < 0 || wanted_video_stream-- > 0) && !video_disable)
                 video_index = i;
             break;
         default:
@@ -2427,8 +2418,10 @@ static void opt_sync(const char *arg)
         av_sync_type = AV_SYNC_VIDEO_MASTER;
     else if (!strcmp(arg, "ext"))
         av_sync_type = AV_SYNC_EXTERNAL_CLOCK;
-    else
+    else {
         show_help();
+        exit(1);
+    }
 }
 
 static void opt_seek(const char *arg)
@@ -2455,8 +2448,14 @@ static void opt_thread_count(const char *arg)
 #endif
 }
 
+static void opt_show_help(void)
+{
+    show_help();
+    exit(0);
+}
+
 const OptionDef options[] = {
-    { "h", 0, {(void*)show_help}, "show help" },
+    { "h", 0, {(void*)opt_show_help}, "show help" },
     { "x", HAS_ARG, {(void*)opt_width}, "force displayed width", "width" },
     { "y", HAS_ARG, {(void*)opt_height}, "force displayed height", "height" },
     { "s", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_size}, "set frame size (WxH or abbreviation)", "size" },
@@ -2464,6 +2463,7 @@ const OptionDef options[] = {
     { "an", OPT_BOOL, {(void*)&audio_disable}, "disable audio" },
     { "vn", OPT_BOOL, {(void*)&video_disable}, "disable video" },
     { "ast", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_audio_stream}, "", "" },
+    { "vst", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_video_stream}, "", "" },
     { "ss", HAS_ARG, {(void*)&opt_seek}, "seek to a given position in seconds", "pos" },
     { "bytes", OPT_BOOL, {(void*)&seek_by_bytes}, "seek by bytes" },
     { "nodisp", OPT_BOOL, {(void*)&display_disable}, "disable graphical display" },
@@ -2493,7 +2493,7 @@ const OptionDef options[] = {
 
 void show_help(void)
 {
-    printf("ffplay version " FFMPEG_VERSION ", Copyright (c) 2003-2006 Fabrice Bellard, et al.\n"
+    printf("ffplay version " FFMPEG_VERSION ", Copyright (c) 2003-2007 Fabrice Bellard, et al.\n"
            "usage: ffplay [options] input_file\n"
            "Simple media player\n");
     printf("\n");
@@ -2513,7 +2513,6 @@ void show_help(void)
            "down/up             seek backward/forward 1 minute\n"
            "mouse click         seek to percentage in file corresponding to fraction of width\n"
            );
-    exit(1);
 }
 
 void parse_arg_file(const char *filename)
@@ -2531,18 +2530,12 @@ int main(int argc, char **argv)
     /* register all codecs, demux and protocols */
     av_register_all();
 
-    #ifdef CONFIG_OS2
-      MorphToPM(); // Morph the VIO application to a PM one to be able to use Win* functions
-
-      // Make stdout and stderr unbuffered
-      setbuf( stdout, NULL );
-      setbuf( stderr, NULL );
-    #endif
-
     parse_options(argc, argv, options);
 
-    if (!input_filename)
+    if (!input_filename) {
         show_help();
+        exit(1);
+    }
 
     if (display_disable) {
         video_disable = 1;