-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathXDecode.cpp
More file actions
133 lines (115 loc) · 2.61 KB
/
XDecode.cpp
File metadata and controls
133 lines (115 loc) · 2.61 KB
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
128
129
130
131
132
133
#include "XDecode.h"
#include <iostream>
using namespace std;
extern "C" {
#include "libavcodec/avcodec.h"
}
XDecode::XDecode() {
};
XDecode::~XDecode() {
};
void XFreePacket(AVPacket **pkt)
{
if (!pkt || !(*pkt)) return;
av_packet_free(pkt);
}
void XFreeFrame(AVFrame** frame)
{
if (!frame || !(*frame)) return;
av_frame_free(frame);
}
void XDecode::Close()
{
mux.lock();
if (codec) {//关闭的时候清理解码缓存了
avcodec_close(codec);
avcodec_free_context(&codec);
}
pts = 0;
mux.unlock();
}
void XDecode::Clear() {
mux.lock();
//清理解码缓冲
if (codec) avcodec_flush_buffers(codec);
mux.unlock();
}
bool XDecode::Open(AVCodecParameters* para)
{
//Close();
if (!para) return false;
Close();
//////////////////////////////////////////////////////////
///视频解码器打开
///找到视频解码器
AVCodec* vcodec = avcodec_find_decoder(para->codec_id);
if (!vcodec)
{
avcodec_parameters_free(¶);
cout << "can't find the codec id " << para->codec_id << endl;
return false;
}
cout << "find the AVCodec " << para->codec_id << endl;
mux.lock();//此处开始访问共享变量
//AVCodecContext *codec = avcodec_alloc_context3(vcodec);
codec = avcodec_alloc_context3(vcodec);
///配置解码器上下文参数
int re = avcodec_parameters_to_context(codec, para);
if (re < 0) {
cout << "avcodec_parameters_to_context failed! :" << endl;
mux.unlock();
return false;
}
//八线程解码
codec->thread_count = 8;
///打开解码器上下文
re = avcodec_open2(codec, 0, 0);
if (re != 0)
{
avcodec_free_context(&codec);
mux.unlock();
char buf[1024] = { 0 };
av_strerror(re, buf, sizeof(buf) - 1);
cout << "avcodec_open2 failed! :" << buf << endl;
return false;
}
mux.unlock();
//cout << "video avcodec_open2 success!" << endl;
return true;
};
//发送到解码线程,不管成功与否清理pkt空间,对象和媒体内容空间
bool XDecode::Send(AVPacket* pkt) {
// 盘错
if (!pkt || pkt->size <= 0 || !pkt->data) return false;
mux.lock();
if (!codec) { //如果加码器不存在
mux.unlock();
return false;
}
int re = avcodec_send_packet(codec, pkt);
mux.unlock();
av_packet_free(&pkt);//与分配是成对的
if (re != 0) return false;
return true;
}
//获取解码数据,一次send可能需要多次Recv,获取缓冲中的数据Send NULL再Recv中多次
//每次赋值一份,由调用者释放av_frame_free
AVFrame* XDecode::Recv()
{
mux.lock();
if (!codec) { //如果解码器不存在
mux.unlock();
return NULL;
}
AVFrame* frame = av_frame_alloc();
int re = avcodec_receive_frame(codec, frame);
mux.unlock();
if (re != 0) {
av_frame_free(&frame);
return NULL;
}
//cout << "[" << frame->linesize[0] << "] " << flush;
pts = frame->pts;
//av_frame_free(&frame);
return frame;
}