summaryrefslogtreecommitdiff
path: root/modules/avcodec/avcodec.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/avcodec/avcodec.c')
-rw-r--r--modules/avcodec/avcodec.c176
1 files changed, 176 insertions, 0 deletions
diff --git a/modules/avcodec/avcodec.c b/modules/avcodec/avcodec.c
new file mode 100644
index 0000000..d6ce3de
--- /dev/null
+++ b/modules/avcodec/avcodec.c
@@ -0,0 +1,176 @@
+/**
+ * @file avcodec.c Video codecs using FFmpeg libavcodec
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+#include <re.h>
+#include <rem.h>
+#include <baresip.h>
+#include <libavcodec/avcodec.h>
+#ifdef USE_X264
+#include <x264.h>
+#endif
+#include "h26x.h"
+#include "avcodec.h"
+
+
+int avcodec_resolve_codecid(const char *s)
+{
+ if (0 == str_casecmp(s, "H263"))
+ return CODEC_ID_H263;
+ else if (0 == str_casecmp(s, "H264"))
+ return CODEC_ID_H264;
+ else if (0 == str_casecmp(s, "MP4V-ES"))
+ return CODEC_ID_MPEG4;
+ else
+ return CODEC_ID_NONE;
+}
+
+
+static uint32_t packetization_mode(const char *fmtp)
+{
+ struct pl pl, mode;
+
+ if (!fmtp)
+ return 0;
+
+ pl_set_str(&pl, fmtp);
+
+ if (fmt_param_get(&pl, "packetization-mode", &mode))
+ return pl_u32(&mode);
+
+ return 0;
+}
+
+
+static int h264_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt,
+ bool offer, void *arg)
+{
+ struct vidcodec *vc = arg;
+ const uint8_t profile_idc = 0x42; /* baseline profile */
+ const uint8_t profile_iop = 0x80;
+ (void)offer;
+
+ if (!mb || !fmt || !vc)
+ return 0;
+
+ return mbuf_printf(mb, "a=fmtp:%s"
+ " packetization-mode=0"
+ ";profile-level-id=%02x%02x%02x"
+ "\r\n",
+ fmt->id, profile_idc, profile_iop, h264_level_idc);
+}
+
+
+static bool h264_fmtp_cmp(const char *fmtp1, const char *fmtp2, void *data)
+{
+ (void)data;
+
+ return packetization_mode(fmtp1) == packetization_mode(fmtp2);
+}
+
+
+static int h263_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt,
+ bool offer, void *arg)
+{
+ (void)offer;
+ (void)arg;
+
+ if (!mb || !fmt)
+ return 0;
+
+ return mbuf_printf(mb, "a=fmtp:%s CIF=1;CIF4=1\r\n", fmt->id);
+}
+
+
+static int mpg4_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt,
+ bool offer, void *arg)
+{
+ (void)offer;
+ (void)arg;
+
+ if (!mb || !fmt)
+ return 0;
+
+ return mbuf_printf(mb, "a=fmtp:%s profile-level-id=3\r\n", fmt->id);
+}
+
+
+static struct vidcodec h264 = {
+ .name = "H264",
+ .variant = "packetization-mode=0",
+ .encupdh = encode_update,
+#ifdef USE_X264
+ .ench = encode_x264,
+#else
+ .ench = encode,
+#endif
+ .decupdh = decode_update,
+ .dech = decode_h264,
+ .fmtp_ench = h264_fmtp_enc,
+ .fmtp_cmph = h264_fmtp_cmp,
+};
+
+static struct vidcodec h263 = {
+ .pt = "34",
+ .name = "H263",
+ .encupdh = encode_update,
+ .ench = encode,
+ .decupdh = decode_update,
+ .dech = decode_h263,
+ .fmtp_ench = h263_fmtp_enc,
+};
+
+static struct vidcodec mpg4 = {
+ .name = "MP4V-ES",
+ .encupdh = encode_update,
+ .ench = encode,
+ .decupdh = decode_update,
+ .dech = decode_mpeg4,
+ .fmtp_ench = mpg4_fmtp_enc,
+};
+
+
+static int module_init(void)
+{
+#ifdef USE_X264
+ debug("avcodec: x264 build %d\n", X264_BUILD);
+#else
+ debug("avcodec: using FFmpeg H.264 encoder\n");
+#endif
+
+#if LIBAVCODEC_VERSION_INT < ((53<<16)+(10<<8)+0)
+ avcodec_init();
+#endif
+
+ avcodec_register_all();
+
+ if (avcodec_find_decoder(CODEC_ID_H264))
+ vidcodec_register(&h264);
+
+ if (avcodec_find_decoder(CODEC_ID_H263))
+ vidcodec_register(&h263);
+
+ if (avcodec_find_decoder(CODEC_ID_MPEG4))
+ vidcodec_register(&mpg4);
+
+ return 0;
+}
+
+
+static int module_close(void)
+{
+ vidcodec_unregister(&mpg4);
+ vidcodec_unregister(&h263);
+ vidcodec_unregister(&h264);
+
+ return 0;
+}
+
+
+EXPORT_SYM const struct mod_export DECL_EXPORTS(avcodec) = {
+ "avcodec",
+ "codec",
+ module_init,
+ module_close
+};