X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavdevice%2Fsdl.c;h=0dd2df92f0ce55d59ba5fd359733ac4b5c9d25b0;hb=7681d0eaca39eacea4cb573c737f6c5f0190307c;hp=5226e0cd0e13180ed8792f318d638ebfbbaa9280;hpb=015903294ca983f007ab5cae098a54013e77f2f6;p=ffmpeg diff --git a/libavdevice/sdl.c b/libavdevice/sdl.c index 5226e0cd0e1..0dd2df92f0c 100644 --- a/libavdevice/sdl.c +++ b/libavdevice/sdl.c @@ -36,9 +36,9 @@ typedef struct { SDL_Overlay *overlay; char *window_title; char *icon_title; - char *window_size; - int window_width, window_height; - int overlay_width, overlay_height; + int window_width, window_height; /**< size of the window */ + int overlay_width, overlay_height; /**< size of the video in the window */ + int overlay_x, overlay_y; int overlay_fmt; int sdl_was_already_inited; } SDLContext; @@ -58,7 +58,6 @@ static int sdl_write_trailer(AVFormatContext *s) av_freep(&sdl->window_title); av_freep(&sdl->icon_title); - av_freep(&sdl->window_size); if (sdl->overlay) { SDL_FreeYUVOverlay(sdl->overlay); @@ -75,7 +74,7 @@ static int sdl_write_header(AVFormatContext *s) SDLContext *sdl = s->priv_data; AVStream *st = s->streams[0]; AVCodecContext *encctx = st->codec; - float sar, dar; /* sample and display aspect ratios */ + AVRational sar, dar; /* sample and display aspect ratios */ int i, ret; if (!sdl->window_title) @@ -120,31 +119,35 @@ static int sdl_write_header(AVFormatContext *s) goto fail; } - if (sdl->window_size) { - if (av_parse_video_size(&sdl->window_width, &sdl->window_height, - sdl->window_size) < 0) { - av_log(s, AV_LOG_ERROR, "Invalid window size '%s'\n", sdl->window_size); - ret = AVERROR(EINVAL); - goto fail; - } - } - /* compute overlay width and height from the codec context information */ - sar = st->sample_aspect_ratio.num ? av_q2d(st->sample_aspect_ratio) : 1; - dar = sar * (float)encctx->width / (float)encctx->height; + sar = st->sample_aspect_ratio.num ? st->sample_aspect_ratio : (AVRational){ 1, 1 }; + dar = av_mul_q(sar, (AVRational){ encctx->width, encctx->height }); /* we suppose the screen has a 1/1 sample aspect ratio */ - sdl->overlay_height = encctx->height; - sdl->overlay_width = ((int)rint(sdl->overlay_height * dar)); - if (sdl->overlay_width > encctx->width) { - sdl->overlay_width = encctx->width; - sdl->overlay_height = ((int)rint(sdl->overlay_width / dar)); - } - - if (!sdl->window_width || !sdl->window_height) { + if (sdl->window_width && sdl->window_height) { + /* fit in the window */ + if (av_cmp_q(dar, (AVRational){ sdl->window_width, sdl->window_height }) > 0) { + /* fit in width */ + sdl->overlay_width = sdl->window_width; + sdl->overlay_height = av_rescale(sdl->overlay_width, dar.den, dar.num); + } else { + /* fit in height */ + sdl->overlay_height = sdl->window_height; + sdl->overlay_width = av_rescale(sdl->overlay_height, dar.num, dar.den); + } + } else { + if (sar.num > sar.den) { + sdl->overlay_width = encctx->width; + sdl->overlay_height = av_rescale(sdl->overlay_width, dar.den, dar.num); + } else { + sdl->overlay_height = encctx->height; + sdl->overlay_width = av_rescale(sdl->overlay_height, dar.num, dar.den); + } sdl->window_width = sdl->overlay_width; sdl->window_height = sdl->overlay_height; } + sdl->overlay_x = (sdl->window_width - sdl->overlay_width ) / 2; + sdl->overlay_y = (sdl->window_height - sdl->overlay_height) / 2; SDL_WM_SetCaption(sdl->window_title, sdl->icon_title); sdl->surface = SDL_SetVideoMode(sdl->window_width, sdl->window_height, @@ -155,19 +158,19 @@ static int sdl_write_header(AVFormatContext *s) goto fail; } - sdl->overlay = SDL_CreateYUVOverlay(sdl->overlay_width, sdl->overlay_height, + sdl->overlay = SDL_CreateYUVOverlay(encctx->width, encctx->height, sdl->overlay_fmt, sdl->surface); - if (!sdl->overlay || sdl->overlay->pitches[0] < sdl->overlay_width) { + if (!sdl->overlay || sdl->overlay->pitches[0] < encctx->width) { av_log(s, AV_LOG_ERROR, "SDL does not support an overlay with size of %dx%d pixels.\n", - sdl->overlay_width, sdl->overlay_height); + encctx->width, encctx->height); ret = AVERROR(EINVAL); goto fail; } - av_log(s, AV_LOG_INFO, "w:%d h:%d fmt:%s sar:%f -> w:%d h:%d\n", - encctx->width, encctx->height, av_get_pix_fmt_name(encctx->pix_fmt), sar, - sdl->window_width, sdl->window_height); + av_log(s, AV_LOG_INFO, "w:%d h:%d fmt:%s sar:%d/%d -> w:%d h:%d\n", + encctx->width, encctx->height, av_get_pix_fmt_name(encctx->pix_fmt), sar.num, sar.den, + sdl->overlay_width, sdl->overlay_height); return 0; fail: @@ -179,7 +182,7 @@ static int sdl_write_packet(AVFormatContext *s, AVPacket *pkt) { SDLContext *sdl = s->priv_data; AVCodecContext *encctx = s->streams[0]->codec; - SDL_Rect rect = { 0, 0, sdl->window_width, sdl->window_height }; + SDL_Rect rect = { sdl->overlay_x, sdl->overlay_y, sdl->overlay_width, sdl->overlay_height }; AVPicture pict; int i; @@ -195,7 +198,7 @@ static int sdl_write_packet(AVFormatContext *s, AVPacket *pkt) SDL_DisplayYUVOverlay(sdl->overlay, &rect); SDL_UnlockYUVOverlay(sdl->overlay); - SDL_UpdateRect(sdl->surface, 0, 0, sdl->overlay_width, sdl->overlay_height); + SDL_UpdateRect(sdl->surface, rect.x, rect.y, rect.w, rect.h); return 0; } @@ -205,7 +208,7 @@ static int sdl_write_packet(AVFormatContext *s, AVPacket *pkt) static const AVOption options[] = { { "window_title", "SDL window title", OFFSET(window_title), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, AV_OPT_FLAG_ENCODING_PARAM }, { "icon_title", "SDL iconified window title", OFFSET(icon_title) , AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, AV_OPT_FLAG_ENCODING_PARAM }, - { "window_size", "SDL window forced size", OFFSET(window_size) , AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, AV_OPT_FLAG_ENCODING_PARAM }, + { "window_size", "SDL window forced size", OFFSET(window_width), AV_OPT_TYPE_IMAGE_SIZE,{.str=NULL}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM }, { NULL }, }; @@ -225,6 +228,6 @@ AVOutputFormat ff_sdl_muxer = { .write_header = sdl_write_header, .write_packet = sdl_write_packet, .write_trailer = sdl_write_trailer, - .flags = AVFMT_NOFILE, + .flags = AVFMT_NOFILE | AVFMT_VARIABLE_FPS | AVFMT_NOTIMESTAMPS, .priv_class = &sdl_class, };