[Libav-user] Incorrect compressed audio
Andrew Randrianasulu
randrianasulu at gmail.com
Sun Jan 26 04:47:59 EET 2020
В сообщении от Sunday 26 January 2020 01:30:44 Jonathan Noble написал(а):
> 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?
I can see your emails (so they arrive at Libav-user), but sadly can't help -
myself is only curious user
> 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
>
More information about the Libav-user
mailing list