cmd로 ffmpeg를 사용하자니 불편해서 대신 명령어를 입력해주는 프로그램을 WPF로 만들었다.
하다보니 약간의 편집기능도 추가하고 썸네일을 추출하거나 gif 로 변환하는 기능까지 추가
ffmpeg 를 대신 실행해주는 프로그램이기 때문에 ffmpeg는 여기서( https://ffmpeg.org/ ) 받아야 한다.
cmd로 ffmpeg를 사용하자니 불편해서 대신 명령어를 입력해주는 프로그램을 WPF로 만들었다.
하다보니 약간의 편집기능도 추가하고 썸네일을 추출하거나 gif 로 변환하는 기능까지 추가
ffmpeg 를 대신 실행해주는 프로그램이기 때문에 ffmpeg는 여기서( https://ffmpeg.org/ ) 받아야 한다.
오래전 ios에 라이브 포토가 나오고 잠금화면 배경화면으로 동영상을 설정하고 싶었다.
그때 당시에는 원본 파일의 확장자 때문인지 코덱 때문인지 여러 프로그램들에서 파일 열기 부터 실패
그 이후로 스팀이나 험블에서 영상편집 프로그램이 할인하거나 번들로 나오면 사놨었다.
시간이 흘러 다시 동영상을 자르고 싶어졌는데 원하는 것은 재인코딩 없이 필요한 부분만 자르기
하지만 시간이 너무 흘러 버렸다.
- Movavi Video Suite 17
스팀에서 할인할때 사놨었는데 오래전 버전이라 h265는 지원 불가
비디오 분할 기능은 앞부분이 포함되면 높은 확률로 작동, 앞부분을 버리고 싶을때는 높은 확률로 작동하지 않는다.
비디오 변환 기능으로 mkv를 mov로 만드는건 성공 했지만 ios17의 라이브 포토 배경화면은 제한사항이 조금 많은듯
- VEGAS Pro 14 Edit
험블에서 번들로 나왔을때 사놨었는데 매직스나 베가스 홈페이지에서는 최신버전 정보만 나와서 지원 코덱이나 해상도를 알수 없어서 설치하지 않고 패스
- Fastcut
역시 험블에서 번들로 샀었는데 매직스 홈페이지에서는 자세한 정보를 찾을수 없고 예전에 라이브 포토를 만드려다가 실패했던 프로그램이 이것이었던 걸로 추정되어서 패스
- Shotcut
프리웨어에 오픈소스 프로그램
4K, 8K, h264, h265 뭐든 잘 작동
하지만 재인코딩을 꼭 거친다. OTL
- FFmpeg
Shotcut 설치 폴더에 있는 ffmpeg.exe 를 보고 구글링 시작
SET FFMPEG_PATH="E:\\Util\\Shotcut\\ffmpeg.exe"
SET IN_FILE="E:\\aaa\\111.mp4"
SET OUT_FILE="E:\\aaa\\111_cut.mp4"
SET START_TIME=00:10:00.000
SET END_TIME=00:20:00.000
%FFMPEG_PATH% -i %IN_FILE% -ss %START_TIME% -to %END_TIME% -movflags +faststart -c copy %OUT_FILE%
재인코딩 없이 동영상 파일 자르기 완료!
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
위 에러 메시지로 인터넷을 검색하면 dll과 dll을 사용하는 프로젝트간의 함수 호출 규칙(cdecl, stdcall)이 달라서 발생하고 동일하게 맞춰주면 해결된다고만 나오지만 근본적으로는 함수 호출할때와 호출 끝났을때의 콜 스택이 달라졌을때 발생한다.
호출 규칙이 같아도 해당 에러메시지가 발생하는 경우는 아래와 같이 라이브러리와 라이브러리를 사용하는 프로젝트의 헤더가 달라서 가상함수 테이블이 다르고 전달인자가 다른 함수를 호출하게 되는 경우가 있다.
* 라이브러리 프로젝트 TestLibClass.h
#pragma once
class TestLibClass
{
public:
TestLibClass();
virtual ~TestLibClass();
virtual void aaa();
#ifdef BBB
virtual void bbb();
#endif
virtual void ccc();
virtual void ddd(int a);
};
* 라이브러리 프로젝트 TestLibClass.cpp
#include "pch.h"
#include <iostream>
#include "TestLibClass.h"
TestLibClass::TestLibClass()
{
}
TestLibClass::~TestLibClass()
{
}
void TestLibClass::aaa()
{
std::cout << "AAA" << std::endl;
}
#ifdef BBB
void TestLibClass::bbb()
{
std::cout << "BBB : " << std::endl;
}
#endif
void TestLibClass::ccc()
{
std::cout << "CCC" << std::endl;
}
void TestLibClass::ddd(int a)
{
std::cout << "DDD" << a << std::endl;
}
* 라이브러리를 사용하는 프로젝트의 main.cpp
#define BBB
#include "../TestLib/TestLibClass.h"
int main(void)
{
TestLibClass* pTest = new TestLibClass();
pTest->ccc();
delete pTest;
return 0;
}
라이브러리에는 BBB 가 정의되거나 전처리기에 추가되지 않아서 bbb()가 제거된 상태로 빌드되고
라이브러리를 사용하는 프로젝트에서는 BBB를 정의한 다음 해더를 포함했기 때문에 bbb()가 있는걸로 인식되어 ccc()를 호출하면 ddd(int a)가 호출된다.
pTest->ccc(); 에 중단점을 걸고 가상함수 테이블을 보면 아래와 같이 bbb()는 없고 끝에 널포인터가 하나 더 있다.
해당 라인에서 디스어셈블리로 이동을 해서 esi 와 esp의 값을 보면 아래와 같은데
함수 호출 후에는 아래와 같이 값이 변하고
__RTC_CheckEsp (0E012EEh) 에서 esi, esp값을 체크할 때 실패해서 Run-Time Check Failure #0 에러가 뜨게 된다.
ps. ddd(int a)를 ddd()로 수정해서 전달인자가 같은 경우에는 __RTC_CheckEsp를 문제없이 통과하지만 ccc()가 아닌ddd()가 호출된다.
ps2. ddd(int a)가 아예 없거나 ccc()대신 ddd(int a)를 호출한 경우에는 널포인터를 참조하게 되어 아래 에러가 뜬다.
"예외 발생(0x00000000, Test1.exe): 0xC0000005: 0x00000000 위치를 실행하는 동안 액세스 위반이 발생했습니다.."