ffplay: add support for more SDL pixel formats when rendering video
Signed-off-by: Marton Balint <cus@passwd.hu>
This commit is contained in:
		
							parent
							
								
									7004ac5eeb
								
							
						
					
					
						commit
						3bd2228d05
					
				
							
								
								
									
										112
									
								
								ffplay.c
									
									
									
									
									
								
							
							
						
						
									
										112
									
								
								ffplay.c
									
									
									
									
									
								
							| @ -362,6 +362,32 @@ static AVPacket flush_pkt; | |||||||
| static SDL_Window *window; | static SDL_Window *window; | ||||||
| static SDL_Renderer *renderer; | static SDL_Renderer *renderer; | ||||||
| 
 | 
 | ||||||
|  | static const struct TextureFormatEntry { | ||||||
|  |     enum AVPixelFormat format; | ||||||
|  |     int texture_fmt; | ||||||
|  | } sdl_texture_format_map[] = { | ||||||
|  |     { AV_PIX_FMT_RGB8,           SDL_PIXELFORMAT_RGB332 }, | ||||||
|  |     { AV_PIX_FMT_RGB444,         SDL_PIXELFORMAT_RGB444 }, | ||||||
|  |     { AV_PIX_FMT_RGB555,         SDL_PIXELFORMAT_RGB555 }, | ||||||
|  |     { AV_PIX_FMT_BGR555,         SDL_PIXELFORMAT_BGR555 }, | ||||||
|  |     { AV_PIX_FMT_RGB565,         SDL_PIXELFORMAT_RGB565 }, | ||||||
|  |     { AV_PIX_FMT_BGR565,         SDL_PIXELFORMAT_BGR565 }, | ||||||
|  |     { AV_PIX_FMT_RGB24,          SDL_PIXELFORMAT_RGB24 }, | ||||||
|  |     { AV_PIX_FMT_BGR24,          SDL_PIXELFORMAT_BGR24 }, | ||||||
|  |     { AV_PIX_FMT_0RGB32,         SDL_PIXELFORMAT_RGB888 }, | ||||||
|  |     { AV_PIX_FMT_0BGR32,         SDL_PIXELFORMAT_BGR888 }, | ||||||
|  |     { AV_PIX_FMT_NE(RGB0, 0BGR), SDL_PIXELFORMAT_RGBX8888 }, | ||||||
|  |     { AV_PIX_FMT_NE(BGR0, 0RGB), SDL_PIXELFORMAT_BGRX8888 }, | ||||||
|  |     { AV_PIX_FMT_RGB32,          SDL_PIXELFORMAT_ARGB8888 }, | ||||||
|  |     { AV_PIX_FMT_RGB32_1,        SDL_PIXELFORMAT_RGBA8888 }, | ||||||
|  |     { AV_PIX_FMT_BGR32,          SDL_PIXELFORMAT_ABGR8888 }, | ||||||
|  |     { AV_PIX_FMT_BGR32_1,        SDL_PIXELFORMAT_BGRA8888 }, | ||||||
|  |     { AV_PIX_FMT_YUV420P,        SDL_PIXELFORMAT_IYUV }, | ||||||
|  |     { AV_PIX_FMT_YUYV422,        SDL_PIXELFORMAT_YUY2 }, | ||||||
|  |     { AV_PIX_FMT_UYVY422,        SDL_PIXELFORMAT_UYVY }, | ||||||
|  |     { AV_PIX_FMT_NONE,           SDL_PIXELFORMAT_UNKNOWN }, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| #if CONFIG_AVFILTER | #if CONFIG_AVFILTER | ||||||
| static int opt_add_vfilter(void *optctx, const char *opt, const char *arg) | static int opt_add_vfilter(void *optctx, const char *opt, const char *arg) | ||||||
| { | { | ||||||
| @ -820,6 +846,7 @@ static int realloc_texture(SDL_Texture **texture, Uint32 new_format, int new_wid | |||||||
|             memset(pixels, 0, pitch * new_height); |             memset(pixels, 0, pitch * new_height); | ||||||
|             SDL_UnlockTexture(*texture); |             SDL_UnlockTexture(*texture); | ||||||
|         } |         } | ||||||
|  |         av_log(NULL, AV_LOG_VERBOSE, "Created %dx%d texture with %s.\n", new_width, new_height, SDL_GetPixelFormatName(new_format)); | ||||||
|     } |     } | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| @ -855,31 +882,33 @@ static void calculate_display_rect(SDL_Rect *rect, | |||||||
|     rect->h = FFMAX(height, 1); |     rect->h = FFMAX(height, 1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int upload_texture(SDL_Texture *tex, AVFrame *frame, struct SwsContext **img_convert_ctx) { | static void get_sdl_pix_fmt_and_blendmode(int format, Uint32 *sdl_pix_fmt, SDL_BlendMode *sdl_blendmode) | ||||||
|  | { | ||||||
|  |     int i; | ||||||
|  |     *sdl_blendmode = SDL_BLENDMODE_NONE; | ||||||
|  |     *sdl_pix_fmt = SDL_PIXELFORMAT_UNKNOWN; | ||||||
|  |     if (format == AV_PIX_FMT_RGB32   || | ||||||
|  |         format == AV_PIX_FMT_RGB32_1 || | ||||||
|  |         format == AV_PIX_FMT_BGR32   || | ||||||
|  |         format == AV_PIX_FMT_BGR32_1) | ||||||
|  |         *sdl_blendmode = SDL_BLENDMODE_BLEND; | ||||||
|  |     for (i = 0; i < FF_ARRAY_ELEMS(sdl_texture_format_map) - 1; i++) { | ||||||
|  |         if (format == sdl_texture_format_map[i].format) { | ||||||
|  |             *sdl_pix_fmt = sdl_texture_format_map[i].texture_fmt; | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int upload_texture(SDL_Texture **tex, AVFrame *frame, struct SwsContext **img_convert_ctx) { | ||||||
|     int ret = 0; |     int ret = 0; | ||||||
|     switch (frame->format) { |     Uint32 sdl_pix_fmt; | ||||||
|         case AV_PIX_FMT_YUV420P: |     SDL_BlendMode sdl_blendmode; | ||||||
|             if (frame->linesize[0] > 0 && frame->linesize[1] > 0 && frame->linesize[2] > 0) { |     get_sdl_pix_fmt_and_blendmode(frame->format, &sdl_pix_fmt, &sdl_blendmode); | ||||||
|                 ret = SDL_UpdateYUVTexture(tex, NULL, frame->data[0], frame->linesize[0], |     if (realloc_texture(tex, sdl_pix_fmt == SDL_PIXELFORMAT_UNKNOWN ? SDL_PIXELFORMAT_ARGB8888 : sdl_pix_fmt, frame->width, frame->height, sdl_blendmode, 0) < 0) | ||||||
|                                                       frame->data[1], frame->linesize[1], |  | ||||||
|                                                       frame->data[2], frame->linesize[2]); |  | ||||||
|             } else if (frame->linesize[0] < 0 && frame->linesize[1] < 0 && frame->linesize[2] < 0) { |  | ||||||
|                 ret = SDL_UpdateYUVTexture(tex, NULL, frame->data[0] + frame->linesize[0] * (frame->height                    - 1), -frame->linesize[0], |  | ||||||
|                                                       frame->data[1] + frame->linesize[1] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[1], |  | ||||||
|                                                       frame->data[2] + frame->linesize[2] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[2]); |  | ||||||
|             } else { |  | ||||||
|                 av_log(NULL, AV_LOG_ERROR, "Mixed negative and positive linesizes are not supported.\n"); |  | ||||||
|         return -1; |         return -1; | ||||||
|             } |     switch (sdl_pix_fmt) { | ||||||
|             break; |         case SDL_PIXELFORMAT_UNKNOWN: | ||||||
|         case AV_PIX_FMT_BGRA: |  | ||||||
|             if (frame->linesize[0] < 0) { |  | ||||||
|                 ret = SDL_UpdateTexture(tex, NULL, frame->data[0] + frame->linesize[0] * (frame->height - 1), -frame->linesize[0]); |  | ||||||
|             } else { |  | ||||||
|                 ret = SDL_UpdateTexture(tex, NULL, frame->data[0], frame->linesize[0]); |  | ||||||
|             } |  | ||||||
|             break; |  | ||||||
|         default: |  | ||||||
|             /* This should only happen if we are not using avfilter... */ |             /* This should only happen if we are not using avfilter... */ | ||||||
|             *img_convert_ctx = sws_getCachedContext(*img_convert_ctx, |             *img_convert_ctx = sws_getCachedContext(*img_convert_ctx, | ||||||
|                 frame->width, frame->height, frame->format, frame->width, frame->height, |                 frame->width, frame->height, frame->format, frame->width, frame->height, | ||||||
| @ -887,16 +916,37 @@ static int upload_texture(SDL_Texture *tex, AVFrame *frame, struct SwsContext ** | |||||||
|             if (*img_convert_ctx != NULL) { |             if (*img_convert_ctx != NULL) { | ||||||
|                 uint8_t *pixels[4]; |                 uint8_t *pixels[4]; | ||||||
|                 int pitch[4]; |                 int pitch[4]; | ||||||
|                 if (!SDL_LockTexture(tex, NULL, (void **)pixels, pitch)) { |                 if (!SDL_LockTexture(*tex, NULL, (void **)pixels, pitch)) { | ||||||
|                     sws_scale(*img_convert_ctx, (const uint8_t * const *)frame->data, frame->linesize, |                     sws_scale(*img_convert_ctx, (const uint8_t * const *)frame->data, frame->linesize, | ||||||
|                               0, frame->height, pixels, pitch); |                               0, frame->height, pixels, pitch); | ||||||
|                     SDL_UnlockTexture(tex); |                     SDL_UnlockTexture(*tex); | ||||||
|                 } |                 } | ||||||
|             } else { |             } else { | ||||||
|                 av_log(NULL, AV_LOG_FATAL, "Cannot initialize the conversion context\n"); |                 av_log(NULL, AV_LOG_FATAL, "Cannot initialize the conversion context\n"); | ||||||
|                 ret = -1; |                 ret = -1; | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|  |         case SDL_PIXELFORMAT_IYUV: | ||||||
|  |             if (frame->linesize[0] > 0 && frame->linesize[1] > 0 && frame->linesize[2] > 0) { | ||||||
|  |                 ret = SDL_UpdateYUVTexture(*tex, NULL, frame->data[0], frame->linesize[0], | ||||||
|  |                                                        frame->data[1], frame->linesize[1], | ||||||
|  |                                                        frame->data[2], frame->linesize[2]); | ||||||
|  |             } else if (frame->linesize[0] < 0 && frame->linesize[1] < 0 && frame->linesize[2] < 0) { | ||||||
|  |                 ret = SDL_UpdateYUVTexture(*tex, NULL, frame->data[0] + frame->linesize[0] * (frame->height                    - 1), -frame->linesize[0], | ||||||
|  |                                                        frame->data[1] + frame->linesize[1] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[1], | ||||||
|  |                                                        frame->data[2] + frame->linesize[2] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[2]); | ||||||
|  |             } else { | ||||||
|  |                 av_log(NULL, AV_LOG_ERROR, "Mixed negative and positive linesizes are not supported.\n"); | ||||||
|  |                 return -1; | ||||||
|  |             } | ||||||
|  |             break; | ||||||
|  |         default: | ||||||
|  |             if (frame->linesize[0] < 0) { | ||||||
|  |                 ret = SDL_UpdateTexture(*tex, NULL, frame->data[0] + frame->linesize[0] * (frame->height - 1), -frame->linesize[0]); | ||||||
|  |             } else { | ||||||
|  |                 ret = SDL_UpdateTexture(*tex, NULL, frame->data[0], frame->linesize[0]); | ||||||
|  |             } | ||||||
|  |             break; | ||||||
|     } |     } | ||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
| @ -956,11 +1006,7 @@ static void video_image_display(VideoState *is) | |||||||
|     calculate_display_rect(&rect, is->xleft, is->ytop, is->width, is->height, vp->width, vp->height, vp->sar); |     calculate_display_rect(&rect, is->xleft, is->ytop, is->width, is->height, vp->width, vp->height, vp->sar); | ||||||
| 
 | 
 | ||||||
|     if (!vp->uploaded) { |     if (!vp->uploaded) { | ||||||
|         int sdl_pix_fmt = vp->frame->format == AV_PIX_FMT_YUV420P ? SDL_PIXELFORMAT_YV12 : SDL_PIXELFORMAT_ARGB8888; |         if (upload_texture(&is->vid_texture, vp->frame, &is->img_convert_ctx) < 0) | ||||||
|         SDL_BlendMode sdl_blendmode = vp->frame->format == AV_PIX_FMT_YUV420P ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND; |  | ||||||
|         if (realloc_texture(&is->vid_texture, sdl_pix_fmt, vp->frame->width, vp->frame->height, sdl_blendmode, 0) < 0) |  | ||||||
|             return; |  | ||||||
|         if (upload_texture(is->vid_texture, vp->frame, &is->img_convert_ctx) < 0) |  | ||||||
|             return; |             return; | ||||||
|         vp->uploaded = 1; |         vp->uploaded = 1; | ||||||
|         vp->flip_v = vp->frame->linesize[0] < 0; |         vp->flip_v = vp->frame->linesize[0] < 0; | ||||||
| @ -1796,7 +1842,7 @@ fail: | |||||||
| 
 | 
 | ||||||
| static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const char *vfilters, AVFrame *frame) | static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const char *vfilters, AVFrame *frame) | ||||||
| { | { | ||||||
|     static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_BGRA, AV_PIX_FMT_NONE }; |     enum AVPixelFormat pix_fmts[FF_ARRAY_ELEMS(sdl_texture_format_map)]; | ||||||
|     char sws_flags_str[512] = ""; |     char sws_flags_str[512] = ""; | ||||||
|     char buffersrc_args[256]; |     char buffersrc_args[256]; | ||||||
|     int ret; |     int ret; | ||||||
| @ -1804,6 +1850,10 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c | |||||||
|     AVCodecParameters *codecpar = is->video_st->codecpar; |     AVCodecParameters *codecpar = is->video_st->codecpar; | ||||||
|     AVRational fr = av_guess_frame_rate(is->ic, is->video_st, NULL); |     AVRational fr = av_guess_frame_rate(is->ic, is->video_st, NULL); | ||||||
|     AVDictionaryEntry *e = NULL; |     AVDictionaryEntry *e = NULL; | ||||||
|  |     int i; | ||||||
|  | 
 | ||||||
|  |     for (i = 0; i < FF_ARRAY_ELEMS(pix_fmts); i++) | ||||||
|  |         pix_fmts[i] = sdl_texture_format_map[i].format; | ||||||
| 
 | 
 | ||||||
|     while ((e = av_dict_get(sws_dict, "", e, AV_DICT_IGNORE_SUFFIX))) { |     while ((e = av_dict_get(sws_dict, "", e, AV_DICT_IGNORE_SUFFIX))) { | ||||||
|         if (!strcmp(e->key, "sws_flags")) { |         if (!strcmp(e->key, "sws_flags")) { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user