ffmpeg demuxer 를 사용해서 rtsp client 를 구현할때 접속이 되지않으면 avformat_open_input 에서 무한 블러킹이 걸린다. 이때 아래와 같이 타임아웃을 주면 avformat_open_input 을 빠져나올수 있다.
AVDictionary* dicts = NULL;
av_dict_set(&dicts, "stimeout", "2000000", 0);
int err = avformat_open_input(&m_pFormatCtx, filepath, NULL, &dicts);
2019년 11월 14일 목요일
avformat_open_input rtsp connection timeout 주기
2019년 7월 10일 수요일
c# 시스템 메모리 사용량 구하기
전체 메모리 사용량 구하는 법을 검색해봤는데 의외로 쓸만한 소스가 없었다.
겨우 찾아낸 이 방법이 제일 나은것 같다.
출처 - https://ash84.net/2012/03/03/c-wmi-eb-a5-bc--ec-9d-b4-ec-9a-a9-ed-95-9c--ed-98-84-ec-9e-ac--eb-a9-94-eb-aa-a8-eb-a6-ac--ec-82-ac-ec-9a-a9-eb-9f-89--ea-b5-ac-ed-95-98-ea-b8-b0/
프로세스 메모리 사용량이 아닌 작업관리자에 나오는 시스템 메모리 사용량 체크 소스이다.
겨우 찾아낸 이 방법이 제일 나은것 같다.
출처 - https://ash84.net/2012/03/03/c-wmi-eb-a5-bc--ec-9d-b4-ec-9a-a9-ed-95-9c--ed-98-84-ec-9e-ac--eb-a9-94-eb-aa-a8-eb-a6-ac--ec-82-ac-ec-9a-a9-eb-9f-89--ea-b5-ac-ed-95-98-ea-b8-b0/
프로세스 메모리 사용량이 아닌 작업관리자에 나오는 시스템 메모리 사용량 체크 소스이다.
private uint GetTotalUsedMemory()
{
ManagementClass cls = new ManagementClass("Win32_OperatingSystem");
ManagementObjectCollection instances = cls.GetInstances();
foreach (ManagementObject info in instances)
{
int total_physical_memeory = int.Parse(info["TotalVisibleMemorySize"].ToString());
int free_physical_memeory = int.Parse(info["FreePhysicalMemory"].ToString());
int remain_physical_memory = total_physical_memeory - free_physical_memeory;
Console.WriteLine("Memory Information ================================");
Console.WriteLine("Total Physical Memory :{0:#,###} KB", info["TotalVisibleMemorySize"]);
Console.WriteLine("Free Physical Memory :{0:#,###} MB", info["FreePhysicalMemory"]);
Console.WriteLine("Memory Usage Percent = {0} %", 100 * remain_physical_memory / total_physical_memeory);
Console.WriteLine("Remain Physical Memory : {0:#,###}", remain_physical_memory);
return (uint)(remain_physical_memory / 1000);
}
return 0;
2019년 7월 4일 목요일
c# unix timestamp local DateTime 으로 변환
int timestamp; // unix timestamp
DateTime dateTimeTimestamp;
...
dateTimeTimestamp = new DateTime(1970, 1, 1).AddSeconds(timestamp);
dateTimeTimestamp += TimeZone.CurrentTimeZone.GetUtcOffset(dateTimeTimestamp);
DateTime dateTimeTimestamp;
...
dateTimeTimestamp = new DateTime(1970, 1, 1).AddSeconds(timestamp);
dateTimeTimestamp += TimeZone.CurrentTimeZone.GetUtcOffset(dateTimeTimestamp);
2019년 7월 2일 화요일
c# simple thread-safe Log Writer
싱글턴 패턴으로된 로그파일을 생성해주는 클래스이다.
로그파일은 날짜별로 생성되고 각 로그 시간을 함께 찍어준다.
프로그램 시작시 StartDeleteLog / 종료시 StopDeleteLog 한다.
로그파일은 디폴트로 30일이 넘으면 삭제된다.
private LogWriter logWriter = LogWriter.Instance;
...
로그파일은 날짜별로 생성되고 각 로그 시간을 함께 찍어준다.
프로그램 시작시 StartDeleteLog / 종료시 StopDeleteLog 한다.
로그파일은 디폴트로 30일이 넘으면 삭제된다.
1: using System;
2: using System.Collections.Generic;
3: using System.IO;
4: using System.Linq;
5: using System.Text;
6: using System.Threading;
7: using System.Threading.Tasks;
8:
9: namespace MyLog
10: {
11: public enum LogType
12: {
13: Info,
14: Exception,
15: Error
16: }
17:
18: public class LogWriter
19: {
20: public delegate void LogWriteHandlerFunc(LogType logType, DateTime logTime, string logMessage);
21: public LogWriteHandlerFunc LogWriteHandler;
22:
23: private static LogWriter instance = new LogWriter();
24: public static LogWriter Instance { get { return instance; } }
25:
26: private object objLogLock = new object();
27:
28: private const string LOG_PATH = @"C:\Log\";
29: private const string LOG_FILENAME = @"log";
30:
31: private Thread threadDeleteLog;
32: private bool bThreadDeleteLogRun = false;
33: private int logDeleteDays = 30;
34:
35: public void StartDeleteLog(int days)
36: {
37: if (!bThreadDeleteLogRun)
38: {
39: logDeleteDays = days;
40: bThreadDeleteLogRun = true;
41: threadDeleteLog = new Thread(new ThreadStart(ThreadDeleteLog));
42: threadDeleteLog.IsBackground = true;
43: threadDeleteLog.Start();
44: }
45: }
46:
47: public void StopDeleteLog()
48: {
49: if (threadDeleteLog != null)
50: {
51: bThreadDeleteLogRun = false;
52: threadDeleteLog.Join();
53: }
54: }
55:
56: private void ThreadDeleteLog()
57: {
58: CheckLogPath(LOG_PATH);
59:
60: DateTime lastTime = DateTime.MinValue;
61:
62: while (bThreadDeleteLogRun)
63: {
64: DateTime now = DateTime.Now;
65: double diff = (now - lastTime).TotalHours;
66: if (diff < 0) diff = 0;
67:
68: if (diff > 24)
69: {
70: try
71: {
72: string[] filepaths = Directory.GetFiles(LOG_PATH, "*.txt");
73: DeleteLogFiles(now, filepaths);
74: }
75: catch (Exception ex)
76: {
77: WriteLog(LogType.Exception, ex.ToString());
78: }
79:
80: lastTime = now;
81: }
82:
83: Thread.Sleep(100);
84: }
85: }
86:
87: private void DeleteLogFiles(DateTime now, string[] filepaths)
88: {
89: foreach (string filepath in filepaths)
90: {
91: try
92: {
93: DateTime date = File.GetCreationTime(filepath);
94: if ((now - date).TotalDays > logDeleteDays)
95: {
96: File.Delete(filepath);
97: }
98: }
99: catch (Exception ex)
100: {
101: WriteLog(LogType.Exception, ex.ToString());
102: }
103: }
104: }
105:
106: public void WriteLog(LogType logType, string log)
107: {
108: try
109: {
110: lock (objLogLock)
111: {
112: Console.WriteLine(log);
113:
114: string filepath = LOG_PATH;
115:
116: CheckLogPath(filepath);
117:
118: DateTime dateTime = DateTime.Now;
119: string strDate = dateTime.ToString("yyyyMMdd");
120: string strDateTime = dateTime.ToString("yyyy-MM-dd HH:mm:ss.fff");
121:
122: filepath = string.Format("{0}{1}_{2}.txt", filepath, LOG_FILENAME, strDate);
123: string logMessage = string.Format("{0} [{1}] {2}", strDateTime, logType, log);
124:
125: using (StreamWriter sw = File.AppendText(filepath))
126: {
127: sw.WriteLine(logMessage);
128: sw.WriteLine("---------------------------------------------------------------------------------------\r");
129: sw.Flush();
130: }
131:
132: if (LogWriteHandler != null) LogWriteHandler(logType, dateTime, log);
133: }
134: }
135: catch (Exception ex)
136: {
137: Console.WriteLine(ex.ToString());
138: }
139: }
140:
141: private void CheckLogPath(string path)
142: {
143: try
144: {
145: if (!Directory.Exists(path))
146: Directory.CreateDirectory(path);
147: }
148: catch (Exception ex)
149: {
150: Console.WriteLine(ex.ToString());
151: }
152: }
153: }
154: }
155:
private LogWriter logWriter = LogWriter.Instance;
...
logWriter.StartDeleteLog(30);
...
logWriter.WriteLog(LogType.Info, "로그 시작...");
logWriter.WriteLog(LogType.Info, "로그 시작...");
...
logWriter.StopDeleteLog();
windeployqt 사용시 주의할 점
qt 배포용 파일들 담아주는 windeployqt 사용시 반드시 32/64 비트 확인할 것.
32비트 빌드는 32비트용 windeployqt 사용 => 32비트 qt dll 들 가져옴
64비트 빌드는 64비트용 windeployqt 사용 => 64비트 qt dll 들 가져옴
(QT 5.XX 32bit for Desktop / QT 5.XX 64bit for Desktop)
32비트 빌드는 32비트용 windeployqt 사용 => 32비트 qt dll 들 가져옴
64비트 빌드는 64비트용 windeployqt 사용 => 64비트 qt dll 들 가져옴
(QT 5.XX 32bit for Desktop / QT 5.XX 64bit for Desktop)
2019년 6월 3일 월요일
C# BeginInvoke/Invoke 동작 원리
c#으로 개발한 UI 기반 프로젝트에서 BeginInvoke/Invoke 에 대해 알아보자.
간단한 동작원리이지만 개발자들이 의외로 잘 모르고 사용하는 경우가 많다.
먼저 아래 링크에 아주 잘 설명되어 있다.
https://www.codeproject.com/Articles/10311/What-s-up-with-BeginInvoke
위 링크에서 하는 설명의 결론을 말하자면 컨트롤에서 BeginInvoke/Invoke 를 호출하는 순간 UI 메시지큐에 사용자 정의 메시지가 push 되고 해당 메시지에 대해 실행되는 메시지 핸들러 함수가 등록되는 원리이다.
외부 쓰레드에서 UI 쓰레드에서 실행되는 delegate 를 등록하여 비동기 실행을 하도록 한다는 것이다.
아래 폼을 보자.
폼 위에 여러가지 UI 요소들이 있다. 여기에 UI 쓰레드가 몇 개가 돌까?
정답은 1개 이다. 특별히 쓰레드를 생성해서 폼을 생성하지않는한 UI 쓰레드는 언제나 한 개이다.
이 말은 win32 API 로 프로그램을 개발했다고 가정했을때 메시지 큐를 처리하는 메시지 루프가 한 개 돌고있다는 말이다.
BeginInvoke를 호출할때 굳이 btnOpen.BeginInvoke 니 textStatus.BeginInvoke 등 처럼 UI 컨트롤 변수를 지정해줄 필요가 없으며 의미도 없다는 말이된다. (WPF 의 Dispatcher 도 마찬가지이다)
그냥 this.BeginInvoke 혹은 BeginInvoke 로 호출하면된다.
Invoke 의 경우 쓰레드 동기화를 위해 이를 호출한 외부 쓰레드에서 delegate 타입의 이벤트 핸들러 함수가 끝날때까지 Sleep 상태로 기다렸다가 함수 실행이 끝나면 다음 코드가 진행되는 방식이다.
Invoke 함수의 경우 폼이 종료된 후 호출되면 UI 쓰레드가 종료된 이후이기 때문에 데드락에 빠지는 경우가 생긴다. 따라서 분명한 이유가 없으면 Invoke보다 BeginInvoke 사용을 권장한다.
간단한 동작원리이지만 개발자들이 의외로 잘 모르고 사용하는 경우가 많다.
먼저 아래 링크에 아주 잘 설명되어 있다.
https://www.codeproject.com/Articles/10311/What-s-up-with-BeginInvoke
위 링크에서 하는 설명의 결론을 말하자면 컨트롤에서 BeginInvoke/Invoke 를 호출하는 순간 UI 메시지큐에 사용자 정의 메시지가 push 되고 해당 메시지에 대해 실행되는 메시지 핸들러 함수가 등록되는 원리이다.
외부 쓰레드에서 UI 쓰레드에서 실행되는 delegate 를 등록하여 비동기 실행을 하도록 한다는 것이다.
아래 폼을 보자.
폼 위에 여러가지 UI 요소들이 있다. 여기에 UI 쓰레드가 몇 개가 돌까?
정답은 1개 이다. 특별히 쓰레드를 생성해서 폼을 생성하지않는한 UI 쓰레드는 언제나 한 개이다.
이 말은 win32 API 로 프로그램을 개발했다고 가정했을때 메시지 큐를 처리하는 메시지 루프가 한 개 돌고있다는 말이다.
BeginInvoke를 호출할때 굳이 btnOpen.BeginInvoke 니 textStatus.BeginInvoke 등 처럼 UI 컨트롤 변수를 지정해줄 필요가 없으며 의미도 없다는 말이된다. (WPF 의 Dispatcher 도 마찬가지이다)
그냥 this.BeginInvoke 혹은 BeginInvoke 로 호출하면된다.
Invoke 의 경우 쓰레드 동기화를 위해 이를 호출한 외부 쓰레드에서 delegate 타입의 이벤트 핸들러 함수가 끝날때까지 Sleep 상태로 기다렸다가 함수 실행이 끝나면 다음 코드가 진행되는 방식이다.
Invoke 함수의 경우 폼이 종료된 후 호출되면 UI 쓰레드가 종료된 이후이기 때문에 데드락에 빠지는 경우가 생긴다. 따라서 분명한 이유가 없으면 Invoke보다 BeginInvoke 사용을 권장한다.
2019년 5월 20일 월요일
C# 프로젝트에 ocx 수동 삽입하기 - Inserting ocx into c# project manually
c# 프로젝트(윈폼/WPF)에 ocx 파일을 삽입할때 보통 UI 에서 추가하는데 이렇게 하면 참조에 아래 2개의 dll 이 자동 추가된다.
ocx 파일명 : DXMediaPlayer.ocx
참조 : AxInterop.DXMediaPlayerLib, Interop.DXMediaPlayerLib
위 2개의 참조경로를 따라면 보통 obj\Release(Debug) 아래 경로에 두 dll을 참조하고 실행경로에 복사되는데 이것은 좋은 방법이 아니다.
보통 obj 경로는 git 으로 관리하지않기 때문에 경우에 따라 참조파일을 잃어버릴수 있고 실행경로에 두 dll 파일이 없으면 실행파일이 ocx 를 사용할 수 없는 예외가 발생한다.
따라서 아래와 같은 방법으로 ocx 를 수동으로 추가하는 방법을 사용할 수 있다.
1. 시작 -> 모든 프로그램 -> Visual Studio 20XX -> Visual Studio Tools -> Developer Command Prompt for VS 20XX 실행
2. ocx 파일 경로로 이동
3. 경로>aximp /source DXMediaPlayer.ocx 실행
4. AxDXMediaPlayerLib.cs 파일과 DXMediaPlayerLib.dll, AxDXMediaPlayerLib.dll 3개의 파일이 생성된다
5. 이 중 AxDXMediaPlayerLib.cs, DXMediaPlayerLib.dll 두 개의 파일을 삽입을 원하는 프로젝트 경로로 복사
6. 프로젝트 참조에 DXMediaPlayerLib.dll 추가, 소스에 AxDXMediaPlayerLib.cs 추가
7. 빌드 후 Assembly.cs 파일에 버전에러 발생하면 해당 라인 주석처리
이렇게 추가하면 실행경로에 dll 파일이 없어도 실행가능하다.
ocx 파일명 : DXMediaPlayer.ocx
참조 : AxInterop.DXMediaPlayerLib, Interop.DXMediaPlayerLib
위 2개의 참조경로를 따라면 보통 obj\Release(Debug) 아래 경로에 두 dll을 참조하고 실행경로에 복사되는데 이것은 좋은 방법이 아니다.
보통 obj 경로는 git 으로 관리하지않기 때문에 경우에 따라 참조파일을 잃어버릴수 있고 실행경로에 두 dll 파일이 없으면 실행파일이 ocx 를 사용할 수 없는 예외가 발생한다.
따라서 아래와 같은 방법으로 ocx 를 수동으로 추가하는 방법을 사용할 수 있다.
1. 시작 -> 모든 프로그램 -> Visual Studio 20XX -> Visual Studio Tools -> Developer Command Prompt for VS 20XX 실행
2. ocx 파일 경로로 이동
3. 경로>aximp /source DXMediaPlayer.ocx 실행
4. AxDXMediaPlayerLib.cs 파일과 DXMediaPlayerLib.dll, AxDXMediaPlayerLib.dll 3개의 파일이 생성된다
5. 이 중 AxDXMediaPlayerLib.cs, DXMediaPlayerLib.dll 두 개의 파일을 삽입을 원하는 프로젝트 경로로 복사
6. 프로젝트 참조에 DXMediaPlayerLib.dll 추가, 소스에 AxDXMediaPlayerLib.cs 추가
7. 빌드 후 Assembly.cs 파일에 버전에러 발생하면 해당 라인 주석처리
이렇게 추가하면 실행경로에 dll 파일이 없어도 실행가능하다.
피드 구독하기:
글 (Atom)