1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Copyright (c) 2016 Josh de Kock 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * This file is part of FFmpeg. 5cabdff1aSopenharmony_ci * 6cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 7cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 8cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 9cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 10cabdff1aSopenharmony_ci * 11cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 12cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 13cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14cabdff1aSopenharmony_ci * Lesser General Public License for more details. 15cabdff1aSopenharmony_ci * 16cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 17cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 18cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19cabdff1aSopenharmony_ci */ 20cabdff1aSopenharmony_ci 21cabdff1aSopenharmony_ci/** 22cabdff1aSopenharmony_ci * @file 23cabdff1aSopenharmony_ci * libSDL2 output device 24cabdff1aSopenharmony_ci */ 25cabdff1aSopenharmony_ci 26cabdff1aSopenharmony_ci#include <SDL.h> 27cabdff1aSopenharmony_ci#include <SDL_thread.h> 28cabdff1aSopenharmony_ci 29cabdff1aSopenharmony_ci#include "libavutil/avstring.h" 30cabdff1aSopenharmony_ci#include "libavutil/imgutils.h" 31cabdff1aSopenharmony_ci#include "libavutil/opt.h" 32cabdff1aSopenharmony_ci#include "libavutil/parseutils.h" 33cabdff1aSopenharmony_ci#include "libavutil/pixdesc.h" 34cabdff1aSopenharmony_ci#include "libavutil/time.h" 35cabdff1aSopenharmony_ci#include "avdevice.h" 36cabdff1aSopenharmony_ci 37cabdff1aSopenharmony_citypedef struct { 38cabdff1aSopenharmony_ci AVClass *class; 39cabdff1aSopenharmony_ci SDL_Window *window; 40cabdff1aSopenharmony_ci SDL_Renderer *renderer; 41cabdff1aSopenharmony_ci char *window_title; 42cabdff1aSopenharmony_ci int window_width, window_height; /**< size of the window */ 43cabdff1aSopenharmony_ci int window_x, window_y; /**< position of the window */ 44cabdff1aSopenharmony_ci int window_fullscreen; 45cabdff1aSopenharmony_ci int window_borderless; 46cabdff1aSopenharmony_ci int enable_quit_action; 47cabdff1aSopenharmony_ci 48cabdff1aSopenharmony_ci SDL_Texture *texture; 49cabdff1aSopenharmony_ci int texture_fmt; 50cabdff1aSopenharmony_ci SDL_Rect texture_rect; 51cabdff1aSopenharmony_ci 52cabdff1aSopenharmony_ci int inited; 53cabdff1aSopenharmony_ci} SDLContext; 54cabdff1aSopenharmony_ci 55cabdff1aSopenharmony_cistatic const struct sdl_texture_format_entry { 56cabdff1aSopenharmony_ci enum AVPixelFormat format; int texture_fmt; 57cabdff1aSopenharmony_ci} sdl_texture_format_map[] = { 58cabdff1aSopenharmony_ci /* 59cabdff1aSopenharmony_ci * Not implemented in FFmpeg, but leaving here for completeness. 60cabdff1aSopenharmony_ci * { AV_PIX_FMT_NONE, SDL_PIXELFORMAT_ARGB4444 }, 61cabdff1aSopenharmony_ci * { AV_PIX_FMT_NONE, SDL_PIXELFORMAT_RGBA4444 }, 62cabdff1aSopenharmony_ci * { AV_PIX_FMT_NONE, SDL_PIXELFORMAT_ABGR4444 }, 63cabdff1aSopenharmony_ci * { AV_PIX_FMT_NONE, SDL_PIXELFORMAT_BGRA4444 }, 64cabdff1aSopenharmony_ci * { AV_PIX_FMT_NONE, SDL_PIXELFORMAT_ARGB1555 }, 65cabdff1aSopenharmony_ci * { AV_PIX_FMT_NONE, SDL_PIXELFORMAT_RGBA5551 }, 66cabdff1aSopenharmony_ci * { AV_PIX_FMT_NONE, SDL_PIXELFORMAT_ABGR1555 }, 67cabdff1aSopenharmony_ci * { AV_PIX_FMT_NONE, SDL_PIXELFORMAT_BGRA5551 }, 68cabdff1aSopenharmony_ci * { AV_PIX_FMT_NONE, SDL_PIXELFORMAT_ARGB2101010 }, 69cabdff1aSopenharmony_ci */ 70cabdff1aSopenharmony_ci { AV_PIX_FMT_RGB8, SDL_PIXELFORMAT_RGB332 }, 71cabdff1aSopenharmony_ci { AV_PIX_FMT_RGB444, SDL_PIXELFORMAT_RGB444 }, 72cabdff1aSopenharmony_ci { AV_PIX_FMT_RGB555, SDL_PIXELFORMAT_RGB555 }, 73cabdff1aSopenharmony_ci { AV_PIX_FMT_BGR555, SDL_PIXELFORMAT_BGR555 }, 74cabdff1aSopenharmony_ci { AV_PIX_FMT_RGB565, SDL_PIXELFORMAT_RGB565 }, 75cabdff1aSopenharmony_ci { AV_PIX_FMT_BGR565, SDL_PIXELFORMAT_BGR565 }, 76cabdff1aSopenharmony_ci { AV_PIX_FMT_RGB24, SDL_PIXELFORMAT_RGB24 }, 77cabdff1aSopenharmony_ci { AV_PIX_FMT_BGR24, SDL_PIXELFORMAT_BGR24 }, 78cabdff1aSopenharmony_ci { AV_PIX_FMT_0RGB32, SDL_PIXELFORMAT_RGB888 }, 79cabdff1aSopenharmony_ci { AV_PIX_FMT_0BGR32, SDL_PIXELFORMAT_BGR888 }, 80cabdff1aSopenharmony_ci#if HAVE_BIGENDIAN 81cabdff1aSopenharmony_ci { AV_PIX_FMT_RGB0, SDL_PIXELFORMAT_RGBX8888 }, 82cabdff1aSopenharmony_ci { AV_PIX_FMT_BGR0, SDL_PIXELFORMAT_BGRX8888 }, 83cabdff1aSopenharmony_ci#else 84cabdff1aSopenharmony_ci { AV_PIX_FMT_0BGR, SDL_PIXELFORMAT_RGBX8888 }, 85cabdff1aSopenharmony_ci { AV_PIX_FMT_0RGB, SDL_PIXELFORMAT_BGRX8888 }, 86cabdff1aSopenharmony_ci#endif 87cabdff1aSopenharmony_ci { AV_PIX_FMT_RGB32, SDL_PIXELFORMAT_ARGB8888 }, 88cabdff1aSopenharmony_ci { AV_PIX_FMT_RGB32_1, SDL_PIXELFORMAT_RGBA8888 }, 89cabdff1aSopenharmony_ci { AV_PIX_FMT_BGR32, SDL_PIXELFORMAT_ABGR8888 }, 90cabdff1aSopenharmony_ci { AV_PIX_FMT_BGR32_1, SDL_PIXELFORMAT_BGRA8888 }, 91cabdff1aSopenharmony_ci { AV_PIX_FMT_YUV420P, SDL_PIXELFORMAT_IYUV }, 92cabdff1aSopenharmony_ci { AV_PIX_FMT_YUYV422, SDL_PIXELFORMAT_YUY2 }, 93cabdff1aSopenharmony_ci { AV_PIX_FMT_UYVY422, SDL_PIXELFORMAT_UYVY }, 94cabdff1aSopenharmony_ci { AV_PIX_FMT_NONE, 0 }, 95cabdff1aSopenharmony_ci}; 96cabdff1aSopenharmony_ci 97cabdff1aSopenharmony_cistatic void compute_texture_rect(AVFormatContext *s) 98cabdff1aSopenharmony_ci{ 99cabdff1aSopenharmony_ci AVRational sar, dar; /* sample and display aspect ratios */ 100cabdff1aSopenharmony_ci SDLContext *sdl = s->priv_data; 101cabdff1aSopenharmony_ci AVStream *st = s->streams[0]; 102cabdff1aSopenharmony_ci AVCodecParameters *codecpar = st->codecpar; 103cabdff1aSopenharmony_ci SDL_Rect *texture_rect = &sdl->texture_rect; 104cabdff1aSopenharmony_ci 105cabdff1aSopenharmony_ci /* compute texture width and height from the codec context information */ 106cabdff1aSopenharmony_ci sar = st->sample_aspect_ratio.num ? st->sample_aspect_ratio : (AVRational){ 1, 1 }; 107cabdff1aSopenharmony_ci dar = av_mul_q(sar, (AVRational){ codecpar->width, codecpar->height }); 108cabdff1aSopenharmony_ci 109cabdff1aSopenharmony_ci /* we suppose the screen has a 1/1 sample aspect ratio */ 110cabdff1aSopenharmony_ci if (sdl->window_width && sdl->window_height) { 111cabdff1aSopenharmony_ci /* fit in the window */ 112cabdff1aSopenharmony_ci if (av_cmp_q(dar, (AVRational){ sdl->window_width, sdl->window_height }) > 0) { 113cabdff1aSopenharmony_ci /* fit in width */ 114cabdff1aSopenharmony_ci texture_rect->w = sdl->window_width; 115cabdff1aSopenharmony_ci texture_rect->h = av_rescale(texture_rect->w, dar.den, dar.num); 116cabdff1aSopenharmony_ci } else { 117cabdff1aSopenharmony_ci /* fit in height */ 118cabdff1aSopenharmony_ci texture_rect->h = sdl->window_height; 119cabdff1aSopenharmony_ci texture_rect->w = av_rescale(texture_rect->h, dar.num, dar.den); 120cabdff1aSopenharmony_ci } 121cabdff1aSopenharmony_ci } else { 122cabdff1aSopenharmony_ci if (sar.num > sar.den) { 123cabdff1aSopenharmony_ci texture_rect->w = codecpar->width; 124cabdff1aSopenharmony_ci texture_rect->h = av_rescale(texture_rect->w, dar.den, dar.num); 125cabdff1aSopenharmony_ci } else { 126cabdff1aSopenharmony_ci texture_rect->h = codecpar->height; 127cabdff1aSopenharmony_ci texture_rect->w = av_rescale(texture_rect->h, dar.num, dar.den); 128cabdff1aSopenharmony_ci } 129cabdff1aSopenharmony_ci sdl->window_width = texture_rect->w; 130cabdff1aSopenharmony_ci sdl->window_height = texture_rect->h; 131cabdff1aSopenharmony_ci } 132cabdff1aSopenharmony_ci 133cabdff1aSopenharmony_ci texture_rect->x = (sdl->window_width - texture_rect->w) / 2; 134cabdff1aSopenharmony_ci texture_rect->y = (sdl->window_height - texture_rect->h) / 2; 135cabdff1aSopenharmony_ci} 136cabdff1aSopenharmony_ci 137cabdff1aSopenharmony_cistatic int sdl2_write_trailer(AVFormatContext *s) 138cabdff1aSopenharmony_ci{ 139cabdff1aSopenharmony_ci SDLContext *sdl = s->priv_data; 140cabdff1aSopenharmony_ci 141cabdff1aSopenharmony_ci if (sdl->texture) 142cabdff1aSopenharmony_ci SDL_DestroyTexture(sdl->texture); 143cabdff1aSopenharmony_ci sdl->texture = NULL; 144cabdff1aSopenharmony_ci 145cabdff1aSopenharmony_ci if (sdl->renderer) 146cabdff1aSopenharmony_ci SDL_DestroyRenderer(sdl->renderer); 147cabdff1aSopenharmony_ci sdl->renderer = NULL; 148cabdff1aSopenharmony_ci 149cabdff1aSopenharmony_ci if (sdl->window) 150cabdff1aSopenharmony_ci SDL_DestroyWindow(sdl->window); 151cabdff1aSopenharmony_ci sdl->window = NULL; 152cabdff1aSopenharmony_ci 153cabdff1aSopenharmony_ci if (!sdl->inited) 154cabdff1aSopenharmony_ci SDL_Quit(); 155cabdff1aSopenharmony_ci 156cabdff1aSopenharmony_ci return 0; 157cabdff1aSopenharmony_ci} 158cabdff1aSopenharmony_ci 159cabdff1aSopenharmony_cistatic int sdl2_write_header(AVFormatContext *s) 160cabdff1aSopenharmony_ci{ 161cabdff1aSopenharmony_ci SDLContext *sdl = s->priv_data; 162cabdff1aSopenharmony_ci AVStream *st = s->streams[0]; 163cabdff1aSopenharmony_ci AVCodecParameters *codecpar = st->codecpar; 164cabdff1aSopenharmony_ci int i, ret = 0; 165cabdff1aSopenharmony_ci int flags = 0; 166cabdff1aSopenharmony_ci 167cabdff1aSopenharmony_ci if (!sdl->window_title) 168cabdff1aSopenharmony_ci sdl->window_title = av_strdup(s->url); 169cabdff1aSopenharmony_ci 170cabdff1aSopenharmony_ci if (SDL_WasInit(SDL_INIT_VIDEO)) { 171cabdff1aSopenharmony_ci av_log(s, AV_LOG_WARNING, 172cabdff1aSopenharmony_ci "SDL video subsystem was already inited, you could have multiple SDL outputs. This may cause unknown behaviour.\n"); 173cabdff1aSopenharmony_ci sdl->inited = 1; 174cabdff1aSopenharmony_ci } 175cabdff1aSopenharmony_ci 176cabdff1aSopenharmony_ci if ( s->nb_streams > 1 177cabdff1aSopenharmony_ci || codecpar->codec_type != AVMEDIA_TYPE_VIDEO 178cabdff1aSopenharmony_ci || codecpar->codec_id != AV_CODEC_ID_RAWVIDEO) { 179cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "Only supports one rawvideo stream\n"); 180cabdff1aSopenharmony_ci goto fail; 181cabdff1aSopenharmony_ci } 182cabdff1aSopenharmony_ci 183cabdff1aSopenharmony_ci for (i = 0; sdl_texture_format_map[i].format != AV_PIX_FMT_NONE; i++) { 184cabdff1aSopenharmony_ci if (sdl_texture_format_map[i].format == codecpar->format) { 185cabdff1aSopenharmony_ci sdl->texture_fmt = sdl_texture_format_map[i].texture_fmt; 186cabdff1aSopenharmony_ci break; 187cabdff1aSopenharmony_ci } 188cabdff1aSopenharmony_ci } 189cabdff1aSopenharmony_ci 190cabdff1aSopenharmony_ci if (!sdl->texture_fmt) { 191cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, 192cabdff1aSopenharmony_ci "Unsupported pixel format '%s'.\n", 193cabdff1aSopenharmony_ci av_get_pix_fmt_name(codecpar->format)); 194cabdff1aSopenharmony_ci goto fail; 195cabdff1aSopenharmony_ci } 196cabdff1aSopenharmony_ci 197cabdff1aSopenharmony_ci /* resize texture to width and height from the codec context information */ 198cabdff1aSopenharmony_ci flags = SDL_WINDOW_HIDDEN | 199cabdff1aSopenharmony_ci (sdl->window_fullscreen ? SDL_WINDOW_FULLSCREEN : 0) | 200cabdff1aSopenharmony_ci (sdl->window_borderless ? SDL_WINDOW_BORDERLESS : SDL_WINDOW_RESIZABLE); 201cabdff1aSopenharmony_ci 202cabdff1aSopenharmony_ci /* initialization */ 203cabdff1aSopenharmony_ci if (!sdl->inited){ 204cabdff1aSopenharmony_ci if (SDL_Init(SDL_INIT_VIDEO) != 0) { 205cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "Unable to initialize SDL: %s\n", SDL_GetError()); 206cabdff1aSopenharmony_ci goto fail; 207cabdff1aSopenharmony_ci } 208cabdff1aSopenharmony_ci } 209cabdff1aSopenharmony_ci 210cabdff1aSopenharmony_ci compute_texture_rect(s); 211cabdff1aSopenharmony_ci 212cabdff1aSopenharmony_ci if (SDL_CreateWindowAndRenderer(sdl->window_width, sdl->window_height, 213cabdff1aSopenharmony_ci flags, &sdl->window, &sdl->renderer) != 0){ 214cabdff1aSopenharmony_ci av_log(sdl, AV_LOG_ERROR, "Couldn't create window and renderer: %s\n", SDL_GetError()); 215cabdff1aSopenharmony_ci goto fail; 216cabdff1aSopenharmony_ci } 217cabdff1aSopenharmony_ci 218cabdff1aSopenharmony_ci SDL_SetWindowTitle(sdl->window, sdl->window_title); 219cabdff1aSopenharmony_ci SDL_SetWindowPosition(sdl->window, sdl->window_x, sdl->window_y); 220cabdff1aSopenharmony_ci SDL_ShowWindow(sdl->window); 221cabdff1aSopenharmony_ci 222cabdff1aSopenharmony_ci sdl->texture = SDL_CreateTexture(sdl->renderer, sdl->texture_fmt, SDL_TEXTUREACCESS_STREAMING, 223cabdff1aSopenharmony_ci codecpar->width, codecpar->height); 224cabdff1aSopenharmony_ci 225cabdff1aSopenharmony_ci if (!sdl->texture) { 226cabdff1aSopenharmony_ci av_log(sdl, AV_LOG_ERROR, "Unable to set create mode: %s\n", SDL_GetError()); 227cabdff1aSopenharmony_ci goto fail; 228cabdff1aSopenharmony_ci } 229cabdff1aSopenharmony_ci 230cabdff1aSopenharmony_ci av_log(s, AV_LOG_VERBOSE, "w:%d h:%d fmt:%s -> w:%d h:%d\n", 231cabdff1aSopenharmony_ci codecpar->width, codecpar->height, av_get_pix_fmt_name(codecpar->format), 232cabdff1aSopenharmony_ci sdl->window_width, sdl->window_height); 233cabdff1aSopenharmony_ci 234cabdff1aSopenharmony_ci sdl->inited = 1; 235cabdff1aSopenharmony_ci 236cabdff1aSopenharmony_ci return 0; 237cabdff1aSopenharmony_cifail: 238cabdff1aSopenharmony_ci sdl2_write_trailer(s); 239cabdff1aSopenharmony_ci return ret; 240cabdff1aSopenharmony_ci} 241cabdff1aSopenharmony_ci 242cabdff1aSopenharmony_cistatic int sdl2_write_packet(AVFormatContext *s, AVPacket *pkt) 243cabdff1aSopenharmony_ci{ 244cabdff1aSopenharmony_ci int ret, quit = 0; 245cabdff1aSopenharmony_ci SDLContext *sdl = s->priv_data; 246cabdff1aSopenharmony_ci AVCodecParameters *codecpar = s->streams[0]->codecpar; 247cabdff1aSopenharmony_ci uint8_t *data[4]; 248cabdff1aSopenharmony_ci int linesize[4]; 249cabdff1aSopenharmony_ci 250cabdff1aSopenharmony_ci SDL_Event event; 251cabdff1aSopenharmony_ci if (SDL_PollEvent(&event)){ 252cabdff1aSopenharmony_ci switch (event.type) { 253cabdff1aSopenharmony_ci case SDL_KEYDOWN: 254cabdff1aSopenharmony_ci switch (event.key.keysym.sym) { 255cabdff1aSopenharmony_ci case SDLK_ESCAPE: 256cabdff1aSopenharmony_ci case SDLK_q: 257cabdff1aSopenharmony_ci quit = 1; 258cabdff1aSopenharmony_ci break; 259cabdff1aSopenharmony_ci default: 260cabdff1aSopenharmony_ci break; 261cabdff1aSopenharmony_ci } 262cabdff1aSopenharmony_ci break; 263cabdff1aSopenharmony_ci case SDL_QUIT: 264cabdff1aSopenharmony_ci quit = 1; 265cabdff1aSopenharmony_ci break; 266cabdff1aSopenharmony_ci case SDL_WINDOWEVENT: 267cabdff1aSopenharmony_ci switch(event.window.event){ 268cabdff1aSopenharmony_ci case SDL_WINDOWEVENT_RESIZED: 269cabdff1aSopenharmony_ci case SDL_WINDOWEVENT_SIZE_CHANGED: 270cabdff1aSopenharmony_ci sdl->window_width = event.window.data1; 271cabdff1aSopenharmony_ci sdl->window_height = event.window.data2; 272cabdff1aSopenharmony_ci compute_texture_rect(s); 273cabdff1aSopenharmony_ci break; 274cabdff1aSopenharmony_ci default: 275cabdff1aSopenharmony_ci break; 276cabdff1aSopenharmony_ci } 277cabdff1aSopenharmony_ci break; 278cabdff1aSopenharmony_ci default: 279cabdff1aSopenharmony_ci break; 280cabdff1aSopenharmony_ci } 281cabdff1aSopenharmony_ci } 282cabdff1aSopenharmony_ci 283cabdff1aSopenharmony_ci if (quit && sdl->enable_quit_action) { 284cabdff1aSopenharmony_ci sdl2_write_trailer(s); 285cabdff1aSopenharmony_ci return AVERROR(EIO); 286cabdff1aSopenharmony_ci } 287cabdff1aSopenharmony_ci 288cabdff1aSopenharmony_ci av_image_fill_arrays(data, linesize, pkt->data, codecpar->format, codecpar->width, codecpar->height, 1); 289cabdff1aSopenharmony_ci switch (sdl->texture_fmt) { 290cabdff1aSopenharmony_ci /* case SDL_PIXELFORMAT_ARGB4444: 291cabdff1aSopenharmony_ci * case SDL_PIXELFORMAT_RGBA4444: 292cabdff1aSopenharmony_ci * case SDL_PIXELFORMAT_ABGR4444: 293cabdff1aSopenharmony_ci * case SDL_PIXELFORMAT_BGRA4444: 294cabdff1aSopenharmony_ci * case SDL_PIXELFORMAT_ARGB1555: 295cabdff1aSopenharmony_ci * case SDL_PIXELFORMAT_RGBA5551: 296cabdff1aSopenharmony_ci * case SDL_PIXELFORMAT_ABGR1555: 297cabdff1aSopenharmony_ci * case SDL_PIXELFORMAT_BGRA5551: 298cabdff1aSopenharmony_ci * case SDL_PIXELFORMAT_ARGB2101010: 299cabdff1aSopenharmony_ci */ 300cabdff1aSopenharmony_ci case SDL_PIXELFORMAT_IYUV: 301cabdff1aSopenharmony_ci case SDL_PIXELFORMAT_YUY2: 302cabdff1aSopenharmony_ci case SDL_PIXELFORMAT_UYVY: 303cabdff1aSopenharmony_ci ret = SDL_UpdateYUVTexture(sdl->texture, NULL, 304cabdff1aSopenharmony_ci data[0], linesize[0], 305cabdff1aSopenharmony_ci data[1], linesize[1], 306cabdff1aSopenharmony_ci data[2], linesize[2]); 307cabdff1aSopenharmony_ci break; 308cabdff1aSopenharmony_ci case SDL_PIXELFORMAT_RGB332: 309cabdff1aSopenharmony_ci case SDL_PIXELFORMAT_RGB444: 310cabdff1aSopenharmony_ci case SDL_PIXELFORMAT_RGB555: 311cabdff1aSopenharmony_ci case SDL_PIXELFORMAT_BGR555: 312cabdff1aSopenharmony_ci case SDL_PIXELFORMAT_RGB565: 313cabdff1aSopenharmony_ci case SDL_PIXELFORMAT_BGR565: 314cabdff1aSopenharmony_ci case SDL_PIXELFORMAT_RGB24: 315cabdff1aSopenharmony_ci case SDL_PIXELFORMAT_BGR24: 316cabdff1aSopenharmony_ci case SDL_PIXELFORMAT_RGB888: 317cabdff1aSopenharmony_ci case SDL_PIXELFORMAT_RGBX8888: 318cabdff1aSopenharmony_ci case SDL_PIXELFORMAT_BGR888: 319cabdff1aSopenharmony_ci case SDL_PIXELFORMAT_BGRX8888: 320cabdff1aSopenharmony_ci case SDL_PIXELFORMAT_ARGB8888: 321cabdff1aSopenharmony_ci case SDL_PIXELFORMAT_RGBA8888: 322cabdff1aSopenharmony_ci case SDL_PIXELFORMAT_ABGR8888: 323cabdff1aSopenharmony_ci case SDL_PIXELFORMAT_BGRA8888: 324cabdff1aSopenharmony_ci ret = SDL_UpdateTexture(sdl->texture, NULL, data[0], linesize[0]); 325cabdff1aSopenharmony_ci break; 326cabdff1aSopenharmony_ci default: 327cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_FATAL, "Unsupported pixel format\n"); 328cabdff1aSopenharmony_ci ret = -1; 329cabdff1aSopenharmony_ci break; 330cabdff1aSopenharmony_ci } 331cabdff1aSopenharmony_ci SDL_RenderClear(sdl->renderer); 332cabdff1aSopenharmony_ci SDL_RenderCopy(sdl->renderer, sdl->texture, NULL, &sdl->texture_rect); 333cabdff1aSopenharmony_ci SDL_RenderPresent(sdl->renderer); 334cabdff1aSopenharmony_ci return ret; 335cabdff1aSopenharmony_ci} 336cabdff1aSopenharmony_ci 337cabdff1aSopenharmony_ci#define OFFSET(x) offsetof(SDLContext,x) 338cabdff1aSopenharmony_ci 339cabdff1aSopenharmony_cistatic const AVOption options[] = { 340cabdff1aSopenharmony_ci { "window_title", "set SDL window title", OFFSET(window_title), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, AV_OPT_FLAG_ENCODING_PARAM }, 341cabdff1aSopenharmony_ci { "window_size", "set SDL window forced size", OFFSET(window_width), AV_OPT_TYPE_IMAGE_SIZE, { .str = NULL }, 0, 0, AV_OPT_FLAG_ENCODING_PARAM }, 342cabdff1aSopenharmony_ci { "window_x", "set SDL window x position", OFFSET(window_x), AV_OPT_TYPE_INT, { .i64 = SDL_WINDOWPOS_CENTERED }, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, 343cabdff1aSopenharmony_ci { "window_y", "set SDL window y position", OFFSET(window_y), AV_OPT_TYPE_INT, { .i64 = SDL_WINDOWPOS_CENTERED }, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, 344cabdff1aSopenharmony_ci { "window_fullscreen", "set SDL window fullscreen", OFFSET(window_fullscreen), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_ENCODING_PARAM }, 345cabdff1aSopenharmony_ci { "window_borderless", "set SDL window border off", OFFSET(window_borderless), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_ENCODING_PARAM }, 346cabdff1aSopenharmony_ci { "window_enable_quit", "set if quit action is available", OFFSET(enable_quit_action), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM }, 347cabdff1aSopenharmony_ci { NULL }, 348cabdff1aSopenharmony_ci}; 349cabdff1aSopenharmony_ci 350cabdff1aSopenharmony_cistatic const AVClass sdl2_class = { 351cabdff1aSopenharmony_ci .class_name = "sdl2 outdev", 352cabdff1aSopenharmony_ci .item_name = av_default_item_name, 353cabdff1aSopenharmony_ci .option = options, 354cabdff1aSopenharmony_ci .version = LIBAVUTIL_VERSION_INT, 355cabdff1aSopenharmony_ci .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT, 356cabdff1aSopenharmony_ci}; 357cabdff1aSopenharmony_ci 358cabdff1aSopenharmony_ciconst AVOutputFormat ff_sdl2_muxer = { 359cabdff1aSopenharmony_ci .name = "sdl,sdl2", 360cabdff1aSopenharmony_ci .long_name = NULL_IF_CONFIG_SMALL("SDL2 output device"), 361cabdff1aSopenharmony_ci .priv_data_size = sizeof(SDLContext), 362cabdff1aSopenharmony_ci .audio_codec = AV_CODEC_ID_NONE, 363cabdff1aSopenharmony_ci .video_codec = AV_CODEC_ID_RAWVIDEO, 364cabdff1aSopenharmony_ci .write_header = sdl2_write_header, 365cabdff1aSopenharmony_ci .write_packet = sdl2_write_packet, 366cabdff1aSopenharmony_ci .write_trailer = sdl2_write_trailer, 367cabdff1aSopenharmony_ci .flags = AVFMT_NOFILE | AVFMT_VARIABLE_FPS | AVFMT_NOTIMESTAMPS, 368cabdff1aSopenharmony_ci .priv_class = &sdl2_class, 369cabdff1aSopenharmony_ci}; 370