Skip to content

Commit 59bcdae

Browse files
committed
Introduce C++20
1 parent 17f8c7d commit 59bcdae

File tree

12 files changed

+186
-48
lines changed

12 files changed

+186
-48
lines changed

example/api2-samples/api2-decode-encode-audio.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ int main(int argc, char **argv)
107107

108108
clog << "Supported sample formats:\n";
109109
for (const auto &fmt : sampleFmts) {
110-
clog << " " << av_get_sample_fmt_name(fmt) << '\n';
110+
av::print(stderr, " {}\n", fmt);
111111
}
112112

113113
clog << "Supported sample rates:\n";

example/api2-samples/api2-remux.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,11 @@ using namespace av;
3030

3131
void usage(int /*argc*/, char **argv, ostream &ost)
3232
{
33-
ost << "Usage: " << argv[0] << " [arguments] input_stream output_stream\n"
34-
" -f format force input format\n"
35-
" -o format force output format\n"
36-
" -d duration duration for transmuxing (double, seconds)";
33+
av::print(ost, "Usage: {} [arguments] input_stream output_stream\n"
34+
" -f format force input format\n"
35+
" -o format force output format\n"
36+
" -d duration duration for transmuxing (double, seconds)",
37+
argv[0]);
3738
}
3839

3940
const static char opts[] = "f:o:d:h";

example/api2-samples/api2-timestamp.cpp

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,35 +14,32 @@ int main()
1414
Timestamp b = {2, {1, 3}};
1515

1616
auto c = a + b;
17-
cout << c << " = " << c.seconds() << endl;
17+
av::print("{} = {}\n", c, c.seconds());
1818

1919
auto d = c - b;
20-
cout << d << " = " << d.seconds() << endl;
20+
av::print("{} = {}\n", d, d.seconds());
2121

2222
auto e = a * b;
23-
cout << e << " = " << e.seconds() << endl;
23+
av::print("{} = {}\n", e, e.seconds());
2424

2525
auto f = a / b;
26-
cout << f << " = " << f.seconds() << endl;
26+
av::print("{} = {}\n", f, f.seconds());
2727

2828
auto g = Timestamp{300, {1, 2}} / Timestamp{150, {1, 3}};
29-
cout << g << " = " << g.seconds() << endl;
29+
av::print("{} = {}\n", g, g.seconds());
3030
}
3131

3232
{
3333
Timestamp ts = std::chrono::microseconds(500);
34-
cout << ts << " = " << ts.seconds() << endl;
34+
av::print("{} = {}\n", ts, ts.seconds());
3535

3636
auto ts2 = ts + std::chrono::seconds(5);
37-
cout << ts2 << " = " << ts2.seconds() << endl;
37+
av::print("{} = {}\n", ts2, ts2.seconds());
3838

3939
auto dur1 = ts2.toDuration<std::chrono::milliseconds>();
40-
cout << dur1.count() << endl;
40+
av::print("{}\n", dur1.count());
4141

4242
auto ts3 = std::chrono::seconds(5) + ts;
43-
cout << ts3 << " = " << ts3.seconds() << endl;
44-
45-
46-
43+
av::print("{} = {}\n", ts3, ts3.seconds());
4744
}
4845
}

src/CMakeLists.txt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,13 @@ foreach(TARGET ${AV_TARGETS})
4444
target_compile_features(${TARGET} PUBLIC cxx_std_26)
4545
elseif ("cxx_std_23" IN_LIST CMAKE_CXX_COMPILE_FEATURES)
4646
target_compile_features(${TARGET} PUBLIC cxx_std_23)
47-
elseif("cxx_std_20" IN_LIST CMAKE_CXX_COMPILE_FEATURES)
48-
target_compile_features(${TARGET} PUBLIC cxx_std_20)
47+
#elseif("cxx_std_20" IN_LIST CMAKE_CXX_COMPILE_FEATURES)
48+
# target_compile_features(${TARGET} PUBLIC cxx_std_20)
4949
else()
50-
target_compile_features(${TARGET} PUBLIC cxx_std_17)
50+
target_compile_features(${TARGET} PUBLIC cxx_std_20)
5151
endif()
52+
elseif(CMAKE_CXX_STANDARD LESS 20)
53+
message(FATAL_ERROR "ACPP requires C++20 compiler at least")
5254
endif()
5355

5456
if(WIN32)

src/avutils.h

Lines changed: 80 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
#pragma once
22

3-
#include <string>
4-
#include <vector>
3+
#include <algorithm>
54
#include <deque>
5+
#include <functional>
6+
#include <iterator>
67
#include <memory>
78
#include <mutex>
89
#include <sstream>
9-
#include <algorithm>
10-
#include <functional>
10+
#include <string>
11+
#include <vector>
12+
13+
#ifdef __cpp_lib_print
14+
# include <print>
15+
#endif
1116

1217
#include "ffmpeg.h"
1318
#include "avtime.h"
@@ -431,5 +436,76 @@ void array_to_container(const T* array, Container &container, Compare isEnd, Cal
431436
container.push_back(convert(value));
432437
}
433438

439+
440+
// printing
441+
#ifdef __cpp_lib_print
442+
using std::print;
443+
#else
444+
445+
namespace internal {
446+
struct fp_output_iterator
447+
{
448+
/// One of the @link iterator_tags tag types@endlink.
449+
typedef std::output_iterator_tag iterator_category;
450+
/// The type "pointed to" by the iterator.
451+
typedef void value_type;
452+
/// Distance between iterators is represented as this type.
453+
typedef ptrdiff_t difference_type;
454+
/// This type represents a pointer-to-value_type.
455+
typedef void pointer;
456+
/// This type represents a reference-to-value_type.
457+
typedef void reference;
458+
459+
private:
460+
std::FILE *m_fp{nullptr};
461+
462+
public:
463+
fp_output_iterator(std::FILE *out) noexcept
464+
: m_fp(out)
465+
{}
466+
467+
fp_output_iterator(const fp_output_iterator& obj) noexcept
468+
: m_fp(obj.m_fp)
469+
{}
470+
fp_output_iterator& operator=(const fp_output_iterator&) = default;
471+
472+
fp_output_iterator& operator=(char ch) {
473+
fputc(ch, m_fp);
474+
return *this;
475+
}
476+
477+
fp_output_iterator& operator=(const char *str) {
478+
fputs(str, m_fp);
479+
return *this;
480+
}
481+
482+
[[nodiscard]] fp_output_iterator& operator*() noexcept { return *this; }
483+
fp_output_iterator& operator++() noexcept { return *this; }
484+
fp_output_iterator& operator++(int) noexcept { return *this; }
485+
};
486+
} // ::internal
487+
488+
template<class... Args>
489+
void print(std::FILE* stream, std::format_string<Args...> fmt, Args&&... args)
490+
{
491+
internal::fp_output_iterator out{stream};
492+
std::format_to(out, std::move(fmt), std::forward<Args>(args)...);
493+
}
494+
495+
template<class... Args>
496+
void print(std::format_string<Args...> fmt, Args&&... args)
497+
{
498+
av::print(stdout, std::move(fmt), std::forward<Args>(args)...);
499+
}
500+
501+
template<class... Args>
502+
std::ostream& print(std::ostream &stream, std::format_string<Args...> fmt, Args&&... args)
503+
{
504+
std::ostream_iterator<char> out{stream};
505+
std::format_to(out, std::move(fmt), std::forward<Args>(args)...);
506+
return stream;
507+
}
508+
#endif
509+
434510
} // ::av
435511

src/ffmpeg.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,3 +177,30 @@ struct PixSampleFmtWrapper
177177
protected:
178178
T m_fmt = NoneValue;
179179
};
180+
181+
#ifdef __cpp_lib_format
182+
# include <format>
183+
184+
template <typename B>
185+
concept has_name_method = requires(const B& t, std::error_code ec) {
186+
{ t.name(ec) } -> std::convertible_to<std::string_view>;
187+
};
188+
189+
// std::format
190+
template <class T>
191+
requires has_name_method<T>
192+
struct std::formatter<T>
193+
{
194+
constexpr auto parse(std::format_parse_context& ctx)
195+
{
196+
return ctx.begin();
197+
}
198+
199+
auto format(const T& value, std::format_context& ctx) const
200+
{
201+
std::error_code dummy;
202+
return std::format_to(ctx.out(), "{}", value.name(dummy));
203+
}
204+
};
205+
#endif
206+

src/filters/filtergraph.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -245,11 +245,16 @@ string FilterGraph::dump(bool doPrint, const string &options)
245245
{
246246
string result;
247247

248-
if (m_raw)
249-
{
250-
result = avfilter_graph_dump(m_raw, options.c_str());
248+
if (m_raw) {
249+
// avoid memory leak here
250+
std::unique_ptr<char, decltype(&av_free)> ret {avfilter_graph_dump(m_raw, options.c_str()), av_free};
251+
252+
if (ret)
253+
result = ret.get();
254+
251255
if (doPrint)
252-
clog << result;
256+
av::print(stderr, "{}\n", result);
257+
253258
}
254259

255260
return result;

src/formatcontext.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ void set_uri(AVFormatContext *ctx, string_view uri)
5858
#if API_AVFORMAT_URL
5959
if (ctx->url)
6060
av_free(ctx->url);
61-
ctx->url = av_strdup(uri.data());
61+
ctx->url = av_strndup(uri.data(), uri.size());
6262
#else
6363
av_strlcpy(ctx->filename, uri.data(), std::min<size_t>(sizeof(m_raw->filename), uri.size() + 1));
6464
ctx->filename[uri.size()] = '\0';
@@ -100,7 +100,7 @@ void FormatContext::setFormat(const InputFormat &format)
100100
{
101101
if (isOpened())
102102
{
103-
cerr << "Can't set format for opened container\n";
103+
av::print(stderr, "Can't set format for opened container\n");
104104
return;
105105
}
106106

@@ -112,7 +112,7 @@ void FormatContext::setFormat(const OutputFormat &format)
112112
{
113113
if (isOpened())
114114
{
115-
cerr << "Can't set format for opened container\n";
115+
av::print(stderr, "Can't set format for opened container\n");
116116
return;
117117
}
118118

@@ -959,7 +959,7 @@ int FormatContext::avioInterruptCb()
959959
std::chrono::duration<double> elapsedTime = currentTime - m_lastSocketAccess;
960960
if (elapsedTime.count() > m_socketTimeout && m_socketTimeout > -1)
961961
{
962-
std::cerr << "Socket timeout" << std::endl;
962+
print(stderr, "Socket timeout\n");
963963
return 1;
964964
}
965965

@@ -998,7 +998,7 @@ void FormatContext::findStreamInfo(AVDictionary **options, size_t optionsCount,
998998
av_dump_format(m_raw, 0, get_uri(m_raw).data(), 0);
999999
return;
10001000
}
1001-
cerr << "Could not found streams in input container\n";
1001+
av::print(stderr, "Could not found streams in input container\n");
10021002
throws_if(ec, sts, ffmpeg_category());
10031003
}
10041004

src/rational.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ int64_t Rational::rescale(int64_t srcValue, const Rational &dstBase) const noexc
4040

4141
void Rational::dump() const noexcept
4242
{
43-
cout << m_value.num << "/" << m_value.den << endl;
43+
av::print("{}/{}\n", m_value.num, m_value.den);
4444
}
4545

4646
Rational &Rational::operator =(const AVRational &value) noexcept

src/rational.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,22 @@ inline std::istream& operator>> (std::istream &stream, Rational &value)
142142

143143
return stream;
144144
}
145+
} // ::av
145146

147+
#ifdef __cpp_lib_format
148+
#include <format>
146149

147-
} // ::av
150+
// std::format
151+
template <>
152+
struct std::formatter<av::Rational>
153+
{
154+
constexpr auto parse(std::format_parse_context& ctx)
155+
{
156+
return ctx.begin();
157+
}
158+
auto format(const av::Rational& value, std::format_context& ctx) const
159+
{
160+
return std::format_to(ctx.out(), "{}/{}", value.getNumerator(), value.getDenominator());
161+
}
162+
};
163+
#endif

0 commit comments

Comments
 (0)