1-1、OpenGL渲染RGB图像步骤

1、初始化SDL接口

if (SDL_Init(SDL_INIT_VIDEO)) {
    cout << SDL_GetError() << endl;
    return -1;
}
static int sdl_width = ui.label->width();
static int sdl_height = ui.label->height();

2、初始化窗口

auto screen = SDL_CreateWindowFrom((void*)ui.label->winId()); // 渲染到Qt

auto screen = SDL_CreateWindow("test sdl ffmpeg", 
                                    SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, // 窗口位置
                                    sdl_width, sdl_height,
                                    SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE
                                    );

3、生成对应窗口的渲染器

auto render = SDL_CreateRenderer(screen, -1, SDL_RENDERER_ACCELERATED); // 使用硬件加速

4、创建材质

​ 材质是在显存当中的,需要接口和内存交互。

auto texture = SDL_CreateTexture(render, SDL_PIXELFORMAT_ARGB8888,	// 像素格式
                                 SDL_TEXTUREACCESS_STREAMING,		// 材质需要修改
                                 sdl_width, sdl_height
                                 );

rgb = new unsigned char[sdl_width * sdl_height * pix_size]; // 分配材质内存 

static int temp = 255;
temp--;
for (int j = 0; j < sdl_height; j++) {  // 写入rgb数据
    int b = j * sdl_width * 4;	  // 第一列像素位置
    for (int i = 0; i < sdl_width * 4; i += 4) {
        rgb[b + i] = 0;           //B
        rgb[b + i + 1] = 0;       //G
        rgb[b + i + 2] = temp;    //R
        rgb[b + i + 3] = 0;       //A
    }
}

SDL_UpdateTexture(texture, NULL, rgb, sdl_width * 4); // 把内存数据写入显存中的材质

5、渲染

SDL_RenderClear(render);     // 清理屏幕

SDL_Rect sdl_rect;  		// 目标尺寸
sdl_rect.x = 0;
sdl_rect.y = 0;
sdl_rect.w = sdl_width;
sdl_rect.h = sdl_height;

// 复制材质到渲染器
SDL_RenderCopy(render, sdl_texture,
               NULL/*原图位置和尺寸*/, 
               &sdl_rect/*目标位置和尺寸*/);

// 渲染
SDL_RenderPresent(render);
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
将 mp4 视频格式转换为 RGB 图像,需要经过以下几个步骤: 1. 使用 `MediaExtractor` 解析视频文件,获取视频中每个音视频轨道的信息。 2. 使用 `MediaCodec` 解码视频轨道中的数据,得到原始的 YUV 数据。 3. 将 YUV 数据转换为 RGB 数据。 4. 将 RGB 数据渲染到屏幕上。 下面是一个简单的示例代码,可以将 mp4 视频格式转换为 RGB 图像并显示在屏幕上: ```java private void decodeVideo(String videoPath) { try { // 创建 MediaExtractor 并指定要解析的视频文件路径 MediaExtractor extractor = new MediaExtractor(); extractor.setDataSource(videoPath); // 获取视频中的视频轨道 MediaFormat format = null; int videoTrackIndex = -1; for (int i = 0; i < extractor.getTrackCount(); i++) { format = extractor.getTrackFormat(i); String mime = format.getString(MediaFormat.KEY_MIME); if (mime.startsWith("video/")) { videoTrackIndex = i; break; } } if (videoTrackIndex == -1) { // 没有找到视频轨道 return; } // 创建 MediaCodec 并配置为解码器 extractor.selectTrack(videoTrackIndex); MediaCodec codec = MediaCodec.createDecoderByType(format.getString(MediaFormat.KEY_MIME)); codec.configure(format, null, null, 0); codec.start(); // 获取视频帧的 YUV 数据 ByteBuffer[] inputBuffers = codec.getInputBuffers(); ByteBuffer[] outputBuffers = codec.getOutputBuffers(); MediaCodec.BufferInfo info = new MediaCodec.BufferInfo(); boolean isEOS = false; long presentationTimeUs = 0; while (!Thread.interrupted()) { if (!isEOS) { int inIndex = codec.dequeueInputBuffer(10000); if (inIndex >= 0) { ByteBuffer buffer = inputBuffers[inIndex]; int sampleSize = extractor.readSampleData(buffer, 0); if (sampleSize < 0) { // 已经读到了视频末尾 codec.queueInputBuffer(inIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM); isEOS = true; } else { presentationTimeUs = extractor.getSampleTime(); codec.queueInputBuffer(inIndex, 0, sampleSize, presentationTimeUs, 0); extractor.advance(); } } } int outIndex = codec.dequeueOutputBuffer(info, 10000); switch (outIndex) { case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED: outputBuffers = codec.getOutputBuffers(); break; case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED: // 获取解码后的视频格式 format = codec.getOutputFormat(); break; case MediaCodec.INFO_TRY_AGAIN_LATER: break; default: ByteBuffer buffer = outputBuffers[outIndex]; // 将 YUV 数据转换为 RGB 数据 byte[] yuvData = new byte[info.size]; buffer.get(yuvData); byte[] rgbData = convertYUVtoRGB(yuvData, format.getInteger(MediaFormat.KEY_WIDTH), format.getInteger(MediaFormat.KEY_HEIGHT)); // 渲染 RGB 数据到屏幕上 renderRGB(rgbData, format.getInteger(MediaFormat.KEY_WIDTH), format.getInteger(MediaFormat.KEY_HEIGHT)); codec.releaseOutputBuffer(outIndex, true); break; } if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { // 已经处理完所有的视频帧 break; } } codec.stop(); codec.release(); extractor.release(); } catch (IOException e) { e.printStackTrace(); } } private byte[] convertYUVtoRGB(byte[] yuvData, int width, int height) { // TODO: 将 YUV 数据转换为 RGB 数据 return null; } private void renderRGB(byte[] rgbData, int width, int height) { // TODO: 渲染 RGB 数据到屏幕上 } ``` 需要注意的是,YUV 数据和 RGB 数据的转换算法比较复杂,具体实现可以参考一些开源库,如 FFmpeg、libyuv 等。另外,在渲染 RGB 数据到屏幕上时,可以使用 OpenGL ES 来实现,具体的 OpenGL ES 代码可以参考其他资料。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值