]> git.sesse.net Git - nageru/blobdiff - audio_encoder.cpp
Fix a crash when trying to load/save files and CEF is active.
[nageru] / audio_encoder.cpp
index ac1c8f509f9aae5057335e3234dd2c2b123e6aa4..e33d2181b46a5465a648bceead3636ba9872b535 100644 (file)
@@ -5,18 +5,24 @@ extern "C" {
 #include <libavformat/avformat.h>
 #include <libavresample/avresample.h>
 #include <libavutil/channel_layout.h>
+#include <libavutil/error.h>
 #include <libavutil/frame.h>
+#include <libavutil/mem.h>
+#include <libavutil/opt.h>
 #include <libavutil/rational.h>
 #include <libavutil/samplefmt.h>
-#include <libavutil/opt.h>
 }
 
 #include <assert.h>
-
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <memory>
 #include <string>
 #include <vector>
 
 #include "defs.h"
+#include "mux.h"
 #include "timebase.h"
 
 using namespace std;
@@ -37,7 +43,7 @@ AudioEncoder::AudioEncoder(const string &codec_name, int bit_rate, const AVOutpu
        ctx->channel_layout = AV_CH_LAYOUT_STEREO;
        ctx->time_base = AVRational{1, TIMEBASE};
        if (oformat->flags & AVFMT_GLOBALHEADER) {
-               ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
+               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());
@@ -118,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()
@@ -150,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);
+}