Skip to content

Commit

Permalink
fix: support building against ffmpeg 7.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Julusian committed Oct 7, 2024
1 parent 7eb501f commit c7999b7
Show file tree
Hide file tree
Showing 10 changed files with 127 additions and 25 deletions.
18 changes: 11 additions & 7 deletions src/modules/bluefish/producer/bluefish_producer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ struct bluefish_producer
src_video->interlaced_frame = !is_progressive;
src_video->top_field_first = height != 486;
src_video->key_frame = 1;
src_video->display_picture_number = frames_captured;
//src_video->display_picture_number = frames_captured;
src_video->pts = capture_ts;

void* video_bytes = reserved_frames_.front()->image_data();
Expand All @@ -461,8 +461,12 @@ struct bluefish_producer
}

// Audio
src_audio->format = AV_SAMPLE_FMT_S32;
src_audio->channels = format_desc_.audio_channels;
src_audio->format = AV_SAMPLE_FMT_S32;
#if FFMPEG_NEW_CHANNEL_LAYOUT
av_channel_layout_default(&src_audio->ch_layout, format_desc_.audio_channels);
#else
src_audio->channels = format_desc_.audio_channels;
#endif
src_audio->sample_rate = format_desc_.audio_sample_rate;
src_audio->nb_samples = 0;
int samples_decoded = 0;
Expand All @@ -480,15 +484,15 @@ struct bluefish_producer
card_type,
reinterpret_cast<unsigned int*>(hanc_buffer),
reinterpret_cast<unsigned int*>(&decoded_audio_bytes_[0]),
src_audio->channels);
format_desc_.audio_channels);

audio_bytes = reinterpret_cast<int32_t*>(&decoded_audio_bytes_[0]);

samples_decoded = no_extracted_pcm_samples / src_audio->channels;
samples_decoded = no_extracted_pcm_samples / format_desc_.audio_channels;
src_audio->nb_samples = samples_decoded;
src_audio->data[0] = reinterpret_cast<uint8_t*>(audio_bytes);
src_audio->linesize[0] =
src_audio->nb_samples * src_audio->channels *
src_audio->nb_samples * format_desc_.audio_channels *
av_get_bytes_per_sample(static_cast<AVSampleFormat>(src_audio->format));
src_audio->pts = capture_ts;
}
Expand All @@ -504,7 +508,7 @@ struct bluefish_producer
auto audio_bytes = reinterpret_cast<uint8_t*>(&decoded_audio_bytes_[0]);
if (audio_bytes) {
src_audio->nb_samples = remainaing_audio_samples_;
int bytes_left = remainaing_audio_samples_ * 4 * src_audio->channels;
int bytes_left = remainaing_audio_samples_ * 4 * format_desc_.audio_channels;
src_audio->data[0] = audio_bytes + bytes_left;
src_audio->linesize[0] = bytes_left;
remainaing_audio_samples_ = 0;
Expand Down
23 changes: 19 additions & 4 deletions src/modules/decklink/producer/decklink_producer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ struct Filter

auto args = (boost::format("time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=%#x") % 1 %
format_desc.audio_sample_rate % format_desc.audio_sample_rate % AV_SAMPLE_FMT_S32 %
av_get_default_channel_layout(format_desc.audio_channels))
ffmpeg::get_channel_layout_mask_for_channels(format_desc.audio_channels))
.str();
auto name = (boost::format("in_%d") % 0).str();

Expand Down Expand Up @@ -237,12 +237,23 @@ struct Filter
#pragma warning(push)
#pragma warning(disable : 4245)
#endif

AVSampleFormat sample_fmts[] = {AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE};
int64_t channel_layouts[] = {av_get_default_channel_layout(format_desc.audio_channels), 0};
int sample_rates[] = {format_desc.audio_sample_rate, 0};
FF(av_opt_set_int_list(sink, "sample_fmts", sample_fmts, -1, AV_OPT_SEARCH_CHILDREN));
FF(av_opt_set_int_list(sink, "channel_layouts", channel_layouts, 0, AV_OPT_SEARCH_CHILDREN));
FF(av_opt_set_int_list(sink, "sample_rates", sample_rates, 0, AV_OPT_SEARCH_CHILDREN));

#if FFMPEG_NEW_CHANNEL_LAYOUT
AVChannelLayout channel_layout = AV_CHANNEL_LAYOUT_STEREO;
av_channel_layout_default(&channel_layout, format_desc.audio_channels);

FF(av_opt_set_chlayout(sink, "ch_layouts", &channel_layout, AV_OPT_SEARCH_CHILDREN));
av_channel_layout_uninit(&channel_layout);
#else
int64_t channel_layouts[] = {av_get_default_channel_layout(format_desc.audio_channels), 0};
FF(av_opt_set_int_list(sink, "channel_layouts", channel_layouts, 0, AV_OPT_SEARCH_CHILDREN));
#endif

#ifdef _MSC_VER
#pragma warning(pop)
#endif
Expand Down Expand Up @@ -585,7 +596,11 @@ class decklink_producer : public IDeckLinkInputCallback
if (audio) {
auto src = std::shared_ptr<AVFrame>(av_frame_alloc(), [](AVFrame* ptr) { av_frame_free(&ptr); });
src->format = AV_SAMPLE_FMT_S32;
#if FFMPEG_NEW_CHANNEL_LAYOUT
av_channel_layout_default(&src->ch_layout, format_desc_.audio_channels);
#else
src->channels = format_desc_.audio_channels;
#endif
src->sample_rate = format_desc_.audio_sample_rate;

void* audio_bytes = nullptr;
Expand All @@ -594,7 +609,7 @@ class decklink_producer : public IDeckLinkInputCallback
src = std::shared_ptr<AVFrame>(src.get(), [src, audio](AVFrame* ptr) { audio->Release(); });
src->nb_samples = audio->GetSampleFrameCount();
src->data[0] = reinterpret_cast<uint8_t*>(audio_bytes);
src->linesize[0] = src->nb_samples * src->channels *
src->linesize[0] = src->nb_samples * format_desc_.audio_channels *
av_get_bytes_per_sample(static_cast<AVSampleFormat>(src->format));

if (SUCCEEDED(audio->GetPacketTime(&in_audio_pts, format_desc_.audio_sample_rate))) {
Expand Down
1 change: 1 addition & 0 deletions src/modules/ffmpeg/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ set(HEADERS
producer/ffmpeg_producer.h
consumer/ffmpeg_consumer.h

defines.h
ffmpeg.h
StdAfx.h
)
Expand Down
19 changes: 16 additions & 3 deletions src/modules/ffmpeg/consumer/ffmpeg_consumer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ struct Stream
} else if (codec->type == AVMEDIA_TYPE_AUDIO) {
auto args = (boost::format("time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=%#x") % 1 %
format_desc.audio_sample_rate % format_desc.audio_sample_rate % AV_SAMPLE_FMT_S32 %
av_get_default_channel_layout(format_desc.audio_channels))
get_channel_layout_mask_for_channels(format_desc.audio_channels))
.str();
auto name = (boost::format("in_%d") % 0).str();

Expand Down Expand Up @@ -229,8 +229,15 @@ struct Stream
#endif
// TODO codec->profiles
FF(av_opt_set_int_list(sink, "sample_fmts", codec->sample_fmts, -1, AV_OPT_SEARCH_CHILDREN));
FF(av_opt_set_int_list(sink, "channel_layouts", codec->channel_layouts, 0, AV_OPT_SEARCH_CHILDREN));
FF(av_opt_set_int_list(sink, "sample_rates", codec->supported_samplerates, 0, AV_OPT_SEARCH_CHILDREN));

#if FFMPEG_NEW_CHANNEL_LAYOUT
// TODO: need to translate codec->ch_layouts into something that can be passed via av_opt_set_*
// FF(av_opt_set_chlayout(sink, "ch_layouts", codec->ch_layouts, AV_OPT_SEARCH_CHILDREN));
#else
FF(av_opt_set_int_list(sink, "channel_layouts", codec->channel_layouts, 0, AV_OPT_SEARCH_CHILDREN));
#endif

#ifdef _MSC_VER
#pragma warning(pop)
#endif
Expand Down Expand Up @@ -283,15 +290,21 @@ struct Stream

enc->sample_fmt = static_cast<AVSampleFormat>(av_buffersink_get_format(sink));
enc->sample_rate = av_buffersink_get_sample_rate(sink);
enc->time_base = st->time_base;

#if FFMPEG_NEW_CHANNEL_LAYOUT
FF(av_buffersink_get_ch_layout(sink, &enc->ch_layout));
#else
enc->channels = av_buffersink_get_channels(sink);
enc->channel_layout = av_buffersink_get_channel_layout(sink);
enc->time_base = st->time_base;

if (!enc->channels) {
enc->channels = av_get_channel_layout_nb_channels(enc->channel_layout);
} else if (!enc->channel_layout) {
enc->channel_layout = av_get_default_channel_layout(enc->channels);
}
#endif

} else {
// TODO
}
Expand Down
5 changes: 5 additions & 0 deletions src/modules/ffmpeg/defines.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#pragma once

#include <libavcodec/version.h>

#define FFMPEG_NEW_CHANNEL_LAYOUT LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(60, 0, 0)
32 changes: 27 additions & 5 deletions src/modules/ffmpeg/producer/av_producer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,12 +127,14 @@ class Decoder
ctx->framerate = av_guess_frame_rate(nullptr, stream, nullptr);
ctx->sample_aspect_ratio = av_guess_sample_aspect_ratio(nullptr, stream, nullptr);
} else if (ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
#if !(FFMPEG_NEW_CHANNEL_LAYOUT)
if (!ctx->channel_layout && ctx->channels) {
ctx->channel_layout = av_get_default_channel_layout(ctx->channels);
}
if (!ctx->channels && ctx->channel_layout) {
ctx->channels = av_get_channel_layout_nb_channels(ctx->channel_layout);
}
#endif
}

if (codec->capabilities & AV_CODEC_CAP_SLICE_THREADS) {
Expand Down Expand Up @@ -178,7 +180,11 @@ class Decoder
// TODO (fix) is this always best?
av_frame->pts = av_frame->best_effort_timestamp;

#if LIBAVUTIL_VERSION_MAJOR < 58
auto duration_pts = av_frame->pkt_duration;
#else
auto duration_pts = av_frame->duration;
#endif
if (duration_pts <= 0) {
if (ctx->codec_type == AVMEDIA_TYPE_VIDEO) {
const auto ticks = av_stream_get_parser(st) ? av_stream_get_parser(st)->repeat_pict + 1
Expand Down Expand Up @@ -313,7 +319,12 @@ struct Filter
AVRational tb = {1, format_desc.audio_sample_rate};
for (auto n = 0U; n < input->nb_streams; ++n) {
const auto st = input->streams[n];
if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->channels > 0) {
#if FFMPEG_NEW_CHANNEL_LAYOUT
const auto codec_channels = st->codecpar->ch_layout.nb_channels;
#else
const auto codec_channels = st->codecpar->channels;
#endif
if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && codec_channels > 0) {
tb = {1, st->codecpar->sample_rate};
break;
}
Expand Down Expand Up @@ -364,7 +375,12 @@ struct Filter
for (auto n = 0U; n < input->nb_streams; ++n) {
const auto st = input->streams[n];

if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->channels == 0) {
#if FFMPEG_NEW_CHANNEL_LAYOUT
const auto codec_channels = st->codecpar->ch_layout.nb_channels;
#else
const auto codec_channels = st->codecpar->channels;
#endif
if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && codec_channels == 0) {
continue;
}

Expand Down Expand Up @@ -468,9 +484,16 @@ struct Filter
FF(avfilter_link(source, 0, cur->filter_ctx, cur->pad_idx));
sources.emplace(index, source);
} else if (st->codec_type == AVMEDIA_TYPE_AUDIO) {
#if FFMPEG_NEW_CHANNEL_LAYOUT
char channel_layout[128];
FF(av_channel_layout_describe(&st->ch_layout, channel_layout, sizeof(channel_layout)));
#else
const auto channel_layout = st->channel_layout;
#endif

auto args = (boost::format("time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=%#x") %
st->pkt_timebase.num % st->pkt_timebase.den % st->sample_rate %
av_get_sample_fmt_name(st->sample_fmt) % st->channel_layout)
av_get_sample_fmt_name(st->sample_fmt) % channel_layout)
.str();
auto name = (boost::format("in_%d") % index).str();

Expand Down Expand Up @@ -523,8 +546,7 @@ struct Filter
const AVSampleFormat sample_fmts[] = {AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE};
FF(av_opt_set_int_list(sink, "sample_fmts", sample_fmts, -1, AV_OPT_SEARCH_CHILDREN));

const int channel_counts[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, -1};
FF(av_opt_set_int_list(sink, "channel_counts", channel_counts, -1, AV_OPT_SEARCH_CHILDREN));
FF(av_opt_set_int(sink, "all_channel_counts", 1, AV_OPT_SEARCH_CHILDREN));

const int sample_rates[] = {format_desc.audio_sample_rate, -1};
FF(av_opt_set_int_list(sink, "sample_rates", sample_rates, -1, AV_OPT_SEARCH_CHILDREN));
Expand Down
32 changes: 28 additions & 4 deletions src/modules/ffmpeg/util/av_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,13 @@ core::mutable_frame make_frame(void* tag,
const int channel_count = 16;
frame.audio_data() = std::vector<int32_t>(audio->nb_samples * channel_count, 0);

if (audio->channels == channel_count) {
#if FFMPEG_NEW_CHANNEL_LAYOUT
auto source_channel_count = audio->ch_layout.nb_channels;
#else
auto source_channel_count = audio->channels;
#endif

if (source_channel_count == channel_count) {
std::memcpy(frame.audio_data().data(),
reinterpret_cast<int32_t*>(audio->data[0]),
sizeof(int32_t) * channel_count * audio->nb_samples);
Expand All @@ -82,8 +88,8 @@ core::mutable_frame make_frame(void* tag,
auto dst = frame.audio_data().data();
auto src = reinterpret_cast<int32_t*>(audio->data[0]);
for (auto i = 0; i < audio->nb_samples; i++) {
for (auto j = 0; j < std::min(channel_count, audio->channels); ++j) {
dst[i * channel_count + j] = src[i * audio->channels + j];
for (auto j = 0; j < std::min(channel_count, source_channel_count); ++j) {
dst[i * channel_count + j] = src[i * source_channel_count + j];
}
}
}
Expand Down Expand Up @@ -291,11 +297,15 @@ std::shared_ptr<AVFrame> make_av_audio_frame(const core::const_frame& frame, con
const auto& buffer = frame.audio_data();

// TODO (fix) Use sample_format_desc.
#if FFMPEG_NEW_CHANNEL_LAYOUT
av_channel_layout_default(&av_frame->ch_layout, format_desc.audio_channels);
#else
av_frame->channels = format_desc.audio_channels;
av_frame->channel_layout = av_get_default_channel_layout(av_frame->channels);
#endif
av_frame->sample_rate = format_desc.audio_sample_rate;
av_frame->format = AV_SAMPLE_FMT_S32;
av_frame->nb_samples = static_cast<int>(buffer.size() / av_frame->channels);
av_frame->nb_samples = static_cast<int>(buffer.size() / format_desc.audio_channels);
FF(av_frame_get_buffer(av_frame.get(), 32));
std::memcpy(av_frame->data[0], buffer.data(), buffer.size() * sizeof(buffer.data()[0]));

Expand Down Expand Up @@ -330,4 +340,18 @@ std::map<std::string, std::string> to_map(AVDictionary** dict)
return map;
}


uint64_t get_channel_layout_mask_for_channels(int channel_count) {
#if FFMPEG_NEW_CHANNEL_LAYOUT
AVChannelLayout layout = AV_CHANNEL_LAYOUT_STEREO;
av_channel_layout_default(&layout, channel_count);
uint64_t channel_layout = layout.u.mask;
av_channel_layout_uninit(&layout);

return channel_layout;
#else
return av_get_default_channel_layout(channel_count);
#endif
}

}} // namespace caspar::ffmpeg
4 changes: 4 additions & 0 deletions src/modules/ffmpeg/util/av_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include <memory>
#include <vector>

#include "../defines.h"

struct AVFrame;
struct AVPacket;
struct AVFilterContext;
Expand All @@ -33,4 +35,6 @@ std::shared_ptr<AVFrame> make_av_audio_frame(const core::const_frame& frame, con
AVDictionary* to_dict(std::map<std::string, std::string>&& map);
std::map<std::string, std::string> to_map(AVDictionary** dict);

uint64_t get_channel_layout_mask_for_channels(int channel_count);

}} // namespace caspar::ffmpeg
6 changes: 5 additions & 1 deletion src/modules/newtek/producer/newtek_ndi_producer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,11 @@ struct newtek_ndi_producer : public core::frame_producer
if (audio_frame.p_data != nullptr) {
audio_frame_32s.reference_level = 0;
ndi_lib_->util_audio_to_interleaved_32s_v2(&audio_frame, &audio_frame_32s);
a_frame->channels = audio_frame_32s.no_channels;
#if FFMPEG_NEW_CHANNEL_LAYOUT
av_channel_layout_default(&a_frame->ch_layout, audio_frame_32s.no_channels);
#else
a_frame->channels = audio_frame_32s.no_channels;
#endif
a_frame->sample_rate = audio_frame_32s.sample_rate;
a_frame->nb_samples = audio_frame_32s.no_samples;
a_frame->data[0] = reinterpret_cast<uint8_t*>(audio_frame_32s.p_data);
Expand Down
12 changes: 11 additions & 1 deletion src/modules/oal/consumer/oal_consumer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
#include <core/frame/frame.h>
#include <core/video_format.h>

#include <modules/ffmpeg/defines.h>

#include <boost/algorithm/string/erase.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/property_tree/ptree.hpp>
Expand Down Expand Up @@ -249,8 +251,12 @@ struct oal_consumer : public core::frame_consumer
auto dst = std::shared_ptr<AVFrame>(av_frame_alloc(), [](AVFrame* ptr) { av_frame_free(&ptr); });
dst->format = AV_SAMPLE_FMT_S16;
dst->sample_rate = format_desc_.audio_sample_rate;
#if FFMPEG_NEW_CHANNEL_LAYOUT
av_channel_layout_default(&dst->ch_layout, 2);
#else
dst->channels = 2;
dst->channel_layout = av_get_default_channel_layout(dst->channels);
#endif
dst->nb_samples = duration_;
if (av_frame_get_buffer(dst.get(), 32) < 0) {
// TODO FF error
Expand All @@ -277,9 +283,13 @@ struct oal_consumer : public core::frame_consumer
auto src = std::shared_ptr<AVFrame>(av_frame_alloc(), [](AVFrame* ptr) { av_frame_free(&ptr); });
src->format = AV_SAMPLE_FMT_S32;
src->sample_rate = format_desc_.audio_sample_rate;
#if FFMPEG_NEW_CHANNEL_LAYOUT
av_channel_layout_default(&src->ch_layout, format_desc_.audio_channels);
#else
src->channels = format_desc_.audio_channels;
src->channel_layout = av_get_default_channel_layout(src->channels);
src->nb_samples = static_cast<int>(frame.audio_data().size() / src->channels);
#endif
src->nb_samples = static_cast<int>(frame.audio_data().size() / format_desc_.audio_channels);
src->extended_data[0] = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(frame.audio_data().data()));
src->linesize[0] = static_cast<int>(frame.audio_data().size() * sizeof(int32_t));

Expand Down

0 comments on commit c7999b7

Please sign in to comment.