添加图片显示功能

This commit is contained in:
JIe Jie 2024-02-21 13:27:28 +08:00
parent 5cb403e96b
commit 3309be9582
2 changed files with 52 additions and 16 deletions

68
main.cc
View File

@ -2,6 +2,7 @@
#include <thread>
#include <SDL2/SDL.h>
#include <filesystem>
#include <opencv2/opencv.hpp>
#include "util.h"
#include "decoder.h"
@ -74,12 +75,12 @@ int InitVideo(SDL_Window*& window, const char* targetFilepath, DecoderParam& dec
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), reinterpret_cast<void*>(3 * sizeof(float)));
glEnableVertexAttribArray(1);
glGenTextures(3, openglVideoParam.texs);
for (int i = 0; i < 3; i++)
for (const unsigned int tex : openglVideoParam.texs)
{
glBindTexture(GL_TEXTURE_2D, openglVideoParam.texs[i]);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@ -93,24 +94,51 @@ int InitVideo(SDL_Window*& window, const char* targetFilepath, DecoderParam& dec
shaderService->SetUniform<int>("textureV", 2);
return 0;
}
void OpenglRender(DecoderParam& decoderParam, const OpenglVideoParam& openglVideoParam, ShaderService* shaderService)
void RenderPicture(SDL_Window* window, SDL_Renderer* renderer, SDL_Texture* texture)
{
SDL_SetRenderTarget(renderer, texture);
SDL_SetRenderTarget(renderer, nullptr);
SDL_RenderCopy(renderer, texture, nullptr, nullptr);
SDL_RenderPresent(renderer);
}
void InitImg(SDL_Window*& window, const char* filepath, SDL_Renderer*& renderer, SDL_Surface*& surface, SDL_Texture*& texture)
{
const cv::Mat img = cv::imread(filepath);
auto width = img.cols, height = img.rows;
cv::Mat target;
SDL_Rect rect;
SDL_GetDisplayBounds(0, &rect);
width = width > rect.w ? rect.w - 100 : width;
height = height > rect.h ? rect.h - 100 : height;
const cv::Size size{ width, height };
cv::resize(img, target, size, 0, 0, cv::INTER_LINEAR_EXACT);
window = SDL_CreateWindow("mp", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_SHOWN);
surface = SDL_CreateRGBSurfaceWithFormat(0, width, height, 24, SDL_PIXELFORMAT_RGB24);
memcpy(surface->pixels, target.data, static_cast<size_t>(width) * height * target.channels());
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
texture = SDL_CreateTextureFromSurface(renderer, surface);
}
void OpenglRenderVideo(DecoderParam& decoderParam, const OpenglVideoParam& openglVideoParam, ShaderService* shaderService)
{
auto frame = RequestFrame(decoderParam);
if (frame == nullptr)
return;
// TODO: TIMER
glBindTexture(GL_TEXTURE_2D, openglVideoParam.texs[0]);
glPixelStoref(GL_UNPACK_ROW_LENGTH, frame->linesize[0]);
glPixelStoref(GL_UNPACK_ROW_LENGTH, static_cast<float>(frame->linesize[0]));
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, frame->width, frame->height, 0, GL_RED, GL_UNSIGNED_BYTE, frame->data[0]);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, openglVideoParam.texs[1]);
glPixelStoref(GL_UNPACK_ROW_LENGTH, frame->linesize[1]);
glPixelStoref(GL_UNPACK_ROW_LENGTH, static_cast<float>(frame->linesize[1]));
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, frame->width / 2, frame->height / 2, 0, GL_RED, GL_UNSIGNED_BYTE, frame->data[1]);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, openglVideoParam.texs[2]);
glPixelStoref(GL_UNPACK_ROW_LENGTH, frame->linesize[2]);
glPixelStoref(GL_UNPACK_ROW_LENGTH, static_cast<float>(frame->linesize[2]));
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, frame->width / 2, frame->height / 2, 0, GL_RED, GL_UNSIGNED_BYTE, frame->data[2]);
av_frame_free(&frame);
@ -118,14 +146,14 @@ void OpenglRender(DecoderParam& decoderParam, const OpenglVideoParam& openglVide
shaderService->Use();
glBindVertexArray(openglVideoParam.VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
}
int main(int argc, char** const argv)
{
// Check File
const char* targetFilepath = argv[1];
if (targetFilepath == nullptr || !std::filesystem::exists(targetFilepath))
if (targetFilepath == nullptr || !exists(targetFilepath))
{
cout << "File Not Exist\n";
return 0;
@ -133,7 +161,7 @@ int main(int argc, char** const argv)
const FileType fileType = Util::GetFileType(targetFilepath);
if (fileType == FileType::ERRORTYPE)
{
cout << "unsupport file type\n";
cout << "unsupported file type\n";
return 0;
}
@ -144,6 +172,9 @@ int main(int argc, char** const argv)
DecoderParam decoderParam{};
OpenglVideoParam openglVideoParam{};
ShaderService* shaderService = nullptr;
SDL_Surface* surface = nullptr;
SDL_Renderer* renderer = nullptr;
SDL_Texture* texture = nullptr;
double framerate = .0f;
if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
{
@ -155,19 +186,20 @@ int main(int argc, char** const argv)
case FileType::VIDEO:
{
InitVideo(window, targetFilepath, decoderParam, openglVideoParam, shaderService);
auto stream_frame_rate = decoderParam.fmtCtx->streams[decoderParam.videoStreamIndex]->avg_frame_rate;
const auto stream_frame_rate = decoderParam.fmtCtx->streams[decoderParam.videoStreamIndex]->avg_frame_rate;
framerate = static_cast<double>(stream_frame_rate.den) / stream_frame_rate.num;
break;
}
case FileType::IMG:
{
InitImg(window, targetFilepath, renderer, surface, texture);
break;
}
case FileType::MUSIC:
{
break;
}
default:
case FileType::ERRORTYPE:
return -1;
}
@ -184,13 +216,15 @@ int main(int argc, char** const argv)
switch (event.key.keysym.scancode)
{
case SDL_SCANCODE_ESCAPE:
return -1;
quit = true;
break;
default:
break;
}
break;
case SDL_QUIT:
return -1;
quit = true;
break;
default:
break;
}
@ -200,12 +234,14 @@ int main(int argc, char** const argv)
switch (fileType)
{
case FileType::VIDEO:
OpenglRender(decoderParam, openglVideoParam, shaderService);
OpenglRenderVideo(decoderParam, openglVideoParam, shaderService);
SDL_GL_SwapWindow(window);
std::this_thread::sleep_until(current_time + std::chrono::milliseconds(static_cast<int>(framerate * 1000)));
current_time = std::chrono::system_clock::now();
break;
case FileType::IMG:
RenderPicture(window, renderer, texture);
break;
default:
break;
}

BIN
video/ocean.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB