SDL_Overlay 的 SDL2.0 替代方案
Posted
技术标签:
【中文标题】SDL_Overlay 的 SDL2.0 替代方案【英文标题】:SDL2.0 Alternative for SDL_Overlay 【发布时间】:2013-07-08 21:26:06 【问题描述】:所以我一直在尝试通过以下关于 ffmpeg 的教程:http://dranger.com/ffmpeg/tutorial02.html
但是,当我尝试使用 gcc 进行编译时,我得到以下输出:
root:/Users/mbrodeur/Downloads/HACKATHON CONTENT/Tutorials-> gcc -o tutorial02 tutorial02.c -lavutil -lavformat -lavcodec -lz -lavutil -lm -lswscale -D_THREAD_SAFE -lSDL2
tutorial02.c: In function ‘main’:
tutorial02.c:41: error: ‘SDL_Overlay’ undeclared (first use in this function)
tutorial02.c:41: error: (Each undeclared identifier is reported only once
tutorial02.c:41: error: for each function it appears in.)
tutorial02.c:41: error: ‘bmp’ undeclared (first use in this function)
tutorial02.c:98: warning: assignment makes pointer from integer without a cast
tutorial02.c:110: error: ‘SDL_YV12_OVERLAY’ undeclared (first use in this function)
现在,我读到 SDL2 中不再使用 SDL_Overlay,所以问题就在这里。我一直在四处寻找,但似乎找不到任何有用的东西。 SDL_Overlay 有替代品吗?有必要吗?
SDL_Overlay 用于以下上下文:
SDL_Overlay *bmp;
bmp = SDL_CreateYUVOverlay(pCodecCtx->width, pCodecCtx->height,
SDL_YV12_OVERLAY, screen);
【问题讨论】:
不相关,但您可能想查看updated source code 版本的教程。 谢谢,我不知道该页面存在。不幸的是,更新的源代码仍然没有解决我的问题。 您有没有及时更新教程并让代码与 sdl2 一起使用?如果可以,可以分享吗?提前致谢。 :D 【参考方案1】:我已更新教程以使用 SDL 2.0.1。它将 SDL_Overlay 替换为 YV12 格式的 SDL_Texture。
int main(int argc, char *argv[])
AVFormatContext *pFormatCtx = NULL;
int videoStream;
unsigned i;
AVCodecContext *pCodecCtxOrig = NULL;
AVCodecContext *pCodecCtx = NULL;
AVCodec *pCodec = NULL;
AVFrame *pFrame = NULL;
AVPacket packet;
int frameFinished;
struct SwsContext *sws_ctx = NULL;
SDL_Event event;
SDL_Window *screen;
SDL_Renderer *renderer;
SDL_Texture *texture;
Uint8 *yPlane, *uPlane, *vPlane;
size_t yPlaneSz, uvPlaneSz;
int uvPitch;
if (argc < 2)
fprintf(stderr, "Usage: test <file>\n");
exit(1);
// Register all formats and codecs
av_register_all();
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER))
fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
exit(1);
// Open video file
if (avformat_open_input(&pFormatCtx, argv[1], NULL, NULL) != 0)
return -1; // Couldn't open file
// Retrieve stream information
if (avformat_find_stream_info(pFormatCtx, NULL) < 0)
return -1; // Couldn't find stream information
// Dump information about file onto standard error
av_dump_format(pFormatCtx, 0, argv[1], 0);
// Find the first video stream
videoStream = -1;
for (i = 0; i < pFormatCtx->nb_streams; i++)
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
videoStream = i;
break;
if (videoStream == -1)
return -1; // Didn't find a video stream
// Get a pointer to the codec context for the video stream
pCodecCtxOrig = pFormatCtx->streams[videoStream]->codec;
// Find the decoder for the video stream
pCodec = avcodec_find_decoder(pCodecCtxOrig->codec_id);
if (pCodec == NULL)
fprintf(stderr, "Unsupported codec!\n");
return -1; // Codec not found
// Copy context
pCodecCtx = avcodec_alloc_context3(pCodec);
if (avcodec_copy_context(pCodecCtx, pCodecCtxOrig) != 0)
fprintf(stderr, "Couldn't copy codec context");
return -1; // Error copying codec context
// Open codec
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
return -1; // Could not open codec
// Allocate video frame
pFrame = av_frame_alloc();
// Make a screen to put our video
screen = SDL_CreateWindow(
"FFmpeg Tutorial",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
pCodecCtx->width,
pCodecCtx->height,
0
);
if (!screen)
fprintf(stderr, "SDL: could not create window - exiting\n");
exit(1);
renderer = SDL_CreateRenderer(screen, -1, 0);
if (!renderer)
fprintf(stderr, "SDL: could not create renderer - exiting\n");
exit(1);
// Allocate a place to put our YUV image on that screen
texture = SDL_CreateTexture(
renderer,
SDL_PIXELFORMAT_YV12,
SDL_TEXTUREACCESS_STREAMING,
pCodecCtx->width,
pCodecCtx->height
);
if (!texture)
fprintf(stderr, "SDL: could not create texture - exiting\n");
exit(1);
// initialize SWS context for software scaling
sws_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,
pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height,
AV_PIX_FMT_YUV420P,
SWS_BILINEAR,
NULL,
NULL,
NULL);
// set up YV12 pixel array (12 bits per pixel)
yPlaneSz = pCodecCtx->width * pCodecCtx->height;
uvPlaneSz = pCodecCtx->width * pCodecCtx->height / 4;
yPlane = (Uint8*)malloc(yPlaneSz);
uPlane = (Uint8*)malloc(uvPlaneSz);
vPlane = (Uint8*)malloc(uvPlaneSz);
if (!yPlane || !uPlane || !vPlane)
fprintf(stderr, "Could not allocate pixel buffers - exiting\n");
exit(1);
uvPitch = pCodecCtx->width / 2;
while (av_read_frame(pFormatCtx, &packet) >= 0)
// Is this a packet from the video stream?
if (packet.stream_index == videoStream)
// Decode video frame
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
// Did we get a video frame?
if (frameFinished)
AVPicture pict;
pict.data[0] = yPlane;
pict.data[1] = uPlane;
pict.data[2] = vPlane;
pict.linesize[0] = pCodecCtx->width;
pict.linesize[1] = uvPitch;
pict.linesize[2] = uvPitch;
// Convert the image into YUV format that SDL uses
sws_scale(sws_ctx, (uint8_t const * const *) pFrame->data,
pFrame->linesize, 0, pCodecCtx->height, pict.data,
pict.linesize);
SDL_UpdateYUVTexture(
texture,
NULL,
yPlane,
pCodecCtx->width,
uPlane,
uvPitch,
vPlane,
uvPitch
);
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
// Free the packet that was allocated by av_read_frame
av_free_packet(&packet);
SDL_PollEvent(&event);
switch (event.type)
case SDL_QUIT:
SDL_DestroyTexture(texture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(screen);
SDL_Quit();
exit(0);
break;
default:
break;
// Free the YUV frame
av_frame_free(&pFrame);
free(yPlane);
free(uPlane);
free(vPlane);
// Close the codec
avcodec_close(pCodecCtx);
avcodec_close(pCodecCtxOrig);
// Close the video file
avformat_close_input(&pFormatCtx);
return 0;
【讨论】:
其他教程更新了吗?心灵分享?我正在使用 SDL 2.0,因为我在 1.2 下载文件中找不到必要的包含。 +1 的努力。#include <stdio.h> #include <windows.h> #include <iostream> extern "C" #include "libavcodec\avcodec.h" #include "libavformat\avformat.h" #include "libswscale\swscale.h" #include "libswresample\swresample.h" #include "sdl/SDL.h" #pragma comment(lib, "SDL2.lib") #pragma comment(lib, "SDL2main.lib") #pragma comment(lib, "SDL2test.lib") #pragma comment(lib, "avcodec.lib") #pragma comment(lib, "avdevice.lib") #pragma comment(lib, "avfilter.lib") #pragma comment(lib, "avformat.lib") #pragma comment(lib, "avutil.lib") #pragma comment(lib, "swscale.lib")
【参考方案2】:
我也遇到了这个问题。我使用 SDL 1.2,因为我不知道如何替换 SDL2.0 中的 SDL_Overlay。如果您使用的是 Mac 10.10,则可以使用此补丁 http://www.emaculation.com/doku.php/compiling_sheepshaver_basilisk#tidbits
patch < no-CGDirectPaletteRef.patch
然后在 /src/video/x11/SDL_x11sym.h 中,将第 168 行和第 169 行替换为此
SDL_X11_SYM(int,_XData32,(Display *dpy,register _Xconst long *data,unsigned len),(dpy,data,len),return)
SDL_X11_SYM(void,_XRead32,(Display *dpy,register long *data,long len),(dpy,data,len), return)
它对我有用。
【讨论】:
【参考方案3】:教程 https://github.com/chelyaev/ffmpeg-tutorial 链接到 SDL1 http://www.libsdl.org/download-1.2.php 并且他们应该提到它(或者他们提到了但我没有看到它)。所有这些都与 SDL1 完美配合。
【讨论】:
【参考方案4】:尝试SDL_CreateTexture()
使用与解码帧的布局和平面性相匹配的 YUV 像素格式。
或者使用libswscale
将ffmpeg
的YUV缓冲区转换为RGB。
编辑:SDL2 >= 2.0.1 有 SDL_UpdateYUVTexture()
用于更新平面 YUV 纹理,因此您不必再手动合并 libav
的缓冲区。
【讨论】:
"这是一个相当慢的函数,用于静态纹理。"似乎不太适合视频? 在 SDL_UpdateTexture (wiki.libsdl.org/SDL_UpdateTexture) 中,它是从您上面的链接链接到的(我假设它是从 SDL_UpdateTexture 派生的)。我是 OpenGL 的新手,但认为写入纹理是最快的方法之一,所以我和你一样感到惊讶。也许 SDL 的实现本身很慢?无论如何,这似乎不是问题的正确答案,因为我认为 OP 想要显示视频。以上是关于SDL_Overlay 的 SDL2.0 替代方案的主要内容,如果未能解决你的问题,请参考以下文章