From d9834e8d74f944754359c0e4592f695ed2ed5c44 Mon Sep 17 00:00:00 2001 From: "Alfred E. Heggestad" Date: Fri, 17 Jun 2022 12:43:41 +0200 Subject: [PATCH] av1 work (#402) * av1 work * fix ci errors * bump coverage --- include/re_av1.h | 18 +++++ src/av1/obu.c | 67 ++++++++++++++++- src/av1/pkt.c | 189 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 272 insertions(+), 2 deletions(-) diff --git a/include/re_av1.h b/include/re_av1.h index 4f68e00ce..b96f2f369 100644 --- a/include/re_av1.h +++ b/include/re_av1.h @@ -5,6 +5,19 @@ */ +enum obu_type { + AV1_OBU_SEQUENCE_HEADER = 1, + AV1_OBU_TEMPORAL_DELIMITER = 2, + AV1_OBU_FRAME_HEADER = 3, + AV1_OBU_TILE_GROUP = 4, + AV1_OBU_METADATA = 5, + AV1_OBU_FRAME = 6, + AV1_OBU_REDUNDANT_FRAME_HEADER = 7, + AV1_OBU_TILE_LIST = 8, + AV1_OBU_PADDING = 15, +}; + + /* OBU (Open Bitstream Units) */ /** @@ -29,6 +42,8 @@ int av1_obu_encode(struct mbuf *mb, uint8_t type, bool has_size, int av1_obu_decode(struct av1_obu_hdr *hdr, struct mbuf *mb); int av1_obu_print(struct re_printf *pf, const struct av1_obu_hdr *hdr); unsigned av1_obu_count(const uint8_t *buf, size_t size); +unsigned av1_obu_count_rtp(const uint8_t *buf, size_t size); +const char *av1_obu_name(enum obu_type type); /* @@ -43,6 +58,9 @@ typedef int (av1_packet_h)(bool marker, uint64_t rtp_ts, int av1_packetize(bool *newp, bool marker, uint64_t rtp_ts, const uint8_t *buf, size_t len, size_t maxlen, av1_packet_h *pkth, void *arg); +int av1_packetize_high(bool *newp, bool marker, uint64_t rtp_ts, + const uint8_t *buf, size_t len, size_t maxlen, + av1_packet_h *pkth, void *arg); enum { diff --git a/src/av1/obu.c b/src/av1/obu.c index 839949b8b..0a64bb310 100644 --- a/src/av1/obu.c +++ b/src/av1/obu.c @@ -193,8 +193,9 @@ int av1_obu_print(struct re_printf *pf, const struct av1_obu_hdr *hdr) if (!hdr) return 0; - return re_hprintf(pf, "type=%u x=%d s=%d size=%zu", - hdr->type, hdr->x, hdr->s, hdr->size); + return re_hprintf(pf, "type=%u,%s x=%d s=%d size=%zu", + hdr->type, av1_obu_name(hdr->type), + hdr->x, hdr->s, hdr->size); } @@ -226,3 +227,65 @@ unsigned av1_obu_count(const uint8_t *buf, size_t size) return count; } + + +unsigned av1_obu_count_rtp(const uint8_t *buf, size_t size) +{ + struct mbuf wrap = { + .buf = (uint8_t *)buf, + .size = size, + .pos = 0, + .end = size + }; + unsigned count = 0; + + while (mbuf_get_left(&wrap) > 1) { + + struct av1_obu_hdr hdr; + + int err = av1_obu_decode(&hdr, &wrap); + if (err) { + DEBUG_WARNING("count: could not decode OBU" + " [%zu bytes]: %m\n", size, err); + return 0; + } + + switch (hdr.type) { + + case AV1_OBU_SEQUENCE_HEADER: + case AV1_OBU_FRAME_HEADER: + case AV1_OBU_METADATA: + case AV1_OBU_FRAME: + case AV1_OBU_REDUNDANT_FRAME_HEADER: + case AV1_OBU_TILE_LIST: + ++count; + break; + + default: + break; + } + + mbuf_advance(&wrap, hdr.size); + } + + return count; +} + + +const char *av1_obu_name(enum obu_type type) +{ + switch (type) { + + case AV1_OBU_SEQUENCE_HEADER: return "OBU_SEQUENCE_HEADER"; + case AV1_OBU_TEMPORAL_DELIMITER: return "OBU_TEMPORAL_DELIMITER"; + case AV1_OBU_FRAME_HEADER: return "OBU_FRAME_HEADER"; + case AV1_OBU_REDUNDANT_FRAME_HEADER: + return "OBU_REDUNDANT_FRAME_HEADER"; + case AV1_OBU_FRAME: return "OBU_FRAME"; + case AV1_OBU_TILE_GROUP: return "OBU_TILE_GROUP"; + case AV1_OBU_METADATA: return "OBU_METADATA"; + case AV1_OBU_TILE_LIST: return "OBU_TILE_LIST"; + case AV1_OBU_PADDING: return "OBU_PADDING"; + default: return "???"; + } +} diff --git a/src/av1/pkt.c b/src/av1/pkt.c index 7952aadb2..5076a9429 100644 --- a/src/av1/pkt.c +++ b/src/av1/pkt.c @@ -6,10 +6,17 @@ #include #include +#include +#include #include #include +#define DEBUG_MODULE "av1" +#define DEBUG_LEVEL 5 +#include + + static void hdr_encode(uint8_t hdr[AV1_AGGR_HDR_SIZE], bool z, bool y, uint8_t w, bool n) { @@ -64,3 +71,185 @@ int av1_packetize(bool *newp, bool marker, uint64_t rtp_ts, return err; } + + +static struct mbuf *encode_obu(uint8_t type, const uint8_t *p, size_t len) +{ + struct mbuf *mb = mbuf_alloc(len); + const bool has_size = false; /* NOTE */ + int err; + + if (!mb) + return NULL; + + err = av1_obu_encode(mb, type, has_size, len, p); + if (err) { + mem_deref(mb); + return NULL; + } + + mb->pos = 0; + + return mb; +} + + +static int copy_obus(struct mbuf *mb_pkt, const uint8_t *buf, size_t size, + bool w0) +{ + struct mbuf wrap = { + .buf = (uint8_t *)buf, + .size = size, + .pos = 0, + .end = size + }; + struct mbuf *mb_obu = NULL; + int err = 0; + + while (mbuf_get_left(&wrap) >= 2) { + + struct av1_obu_hdr hdr; + bool last; + + err = av1_obu_decode(&hdr, &wrap); + if (err) { + DEBUG_WARNING("av1: encode: hdr dec error (%m)\n", + err); + return err; + } + + last = (hdr.size == mbuf_get_left(&wrap)); + + switch (hdr.type) { + + case AV1_OBU_SEQUENCE_HEADER: + case AV1_OBU_FRAME_HEADER: + case AV1_OBU_METADATA: + case AV1_OBU_FRAME: + case AV1_OBU_REDUNDANT_FRAME_HEADER: + case AV1_OBU_TILE_LIST: + mb_obu = encode_obu(hdr.type, mbuf_buf(&wrap), + hdr.size); + if (!mb_obu) { + err = ENOMEM; + goto out; + } + + if (last) { + if (w0) + err = av1_leb128_encode(mb_pkt, + mb_obu->end); + } + else { + err = av1_leb128_encode(mb_pkt, mb_obu->end); + } + + if (err) + goto out; + + err = mbuf_write_mem(mb_pkt, mb_obu->buf, mb_obu->end); + if (err) + goto out; + + break; + + case AV1_OBU_TEMPORAL_DELIMITER: + case AV1_OBU_TILE_GROUP: + case AV1_OBU_PADDING: + /* skip */ + break; + + default: + DEBUG_WARNING("av1: unknown obu type %u\n", hdr.type); + break; + } + + mbuf_advance(&wrap, hdr.size); + + mb_obu = mem_deref(mb_obu); + } + + out: + mem_deref(mb_obu); + return err; +} + + +static int av1_packetize_internal(bool *newp, bool marker, uint64_t rtp_ts, + const uint8_t *buf, size_t len, + size_t maxlen, uint8_t w, + av1_packet_h *pkth, void *arg) +{ + uint8_t hdr[AV1_AGGR_HDR_SIZE]; + bool cont = false; + int err = 0; + + + if (w > 3) { + DEBUG_WARNING("w too large\n"); + return EPROTO; + } + + maxlen -= sizeof(hdr); + + while (len > maxlen) { + + hdr_encode(hdr, cont, true, w, *newp); + *newp = false; + + err |= pkth(false, rtp_ts, hdr, sizeof(hdr), buf, maxlen, arg); + + buf += maxlen; + len -= maxlen; + cont = true; + } + + hdr_encode(hdr, cont, false, w, *newp); + *newp = false; + + err |= pkth(marker, rtp_ts, hdr, sizeof(hdr), buf, len, arg); + + return err; +} + + +int av1_packetize_high(bool *newp, bool marker, uint64_t rtp_ts, + const uint8_t *buf, size_t len, size_t maxlen, + av1_packet_h *pkth, void *arg) +{ + struct mbuf *mb_pkt; + unsigned count = 0; + uint8_t w; + int err; + + if (!newp || !buf || !len || maxlen < (AV1_AGGR_HDR_SIZE + 1) || !pkth) + return EINVAL; + + mb_pkt = mbuf_alloc(len); + if (!mb_pkt) + return ENOMEM; + + count = av1_obu_count_rtp(buf, len); + + if (count > 3) { + w = 0; + } + else { + w = count; + } + + err = copy_obus(mb_pkt, buf, len, count > 3); + if (err) + goto out; + + err = av1_packetize_internal(newp, marker, rtp_ts, + mb_pkt->buf, mb_pkt->end, maxlen, + w, + pkth, arg); + if (err) + goto out; + + out: + mem_deref(mb_pkt); + return err; +}