diff --git a/.gitignore b/.gitignore index 1a9c3ec..0611cae 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ /build/* .cache/* .vscode/* +/.vs +/CMakeSettings.json diff --git a/CMakeLists.txt b/CMakeLists.txt index d0ab88e..730c010 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,14 +6,16 @@ set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) +include_directories(${PROJECT_SOURCE_DIR}/include) +file(GLOB_RECURSE srcs ${PROJECT_SOURCE_DIR}/src/*.cc) +find_package(SDL2 REQUIRED) + +IF(UNIX) include_directories(/usr/include/x86_64-linux-gnu) set(GLAD_DIR /home/jie/documents/third/glad) set(GLM_DIR /home/jie/documents/third/glm) include_directories(${GLAD_DIR}/include) include_directories(${GLM_DIR}) -include_directories(${PROJECT_SOURCE_DIR}/include) -find_package(SDL2 REQUIRED) -file(GLOB_RECURSE srcs ${PROJECT_SOURCE_DIR}/src/*.cc) add_executable(${PROJECT_N} main.cc ${GLAD_DIR}/src/glad.c @@ -28,3 +30,47 @@ target_link_libraries(${PROJECT_N} vorbis avutil ) + +ELSE(WIN32) + +set(CMAKE_PREFIX_PATH C:/document/lib/) +set(THIRD_LIB_DIR C:/document/lib/) + +#vcpkg +set(VCPKG_PACKAGE C:/document/lib/vcpkg/packages) +set(VCPKG_BUILDTREES_DIR C:/document/lib/vcpkg/buildtrees) +set(VCPKG_INSTALLED C:/document/lib/vcpkg/installed/x64-windows) +#opengl +find_package(OpenGL) +#SDL2 +find_package(SDL2_image) +#rangev3 +include_directories(${VCPKG_PACKAGE}/range-v3_x64-windows/include) +#ffmpeg +include_directories(${VCPKG_PACKAGE}/ffmpeg_x64-windows/include) +file(GLOB_RECURSE FFMPEG_LIBS ${VCPKG_PACKAGE}/ffmpeg_x64-windows/debug/lib/*.lib) +#glad +include_directories(${THIRD_LIB_DIR}/glad/include) +set(GLAD_SRCS ${THIRD_LIB_DIR}/glad/src/glad.c) +#glm +include_directories(${THIRD_LIB_DIR}/glm) +#opencv +include_directories(${THIRD_LIB_DIR}/opencv/opencv/build/include) +link_directories(E:/dependency/lib) +set(OpenCV_LIBS + opencv_world460d.lib +) + +add_executable(${PROJECT_N} + ${srcs} + main.cc + ${GLAD_SRCS} +) +target_include_directories(${PROJECT_N} PUBLIC include) +target_link_libraries(${PROJECT_N} + ${SDL2_LIBRARIES} + ${FFMPEG_LIBS} + ${OpenCV_LIBS} + OpenGL32 +) +ENDIF() diff --git a/include/decoder.h b/include/decoder.h index 505d004..174d863 100644 --- a/include/decoder.h +++ b/include/decoder.h @@ -1,25 +1,18 @@ #ifndef DECODER_H #define DECODER_H -extern "C"{ - #include "libavcodec/avcodec.h" - #include "libavformat/avformat.h" - #include "libavutil/imgutils.h" +extern "C" { +#include "libavcodec/avcodec.h" +#include "libavformat/avformat.h" +#include "libavutil/imgutils.h" } -struct DecoderParam{ - AVFormatContext* fmtCtx; - AVCodecContext* codecCtx; - int width; - int height; - int videoStreamIndex; +struct DecoderParam { + AVFormatContext* fmtCtx; + AVCodecContext* codecCtx; + int width; + int height; + int videoStreamIndex; }; - -extern "C"{ - #include "libavcodec/avcodec.h" - #include "libavformat/avformat.h" - #include "libavutil/imgutils.h" -} - void InitDecoder(const char* filepath, DecoderParam& param); AVFrame* RequestFrame(DecoderParam& param); #endif \ No newline at end of file diff --git a/include/util.h b/include/util.h index 9048552..c068791 100644 --- a/include/util.h +++ b/include/util.h @@ -6,70 +6,69 @@ #include #include #include - -enum class FileType{ - MUSIC, - VIDEO, - IMG, - ERRORTYPE +#include +enum class FileType { + MUSIC, + VIDEO, + IMG, + ERRORTYPE }; -const std::array MusicFileExtensive = { - "mp3" +const std::array MusicFileExtensive = { + "mp3" }; -const std::array VideoFileExtensive = { - "mp4" +const std::array VideoFileExtensive = { + "mp4" }; -const std::array ImgFileExtensive = { - "jpeg", - "jpg", - "png", +const std::array ImgFileExtensive = { + "jpeg", + "jpg", + "png", }; - using namespace std::filesystem; -class Util{ +class Util { private: - static const char* GetFileExtensive(path filepath){ - std::string ext = filepath.extension().string(); - ext.erase(std::remove_if(ext.begin(), ext.end(), [](char c){return c=='.';}), ext.end()); - return ext.c_str(); - } - static bool IsMusic(path filepath){ - const auto ext = GetFileExtensive(filepath); - for(const auto& it : MusicFileExtensive){ - if(std::strcmp(it, ext) == 0) - return true; - } - return false; - } - - static bool IsVideo(path filepath){ - const auto ext = GetFileExtensive(filepath); - for(const auto& it : VideoFileExtensive){ - if(std::strcmp(it, ext) == 0) - return true; - } - return false; - } - - static bool IsImg(path filepath){ - const auto ext = GetFileExtensive(filepath); - for(const auto& it : ImgFileExtensive){ - if(std::strcmp(it, ext) == 0) - return true; - } - return false; - } + static std::string_view GetFileExtensive(const path& filepath) { + static std::string ext = filepath.extension().string(); + ext.erase(std::ranges::remove_if(ext, [](char c) {return c == '.'; }).begin(), ext.end()); + return std::string_view{ ext.c_str() }; + } + static bool IsMusic(const path& filepath) { + const auto ext = GetFileExtensive(filepath); + for (const auto& it : MusicFileExtensive) { + if (it == ext) + return true; + } + return false; + } + + static bool IsVideo(const path& filepath) { + const auto ext = GetFileExtensive(filepath); + for (const auto& it : VideoFileExtensive) { + if (it == ext) + return true; + } + return false; + } + + static bool IsImg(const path& filepath) { + const auto ext = GetFileExtensive(filepath); + for (const auto& it : ImgFileExtensive) { + if (it == ext) + return true; + } + return false; + } public: - static FileType GetFileType(path filepath){ - if(IsMusic(filepath)) return FileType::MUSIC; - if(IsVideo(filepath)) return FileType::VIDEO; - if(IsImg(filepath)) return FileType::IMG; - return FileType::ERRORTYPE; - } + static FileType GetFileType(const path& filepath) { + if (IsMusic(filepath)) return FileType::MUSIC; + if (IsVideo(filepath)) return FileType::VIDEO; + if (IsImg(filepath)) return FileType::IMG; + return FileType::ERRORTYPE; + } }; #endif \ No newline at end of file diff --git a/main.cc b/main.cc index 025bef6..5fcf53d 100644 --- a/main.cc +++ b/main.cc @@ -1,7 +1,6 @@ #include #include #include -#include #include #include "util.h" @@ -12,212 +11,210 @@ using std::cout, std::endl; struct OpenglVideoParam { - SDL_GLContext glContext; - unsigned int VAO, VBO, EBO; - unsigned int texs[3]; + SDL_GLContext glContext; + unsigned int VAO, VBO, EBO; + unsigned int texs[3]; }; -int InitVideo(SDL_Window *&window, const char *targetFilepath, DecoderParam &decoderParam, OpenglVideoParam &openglVideoParam, ShaderService *&shaderService) +int InitVideo(SDL_Window*& window, const char* targetFilepath, DecoderParam& decoderParam, OpenglVideoParam& openglVideoParam, ShaderService*& shaderService) { - InitDecoder(targetFilepath, decoderParam); - int client_width = decoderParam.width / 2; - int client_height = decoderParam.height / 2; - window = SDL_CreateWindow( - "MP", - SDL_WINDOWPOS_UNDEFINED, - SDL_WINDOWPOS_UNDEFINED, - client_width, - client_height, - SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL); - if (!window) - { - cout << SDL_GetError() << "\n"; - return -1; - } - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + InitDecoder(targetFilepath, decoderParam); + const int client_width = decoderParam.width / 2; + const int client_height = decoderParam.height / 2; + window = SDL_CreateWindow( + "MP", + SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, + client_width, + client_height, + SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL); + if (!window) + { + cout << SDL_GetError() << "\n"; + return -1; + } + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); - openglVideoParam.glContext = SDL_GL_CreateContext(window); - if (!openglVideoParam.glContext) - { - cout << SDL_GetError() << "\n"; - return -1; - } + openglVideoParam.glContext = SDL_GL_CreateContext(window); + if (!openglVideoParam.glContext) + { + cout << SDL_GetError() << "\n"; + return -1; + } - if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress)) - { - auto error = glad_glGetError(); - return static_cast(error); - } + if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress)) + { + auto error = glad_glGetError(); + return static_cast(error); + } - float vertices[] = { - 1.f, 1.f, 0.0, 1.0, 0.0, - 1.f, -1.f, 0.0, 1.0, 1.0, - -1.f, -1.f, 0.0, 0.0, 1.0, - -1.f, 1.f, 0.0, 0.0, 0.0}; - unsigned int indices[]{ - 0, - 1, - 3, - 1, - 2, - 3, - }; + float vertices[] = { + 1.f, 1.f, 0.0, 1.0, 0.0, + 1.f, -1.f, 0.0, 1.0, 1.0, + -1.f, -1.f, 0.0, 0.0, 1.0, + -1.f, 1.f, 0.0, 0.0, 0.0 }; + unsigned int indices[]{ + 0, + 1, + 3, + 1, + 2, + 3, + }; - glGenVertexArrays(1, &openglVideoParam.VAO); - glGenBuffers(1, &openglVideoParam.VBO); - glGenBuffers(1, &openglVideoParam.EBO); - glBindVertexArray(openglVideoParam.VAO); - glBindBuffer(GL_ARRAY_BUFFER, openglVideoParam.VBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, openglVideoParam.EBO); - 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))); - glEnableVertexAttribArray(1); - glGenTextures(3, openglVideoParam.texs); - for (int i = 0; i < 3; i++) - { - glBindTexture(GL_TEXTURE_2D, openglVideoParam.texs[i]); - 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); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } + glGenVertexArrays(1, &openglVideoParam.VAO); + glGenBuffers(1, &openglVideoParam.VBO); + glGenBuffers(1, &openglVideoParam.EBO); + glBindVertexArray(openglVideoParam.VAO); + glBindBuffer(GL_ARRAY_BUFFER, openglVideoParam.VBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, openglVideoParam.EBO); + 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))); + glEnableVertexAttribArray(1); + glGenTextures(3, openglVideoParam.texs); + for (int i = 0; i < 3; i++) + { + glBindTexture(GL_TEXTURE_2D, openglVideoParam.texs[i]); + 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); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } - shaderService = new ShaderService{vSource.data(), fSource.data()}; - shaderService->Use(); - shaderService->SetUniform("textureY", 0); - shaderService->SetUniform("textureU", 1); - shaderService->SetUniform("textureV", 2); - return 0; + shaderService = new ShaderService{ vSource.data(), fSource.data() }; + shaderService->Use(); + shaderService->SetUniform("textureY", 0); + shaderService->SetUniform("textureU", 1); + shaderService->SetUniform("textureV", 2); + return 0; } -void OpenglRender(DecoderParam &decoderParam, OpenglVideoParam &openglVideoParam, ShaderService *shaderService) +void OpenglRender(DecoderParam& decoderParam, const OpenglVideoParam& openglVideoParam, ShaderService* shaderService) { - auto frame = RequestFrame(decoderParam); - if(frame == nullptr) - return; - int64_t pts = frame->pts; - static bool first_frame = true; - // TODO: TIMER - glBindTexture(GL_TEXTURE_2D, openglVideoParam.texs[0]); - glPixelStoref(GL_UNPACK_ROW_LENGTH, frame->linesize[0]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, frame->width, frame->height, 0, GL_RED, GL_UNSIGNED_BYTE, frame->data[0]); + 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]); + 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]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, frame->width / 2, frame->height / 2, 0, GL_RED, GL_UNSIGNED_BYTE, frame->data[1]); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, openglVideoParam.texs[1]); + glPixelStoref(GL_UNPACK_ROW_LENGTH, 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]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, frame->width / 2, frame->height / 2, 0, GL_RED, GL_UNSIGNED_BYTE, frame->data[2]); + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, openglVideoParam.texs[2]); + glPixelStoref(GL_UNPACK_ROW_LENGTH, 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]); - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + av_frame_free(&frame); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - shaderService->Use(); - glBindVertexArray(openglVideoParam.VAO); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); - av_frame_free(&frame); + shaderService->Use(); + glBindVertexArray(openglVideoParam.VAO); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); } -int main(int argc, char **const argv) +int main(int argc, char** const argv) { - // Check File - const char *targetFilepath = argv[1]; - if (targetFilepath == nullptr || !std::filesystem::exists(targetFilepath)) - { - cout << "File Not Exist\n"; - return 0; - } - const FileType fileType = Util::GetFileType(targetFilepath); - if (fileType == FileType::ERRORTYPE) - { - cout << "unsupport file type\n"; - return 0; - } + // Check File + const char* targetFilepath = argv[1]; + if (targetFilepath == nullptr || !std::filesystem::exists(targetFilepath)) + { + cout << "File Not Exist\n"; + return 0; + } + const FileType fileType = Util::GetFileType(targetFilepath); + if (fileType == FileType::ERRORTYPE) + { + cout << "unsupport file type\n"; + return 0; + } - // INIT + // INIT - int client_width, client_height; - SDL_Window *window = nullptr; - DecoderParam decoderParam{}; - OpenglVideoParam openglVideoParam{}; - ShaderService *shaderService = nullptr; - double framerate = .0f; - if (SDL_Init(SDL_INIT_EVERYTHING) < 0) - { - cout << SDL_GetError() << "\n"; - return -1; - } - switch (fileType) - { - case FileType::VIDEO: - { - InitVideo(window, targetFilepath, decoderParam, openglVideoParam, shaderService); - auto& time_base = decoderParam.fmtCtx->streams[decoderParam.videoStreamIndex]->time_base; - framerate = (double)time_base.num / time_base.den; - break; - } - case FileType::IMG: - { - break; - } - case FileType::MUSIC: - { - break; - } - default: - return -1; - } + int client_width, client_height; + SDL_Window* window = nullptr; + DecoderParam decoderParam{}; + OpenglVideoParam openglVideoParam{}; + ShaderService* shaderService = nullptr; + double framerate = .0f; + if (SDL_Init(SDL_INIT_EVERYTHING) < 0) + { + cout << SDL_GetError() << "\n"; + return -1; + } + switch (fileType) + { + case FileType::VIDEO: + { + InitVideo(window, targetFilepath, decoderParam, openglVideoParam, shaderService); + auto& time_base = decoderParam.fmtCtx->streams[decoderParam.videoStreamIndex]->time_base; + framerate = (double)time_base.num / time_base.den; + break; + } + case FileType::IMG: + { + break; + } + case FileType::MUSIC: + { + break; + } + default: + return -1; + } - bool quit = false; - auto current_time = std::chrono::system_clock::now(); - SDL_Event event; - while (!quit) - { - while (SDL_PollEvent(&event)) - { - switch (event.type) - { - case SDL_KEYDOWN: - switch (event.key.keysym.scancode) - { - case SDL_SCANCODE_ESCAPE: - return -1; - default: - break; - } - break; - case SDL_QUIT: - return -1; - default: - break; - } - } + bool quit = false; + auto current_time = std::chrono::system_clock::now(); + SDL_Event event; + while (!quit) + { + while (SDL_PollEvent(&event)) + { + switch (event.type) + { + case SDL_KEYDOWN: + switch (event.key.keysym.scancode) + { + case SDL_SCANCODE_ESCAPE: + return -1; + default: + break; + } + break; + case SDL_QUIT: + return -1; + default: + break; + } + } - // Render - switch (fileType) - { - case FileType::VIDEO: - OpenglRender(decoderParam, openglVideoParam, shaderService); - SDL_GL_SwapWindow(window); - std::this_thread::sleep_until(current_time + std::chrono::milliseconds((int)(framerate * 1000))); - current_time = std::chrono::system_clock::now(); - break; + // Render + switch (fileType) + { + case FileType::VIDEO: + OpenglRender(decoderParam, openglVideoParam, shaderService); + SDL_GL_SwapWindow(window); + std::this_thread::sleep_until(current_time + std::chrono::milliseconds((int)(framerate * 1000))); + current_time = std::chrono::system_clock::now(); + break; - default: - break; - } - } + default: + break; + } + } - avcodec_close(decoderParam.codecCtx); - avformat_close_input(&(decoderParam.fmtCtx)); - SDL_GL_DeleteContext(openglVideoParam.glContext); - SDL_DestroyWindow(window); - SDL_Quit(); - return 0; -} + avcodec_close(decoderParam.codecCtx); + avformat_close_input(&(decoderParam.fmtCtx)); + SDL_GL_DeleteContext(openglVideoParam.glContext); + SDL_DestroyWindow(window); + SDL_Quit(); + return 0; +} \ No newline at end of file diff --git a/src/decoder.cc b/src/decoder.cc index 2ba4dd2..3966c2d 100644 --- a/src/decoder.cc +++ b/src/decoder.cc @@ -1,52 +1,59 @@ #include "decoder.h" -void InitDecoder(const char* filepath, DecoderParam& param){ - AVFormatContext* fmtCtx = nullptr; - AVCodecContext* codecFmt = nullptr; - auto ret = avformat_open_input(&fmtCtx, filepath, NULL, NULL); - avformat_find_stream_info(fmtCtx, nullptr); +void InitDecoder(const char* filepath, DecoderParam& param) { + AVFormatContext* fmtCtx = nullptr; + AVCodecContext* codecFmt = nullptr; + auto ret = avformat_open_input(&fmtCtx, filepath, NULL, NULL); + avformat_find_stream_info(fmtCtx, nullptr); - for(int i=0; inb_streams; i++){ - auto stream = fmtCtx->streams[i]; - auto codec = avcodec_find_decoder(stream->codecpar->codec_id); - if(codec->type == AVMEDIA_TYPE_VIDEO){ - param.videoStreamIndex = i; - codecFmt = avcodec_alloc_context3(codec); - avcodec_parameters_to_context(codecFmt, stream->codecpar); - avcodec_open2(codecFmt, codec, nullptr); - } - } + for (int i = 0; i < fmtCtx->nb_streams; i++) { + const auto stream = fmtCtx->streams[i]; + const auto codec = avcodec_find_decoder(stream->codecpar->codec_id); + if (codec->type == AVMEDIA_TYPE_VIDEO) { + param.videoStreamIndex = i; + codecFmt = avcodec_alloc_context3(codec); + avcodec_parameters_to_context(codecFmt, stream->codecpar); + avcodec_open2(codecFmt, codec, nullptr); + } + } - param.codecCtx = codecFmt; - param.fmtCtx = fmtCtx; - param.width = codecFmt->width; - param.height = codecFmt->height; + param.codecCtx = codecFmt; + param.fmtCtx = fmtCtx; + param.width = codecFmt->width; + param.height = codecFmt->height; } -AVFrame* RequestFrame(DecoderParam& param){ - auto& fmtCtx = param.fmtCtx; - auto& codecCtx = param.codecCtx; - auto& videoStreamIndex = param.videoStreamIndex; +AVFrame* RequestFrame(DecoderParam& param) { + const auto& fmtCtx = param.fmtCtx; + const auto& codecCtx = param.codecCtx; + const auto& videoStreamIndex = param.videoStreamIndex; - while(true){ - AVPacket* packet = av_packet_alloc(); - int ret = av_read_frame(fmtCtx, packet); - if(ret == 0 && packet->stream_index == videoStreamIndex){ - ret = avcodec_send_packet(codecCtx, packet); - if(ret == 0){ - AVFrame* frame = av_frame_alloc(); - ret = avcodec_receive_frame(codecCtx, frame); - if(ret == 0){ - av_packet_unref(packet); - return frame; - }else if(ret == AVERROR(EAGAIN)){ - av_frame_unref(frame); - }else{ - return nullptr; - } - } - } - av_packet_unref(packet); - } - return nullptr; -} + AVPacket* packet = av_packet_alloc(); + AVFrame* frame = av_frame_alloc(); + + while (true) { + int ret = av_read_frame(fmtCtx, packet); + if (ret == 0 && packet->stream_index == videoStreamIndex) { + ret = avcodec_send_packet(codecCtx, packet); + if (ret == 0) { + ret = avcodec_receive_frame(codecCtx, frame); + if (ret == 0) { + av_packet_unref(packet); + return frame; + } + if (ret == AVERROR(EAGAIN)) { + continue; + } + av_frame_free(&frame); + av_packet_free(&packet); + return nullptr; + } + } + else if (ret == AVERROR_EOF) + { + av_packet_unref(packet); + return nullptr; + } + av_packet_unref(packet); + } +} \ No newline at end of file