前两天搞定了本机的视频截图
感觉还达不到项目要求
今天尝试一下把所有功能整合一下
可传输mp4的live555服务器 + opencv 实现视频截图
首先live555是不支持mp4格式的,于是我查找使他可以传输mp4文件的方法
下面这篇文章实现了这个功能
http://blog.csdn.net/c_m_deng/article/details/8049515
具体实现为只需在DynamicRTSPServer.cpp文件中添加如下实现代码:
else if((strcmp(extension, ".mp4") == 0) || (strcmp(extension, ".m4v") == 0))
{
NEW_SMS("MPEG-4 Video/Audio");
// get the info about file
char * command = (char *) malloc(150 * sizeof (char));
memset(command,0,150*sizeof(char));
command = strcat(command, "mp4info ");
command = strcat(command, fileName);
command = strcat(command, " >temp ");
puts(command);
system(command);
/parsing code/
FILE * fTemp = fopen("temp", "r"),*temp = NULL;
if (fTemp != NULL)
{
char c, ext[4];
ext[0] = '.';
ext[1] = 't';
ext[3] = '\0';
char * Word = (char *) malloc(100 * sizeof (char));
memset(Word,0,100 * sizeof(char));
int flagLine = 0, lineCount = 0, flagWord = 0, wordCount = 0, i = 0, flagCodec = 0, streamCount = 1;
while (!feof(fTemp))
{
if (lineCount != 3)
{
c = getc(fTemp);
}
if (flagLine == 1)
{
flagLine = 0;
if ((c > 48) && (c < 59)) {// get inside the stream numbers only ...
flagWord = 1;
while ((c != '\n') && (!feof(fTemp)))
{
c = getc(fTemp);
if (flagWord == 1)
{
i = 0;
while ((c != ' ') && (c != '\t') && (!feof(fTemp)))
{
Word[i] = tolower(c);
i++;
c = getc(fTemp);
}
Word[i] = '\0';
if ((strcmp("video", Word) == 0) || (strcmp("audio", Word) == 0))
{
flagCodec = 1;
wordCount = 0;
int i;
for (i = 0; i < 100; i++)
{
Word[i] = '\n';
}
ext[2] = '0' + streamCount;
strcpy(Word, "mp4creator -extract=");
Word[20] = streamCount + 48;
Word[21] = ' ';
Word[22] = '\0';
Word = strcat(Word,fileName);
puts(Word);
command = strcpy(command, fileName);
command = strcat(command, ext);
temp = fopen(command,"r");
if(temp == NULL)
{
env<< "creating files";
system(Word);
}
puts(command);
streamCount++;
}
if ((flagCodec == 1) && (wordCount == 1))
{
if (strcmp("h264", Word) == 0)
{
// printf("error cant play H.264 files.");
// return 0;
NEW_SMS("H.264 Video");
OutPacketBuffer::maxSize = 100000; // allow for some possibly large H.264 frames
sms->addSubsession(H264VideoFileServerMediaSubsession::createNew(env, command, reuseSource));
}
}
if ((flagCodec == 1) && (wordCount == 2))
{
flagCodec = 0;
printf("Flagged - %s line: %d\n", Word, lineCount);
///enter the code here
if (strcmp("aac", Word) == 0)
{
puts("aac found");
sms->addSubsession(ADTSAudioFileServerMediaSubsession
::createNew(env, command, reuseSource));
puts(ext);
} else if (strcmp("simple", Word) == 0)
{
puts("m4e found");
sms->addSubsession(MPEG4VideoFileServerMediaSubsession
::createNew(env,command, reuseSource));
puts(ext);
} else if (strcmp("h264", Word) == 0)
{
puts("m4e found");
puts(ext);
} else if (strcmp("amr", Word) == 0)
{
puts("amr found");
puts(ext);
}
}
flagWord = 0; // the word flag is reset
}
if ((c == '\t') || (c == ' '))
{
wordCount++;
flagWord = 1; // the word flag set for getting next word.
}
}
flagWord = 0;
wordCount = 0;
goto out;
}
}
out:
if (c == '\n')
{
lineCount++;
if (lineCount > 2)
{
flagLine = 1;
}
}
}
} else
{
printf("the file not found");
return 0;
}
}
需要用到的两个工具传到了百度云 把这两个工具放在live555的exe目录里 http://pan.baidu.com/s/1qYdhTUG ovhr
然后可以本机测试一下,我用的vlc测试,可以播放MP4
然后opencv这边的代码
#define _CRT_SECURE_NO_WARNINGS
#include<cstring>
#include "cv.h"
#include "highgui.h"
#include"stdlib.h"
#include<string>
#include<iostream>
using namespace std;
int main()
{
CvCapture *capture;
capture = cvCreateFileCapture("rtsp://127.0.0.1/2333.mp4");//主要就是这里改一下就ok
if (!capture) {
printf("Can not get the video stream from the camera!\n");
return NULL;
}
//assert(capture != NULL); //使用断言对函数参数进行确认,“假设”不成立则中断。
//显示视频信息--我的视频h576*w704,fps25,frame number15036
int frameH = (int)cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);
int frameW = (int)cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
int fps = (int)cvGetCaptureProperty(capture, CV_CAP_PROP_FPS);
int numFrames = (int)cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_COUNT);
printf("\tvideo height : %d\n\tvideo width : %d\n\tfps : %d\n\tframe numbers : %d\n", frameH, frameW, fps, numFrames> 0 ? numFrames :0 );
IplImage *frame = 0; //初始化定义
int n = 0; //初始化
char image_name[256]; //image_name的名字、类型、存放路径的字符串长度,小了可能会内存溢出中断
//要求提取5分10秒的截图
cout << endl;
int minu = numFrames>0? int(numFrames / 15.0 / 60.0):0;
cout << "视频总长度为" <<minu <<"分钟"<< endl;
cout << "截图格式为 分-秒 (不带空格)如5分10秒则输入5-10" << endl<<"请输入要截图的时间:";
string time,min,sec;
//time = "5-10";
cin >> time;
if (time.find("-")) {
min = time.substr(0, time.find("-"));
sec = time.substr(min.length() + 1, time.length() - 1);
}
else
{
cout << "输入错误" << endl;
}
int fra = fps*(stoi(min) * 60 + stoi(sec));
while (1)
{
++n;
frame = cvQueryFrame(capture); //获取一帧图像
if (!frame)
continue;
if (n == fra)break;
}
sprintf(image_name, "%s%d%s", ".\\", fra, ".jpg");
//保存的文件地址、类型、名称,中文路径保存不了。
//IplImage*out = cvCreateImage(CvSize(frame->width/2 , frame->height/2 ), frame->depth, frame->nChannels);
//cvPyrDown(frame, out, CV_GAUSSIAN_5x5); //下采样缩小图像
cvSaveImage(image_name, frame); //保存一帧图像
//cvReleaseImage(&frame);
cvReleaseCapture(&capture);
frame = NULL; //cvReleaseImage()和cvCreateImage()相对应的。在程序中如果没有使用cvCreateImage()“创建”就不能“释放”。
cout << "截图成功!" << endl;
system("pause");
return 0;
}