#include #include #include #include #include #include #include #include #include "muxer.h" #include "encoder.h" #include "decoder.h" #include "resampler.h" #include "stream.h" #define NANOSEC (uint64_t)1000000000 struct AudioMuxer { struct Stream stream; struct Encoder encoder; struct Decoder decoder; struct Resampler resampler; AVFrame *frame_in; AVFrame *frame_out; AVPacket *packet; /* The amount of output samples that went out of this muxer. Starts at 0 and * keep on increasing. */ unsigned int nb_samples_out; }; int64_t audiomuxer_flush(AudioMuxer *muxer); uint64_t audiomuxer_get_runtime(const AudioMuxer *muxer) { return (muxer->nb_samples_out * NANOSEC) / muxer->resampler.out_sample_rate; } int audiomuxer_init(AudioMuxer **pmuxer, AVFormatContext *s, const struct AudioMuxerOpt *opts) { int err; AudioMuxer *muxer; AVFrame *frame_out; AVFrame *frame_in; AVPacket *pkt; *pmuxer = NULL; if ((muxer = malloc(sizeof(AudioMuxer))) == NULL) return AVERROR(ENOMEM); muxer->decoder.avctx = NULL; muxer->encoder.avctx = NULL; muxer->resampler.swr = NULL; err = stream_init( &muxer->stream, s, opts->codec_id, opts->sample_rate, opts->sample_format, &opts->ch_layout, opts->opts_muxer); if (err) goto error; err = encoder_init_for_stream(&muxer->encoder, muxer->stream.av_stream, opts->opts_encoder); if (err) goto error; err = resampler_init_for_encoder(&muxer->resampler, &muxer->encoder); if (err) goto error; if ((frame_out = av_frame_alloc()) == NULL) goto enomem; if ((frame_in = av_frame_alloc()) == NULL) goto enomem; if ((pkt = av_packet_alloc()) == NULL) goto enomem; frame_out->format = muxer->encoder.avctx->sample_fmt; frame_out->nb_samples = muxer->encoder.avctx->frame_size; frame_out->ch_layout = muxer->encoder.avctx->ch_layout; frame_out->sample_rate = muxer->encoder.avctx->sample_rate; if ((err = av_frame_get_buffer(frame_out, 0))) goto error; muxer->packet = pkt; muxer->frame_out = frame_out; muxer->frame_in = frame_in; *pmuxer = muxer; return 0; enomem: err = AVERROR(ENOMEM); error: audiomuxer_free(muxer); return err; } int audiomuxer_conf (AudioMuxer *muxer, const AVStream *input) { int err, src_rate, dst_rate; const AVCodec *codec; SwrContext *resampler; src_rate = input->codecpar->sample_rate; err = decoder_init_for_stream(&muxer->decoder, input, NULL); // TODO: Pass options // TODO: Pass options if (err) { fprintf(stderr, "Failed to configure decoder: %s\n", av_err2str(err)); return err; } err = resampler_conf_for_decoder(&muxer->resampler, &muxer->decoder); if (err) { fprintf(stderr, "Failed to configure resampler: %s\n", av_err2str(err)); return err; } muxer->frame_in->format = muxer->decoder.avctx->sample_fmt; muxer->frame_in->nb_samples = muxer->decoder.avctx->frame_size; muxer->frame_in->ch_layout = muxer->decoder.avctx->ch_layout; muxer->frame_in->sample_rate = muxer->decoder.avctx->sample_rate; if ((err = av_frame_get_buffer(muxer->frame_in, 0))) return err; return 0; } int audiomuxer_send_packet (AudioMuxer *muxer, const AVPacket *pkt_in) { int err, duration; AVFrame *frame_in; frame_in = muxer->frame_in; if ((err = decoder_send(&muxer->decoder, pkt_in)) < 0) return err; /* Since a packet might contains several frames, we call decoder_convert * repeatedly until we're out of data. */ while ((err = decoder_convert(&muxer->decoder, frame_in)) != AVERROR(EAGAIN)) { /* Errors other than EAGAIN should be repported */ if (err) { fprintf(stderr, "Failed to decode frame: %s\n", av_err2str(err)); return err; } /* Immediately send frame to resampler and postpone silent injection */ if ((err = resampler_send_frame(&muxer->resampler, frame_in)) < 0) { fprintf(stderr, "Failed to send data to resampler: %s\n", av_err2str(err)); return err; } /* Flush frame if possible */ if ((err = audiomuxer_flush(muxer)) < 0) return err; } return 0; } int audiomuxer_send_silence (AudioMuxer *muxer, unsigned int microsec) { int err; if ((err = resampler_send_empty(&muxer->resampler, microsec))) return err; return audiomuxer_flush(muxer); } int64_t audiomuxer_flush(AudioMuxer *muxer) { int err; AVPacket *pkt_out; AVFrame *frame_out; frame_out = muxer->frame_out; pkt_out = muxer->packet; if ((err = resampler_convert(&muxer->resampler, frame_out))) { if (err == AVERROR(EAGAIN)) return 0; fprintf(stderr, "Failed to resample: %s\n", av_err2str(err)); return err; } if ((err = encoder_send(&muxer->encoder, frame_out))) { fprintf(stderr, "Failed to send frame to encoder: %s\n", av_err2str(err)); return err; } if ((err = encoder_convert(&muxer->encoder, pkt_out))) { if (err == AVERROR(EAGAIN)) return 0; fprintf(stderr, "Failed to encode packet: %s\n", av_err2str(err)); return err; } /* pkt_out->duration is the "Duration of this packet in AVStream->time_base * units, 0 if unknown." In practice, the timebase appears to be 1 / * sample_rate, so, in other words, pkt_out->duration is the amount of * samples stored in that packet. * * TODO: This behaviour is however undocumented, and asserts should be put * in place to catch potential regressions. * * NOTE: duration is usually 1152 with a default MP3 audio stream. */ assert(pkt_out->duration > 0); muxer->nb_samples_out += pkt_out->duration; /* Finally send packet to stream. */ if ((err = stream_send(&muxer->stream, pkt_out)) < 0) { fprintf(stderr, "Failed stream packet: %s\n", av_err2str(err)); return err; } return 0; } void audiomuxer_free (AudioMuxer *muxer) { if (muxer == NULL) return; /* Flush decoder */ avcodec_send_packet(muxer->decoder.avctx, NULL); encoder_free(&muxer->encoder); decoder_free(&muxer->decoder); resampler_free(&muxer->resampler); free(muxer); }