I am trying to learn how to use the FFmpeg libav* libraries but have encountered an issue when encoding to FLAC audio.
Running FFmpeg 5.1.7
I have copied the transcoding.c example from https://www.ffmpeg.org/doxygen/5.1/transcoding_8c-example.html , but made a slight modification in open_output_file() , where I change line 151 from:
encoder = avcodec_find_encoder(dec_ctx->codec_id);
to:
encoder = avcodec_find_encoder(AV_CODEC_ID_FLAC);
Otherwise, I would get the error:
Invalid audio stream. Exactly one FLAC audio stream is required.
I ran this to convert an MP3 file to a FLAC file, but it wouldn't be played by VLC. The ffplay command would play it just fine though, and sounds just the same as the source file. I then ran it with the flac -t and flac -a command, and would get the error:
ERROR, MD5 signature mismatch
When I convert the file using just the regular ffmpeg command instead, the resulting output file does not have the MD5 signature mismatch.
I have also tried:
Converting from a WAV file instead (same issue)
Manually setting encoder codec parameters (sample format S16, S32, 24-bit, etc.)
Nothing seems to resolve the issue.
Question: What might be causing the MD5 signature mismatch error?
Example that reproduces the error when converting S16 WAV to FLAC:
transcode.c:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int ret;
int main(int argc, char **argv) {
int error_code = 0;
if (argc != 3) {
av_log(NULL, AV_LOG_ERROR, "Usage: %s \n", argv[0]);
return 1;
}
const char *in_file = argv[1];
const char *out_file = argv[2];
AVFormatContext *decoder_format_context = avformat_alloc_context();
AVFormatContext *encoder_format_context = avformat_alloc_context();
AVStream *input_stream, *output_stream;
const AVCodec *decoder_codec, *encoder_codec;
AVCodecContext *decoder_codec_context, *encoder_codec_context;
AVFrame *decoded_frame;
AVPacket *input_packet, *output_packet;
ret = avformat_open_input(&decoder_format_context, in_file, NULL, NULL);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Failed to open input file \"%s\", error code %d\n", in_file, ret);
error_code = 1;
goto end;
}
ret = avformat_alloc_output_context2(&encoder_format_context, NULL, NULL, out_file);
if (!encoder_format_context) {
av_log(NULL, AV_LOG_ERROR, "Failed to allocate encoder format context, error code %d\n", ret);
error_code = 1;
goto end;
}
av_dump_format(decoder_format_context, 0, in_file, 0);
input_stream = decoder_format_context->streams[0];
decoder_codec = avcodec_find_decoder(input_stream->codecpar->codec_id);
decoder_codec_context = avcodec_alloc_context3(decoder_codec);
avcodec_parameters_to_context(decoder_codec_context, input_stream->codecpar);
avcodec_open2(decoder_codec_context, decoder_codec, NULL);
encoder_codec = avcodec_find_encoder(AV_CODEC_ID_FLAC);
encoder_codec_context = avcodec_alloc_context3(encoder_codec);
output_stream = avformat_new_stream(encoder_format_context, NULL);
if (!output_stream) {
av_log(NULL, AV_LOG_ERROR, "Failed to create output stream");
error_code = 1;
goto end2;
}
encoder_codec_context->sample_fmt = AV_SAMPLE_FMT_S16;
encoder_codec_context->bits_per_raw_sample = 16;
encoder_codec_context->sample_rate = input_stream->codecpar->sample_rate;
encoder_codec_context->time_base = input_stream->time_base;
av_channel_layout_copy(&encoder_codec_context->ch_layout, &input_stream->codecpar->ch_layout);
if (encoder_format_context->oformat->flags & AVFMT_GLOBALHEADER) {
encoder_codec_context->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}
avcodec_open2(encoder_codec_context, encoder_codec, NULL);
avcodec_parameters_from_context(output_stream->codecpar, encoder_codec_context);
av_dump_format(encoder_format_context, 0, out_file, 1);
ret = avio_open(&encoder_format_context->pb, out_file, AVIO_FLAG_WRITE);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Failed to open output file, error code %d\n", ret);
error_code = 1;
goto end2;
}
ret = avformat_write_header(encoder_format_context, NULL);
if (ret != AVSTREAM_INIT_IN_WRITE_HEADER && ret != AVSTREAM_INIT_IN_INIT_OUTPUT) {
av_log(NULL, AV_LOG_ERROR, "Failed to write output file header, error code %d\n", ret);
error_code = 1;
goto end2;
}
decoded_frame = av_frame_alloc();
input_packet = av_packet_alloc();
output_packet = av_packet_alloc();
while(av_read_frame(decoder_format_context, input_packet) >= 0) {
ret = avcodec_send_packet(decoder_codec_context, input_packet);
// For all frames in input packet
while (ret >= 0) {
ret = avcodec_receive_frame(decoder_codec_context, decoded_frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
av_frame_unref(decoded_frame);
break;
} else if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Error receiving frame, error code %d\n", ret);
av_frame_unref(decoded_frame);
av_packet_unref(input_packet);
error_code = 1;
goto end3;
}
int ret2 = avcodec_send_frame(encoder_codec_context, decoded_frame);
// For all output packets from frame
while (ret2 >= 0) {
ret2 = avcodec_receive_packet(encoder_codec_context, output_packet);
if (ret2 == AVERROR(EAGAIN) || ret2 == AVERROR_EOF) {
av_packet_unref(output_packet);
break;
} else if (ret2 < 0) {
av_log(NULL, AV_LOG_ERROR, "Error receiving packet, error code %d\n", ret2);
av_packet_unref(output_packet);
av_frame_unref(decoded_frame);
av_packet_unref(input_packet);
error_code = 1;
goto end3;
}
output_packet->stream_index = 0;
ret2 = av_interleaved_write_frame(encoder_format_context, output_packet);
if (ret2 < 0) {
av_log(NULL, AV_LOG_ERROR, "Error writing frame, error code %d\n", ret2);
av_packet_unref(output_packet);
av_frame_unref(decoded_frame);
av_packet_unref(input_packet);
error_code = 1;
goto end3;
}
av_packet_unref(output_packet);
}
av_frame_unref(decoded_frame);
}
av_packet_unref(input_packet);
}
// Flushing encoder
ret = avcodec_send_frame(encoder_codec_context, NULL);
while (ret >= 0) {
ret = avcodec_receive_packet(encoder_codec_context, output_packet);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
av_packet_unref(output_packet);
break;
} else if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Error receiving packet, error code %d\n", ret);
av_packet_unref(output_packet);
error_code = 1;
goto end3;
}
output_packet->stream_index = 0;
ret = av_interleaved_write_frame(encoder_format_context, output_packet);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Error writing frame, error code %d\n", ret);
av_packet_unref(output_packet);
error_code = 1;
goto end3;
}
av_packet_unref(output_packet);
}
ret = av_write_trailer(encoder_format_context);
if (ret != AVSTREAM_INIT_IN_WRITE_HEADER && ret != AVSTREAM_INIT_IN_INIT_OUTPUT) {
av_log(NULL, AV_LOG_ERROR, "Failed to write output file trailer, error code %d\n", ret);
error_code = 1;
goto end3;
}
end3:
av_frame_free(&decoded_frame);
av_packet_free(&input_packet);
av_packet_free(&output_packet);
end2:
avcodec_free_context(&decoder_codec_context);
avcodec_free_context(&encoder_codec_context);
end:
avformat_free_context(decoder_format_context);
avformat_free_context(encoder_format_context);
return error_code;
}
Compiled with:
gcc transcode.c -lavcodec -lavformat -lavfilter -l avutil -std=c99 -o transcode
Ran with:
./transcode INPUT.wav OUTPUT.flac