Merge tag 'v0.22.11'
release v0.22.11
This commit is contained in:
@@ -32,12 +32,12 @@ extern "C" {
|
||||
FfmpegFilter::FfmpegFilter(const AudioFormat &in_audio_format,
|
||||
const AudioFormat &_out_audio_format,
|
||||
Ffmpeg::FilterGraph &&_graph,
|
||||
Ffmpeg::FilterContext &&_buffer_src,
|
||||
Ffmpeg::FilterContext &&_buffer_sink) noexcept
|
||||
AVFilterContext &_buffer_src,
|
||||
AVFilterContext &_buffer_sink) noexcept
|
||||
:Filter(_out_audio_format),
|
||||
graph(std::move(_graph)),
|
||||
buffer_src(std::move(_buffer_src)),
|
||||
buffer_sink(std::move(_buffer_sink)),
|
||||
buffer_src(_buffer_src),
|
||||
buffer_sink(_buffer_sink),
|
||||
in_format(Ffmpeg::ToFfmpegSampleFormat(in_audio_format.format)),
|
||||
in_sample_rate(in_audio_format.sample_rate),
|
||||
in_channels(in_audio_format.channels),
|
||||
@@ -61,7 +61,7 @@ FfmpegFilter::FilterPCM(ConstBuffer<void> src)
|
||||
|
||||
memcpy(frame.GetData(0), src.data, src.size);
|
||||
|
||||
int err = av_buffersrc_add_frame(buffer_src.get(), frame.get());
|
||||
int err = av_buffersrc_add_frame(&buffer_src, frame.get());
|
||||
if (err < 0)
|
||||
throw MakeFfmpegError(err, "av_buffersrc_write_frame() failed");
|
||||
|
||||
@@ -69,7 +69,7 @@ FfmpegFilter::FilterPCM(ConstBuffer<void> src)
|
||||
|
||||
frame.Unref();
|
||||
|
||||
err = av_buffersink_get_frame(buffer_sink.get(), frame.get());
|
||||
err = av_buffersink_get_frame(&buffer_sink, frame.get());
|
||||
if (err < 0) {
|
||||
if (err == AVERROR(EAGAIN) || err == AVERROR_EOF)
|
||||
return nullptr;
|
||||
|
@@ -30,7 +30,7 @@
|
||||
*/
|
||||
class FfmpegFilter final : public Filter {
|
||||
Ffmpeg::FilterGraph graph;
|
||||
Ffmpeg::FilterContext buffer_src, buffer_sink;
|
||||
AVFilterContext &buffer_src, &buffer_sink;
|
||||
Ffmpeg::Frame frame;
|
||||
|
||||
FfmpegBuffer interleave_buffer;
|
||||
@@ -51,8 +51,8 @@ public:
|
||||
FfmpegFilter(const AudioFormat &in_audio_format,
|
||||
const AudioFormat &_out_audio_format,
|
||||
Ffmpeg::FilterGraph &&_graph,
|
||||
Ffmpeg::FilterContext &&_buffer_src,
|
||||
Ffmpeg::FilterContext &&_buffer_sink) noexcept;
|
||||
AVFilterContext &_buffer_src,
|
||||
AVFilterContext &_buffer_sink) noexcept;
|
||||
|
||||
/* virtual methods from class Filter */
|
||||
ConstBuffer<void> FilterPCM(ConstBuffer<void> src) override;
|
||||
|
@@ -37,39 +37,79 @@ public:
|
||||
std::unique_ptr<Filter> Open(AudioFormat &af) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fallback for PreparedFfmpegFilter::Open() just in case the filter's
|
||||
* native output format could not be determined.
|
||||
*
|
||||
* TODO: improve the MPD filter API to allow returning the output
|
||||
* format later, and eliminate this kludge
|
||||
*/
|
||||
static auto
|
||||
OpenWithAformat(const char *graph_string, AudioFormat &in_audio_format)
|
||||
{
|
||||
Ffmpeg::FilterGraph graph;
|
||||
|
||||
auto &buffer_src =
|
||||
Ffmpeg::MakeAudioBufferSource(in_audio_format, *graph);
|
||||
|
||||
auto &buffer_sink = Ffmpeg::MakeAudioBufferSink(*graph);
|
||||
|
||||
AudioFormat out_audio_format = in_audio_format;
|
||||
auto &aformat = Ffmpeg::MakeAformat(out_audio_format, *graph);
|
||||
|
||||
int error = avfilter_link(&aformat, 0, &buffer_sink, 0);
|
||||
if (error < 0)
|
||||
throw MakeFfmpegError(error, "avfilter_link() failed");
|
||||
|
||||
graph.ParseSingleInOut(graph_string, aformat, buffer_src);
|
||||
graph.CheckAndConfigure();
|
||||
|
||||
return std::make_unique<FfmpegFilter>(in_audio_format,
|
||||
out_audio_format,
|
||||
std::move(graph),
|
||||
buffer_src,
|
||||
buffer_sink);
|
||||
}
|
||||
|
||||
std::unique_ptr<Filter>
|
||||
PreparedFfmpegFilter::Open(AudioFormat &in_audio_format)
|
||||
{
|
||||
Ffmpeg::FilterGraph graph;
|
||||
|
||||
auto buffer_src =
|
||||
Ffmpeg::FilterContext::MakeAudioBufferSource(in_audio_format,
|
||||
*graph);
|
||||
auto &buffer_src =
|
||||
Ffmpeg::MakeAudioBufferSource(in_audio_format, *graph);
|
||||
|
||||
auto buffer_sink = Ffmpeg::FilterContext::MakeAudioBufferSink(*graph);
|
||||
auto &buffer_sink = Ffmpeg::MakeAudioBufferSink(*graph);
|
||||
|
||||
Ffmpeg::FilterInOut io_sink("out", *buffer_sink);
|
||||
Ffmpeg::FilterInOut io_src("in", *buffer_src);
|
||||
auto io = graph.Parse(graph_string, std::move(io_sink),
|
||||
std::move(io_src));
|
||||
/* if the filter's output format is not supported by MPD, this
|
||||
"aformat" filter is inserted at the end and takes care for
|
||||
the required conversion */
|
||||
auto &aformat = Ffmpeg::MakeAutoAformat(*graph);
|
||||
|
||||
if (io.first.get() != nullptr)
|
||||
throw std::runtime_error("FFmpeg filter has an open input");
|
||||
|
||||
if (io.second.get() != nullptr)
|
||||
throw std::runtime_error("FFmpeg filter has an open output");
|
||||
int error = avfilter_link(&aformat, 0, &buffer_sink, 0);
|
||||
if (error < 0)
|
||||
throw MakeFfmpegError(error, "avfilter_link() failed");
|
||||
|
||||
graph.ParseSingleInOut(graph_string, aformat, buffer_src);
|
||||
graph.CheckAndConfigure();
|
||||
|
||||
const auto out_audio_format =
|
||||
Ffmpeg::DetectFilterOutputFormat(in_audio_format, *buffer_src,
|
||||
*buffer_sink);
|
||||
Ffmpeg::DetectFilterOutputFormat(in_audio_format, buffer_src,
|
||||
buffer_sink);
|
||||
|
||||
if (!out_audio_format.IsDefined())
|
||||
/* the filter's native output format could not be
|
||||
determined yet, but we need to know it now; as a
|
||||
workaround for this MPD API deficiency, try again
|
||||
with an "aformat" filter which forces a specific
|
||||
output format */
|
||||
return OpenWithAformat(graph_string, in_audio_format);
|
||||
|
||||
return std::make_unique<FfmpegFilter>(in_audio_format,
|
||||
out_audio_format,
|
||||
std::move(graph),
|
||||
std::move(buffer_src),
|
||||
std::move(buffer_sink));
|
||||
buffer_src,
|
||||
buffer_sink);
|
||||
}
|
||||
|
||||
static std::unique_ptr<PreparedFilter>
|
||||
|
@@ -42,24 +42,13 @@ OpenHdcdFilter(AudioFormat &in_audio_format)
|
||||
{
|
||||
Ffmpeg::FilterGraph graph;
|
||||
|
||||
auto buffer_src =
|
||||
Ffmpeg::FilterContext::MakeAudioBufferSource(in_audio_format,
|
||||
*graph);
|
||||
auto &buffer_src =
|
||||
Ffmpeg::MakeAudioBufferSource(in_audio_format,
|
||||
*graph);
|
||||
|
||||
auto buffer_sink = Ffmpeg::FilterContext::MakeAudioBufferSink(*graph);
|
||||
|
||||
Ffmpeg::FilterInOut io_sink("out", *buffer_sink);
|
||||
Ffmpeg::FilterInOut io_src("in", *buffer_src);
|
||||
|
||||
auto io = graph.Parse(hdcd_graph, std::move(io_sink),
|
||||
std::move(io_src));
|
||||
|
||||
if (io.first.get() != nullptr)
|
||||
throw std::runtime_error("FFmpeg filter has an open input");
|
||||
|
||||
if (io.second.get() != nullptr)
|
||||
throw std::runtime_error("FFmpeg filter has an open output");
|
||||
auto &buffer_sink = Ffmpeg::MakeAudioBufferSink(*graph);
|
||||
|
||||
graph.ParseSingleInOut(hdcd_graph, buffer_sink, buffer_src);
|
||||
graph.CheckAndConfigure();
|
||||
|
||||
auto out_audio_format = in_audio_format;
|
||||
@@ -69,8 +58,8 @@ OpenHdcdFilter(AudioFormat &in_audio_format)
|
||||
return std::make_unique<FfmpegFilter>(in_audio_format,
|
||||
out_audio_format,
|
||||
std::move(graph),
|
||||
std::move(buffer_src),
|
||||
std::move(buffer_sink));
|
||||
buffer_src,
|
||||
buffer_sink);
|
||||
}
|
||||
|
||||
class PreparedHdcdFilter final : public PreparedFilter {
|
||||
|
Reference in New Issue
Block a user