ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

网络视频流 -- ffmpeg 推流

2020-12-10 16:29:06  阅读:260  来源: 互联网

标签:pkt -- 视频流 ctx base ofmt time av 推流


        一般流媒体服务器自动拉流功能要求较多,需要自己实现rtsp协议中较多部分,而ffmpeg本身rtsp拉流配置支持不好,本着站在巨人肩膀上的原则,直接采用ffmpeg推流,将数据推送到视频服务器,再由视频服务器转发,供更多设备拉取数据。

        ffmpeg推流与文件保存流程相同,只是始终写而不结束,拉流配置代码如下:

	AVCodecContext* pCodecCtx = 0;
	AVCodec* pCodec;
	int in_w, in_h, got_picture, ret;
	AVPacket pkt;
	uint8_t* picture_buf;
	AVFrame* pFrame = 0;
	int picture_size;
	struct SwsContext* img_convert_ctx;
	AVDictionary* param = 0;
	
	//传输
	AVFormatContext* ofmt_ctx = NULL;
	AVStream* video_st;
	int framecnt = 0;
	AVRational time_base_q = { 1, AV_TIME_BASE };
	int vid_next_pts = 0;

	
	if (avformat_alloc_output_context2(&ofmt_ctx, NULL, "rtsp", pInf->RTSP_addr) < 0)
	{
		printf("Fail: avformat_alloc_output_context2\n");
		goto o_Terminate_Coder_Thread;
	}

	//检查所有流是否都有数据,如果没有数据会等待max_interleave_delta微秒
	ofmt_ctx->max_interleave_delta = 1000000;

	//使用tcp协议传输
	av_opt_set(ofmt_ctx->priv_data, "rtsp_transport", "tcp", 0);

	/* Some formats want stream headers to be separate. */
	//Add a new stream to output, should be called by the user before avformat_write_header() for muxing
	video_st = avformat_new_stream(ofmt_ctx, pCodec);
	if (video_st == NULL)
	{
		goto o_Terminate_Coder_Thread;
	}
	video_st->time_base.num = 1;
	//video_st->time_base.den = 75;
	video_st->time_base.den = 10;
	avcodec_parameters_from_context(video_st->codecpar, pCodecCtx);
	printf("======= av_dump_format output =======\n");
	av_dump_format(ofmt_ctx, 0, pInf->RTSP_addr, 1);
	printf("============== dump end ========= \n");

	//Open output URL
	if (!(ofmt_ctx->oformat->flags & AVFMT_NOFILE))
	{
		ret = avio_open(&ofmt_ctx->pb, pInf->RTSP_addr, AVIO_FLAG_READ_WRITE);
		if (ret < 0)
		{
			printf("Could not open output URL '%s'", pInf->RTSP_addr);
			goto o_Terminate_Coder_Thread;
		}
	}

	av_dict_free(&param);
	av_dict_set(&param, "stimeout", "5000000", 0);//很关键,当推送目标没有响应时,5秒后会自动退出,要不就死这了
	ret = avformat_write_header(ofmt_ctx, &param);
	if (ret < 0)
		printf("Error occurred when opening output URL\n");
	else
		printf("avformat_write_header return: %d\n", ret);


	while (1)
	{

		pkt.data = NULL;
		pkt.size = 0;
		av_init_packet(&pkt);

		//注意,在这里获得编码数据
		//pkt = 。。。
		///

		framecnt++;
		pkt.stream_index = video_st->index;

		AVRational time_base = ofmt_ctx->streams[0]->time_base;//{ 1, 1000 };
		AVRational r_framerate1 = { 1, 25 };
		//Duration between 2 frames (us)
		int64_t calc_duration = (double)(AV_TIME_BASE) * (1 / av_q2d(r_framerate1));	//内部时间戳
		//Parameters
		//enc_pkt.pts = (double)(framecnt*calc_duration)*(double)(av_q2d(time_base_q)) / (double)(av_q2d(time_base));
		pkt.pts = av_rescale_q(framecnt * calc_duration, time_base_q, time_base);
		pkt.dts = pkt.pts;
		pkt.duration = av_rescale_q(calc_duration, time_base_q, time_base); //(double)(calc_duration)*(double)(av_q2d(time_base_q)) / (double)(av_q2d(time_base));
		pkt.pos = -1;

		vid_next_pts = framecnt * calc_duration; //general timebase

		if(pInf->close_coder_Thread == 0)SendToRTSP(pInf, pkt.data + 4, pkt.size - 4);

		//av_write_frame(ofmt_ctx, &pkt);
		ret = av_interleaved_write_frame(ofmt_ctx, &pkt);

		av_packet_unref(&pkt);
		delete[] p;
		pInf->VideoBuffer_Count--;
	}

	av_write_trailer(ofmt_ctx);

 

标签:pkt,--,视频流,ctx,base,ofmt,time,av,推流
来源: https://blog.csdn.net/lz201_xxj/article/details/110955707

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有