Skip to content

Commit 3068c15

Browse files
authored
add a basic filtering example (#128)
* add a basic filtering example * use modern C++ initialization * fix english
1 parent a3b895a commit 3068c15

File tree

1 file changed

+235
-0
lines changed

1 file changed

+235
-0
lines changed
Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
#include <functional>
2+
#include <iostream>
3+
#include <map>
4+
#include <memory>
5+
#include <set>
6+
7+
#include "audioresampler.h"
8+
#include "av.h"
9+
#include "avutils.h"
10+
#include "codec.h"
11+
#include "ffmpeg.h"
12+
#include "packet.h"
13+
#include "videorescaler.h"
14+
15+
// API2
16+
#include "codec.h"
17+
#include "codeccontext.h"
18+
#include "filters/buffersink.h"
19+
#include "filters/buffersrc.h"
20+
#include "filters/filtergraph.h"
21+
#include "format.h"
22+
#include "formatcontext.h"
23+
24+
using namespace std;
25+
using namespace av;
26+
27+
int main(int argc, char **argv)
28+
{
29+
if (argc < 2)
30+
return 1;
31+
32+
av::init();
33+
av::setFFmpegLoggingLevel(AV_LOG_DEBUG);
34+
35+
string uri{argv[1]};
36+
37+
ssize_t videoStream = -1;
38+
VideoDecoderContext vdec;
39+
Stream vst;
40+
error_code ec;
41+
42+
int count = 0;
43+
44+
{
45+
46+
FormatContext ictx;
47+
48+
ictx.openInput(uri, ec);
49+
if (ec)
50+
{
51+
cerr << "Can't open input\n";
52+
return 1;
53+
}
54+
55+
cerr << "Streams: " << ictx.streamsCount() << endl;
56+
57+
ictx.findStreamInfo(ec);
58+
if (ec)
59+
{
60+
cerr << "Can't find streams: " << ec << ", " << ec.message() << endl;
61+
return 1;
62+
}
63+
64+
for (size_t i = 0; i < ictx.streamsCount(); ++i)
65+
{
66+
auto st = ictx.stream(i);
67+
if (st.mediaType() == AVMEDIA_TYPE_VIDEO)
68+
{
69+
videoStream = i;
70+
vst = st;
71+
break;
72+
}
73+
}
74+
75+
cerr << videoStream << endl;
76+
77+
if (vst.isNull())
78+
{
79+
cerr << "Video stream not found\n";
80+
return 1;
81+
}
82+
83+
if (vst.isValid())
84+
{
85+
vdec = VideoDecoderContext(vst);
86+
87+
Codec codec = findDecodingCodec(vdec.raw()->codec_id);
88+
89+
vdec.setCodec(codec);
90+
vdec.setRefCountedFrames(true);
91+
92+
vdec.open({{"threads", "1"}}, Codec(), ec);
93+
// vdec.open(ec);
94+
if (ec)
95+
{
96+
cerr << "Can't open codec\n";
97+
return 1;
98+
}
99+
}
100+
101+
// Setup filter
102+
Filter filter_buffer_src{"buffer"};
103+
Filter filter_buffer_sink{"buffersink"};
104+
FilterGraph filter_graph;
105+
106+
// Input and ouput contexts
107+
std::stringstream src_args;
108+
src_args << "video_size=" << vdec.width() << "x" << vdec.height() << ":pix_fmt=" << vdec.pixelFormat()
109+
<< ":time_base=" << vdec.timeBase() << ":pixel_aspect=" << vdec.sampleAspectRatio();
110+
clog << "Input arguments: " << src_args.str() << endl;
111+
FilterContext src_ctx = filter_graph.createFilter(filter_buffer_src, "in", src_args.str(), ec);
112+
if (ec)
113+
{
114+
clog << "Error creating filter source context: " << ec << ", " << ec.message() << endl;
115+
return 1;
116+
}
117+
FilterContext sink_ctx = filter_graph.createFilter(filter_buffer_sink, "out", "", ec);
118+
if (ec)
119+
{
120+
clog << "Error creating filter sink context: " << ec << ", " << ec.message() << endl;
121+
return 1;
122+
}
123+
124+
// Setup the filter chain
125+
filter_graph.parse("scale=320x200", src_ctx, sink_ctx, ec);
126+
if (ec)
127+
{
128+
clog << "Error parsing filter chain: " << ec << ", " << ec.message() << endl;
129+
return 1;
130+
}
131+
filter_graph.config(ec);
132+
if (ec)
133+
{
134+
clog << "Error configuring filter chain: " << ec << ", " << ec.message() << endl;
135+
return 1;
136+
}
137+
138+
// Setup the entry/exit points
139+
BufferSrcFilterContext buffer_src{src_ctx};
140+
BufferSinkFilterContext buffer_sink{sink_ctx};
141+
142+
while (Packet pkt = ictx.readPacket(ec))
143+
{
144+
if (ec)
145+
{
146+
clog << "Packet reading error: " << ec << ", " << ec.message() << endl;
147+
return 1;
148+
}
149+
150+
if (pkt.streamIndex() != videoStream)
151+
{
152+
continue;
153+
}
154+
155+
VideoFrame frame = vdec.decode(pkt, ec);
156+
157+
count++;
158+
// if (count > 100)
159+
// break;
160+
161+
if (ec)
162+
{
163+
cerr << "Error: " << ec << ", " << ec.message() << endl;
164+
return 1;
165+
}
166+
else if (!frame)
167+
{
168+
cerr << "Empty frame\n";
169+
continue;
170+
}
171+
172+
// Push into the filter
173+
buffer_src.addVideoFrame(frame, AV_BUFFERSRC_FLAG_KEEP_REF, ec);
174+
if (ec)
175+
{
176+
clog << "Filter push error: " << ec << ", " << ec.message() << endl;
177+
return 1;
178+
}
179+
180+
// Pull until there are no more incoming frames
181+
VideoFrame filtered;
182+
while (buffer_sink.getVideoFrame(filtered, ec))
183+
{
184+
filtered.setTimeBase(frame.timeBase());
185+
auto ts = filtered.pts();
186+
187+
clog << " filtered: " << filtered.width() << "x" << filtered.height() << ", size=" << filtered.size()
188+
<< ", ts=" << ts << ", tm: " << ts.seconds() << ", tb: " << filtered.timeBase()
189+
<< ", ref=" << filtered.isReferenced() << ":" << filtered.refCount() << endl;
190+
}
191+
if (ec && ec.value() != -EAGAIN)
192+
{
193+
clog << "Filter pull error: " << ec << ", " << ec.message() << endl;
194+
return 1;
195+
}
196+
}
197+
198+
clog << "Flush frames;\n";
199+
while (true)
200+
{
201+
VideoFrame frame = vdec.decode(Packet(), ec);
202+
if (ec)
203+
{
204+
cerr << "Error: " << ec << ", " << ec.message() << endl;
205+
return 1;
206+
}
207+
if (!frame)
208+
break;
209+
210+
// Push into the filter
211+
buffer_src.addVideoFrame(frame, ec);
212+
if (ec)
213+
{
214+
clog << "Filter push error: " << ec << ", " << ec.message() << endl;
215+
return 1;
216+
}
217+
218+
// Pull until there are no more incoming frames
219+
VideoFrame filtered;
220+
while (buffer_sink.getVideoFrame(filtered, ec))
221+
{
222+
filtered.setTimeBase(frame.timeBase());
223+
auto ts = filtered.pts();
224+
clog << " filtered: " << filtered.width() << "x" << filtered.height() << ", size=" << filtered.size()
225+
<< ", ts=" << ts << ", tm: " << ts.seconds() << ", tb: " << filtered.timeBase()
226+
<< ", ref=" << filtered.isReferenced() << ":" << filtered.refCount() << endl;
227+
}
228+
if (ec && ec.value() != -EAGAIN)
229+
{
230+
clog << "Filter pull error: " << ec << ", " << ec.message() << endl;
231+
return 1;
232+
}
233+
}
234+
}
235+
}

0 commit comments

Comments
 (0)