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程序与服务器连接的WSGI接口
Apr 29 Python
Python实现二分查找与bisect模块详解
Jan 13 Python
Python基于csv模块实现读取与写入csv数据的方法
Jan 18 Python
利用python实现微信头像加红色数字功能
Mar 26 Python
python requests爬取高德地图数据的实例
Nov 10 Python
django框架用户权限中的session缓存到redis中的方法
Aug 06 Python
wxpython实现按钮切换界面的方法
Nov 19 Python
基于Tensorflow一维卷积用法详解
May 22 Python
Python flask框架实现查询数据库并显示数据
Jun 04 Python
Python enumerate() 函数如何实现索引功能
Jun 29 Python
python使用pywinauto驱动微信客户端实现公众号爬虫
May 19 Python
python函数的两种嵌套方法使用
Apr 02 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
phpMyAdmin 安装及问题总结
2009/05/28 PHP
浅析PHP微信支付通知的处理方式
2014/05/25 PHP
php socket通信简单实现
2016/11/18 PHP
JavaScript中Object和Function的关系小结
2009/09/26 Javascript
基于jQuery的简单九宫格实现代码
2012/08/09 Javascript
JavaScript和CSS通过expression实现Table居中显示
2013/06/28 Javascript
from 表单提交返回值用post或者是get方法实现
2013/08/21 Javascript
常用DOM整理
2015/06/16 Javascript
js识别uc浏览器的代码
2015/11/06 Javascript
利用AJAX实现WordPress中的文章列表及评论的分页功能
2016/05/17 Javascript
Vue.js双向绑定实现原理详解
2016/12/22 Javascript
less简单入门(CSS 预处理语言)
2017/03/08 Javascript
JS简单实现数组去重的方法示例
2017/03/27 Javascript
信息滚动效果的实例讲解
2017/09/18 Javascript
Angular4自制一个市县二级联动组件示例
2017/11/21 Javascript
vue-router实现编程式导航的代码实例
2019/01/19 Javascript
Vue自动构建发布脚本的方法示例
2020/07/24 Javascript
[06:35]2014DOTA2国际邀请赛 老男孩梦圆西雅图中国军团世界最强
2014/07/22 DOTA
Python实现快速排序和插入排序算法及自定义排序的示例
2016/02/16 Python
PyCharm2019 安装和配置教程详解附激活码
2020/07/31 Python
用Python实现职工信息管理系统
2020/12/30 Python
使用numpngw和matplotlib生成png动画的示例代码
2021/01/24 Python
LG西班牙网上商店:Tienda LG Online Es
2019/07/30 全球购物
法国房车租赁网站:Yescapa
2019/08/26 全球购物
联想智利官方网站:Lenovo Chile
2020/06/03 全球购物
物流专业毕业生推荐信范文
2013/11/18 职场文书
寒假实习自荐信
2014/01/26 职场文书
心理健康教育制度
2014/01/27 职场文书
小学庆六一活动方案
2014/02/28 职场文书
担保书格式及范文
2014/04/01 职场文书
个人租房协议书
2014/04/09 职场文书
煤矿安全生产责任书
2014/04/15 职场文书
党的群众路线教育实践活动个人对照检查材料
2014/09/22 职场文书
财务人员廉洁自律心得体会
2016/01/13 职场文书
2017元旦晚会开幕词
2016/03/03 职场文书
Python insert() / append() 用法 Leetcode实战演示
2021/03/31 Python