[Libav-user] Incorrect compressed audio
Jonathan Noble
jonnobleuk at gmail.com
Tue Jan 28 11:49:00 EET 2020
On Tue, 28 Jan 2020 at 00:12, Leandro Moreira <
leandro.ribeiro.moreira at gmail.com> wrote:
> Hi there,
>
> I think that the transcoder example
> <https://github.com/FFmpeg/FFmpeg/blob/master/doc/examples/transcoding.c>
> provided by ffmpeg works as well as some community sample code
> <https://github.com/leandromoreira/ffmpeg-libav-tutorial#chapter-3---transcoding>
> .
>
> Thanks. Those are the ones I've been referring to, amongst countless
others, so far. I'll have a read through them again or try my encoding
stage with a definite known input (create samples in code to replicate a
sinewave or silence).
>
> On Sat, Jan 25, 2020 at 7:31 PM Jonathan Noble <jonnobleuk at gmail.com>
> wrote:
>
>> Hi,
>> I don't know why I am not getting a reply to my previous e-mails, so I am
>> trying again. Please let me know if they were there.
>>
>> I have a pipeline of reader->decoder->encoder->writer where the codec
>> parameters are the same on encoder and decoder.
>> The resultant file has audio that is distorted and considerably shorter
>> than the file that was being read from. There are no messages returned from
>> ffmpeg to indicate anything going wrong.
>>
>> I've spent the last week looking into this and i've not got any further
>> than at the start. Instead of posting my original code I thought i'd make a
>> small representation of my code use ffmpeg calls only.
>>
>> What is it that I am missing? Are my e-mails getting through?
>> Thanks in advance.
>> Jon Noble
>>
>> ### The code ###
>>
>> #include <assert.h>
>> #include <libavformat/avformat.h>
>> #include <libavcodec/avcodec.h>
>> #include <stdio.h>
>>
>> const char* source =
>> "/home/jon/Projects/Code/mediahandling/RegressionTests/ReferenceMedia/Audio/ogg/monotone.ogg";
>> const char* destination = "/tmp/vorbis.ogg";
>>
>> AVFormatContext* d_ctx = NULL;
>> AVCodec* d_codec = NULL;
>> AVCodecParameters* d_codec_params = NULL;
>> int d_stream_index = -1;
>> AVFrame* d_frame = NULL;
>>
>> AVFormatContext* e_ctx = NULL;
>> AVCodec* e_codec = NULL;
>> AVCodecContext* e_codec_ctx = NULL;
>> AVStream* e_stream = NULL;
>> AVFrame* e_frame = NULL;
>>
>>
>> int sample_count = 0;
>> int sample_rate = 0;
>>
>> int open_source()
>> {
>> d_ctx = avformat_alloc_context();
>> int code = avformat_open_input(&d_ctx, source, NULL, NULL);
>> assert(code >= 0);
>> code = avformat_find_stream_info(d_ctx, NULL);
>> assert(code >= 0);
>>
>> for (int i = 0; i < d_ctx->nb_streams; ++i)
>> {
>> AVCodecParameters* local = d_ctx->streams[i]->codecpar;
>> assert(local != NULL);
>> if (local->codec_type == AVMEDIA_TYPE_AUDIO)
>> {
>> sample_rate = local->sample_rate;
>> d_stream_index = i;
>> d_codec_params = local;
>> d_codec = avcodec_find_decoder(local->codec_id);
>> assert(d_codec != NULL);
>> av_dump_format(d_ctx,i, source, 0);
>> return 0;
>> }
>> }
>> return code;
>> }
>>
>> int setup_encoder()
>> {
>> /* allocate the output media context */
>> int ret = avformat_alloc_output_context2(&e_ctx, NULL, NULL,
>> destination);
>> assert(ret >= 0);
>>
>> AVOutputFormat *fmt = e_ctx->oformat;
>> if (fmt->audio_codec != AV_CODEC_ID_NONE)
>> {
>> e_codec = avcodec_find_encoder(fmt->audio_codec);
>> e_stream = avformat_new_stream(e_ctx, NULL);
>> e_stream->id = e_ctx->nb_streams - 1;
>> e_codec_ctx = avcodec_alloc_context3(e_codec);
>> e_codec_ctx->sample_fmt = d_codec_params->format;
>> e_codec_ctx->bit_rate = d_codec_params->bit_rate;
>> e_codec_ctx->sample_rate = d_codec_params->sample_rate;
>> e_codec_ctx->channels = d_codec_params->channels;
>> e_codec_ctx->channel_layout = d_codec_params->channel_layout;
>> e_stream->time_base = (AVRational) {1, e_codec_ctx->sample_rate};
>> if (e_ctx->oformat->flags & AVFMT_GLOBALHEADER)
>> {
>> e_codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
>> }
>>
>> ret = avcodec_open2(e_codec_ctx, e_codec, NULL);
>> assert(ret >= 0);
>> ret = avcodec_parameters_from_context(e_stream->codecpar,
>> e_codec_ctx);
>> assert(ret >= 0);
>>
>> av_dump_format(e_ctx, 0, destination, 1);
>> ret = avio_open(&e_ctx->pb, destination, AVIO_FLAG_WRITE);
>> assert(ret >= 0);
>>
>> int64_t sample_count = 0;
>> e_frame = av_frame_alloc();
>> e_frame->format = d_codec_params->format;
>> e_frame->channel_layout = d_codec_params->channel_layout;
>> e_frame->sample_rate = d_codec_params->sample_rate;
>> e_frame->nb_samples = e_codec_ctx->codec->capabilities &
>> AV_CODEC_CAP_VARIABLE_FRAME_SIZE ? 10000 : e_codec_ctx->frame_size;
>> ret = av_frame_get_buffer(e_frame, 0);
>> assert(ret >= 0);
>> }
>> return ret;
>> }
>>
>> int encode()
>> {
>> assert(e_frame);
>> assert(e_ctx);
>> assert(e_codec_ctx);
>> AVPacket pkt = { NULL, 0, 0 }; // data and size must be 0;
>> av_init_packet(&pkt);
>>
>> int code = av_frame_make_writable(e_frame);
>> assert(code >= 0);
>> e_frame->pts = av_rescale_q(sample_count, (AVRational){1,
>> sample_rate}, e_codec_ctx->time_base);
>> e_frame->data[0] = d_frame->data[0];
>>
>> int got_packet;
>> code = avcodec_encode_audio2(e_codec_ctx, &pkt, e_frame, &got_packet);
>> assert(code >= 0);
>> if (got_packet == 1) {
>> av_packet_rescale_ts(&pkt, e_codec_ctx->time_base,
>> e_stream->time_base);
>> pkt.stream_index = e_stream->index;
>> code = av_interleaved_write_frame(e_ctx, &pkt);
>> assert(code >= 0);
>> }
>> sample_count += d_frame->nb_samples;
>> return code;
>> }
>>
>> int main()
>> {
>>
>> int code = open_source();
>> assert(code >= 0);
>> assert(d_ctx != NULL);
>> assert(d_codec != NULL);
>> assert(d_codec_params != NULL);
>> AVCodecContext* d_codec_context = avcodec_alloc_context3(d_codec);
>> assert(d_codec_context != NULL);
>> code = avcodec_parameters_to_context(d_codec_context, d_codec_params);
>> assert(code >= 0);
>> code = avcodec_open2(d_codec_context, d_codec, NULL);
>> assert(code >= 0);
>> d_frame = av_frame_alloc();
>> AVPacket* d_packet = av_packet_alloc();
>>
>> code = setup_encoder();
>> assert(code >= 0);
>>
>> code = avformat_write_header(e_ctx, NULL);
>> assert(code >= 0);
>>
>> // read raw packets from stream
>> while (av_read_frame(d_ctx, d_packet) >= 0)
>> {
>> if (d_packet->stream_index == d_stream_index)
>> {
>> // send packet to decoder
>> code = avcodec_send_packet(d_codec_context, d_packet);
>> assert(code >= 0);
>> while (code >= 0)
>> {
>> code = avcodec_receive_frame(d_codec_context, d_frame);
>> if (code == AVERROR(EAGAIN) || code == AVERROR_EOF)
>> {
>> break;
>> }
>> assert(code >= 0);
>> encode();
>> }
>> }
>> av_packet_unref(d_packet);
>> }
>>
>> av_frame_free(&e_frame);
>> return code;
>> }
>>
>> ### STDOUT ###
>>
>> [jon at jon-desktop ffmpegtest]$ ./a.out
>> Input #0, ogg, from
>> '/home/jon/Projects/Code/mediahandling/RegressionTests/ReferenceMedia/Audio/ogg/monotone.ogg':
>> Duration: 00:00:03.00, start: 0.000000, bitrate: 23 kb/s
>> Stream #0:0: Audio: vorbis, 44100 Hz, mono, fltp, 96 kb/s
>> Output #0, ogg, to '/tmp/vorbis.ogg':
>> Stream #0:0: Audio: vorbis, 44100 Hz, mono, fltp, 96 kb/s
>> _______________________________________________
>> Libav-user mailing list
>> Libav-user at ffmpeg.org
>> https://ffmpeg.org/mailman/listinfo/libav-user
>>
>> To unsubscribe, visit link above, or email
>> libav-user-request at ffmpeg.org with subject "unsubscribe".
>
> _______________________________________________
> Libav-user mailing list
> Libav-user at ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/libav-user
>
> To unsubscribe, visit link above, or email
> libav-user-request at ffmpeg.org with subject "unsubscribe".
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://ffmpeg.org/pipermail/libav-user/attachments/20200128/23448169/attachment.html>
More information about the Libav-user
mailing list