python opencv图片编码为h264文件的实例


Posted in Python onDecember 12, 2019

python部分

#!/usr/bin/env Python
# coding=utf-8
from ctypes import *


from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import time
import numpy as np
import cv2
import struct

import datetime


from numba import jit
import os
cam_dict={}


class CamInfo:
 def __init__(self, cam_no=0,deviceid="default",cam_name="default"):
  self.cam_no = cam_no
  self.deviceid = deviceid
  self.cam_name = cam_name


@jit
def trans(data,size,height,width):
 bbb = string_at(data,size)
 nparr = np.fromstring(bbb, np.uint8)
 r = nparr.reshape(height,width, 3)
 return r
def str2char_p(str_v):
 pStr = c_char_p( )
 pStr.value = str_v
 return pStr


def callb_stream(data,size,cam_no,height,width):
 r = trans(data, size,height,width)
 r = cv2.cvtColor(r, cv2.COLOR_RGB2BGR)
 counter = datetime.datetime.now().strftime('%Y%m%d_%H%M%S_%f')
 # print(1, counter)
 cv2.imshow(str(cam_no), r)
 cv2.waitKey(1)


def callb_camerainfo(cam_no,camera_info,camera_info_size):
 # print(cast(camera_info,c_char_p).value)
 # print(str(cast(camera_info, c_char_p).value))
 bbb = string_at(camera_info, camera_info_size)
 info=str(bbb,encoding="utf-8").split(",")
 cam_dict[cam_no]= CamInfo(cam_no,info[1],info[2])
 print("camerainfo",cam_dict[cam_no].cam_no,cam_dict[cam_no].cam_name,cam_dict[cam_no].deviceid)




class Mythread(QThread):
 # 定义信号,定义参数为str类型
 breakSignal = pyqtSignal(str,list)


 def __init__(self, parent=None):
  super().__init__(parent)
  # super(Mythread, self).__init__()


 def callb_error(self, err_type, cam_no, msg_no, msg_level, msg_txt, msg_txtlen):
  print("myerror", err_type, cam_no, msg_no, msg_level, msg_txt, msg_txtlen)
 def run(self):
  dll = CDLL(r"./hik_client.dll")
  width=60
  height=40
  dll.pre_encode.restype = c_void_p
  ret=dll.pre_encode(width,height)
  ret=cast(ret,c_void_p)
  for i in range(20000):
   n=i%200+1
   img=cv2.imread("bmp/"+str(n)+".bmp")
   len = img.shape[0] * img.shape[1] * img.shape[2]
   # img=np.transpose(img,(1, 0, 2))
   # b, g, r = cv2.split(img)
   # b = b.reshape(-1)
   # g = g.reshape(-1)
   # r = r.reshape(-1)
   # b = np.append(b, g)
   # img = np.append(b, r)
   img = img.reshape(-1)
   # b, g, r = cv2.split(img)
   # b = b.reshape(-1)
   # g = g.reshape(-1)
   # r = r.reshape(-1)
   # b = np.append(b,g)
   # img = np.append(b, r)
   INPUT = c_int * len
   # 实例化一个长度为2的整型数组
   input = INPUT()
   # 为数组赋值(input这个数组是不支持迭代的)
   for i in range(len):
    input[i] = img[i]


   # bytes(aaaa, encoding="utf-8")
   a = dll.push_rtsp(input,len,ret)
  QCoreApplication.instance().quit()
   # print("encode_ok",i)
  # b = string_at(a, 1280*720*3)
  # print(b)
  # nparr = np.fromstring(b, np.uint8)
  # # print(nparr[-10:-1],min(nparr),max(nparr))
  # img_decode = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
  # # if img_decode:
  # cv2.imshow("sadf", img_decode)
  # # cv2.imwrite(str(index)+".jpg", img_decode)
  # cv2.waitKey(0)
  #
  #
  #
  #
  # ErrorCall = CFUNCTYPE(c_void_p, c_int, c_int, c_int,c_int,c_char_p,c_int)
  # error_callback = ErrorCall(self.callb_error)
  # dll.set_callback(error_callback)
  # CamCall = CFUNCTYPE(c_void_p, c_int, c_char_p,c_int)
  # caminfo_CamCall = CamCall(callb_camerainfo)
  # # print(b)
  # if not os.path.exists("video"):
  #  os.makedirs("video")
  # ip = b"127.0.0.1"
  # port = 8888
  # print("start conn")
  # ret=-1
  # while(ret):
  #  print("conn server...")
  #  ret= dll.tcp_init(str2char_p(ip), port)
  #  time.sleep(0.3)
  # if (ret==0):
  #  type=1
  #  ret = dll.getcameralist(type, caminfo_CamCall)
  #  if (1):
  #   # deviceId = b"af94a68df0124d1fbf0fc2b07f3b3c3a"
  #   cam_no=14
  # else:
  #  print("tcp error")
  # for i in range(2000000):
  #  # 发出信号
  #  a=[i,i+1]
  #  self.breakSignal.emit(str(i),a)
  #  # 让程序休眠
  #  time.sleep(0.5)


if __name__ == '__main__':


 app = QApplication([])
 dlg = QDialog()
 dlg.resize(400, 300)
 dlg.setWindowTitle("自定义按钮测试")
 dlgLayout = QVBoxLayout()
 dlgLayout.setContentsMargins(40, 40, 40, 40)
 btn = QPushButton('测试按钮')
 dlgLayout.addWidget(btn)
 dlgLayout.addStretch(40)
 dlg.setLayout(dlgLayout)
 dlg.show()


 def chuli(a,s):
  # dlg.setWindowTitle(s)
  btn.setText(a+str(s[0]*10))


 # 创建线程
 thread = Mythread()
 # # 注册信号处理函数
 thread.breakSignal.connect(chuli)
 # # 启动线程
 thread.start()
 dlg.exec_()
 app.exit()

c++动态库部分

#include "stdafx.h"
#include "CVdll.h"
#include "SimpleLog.h"
#include <iostream>
#include<fstream>
#include <sys/types.h> 
#include "opencv2/opencv.hpp"


#include "Ws2tcpip.h"


#include <winsock2.h>
#include <fcntl.h>
#include <cstring>
#include <cstdio>
#include <signal.h>
#pragma comment(lib,"ws2_32.lib")
#include <queue> 
using namespace cv;
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavdevice/avdevice.h"
#include "libavutil/log.h"


//#include "libavutil/imgutils.h"
};


//说明,动态库需要拷贝三个文件,否则重连会出问题


char* testchar(int plus1) {


	char* str = "hello world111111";
	return str;
}
char* testimg(char* data,int length) {


	char* str = "hello world111111";
	return str;
}
	


	int outbuf_size = 100000;
	
	


	class Rtmp_tool {
	public:
		int nWidth = 0;
		int nHeight = 0;
		AVCodecContext *c;
		AVFrame *m_pRGBFrame = new AVFrame[1]; //RGB帧数据  
		AVFrame *m_pYUVFrame = new AVFrame[1];; //YUV帧数据 
		uint8_t * yuv_buff;// 
		uint8_t * outbuf;
		SwsContext * scxt;
		FILE *f = NULL;


	};
void* pre_encode(int width,int height) {


	Rtmp_tool *rtmp_tool;
	rtmp_tool = new Rtmp_tool();
	int nLen;
	int fileI;
	rtmp_tool->nWidth = width;
	rtmp_tool->nHeight = height;


	av_register_all();
	avcodec_register_all();
	//AVFrame *m_pRGBFrame = new AVFrame[1]; //RGB帧数据  
	//AVFrame *m_pYUVFrame = new AVFrame[1];; //YUV帧数据 
	AVCodecContext *c = NULL;
	AVCodecContext *in_c = NULL;
	AVCodec *pCodecH264; //编码器 
	
					 //查找h264编码器 
	pCodecH264 = avcodec_find_encoder(AV_CODEC_ID_H264);




	c = avcodec_alloc_context3(pCodecH264);
	c->bit_rate = 3000000;// put sample parameters  
	c->width = width;//  
	c->height = height;//  


						// frames per second  
	AVRational rate;
	rate.num = 1;
	rate.den = 5;
	c->time_base = rate;//(AVRational){1,25}; 
	c->gop_size = 10; // emit one intra frame every ten frames  
	c->max_b_frames = 1;
	c->thread_count = 1;
	c->pix_fmt = AV_PIX_FMT_YUV420P;//PIX_FMT_RGB24; 


									//av_opt_set(c->priv_data, /*"preset"*/"libvpx-1080p.ffpreset", /*"slow"*/NULL, 0); 
									//打开编码器 
	if (avcodec_open2(c, pCodecH264, NULL)<0)
		printf("不能打开编码库");


	int size = c->width * c->height;


	rtmp_tool->yuv_buff = (uint8_t *)malloc((size * 3) / 2); // size for YUV 420  




	//图象编码 


	rtmp_tool->outbuf = (uint8_t*)malloc(outbuf_size);
	int u_size = 0;
	
	const char * filename = "0_Data.h264";
	rtmp_tool->f = fopen(filename, "wb");
	if (!rtmp_tool->f)
	{
		printf("could not open %s\n", filename);
		exit(1);
	}


	//初始化SwsContext 
	rtmp_tool->scxt = sws_getContext(c->width, c->height, AV_PIX_FMT_BGR24, c->width, c->height, AV_PIX_FMT_YUV420P, SWS_POINT, NULL, NULL, NULL);




	rtmp_tool->c = c;
	return rtmp_tool;
}


char* push_rtsp(int* plus1,int len,void* vp) {
	Rtmp_tool *rtmp_tool =(Rtmp_tool *) vp;


	for (int i = 0; i < len; i++) {
		plus1[i] = (uint8_t)plus1[i];
	}
	


	 AVCodecContext *c = rtmp_tool->c;// (AVCodecContext*)vp;
	printf("2 %d %d\n", c->width, c->height);
	//---------------
	AVPacket avpkt;
	AVFrame *m_pRGBFrame = rtmp_tool->m_pRGBFrame;
	AVFrame *m_pYUVFrame = rtmp_tool->m_pYUVFrame;
	/*unsigned char *pBmpBuf;
	pBmpBuf = new unsigned char[len];*/
	
	//memcpy(rgb_buff, (uint8_t*)plus1, nDataLen);
 //
	avpicture_fill((AVPicture*)m_pRGBFrame, (uint8_t*)plus1, AV_PIX_FMT_RGB24, rtmp_tool->nWidth, rtmp_tool->nHeight);
	m_pRGBFrame->linesize[0] = c->width * 3;
	m_pRGBFrame->linesize[1] =0;
	m_pRGBFrame->linesize[2] =0;
	m_pRGBFrame->linesize[3] =0;
	m_pRGBFrame->format = AV_PIX_FMT_RGB24;
	m_pRGBFrame->width = rtmp_tool->nWidth;
	m_pRGBFrame->height = rtmp_tool->nHeight;


	uint8_t *p = m_pRGBFrame->data[0];
	int y = 0, x = 0;
	for (y = 0; y < rtmp_tool->nHeight; y++) {
		for (x = 0; x < rtmp_tool->nWidth; x++) {
			*p++ = (uint8_t)plus1[(y*rtmp_tool->nWidth + x) * 3]; // R
			*p++ = (uint8_t)plus1[(y*rtmp_tool->nWidth + x) * 3 +1]; // G
			*p++ = (uint8_t)plus1[(y*rtmp_tool->nWidth + x) * 3 +2] ; // B
		}
	}
	printf("1 %d %d \n", rtmp_tool->nWidth, rtmp_tool->nHeight);
	//将YUV buffer 填充YUV Frame 
	avpicture_fill((AVPicture*)m_pYUVFrame, (uint8_t*)rtmp_tool->yuv_buff, AV_PIX_FMT_YUV420P, rtmp_tool->nWidth, rtmp_tool->nHeight);


	// 翻转RGB图像 
	//m_pRGBFrame->data[0] += m_pRGBFrame->linesize[0] * (rtmp_tool->nHeight - 1);
	//m_pRGBFrame->linesize[0] *= -1;
	//m_pRGBFrame->data[1] += m_pRGBFrame->linesize[1] * (rtmp_tool->nHeight / 2 - 1);
	//m_pRGBFrame->linesize[1] *= -1;
	//m_pRGBFrame->data[2] += m_pRGBFrame->linesize[2] * (rtmp_tool->nHeight / 2 - 1);
	//m_pRGBFrame->linesize[2] *= -1;




	//将RGB转化为YUV 
	sws_scale(rtmp_tool->scxt, m_pRGBFrame->data, m_pRGBFrame->linesize, 0, c->height, m_pYUVFrame->data, m_pYUVFrame->linesize);


	int got_packet_ptr = 0;
	av_init_packet(&avpkt);
	avpkt.data = rtmp_tool->outbuf;
	avpkt.size = outbuf_size;
	int u_size = avcodec_encode_video2(c, &avpkt, m_pYUVFrame, &got_packet_ptr);
	m_pYUVFrame->pts++;
	if (u_size == 0){
		int res = fwrite(avpkt.data, 1, avpkt.size, rtmp_tool->f);
		if (res == 0) {
			printf("000");
		}
		else {
			printf("1253");
		}


	}
	//-------end---------




	//Mat mat;
	////加载图片 
	//mat = imread("bgs.jpg", CV_LOAD_IMAGE_COLOR);
	//printf("a %d %d", mat.rows, mat.cols);
	////if (!mat.empty()) {


	//int m, n;
	//n = mat.cols * 3;
	//m = mat.rows;
	//unsigned char *data = (unsigned char*)malloc(sizeof(unsigned char) * m * n);
	//int p = 0;
	//for (int i = 0; i < m; i++)
	//{
	//	for (int j = 0; j < n; j++)
	//	{
	//		data[p] = mat.at<unsigned char>(i, j);
	//		p++;
	//	}
	//}
	//*plus1 = p;
	return NULL;
	//return (char*)data;
}


struct RecStruct //数据包 
{
	int size;
	int data_type;
	int cam_no;
	int error_code;
	char recvbuf[1500];
};
struct SendStcuct
{
	int size;
	int data_type;
	int cam_no;
	char sendbuf[1000];
}data_send;






static ErrorCallBack g_errorcall = 0;
static CamInfoCallBack g_caminfocall = 0;


typedef struct CameraInfo
{
	std::ofstream foutV;
	int timeInHour = -1;
}caminfo;
std::map<int, CameraInfo*> cameraMap;
//static std::map<int, queue<RecStruct*>> namemap;


static SOCKET g_sockClient;
HANDLE hMutex;
//char* deviceId;
/**判断str1是否以str2开头
* 如果是返回1
* 不是返回0
* 出错返回-1
* */
int is_begin_with(const char * str1, char *str2)
{
	if (str1 == NULL || str2 == NULL)
		return -1;
	int len1 = strlen(str1);
	int len2 = strlen(str2);
	if ((len1 < len2) || (len1 == 0 || len2 == 0))
		return -1;
	char *p = str2;
	int i = 0;
	while (*p != '\0')
	{
		if (*p != str1[i])
			return 0;
		p++;
		i++;
	}
	return 1;
}


char* Strcpy(char * a, const char * b)
{
	int i = 0;
	while (*b) a[i++] = *b++;
	a[i] = 0;
	return a;
}


int sendcmd(char* data, int cam_no, int type, int size) {


	memset(data_send.sendbuf, 0, 1000);
	//data2send.sendbuf = new char[strlen(data)];
	//memset(data2send.sendbuf, 0, strlen(data));
	data_send.size = size;
	data_send.data_type = type;
	data_send.cam_no = cam_no;
	memcpy(data_send.sendbuf, data, sizeof(char) * (size));
	printf("data_send len %d\n", sizeof(data_send));
	if (g_sockClient)
		send(g_sockClient, (char *)&data_send, sizeof(struct SendStcuct), 0);
	return 0;
}
int set_callback(ErrorCallBack terrorcall(int error_type, int cam_no, int err_no, int msg_level, char* msg_txt, int spare)) {
	g_errorcall = (ErrorCallBack)terrorcall;
	return 0;
}
MYLIBDLL int getcameralist(int type, CamInfoCallBack caminfocall(int cam_no, char* cam_info, int cam_info_size)) {
	g_caminfocall = (CamInfoCallBack)caminfocall;
	SendStcuct data_send;
	memset(&data_send, 0, sizeof(struct SendStcuct));
	data_send.size = 20;
	data_send.data_type = 1;
	data_send.cam_no = 0;
	char* data = "getcameralist";
	memcpy(data_send.sendbuf, data, sizeof(char) * (20));
	printf("data_send len %d\n", sizeof(data_send));
	if (g_sockClient)
		send(g_sockClient, (char *)&data_send, sizeof(struct SendStcuct), 0);
	return 0;
}
DWORD WINAPI RecvThread(LPVOID lpParameter);
DWORD WINAPI RecvThread(LPVOID lpParameter){
	SOCKET sockClient = (SOCKET)lpParameter;
	while (1) {
		RecStruct data_recv;
		int ret;
		memset(&data_recv, '0', sizeof(struct RecStruct));
		ret = recv(sockClient, (char *)&data_recv, sizeof(struct RecStruct), 0); //第二个参数使用强制类型,为一个数据包 
		if (ret == 0) // server调用了close 
		{
			printf("server close");
			break;
		}
		else if (ret == SOCKET_ERROR) // 网络错误 
		{
			int err = WSAGetLastError();
			printf("get message %d %d %d \n", ret, SOCKET_ERROR, err);
			if (err == WSAECONNRESET || err == WSAECONNABORTED) {
				printf("tcp error %d %d \n", err, SOCKET_ERROR);
			 //int n = namemap.erase(deviceId);//如果删除了会返回1,否则返回0 
			}
			break;


		}
		//printf("reve type %d %d", data_recv.data_type, data_recv.size);
		switch (data_recv.data_type)
		{
		case 1://摄像头列表
		{
			g_caminfocall(data_recv.cam_no, data_recv.recvbuf, data_recv.size);
		}
			break;
		case 3://异常信息
		{
			if (g_errorcall!=0)
				g_errorcall(1, 1, data_recv.error_code,4,NULL,0);
			break;
		}
		case 2:
		{
			char* recemsg = data_recv.recvbuf;
			int is_null = is_begin_with(recemsg, "00000");
			if (is_null == 1) {
				printf("recv type 2 00000");
				continue;
			}
		
			break;
		}
		default:
			break;
		}


		if (ret < 0) {
			printf("WSAStartup() failed!\n");
			return -1;
		}
		Sleep(20);


	}


	return 0;
}






int tcpInit(char* ip, int port)
{
	av_log_set_level(AV_LOG_PANIC);
	WSADATA wsaData;


	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
	{
		printf("初始化Winsock失败");
		return -1;
	}


	SOCKADDR_IN addrSrv;
	addrSrv.sin_family = AF_INET;
	addrSrv.sin_port = htons(port);
	SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);


	int nRecvBuf = 0;//设置为32K
	setsockopt(sockClient, SOL_SOCKET, SO_RCVBUF, (const char*)&nRecvBuf, sizeof(int));
	//setsockopt(sockClient, SOL_SOCKET, SO_RCVBUF, (char *)&nZero, sizeof(nZero));
	inet_pton(AF_INET, ip, &addrSrv.sin_addr.s_addr);
	if (connect(sockClient, (struct sockaddr*)&addrSrv, sizeof(addrSrv)) == -1)
		return -2;
	//throw "连接失败";
	if (SOCKET_ERROR == sockClient) {
		printf("Socket() error:%d", WSAGetLastError());
		return -3;
	}
	g_sockClient = sockClient;
	HANDLE h_thread = CreateThread(NULL, 0, RecvThread, (LPVOID)sockClient, 0, NULL);
	CloseHandle(h_thread);
	return 0;
}


class DeviceInfo {


public:
	string cam_name;
	int cam_no;
	SOCKET sockClient;
};


//Callback 
int read_buffer(void *opaque, uint8_t *buf, int buf_size) {


	DeviceInfo deviceInfo = *((DeviceInfo *)opaque);
	
	int null_count=0;
	int display_count = 0;
	while (1) {
		RecStruct data_recv;
		int ret;
		memset(&data_recv, '0', sizeof(struct RecStruct));


		ret = recv(deviceInfo.sockClient, (char *)&data_recv, sizeof(struct RecStruct), 0); //第二个参数使用强制类型,为一个数据包 
		if (ret == 0) // server调用了close 
		{
			printf("server close");
			break;
		}
		else if (ret == SOCKET_ERROR) // 网络错误 
		{
			printf("get message %d %d \n", ret, SOCKET_ERROR);
			
			int err = WSAGetLastError();
			if (g_errorcall != 0)
				g_errorcall(1, deviceInfo.cam_no, err,4,"socket err",0);
			//if (err == WSAECONNRESET || err == WSAECONNABORTED) {
			// printf("server break %s", deviceId);
			// //int n = namemap.erase(deviceId);//如果删除了会返回1,否则返回0 
			//}
			break;


		}
		if (data_recv.size == 0) {
			null_count++;
			if (null_count %1000==0) {
				if (g_errorcall != 0)
					g_errorcall(1, deviceInfo.cam_no, 0, 2, "data_recv 0", 11);
				printf("reve len=0 type %d\n", data_recv.data_type);
				null_count = 0;
			}
			Sleep(2);
			continue;
		}
		else if (data_recv.size >1500) {
			if (g_errorcall != 0)
				g_errorcall(1, deviceInfo.cam_no, 0, 2, "data_recv too long", data_recv.size);
			printf("reve data too long %d\n", data_recv.size);
			continue;
		}
		if (data_recv.data_type == 3)
		{
			if (g_errorcall) {
				char err_str[10];
				_itoa(data_recv.error_code, err_str, 10); //正确解法一
				g_errorcall(1, deviceInfo.cam_no, data_recv.error_code, 4, err_str, 0);
			}
		}
		else if (data_recv.data_type == 2)
		{
			null_count=0;
			display_count++;
			char* recemsg = data_recv.recvbuf;
			int is_null = is_begin_with(recemsg, "00000");
			if (is_null == 1) {
				printf("recv 00000");
				continue;
			}
			//printf("cam_no %d", data_recv.cam_no);
			//int cam_no = data_recv.cam_no;
			buf_size = data_recv.size;
			memcpy(buf, data_recv.recvbuf, buf_size);


			if (g_errorcall && buf_size>1000 && display_count%20==0) {
				g_errorcall(2, deviceInfo.cam_no, 1, 0, "rece data", 1);//err_type, cam_no, column, msg_level, msg_txt, spare
				display_count = 0;
			}
			//保存流数据并分小时存储
			time_t tt = time(NULL);//这句返回的只是一个时间cuo
			tm* t = localtime(&tt);
			auto iter = cameraMap.find(deviceInfo.cam_no);
			if (iter != cameraMap.end()){
				iter->second->foutV.write(data_recv.recvbuf, data_recv.size);
				if (t->tm_min == 0 && (iter->second->timeInHour != t->tm_hour)) {
					//判断间隔一小时
					iter->second->timeInHour = t->tm_hour;
					iter->second->foutV.close();
					time_t tt = time(NULL);//这句返回的只是一个时间cuo
					tm* t = localtime(&tt);
					char ctmBegin[20];
					strftime(ctmBegin, 20, "/%Y%m%d%H%M", t);
					char str3[80];
					sprintf(str3, "create data:%s%s%s", deviceInfo.cam_name, ctmBegin, ".dat");
					SLOG1(str3);
					printf("%s", deviceInfo.cam_name + std::string(ctmBegin) + ".dat");
					iter->second->foutV.open(deviceInfo.cam_name + std::string(ctmBegin) + ".dat", ios::binary);
				}
			}
			return buf_size;
		}
		if (ret < 0) {
			printf("WSAStartup() failed!\n");
			continue;
			//return 0;
		}
	}
	return 0;
}


int send_cmd(int cam_no,int size,int datatype,char* cam_name, SOCKET& sockClient) {
	SendStcuct data_send;
	memset(&data_send, 0, sizeof(struct SendStcuct));
	data_send.size = size;
	data_send.data_type = datatype;
	data_send.cam_no = cam_no;
	memcpy(data_send.sendbuf, cam_name, sizeof(char) * (size));
	printf("data_send len %d\n", sizeof(data_send));


	send(sockClient, (char *)&data_send, sizeof(struct SendStcuct), 0);
	return 0;
}


int tcp_recv_conn(char* ip, int port, char* cam_name, int size, int cam_no, FrameFunc tcallback(char* a, int size, int cam_no, int height, int width))
{
	WSADATA wsaData;


	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
	{
		printf("初始化Winsock失败");
		return -1;
	}


	SOCKADDR_IN addrSrv;
	addrSrv.sin_family = AF_INET;
	addrSrv.sin_port = htons(port);
	SOCKET	sockClient = socket(AF_INET, SOCK_STREAM, 0);


	int nRecvBuf = 0;//设置为32K
	setsockopt(sockClient, SOL_SOCKET, SO_RCVBUF, (const char*)&nRecvBuf, sizeof(int));
	setsockopt(sockClient, SOL_SOCKET, SO_SNDBUF, (char *)&nRecvBuf, sizeof(int));
	inet_pton(AF_INET, ip, &addrSrv.sin_addr.s_addr);
	if (connect(sockClient, (struct sockaddr*)&addrSrv, sizeof(addrSrv)) == -1)
		return -2;
	//throw "连接失败";
	if (SOCKET_ERROR == sockClient) {
		printf("Socket() error:%d", WSAGetLastError());
		return -3;
	}
	
	DeviceInfo deviceInfo;
	deviceInfo.cam_no = cam_no;
	deviceInfo.sockClient = sockClient;
	av_register_all();
	unsigned version = avcodec_version();
	//printf("FFmpeg version: %d\n", version);


	//初始化流文件状态
	time_t tt = time(NULL);//这句返回的只是一个时间cuo
	tm* t = localtime(&tt);
	char ctmBegin[20];
	strftime(ctmBegin, 20, "/%Y%m%d%H%M", t);
	caminfo cinfoInstance;
	deviceInfo.cam_name = cam_name;
	//std::string dataName = cam_name;
	cinfoInstance.foutV.open(cam_name + std::string(ctmBegin) + ".dat", ios::binary);
	//判断间隔一小时
	cinfoInstance.timeInHour = t->tm_hour;
	cameraMap[cam_no] = &cinfoInstance;
	char str3[20];
	sprintf(str3, "camno: %d start", cam_no);
	SLOG1(str3);
	AVFormatContext *pFormatCtx;
	int   i, videoindex;
	AVCodecContext *pCodecCtx;
	AVCodec  *pCodec;
	char filepath[] = "video.264";
	//av_register_all();
	avformat_network_init();
	pFormatCtx = avformat_alloc_context();
	//patha = "C:\\Users\\sbd01\\Pictures\\ffmpegtest\\Debug\\video.dat";


	//fp_open = fopen(patha.c_str(), "rb+");
	unsigned char *aviobuffer = (unsigned char *)av_malloc(1512);
	
	send_cmd(cam_no, size,2,cam_name, sockClient);
	AVIOContext *avio = avio_alloc_context(aviobuffer, 1512, 0, &deviceInfo, read_buffer, NULL, NULL);


	pFormatCtx->pb = avio;
	//if (avformat_open_input(&pFormatCtx, patha.c_str(), NULL, NULL) != 0) {
	if (avformat_open_input(&pFormatCtx, NULL, NULL, NULL) != 0) {
		printf("Couldn't open input stream %d\n", cam_no);
		return -1;
	}
	printf("camno %d find stream\n", cam_no);
	pFormatCtx->probesize = 1000 * 1024;
	pFormatCtx->max_analyze_duration = 10 * AV_TIME_BASE;


	pCodec = NULL;
	while (pCodec == NULL) {
		printf("%d start find stream info \n", cam_no);
		if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
			printf("Couldn't find stream info %d\n", cam_no);
			goto restart_stream;
			continue;
		}
		videoindex = -1;
		for (i = 0; i < pFormatCtx->nb_streams; i++)
			if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
				if (videoindex == -1) {
					videoindex = i;
				}
				//break;
			}
		if (videoindex == -1) {
			printf("%d Didn't find a video stream.\n", cam_no);
			goto restart_stream;
		}
		pCodecCtx = pFormatCtx->streams[videoindex]->codec;
		//pCodec = avcodec_find_decoder(AV_CODEC_ID_H264);
		
		pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
		if (pCodec == NULL) {
			printf("%d Codec not found \n", cam_no);
			goto restart_stream;
			//return -1;
		}
		if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
			printf("%d Could not open codec.\n", cam_no);
			goto restart_stream;
			continue;
			//return -1;
		}
		if (pCodecCtx->width <= 0 || pCodecCtx->height <= 0 || pCodecCtx->height >2000 || pCodecCtx->width >3000) {
			printf("cam %d pCodecCtx error 1 width %d height %d ", cam_no, pCodecCtx->width, pCodecCtx->height);
			goto restart_stream;
		}
		goto ok;
	restart_stream:
		printf("%d restart 1 ", cam_no);
		avformat_free_context(pFormatCtx);
		printf("restart 2 ");
		//avformat_close_input(&pFormatCtx);
		pFormatCtx = NULL;
		pFormatCtx = avformat_alloc_context();
		printf("restart 3 ");
		//av_freep(aviobuffer);
		//printf("restart 4");
		aviobuffer = (unsigned char *)av_malloc(1512);
		printf("restart 4 ");
		AVIOContext *avio2 = avio_alloc_context(aviobuffer, 1512, 0, &deviceInfo, read_buffer, NULL, NULL);
		pFormatCtx->pb = avio2;
		pFormatCtx->probesize = 1000 * 1024;
		pFormatCtx->max_analyze_duration = 10 * AV_TIME_BASE;
		if (avformat_open_input(&pFormatCtx, NULL, NULL, NULL) != 0) {
			printf("2Couldn't open input stream %d\n", cam_no);
			//return -1;
		}
		printf("restart 5\n");
		pCodec = NULL;
		continue;
	ok:
		break;
	}


	printf("camno:%d code name :%s width %d height %d\n",cam_no, pCodec->name, pCodecCtx->width, pCodecCtx->height);
	AVFrame *pFrame, *pFrameYUV;
	pFrame = av_frame_alloc();
	pFrameYUV = av_frame_alloc();
	int ret, got_picture;


	if (g_errorcall) {
		char* cc;
		int length = strlen(pCodec->name);
		cc = new char[length + 1];
		strcpy(cc, pCodec->name);
		g_errorcall(0, cam_no, pCodecCtx->width, pCodecCtx->height, cc, 11);
	}
	AVPacket *packet = (AVPacket *)av_malloc(sizeof(AVPacket));
	struct SwsContext *img_convert_ctx;
	img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
	uint8_t *out_buffer;
	printf("cam %d ready decode 2", cam_no);
	out_buffer = new uint8_t[avpicture_get_size(AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height)];
	avpicture_fill((AVPicture *)pFrameYUV, out_buffer, AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);


	//av_image_fill_arrays(pFrameYUV->data, pFrameYUV->linesize, out_buffer, AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height, 1);
	printf("cam %d ready decode 3", cam_no);
	int dec_error_count = 0;
	int tmp_test = 0;
	while (av_read_frame(pFormatCtx, packet) >= 0) {
		if (packet->stream_index == videoindex) {
			//tmp_test++;
			if (packet->size < 50) {
				av_free_packet(packet);
				//printf("cam:%d packet is too small %d\n", cam_no, packet->size);
				Sleep(3);
				continue;
			}
			if (g_errorcall != 0)
				g_errorcall(2, deviceInfo.cam_no, 1, 2, "start decode",3);
			char str_decode[40];
			sprintf(str_decode, "cam %d start decode", cam_no);
			SLOG1(str_decode);
			ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
			if (ret < 0) {
				dec_error_count++;
				char str3[80];
				sprintf(str3, "%d%s decode_error:%d error_count %d", cam_no, " Decode Error", ret, dec_error_count);
				SLOG1(str3);
				if (g_errorcall != 0)
					g_errorcall(1, deviceInfo.cam_no, 0, 2, str3, 80);
				printf("cam:%d Decode Error got_picture %d decode_error_num %d\n", cam_no, got_picture, dec_error_count);
				if (dec_error_count > 2) {
				dec_error_count = 0;
					// restart ffmpeg
				av_free_packet(packet);


				Sleep(50);
				sws_freeContext(img_convert_ctx);
				img_convert_ctx = NULL;
				printf("cam %d sws_freeContext 1\n", cam_no);
				//av_free(out_buffer); 
				//av_free(pFrameYUV);
				avcodec_close(pCodecCtx);
				//pCodecCtx = NULL;
				if (avcodec_open2(pCodecCtx, pCodec, NULL)<0) {
					printf("Could not open codec.\n");
					return -1;
				}
				/*pFrame = av_frame_alloc();
				pFrameYUV = av_frame_alloc();*/


				//packet = (AVPacket *)av_malloc(sizeof(AVPacket));
				printf("cam_no %d avcodec_open2 ok width:%d height:%d\n", cam_no, pCodecCtx->width, pCodecCtx->height);
				img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
				
				char str3[40];
				sprintf(str3, "ffmpeg restart cam %d ", cam_no);
				SLOG1(str3);
				continue;
				}
			}
			if (got_picture) {
				if (g_errorcall != 0)
					g_errorcall(2, deviceInfo.cam_no, 1, 2, "got_picture",4);
				char str3[40];
				sprintf(str3, "cam %d got_picture", cam_no);
				SLOG1(str3);
				sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);


				/*fwrite(pFrameYUV->data[0], (pCodecCtx->width)*(pCodecCtx->height) * 3, 1, output);*/


				tcallback((char*)pFrameYUV->data[0], pCodecCtx->height * pCodecCtx->width * 3, cam_no, pCodecCtx->height, pCodecCtx->width);


			}
		}
		av_free_packet(packet);
		Sleep(10);
	}
	sws_freeContext(img_convert_ctx);


	//av_free(out_buffer); 
	av_free(pFrameYUV);
	avcodec_close(pCodecCtx);
	avformat_close_input(&pFormatCtx);
	return 0;
}


int tcp_init(char* ip, int port) {
	int res = tcpInit(ip, port);
	//printf("conn server\t%d\n", res);
	return res;
}




int ffmpeg_recv(int cam_no, FrameFunc tcallback(char* a, int size, int cam_no, int height, int width))
{
	av_register_all();
	unsigned version = avcodec_version();


	printf("FFmpeg version: %d\n", version);


	AVFormatContext *pFormatCtx;
	int   i, videoindex;
	AVCodecContext *pCodecCtx;
	AVCodec  *pCodec;
	char filepath[] = "video.264";
	avformat_network_init();
	pFormatCtx = avformat_alloc_context();
	//string patha = "C:\\Users\\sbd01\\Videos\\video.264";


	//fp_open = fopen(patha.c_str(), "rb+");
	unsigned char *aviobuffer = (unsigned char *)av_malloc(1512);
	AVIOContext *avio = avio_alloc_context(aviobuffer, 1512, 0, &cam_no, read_buffer, NULL, NULL);


	pFormatCtx->pb = avio;
	if (avformat_open_input(&pFormatCtx, NULL, NULL, NULL) != 0) {
		printf("Couldn't open input stream.\n");
		return -1;
	}
	if (avformat_find_stream_info(pFormatCtx, NULL)<0) {
		printf("Couldn't find stream information.\n");
		return -1;
	}
	videoindex = -1;
	for (i = 0; i<pFormatCtx->nb_streams; i++)
		if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
			videoindex = i;
			break;
		}
	if (videoindex == -1) {
		printf("Didn't find a video stream.\n");
		return -1;
	}
	pCodecCtx = pFormatCtx->streams[videoindex]->codec;
	pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
	if (pCodec == NULL) {
		printf("Codec not found.\n");
		return -1;
	}
	if (avcodec_open2(pCodecCtx, pCodec, NULL)<0) {
		printf("Could not open codec.\n");
		return -1;
	}
	AVFrame *pFrame, *pFrameYUV;
	pFrame = av_frame_alloc();
	pFrameYUV = av_frame_alloc();


	int ret, got_picture;


	AVPacket *packet = (AVPacket *)av_malloc(sizeof(AVPacket));


	struct SwsContext *img_convert_ctx;
	img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);


	uint8_t *out_buffer;


	out_buffer = new uint8_t[avpicture_get_size(AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height)];
	avpicture_fill((AVPicture *)pFrameYUV, out_buffer, AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);


	while (av_read_frame(pFormatCtx, packet) >= 0) {
		if (packet->stream_index == videoindex) {
			ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
			if (ret < 0) {
				printf("Decode Error.\n");
				return -1;
			}
			if (got_picture) {
				sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);


				/*fwrite(pFrameYUV->data[0], (pCodecCtx->width)*(pCodecCtx->height) * 3, 1, output);*/
				tcallback((char*)pFrameYUV->data[0], pCodecCtx->height * pCodecCtx->width * 3, cam_no, pCodecCtx->height, pCodecCtx->width);
			}
		}
		av_free_packet(packet);
	}
	sws_freeContext(img_convert_ctx);


	//fclose(fp_open);


	//SDL_Quit();


	//av_free(out_buffer); 
	av_free(pFrameYUV);
	avcodec_close(pCodecCtx);
	avformat_close_input(&pFormatCtx);
	return 0;
}








//Callback 
int file_buffer(void *opaque, uint8_t *buf, int buf_size) {


	FILE *fp_open = (FILE *)opaque;
	if (!feof(fp_open)) {
		int true_size = fread(buf, 1, buf_size, fp_open);
		return true_size;
	}
	else {
		return -1;
	}


}
int play_file(char* file_name, FrameFunc tcallback(char* a, int size,int num, int height, int width))
{
	av_register_all();
	unsigned version = avcodec_version();


	printf("FFmpeg version: %d\n", version);


	AVFormatContext *pFormatCtx;
	int   i, videoindex;
	AVCodecContext *pCodecCtx;
	AVCodec  *pCodec;
	char filepath[] = "video.264";
	//av_register_all();
	avformat_network_init();
	pFormatCtx = avformat_alloc_context();
	string patha = "C:\\Users\\sbd01\\Videos\\video.264";
	//patha = "C:\\Users\\sbd01\\Pictures\\ffmpegtest\\Debug\\video.dat";
	FILE *fp_open = fopen(file_name, "rb+");
	unsigned char *aviobuffer = (unsigned char *)av_malloc(32768);
	//printf("avio_alloc_context %d\n", cam_no);
	AVIOContext *avio = avio_alloc_context(aviobuffer, 32768, 0, (void*)fp_open, file_buffer, NULL, NULL);


	pFormatCtx->pb = avio;
	//if (avformat_open_input(&pFormatCtx, patha.c_str(), NULL, NULL) != 0) {
	if (avformat_open_input(&pFormatCtx, NULL, NULL, NULL) != 0) {
		printf("Couldn't open input stream.\n");
		return -1;
	}
	if (avformat_find_stream_info(pFormatCtx, NULL)<0) {
		printf("Couldn't find stream information.\n");
		return -1;
	}
	videoindex = -1;
	for (i = 0; i<pFormatCtx->nb_streams; i++)
		if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
			videoindex = i;
			break;
		}
	if (videoindex == -1) {
		printf("Didn't find a video stream.\n");
		return -1;
	}
	pCodecCtx = pFormatCtx->streams[videoindex]->codec;
	pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
	if (pCodec == NULL) {
		printf("Codec not found.\n");
		return -1;
	}
	if (avcodec_open2(pCodecCtx, pCodec, NULL)<0) {
		printf("Could not open codec.\n");
		return -1;
	}
	AVFrame *pFrame, *pFrameYUV;
	pFrame = av_frame_alloc();
	pFrameYUV = av_frame_alloc();


	/*if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
	printf("Could not initialize SDL - %s\n", SDL_GetError());
	return -1;
	}*/


	/*int screen_w = 0, screen_h = 0;
	SDL_Surface *screen;
	screen_w = pCodecCtx->width;
	screen_h = pCodecCtx->height;
	screen = SDL_SetVideoMode(screen_w, screen_h, 0, 0);


	if (!screen) {
	printf("SDL: could not set video mode - exiting:%s\n", SDL_GetError());
	return -1;
	}
	SDL_Overlay *bmp;
	bmp = SDL_CreateYUVOverlay(pCodecCtx->width, pCodecCtx->height, SDL_YV12_OVERLAY, screen);
	SDL_Rect rect;
	rect.x = 0;
	rect.y = 0;
	rect.w = screen_w;
	rect.h = screen_h;*/
	//SDL End------------------------ 
	int ret, got_picture;


	AVPacket *packet = (AVPacket *)av_malloc(sizeof(AVPacket));


	struct SwsContext *img_convert_ctx;
	img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);


	uint8_t *out_buffer;


	out_buffer = new uint8_t[avpicture_get_size(AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height)];
	avpicture_fill((AVPicture *)pFrameYUV, out_buffer, AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);


	while (av_read_frame(pFormatCtx, packet) >= 0) {
		if (packet->stream_index == videoindex) {
			ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
			if (ret < 0) {
				printf("Decode Error.\n");
				return -1;
			}
			if (got_picture) {
				sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);


				/*fwrite(pFrameYUV->data[0], (pCodecCtx->width)*(pCodecCtx->height) * 3, 1, output);*/


				tcallback((char*)pFrameYUV->data[0], pCodecCtx->height * pCodecCtx->width * 3, 1, pCodecCtx->height, pCodecCtx->width);




			}
		}
		av_free_packet(packet);
	}
	sws_freeContext(img_convert_ctx);
	//fclose(fp_open);
	//SDL_Quit();


	//av_free(out_buffer); 
	av_free(pFrameYUV);
	avcodec_close(pCodecCtx);
	avformat_close_input(&pFormatCtx);
	return 0;
}

以上这篇python opencv图片编码为h264文件的实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python实现自动登录人人网并采集信息的方法
Jun 28 Python
python非递归全排列实现方法
Apr 10 Python
解决python3 urllib 链接中有中文的问题
Jul 16 Python
Python 数据库操作 SQLAlchemy的示例代码
Feb 18 Python
Python3中exp()函数用法分析
Feb 19 Python
python 弹窗提示警告框MessageBox的实例
Jun 18 Python
Python Matplotlib 基于networkx画关系网络图
Jul 10 Python
在python中用url_for构造URL的方法
Jul 25 Python
Python中的wordcloud库安装问题及解决方法
May 27 Python
解决pyinstaller 打包exe文件太大,用pipenv 缩小exe的问题
Jul 13 Python
Python爬虫爬取ts碎片视频+验证码登录功能
Feb 22 Python
用Python selenium实现淘宝抢单机器人
Jun 18 Python
Python pygame绘制文字制作滚动文字过程解析
Dec 12 #Python
详解python 中in 的 用法
Dec 12 #Python
python调用c++返回带成员指针的类指针实例
Dec 12 #Python
在Python中实现函数重载的示例代码
Dec 12 #Python
django框架F&amp;Q 聚合与分组操作示例
Dec 12 #Python
使用OpenCV-python3实现滑动条更新图像的Canny边缘检测功能
Dec 12 #Python
django框架使用views.py的函数对表进行增删改查内容操作详解【models.py中表的创建、views.py中函数的使用,基于对象的跨表查询】
Dec 12 #Python
You might like
探讨PHP JSON中文乱码的解决方法详解
2013/06/06 PHP
php实现cc攻击防御和防止快速刷新页面示例
2014/02/13 PHP
php过滤敏感词的示例
2014/03/31 PHP
兼容PHP和Java的des加密解密代码分享
2014/06/26 PHP
PHP环境搭建(php+Apache+mysql)
2016/11/14 PHP
PHP新特性之字节码缓存和内置服务器
2017/08/11 PHP
JQUERY的属性选择符和自定义选择符使用方法(二)
2011/04/07 Javascript
jquery必须知道的一些常用特效方法及使用示例(整理)
2013/06/24 Javascript
JavaScript禁止页面操作的示例代码
2013/12/17 Javascript
基于jquery实现简单的分页控件
2016/03/17 Javascript
JavaScript 输出显示内容(document.write、alert、innerHTML、console.log)
2016/12/14 Javascript
Bootstrap CSS布局之列表
2016/12/15 Javascript
node.js(express)中使用Jcrop进行图片剪切上传功能
2017/04/21 Javascript
ionic 自定义弹框效果
2017/06/27 Javascript
Vue使用vue-cli创建项目
2017/09/01 Javascript
详解一次Vue低版本安卓白屏问题的解决过程
2019/05/30 Javascript
详解vue微信网页授权最终解决方案
2019/06/16 Javascript
微信小程序上传帖子的实例代码(含有文字图片的微信验证)
2020/07/11 Javascript
[01:22:29]真视界:2019年国际邀请赛总决赛
2020/01/29 DOTA
pydev使用wxpython找不到路径的解决方法
2013/02/10 Python
linux下python抓屏实现方法
2015/05/22 Python
python和pygame实现简单俄罗斯方块游戏
2021/02/19 Python
Python之Class&amp;Object用法详解
2019/12/25 Python
Python如何向SQLServer存储二进制图片
2020/06/08 Python
keras 简单 lstm实例(基于one-hot编码)
2020/07/02 Python
PyTorch: Softmax多分类实战操作
2020/07/07 Python
美国最大的高尔夫发球时间预订网站:TeeOff.com
2018/03/28 全球购物
德国药房apodiscounter中文官网:德国排名前三的网上药店
2019/06/03 全球购物
儿科主治医生个人求职信
2013/09/23 职场文书
专科文秘应届生求职信
2013/11/18 职场文书
任命书格式
2014/06/05 职场文书
对外汉语专业大学生职业生涯规划书
2014/10/11 职场文书
2014年党员发展工作总结
2014/12/02 职场文书
商务宴请邀请函范文
2015/02/02 职场文书
文案策划岗位职责
2015/02/11 职场文书
浅谈MySQL函数
2021/10/05 MySQL