之前在公司做的一个小项目,功能很简单,就是在Ubuntu下采集 指定采集卡(模转数)的电视画面,以及音频输入信号,完成后再在本机进行视频的全屏播放,以及音频的本地播放(麦克风>>扬声器)。
中间视频画面经过了图像格式的转换,最终由SDL进行渲染播放。
同时附加简单的冗余功能,有两台设备同事运行,之间互有心跳,一台设备挂机后,另一台设备自动开始工作。
程序使用QT/C/C++进行开发,使用V4L2,FFMPEG,SDL进行开发。
入口:
#include <QtGui/QApplication>
#include "widget.h"
#include <QSharedMemory>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//共享内存保证单实例运行
QSharedMemory *shareMem = new QSharedMemory(QString("SingleInstanceIdentify"));
/* if the sharedmemory has not been created, it returns false, otherwise true.
* But if the application exit unexpectedly, the sharedmemory will not detach.
* So, we try twice.
*/
volatile short i = 2;
while (i--)
{
if (shareMem->attach(QSharedMemory::ReadOnly)) /* no need to lock, bcs it's read only */
{
shareMem->detach();
}
}
if (shareMem->create(1))
{
//采集并播放类开始运行,全部放到UI类中进行
MainWindow w;
w.setWindowTitle("LCD Player");
// w.show();
w.showFullScreen();
a.exec();
}
}
主要的设备管理、逻辑管理类接口:
class CDeviceCtrl : public QObject
{
Q_OBJECT
public:
explicit CDeviceCtrl(QObject *parent = 0);
~CDeviceCtrl();
int OpenDevice();
int ReadAndDisplay();
int CloseDevice();
int GetDeviceHandle() {return fd;}
PSDLMODULE GetSdlModule(){return pSdlModule;}
PTAVSDLYUVSURFACE GetSurface(){return pSurface;}
struct VideoBuffer *GetVideoBuffer(){return video_buffers;}
bool GetCapFlag() {return devam;}
CDebugLog* GetDebugLog(){ return pLog;}
protected:
int ReadConfigure(const char *filename);
private:
QObject* parent;
CDebugLog* pLog;
pthread_t hThreadDisplayHandle; //渲染线程句柄
pthread_t hThreadRecordHandle; //录制线程句柄
bool devam;
int fd;
unsigned int buffer_count;
char out_name[256];
PSDLMODULE pSdlModule; //SDL资源
PTAVSDLYUVSURFACE pSurface; //SDL资源
struct VideoBuffer* video_buffers;
}
完整代码,请前往我的码云平台下载,地址是:https://git.oschina.net/icedbeer/LinuxMediaCapture
这是QT工程,请使用QtCreator打开工程文件.pro。
上面的这个工程这是简单的把画面进行本地显示,如果需要进行编码并传输的话,请参考另一个工程(QT+Linux),源码下载地址是:https://git.oschina.net/icedbeer/LinuxMediaCaptureRtsp
此工程主要功能是:
Linux下视频采集并编码H.264格式,同时封装为TS流;
开启RTST流服务器监控,接受客户端连接请求,并创建一个新的线程将TS流数据发送给Client。
此代码只是实验性的代码,每个Client都会开启一个线程,所以如果需要大并发运行的话,请勿效仿。