summaryrefslogtreecommitdiff
path: root/audio/encoder.c
diff options
context:
space:
mode:
authorbbergeron <[email protected]>2024-04-03 17:32:01 -0400
committerbbergeron <[email protected]>2024-04-03 17:32:01 -0400
commitc1cb78d574c0429aa5e3ff3a2b3886e4bc153212 (patch)
treebf68806bcbddcafafc015b28c25550ea457eeecc /audio/encoder.c
Reset Git repo and use a pseudonym to sign commits
I used to sign my commits with my real name and my personal email address, which I wanted scrubbed off the "B." pseudosphere. Re-creating a new git repository was safer than simpler than re-writing the history (although the latter could've also worked but, oh well).
Diffstat (limited to 'audio/encoder.c')
-rw-r--r--audio/encoder.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/audio/encoder.c b/audio/encoder.c
new file mode 100644
index 0000000..17cf2d2
--- /dev/null
+++ b/audio/encoder.c
@@ -0,0 +1,69 @@
+#include "encoder.h"
+#include <assert.h>
+
+int encoder_init (struct Encoder *encoder, const AVCodecParameters *codecpar, AVDictionary **opts)
+{
+ /* NOTE: While encoder->time_base "MUST be set by user" when encoding
+ * (quoted from the official FFMPEG documentation), avcodec_open2 actually
+ * discard it's value and set it to '1/sample_rate'.
+ *
+ * NOTE: The assert at the end of this section serves to protect cybd in
+ * case the FFMPEG devs update their code to implement some funny behaviors.
+ */
+ int err;
+ AVCodecContext *avctx;
+ const AVCodec *codec;
+
+ if ((codec = avcodec_find_encoder(codecpar->codec_id)) == NULL) {
+ err = AVERROR_ENCODER_NOT_FOUND;
+ goto error;
+ }
+
+ if ((avctx = avcodec_alloc_context3(codec)) == NULL)
+ return AVERROR(ENOMEM);
+
+ if ((err = avcodec_parameters_to_context(avctx, codecpar)) < 0)
+ goto error;
+
+ if ((err = avcodec_open2(avctx, codec, opts)))
+ goto error;
+
+ /* Because some code rely on avctx's time base to be 1/sample_rate, and
+ * because this behavious currently appears undocumented, I placed some
+ * assert here to catch up if anything changes up with ffmpeg. */
+ assert(avctx->time_base.num == 1);
+ assert(avctx->time_base.den == avctx->sample_rate);
+ encoder->avctx = avctx;
+ encoder->pts = 0;
+ return 0;
+
+error:
+ avcodec_free_context(&avctx);
+ return err;
+}
+
+int encoder_init_for_stream (struct Encoder *encoder, const AVStream *stream, AVDictionary **opts)
+{
+ return encoder_init(encoder, stream->codecpar, opts);
+}
+
+int encoder_send (struct Encoder *encoder, const AVFrame *frame)
+{
+ return avcodec_send_frame(encoder->avctx, frame);
+}
+
+int encoder_convert (struct Encoder *encoder, AVPacket *pkt_out)
+{
+ int err;
+ err = avcodec_receive_packet(encoder->avctx, pkt_out);
+ if (err < 0) return err;
+ // Manually setting pts because FFMPEG doesn't do it consistantly
+ //pkt_out->pts = encoder->pts;
+ //encoder->pts += pkt_out->duration;
+ return 0;
+}
+
+void encoder_free (struct Encoder *encoder)
+{
+ avcodec_free_context(&encoder->avctx);
+}