Skip to content

Commit

Permalink
Merge pull request #3109 from traversaro/fixffmpeg7
Browse files Browse the repository at this point in the history
SoundFileMp3 and ffmpegPortmonitor: Fix compatibility with ffmpeg 7
  • Loading branch information
randaz81 authored Jun 3, 2024
2 parents 93ac24d + fd90f84 commit 2c1ff12
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 6 deletions.
1 change: 1 addition & 0 deletions doc/release/master.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Fixes

* Configuration files installed by the `yarp_configure_plugins_installation` CMake macro are now relocatable (https://github.com/robotology/yarp/issues/2445, ).
* Improved `ffmpeg` port monitor to allow using different couples of coders/decodes
* Fixed compatibility with ffmpeg 7 (https://github.com/robotology/yarp/pull/3109).

New Features
------------
Expand Down
84 changes: 78 additions & 6 deletions src/libYARP_sig/src/yarp/sig/SoundFileMp3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,17 @@ bool decode(AVCodecContext* dec_ctx, AVPacket* pkt, AVFrame* frame, Sound& sound
}

yarp::sig::Sound frame_sound;
frame_sound.resize(frame->nb_samples, dec_ctx->channels);
if (sound_data.getChannels()==0) { sound_data.resize(0, dec_ctx->channels);}
#if LIBAVCODEC_VERSION_MAJOR >= 61
int num_channels = dec_ctx->ch_layout.nb_channels;
#else
int num_channels = dec_ctx->channels;
#endif
frame_sound.resize(frame->nb_samples, num_channels);
if (sound_data.getChannels()==0) { sound_data.resize(0, num_channels);}

for (i = 0; i < frame->nb_samples; i++) //1152
{
for (ch = 0; ch < dec_ctx->channels; ch++) //2
for (ch = 0; ch < num_channels; ch++) //2
{
short int val = *((short int*)frame->data[ch] + i);
frame_sound.set(val,i,ch);
Expand Down Expand Up @@ -168,6 +173,42 @@ bool encode(AVCodecContext* ctx, AVFrame* frame, AVPacket* pkt, std::fstream& os
return true;
}

#if LIBAVCODEC_VERSION_MAJOR >= 61
// Taken from https://github.com/FFmpeg/FFmpeg/blob/f5ef91e02080316f50d606f5b0b03333bb627ed7/doc/examples/encode_audio.c#L72C1-L92C2
/* select layout with the highest channel count */
static int select_channel_layout(const AVCodec *codec, AVChannelLayout *dst)
{
const AVChannelLayout *p, *best_ch_layout=nullptr;
int best_nb_channels = 0;

if (!codec->ch_layouts)
{
AVChannelLayout layout_stereo = AV_CHANNEL_LAYOUT_STEREO;
return av_channel_layout_copy(dst, &layout_stereo);
}

p = codec->ch_layouts;
while (p->nb_channels)
{
int nb_channels = p->nb_channels;

if (nb_channels > best_nb_channels)
{
best_ch_layout = p;
best_nb_channels = nb_channels;
}
p++;
}

if (!best_ch_layout)
{
return -1;
}

return av_channel_layout_copy(dst, best_ch_layout);
}
#else
// Taken from https://github.com/FFmpeg/FFmpeg/blob/50e9e11316064ecdee889b18a0b6681a248edcf4/doc/examples/encode_audio.c#L72C1-L93C2
/* select layout with the highest channel count */
int select_channel_layout(const AVCodec * codec)
{
Expand All @@ -193,7 +234,8 @@ int select_channel_layout(const AVCodec * codec)
}
return best_ch_layout;
}
#endif
#endif /* LIBAVCODEC_VERSION_MAJOR >= 61 */
#endif /* defined (YARP_HAS_FFMPEG) */

//#######################################################################################################
bool yarp::sig::file::write_mp3_file(const Sound& sound_data, const char* filename, size_t bitrate)
Expand Down Expand Up @@ -245,8 +287,18 @@ bool yarp::sig::file::write_mp3_file(const Sound& sound_data, const char* filena

// select other audio parameters supported by the encoder
c->sample_rate = select_sample_rate(codec);
#if LIBAVCODEC_VERSION_MAJOR >= 61
// from https://github.com/FFmpeg/FFmpeg/commit/f5ef91e02080316f50d606f5b0b03333bb627ed7#diff-85abeaf18e8c74a972fa1f5ab3c2fdfa7ddc818f9048196c6bd5f63a837b076aL167
ret = select_channel_layout(codec, &c->ch_layout);
if (ret < 0)
{
yCError(SOUNDFILE_MP3, "Could not select_channel_layout");
return false;
}
#else
c->channel_layout = select_channel_layout(codec);
c->channels = av_get_channel_layout_nb_channels(c->channel_layout);
#endif

// open it
if (avcodec_open2(c, codec, NULL) < 0)
Expand Down Expand Up @@ -282,7 +334,19 @@ bool yarp::sig::file::write_mp3_file(const Sound& sound_data, const char* filena

frame->nb_samples = c->frame_size;
frame->format = c->sample_fmt;

#if LIBAVCODEC_VERSION_MAJOR >= 61
// See https://github.com/FFmpeg/FFmpeg/commit/f5ef91e02080316f50d606f5b0b03333bb627ed7#diff-85abeaf18e8c74a972fa1f5ab3c2fdfa7ddc818f9048196c6bd5f63a837b076aL198
ret = av_channel_layout_copy(&frame->ch_layout, &c->ch_layout);
if (ret < 0)
{
yCError(SOUNDFILE_MP3, "Could not copy channel layout");
fos.close();
return false;
}
#else
frame->channel_layout = c->channel_layout;
#endif

// allocate the data buffers
ret = av_frame_get_buffer(frame, 0);
Expand All @@ -305,11 +369,19 @@ bool yarp::sig::file::write_mp3_file(const Sound& sound_data, const char* filena
exit(1);
}

#if LIBAVCODEC_VERSION_MAJOR >= 61
// See https://github.com/FFmpeg/FFmpeg/commit/f5ef91e02080316f50d606f5b0b03333bb627ed7#diff-85abeaf18e8c74a972fa1f5ab3c2fdfa7ddc818f9048196c6bd5f63a837b076aL221
int ch_layout_nb_channels = c->ch_layout.nb_channels;
#else
int ch_layout_nb_channels = c->channels;
#endif


samples = (uint16_t*)frame->data[0];
for (int j = 0; j < c->frame_size; j++)
{
for (int k = 0; k < c->channels; k++) {
samples[j * c->channels + k] = sound_data.get(j + i * c->frame_size, k);
for (int k = 0; k < ch_layout_nb_channels; k++) {
samples[j * ch_layout_nb_channels + k] = sound_data.get(j + i * c->frame_size, k);
}
}
if (encode(c, frame, pkt, fos) == false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,10 @@ void FfmpegMonitorObject::destroy(void)

// Check if codec context is freeable, if yes free it.
if (codecContext != NULL) {
#if LIBAVCODEC_VERSION_MAJOR < 61
// See https://github.com/FFmpeg/FFmpeg/blob/n7.0/libavcodec/avcodec.h#L2381-L2384
avcodec_close(codecContext);
#endif
avcodec_free_context(&codecContext);
codecContext = NULL;
}
Expand Down Expand Up @@ -535,7 +538,12 @@ int FfmpegMonitorObject::compress(Image* img, AVPacket *pkt) {
}

// Set presentation timestamp
#if LIBAVCODEC_VERSION_MAJOR >= 61
// See https://github.com/FFmpeg/FFmpeg/commit/6b6f7db81932f94876ff4bcfd2da0582b8ab897e
endFrame->pts = codecContext->frame_num;
#else
endFrame->pts = codecContext->frame_number;
#endif

// Send image frame to codec
ret = avcodec_send_frame(codecContext, endFrame);
Expand Down

0 comments on commit 2c1ff12

Please sign in to comment.