X-Git-Url: https://git.sesse.net/?p=nageru;a=blobdiff_plain;f=audio_encoder.cpp;h=e33d2181b46a5465a648bceead3636ba9872b535;hp=2b735e4d44f5ff27b95588032fd3e73459ff7e64;hb=4e3c52ba57c4552a969e71ccdefd9941ce8d6290;hpb=2804eb55c7d4f9f6d70203d106d0f1e69b19c2ee diff --git a/audio_encoder.cpp b/audio_encoder.cpp index 2b735e4..e33d218 100644 --- a/audio_encoder.cpp +++ b/audio_encoder.cpp @@ -5,23 +5,29 @@ extern "C" { #include #include #include +#include #include +#include +#include #include #include -#include } #include - +#include +#include +#include +#include #include #include #include "defs.h" +#include "mux.h" #include "timebase.h" using namespace std; -AudioEncoder::AudioEncoder(const string &codec_name, int bit_rate) +AudioEncoder::AudioEncoder(const string &codec_name, int bit_rate, const AVOutputFormat *oformat) { AVCodec *codec = avcodec_find_encoder_by_name(codec_name.c_str()); if (codec == nullptr) { @@ -36,7 +42,9 @@ AudioEncoder::AudioEncoder(const string &codec_name, int bit_rate) ctx->channels = 2; ctx->channel_layout = AV_CH_LAYOUT_STEREO; ctx->time_base = AVRational{1, TIMEBASE}; - ctx->flags |= CODEC_FLAG_GLOBAL_HEADER; + if (oformat->flags & AVFMT_GLOBALHEADER) { + ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; + } if (avcodec_open2(ctx, codec, NULL) < 0) { fprintf(stderr, "Could not open codec '%s'\n", codec_name.c_str()); exit(1); @@ -116,24 +124,35 @@ void AudioEncoder::encode_audio_one_frame(const float *audio, size_t num_samples exit(1); } - AVPacket pkt; - av_init_packet(&pkt); - pkt.data = nullptr; - pkt.size = 0; - int got_output = 0; - avcodec_encode_audio2(ctx, &pkt, audio_frame, &got_output); - if (got_output) { - pkt.stream_index = 1; - pkt.flags = 0; - for (Mux *mux : muxes) { - mux->add_packet(pkt, pkt.pts, pkt.dts); + int err = avcodec_send_frame(ctx, audio_frame); + if (err < 0) { + fprintf(stderr, "avcodec_send_frame() failed with error %d\n", err); + exit(1); + } + + for ( ;; ) { // Termination condition within loop. + AVPacket pkt; + av_init_packet(&pkt); + pkt.data = nullptr; + pkt.size = 0; + int err = avcodec_receive_packet(ctx, &pkt); + if (err == 0) { + pkt.stream_index = 1; + pkt.flags = 0; + for (Mux *mux : muxes) { + mux->add_packet(pkt, pkt.pts, pkt.dts); + } + av_packet_unref(&pkt); + } else if (err == AVERROR(EAGAIN)) { + break; + } else { + fprintf(stderr, "avcodec_receive_frame() failed with error %d\n", err); + exit(1); } } av_freep(&audio_frame->data[0]); - av_frame_unref(audio_frame); - av_free_packet(&pkt); } void AudioEncoder::encode_last_audio() @@ -148,20 +167,31 @@ void AudioEncoder::encode_last_audio() if (ctx->codec->capabilities & AV_CODEC_CAP_DELAY) { // Collect any delayed frames. for ( ;; ) { - int got_output = 0; AVPacket pkt; av_init_packet(&pkt); pkt.data = nullptr; pkt.size = 0; - avcodec_encode_audio2(ctx, &pkt, nullptr, &got_output); - if (!got_output) break; - - pkt.stream_index = 1; - pkt.flags = 0; - for (Mux *mux : muxes) { - mux->add_packet(pkt, pkt.pts, pkt.dts); + int err = avcodec_receive_packet(ctx, &pkt); + if (err == 0) { + pkt.stream_index = 1; + pkt.flags = 0; + for (Mux *mux : muxes) { + mux->add_packet(pkt, pkt.pts, pkt.dts); + } + av_packet_unref(&pkt); + } else if (err == AVERROR_EOF) { + break; + } else { + fprintf(stderr, "avcodec_receive_frame() failed with error %d\n", err); + exit(1); } - av_free_packet(&pkt); } } } + +AVCodecParametersWithDeleter AudioEncoder::get_codec_parameters() +{ + AVCodecParameters *codecpar = avcodec_parameters_alloc(); + avcodec_parameters_from_context(codecpar, ctx); + return AVCodecParametersWithDeleter(codecpar); +}