|
|
|
@ -362,6 +362,32 @@ static AVPacket flush_pkt; |
|
|
|
|
static SDL_Window *window; |
|
|
|
|
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 |
|
|
|
|
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); |
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
@ -855,31 +882,33 @@ static void calculate_display_rect(SDL_Rect *rect, |
|
|
|
|
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; |
|
|
|
|
switch (frame->format) { |
|
|
|
|
case AV_PIX_FMT_YUV420P: |
|
|
|
|
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; |
|
|
|
|
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: |
|
|
|
|
Uint32 sdl_pix_fmt; |
|
|
|
|
SDL_BlendMode sdl_blendmode; |
|
|
|
|
get_sdl_pix_fmt_and_blendmode(frame->format, &sdl_pix_fmt, &sdl_blendmode); |
|
|
|
|
if (realloc_texture(tex, sdl_pix_fmt == SDL_PIXELFORMAT_UNKNOWN ? SDL_PIXELFORMAT_ARGB8888 : sdl_pix_fmt, frame->width, frame->height, sdl_blendmode, 0) < 0) |
|
|
|
|
return -1; |
|
|
|
|
switch (sdl_pix_fmt) { |
|
|
|
|
case SDL_PIXELFORMAT_UNKNOWN: |
|
|
|
|
/* This should only happen if we are not using avfilter... */ |
|
|
|
|
*img_convert_ctx = sws_getCachedContext(*img_convert_ctx, |
|
|
|
|
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) { |
|
|
|
|
uint8_t *pixels[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, |
|
|
|
|
0, frame->height, pixels, pitch); |
|
|
|
|
SDL_UnlockTexture(tex); |
|
|
|
|
SDL_UnlockTexture(*tex); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
av_log(NULL, AV_LOG_FATAL, "Cannot initialize the conversion context\n"); |
|
|
|
|
ret = -1; |
|
|
|
|
} |
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
@ -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); |
|
|
|
|
|
|
|
|
|
if (!vp->uploaded) { |
|
|
|
|
int sdl_pix_fmt = vp->frame->format == AV_PIX_FMT_YUV420P ? SDL_PIXELFORMAT_YV12 : SDL_PIXELFORMAT_ARGB8888; |
|
|
|
|
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) |
|
|
|
|
if (upload_texture(&is->vid_texture, vp->frame, &is->img_convert_ctx) < 0) |
|
|
|
|
return; |
|
|
|
|
vp->uploaded = 1; |
|
|
|
|
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 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 buffersrc_args[256]; |
|
|
|
|
int ret; |
|
|
|
@ -1804,6 +1850,10 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c |
|
|
|
|
AVCodecParameters *codecpar = is->video_st->codecpar; |
|
|
|
|
AVRational fr = av_guess_frame_rate(is->ic, is->video_st, 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))) { |
|
|
|
|
if (!strcmp(e->key, "sws_flags")) { |
|
|
|
|