Blame view

src/decoder/gb28181/rtp/FFRtpParser.cpp 3.4 KB
150d457d   Hu Chunming   代码暂存,未完成
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
  //
  // Created by bxc on 2023/4/18.
  // 作者:北小菜
  // 邮箱:bilibili_bxc@126.com
  // 西瓜视频主页:https://www.ixigua.com/home/4171970536803763
  // 哔哩哔哩主页:https://space.bilibili.com/487906612/
  //
  
  #include "FFRtpParser.h"
  #include "Utils.h"
  #include <string.h>
  
  int avio_read_packet(void* opaque, uint8_t* buf, int buffsize){
  	FFRtpParser* player = (FFRtpParser*)opaque;
  
  	int ret = 0;
  	if (player->bufferSize >= buffsize)
  	{
  		memcpy(buf, player->buffer, buffsize);
  		player->bufferSize = player->bufferSize - buffsize;
  		memmove(player->buffer, player->buffer + buffsize, player->bufferSize);
  		ret = buffsize;
  
  		LOG_INFO("avio_read_packet=%d", buffsize);
  	}
  	return ret;
  }
  
  FFRtpParser::FFRtpParser()
  {
  }
  
  FFRtpParser::~FFRtpParser()
  {
  	if (mVideoCodecPar) {
  		avcodec_parameters_free(&mVideoCodecPar);
  	}
  	if (mVideoCodecCtx) {
  		avcodec_close(mVideoCodecCtx);
  		mVideoCodecCtx = nullptr;
  	}
  
  	if (mFmtCtx) {
  		avformat_close_input(&mFmtCtx);
  		mFmtCtx = nullptr;
  	}
  }
  
  bool FFRtpParser::probe()
  {
  	mFmtCtx = avformat_alloc_context();
  
  	unsigned char* avioBuff = (unsigned char*)av_malloc(1920 * 1080);
  	mAvioCtx = avio_alloc_context(avioBuff, sizeof(avioBuff), 0, this, avio_read_packet, NULL, NULL);
  	//探测流(获取码流格式)
  	if (av_probe_input_buffer2(mAvioCtx, (const AVInputFormat**)&mInputFmt, "", NULL, 0, 0) < 0){
  		LOG_ERROR("av_probe_input_buffer2 error");
  		return false;
  	}
  	mFmtCtx->pb = mAvioCtx;
  
  	//配置流参数
  	//av_dict_set(&options, "fflags", "nobuffer", 0); //不缓存直接解码
  
  	//打开流
  	if (avformat_open_input(&mFmtCtx, "", mInputFmt, &net_options) != 0)
  	{
  		LOG_ERROR("avformat_open_input error");
  		return false;
  	}
  	//获取流信息
  	if (avformat_find_stream_info(mFmtCtx, NULL) < 0)//?
  	{
  		LOG_ERROR("avformat_find_stream_info error");
  		return false;
  	}
  	//获取视频流
  	mVideoStream = av_find_best_stream(mFmtCtx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
  	if (mVideoStream < 0)
  	{
  		LOG_ERROR("av_find_best_stream error");
  		return false;
  	}
  	//获取解码信息
  	mVideoCodecPar = mFmtCtx->streams[mVideoStream]->codecpar;
  	const AVCodec* videoCodec = avcodec_find_decoder(mVideoCodecPar->codec_id);
  	if (!videoCodec){
  		LOG_ERROR("avcodec_find_decoder error");
  		return false;
  	}
  	mVideoCodecCtx = avcodec_alloc_context3(videoCodec);
  
  	//codecpar为解码器上下文赋值
  	if (avcodec_parameters_to_context(mVideoCodecCtx, mVideoCodecPar) != 0)
  	{
  		LOG_ERROR("avcodec_parameters_to_context error");
  		return false;
  	}
  
  	//设置解码器参数
  	//av_dict_set(&codec_options, "tune", "zero-latency", 0);//设置零延迟
  	//av_dict_set(&codec_options, "preset", "ultrafast", 0);//设置最模糊但是最快的解码方式
  	//av_dict_set(&codec_options, "x265-params", "qp=20", 0);//设置265量化参数
  	//量化参数:控制了视频帧中每一个宏区块(Macroblock)的压缩量。较大的数值,量化值更高,意味着更多的压缩,更低的质量,较小的数值代表相反的含义。
  
  	//打开解码器
  	if (avcodec_open2(mVideoCodecCtx, videoCodec, &codec_options) < 0)
  	{
  		LOG_ERROR("avcodec_open2 error");
  		return false;
  	}
  	LOG_INFO("mVideoCodecCtx->width=%d,mVideoCodecCtx->height=%d", mVideoCodecCtx->width, mVideoCodecCtx->height);
  	return true;
  }
  
  void FFRtpParser::play(){
  	LOG_INFO("start");
  
  	AVPacket pkt;
  	while (av_read_frame(mFmtCtx, &pkt) >= 0) {
  		if (pkt.stream_index == mVideoStream){
  
  		}
  		av_packet_unref(&pkt);
  	}
  	LOG_INFO("end");
  }