通过FFmpeg 来筛选合并视频文件的项目记录

项目需求

平台通过http下发json格式的消息

程序收到消息后 根据日期时间戳去对应的目录检索是否符合要求的文件 比如某个时间段

检索到之后 将视频片段拼接成一个完整的视频文件 

没有的话 根据时间戳判断是否需要等待或者 返回没有检索到 

头文件

#ifndef QMCY_LED_H
#define QMCY_LED_H

#include 
#include 
#include
#include
#include

#include
#include 
#include 
#include 
#include 



#include 
#include 
#include 


#include "zlog.h"

#include "httplib.h"
#include "json.hpp"
#include "BlockQueue.hpp"
#include "BlackBox.h"



#define HTTP_PORT	8081
#define HTTP_IP	"0.0.0.0"

#define 		MAX_THREADS	2
#define 		MAX_QUEUE_SIZE 4

#define DEVICE_VERSION	"VIDEO FILETER 1.0"




#define HTTP_SEARCH	"/api/search"


typedef enum
{
	MSG_SET_CONTENT,
	MSG_UPDATE_LED_LIST,
	MSG_EXIT_LED
}MSG_ID;



struct INNER_MSG
{
	MSG_ID msg_id;

	std::string taskid;
	std::string date;
	std::string time;
	int total_time;
};



typedef struct {

	std::string server_ip_name;
	std::string server_port_name;
	std::string local_port_name;


	std::string server_ip;
	std::string local_ip;
	std::string device_id;
	int server_port;
	int local_port;	
	bool debug_mode;
	bool encrypt_mode;
}AppBasicInfo;



template
class HANA 
{
	public:
		/**
		 * @brief 返回单例智能指针
		 */
		static std::shared_ptr GetHANA()
		{

			static std::shared_ptr object (new Typename);
			std::cout<<__func__<<" "< lock(_mutex);
        _count += n;
        if (n == 1) {
            _condition.notify_one();
        } else {
            _condition.notify_all();
        }
#endif
    }

    void wait() {
#if defined(HAVE_SEM)
        sem_wait(&_sem);
#else
        std::unique_lock lock(_mutex);
        while (_count == 0) {
            _condition.wait(lock);
        }
        --_count;
#endif
    }

private:
#if defined(HAVE_SEM)
    sem_t _sem;
#else
    size_t _count;
    std::recursive_mutex _mutex;
    std::condition_variable_any _condition;
#endif
};



class QMCY_APP:public std::enable_shared_from_this
{
public:
	using PTR = std::shared_ptr;
	//using LED_TABLE = std::unordered_map>;

	QMCY_APP();
	~QMCY_APP();

	void Version();

	bool Init(std::string &config_file, char *env[]);
	bool Start();	
	bool  Stop();



private:
	uint64_t m_counter;
	std::atomicm_run_flag;
	AppBasicInfo m_basic_info;
	std::thread m_http_thread;
	std::thread m_task_thread;
	std::thread m_timer_thread;	


	std::mutex m_table_mutex;


	httplib::Server m_http;
	

	void MainTask();
	void  HttpTask();	
	void TimerTask();	

	void DispatchTask(INNER_MSG inner_msg);
	void RealExecUnit(INNER_MSG inner_msg);
	
	void Report();

	void ParseSearch(const std :: string & json);

	std::vector GetFiles(std::string dir,std::string time);
	void ReadConfig(const std::string &json);	
	
	std::shared_ptr m_http_client;

	std::shared_ptr>	m_inner_queue;	
	
	std::shared_ptr m_thread_pool;
	
};


#endif 

cpp文件

#include "QMCY_DUMP.h"
#include 
#include 



static semaphore sem;

zlog_category_t *g_zlog;


QMCY_APP::QMCY_APP()
{
	m_counter = 0;

	std::cout<<__func__< QMCY_APP::GetFiles(const std::string dir,std::string time)
{

	int hour,minute,second,sn;
	int converted;
	unsigned int last_item_time = 0;
	int check_times = 0;
	
	std::vector result;
	std::map table;
	unsigned int keyword;
	char path[1000];
	strcpy(path,dir.c_str());
	DIR *dp;
	struct dirent *files;
	/*structure for storing inode numbers and files in dir
	struct dirent
	{
	  ino_t d_ino;
	  char d_name[NAME_MAX+1]
	}
	*/


	RECHECK:

	result.clear();
	table.clear();
	
	check_times++;

	
	if((dp=opendir(path))==NULL)
	  perror("dir\n");
	char newp[1000];
	struct stat buf;
	while((files=readdir(dp))!=NULL)
	{
		if(!strcmp(files->d_name,".") || !strcmp(files->d_name,".."))
		 continue;

		strcpy(newp,path);
		strcat(newp,"/");
		strcat(newp,files->d_name); 
		//printf("%s\n",newp);

		//printf("%s\n",files->d_name);

		std::string filename = files->d_name;
		std::size_t found = filename.find_last_of(".mp4");
		if(found == filename.size() -1)
		{
			//printf("find :%d\n",found);


			converted = sscanf(files->d_name, "%02d-%02d-%02d-%d", &hour, &minute, &second,&sn);
			if(converted == 4)
			{
				unsigned int key = hour*3600+minute*60+second;
				table.insert(std::pair(key,files->d_name));
			}

		}
		else
		{
			printf("not a mp4 file\n");
			continue;
		}

	}


	

	converted = sscanf(time.c_str(), "%02d:%02d:%02d", &hour, &minute, &second);



	

	if(converted == 3)
	{
		keyword = 		hour*3600+minute*60+second;
		std::cout<<"keyword is:"<=keyword-6 && item.first <=keyword+6)
			{
				std::cout<<"matched :"<"<"< files = GetFiles(inner_msg.date,inner_msg.time);

	std::string filecontent;

	if(files.size() >0)
	{
		for(auto &item:files)
		{
				std::cout<<"matched :"<get_tasks();

	if(size >= MAX_QUEUE_SIZE)
	{
		//Need to tell server this task can not be exectued!!!!!
		std::cout<<"Task full   add failed  task size "<AddTask([this,inner_msg](){
		RealExecUnit(inner_msg);
	});	

	//std::cout<<" DispatchTask AddTask Exit !!!!!!!!!!!"<pop_data(inner_msg); 
		if(ret )
		{
			if(MSG_EXIT_LED == inner_msg.msg_id)
			{
				std::cout<<"Get exit msg :"< lock(m_table_mutex);

	jsonxx::json response ;
#if 0
	for(auto it=m_led_table.begin(); it!=m_led_table.end();it++)
	{

		jsonxx::json item;

		auto led   = it->second;

		if(m_run_flag.load() == false || led == nullptr)
		{
			return;
		}

		auto result = led ->NVR_GetStatus();

		item["bmsid"]= it->first;
		item["status"]= result.first;
		item["msg"]= result.second;
		
		response.push_back(std::move(item));

	}

	auto output = response.dump();
	if(output.size())
	{
		std::cout<<"Report content:"<Post("/qmcy",output,"application/json"))
		{
			if (res->status == 200)
			{
				
			}
			else
			{
				auto err = res.error();
				std::cout << "HTTP error: " << httplib::to_string(err) << std::endl;
			}
	
		}
		else
		{
			std::cout<<"Report status to server  failed!"<server_ip,pHandle->server_port);
		}
	}
#endif	

}



void QMCY_APP::TimerTask()
{

	while(m_run_flag.load())
	{
		m_counter++;
		if(m_counter % 200 == 0)
		{
			if(m_run_flag.load())
			{
				Report();
			}

		}
		std::this_thread::sleep_for(std::chrono::seconds(1));
	}

	std::cout<<__func__<<" exit!!!"<20)
		{
			inner_msg.total_time = 10;
		}
	}


	inner_msg.msg_id = MSG_SET_CONTENT;
	m_inner_queue->push_data(inner_msg);
}




void QMCY_APP::HttpTask()
{

	m_http.Get("/hi", [](const httplib::Request &, httplib::Response &res) {
	  res.set_content("Hello World!", "text/plain");
	});


	m_http.Get("/led/status", [](const httplib::Request &, httplib::Response &res) {
	  res.set_content("Get led status World!", "text/plain");
	});


	m_http.Post("/Stop", [](const httplib::Request &req, httplib::Response &res) {
		  res.set_content("PostLEDConfig message!", "text/plain");
	  		std::cout<<"APP exit message"<65535 )
	{
		m_basic_info.local_port = 8888;
	}

	if(m_basic_info.server_port<1024|| m_basic_info.server_port >65535 )
	{
		m_basic_info.server_port = 8888;
	}



	zlog_info(g_zlog,"APP run info:[server ip = %s,server port=%d, local port = %d]",m_basic_info.server_ip.c_str(),m_basic_info.server_port,m_basic_info.local_port);


	std::string posturi = "http://";
	posturi.append(m_basic_info.server_ip);
	posturi.append(":");	
	posturi.append(std::to_string(m_basic_info.server_port));	


	m_http_client = std::make_shared(posturi);

	//m_log = HANA::GetHANA();

	m_thread_pool = std::make_shared(MAX_THREADS,MAX_QUEUE_SIZE);
	m_thread_pool->init();

	m_inner_queue = std::make_shared>(30);

	return true;	
		
}



bool QMCY_APP::Start()
{

	m_run_flag = true;
	
	m_task_thread = std::thread(&QMCY_APP::MainTask,this);
	m_http_thread = std::thread(&QMCY_APP::HttpTask,this);	
	m_timer_thread = std::thread(&QMCY_APP::TimerTask,this);	



	//std::this_thread::sleep_for(std::chrono::seconds(1));

	zlog_info(g_zlog,"QMCY Video filter system successfully started");

	
	return true;
}


bool QMCY_APP::Stop()
{
	std::cout<<__func__<push_data(inner_msg);

	m_thread_pool->shutdown();
	

	m_run_flag = false;


	m_http.stop();


	m_task_thread.join();
	m_http_thread.join();
	if(m_timer_thread.joinable())
	{
		m_timer_thread.join();
	}


	return true;
}



void PrintLEDVersion()
{
	const char APP_time[] =  "QMCY VIDEO FILTER (build in: " __DATE__ " " __TIME__ ")";

	zlog_info(g_zlog,"=====================================================================================\n");
	zlog_info(g_zlog,"                     QMCY VIDEO FILTER system Version[%s], Date[%s]                  \n",DEVICE_VERSION, APP_time);
	zlog_info(g_zlog,"=====================================================================================\n"); 


	printf("程序版本[%s]\n",APP_time);

}




int main(int argc,char *argv[], char *env[])
{


	auto rc = zlog_init("./zlog.conf");
	if (rc) {
		printf("init failed\n");
		return false;
	}

	g_zlog = zlog_get_category("qmcy");
	if (!g_zlog) {
		printf("get cat fail\n");
		zlog_fini();
		return -1;
	}


	std::string config = "config.json";


	std::shared_ptr app = HANA::GetHANA();

	
	if(app->Init(config,env) == false) 
	{
		std::cout<<"APP init failed"<Start();


  signal(SIGINT, [](int) {
		std::cout << "GET QMCY exit signal SIGINT:exit";
		signal(SIGINT, SIG_IGN);// 设置退出信号
		sem.post();
  });// 设置退出信号

	sem.wait();

	app->Stop();

	std::cout<<"Exit QMCY APP system"<

Http服务用cpphttp

项目中用到 线程池 等待队列 等 

你可能感兴趣的:(ffmpeg)