多线程,偶尔崩溃

sheny沈 2013-05-06 09:56:26
要么就一直都正常运行,要么就是一开始就崩溃。各位大侠看看是不是多线程部分哪里写的不对,尤其是m_pProcessDll
// ----------------------------------------------------------------------
// 函数名: CVideoProcessDlgProvider::VideoProcess
// 作者:
// 描述: 对视频进行增强处理 采用多线程
// 返回值:
// [BOOL]
// 参数:
// [const string& command]
// [const string& video_path]
// ----------------------------------------------------------------------




int CVideoProcessDlgProvider::VideoProcess(const string& command, CWnd * wnd)
{
SYSTEM_INFO SystemInfo;
GetSystemInfo(&SystemInfo);


//1核的电脑创建一个线程0,两核创建两个线程,4核及以上,创建N-1个线程
HANDLE ThreadHandle[64];
if (SystemInfo.dwNumberOfProcessors<4 )
SystemInfo.dwNumberOfProcessors=SystemInfo.dwNumberOfProcessors;
else
SystemInfo.dwNumberOfProcessors=SystemInfo.dwNumberOfProcessors-1;
#ifdef _DEBUG
std::string dll_name = "ImageProcess\\" + command + "D.dll";
#else
std::string dll_name = "ImageProcess\\" + command + ".dll";
#endif

std::map<std::string, std::string> task_context;
task_context["Command"] = command;

if (m_pProcessDll != NULL)
{
delete m_pProcessDll;
m_pProcessDll = NULL;
}

// 创建视频处理dll指针


m_pProcessDll = new CImageProcessDll(dll_name);
if (!m_pProcessDll->IsActive())
{
delete m_pProcessDll;
m_pProcessDll = NULL;
return FAIL_STATE;
}

if (!m_pProcessDll->Init(task_context))
{
delete m_pProcessDll;
m_pProcessDll = NULL;
return FAIL_STATE;
}

if (!m_pProcessDll->Option(m_VideoImage.GetImage()))
{
delete m_pProcessDll;
m_pProcessDll = NULL;
return CANCEL_STATE;
}

// 获取视频总帧数,用于进度条
int frame_count=0;


for(DWORD i = 0; i < SystemInfo.dwNumberOfProcessors ; i++)
{
//打开视频文件
CvCapture * capture_ptr = NULL;
if (m_ProcessCount > 0)
{
capture_ptr = cvCaptureFromFile(m_DestVideo.c_str());
}
else
{
capture_ptr = cvCaptureFromFile(m_VideoPath.c_str());
}

if (!capture_ptr)
{
return FAIL_STATE;
}
frame_count = (int)cvGetCaptureProperty(capture_ptr, CV_CAP_PROP_FRAME_COUNT);

cvSetCaptureProperty(capture_ptr, CV_CAP_PROP_POS_FRAMES, i * frame_count/SystemInfo.dwNumberOfProcessors);


IplImage* src_image = cvQueryFrame(capture_ptr);

stParamVideoProcess* stParam = new stParamVideoProcess;
stParam->pThis= this;
stParam->capture_ptr = capture_ptr;
stParam->frame_count = frame_count/SystemInfo.dwNumberOfProcessors;
stParam->nProcessIndex = i;

ThreadHandle[i] = CreateThread(NULL, 0, VideoThreadProc, stParam, 0, NULL);
assert(ThreadHandle != INVALID_HANDLE_VALUE);
}



//CProgressWnd ProgressWnd(wnd, "进度", TRUE);//有取消
CProgressWnd ProgressWnd(wnd, "进度", FALSE);//没有取消
ProgressWnd.GoModal();
ProgressWnd.SetRange(0, frame_count);
ProgressWnd.SetText("正在进行视频增强处理。请稍候...");

int a=0;
while(1)
{
a=0;
int s=0;//处理了几个线程
for (int i=0;i<SystemInfo.dwNumberOfProcessors;i++)
{

a=a+num[i];
if (startprocess[i]==1)
s++;

}

ProgressWnd.SetPos(a);
ProgressWnd.PeekAndPump(FALSE);

if (s==SystemInfo.dwNumberOfProcessors)//判断几个线程是否执行完
break;

}
for (int b=0;b<SystemInfo.dwNumberOfProcessors;b++)
{
startprocess[b]=0;
num[b]=0;

}


//上面都是进度条的东西


WaitForMultipleObjects(SystemInfo.dwNumberOfProcessors, ThreadHandle, TRUE, INFINITE);
delete m_pProcessDll;
m_pProcessDll=NULL;//两个线程处理完以后删除指针

for (int i = 0; i < SystemInfo.dwNumberOfProcessors; i++)
{
CloseHandle(ThreadHandle[i]);
}
if (ProgressWnd.Cancelled())
{
return CANCEL_STATE;
}
m_ProcessCount++;
m_DestVideo = BuildDestVideo(m_ProcessCount);
return SUCCESS_STATE;
}

DWORD WINAPI CVideoProcessDlgProvider:: VideoThreadProc( LPVOID lpParameter)
{
stParamVideoProcess* stParam = (stParamVideoProcess*)lpParameter;

stParam->pThis->_VideoProcess2(stParam->capture_ptr,stParam->frame_count, stParam->nProcessIndex);
delete stParam;
return 0;
}

//线程

int CVideoProcessDlgProvider::_VideoProcess2(CvCapture * capture_ptr,
int frame_count, int nProcessIndex)

{

// 获取视频宽度
int frame_width = (int)cvGetCaptureProperty(capture_ptr, CV_CAP_PROP_FRAME_WIDTH);

// 获取视频高度
int frame_height = (int)cvGetCaptureProperty(capture_ptr, CV_CAP_PROP_FRAME_HEIGHT);

// 获取视频总帧数
//int frame_count = (int)cvGetCaptureProperty(capture_ptr, CV_CAP_PROP_FRAME_COUNT);

// 获取视频帧率
int fps = (int)cvGetCaptureProperty(capture_ptr, CV_CAP_PROP_FPS);

std::string temp_dest_video;

string tempIndex;
ostringstream oss;
oss<<nProcessIndex;
tempIndex=oss.str();
temp_dest_video = temp_dir + "\\Processed"+tempIndex+".avi";



//如果是镜头畸变校正,需要增大目标图像缓存区
CvSize video_size;
CvVideoWriter * video_writer;
video_size = cvSize(frame_width, frame_height);
video_writer = cvCreateVideoWriter(temp_dest_video.c_str(), CV_FOURCC('X', 'V', 'I', 'D'), fps, video_size);

if (!video_writer)
{
cvReleaseCapture(&capture_ptr);
return FAIL_STATE;
}




// 循环处理,对每一帧图像进行视频增强
int cur_frame = 0;
BOOL break_flag = FALSE;
IplImage * dst_image = NULL;
IplImage* src_image=NULL;
num[nProcessIndex]=0;
while (cur_frame < frame_count)
{
src_image = cvQueryFrame(capture_ptr);
cur_frame++;
num[nProcessIndex]++;//把每个线程处理了多少帧,传出去
if (!src_image)
{
break;
}

if (!dst_image)
{
dst_image = cvCreateImage(video_size, src_image->depth, src_image->nChannels);
}

if (m_pProcessDll->Process(src_image, dst_image))
{
// 视频增强结果输出
cvWriteFrame(video_writer, dst_image);
}



}

if (dst_image)
{
cvReleaseImage(&dst_image);
}
cvReleaseVideoWriter(&video_writer);
cvReleaseCapture(&capture_ptr);


m_tempDestVideo = BuildtempDestVideo(nProcessIndex);

::MoveFile(temp_dest_video.c_str(), m_tempDestVideo.c_str());


startprocess[nProcessIndex]=1;
return SUCCESS_STATE;
}
...全文
331 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
Star-light 2013-05-07
  • 打赏
  • 举报
回复
引用 5 楼 sheny1110 的回复:
[quote=引用 4 楼 zdarkalone 的回复:] 代码没怎么看,但有如下建议: opencv的cv::Capture不支持多线程,请用一个线程读写文件 请保证程序其他部分heap使用正确无误,有时候是别的地方出错了,然后opencv报错
偶尔出错,就是要不同的capture啊,是分段处理,最后合起来[/quote] 那就对cv::Capture的读写加锁
  • 打赏
  • 举报
回复
看代码就看晕了。。。实在不想看
赵4老师 2013-05-07
  • 打赏
  • 举报
回复
崩溃的时候在弹出的对话框按相应按钮进入调试,按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处。 判断是否越界访问,可以在数组的最后一个元素之后对应的地址处设置数据读写断点。如果该地址对应其它变量干扰判断,可将数组多声明一个元素,并设置数据读写断点在该多出元素对应的地址上。 特供调试多线程程序使用:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
    #include <windows.h>
    #include <io.h>
#else
    #include <unistd.h>
    #include <sys/time.h>
    #include <pthread.h>
    #define  CRITICAL_SECTION   pthread_mutex_t
    #define  _vsnprintf         vsnprintf
#endif
//Log{
#define MAXLOGSIZE 20000000
#define MAXLINSIZE 16000
#include <time.h>
#include <sys/timeb.h>
#include <stdarg.h>
char logfilename1[]="MyLog1.log";
char logfilename2[]="MyLog2.log";
static char logstr[MAXLINSIZE+1];
char datestr[16];
char timestr[16];
char mss[4];
CRITICAL_SECTION cs_log;
FILE *flog;
#ifdef WIN32
void Lock(CRITICAL_SECTION *l) {
    EnterCriticalSection(l);
}
void Unlock(CRITICAL_SECTION *l) {
    LeaveCriticalSection(l);
}
#else
void Lock(CRITICAL_SECTION *l) {
    pthread_mutex_lock(l);
}
void Unlock(CRITICAL_SECTION *l) {
    pthread_mutex_unlock(l);
}
#endif
void LogV(const char *pszFmt,va_list argp) {
    struct tm *now;
    struct timeb tb;

    if (NULL==pszFmt||0==pszFmt[0]) return;
    _vsnprintf(logstr,MAXLINSIZE,pszFmt,argp);
    ftime(&tb);
    now=localtime(&tb.time);
    sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday);
    sprintf(timestr,"%02d:%02d:%02d",now->tm_hour     ,now->tm_min  ,now->tm_sec );
    sprintf(mss,"%03d",tb.millitm);
    printf("%s %s.%s %s",datestr,timestr,mss,logstr);
    flog=fopen(logfilename1,"a");
    if (NULL!=flog) {
        fprintf(flog,"%s %s.%s %s",datestr,timestr,mss,logstr);
        if (ftell(flog)>MAXLOGSIZE) {
            fclose(flog);
            if (rename(logfilename1,logfilename2)) {
                remove(logfilename2);
                rename(logfilename1,logfilename2);
            }
        } else {
            fclose(flog);
        }
    }
}
void Log(const char *pszFmt,...) {
    va_list argp;

    Lock(&cs_log);
    va_start(argp,pszFmt);
    LogV(pszFmt,argp);
    va_end(argp);
    Unlock(&cs_log);
}
//Log}
int main(int argc,char * argv[]) {
    int i;
#ifdef WIN32
    InitializeCriticalSection(&cs_log);
#else
    pthread_mutex_init(&cs_log,NULL);
#endif
    for (i=0;i<10000;i++) {
        Log("This is a Log %04d from FILE:%s LINE:%d\n",i, __FILE__, __LINE__);
    }
#ifdef WIN32
    DeleteCriticalSection(&cs_log);
#else
    pthread_mutex_destroy(&cs_log);
#endif
    return 0;
}
sheny沈 2013-05-06
  • 打赏
  • 举报
回复
没人回额,可能10多次才出错一次,我现在运行半天都没出错,咋办啊
sheny沈 2013-05-06
  • 打赏
  • 举报
回复
引用 4 楼 zdarkalone 的回复:
代码没怎么看,但有如下建议: opencv的cv::Capture不支持多线程,请用一个线程读写文件 请保证程序其他部分heap使用正确无误,有时候是别的地方出错了,然后opencv报错
偶尔出错,就是要不同的capture啊,是分段处理,最后合起来
Star-light 2013-05-06
  • 打赏
  • 举报
回复
代码没怎么看,但有如下建议: opencv的cv::Capture不支持多线程,请用一个线程读写文件 请保证程序其他部分heap使用正确无误,有时候是别的地方出错了,然后opencv报错
sheny沈 2013-05-06
  • 打赏
  • 举报
回复
引用 2 楼 dahuaixiaohuai 的回复:
这是线程函数吗?
process是总的函数,调用_process2这个线程函数
一叶之舟 2013-05-06
  • 打赏
  • 举报
回复
这是线程函数吗?

64,643

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧