天天看点

pybind 播放h264

python:

平均耗时在30s左右,没有cpython快。

#-*- coding:utf-8 -*-
import pyiotsdk as binddemo
import time
import numpy as np
filepath="0217.h264"
import cv2
start=time.time()
def m_callback(a,width,height,t1):
    global start
    # print(a)
    cv2.imshow("a",a)
    cv2.waitKeyEx(1)
    print('callback ok', width,height,time.time()-start,t1)
    start=time.time()
    return 0
    # print('callback ok',a)


# filename=b'rtsp://admin:[email protected]:554/h264/ch1/main/av_stream'
filename=r"D:\project\hik_client_dll_4\x64\Debug\201805171600.dat"

# aaa= binddemo.proxy_init3F(3.0)
# aaa=aaa.astype(np.uint8)
# print(aaa.shape)
# # aaa=cv2.imread("d:/f1.jpg")
# cv2.imshow("a",aaa)
# cv2.waitKeyEx()
# print(aaa)
binddemo.play_url(filename, m_callback)
# vp= binddemo.add(1280, 720, aaa)

#
# m = [[[0] * 2 for _ in range(3) ] for _ in range(4)]
# print(m)
           

c++ ffmpeg 4

int play_url(char* url, py::function callback_f)
{

	av_log_set_level(AV_LOG_WARNING);
	unsigned version = avcodec_version();

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

	AVFormatContext *avFormatCtx = NULL;
	int            i, videoindex;
	AVCodecContext  *avCodecCtx = NULL;
	AVCodec        *avCodec;
	avformat_network_init();
	AVDictionary* options = NULL;
	av_dict_set(&options, "buffer_size", "1024000", 0);
	//av_dict_set(&options, "max_delay", "500000", 0);
	//av_dict_set(&options, "stimeout", "20000000", 0);  //设置超时断开连接时间
	av_dict_set(&options, "rtsp_transport", "udp", 0);  //以udp方式打开,如果以tcp方式打开将udp替换为tcp  
	if (avformat_open_input(&avFormatCtx, url, NULL, &options) != 0) {
	//if (avformat_open_input(&avFormatCtx, url, NULL, NULL) != 0) {
		printf("Couldn't open input stream.\n");
		return -1;
	}
	avCodec = NULL;
	while (avCodec == NULL) {
		printf("start find stream info \n");
		if (avformat_find_stream_info(avFormatCtx, NULL) < 0) {
			printf("Couldn't find stream info\n");
			goto restart_stream;
			continue;
		}
		videoindex = -1;
		for (i = 0; i < avFormatCtx->nb_streams; i++)
			if (avFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
				if (videoindex == -1) {
					videoindex = i;
				}
				//break;
			}
		if (videoindex == -1) {
			printf("Didn't find a video stream.\n");
			goto restart_stream;
		}
		avCodecCtx = avcodec_alloc_context3(NULL);
		avcodec_parameters_to_context(avCodecCtx, avFormatCtx->streams[videoindex]->codecpar);
		av_opt_set(avCodecCtx->priv_data, "preset", "ultrafast", 0);
		av_opt_set(avCodecCtx->priv_data, "tune", "zerolatency", 0);  //
		avCodec = avcodec_find_decoder(avCodecCtx->codec_id);
		if (avCodec == NULL) {
			printf("Codec not found \n");
			goto restart_stream;
			//return -1;
		}
		if (avcodec_open2(avCodecCtx, avCodec, NULL) < 0) {
			printf("Could not open codec.\n");
			goto restart_stream;
			continue;
			//return -1;
		}
		goto ok;
	restart_stream:
		printf("restart 1  ");
		avformat_free_context(avFormatCtx);
		printf("restart 2  ");
		//avformat_close_input(&pFormatCtx);
		avFormatCtx = NULL;
		avFormatCtx = avformat_alloc_context();
		printf("restart 3  ");
		//printf("restart 4");
		printf("restart 4  ");

		int open_ret = avformat_open_input(&avFormatCtx, url, NULL, NULL);
		if (open_ret != 0) {
			printf("2Couldn't open input stream %d\n", open_ret);
			return -1;
		}
		avFormatCtx->probesize = 1000 * 1024;
		avFormatCtx->max_analyze_duration = 10 * AV_TIME_BASE;
		printf("restart 5\n");
		avCodec = NULL;
		continue;
	ok:
		break;
	}

	AVFrame *pFrameYUV;
	AVFrame *pFrameRGB;
	pFrameYUV = av_frame_alloc();
	pFrameRGB = av_frame_alloc();


	uint8_t *out_buffer;

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

	out_buffer = new uint8_t[avpicture_get_size(AV_PIX_FMT_RGB24, avCodecCtx->width, avCodecCtx->height)];
	//avpicture_fill((AVPicture *)pFrameRGB, out_buffer, AV_PIX_FMT_RGB24, avCodecCtx->width, avCodecCtx->height);
	av_image_fill_arrays(pFrameRGB->data, pFrameRGB->linesize, out_buffer, AV_PIX_FMT_RGB24, avCodecCtx->width, avCodecCtx->height, 1);

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

	int need_decode = 1;
	int is_key_frame = 0;
	DWORD start_time = GetTickCount();
	while (av_read_frame(avFormatCtx, &packet) >= 0) {
		if (packet.stream_index == videoindex) {
		
			if (avcodec_send_packet(avCodecCtx, &packet) != 0) {
				printf("avcodec_send_packet错误\n");
				break;
			}
			while (avcodec_receive_frame(avCodecCtx, pFrameYUV) == 0) {


				printf("decode ok %d %u\n", avCodecCtx->flags, GetTickCount() - start_time);
				start_time = GetTickCount();

				sws_scale(img_convert_ctx, pFrameYUV->data, pFrameYUV->linesize, 0, avCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);

			
				/*fwrite(pFrameYUV->data[0], (pCodecCtx->width)*(pCodecCtx->height) * 3, 1, output);*/
			
				py::array_t<uint8_t> result(avCodecCtx->height *avCodecCtx->width* 3 );//h w c
			   //std:s:fill(result.mutable_data(), vptr, 720 * 1280 * 3);
				memcpy(result.mutable_data(), pFrameRGB->data[0], avCodecCtx->height *avCodecCtx->width * 3);
							
				//callback_f(data_rgb, 1,  avCodecCtx->width, avCodecCtx->height, GetTickCount());
				callback_f(result, avCodecCtx->width, avCodecCtx->height, GetTickCount());
				//av_frame_free(&pFrameYUV);

			}
		}
		av_packet_unref(&packet);
	}


	avcodec_close(avCodecCtx);
	avformat_close_input(&avFormatCtx);
	return 0;
}
           

继续阅读