学习FFmpeg简单Samples之拉取网络流并显示

9 篇文章 2 订阅

实例代码


int sdl_texture_format_map[][21] = 
{
	{ AV_PIX_FMT_RGB8,           SDL_PIXELFORMAT_RGB332 },
	{ AV_PIX_FMT_RGB444,         SDL_PIXELFORMAT_RGB444 },
	{ AV_PIX_FMT_RGB555,         SDL_PIXELFORMAT_RGB555 },
	{ AV_PIX_FMT_BGR555,         SDL_PIXELFORMAT_BGR555 },
	{ AV_PIX_FMT_RGB565,         SDL_PIXELFORMAT_RGB565 },
	{ AV_PIX_FMT_BGR565,         SDL_PIXELFORMAT_BGR565 },
	{ AV_PIX_FMT_RGB24,          SDL_PIXELFORMAT_RGB24 },
	{ AV_PIX_FMT_BGR24,          SDL_PIXELFORMAT_BGR24 },
	{ AV_PIX_FMT_0RGB32,         SDL_PIXELFORMAT_RGB888 },
	{ AV_PIX_FMT_0BGR32,         SDL_PIXELFORMAT_BGR888 },
	{ AV_PIX_FMT_NE(RGB0, 0BGR), SDL_PIXELFORMAT_RGBX8888 },
	{ AV_PIX_FMT_NE(BGR0, 0RGB), SDL_PIXELFORMAT_BGRX8888 },
	{ AV_PIX_FMT_RGB32,          SDL_PIXELFORMAT_ARGB8888 },
	{ AV_PIX_FMT_RGB32_1,        SDL_PIXELFORMAT_RGBA8888 },
	{ AV_PIX_FMT_BGR32,          SDL_PIXELFORMAT_ABGR8888 },
	{ AV_PIX_FMT_BGR32_1,        SDL_PIXELFORMAT_BGRA8888 },
	{ AV_PIX_FMT_YUV420P,        SDL_PIXELFORMAT_IYUV },
	{ AV_PIX_FMT_YUVJ420P,       SDL_PIXELFORMAT_IYUV},
	{ AV_PIX_FMT_YUYV422,        SDL_PIXELFORMAT_YUY2 },
	{ AV_PIX_FMT_UYVY422,        SDL_PIXELFORMAT_UYVY },
	{ AV_PIX_FMT_NONE,           SDL_PIXELFORMAT_UNKNOWN },
};

Uint32 FFmpegFmt_2_SDLFmt(AVPixelFormat pixFmt)
{
	for (int i = 0; i < 21; i++){
		if (sdl_texture_format_map[i][0] == (int)pixFmt){
			return sdl_texture_format_map[i][1];
		}
	}
	return -1;
}

int IpCamera()
{
	AVDictionary* options = NULL;
	av_dict_set(&options, "buffer_size", "4096000", 0); //设置缓存大小,1080p可将值调大
	av_dict_set(&options, "rtsp_transport", "udp", 0);
	av_dict_set(&options, "stimeout", "20000000", 0); //设置超时断开连接时间,单位微秒
	av_dict_set(&options, "max_delay", "500000", 0); //设置最大时延

	int ret = 0;

	//const char* url = "rtmp://192.168.0.188/app/rtmpstream0";
	const char* url = "rtsp://192.168.0.188:554/stream/main";
	//const char* url = "rtmp://192.168.0.112:1936/live/123";
	AVFormatContext* m_fmt_ctx = avformat_alloc_context();

	ret = avformat_open_input(&m_fmt_ctx, url, NULL, &options);
	if (ret != 0) {
		cout << "avformat_open_input is fail !!!" << endl;
		return -1;
	}

	//设置查找时间以避免耗时过长
	m_fmt_ctx->probesize = 1000;
	m_fmt_ctx->max_analyze_duration = 2048;//AV_TIME_BASE

	ret = avformat_find_stream_info(m_fmt_ctx, NULL);
	if (ret < 0) {
		cout << "avformat_find_stream_info is fail !!!" << endl;
		return -1;
	}

	av_dump_format(m_fmt_ctx, 0, url, 0);

	int video_stream = -1;
		
	video_stream =	av_find_best_stream(m_fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);

	if (video_stream < 0) {
		return -1;
	}

	AVCodecContext* _codec_ctx = m_fmt_ctx->streams[video_stream]->codec;
	AVCodec* _codec = avcodec_find_decoder(_codec_ctx->codec_id);
	if (_codec == NULL) {
		return -1;
	}

	ret = avcodec_open2(_codec_ctx, _codec, NULL);
	if (ret != 0) {
		return -1;
	}

	int width = m_fmt_ctx->streams[video_stream]->codecpar->width;
	int height = m_fmt_ctx->streams[video_stream]->codecpar->height;
	int pts = m_fmt_ctx->streams[video_stream]->codec->framerate.den;
	AVPixelFormat inputFormat = m_fmt_ctx->streams[video_stream]->codec->pix_fmt;

	ret = SDL_Init(SDL_INIT_VIDEO);

	SDL_Window*  window = SDL_CreateWindow("FFmpeg_Demo", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 800, 600, SDL_WINDOW_SHOWN);
	
	SDL_Renderer* renderer = NULL;

	if (window) {
		renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
		if (!renderer) {
			av_log(NULL, AV_LOG_WARNING, "Failed to initialize a hardware accelerated renderer: %s\n", SDL_GetError());
			renderer = SDL_CreateRenderer(window, -1, 0);
		}
	}

	SDL_Texture* texture = NULL;

	Uint32 format = FFmpegFmt_2_SDLFmt(inputFormat);

	if (!(texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_STREAMING, width, height)))
		return -1;

	int frameIndex = 0;

	int got_picture = 0;

	AVPacket* packet = av_packet_alloc();

	AVFrame *frame_yuv = av_frame_alloc();

	int64_t pre_pts = -1;

	int64_t start_time = av_gettime();

	while (frameIndex < 500)
	{

		ret = av_read_frame(m_fmt_ctx, packet);

		if (ret < 0) {
			break;
		}

		if (packet->stream_index == video_stream)
		{
			//FIX:No PTS (Example: Raw H.264)
			//Simple Write PTS
			if (packet->pts == AV_NOPTS_VALUE) {
				//Write PTS
				AVRational time_base1 = m_fmt_ctx->streams[video_stream]->time_base;
				//Duration between 2 frames (us)
				int64_t calc_duration = (double)AV_TIME_BASE / av_q2d(m_fmt_ctx->streams[video_stream]->r_frame_rate);
				//Parameters
				packet->pts = (double)(frameIndex * calc_duration) / (double)(av_q2d(time_base1) * AV_TIME_BASE);
				packet->dts= packet->pts;
				packet->duration = (double)calc_duration / (double)(av_q2d(time_base1) * AV_TIME_BASE);
			}
			
			ret = avcodec_decode_video2(_codec_ctx, frame_yuv, &got_picture, packet);
			if (ret < 0) {
				printf("Decode Error.\n");
				return ret;
			}

			if (got_picture) {

				if (pre_pts == -1)
					pre_pts = frame_yuv->pts;

				//frame_yuv->pts -= pre_pts;

				AVRational time_base = m_fmt_ctx->streams[video_stream]->time_base;
				AVRational time_base_q = { 1,AV_TIME_BASE };
				int64_t pts_time = av_rescale_q(frame_yuv->pts, time_base, time_base_q);
				int64_t now_time = av_gettime() - start_time;
				if (pts_time > now_time) {
					cout << "delay time : " << pts_time - now_time << endl;
					av_usleep(pts_time - now_time );
				}
			
				cout << "index: " << frameIndex << " pts:" << frame_yuv->pts <<" size: "<<packet->size <<" playTime :" << pts_time << "  key" << frame_yuv->key_frame<< endl;

				//long long currentTime = av_gettime();
				//if (playTime > (currentTime - startTime))
				//	av_usleep(playTime - currentTime);

				ret = SDL_UpdateYUVTexture(texture, NULL,
					frame_yuv->data[0], frame_yuv->linesize[0],
					frame_yuv->data[1], frame_yuv->linesize[1],
					frame_yuv->data[2], frame_yuv->linesize[2]);

				

				if (ret < 0)
					break;

				ret = SDL_RenderClear(renderer);
				if (ret < 0)
					break;

				ret = SDL_RenderCopy(renderer, texture, NULL, NULL);
				if (ret < 0)
					break;

				SDL_RenderPresent(renderer);

				frameIndex++;
			}
		}

		av_packet_unref(packet);
	}

	SDL_DestroyTexture(texture);

	SDL_DestroyRenderer(renderer);

	SDL_DestroyWindow(window);

	SDL_Quit();

	av_packet_free(&packet);

	avformat_close_input(&m_fmt_ctx);

	return 0;
}

实例测试结果

在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值