check_tool.cpp1 5.5 KB
#include"check_tool.h"

extern "C"
{
	#include <libavcodec/avcodec.h> 
	#include <libavdevice/avdevice.h> 
	#include <libavformat/avformat.h> 
	#include <libavfilter/avfilter.h> 
	#include <libavutil/avutil.h> 
    #include <libavutil/pixdesc.h> 
	#include <libswscale/swscale.h>
    #include <libavutil/imgutils.h>
}

#include <chrono>


static long long get_cur_time(){
    // 获取操作系统当前时间点(精确到微秒)
    chrono::time_point<chrono::system_clock, chrono::milliseconds> tpMicro
        = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now());
    // (微秒精度的)时间点 => (微秒精度的)时间戳
    time_t currentTime = tpMicro.time_since_epoch().count();

    return (long long )currentTime;
}

void save_pkt(const string& uri){
	AVFormatContext* ifmt_ctx = nullptr;
	AVCodecContext* codec_ctx = nullptr;
	AVCodec *decoder = nullptr;
	AVCodec* codec = nullptr;
	AVPacket* pkt = nullptr;
	int video_index = -1;
	AVStream* i_video_stream = nullptr;
	SwsContext *img_convert_ctx = nullptr;
	uint8_t *buffer = nullptr;
    int numBytes = 0;

	long start_time = 0;
	long end_time = 0;
	long s_time = 0;
	long e_time = 0;
	long long sum = 0;
	double avg_time = 0.0;

	int sep = 0;

	AVFormatContext *o_fmt_ctx;
	AVStream *o_video_stream;

	const char *filename = "test.mp4";
 

	avformat_network_init();

	// 打开输入视频文件
	AVDictionary *options = nullptr;
	av_dict_set( &options, "bufsize", "655360", 0 );
	av_dict_set( &options, "rtsp_transport", "tcp", 0 );
	// av_dict_set( &options, "listen_timeout", "30", 0 ); // 单位为s
	av_dict_set( &options, "stimeout", "30000000", 0 ); // 单位为 百万分之一秒
	
	///打开输入的流
	ifmt_ctx = avformat_alloc_context();
	int ret = avformat_open_input(&ifmt_ctx, uri.c_str(), nullptr, &options);
	if (ret != 0){
		av_log(nullptr, AV_LOG_ERROR, "Couldn't open input stream ! \n");
		goto end_flag ;
	}
 
	//查找流信息
	if (avformat_find_stream_info(ifmt_ctx, nullptr) < 0){
		av_log(nullptr, AV_LOG_ERROR, "Couldn't find stream information ! \n");
		goto end_flag ;
	}

	// 查找视频流信息
	video_index = av_find_best_stream(ifmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &decoder, 0);
	if (video_index < 0) {
		av_log(nullptr, AV_LOG_ERROR, "Cannot find a video stream in the input file ! \n");
		goto end_flag ;
	}
    
    //申请AVCodecContext
    codec_ctx = avcodec_alloc_context3(decoder);
    if (!codec_ctx){
        goto end_flag ;
    }
 
	i_video_stream = ifmt_ctx->streams[video_index];
	if(avcodec_parameters_to_context(codec_ctx, i_video_stream->codecpar) < 0){
		goto end_flag ;
	}

	{
		av_log(nullptr, AV_LOG_INFO, "path: %s \n", ifmt_ctx->url);
		av_log(nullptr, AV_LOG_INFO, "format: %s \n", ifmt_ctx->iformat->name);
		const char* profile = avcodec_profile_name(codec_ctx->codec_id, codec_ctx->profile);
		av_log(nullptr, AV_LOG_INFO, "codec: %s(%s) \n", decoder->name, profile);
		const char* pix_fmt_name = av_get_pix_fmt_name(codec_ctx->pix_fmt);
		av_log(nullptr, AV_LOG_INFO, "pix_fmt_name: %s \n", pix_fmt_name);
		av_log(nullptr, AV_LOG_INFO, "width x height: %dX%d \n", i_video_stream->codecpar->width, i_video_stream->codecpar->height);

		av_log(NULL, AV_LOG_INFO, "frame_rate: %1.0f ", av_q2d(i_video_stream->r_frame_rate));
		av_log(NULL, AV_LOG_INFO, "  -->  reference PPS: %f ms\n", 1/av_q2d(i_video_stream->r_frame_rate) * 1000);
	}


	avformat_alloc_output_context2(&o_fmt_ctx, NULL, NULL, filename);

    /*
        * since all input files are supposed to be identical (framerate, dimension, color format, ...)
        * we can safely set output codec values from first input file
        */
    o_video_stream = avformat_new_stream(o_fmt_ctx, NULL);
    {
        AVCodecContext *c;
        c = o_video_stream->codec;
        c->bit_rate = 400000;
        c->codec_id = i_video_stream->codec->codec_id;
        c->codec_type = i_video_stream->codec->codec_type;
        c->time_base.num = i_video_stream->time_base.num;
        c->time_base.den = i_video_stream->time_base.den;
        fprintf(stderr, " = time_base.num = %d time_base.den = %d\n", c->time_base.num, c->time_base.den);
        c->width = i_video_stream->codec->width;
        c->height = i_video_stream->codec->height;
        c->pix_fmt = i_video_stream->codec->pix_fmt;
        printf(" = width: %d height: %d pix_fmt: %d\n", c->width, c->height, c->pix_fmt);
        c->flags = i_video_stream->codec->flags;
        c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
        c->me_range = i_video_stream->codec->me_range;
        c->max_qdiff = i_video_stream->codec->max_qdiff;

        c->qmin = i_video_stream->codec->qmin;
        c->qmax = i_video_stream->codec->qmax;

        c->qcompress = i_video_stream->codec->qcompress;
    }

    avio_open(&o_fmt_ctx->pb, filename, AVIO_FLAG_WRITE);

    avformat_write_header(o_fmt_ctx, NULL);

	
	s_time = get_cur_time();
	start_time = get_cur_time();
	pkt = av_packet_alloc();
	while (av_read_frame(ifmt_ctx, pkt) >= 0){
		end_time = get_cur_time();
		sum ++ ;
		sep ++ ;
		if(end_time - start_time > 1000){
			avg_time = double(end_time - start_time) / sep;
			start_time = get_cur_time();
			sep = 0;
			av_log(nullptr, AV_LOG_INFO, "PPS: %f ms\n", avg_time);
		}
		av_packet_unref(pkt);
	}

	e_time = get_cur_time();
	avg_time = double(e_time - s_time) / sum;
	av_log(nullptr, AV_LOG_INFO, "TOOTAL PPS: %f ms\n", avg_time);

end_flag:
	if (codec_ctx != nullptr){
		avcodec_close(codec_ctx);
		avcodec_free_context(&codec_ctx);
	}
	
	if (ifmt_ctx != nullptr){
		avformat_close_input(&ifmt_ctx);
	}

	if (pkt != nullptr){
		av_packet_free(&pkt);
	}
}