Ticket #3604: 0001-ffplay-convert-ffplay-to-use-SDL2.patch
| File 0001-ffplay-convert-ffplay-to-use-SDL2.patch, 40.4 KB (added by , 11 years ago) |
|---|
-
configure
From 84019449aea94dc2519d6dd6801f41738aee415a Mon Sep 17 00:00:00 2001 From: Marton Balint <cus@passwd.hu> Date: Tue, 23 Feb 2016 20:43:41 +0000 Subject: [PATCH 1/2] ffplay: convert ffplay to use SDL2 --- configure | 27 ++- ffplay.c | 591 ++++++++++++++++++++++++++------------------------------------ 2 files changed, 268 insertions(+), 350 deletions(-) diff --git a/configure b/configure index 3d1ee49..bd65ce4 100755
a b HAVE_LIST=" 1964 1964 perl 1965 1965 pod2man 1966 1966 sdl 1967 sdl2 1967 1968 section_data_rel_ro 1968 1969 texi2html 1969 1970 threads … … ffmpeg_deps="avcodec avfilter avformat swresample" 2960 2961 ffmpeg_select="aformat_filter anull_filter atrim_filter format_filter 2961 2962 null_filter 2962 2963 setpts_filter trim_filter" 2963 ffplay_deps="avcodec avformat swscale swresample sdl "2964 ffplay_libs='$sdl _libs'2964 ffplay_deps="avcodec avformat swscale swresample sdl2" 2965 ffplay_libs='$sdl2_libs' 2965 2966 ffplay_select="rdft crop_filter transpose_filter hflip_filter vflip_filter rotate_filter" 2966 2967 ffprobe_deps="avcodec avformat" 2967 2968 ffserver_deps="avformat fork sarestart" … … if enabled gcrypt; then 5630 5631 fi 5631 5632 fi 5632 5633 5633 if ! disabled sdl; then 5634 5635 SDL2_CONFIG="${cross_prefix}sdl2-config" 5636 if check_pkg_config sdl2 SDL_events.h SDL_PollEvent; then 5637 check_cpp_condition SDL.h "(SDL_MAJOR_VERSION<<16 | SDL_MINOR_VERSION<<8 | SDL_PATCHLEVEL) >= 0x020001" $sdl2_cflags && 5638 check_cpp_condition SDL.h "(SDL_MAJOR_VERSION<<16 | SDL_MINOR_VERSION<<8 | SDL_PATCHLEVEL) < 0x020100" $sdl2_cflags && 5639 enable sdl2 5640 else 5641 if "${SDL2_CONFIG}" --version > /dev/null 2>&1; then 5642 sdl2_cflags=$("${SDL2_CONFIG}" --cflags) 5643 sdl2_libs=$("${SDL2_CONFIG}" --libs) 5644 check_cpp_condition SDL.h "(SDL_MAJOR_VERSION<<16 | SDL_MINOR_VERSION<<8 | SDL_PATCHLEVEL) >= 0x020001" $sdl2_cflags && 5645 check_cpp_condition SDL.h "(SDL_MAJOR_VERSION<<16 | SDL_MINOR_VERSION<<8 | SDL_PATCHLEVEL) < 0x020100" $sdl2_cflags && 5646 enable sdl2 5647 fi 5648 fi 5649 enabled sdl2 && add_cflags $sdl2_cflags && add_extralibs $sdl2_libs 5650 5651 if ! disabled sdl and ! enabled sdl2; then 5634 5652 SDL_CONFIG="${cross_prefix}sdl-config" 5635 5653 if check_pkg_config sdl SDL_events.h SDL_PollEvent; then 5636 5654 check_cpp_condition SDL.h "(SDL_MAJOR_VERSION<<16 | SDL_MINOR_VERSION<<8 | SDL_PATCHLEVEL) >= 0x010201" $sdl_cflags && … … echo "network support ${network-no}" 6223 6241 echo "threading support ${thread_type-no}" 6224 6242 echo "safe bitstream reader ${safe_bitstream_reader-no}" 6225 6243 echo "SDL support ${sdl-no}" 6244 echo "SDL2 support ${sdl2-no}" 6226 6245 echo "opencl enabled ${opencl-no}" 6227 6246 echo "texi2html enabled ${texi2html-no}" 6228 6247 echo "perl enabled ${perl-no}" … … HOSTLD_O=$HOSTLD_O 6376 6395 TARGET_EXEC=$target_exec $target_exec_args 6377 6396 TARGET_PATH=$target_path 6378 6397 TARGET_SAMPLES=${target_samples:-\$(SAMPLES)} 6379 CFLAGS-ffplay=$sdl _cflags6398 CFLAGS-ffplay=$sdl2_cflags 6380 6399 ZLIB=$($ldflags_filter -lz) 6381 6400 LIB_INSTALL_EXTRA_CMD=$LIB_INSTALL_EXTRA_CMD 6382 6401 EXTRALIBS=$extralibs -
ffplay.c
diff --git a/ffplay.c b/ffplay.c index 2cfdf26..d4193ad 100644
a b const int program_birth_year = 2003; 105 105 106 106 #define CURSOR_HIDE_DELAY 1000000 107 107 108 #define USE_ONEPASS_SUBTITLE_RENDER 1 109 108 110 static unsigned sws_flags = SWS_BICUBIC; 109 111 110 112 typedef struct MyAVPacketList { … … typedef struct Clock { 151 153 typedef struct Frame { 152 154 AVFrame *frame; 153 155 AVSubtitle sub; 154 AVSubtitleRect **subrects; /* rescaled subtitle rectangles in yuva */155 156 int serial; 156 157 double pts; /* presentation timestamp for the frame */ 157 158 double duration; /* estimated duration of the frame */ 158 159 int64_t pos; /* byte position of the frame in the input file */ 159 SDL_ Overlay*bmp;160 SDL_Texture *bmp; 160 161 int allocated; 161 int reallocate;162 162 int width; 163 163 int height; 164 int format; 164 165 AVRational sar; 166 int uploaded; 165 167 } Frame; 166 168 167 169 typedef struct FrameQueue { … … typedef struct VideoState { 272 274 FFTSample *rdft_data; 273 275 int xpos; 274 276 double last_vis_time; 277 SDL_Texture *vis_texture; 278 SDL_Texture *sub_texture; 275 279 276 280 int subtitle_stream; 277 281 AVStream *subtitle_st; … … typedef struct VideoState { 284 288 AVStream *video_st; 285 289 PacketQueue videoq; 286 290 double max_frame_duration; // maximum duration of a frame - above this, we consider the jump a timestamp discontinuity 287 #if !CONFIG_AVFILTER288 291 struct SwsContext *img_convert_ctx; 289 #endif290 292 struct SwsContext *sub_convert_ctx; 291 SDL_Rect last_display_rect;292 293 int eof; 293 294 294 295 char *filename; … … typedef struct VideoState { 313 314 static AVInputFormat *file_iformat; 314 315 static const char *input_filename; 315 316 static const char *window_title; 316 static int fs_screen_width;317 static int fs_screen_height;318 317 static int default_width = 640; 319 318 static int default_height = 480; 320 319 static int screen_width = 0; … … static AVPacket flush_pkt; 362 361 #define FF_ALLOC_EVENT (SDL_USEREVENT) 363 362 #define FF_QUIT_EVENT (SDL_USEREVENT + 2) 364 363 365 static SDL_Surface *screen; 364 static SDL_Window *window; 365 static SDL_Renderer *renderer; 366 366 367 367 #if CONFIG_AVFILTER 368 368 static int opt_add_vfilter(void *optctx, const char *opt, const char *arg) … … static void decoder_destroy(Decoder *d) { 646 646 647 647 static void frame_queue_unref_item(Frame *vp) 648 648 { 649 int i;650 for (i = 0; i < vp->sub.num_rects; i++) {651 av_freep(&vp->subrects[i]->data[0]);652 av_freep(&vp->subrects[i]);653 }654 av_freep(&vp->subrects);655 649 av_frame_unref(vp->frame); 656 650 avsubtitle_free(&vp->sub); 657 651 } … … static void decoder_abort(Decoder *d, FrameQueue *fq) 802 796 packet_queue_flush(d->queue); 803 797 } 804 798 805 static inline void fill_rectangle(SDL_Surface *screen, 806 int x, int y, int w, int h, int color, int update) 799 static inline void fill_rectangle(int x, int y, int w, int h) 807 800 { 808 801 SDL_Rect rect; 809 802 rect.x = x; 810 803 rect.y = y; 811 804 rect.w = w; 812 805 rect.h = h; 813 SDL_FillRect(screen, &rect, color); 814 if (update && w > 0 && h > 0) 815 SDL_UpdateRect(screen, x, y, w, h); 816 } 817 818 /* draw only the border of a rectangle */ 819 static void fill_border(int xleft, int ytop, int width, int height, int x, int y, int w, int h, int color, int update) 820 { 821 int w1, w2, h1, h2; 822 823 /* fill the background */ 824 w1 = x; 825 if (w1 < 0) 826 w1 = 0; 827 w2 = width - (x + w); 828 if (w2 < 0) 829 w2 = 0; 830 h1 = y; 831 if (h1 < 0) 832 h1 = 0; 833 h2 = height - (y + h); 834 if (h2 < 0) 835 h2 = 0; 836 fill_rectangle(screen, 837 xleft, ytop, 838 w1, height, 839 color, update); 840 fill_rectangle(screen, 841 xleft + width - w2, ytop, 842 w2, height, 843 color, update); 844 fill_rectangle(screen, 845 xleft + w1, ytop, 846 width - w1 - w2, h1, 847 color, update); 848 fill_rectangle(screen, 849 xleft + w1, ytop + height - h2, 850 width - w1 - w2, h2, 851 color, update); 852 } 853 854 #define ALPHA_BLEND(a, oldp, newp, s)\ 855 ((((oldp << s) * (255 - (a))) + (newp * (a))) / (255 << s)) 856 857 858 859 #define BPP 1 860 861 static void blend_subrect(uint8_t **data, int *linesize, const AVSubtitleRect *rect, int imgw, int imgh) 862 { 863 int x, y, Y, U, V, A; 864 uint8_t *lum, *cb, *cr; 865 int dstx, dsty, dstw, dsth; 866 const AVSubtitleRect *src = rect; 867 868 dstw = av_clip(rect->w, 0, imgw); 869 dsth = av_clip(rect->h, 0, imgh); 870 dstx = av_clip(rect->x, 0, imgw - dstw); 871 dsty = av_clip(rect->y, 0, imgh - dsth); 872 lum = data[0] + dstx + dsty * linesize[0]; 873 cb = data[1] + dstx/2 + (dsty >> 1) * linesize[1]; 874 cr = data[2] + dstx/2 + (dsty >> 1) * linesize[2]; 875 876 for (y = 0; y<dsth; y++) { 877 for (x = 0; x<dstw; x++) { 878 Y = src->data[0][x + y*src->linesize[0]]; 879 A = src->data[3][x + y*src->linesize[3]]; 880 lum[0] = ALPHA_BLEND(A, lum[0], Y, 0); 881 lum++; 882 } 883 lum += linesize[0] - dstw; 884 } 885 886 for (y = 0; y<dsth/2; y++) { 887 for (x = 0; x<dstw/2; x++) { 888 U = src->data[1][x + y*src->linesize[1]]; 889 V = src->data[2][x + y*src->linesize[2]]; 890 A = src->data[3][2*x + 2*y *src->linesize[3]] 891 + src->data[3][2*x + 1 + 2*y *src->linesize[3]] 892 + src->data[3][2*x + 1 + (2*y+1)*src->linesize[3]] 893 + src->data[3][2*x + (2*y+1)*src->linesize[3]]; 894 cb[0] = ALPHA_BLEND(A>>2, cb[0], U, 0); 895 cr[0] = ALPHA_BLEND(A>>2, cr[0], V, 0); 896 cb++; 897 cr++; 898 } 899 cb += linesize[1] - dstw/2; 900 cr += linesize[2] - dstw/2; 901 } 806 if (w && h) 807 SDL_RenderFillRect(renderer, &rect); 902 808 } 903 809 904 810 static void free_picture(Frame *vp) 905 811 { 906 812 if (vp->bmp) { 907 SDL_ FreeYUVOverlay(vp->bmp);813 SDL_DestroyTexture(vp->bmp); 908 814 vp->bmp = NULL; 909 815 } 910 816 } 911 817 818 static int realloc_texture(SDL_Texture **texture, Uint32 new_format, int new_width, int new_height, SDL_BlendMode blendmode, int init_texture) 819 { 820 Uint32 format; 821 int access, w, h; 822 if (SDL_QueryTexture(*texture, &format, &access, &w, &h) < 0 || new_width != w || new_height != h || new_format != format) { 823 void *pixels; 824 int pitch; 825 SDL_DestroyTexture(*texture); 826 if (!(*texture = SDL_CreateTexture(renderer, new_format, SDL_TEXTUREACCESS_STREAMING, new_width, new_height))) 827 return -1; 828 if (SDL_SetTextureBlendMode(*texture, blendmode) < 0) 829 return -1; 830 if (init_texture) { 831 if (SDL_LockTexture(*texture, NULL, &pixels, &pitch) < 0) 832 return -1; 833 memset(pixels, 0, pitch * new_height); 834 SDL_UnlockTexture(*texture); 835 } 836 } 837 return 0; 838 } 839 912 840 static void calculate_display_rect(SDL_Rect *rect, 913 841 int scr_xleft, int scr_ytop, int scr_width, int scr_height, 914 842 int pic_width, int pic_height, AVRational pic_sar) … … static void calculate_display_rect(SDL_Rect *rect, 940 868 rect->h = FFMAX(height, 1); 941 869 } 942 870 871 static int upload_texture(SDL_Texture *tex, AVFrame *frame, struct SwsContext **img_convert_ctx) { 872 int ret = 0; 873 switch (frame->format) { 874 case AV_PIX_FMT_YUV420P: 875 ret = SDL_UpdateYUVTexture(tex, NULL, frame->data[0], frame->linesize[0], 876 frame->data[1], frame->linesize[1], 877 frame->data[2], frame->linesize[2]); 878 break; 879 case AV_PIX_FMT_BGRA: 880 ret = SDL_UpdateTexture(tex, NULL, frame->data[0], frame->linesize[0]); 881 break; 882 default: 883 /* This should only happen if we are not using avfilter... */ 884 *img_convert_ctx = sws_getCachedContext(*img_convert_ctx, 885 frame->width, frame->height, frame->format, frame->width, frame->height, 886 AV_PIX_FMT_BGRA, sws_flags, NULL, NULL, NULL); 887 if (*img_convert_ctx != NULL) { 888 uint8_t *pixels; 889 int pitch; 890 if (!SDL_LockTexture(tex, NULL, (void **)&pixels, &pitch)) { 891 sws_scale(*img_convert_ctx, (const uint8_t * const *)frame->data, frame->linesize, 892 0, frame->height, &pixels, &pitch); 893 SDL_UnlockTexture(tex); 894 } 895 } else { 896 av_log(NULL, AV_LOG_FATAL, "Cannot initialize the conversion context\n"); 897 ret = -1; 898 } 899 break; 900 } 901 return ret; 902 } 903 943 904 static void video_image_display(VideoState *is) 944 905 { 945 906 Frame *vp; 946 Frame *sp ;907 Frame *sp = NULL; 947 908 SDL_Rect rect; 948 int i;949 909 950 910 vp = frame_queue_peek(&is->pictq); 951 911 if (vp->bmp) { … … static void video_image_display(VideoState *is) 954 914 sp = frame_queue_peek(&is->subpq); 955 915 956 916 if (vp->pts >= sp->pts + ((float) sp->sub.start_display_time / 1000)) { 957 uint8_t *data[4]; 958 int linesize[4]; 959 960 SDL_LockYUVOverlay (vp->bmp); 961 962 data[0] = vp->bmp->pixels[0]; 963 data[1] = vp->bmp->pixels[2]; 964 data[2] = vp->bmp->pixels[1]; 965 966 linesize[0] = vp->bmp->pitches[0]; 967 linesize[1] = vp->bmp->pitches[2]; 968 linesize[2] = vp->bmp->pitches[1]; 969 970 for (i = 0; i < sp->sub.num_rects; i++) 971 blend_subrect(data, linesize, sp->subrects[i], 972 vp->bmp->w, vp->bmp->h); 973 974 SDL_UnlockYUVOverlay (vp->bmp); 975 } 917 if (!sp->uploaded) { 918 uint8_t *pixels; 919 int pitch; 920 int i; 921 if (!sp->width || !sp->height) { 922 sp->width = vp->width; 923 sp->height = vp->height; 924 } 925 if (realloc_texture(&is->sub_texture, SDL_PIXELFORMAT_ARGB8888, sp->width, sp->height, SDL_BLENDMODE_BLEND, 1) < 0) 926 return; 927 928 for (i = 0; i < sp->sub.num_rects; i++) { 929 AVSubtitleRect *sub_rect = sp->sub.rects[i]; 930 931 sub_rect->x = av_clip(sub_rect->x, 0, sp->width ); 932 sub_rect->y = av_clip(sub_rect->y, 0, sp->height); 933 sub_rect->w = av_clip(sub_rect->w, 0, sp->width - sub_rect->x); 934 sub_rect->h = av_clip(sub_rect->h, 0, sp->height - sub_rect->y); 935 936 is->sub_convert_ctx = sws_getCachedContext(is->sub_convert_ctx, 937 sub_rect->w, sub_rect->h, AV_PIX_FMT_PAL8, 938 sub_rect->w, sub_rect->h, AV_PIX_FMT_BGRA, 939 0, NULL, NULL, NULL); 940 if (!is->sub_convert_ctx) { 941 av_log(NULL, AV_LOG_FATAL, "Cannot initialize the conversion context\n"); 942 return; 943 } 944 if (!SDL_LockTexture(is->sub_texture, (SDL_Rect *)sub_rect, (void **)&pixels, &pitch)) { 945 sws_scale(is->sub_convert_ctx, (const uint8_t * const *)sub_rect->data, sub_rect->linesize, 946 0, sub_rect->h, &pixels, &pitch); 947 SDL_UnlockTexture(is->sub_texture); 948 } 949 } 950 sp->uploaded = 1; 951 } 952 } else 953 sp = NULL; 976 954 } 977 955 } 978 956 979 957 calculate_display_rect(&rect, is->xleft, is->ytop, is->width, is->height, vp->width, vp->height, vp->sar); 980 958 981 SDL_DisplayYUVOverlay(vp->bmp, &rect); 959 if (!vp->uploaded) { 960 if (upload_texture(vp->bmp, vp->frame, &is->img_convert_ctx) < 0) 961 return; 962 vp->uploaded = 1; 963 } 982 964 983 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) { 984 int bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00); 985 fill_border(is->xleft, is->ytop, is->width, is->height, rect.x, rect.y, rect.w, rect.h, bgcolor, 1); 986 is->last_display_rect = rect; 965 SDL_RenderCopy(renderer, vp->bmp, NULL, &rect); 966 if (sp) { 967 #if USE_ONEPASS_SUBTITLE_RENDER 968 SDL_RenderCopy(renderer, is->sub_texture, NULL, &rect); 969 #else 970 int i; 971 double xratio = (double)rect.w / (double)sp->width; 972 double yratio = (double)rect.h / (double)sp->height; 973 for (i = 0; i < sp->sub.num_rects; i++) { 974 SDL_Rect *sub_rect = (SDL_Rect*)sp->sub.rects[i]; 975 SDL_Rect target = {.x = rect.x + sub_rect->x * xratio, 976 .y = rect.y + sub_rect->y * yratio, 977 .w = sub_rect->w * xratio, 978 .h = sub_rect->h * yratio}; 979 SDL_RenderCopy(renderer, is->sub_texture, sub_rect, &target); 980 } 981 #endif 987 982 } 988 983 } 989 984 } … … static inline int compute_mod(int a, int b) 996 991 static void video_audio_display(VideoState *s) 997 992 { 998 993 int i, i_start, x, y1, y, ys, delay, n, nb_display_channels; 999 int ch, channels, h, h2 , bgcolor, fgcolor;994 int ch, channels, h, h2; 1000 995 int64_t time_diff; 1001 996 int rdft_bits, nb_freq; 1002 997 … … static void video_audio_display(VideoState *s) 1046 1041 i_start = s->last_i_start; 1047 1042 } 1048 1043 1049 bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);1050 1044 if (s->show_mode == SHOW_MODE_WAVES) { 1051 fill_rectangle(screen, 1052 s->xleft, s->ytop, s->width, s->height, 1053 bgcolor, 0); 1054 1055 fgcolor = SDL_MapRGB(screen->format, 0xff, 0xff, 0xff); 1045 SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); 1056 1046 1057 1047 /* total height for one channel */ 1058 1048 h = s->height / nb_display_channels; … … static void video_audio_display(VideoState *s) 1069 1059 } else { 1070 1060 ys = y1; 1071 1061 } 1072 fill_rectangle(screen, 1073 s->xleft + x, ys, 1, y, 1074 fgcolor, 0); 1062 fill_rectangle(s->xleft + x, ys, 1, y); 1075 1063 i += channels; 1076 1064 if (i >= SAMPLE_ARRAY_SIZE) 1077 1065 i -= SAMPLE_ARRAY_SIZE; 1078 1066 } 1079 1067 } 1080 1068 1081 fgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0xff);1069 SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255); 1082 1070 1083 1071 for (ch = 1; ch < nb_display_channels; ch++) { 1084 1072 y = s->ytop + ch * h; 1085 fill_rectangle(screen, 1086 s->xleft, y, s->width, 1, 1087 fgcolor, 0); 1073 fill_rectangle(s->xleft, y, s->width, 1); 1088 1074 } 1089 SDL_UpdateRect(screen, s->xleft, s->ytop, s->width, s->height);1090 1075 } else { 1076 if (realloc_texture(&s->vis_texture, SDL_PIXELFORMAT_ARGB8888, s->width, s->height, SDL_BLENDMODE_NONE, 1) < 0) 1077 return; 1078 1091 1079 nb_display_channels= FFMIN(nb_display_channels, 2); 1092 1080 if (rdft_bits != s->rdft_bits) { 1093 1081 av_rdft_end(s->rdft); … … static void video_audio_display(VideoState *s) 1101 1089 s->show_mode = SHOW_MODE_WAVES; 1102 1090 } else { 1103 1091 FFTSample *data[2]; 1092 SDL_Rect rect = {.x = s->xpos, .y = 0, .w = 1, .h = s->height}; 1093 uint32_t *pixels; 1094 int pitch; 1104 1095 for (ch = 0; ch < nb_display_channels; ch++) { 1105 1096 data[ch] = s->rdft_data + 2 * nb_freq * ch; 1106 1097 i = i_start + ch; … … static void video_audio_display(VideoState *s) 1115 1106 } 1116 1107 /* Least efficient way to do this, we should of course 1117 1108 * directly access it but it is more than fast enough. */ 1118 for (y = 0; y < s->height; y++) { 1119 double w = 1 / sqrt(nb_freq); 1120 int a = sqrt(w * hypot(data[0][2 * y + 0], data[0][2 * y + 1])); 1121 int b = (nb_display_channels == 2 ) ? sqrt(w * hypot(data[1][2 * y + 0], data[1][2 * y + 1])) 1122 : a; 1123 a = FFMIN(a, 255); 1124 b = FFMIN(b, 255); 1125 fgcolor = SDL_MapRGB(screen->format, a, b, (a + b) / 2); 1126 1127 fill_rectangle(screen, 1128 s->xpos, s->height-y, 1, 1, 1129 fgcolor, 0); 1109 if (!SDL_LockTexture(s->vis_texture, &rect, (void **)&pixels, &pitch)) { 1110 pitch >>= 2; 1111 pixels += pitch * s->height; 1112 for (y = 0; y < s->height; y++) { 1113 double w = 1 / sqrt(nb_freq); 1114 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])); 1115 int b = (nb_display_channels == 2 ) ? sqrt(w * hypot(data[1][2 * y + 0], data[1][2 * y + 1])) 1116 : a; 1117 a = FFMIN(a, 255); 1118 b = FFMIN(b, 255); 1119 pixels -= pitch; 1120 *pixels = (a << 16) + (b << 8) + ((a+b) >> 1); 1121 } 1122 SDL_UnlockTexture(s->vis_texture); 1130 1123 } 1124 SDL_RenderCopy(renderer, s->vis_texture, NULL, NULL); 1131 1125 } 1132 SDL_UpdateRect(screen, s->xpos, s->ytop, 1, s->height);1133 1126 if (!s->paused) 1134 1127 s->xpos++; 1135 1128 if (s->xpos >= s->width) … … static void stream_close(VideoState *is) 1220 1213 frame_queue_destory(&is->sampq); 1221 1214 frame_queue_destory(&is->subpq); 1222 1215 SDL_DestroyCond(is->continue_read_thread); 1223 #if !CONFIG_AVFILTER1224 1216 sws_freeContext(is->img_convert_ctx); 1225 #endif1226 1217 sws_freeContext(is->sub_convert_ctx); 1227 1218 av_free(is->filename); 1219 if (is->vis_texture) 1220 SDL_DestroyTexture(is->vis_texture); 1221 if (is->sub_texture) 1222 SDL_DestroyTexture(is->sub_texture); 1228 1223 av_free(is); 1229 1224 } 1230 1225 … … static void do_exit(VideoState *is) 1233 1228 if (is) { 1234 1229 stream_close(is); 1235 1230 } 1231 if (renderer) 1232 SDL_DestroyRenderer(renderer); 1233 if (window) 1234 SDL_DestroyWindow(window); 1236 1235 av_lockmgr_register(NULL); 1237 1236 uninit_opts(); 1238 1237 #if CONFIG_AVFILTER … … static void set_default_window_size(int width, int height, AVRational sar) 1259 1258 default_height = rect.h; 1260 1259 } 1261 1260 1262 static int video_open(VideoState *is, int force_set_video_mode,Frame *vp)1261 static int video_open(VideoState *is, Frame *vp) 1263 1262 { 1264 int flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL;1265 1263 int w,h; 1266 1264 1267 if (is_full_screen) flags |= SDL_FULLSCREEN;1268 else flags |= SDL_RESIZABLE;1269 1270 1265 if (vp && vp->width) 1271 1266 set_default_window_size(vp->width, vp->height, vp->sar); 1272 1267 1273 if (is_full_screen && fs_screen_width) { 1274 w = fs_screen_width; 1275 h = fs_screen_height; 1276 } else if (!is_full_screen && screen_width) { 1268 if (screen_width) { 1277 1269 w = screen_width; 1278 1270 h = screen_height; 1279 1271 } else { 1280 1272 w = default_width; 1281 1273 h = default_height; 1282 1274 } 1283 w = FFMIN(16383, w); 1284 if (screen && is->width == screen->w && screen->w == w 1285 && is->height== screen->h && screen->h == h && !force_set_video_mode) 1286 return 0; 1287 screen = SDL_SetVideoMode(w, h, 0, flags); 1288 if (!screen) { 1275 1276 if (!window) { 1277 int flags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE; 1278 if (!window_title) 1279 window_title = input_filename; 1280 if (is_full_screen) 1281 flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; 1282 window = SDL_CreateWindow(window_title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w, h, flags); 1283 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); 1284 if (window) { 1285 SDL_RendererInfo info; 1286 renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); 1287 if (renderer) { 1288 if (!SDL_GetRendererInfo(renderer, &info)) 1289 av_log(NULL, AV_LOG_VERBOSE, "Initialized %s renderer.\n", info.name); 1290 } 1291 } 1292 } else { 1293 SDL_SetWindowSize(window, w, h); 1294 } 1295 1296 if (!window || !renderer) { 1289 1297 av_log(NULL, AV_LOG_FATAL, "SDL: could not set video mode - exiting\n"); 1290 1298 do_exit(is); 1291 1299 } 1292 if (!window_title)1293 window_title = input_filename;1294 SDL_WM_SetCaption(window_title, window_title);1295 1300 1296 is->width = screen->w;1297 is->height = screen->h;1301 is->width = w; 1302 is->height = h; 1298 1303 1299 1304 return 0; 1300 1305 } … … static int video_open(VideoState *is, int force_set_video_mode, Frame *vp) 1302 1307 /* display the current picture, if any */ 1303 1308 static void video_display(VideoState *is) 1304 1309 { 1305 if (!screen) 1306 video_open(is, 0, NULL); 1310 if (!window) 1311 video_open(is, NULL); 1312 1313 SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); 1314 SDL_RenderClear(renderer); 1307 1315 if (is->audio_st && is->show_mode != SHOW_MODE_VIDEO) 1308 1316 video_audio_display(is); 1309 1317 else if (is->video_st) 1310 1318 video_image_display(is); 1319 SDL_RenderPresent(renderer); 1311 1320 } 1312 1321 1313 1322 static double get_clock(Clock *c) … … retry: 1601 1610 || (is->vidclk.pts > (sp->pts + ((float) sp->sub.end_display_time / 1000))) 1602 1611 || (sp2 && is->vidclk.pts > (sp2->pts + ((float) sp2->sub.start_display_time / 1000)))) 1603 1612 { 1613 if (sp->uploaded) { 1614 int i; 1615 for (i = 0; i < sp->sub.num_rects; i++) { 1616 AVSubtitleRect *sub_rect = sp->sub.rects[i]; 1617 uint8_t *pixels; 1618 int pitch, j; 1619 1620 if (!SDL_LockTexture(is->sub_texture, (SDL_Rect *)sub_rect, (void **)&pixels, &pitch)) { 1621 for (j = 0; j < sub_rect->h; j++, pixels += pitch) 1622 memset(pixels, 0, sub_rect->w << 2); 1623 SDL_UnlockTexture(is->sub_texture); 1624 } 1625 } 1626 } 1604 1627 frame_queue_next(&is->subpq); 1605 1628 } else { 1606 1629 break; … … display: 1666 1689 static void alloc_picture(VideoState *is) 1667 1690 { 1668 1691 Frame *vp; 1669 int 64_t bufferdiff;1692 int sdl_format; 1670 1693 1671 1694 vp = &is->pictq.queue[is->pictq.windex]; 1672 1695 1673 free_picture(vp);1696 video_open(is, vp); 1674 1697 1675 video_open(is, 0, vp); 1698 if (vp->format == AV_PIX_FMT_YUV420P) 1699 sdl_format = SDL_PIXELFORMAT_YV12; 1700 else 1701 sdl_format = SDL_PIXELFORMAT_ARGB8888; 1676 1702 1677 vp->bmp = SDL_CreateYUVOverlay(vp->width, vp->height, 1678 SDL_YV12_OVERLAY, 1679 screen); 1680 bufferdiff = vp->bmp ? FFMAX(vp->bmp->pixels[0], vp->bmp->pixels[1]) - FFMIN(vp->bmp->pixels[0], vp->bmp->pixels[1]) : 0; 1681 if (!vp->bmp || vp->bmp->pitches[0] < vp->width || bufferdiff < (int64_t)vp->height * vp->bmp->pitches[0]) { 1703 if (realloc_texture(&vp->bmp, sdl_format, vp->width, vp->height, SDL_BLENDMODE_NONE, 0) < 0) { 1682 1704 /* SDL allocates a buffer smaller than requested if the video 1683 1705 * overlay hardware is unable to support the requested size. */ 1684 1706 av_log(NULL, AV_LOG_FATAL, … … static void alloc_picture(VideoState *is) 1694 1716 SDL_UnlockMutex(is->pictq.mutex); 1695 1717 } 1696 1718 1697 static void duplicate_right_border_pixels(SDL_Overlay *bmp) {1698 int i, width, height;1699 Uint8 *p, *maxp;1700 for (i = 0; i < 3; i++) {1701 width = bmp->w;1702 height = bmp->h;1703 if (i > 0) {1704 width >>= 1;1705 height >>= 1;1706 }1707 if (bmp->pitches[i] > width) {1708 maxp = bmp->pixels[i] + bmp->pitches[i] * height - 1;1709 for (p = bmp->pixels[i] + width - 1; p < maxp; p += bmp->pitches[i])1710 *(p+1) = *p;1711 }1712 }1713 }1714 1715 1719 static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, double duration, int64_t pos, int serial) 1716 1720 { 1717 1721 Frame *vp; … … static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, double 1725 1729 return -1; 1726 1730 1727 1731 vp->sar = src_frame->sample_aspect_ratio; 1732 vp->uploaded = 0; 1728 1733 1729 1734 /* alloc or resize hardware picture buffer */ 1730 if (!vp->bmp || vp->reallocate ||!vp->allocated ||1735 if (!vp->bmp || !vp->allocated || 1731 1736 vp->width != src_frame->width || 1732 vp->height != src_frame->height) { 1737 vp->height != src_frame->height || 1738 vp->format != src_frame->format) { 1733 1739 SDL_Event event; 1734 1740 1735 vp->allocated = 0; 1736 vp->reallocate = 0; 1741 vp->allocated = 0; 1737 1742 vp->width = src_frame->width; 1738 1743 vp->height = src_frame->height; 1744 vp->format = src_frame->format; 1739 1745 1740 1746 /* the allocation must be done in the main thread to avoid 1741 1747 locking problems. */ … … static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, double 1749 1755 SDL_CondWait(is->pictq.cond, is->pictq.mutex); 1750 1756 } 1751 1757 /* if the queue is aborted, we have to pop the pending ALLOC event or wait for the allocation to complete */ 1752 if (is->videoq.abort_request && SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_EVENTMASK(FF_ALLOC_EVENT)) != 1) {1758 if (is->videoq.abort_request && SDL_PeepEvents(&event, 1, SDL_GETEVENT, FF_ALLOC_EVENT, FF_ALLOC_EVENT) != 1) { 1753 1759 while (!vp->allocated && !is->abort_request) { 1754 1760 SDL_CondWait(is->pictq.cond, is->pictq.mutex); 1755 1761 } … … static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, double 1762 1768 1763 1769 /* if the frame is not skipped, then display it */ 1764 1770 if (vp->bmp) { 1765 uint8_t *data[4];1766 int linesize[4];1767 1768 /* get a pointer on the bitmap */1769 SDL_LockYUVOverlay (vp->bmp);1770 1771 data[0] = vp->bmp->pixels[0];1772 data[1] = vp->bmp->pixels[2];1773 data[2] = vp->bmp->pixels[1];1774 1775 linesize[0] = vp->bmp->pitches[0];1776 linesize[1] = vp->bmp->pitches[2];1777 linesize[2] = vp->bmp->pitches[1];1778 1779 #if CONFIG_AVFILTER1780 // FIXME use direct rendering1781 av_image_copy(data, linesize, (const uint8_t **)src_frame->data, src_frame->linesize,1782 src_frame->format, vp->width, vp->height);1783 #else1784 {1785 AVDictionaryEntry *e = av_dict_get(sws_dict, "sws_flags", NULL, 0);1786 if (e) {1787 const AVClass *class = sws_get_class();1788 const AVOption *o = av_opt_find(&class, "sws_flags", NULL, 0,1789 AV_OPT_SEARCH_FAKE_OBJ);1790 int ret = av_opt_eval_flags(&class, o, e->value, &sws_flags);1791 if (ret < 0)1792 exit(1);1793 }1794 }1795 1796 is->img_convert_ctx = sws_getCachedContext(is->img_convert_ctx,1797 vp->width, vp->height, src_frame->format, vp->width, vp->height,1798 AV_PIX_FMT_YUV420P, sws_flags, NULL, NULL, NULL);1799 if (!is->img_convert_ctx) {1800 av_log(NULL, AV_LOG_FATAL, "Cannot initialize the conversion context\n");1801 exit(1);1802 }1803 sws_scale(is->img_convert_ctx, src_frame->data, src_frame->linesize,1804 0, vp->height, data, linesize);1805 #endif1806 /* workaround SDL PITCH_WORKAROUND */1807 duplicate_right_border_pixels(vp->bmp);1808 /* update the bitmap content */1809 SDL_UnlockYUVOverlay(vp->bmp);1810 1811 1771 vp->pts = pts; 1812 1772 vp->duration = duration; 1813 1773 vp->pos = pos; 1814 1774 vp->serial = serial; 1815 1775 1816 /* now we can update the picture count */1776 av_frame_move_ref(vp->frame, src_frame); 1817 1777 frame_queue_push(&is->pictq); 1818 1778 } 1819 1779 return 0; … … fail: 1901 1861 1902 1862 static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const char *vfilters, AVFrame *frame) 1903 1863 { 1904 static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_ NONE };1864 static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_BGRA, AV_PIX_FMT_NONE }; 1905 1865 char sws_flags_str[512] = ""; 1906 1866 char buffersrc_args[256]; 1907 1867 int ret; … … static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c 1964 1924 last_filter = filt_ctx; \ 1965 1925 } while (0) 1966 1926 1967 /* SDL YUV code is not handling odd width/height for some driver1968 * combinations, therefore we crop the picture to an even width/height. */1969 INSERT_FILT("crop", "floor(in_w/2)*2:floor(in_h/2)*2");1970 1971 1927 if (autorotate) { 1972 1928 double theta = get_rotation(is->video_st); 1973 1929 … … static int audio_thread(void *arg) 2162 2118 static int decoder_start(Decoder *d, int (*fn)(void *), void *arg) 2163 2119 { 2164 2120 packet_queue_start(d->queue); 2165 d->decoder_tid = SDL_CreateThread(fn, arg);2121 d->decoder_tid = SDL_CreateThread(fn, "decoder", arg); 2166 2122 if (!d->decoder_tid) { 2167 2123 av_log(NULL, AV_LOG_ERROR, "SDL_CreateThread(): %s\n", SDL_GetError()); 2168 2124 return AVERROR(ENOMEM); … … static int video_thread(void *arg) 2282 2238 static int subtitle_thread(void *arg) 2283 2239 { 2284 2240 VideoState *is = arg; 2241 AVCodecContext *dec = is->subtitle_st->codec; 2285 2242 Frame *sp; 2286 2243 int got_subtitle; 2287 2244 double pts; 2288 int i;2289 2245 2290 2246 for (;;) { 2291 2247 if (!(sp = frame_queue_peek_writable(&is->subpq))) … … static int subtitle_thread(void *arg) 2301 2257 pts = sp->sub.pts / (double)AV_TIME_BASE; 2302 2258 sp->pts = pts; 2303 2259 sp->serial = is->subdec.pkt_serial; 2304 if (!(sp->subrects = av_mallocz_array(sp->sub.num_rects, sizeof(AVSubtitleRect*)))) { 2305 av_log(NULL, AV_LOG_FATAL, "Cannot allocate subrects\n"); 2306 exit(1); 2307 } 2308 2309 for (i = 0; i < sp->sub.num_rects; i++) 2310 { 2311 int in_w = sp->sub.rects[i]->w; 2312 int in_h = sp->sub.rects[i]->h; 2313 int subw = is->subdec.avctx->width ? is->subdec.avctx->width : is->viddec_width; 2314 int subh = is->subdec.avctx->height ? is->subdec.avctx->height : is->viddec_height; 2315 int out_w = is->viddec_width ? in_w * is->viddec_width / subw : in_w; 2316 int out_h = is->viddec_height ? in_h * is->viddec_height / subh : in_h; 2317 2318 if (!(sp->subrects[i] = av_mallocz(sizeof(AVSubtitleRect))) || 2319 av_image_alloc(sp->subrects[i]->data, sp->subrects[i]->linesize, out_w, out_h, AV_PIX_FMT_YUVA420P, 16) < 0) { 2320 av_log(NULL, AV_LOG_FATAL, "Cannot allocate subtitle data\n"); 2321 exit(1); 2322 } 2323 2324 is->sub_convert_ctx = sws_getCachedContext(is->sub_convert_ctx, 2325 in_w, in_h, AV_PIX_FMT_PAL8, out_w, out_h, 2326 AV_PIX_FMT_YUVA420P, sws_flags, NULL, NULL, NULL); 2327 if (!is->sub_convert_ctx) { 2328 av_log(NULL, AV_LOG_FATAL, "Cannot initialize the sub conversion context\n"); 2329 exit(1); 2330 } 2331 sws_scale(is->sub_convert_ctx, 2332 (void*)sp->sub.rects[i]->data, sp->sub.rects[i]->linesize, 2333 0, in_h, sp->subrects[i]->data, sp->subrects[i]->linesize); 2334 2335 sp->subrects[i]->w = out_w; 2336 sp->subrects[i]->h = out_h; 2337 sp->subrects[i]->x = sp->sub.rects[i]->x * out_w / in_w; 2338 sp->subrects[i]->y = sp->sub.rects[i]->y * out_h / in_h; 2339 } 2260 sp->width = dec->width; 2261 sp->height = dec->height; 2262 sp->uploaded = 0; 2340 2263 2341 2264 /* now we can update the picture count */ 2342 2265 frame_queue_push(&is->subpq); … … static VideoState *stream_open(const char *filename, AVInputFormat *iformat) 3181 3104 is->audio_volume = SDL_MIX_MAXVOLUME; 3182 3105 is->muted = 0; 3183 3106 is->av_sync_type = av_sync_type; 3184 is->read_tid = SDL_CreateThread(read_thread, is);3107 is->read_tid = SDL_CreateThread(read_thread, "read_thread", is); 3185 3108 if (!is->read_tid) { 3186 3109 av_log(NULL, AV_LOG_FATAL, "SDL_CreateThread(): %s\n", SDL_GetError()); 3187 3110 fail: … … static void stream_cycle_channel(VideoState *is, int codec_type) 3272 3195 3273 3196 static void toggle_full_screen(VideoState *is) 3274 3197 { 3275 #if defined(__APPLE__) && SDL_VERSION_ATLEAST(1, 2, 14)3276 /* OS X needs to reallocate the SDL overlays */3277 int i;3278 for (i = 0; i < VIDEO_PICTURE_QUEUE_SIZE; i++)3279 is->pictq.queue[i].reallocate = 1;3280 #endif3281 3198 is_full_screen = !is_full_screen; 3282 video_open(is, 1, NULL);3199 SDL_SetWindowFullscreen(window, is_full_screen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); 3283 3200 } 3284 3201 3285 3202 static void toggle_audio_display(VideoState *is) 3286 3203 { 3287 int bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);3288 3204 int next = is->show_mode; 3289 3205 do { 3290 3206 next = (next + 1) % SHOW_MODE_NB; 3291 3207 } while (next != is->show_mode && (next == SHOW_MODE_VIDEO && !is->video_st || next != SHOW_MODE_VIDEO && !is->audio_st)); 3292 3208 if (is->show_mode != next) { 3293 fill_rectangle(screen,3294 is->xleft, is->ytop, is->width, is->height,3295 bgcolor, 1);3296 3209 is->force_refresh = 1; 3297 3210 is->show_mode = next; 3298 3211 } … … static void toggle_audio_display(VideoState *is) 3301 3214 static void refresh_loop_wait_event(VideoState *is, SDL_Event *event) { 3302 3215 double remaining_time = 0.0; 3303 3216 SDL_PumpEvents(); 3304 while (!SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_ ALLEVENTS)) {3217 while (!SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)) { 3305 3218 if (!cursor_hidden && av_gettime_relative() - cursor_last_shown > CURSOR_HIDE_DELAY) { 3306 3219 SDL_ShowCursor(0); 3307 3220 cursor_hidden = 1; … … static void event_loop(VideoState *cur_stream) 3465 3378 break; 3466 3379 } 3467 3380 break; 3468 case SDL_VIDEOEXPOSE:3469 cur_stream->force_refresh = 1;3470 break;3471 3381 case SDL_MOUSEBUTTONDOWN: 3472 3382 if (exit_on_mousedown) { 3473 3383 do_exit(cur_stream); … … static void event_loop(VideoState *cur_stream) 3523 3433 stream_seek(cur_stream, ts, 0, 0); 3524 3434 } 3525 3435 break; 3526 case SDL_VIDEORESIZE: 3527 screen = SDL_SetVideoMode(FFMIN(16383, event.resize.w), event.resize.h, 0, 3528 SDL_HWSURFACE|(is_full_screen?SDL_FULLSCREEN:SDL_RESIZABLE)|SDL_ASYNCBLIT|SDL_HWACCEL); 3529 if (!screen) { 3530 av_log(NULL, AV_LOG_FATAL, "Failed to set video mode\n"); 3531 do_exit(cur_stream); 3532 } 3533 screen_width = cur_stream->width = screen->w; 3534 screen_height = cur_stream->height = screen->h; 3535 cur_stream->force_refresh = 1; 3436 case SDL_WINDOWEVENT: 3437 switch (event.window.event) { 3438 case SDL_WINDOWEVENT_RESIZED: 3439 screen_width = cur_stream->width = event.window.data1; 3440 screen_height = cur_stream->height = event.window.data2; 3441 if (cur_stream->vis_texture) { 3442 SDL_DestroyTexture(cur_stream->vis_texture); 3443 cur_stream->vis_texture = NULL; 3444 } 3445 case SDL_WINDOWEVENT_EXPOSED: 3446 cur_stream->force_refresh = 1; 3447 } 3536 3448 break; 3537 3449 case SDL_QUIT: 3538 3450 case FF_QUIT_EVENT: … … int main(int argc, char **argv) 3769 3681 { 3770 3682 int flags; 3771 3683 VideoState *is; 3772 char dummy_videodriver[] = "SDL_VIDEODRIVER=dummy";3773 3684 3774 3685 av_log_set_flags(AV_LOG_SKIP_REPEATED); 3775 3686 parse_loglevel(argc, argv, options); … … int main(int argc, char **argv) 3808 3719 if (audio_disable) 3809 3720 flags &= ~SDL_INIT_AUDIO; 3810 3721 if (display_disable) 3811 SDL_putenv(dummy_videodriver); /* For the event queue, we always need a video driver. */ 3812 #if !defined(_WIN32) && !defined(__APPLE__) 3813 flags |= SDL_INIT_EVENTTHREAD; /* Not supported on Windows or Mac OS X */ 3814 #endif 3722 flags &= ~SDL_INIT_VIDEO; 3815 3723 if (SDL_Init (flags)) { 3816 3724 av_log(NULL, AV_LOG_FATAL, "Could not initialize SDL - %s\n", SDL_GetError()); 3817 3725 av_log(NULL, AV_LOG_FATAL, "(Did you set the DISPLAY variable?)\n"); 3818 3726 exit(1); 3819 3727 } 3820 3728 3821 if (!display_disable) {3822 const SDL_VideoInfo *vi = SDL_GetVideoInfo();3823 fs_screen_width = vi->current_w;3824 fs_screen_height = vi->current_h;3825 }3826 3827 SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);3828 3729 SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE); 3829 3730 SDL_EventState(SDL_USEREVENT, SDL_IGNORE); 3830 3731 3831 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);3832 3833 3732 if (av_lockmgr_register(lockmgr)) { 3834 3733 av_log(NULL, AV_LOG_FATAL, "Could not initialize lock manager!\n"); 3835 3734 do_exit(NULL);
