diff options
author | Alfred E. Heggestad <aeh@db.org> | 2014-12-26 13:38:05 +0100 |
---|---|---|
committer | Alfred E. Heggestad <aeh@db.org> | 2014-12-26 13:38:05 +0100 |
commit | e95e76d8b222c5433005ca6ad53407bcb51b58d7 (patch) | |
tree | 7784dbe6666b8a16097625eeb8dd20551ec396f2 /modules/h265 | |
parent | f55560474869956b374606973e4633206e9bf0da (diff) |
added h265 module
Diffstat (limited to 'modules/h265')
-rw-r--r-- | modules/h265/README | 29 | ||||
-rw-r--r-- | modules/h265/TODO | 6 | ||||
-rw-r--r-- | modules/h265/decode.c | 289 | ||||
-rw-r--r-- | modules/h265/encode.c | 253 | ||||
-rw-r--r-- | modules/h265/fmt.c | 159 | ||||
-rw-r--r-- | modules/h265/h265.c | 68 | ||||
-rw-r--r-- | modules/h265/h265.h | 69 | ||||
-rw-r--r-- | modules/h265/module.mk | 12 | ||||
-rw-r--r-- | modules/h265/notes | 75 |
9 files changed, 960 insertions, 0 deletions
diff --git a/modules/h265/README b/modules/h265/README new file mode 100644 index 0000000..75967c0 --- /dev/null +++ b/modules/h265/README @@ -0,0 +1,29 @@ +README h265 module +------------------ + + +Steps for building and testing: + + +1. build and install x265 from https://github.com/mirror/x265.git +2. build and install ffmpeg from git://source.ffmpeg.org/ffmpeg.git + + $ ./configure --disable-everything --enable-decoder=hevc \ + && make -j4 && sudo make install + +3. build baresip with H265 module: + + $ cd baresip + $ make EXTRA_MODULES=h265 + +4. add h265.so to $HOME/.baresip/config + module h265.so + +5. start baresip with the "vidloop" module, to test a local loop + from a suitable vidsrc and vidisp module: + + $ ./baresip -evv + + + +[END] diff --git a/modules/h265/TODO b/modules/h265/TODO new file mode 100644 index 0000000..de706c6 --- /dev/null +++ b/modules/h265/TODO @@ -0,0 +1,6 @@ +TODO: + +done - get encoder working +done - get decoder working + - add timestamp to vidsrc API + - add timestamp to vidcodec API diff --git a/modules/h265/decode.c b/modules/h265/decode.c new file mode 100644 index 0000000..f05aafc --- /dev/null +++ b/modules/h265/decode.c @@ -0,0 +1,289 @@ +/** + * @file h265/decode.c H.265 Decode + * + * Copyright (C) 2010 Creytiv.com + */ + +#include <re.h> +#include <rem.h> +#include <baresip.h> +#include <libavcodec/avcodec.h> +#include "h265.h" + + +enum { + FU_HDR_SIZE = 1 +}; + +enum { + DECODE_MAXSZ = 524288, +}; + + +struct fu { + unsigned s:1; + unsigned e:1; + unsigned type:5; +}; + +struct viddec_state { + AVCodecContext *ctx; + AVFrame *pict; + struct mbuf *mb; + size_t frag_start; + bool frag; + uint16_t frag_seq; +}; + + +static void destructor(void *arg) +{ + struct viddec_state *vds = arg; + + if (vds->ctx) { + avcodec_close(vds->ctx); + av_free(vds->ctx); + } + + if (vds->pict) + av_free(vds->pict); + + mem_deref(vds->mb); +} + + +int h265_decode_update(struct viddec_state **vdsp, const struct vidcodec *vc, + const char *fmtp) +{ + struct viddec_state *vds; + AVCodec *codec; + int err = 0; + (void)vc; + (void)fmtp; + + if (!vdsp) + return EINVAL; + + vds = *vdsp; + + if (vds) + return 0; + + codec = avcodec_find_decoder(AV_CODEC_ID_H265); + if (!codec) { + warning("h265: could not find H265 decoder\n"); + return ENOSYS; + } + + vds = mem_zalloc(sizeof(*vds), destructor); + if (!vds) + return ENOMEM; + + vds->mb = mbuf_alloc(1024); + if (!vds->mb) { + err = ENOMEM; + goto out; + } + + vds->pict = av_frame_alloc(); + if (!vds->pict) { + err = ENOMEM; + goto out; + } + + vds->ctx = avcodec_alloc_context3(codec); + if (!vds->ctx) { + err = ENOMEM; + goto out; + } + + if (avcodec_open2(vds->ctx, codec, NULL) < 0) { + err = ENOMEM; + goto out; + } + + out: + if (err) + mem_deref(vds); + else + *vdsp = vds; + + return err; +} + + +static inline int fu_decode(struct fu *fu, struct mbuf *mb) +{ + uint8_t v; + + if (mbuf_get_left(mb) < 1) + return EBADMSG; + + v = mbuf_read_u8(mb); + + fu->s = v>>7 & 0x1; + fu->e = v>>6 & 0x1; + fu->type = v>>0 & 0x3f; + + return 0; +} + + +static inline int16_t seq_diff(uint16_t x, uint16_t y) +{ + return (int16_t)(y - x); +} + + +static inline void fragment_rewind(struct viddec_state *vds) +{ + vds->mb->pos = vds->frag_start; + vds->mb->end = vds->frag_start; +} + + +int h265_decode(struct viddec_state *vds, struct vidframe *frame, + bool marker, uint16_t seq, struct mbuf *mb) +{ + static const uint8_t nal_seq[3] = {0, 0, 1}; + int err, ret, got_picture, i; + struct h265_nal hdr; + AVPacket avpkt; + + if (!vds || !frame || !mb) + return EINVAL; + + err = h265_nal_decode(&hdr, mbuf_buf(mb)); + if (err) + return err; + + mbuf_advance(mb, H265_HDR_SIZE); + +#if 1 + debug("h265: decode: %s type=%2d %s\n", + h265_is_keyframe(hdr.nal_unit_type) ? "<KEY>" : " ", + hdr.nal_unit_type, + h265_nalunit_name(hdr.nal_unit_type)); +#endif + + + if (vds->frag && hdr.nal_unit_type != H265_NAL_FU) { + debug("h265: lost fragments; discarding previous NAL\n"); + fragment_rewind(vds); + vds->frag = false; + } + + /* handle NAL types */ + if (0 <= hdr.nal_unit_type && hdr.nal_unit_type <= 40) { + + mb->pos -= H265_HDR_SIZE; + + err = mbuf_write_mem(vds->mb, nal_seq, 3); + err |= mbuf_write_mem(vds->mb, mbuf_buf(mb),mbuf_get_left(mb)); + if (err) + goto out; + } + else if (H265_NAL_FU == hdr.nal_unit_type) { + + struct fu fu; + + err = fu_decode(&fu, mb); + if (err) + return err; + + if (fu.s) { + if (vds->frag) { + debug("h265: lost fragments; ignoring NAL\n"); + fragment_rewind(vds); + } + + vds->frag_start = vds->mb->pos; + vds->frag = true; + + hdr.nal_unit_type = fu.type; + + err = mbuf_write_mem(vds->mb, nal_seq, 3); + err = h265_nal_encode_mbuf(vds->mb, &hdr); + if (err) + goto out; + } + else { + if (!vds->frag) { + debug("h265: ignoring fragment\n"); + return 0; + } + + if (seq_diff(vds->frag_seq, seq) != 1) { + debug("h265: lost fragments detected\n"); + fragment_rewind(vds); + vds->frag = false; + return 0; + } + } + + err = mbuf_write_mem(vds->mb, mbuf_buf(mb), mbuf_get_left(mb)); + if (err) + goto out; + + if (fu.e) + vds->frag = false; + + vds->frag_seq = seq; + } + else { + warning("h265: unknown NAL type %u\n", hdr.nal_unit_type); + return ENOSYS; + } + + if (!marker) { + + if (vds->mb->end > DECODE_MAXSZ) { + warning("h265: decode buffer size exceeded\n"); + err = ENOMEM; + goto out; + } + + return 0; + } + + if (vds->frag) { + err = EPROTO; + goto out; + } + + av_init_packet(&avpkt); + avpkt.data = vds->mb->buf; + avpkt.size = (int)vds->mb->end; + + ret = avcodec_decode_video2(vds->ctx, vds->pict, &got_picture, &avpkt); + if (ret < 0) { + debug("h265: decode error\n"); + err = EPROTO; + goto out; + } + + if (!got_picture) { + /* debug("h265: no picture\n"); */ + goto out; + } + + if (vds->pict->format != PIX_FMT_YUV420P) { + warning("h265: bad pixel format (%i)\n", vds->pict->format); + goto out; + } + + for (i=0; i<4; i++) { + frame->data[i] = vds->pict->data[i]; + frame->linesize[i] = vds->pict->linesize[i]; + } + + frame->size.w = vds->ctx->width; + frame->size.h = vds->ctx->height; + frame->fmt = VID_FMT_YUV420P; + + out: + mbuf_rewind(vds->mb); + vds->frag = false; + + return err; +} diff --git a/modules/h265/encode.c b/modules/h265/encode.c new file mode 100644 index 0000000..18685d6 --- /dev/null +++ b/modules/h265/encode.c @@ -0,0 +1,253 @@ +/** + * @file h265/encode.c H.265 Encode + * + * Copyright (C) 2010 Creytiv.com + */ + +#include <string.h> +#include <re.h> +#include <rem.h> +#include <baresip.h> +#include <x265.h> +#include "h265.h" + + +struct videnc_state { + struct vidsz size; + x265_param *param; + x265_encoder *x265; + int64_t pts; + unsigned fps; + unsigned bitrate; + unsigned pktsize; +}; + + +static void destructor(void *arg) +{ + struct videnc_state *st = arg; + + if (st->x265) + x265_encoder_close(st->x265); + if (st->param) + x265_param_free(st->param); +} + + +static int set_params(struct videnc_state *st, unsigned fps, unsigned bitrate) +{ + st->param = x265_param_alloc(); + if (!st->param) { + warning("h265: x265_param_alloc failed\n"); + return ENOMEM; + } + + x265_param_default(st->param); + + if (0 != x265_param_apply_profile(st->param, "main")) { + warning("h265: x265_param_apply_profile failed\n"); + return EINVAL; + } + + if (0 != x265_param_default_preset(st->param, + "ultrafast", "zerolatency")) { + + warning("h265: x265_param_default_preset error\n"); + return EINVAL; + } + + st->param->fpsNum = fps; + st->param->fpsDenom = 1; + + /* VPS, SPS and PPS headers should be output with each keyframe */ + st->param->bRepeatHeaders = 1; + + /* Rate Control */ + st->param->rc.rateControlMode = X265_RC_CRF; + st->param->rc.bitrate = bitrate / 1000; + st->param->rc.vbvMaxBitrate = bitrate / 1000; + st->param->rc.vbvBufferSize = 2 * bitrate / fps; + + return 0; +} + + +int h265_encode_update(struct videnc_state **vesp, const struct vidcodec *vc, + struct videnc_param *prm, const char *fmtp) +{ + struct videnc_state *ves; + int err = 0; + (void)fmtp; + + if (!vesp || !vc || !prm || prm->pktsize < 3) + return EINVAL; + + ves = *vesp; + + if (!ves) { + + ves = mem_zalloc(sizeof(*ves), destructor); + if (!ves) + return ENOMEM; + + *vesp = ves; + } + else { + if (ves->x265 && (ves->bitrate != prm->bitrate || + ves->pktsize != prm->pktsize || + ves->fps != prm->fps)) { + + x265_encoder_close(ves->x265); + ves->x265 = NULL; + } + } + + ves->bitrate = prm->bitrate; + ves->pktsize = prm->pktsize; + ves->fps = prm->fps; + + err = set_params(ves, prm->fps, prm->bitrate); + if (err) + return err; + + return 0; +} + + +static int open_encoder(struct videnc_state *st, const struct vidsz *size) +{ + if (st->x265) { + debug("h265: re-opening encoder\n"); + x265_encoder_close(st->x265); + } + + st->param->sourceWidth = size->w; + st->param->sourceHeight = size->h; + + st->x265 = x265_encoder_open(st->param); + if (!st->x265) { + warning("h265: x265_encoder_open failed\n"); + return ENOMEM; + } + + return 0; +} + + +static inline int packetize(bool marker, const uint8_t *buf, size_t len, + size_t maxlen, videnc_packet_h *pkth, void *arg) +{ + int err = 0; + + if (len <= maxlen) { + err = pkth(marker, NULL, 0, buf, len, arg); + } + else { + struct h265_nal nal; + uint8_t fu_hdr[3]; + const size_t flen = maxlen - sizeof(fu_hdr); + + err = h265_nal_decode(&nal, buf); + + h265_nal_encode(fu_hdr, H265_NAL_FU, + nal.nuh_temporal_id_plus1); + + fu_hdr[2] = 1<<7 | nal.nal_unit_type; + + buf+=2; + len-=2; + + while (len > flen) { + err |= pkth(false, fu_hdr, 3, buf, flen, arg); + + buf += flen; + len -= flen; + fu_hdr[2] &= ~(1 << 7); /* clear Start bit */ + } + + fu_hdr[2] |= 1<<6; /* set END bit */ + + err |= pkth(marker, fu_hdr, 3, buf, len, arg); + } + + return err; +} + + +int h265_encode(struct videnc_state *st, bool update, + const struct vidframe *frame, + videnc_packet_h *pkth, void *arg) +{ + x265_picture *pic_in = NULL, pic_out; + x265_nal *nalv; + uint32_t i, nalc = 0; + int n, err = 0; + + if (!st || !frame || !pkth || frame->fmt != VID_FMT_YUV420P) + return EINVAL; + + if (!st->x265 || !vidsz_cmp(&st->size, &frame->size)) { + + err = open_encoder(st, &frame->size); + if (err) + return err; + + st->size = frame->size; + } + + if (update) { + debug("h265: encode: picture update was requested\n"); + } + + pic_in = x265_picture_alloc(); + if (!pic_in) { + warning("h265: x265_picture_alloc failed\n"); + return ENOMEM; + } + + x265_picture_init(st->param, pic_in); + + pic_in->sliceType = update ? X265_TYPE_IDR : X265_TYPE_AUTO; + pic_in->pts = ++st->pts; /* XXX: add PTS to API */ + pic_in->colorSpace = X265_CSP_I420; + + for (i=0; i<3; i++) { + pic_in->planes[i] = frame->data[i]; + pic_in->stride[i] = frame->linesize[i]; + } + + /* NOTE: important to get the PTS of the "out" picture */ + n = x265_encoder_encode(st->x265, &nalv, &nalc, pic_in, &pic_out); + if (n <= 0) + goto out; + + for (i=0; i<nalc; i++) { + + x265_nal *nal = &nalv[i]; + uint8_t *p = nal->payload; + size_t len = nal->sizeBytes; + bool marker; + +#if 1 + debug("h265: encode: %s type=%2d %s\n", + h265_is_keyframe(nal->type) ? "<KEY>" : " ", + nal->type, h265_nalunit_name(nal->type)); +#endif + + h265_skip_startcode(&p, &len); + + /* XXX: use pic_out.pts */ + + marker = (i+1)==nalc; /* last NAL */ + + err = packetize(marker, p, len, st->pktsize, pkth, arg); + if (err) + goto out; + } + + out: + if (pic_in) + x265_picture_free(pic_in); + + return err; +} diff --git a/modules/h265/fmt.c b/modules/h265/fmt.c new file mode 100644 index 0000000..a3acc0b --- /dev/null +++ b/modules/h265/fmt.c @@ -0,0 +1,159 @@ + +#include <string.h> +#include <re.h> +#include <baresip.h> +#include "h265.h" + + +/* +1.1.4 NAL Unit Header + + HEVC maintains the NAL unit concept of H.264 with modifications. + HEVC uses a two-byte NAL unit header, as shown in Figure 1. The + payload of a NAL unit refers to the NAL unit excluding the NAL unit + header. + + +---------------+---------------+ + |0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |F| Type | LayerId | TID | + +-------------+-----------------+ + + Figure 1 The structure of HEVC NAL unit header +*/ + + +void h265_nal_encode(uint8_t buf[2], unsigned nal_unit_type, + unsigned nuh_temporal_id_plus1) +{ + if (!buf) + return; + + buf[0] = (nal_unit_type & 0x3f) << 1; + buf[1] = nuh_temporal_id_plus1 & 0x07; +} + + +int h265_nal_encode_mbuf(struct mbuf *mb, const struct h265_nal *nal) +{ + uint8_t buf[2]; + + h265_nal_encode(buf, nal->nal_unit_type, nal->nuh_temporal_id_plus1); + + return mbuf_write_mem(mb, buf, sizeof(buf)); +} + + +int h265_nal_decode(struct h265_nal *nal, const uint8_t *p) +{ + bool forbidden_zero_bit; + unsigned nuh_layer_id; + + if (!nal || !p) + return EINVAL; + + forbidden_zero_bit = p[0] >> 7; + nal->nal_unit_type = (p[0] >> 1) & 0x3f; + nuh_layer_id = (p[0]&1)<<5 | p[1] >> 3; + nal->nuh_temporal_id_plus1 = p[1] & 0x07; + + if (forbidden_zero_bit) { + re_fprintf(stderr, "?!?!?!?! FORBIDDEN !!! ?!?!?!*\n"); + return EBADMSG; + } + if (nuh_layer_id != 0) { + re_fprintf(stderr, "h265_nal_decode: LayerId MUST be zero\n"); + return EBADMSG; + } + + return 0; +} + + +void h265_nal_print(const struct h265_nal *nal) +{ + re_printf("type=%u(%s), TID=%u\n", + nal->nal_unit_type, + h265_nalunit_name(nal->nal_unit_type), + nal->nuh_temporal_id_plus1); +} + + +static const uint8_t sc3[3] = {0, 0, 1}; +static const uint8_t sc4[4] = {0, 0, 0, 1}; + + +void h265_skip_startcode(uint8_t **p, size_t *n) +{ + if (*n < 4) + return; + + if (0 == memcmp(*p, sc4, 4)) { + (*p) += 4; + *n -= 4; + } + else if (0 == memcmp(*p, sc3, 3)) { + (*p) += 3; + *n -= 3; + } +} + + +bool h265_have_startcode(const uint8_t *p, size_t len) +{ + if (len >= 4 && 0 == memcmp(p, sc4, 4)) return true; + if (len >= 3 && 0 == memcmp(p, sc3, 3)) return true; + + return false; +} + + +bool h265_is_keyframe(enum h265_naltype type) +{ + /* between 16 and 21 (inclusive) */ + switch (type) { + + case H265_NAL_BLA_W_LP: + case H265_NAL_BLA_W_RADL: + case H265_NAL_BLA_N_LP: + case H265_NAL_IDR_W_RADL: + case H265_NAL_IDR_N_LP: + case H265_NAL_CRA_NUT: + return true; + default: + return false; + } +} + + +const char *h265_nalunit_name(enum h265_naltype type) +{ + switch (type) { + + /* VCL class */ + case H265_NAL_TRAIL_N: return "TRAIL_N"; + case H265_NAL_TRAIL_R: return "TRAIL_R"; + + case H265_NAL_RASL_N: return "RASL_N"; + case H265_NAL_RASL_R: return "RASL_R"; + + case H265_NAL_BLA_W_LP: return "BLA_W_LP"; + case H265_NAL_BLA_W_RADL: return "BLA_W_RADL"; + case H265_NAL_BLA_N_LP: return "BLA_N_LP"; + case H265_NAL_IDR_W_RADL: return "IDR_W_RADL"; + case H265_NAL_IDR_N_LP: return "IDR_N_LP"; + case H265_NAL_CRA_NUT: return "CRA_NUT"; + + /* non-VCL class */ + case H265_NAL_VPS_NUT: return "VPS_NUT"; + case H265_NAL_SPS_NUT: return "SPS_NUT"; + case H265_NAL_PPS_NUT: return "PPS_NUT"; + case H265_NAL_PREFIX_SEI_NUT: return "PREFIX_SEI_NUT"; + case H265_NAL_SUFFIX_SEI_NUT: return "SUFFIX_SEI_NUT"; + + /* draft-ietf-payload-rtp-h265 */ + case H265_NAL_FU: return "H265_NAL_FU"; + } + + return "???"; +} diff --git a/modules/h265/h265.c b/modules/h265/h265.c new file mode 100644 index 0000000..04ad679 --- /dev/null +++ b/modules/h265/h265.c @@ -0,0 +1,68 @@ +/** + * @file h265.c H.265 Video Codec + * + * Copyright (C) 2010 Creytiv.com + */ + +#include <re.h> +#include <baresip.h> +#include <libavcodec/avcodec.h> +#include <x265.h> +#include "h265.h" + + +/** + * @defgroup h265 h265 + * + * The H.265 video codec (aka HEVC) + * + * This is an experimental module adding support for H.265 video codec. + * The encoder is using x265 and the decoder is using libavcodec. + * + * + * References: + * + * draft-ietf-payload-rtp-h265-07 + * http://x265.org/ + * https://www.ffmpeg.org/ + */ + + +static struct vidcodec h265 = { + .name = "H265", + .encupdh = h265_encode_update, + .ench = h265_encode, + .decupdh = h265_decode_update, + .dech = h265_decode, +}; + + +static int module_init(void) +{ + info("h265: using x265 %s %s\n", + x265_version_str, x265_build_info_str); + + avcodec_register_all(); + + vidcodec_register(&h265); + + return 0; +} + + +static int module_close(void) +{ + vidcodec_unregister(&h265); + + x265_cleanup(); + + return 0; +} + + +EXPORT_SYM const struct mod_export DECL_EXPORTS(h265) = { + "h265", + "vidcodec", + module_init, + module_close, +}; diff --git a/modules/h265/h265.h b/modules/h265/h265.h new file mode 100644 index 0000000..f537ea9 --- /dev/null +++ b/modules/h265/h265.h @@ -0,0 +1,69 @@ +/** + * @file h265.h H.265 Video Codec -- internal API + * + * Copyright (C) 2010 Creytiv.com + */ + + +/* + * H.265 format + */ +enum { + H265_HDR_SIZE = 2 +}; + +enum h265_naltype { + /* VCL class */ + H265_NAL_TRAIL_N = 0, + H265_NAL_TRAIL_R = 1, + + H265_NAL_RASL_N = 8, + H265_NAL_RASL_R = 9, + + H265_NAL_BLA_W_LP = 16, + H265_NAL_BLA_W_RADL = 17, + H265_NAL_BLA_N_LP = 18, + H265_NAL_IDR_W_RADL = 19, + H265_NAL_IDR_N_LP = 20, + H265_NAL_CRA_NUT = 21, + + /* non-VCL class */ + H265_NAL_VPS_NUT = 32, + H265_NAL_SPS_NUT = 33, + H265_NAL_PPS_NUT = 34, + H265_NAL_PREFIX_SEI_NUT = 39, + H265_NAL_SUFFIX_SEI_NUT = 40, + + /* draft-ietf-payload-rtp-h265 */ + H265_NAL_FU = 49, +}; + +struct h265_nal { + unsigned nal_unit_type:6; /* NAL unit type (0-40) */ + unsigned nuh_temporal_id_plus1:3; /* temporal identifier plus 1 */ +}; + +void h265_nal_encode(uint8_t buf[2], unsigned nal_unit_type, + unsigned nuh_temporal_id_plus1); +int h265_nal_encode_mbuf(struct mbuf *mb, const struct h265_nal *nal); +int h265_nal_decode(struct h265_nal *nal, const uint8_t *p); +void h265_nal_print(const struct h265_nal *nal); + +bool h265_have_startcode(const uint8_t *p, size_t len); +void h265_skip_startcode(uint8_t **p, size_t *n); +bool h265_is_keyframe(enum h265_naltype type); +const char *h265_nalunit_name(enum h265_naltype type); + + +/* encoder */ +int h265_encode_update(struct videnc_state **vesp, const struct vidcodec *vc, + struct videnc_param *prm, const char *fmtp); +int h265_encode(struct videnc_state *ves, bool update, + const struct vidframe *frame, + videnc_packet_h *pkth, void *arg); + +/* decoder */ +int h265_decode_update(struct viddec_state **vdsp, const struct vidcodec *vc, + const char *fmtp); +int h265_decode(struct viddec_state *vds, struct vidframe *frame, + bool marker, uint16_t seq, struct mbuf *mb); diff --git a/modules/h265/module.mk b/modules/h265/module.mk new file mode 100644 index 0000000..1600a61 --- /dev/null +++ b/modules/h265/module.mk @@ -0,0 +1,12 @@ +# +# module.mk +# +# Copyright (C) 2010 Creytiv.com +# + +MOD := h265 +$(MOD)_SRCS += h265.c encode.c decode.c fmt.c +$(MOD)_LFLAGS += -lavcodec -lavutil -lx265 +CFLAGS += + +include mk/mod.mk diff --git a/modules/h265/notes b/modules/h265/notes new file mode 100644 index 0000000..0f01c5a --- /dev/null +++ b/modules/h265/notes @@ -0,0 +1,75 @@ +notes: +----- + + +x265 [info]: HEVC encoder version 1.4-253-g920d714 +x265 [info]: build info [Linux][GCC 4.9.1][64 bit] 8bpp +x265 [info]: using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX +x265 [info]: Main profile, Level-2 (Main tier) +x265 [info]: WPP streams / frame threads / pool : 8 / 2 / 4 +x265 [info]: CTU size / RQT depth inter / intra : 32 / 1 / 1 +x265 [info]: ME / range / subpel / merge : dia / 25 / 0 / 2 +x265 [info]: Keyframe min / max / scenecut : 25 / 250 / 0 +x265 [info]: Lookahead / bframes / badapt : 10 / 4 / 0 +x265 [info]: b-pyramid / weightp / weightb / refs: 1 / 0 / 0 / 1 +x265 [info]: Rate Control / AQ-Strength / CUTree : CRF-28.0 / 0.0 / 0 +x265 [info]: VBV/HRD buffer / max-rate / init : 40960 / 512 / 0.900 +x265 [info]: tools: rd=2 early-skip fast-intra tmvp + + +x265 [info]: frame I: 1, Avg QP:25.40 kb/s: 639.60 +x265 [info]: frame P: 3, Avg QP:30.29 kb/s: 256.93 +x265 [info]: frame B: 12, Avg QP:32.92 kb/s: 58.68 +x265 [info]: global : 16, Avg QP:31.96 kb/s: 132.16 +x265 [info]: consecutive B-frames: 20.0% 0.0% 0.0% 0.0% 80.0% + + + + +h265: decode: type=32 VPS_NUT +h265: decode: type=33 SPS_NUT +h265: decode: type=34 PPS_NUT +h265: decode: type=39 PREFIX_SEI_NUT +h265: decode: type=39 PREFIX_SEI_NUT +h265: decode: type=49 H265_NAL_FU +h265: decode: type=49 H265_NAL_FU +h265: decode: type=49 H265_NAL_FU +h265: decode: type=49 H265_NAL_FU +h265: decode: type=49 H265_NAL_FU +h265: decode: type=49 H265_NAL_FU +h265: decode: type=49 H265_NAL_FU +h265: decode: type=49 H265_NAL_FU +h265: decode: type=49 H265_NAL_FU +h265: decode: type=49 H265_NAL_FU +h265: decode: type=49 H265_NAL_FU + + + + +Test-call between 2 peers (A) and (B): + + +(A): + +video Transmit: Receive: +packets: 435 2001 +avg. bitrate: 56.0 416.0 (kbit/s) +errors: 0 0 +pkt.report: 417 1939 +lost: 0 0 +jitter: 23.3 0.4 (ms) + + +(B): + +video Transmit: Receive: +packets: 2012 435 +avg. bitrate: 416.0 56.0 (kbit/s) +errors: 0 0 +pkt.report: 1939 417 +lost: 0 0 +jitter: 0.4 23.3 (ms) + + + +[END] |