mirror of
https://github.com/mpromonet/v4l2rtspserver
synced 2024-11-03 23:15:56 +00:00
Merge branch 'master' of https://github.com/mpromonet/h264_v4l2_rtspserver
This commit is contained in:
commit
4a767df872
@ -8,12 +8,36 @@ set(CMAKE_BUILD_TYPE DEBUG)
|
||||
set(CMAKE_C_FLAGS "-Wall")
|
||||
set(CMAKE_CXX_FLAGS "-Wall")
|
||||
|
||||
add_custom_target(git_update
|
||||
COMMAND git submodule init
|
||||
COMMAND git submodule update
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
# define executable to build
|
||||
include_directories("${PROJECT_BINARY_DIR}/inc")
|
||||
aux_source_directory(src SRC_FILES)
|
||||
include_directories("${PROJECT_BINARY_DIR}/v4l2wrapper/inc")
|
||||
aux_source_directory(v4l2wrapper/src SRC_FILES)
|
||||
add_executable(${PROJECT_NAME} ${SRC_FILES})
|
||||
add_dependencies(${PROJECT_NAME} git_update)
|
||||
|
||||
# v4l2wrapper
|
||||
include_directories("${PROJECT_BINARY_DIR}/v4l2wrapper/inc")
|
||||
set_source_files_properties(${PROJECT_BINARY_DIR}/v4l2wrapper/src/V4l2Capture.cpp PROPERTIES GENERATED 1)
|
||||
set_source_files_properties(${PROJECT_BINARY_DIR}/v4l2wrapper/src/V4l2MmapCapture.cpp PROPERTIES GENERATED 1)
|
||||
set_source_files_properties(${PROJECT_BINARY_DIR}/v4l2wrapper/src/V4l2ReadCapture.cpp PROPERTIES GENERATED 1)
|
||||
|
||||
add_library(v4l2wrapper
|
||||
STATIC
|
||||
v4l2wrapper/src/V4l2Capture.cpp
|
||||
v4l2wrapper/src/V4l2MmapCapture.cpp
|
||||
v4l2wrapper/src/V4l2ReadCapture.cpp
|
||||
)
|
||||
target_link_libraries(${PROJECT_NAME} v4l2wrapper)
|
||||
add_dependencies(v4l2wrapper git_update)
|
||||
|
||||
#pthread
|
||||
find_package (Threads)
|
||||
target_link_libraries (${PROJECT_NAME} ${CMAKE_THREAD_LIBS_INIT})
|
||||
|
||||
# LOG4CPP
|
||||
find_path(LOG4CPP_INCLUDE_DIR log4cpp/Category.hh)
|
||||
|
@ -27,8 +27,6 @@ Dependencies
|
||||
|
||||
Build
|
||||
-------
|
||||
git submodule init
|
||||
git submodule update
|
||||
cmake .
|
||||
make
|
||||
|
||||
@ -52,7 +50,7 @@ This RTSP server works on Raspberry Pi using :
|
||||
|
||||
Usage
|
||||
-----
|
||||
./h264_v4l2_rtspserver [-v[v]][-m] [-P RTSP port][-P RTSP/HTTP port][-Q queueSize] [-M] [-W width] [-H height] [-F fps] [-O file] [device]
|
||||
./h264_v4l2_rtspserver [-v[v]][-m] [-P RTSP port][-P RTSP/HTTP port][-Q queueSize] [-M] [-t] [-W width] [-H height] [-F fps] [-O file] [device]
|
||||
-v : verbose
|
||||
-vv : very verbose
|
||||
-Q length: Number of frame queue (default 10)
|
||||
@ -63,8 +61,10 @@ Usage
|
||||
-P port : RTSP port (default 8554)
|
||||
-H port : RTSP over HTTP port (default 0)
|
||||
V4L2 options :
|
||||
-M : V4L2 capture using memory mapped buffers (default use read interface)
|
||||
-M 0/1 : V4L2 capture 0:read interface /1:memory mapped buffers (default is 1)
|
||||
-t 0/1 : V4L2 capture 0:read in live555 mainloop /1:in a thread (default is 1)
|
||||
-F fps : V4L2 capture framerate (default 25)
|
||||
-W width : V4L2 capture width (default 640)
|
||||
-H height: V4L2 capture height (default 480)
|
||||
device : V4L2 capture device (default /dev/video0)
|
||||
|
||||
|
@ -64,18 +64,20 @@ class V4L2DeviceSource: public FramedSource
|
||||
};
|
||||
|
||||
public:
|
||||
static V4L2DeviceSource* createNew(UsageEnvironment& env, V4L2DeviceParameters params, V4l2Capture * device, int outputFd, unsigned int queueSize, int verbose) ;
|
||||
static V4L2DeviceSource* createNew(UsageEnvironment& env, V4L2DeviceParameters params, V4l2Capture * device, int outputFd, unsigned int queueSize, int verbose, bool useThread) ;
|
||||
std::string getAuxLine() { return m_auxLine; };
|
||||
|
||||
protected:
|
||||
V4L2DeviceSource(UsageEnvironment& env, V4L2DeviceParameters params, V4l2Capture * device, int outputFd, unsigned int queueSize, int verbose);
|
||||
V4L2DeviceSource(UsageEnvironment& env, V4L2DeviceParameters params, V4l2Capture * device, int outputFd, unsigned int queueSize, int verbose, bool useThread);
|
||||
virtual ~V4L2DeviceSource();
|
||||
|
||||
protected:
|
||||
static void* threadStub(void* clientData) { return ((V4L2DeviceSource*) clientData)->thread();};
|
||||
void* thread();
|
||||
static void deliverFrameStub(void* clientData) {((V4L2DeviceSource*) clientData)->deliverFrame();};
|
||||
void deliverFrame();
|
||||
static void incomingPacketHandlerStub(void* clientData, int mask) { ((V4L2DeviceSource*) clientData)->getNextFrame(); };
|
||||
void getNextFrame();
|
||||
int getNextFrame();
|
||||
bool processConfigrationFrame(char * frame, int frameSize);
|
||||
void processFrame(char * frame, int &frameSize, const timeval &ref);
|
||||
void queueFrame(char * frame, int frameSize, const timeval &tv);
|
||||
@ -95,6 +97,7 @@ class V4L2DeviceSource: public FramedSource
|
||||
V4l2Capture * m_device;
|
||||
unsigned int m_queueSize;
|
||||
int m_verbose;
|
||||
pthread_t m_thid;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -48,18 +48,18 @@ int V4L2DeviceSource::Stats::notify(int tv_sec, int framesize, int verbose)
|
||||
// ---------------------------------
|
||||
// V4L2 FramedSource
|
||||
// ---------------------------------
|
||||
V4L2DeviceSource* V4L2DeviceSource::createNew(UsageEnvironment& env, V4L2DeviceParameters params, V4l2Capture * device, int outputFd, unsigned int queueSize, int verbose)
|
||||
V4L2DeviceSource* V4L2DeviceSource::createNew(UsageEnvironment& env, V4L2DeviceParameters params, V4l2Capture * device, int outputFd, unsigned int queueSize, int verbose, bool useThread)
|
||||
{
|
||||
V4L2DeviceSource* source = NULL;
|
||||
if (device)
|
||||
{
|
||||
source = new V4L2DeviceSource(env, params, device, outputFd, queueSize, verbose);
|
||||
source = new V4L2DeviceSource(env, params, device, outputFd, queueSize, verbose, useThread);
|
||||
}
|
||||
return source;
|
||||
}
|
||||
|
||||
// Constructor
|
||||
V4L2DeviceSource::V4L2DeviceSource(UsageEnvironment& env, V4L2DeviceParameters params, V4l2Capture * device, int outputFd, unsigned int queueSize, int verbose)
|
||||
V4L2DeviceSource::V4L2DeviceSource(UsageEnvironment& env, V4L2DeviceParameters params, V4l2Capture * device, int outputFd, unsigned int queueSize, int verbose, bool useThread)
|
||||
: FramedSource(env),
|
||||
m_params(params),
|
||||
m_in("in"),
|
||||
@ -72,17 +72,61 @@ V4L2DeviceSource::V4L2DeviceSource(UsageEnvironment& env, V4L2DeviceParameters p
|
||||
m_eventTriggerId = envir().taskScheduler().createEventTrigger(V4L2DeviceSource::deliverFrameStub);
|
||||
if (m_device)
|
||||
{
|
||||
envir().taskScheduler().turnOnBackgroundReadHandling( m_device->getFd(), V4L2DeviceSource::incomingPacketHandlerStub, this);
|
||||
if (useThread)
|
||||
{
|
||||
pthread_create(&m_thid, NULL, threadStub, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
envir().taskScheduler().turnOnBackgroundReadHandling( m_device->getFd(), V4L2DeviceSource::incomingPacketHandlerStub, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Destructor
|
||||
V4L2DeviceSource::~V4L2DeviceSource()
|
||||
{
|
||||
{
|
||||
envir().taskScheduler().deleteEventTrigger(m_eventTriggerId);
|
||||
m_device->captureStop();
|
||||
pthread_join(m_thid, NULL);
|
||||
}
|
||||
|
||||
|
||||
// thread mainloop
|
||||
void* V4L2DeviceSource::thread()
|
||||
{
|
||||
int stop=0;
|
||||
fd_set fdset;
|
||||
FD_ZERO(&fdset);
|
||||
timeval tv;
|
||||
|
||||
envir() << "begin thread\n";
|
||||
while (!stop)
|
||||
{
|
||||
FD_SET(m_device->getFd(), &fdset);
|
||||
tv.tv_sec=1;
|
||||
tv.tv_usec=0;
|
||||
int ret = select(m_device->getFd()+1, &fdset, NULL, NULL, &tv);
|
||||
if (ret == 1)
|
||||
{
|
||||
if (FD_ISSET(m_device->getFd(), &fdset))
|
||||
{
|
||||
if (this->getNextFrame() <= 0)
|
||||
{
|
||||
envir() << "error:" << strerror(errno) << "\n";
|
||||
stop=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ret == -1)
|
||||
{
|
||||
envir() << "stop " << strerror(errno) << "\n";
|
||||
stop=1;
|
||||
}
|
||||
}
|
||||
envir() << "end thread\n";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// getting FrameSource callback
|
||||
void V4L2DeviceSource::doGetNextFrame()
|
||||
{
|
||||
@ -149,9 +193,9 @@ void V4L2DeviceSource::deliverFrame()
|
||||
FramedSource::afterGetting(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// FrameSource callback on read event
|
||||
void V4L2DeviceSource::getNextFrame()
|
||||
int V4L2DeviceSource::getNextFrame()
|
||||
{
|
||||
char* buffer = new char[m_device->getBufferSize()];
|
||||
timeval ref;
|
||||
@ -168,6 +212,7 @@ void V4L2DeviceSource::getNextFrame()
|
||||
{
|
||||
envir() << "V4L2DeviceSource::getNextFrame no data errno:" << errno << " " << strerror(errno) << "\n";
|
||||
delete [] buffer;
|
||||
handleClosure(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -190,6 +235,7 @@ void V4L2DeviceSource::getNextFrame()
|
||||
delete [] buffer;
|
||||
}
|
||||
}
|
||||
return frameSize;
|
||||
}
|
||||
|
||||
bool V4L2DeviceSource::processConfigrationFrame(char * frame, int frameSize)
|
||||
|
17
src/main.cpp
17
src/main.cpp
@ -140,7 +140,7 @@ int createOutput(const std::string & outputFile, int inputFd)
|
||||
}
|
||||
return outputFd;
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------
|
||||
// entry point
|
||||
// -----------------------------------------
|
||||
@ -162,13 +162,14 @@ int main(int argc, char** argv)
|
||||
bool multicast = false;
|
||||
int verbose = 0;
|
||||
std::string outputFile;
|
||||
bool useMmap = false;
|
||||
bool useMmap = true;
|
||||
std::string url = "unicast";
|
||||
std::string murl = "multicast";
|
||||
bool useThread = true;
|
||||
|
||||
// decode parameters
|
||||
int c = 0;
|
||||
while ((c = getopt (argc, argv, "hW:H:Q:P:F:v::O:T:m:u:M")) != -1)
|
||||
while ((c = getopt (argc, argv, "hW:H:Q:P:F:v::O:T:m:u:M:t:")) != -1)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
@ -181,13 +182,14 @@ int main(int argc, char** argv)
|
||||
case 'P': rtspPort = atoi(optarg); break;
|
||||
case 'T': rtspOverHTTPPort = atoi(optarg); break;
|
||||
case 'F': fps = atoi(optarg); break;
|
||||
case 'M': useMmap = true; break;
|
||||
case 'M': useMmap = atoi(optarg); break;
|
||||
case 't': useThread = atoi(optarg); break;
|
||||
case 'u': url = optarg; break;
|
||||
|
||||
case 'h':
|
||||
default:
|
||||
{
|
||||
std::cout << argv[0] << " [-v[v]][-m] [-P RTSP port][-P RTSP/HTTP port][-Q queueSize] [-M] [-W width] [-H height] [-F fps] [-O file] [device]" << std::endl;
|
||||
std::cout << argv[0] << " [-v[v]][-m] [-P RTSP port][-P RTSP/HTTP port][-Q queueSize] [-M] [-t] [-W width] [-H height] [-F fps] [-O file] [device]" << std::endl;
|
||||
std::cout << "\t -v : verbose" << std::endl;
|
||||
std::cout << "\t -vv : very verbose" << std::endl;
|
||||
std::cout << "\t -Q length: Number of frame queue (default "<< queueSize << ")" << std::endl;
|
||||
@ -198,7 +200,8 @@ int main(int argc, char** argv)
|
||||
std::cout << "\t -P port : RTSP port (default "<< rtspPort << ")" << std::endl;
|
||||
std::cout << "\t -H port : RTSP over HTTP port (default "<< rtspOverHTTPPort << ")" << std::endl;
|
||||
std::cout << "\t V4L2 options :" << std::endl;
|
||||
std::cout << "\t -M : V4L2 capture using memory mapped buffers (default use read interface)" << std::endl;
|
||||
std::cout << "\t -M 0/1 : V4L2 capture 0:read interface /1:memory mapped buffers (default is 1)" << std::endl;
|
||||
std::cout << "\t -t 0/1 : V4L2 capture 0:read in live555 mainloop /1:in a thread (default is 1)" << std::endl;
|
||||
std::cout << "\t -F fps : V4L2 capture framerate (default "<< fps << ")" << std::endl;
|
||||
std::cout << "\t -W width : V4L2 capture width (default "<< width << ")" << std::endl;
|
||||
std::cout << "\t -H height: V4L2 capture height (default "<< height << ")" << std::endl;
|
||||
@ -241,7 +244,7 @@ int main(int argc, char** argv)
|
||||
int outputFd = createOutput(outputFile, videoCapture->getFd());
|
||||
LOG(NOTICE) << "Start V4L2 Capture..." << dev_name;
|
||||
videoCapture->captureStart();
|
||||
V4L2DeviceSource* videoES = V4L2DeviceSource::createNew(*env, param, videoCapture, outputFd, queueSize, verbose);
|
||||
V4L2DeviceSource* videoES = V4L2DeviceSource::createNew(*env, param, videoCapture, outputFd, queueSize, verbose, useThread);
|
||||
if (videoES == NULL)
|
||||
{
|
||||
LOG(FATAL) << "Unable to create source for device " << dev_name;
|
||||
|
Loading…
Reference in New Issue
Block a user