Skip to content

Commit

Permalink
h264: add STAP-A (#584)
Browse files Browse the repository at this point in the history
  • Loading branch information
alfredh authored Nov 1, 2022
1 parent 2227d18 commit 54dd27f
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .github/workflows/mingw.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,5 +73,5 @@ jobs:
secret: ${{ secrets.GITHUB_TOKEN }}

- name: "run retest.exe"
run: mv retest-exe/retest.exe retest/ && cd retest && ./retest.exe
run: mv retest-exe/retest.exe retest/ && cd retest && ./retest.exe -v
shell: bash
5 changes: 5 additions & 0 deletions include/re_h264.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ struct h264_nal_header {

int h264_nal_header_encode(struct mbuf *mb, const struct h264_nal_header *hdr);
int h264_nal_header_decode(struct h264_nal_header *hdr, struct mbuf *mb);
void h264_nal_header_decode_buf(struct h264_nal_header *hdr,
const uint8_t *buf);
const char *h264_nal_unit_name(enum h264_nalu nal_type);


Expand Down Expand Up @@ -99,3 +101,6 @@ int h264_nal_send(bool first, bool last,
const uint8_t *buf, size_t size, size_t maxsz,
h264_packet_h *pkth, void *arg);
bool h264_is_keyframe(int type);
int h264_stap_encode(struct mbuf *mb, const uint8_t *frame,
size_t frame_sz);
int h264_stap_decode_annexb(struct mbuf *mb_frame, struct mbuf *mb_pkt);
139 changes: 139 additions & 0 deletions src/h264/nal.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,40 @@

#include <re_types.h>
#include <re_mbuf.h>
#include <re_net.h>
#include <re_fmt.h>
#include <re_h264.h>


enum {
H264_HEADER_LENGTH = 1,
H264_STAP_MIN_LENGTH = sizeof(uint16_t)
};


static int nal_header_encode_val(struct mbuf *mb,
uint8_t nri, enum h264_nalu type)
{
uint8_t v = nri<<5 | type;

return mbuf_write_u8(mb, v);
}


void h264_nal_header_decode_buf(struct h264_nal_header *hdr,
const uint8_t *buf)
{
if (!hdr || !buf)
return;

uint8_t v = buf[0];

hdr->f = v>>7 & 0x1;
hdr->nri = v>>5 & 0x3;
hdr->type = v & 0x1f;
}


/**
* Encode H.264 NAL header
*
Expand Down Expand Up @@ -257,3 +288,111 @@ bool h264_is_keyframe(int type)
{
return type == H264_NALU_IDR_SLICE;
}


/**
* Encode STAP-A header and payload
*
* @param mb Target mbuffer for STAP-A NAL unit
* @param frame Input frame in Annex-B format
* @param frame_sz Number of bytes in input frame
*
* @return 0 if success, otherwise errorcode
*
* NOTE: The value of NRI MUST be the maximum of all the
* NAL units carried in the aggregation packet.
*
* NOTE: The input must be in Annex-B format (3-4 byte Startcode)
*/
int h264_stap_encode(struct mbuf *mb, const uint8_t *frame,
size_t frame_sz)
{
uint8_t nri_max = 0;

if (!mb || !frame || !frame_sz)
return EINVAL;

size_t start = mb->pos;
const uint8_t *end = frame + frame_sz;

int err = nal_header_encode_val(mb, 0, H264_NALU_STAP_A);
if (err)
return err;

const uint8_t *r = h264_find_startcode(frame, end);

while (r < end) {

struct h264_nal_header hdr;

while (!*(r++))
;

const uint8_t *r1 = h264_find_startcode(r, end);
size_t len = r1 - r;

if (len > UINT16_MAX)
return ERANGE;

err = mbuf_write_u16(mb, htons((uint16_t)len));
err |= mbuf_write_mem(mb, r, len);
if (err)
return err;

h264_nal_header_decode_buf(&hdr, r);
nri_max = max(hdr.nri, nri_max);

r = r1;
}

/* update NAL header */
mb->buf[start] |= nri_max<<5;

return 0;
}


/**
* Decode STAP-A payload and convert to Annex-B NAL units
*
* @param mb_frame Target mbuffer for frame with multiple NAL units
* @param mb_pkt Input packet with STAP-A payload
*
* @return 0 if success, otherwise errorcode
*
* NOTE: The NAL header must be decoded outside
*/
int h264_stap_decode_annexb(struct mbuf *mb_frame, struct mbuf *mb_pkt)
{
if (!mb_frame || !mb_pkt)
return EINVAL;

while (mbuf_get_left(mb_pkt) >= H264_STAP_MIN_LENGTH) {

uint16_t len = ntohs(mbuf_read_u16(mb_pkt));

if (len < H264_HEADER_LENGTH || len > mbuf_get_left(mb_pkt))
return EBADMSG;

#if 0
struct h264_nal_header hdr;

h264_nal_header_decode_buf(&hdr, mbuf_buf(mb_pkt));

re_printf("STAP-A decode: len=%u nri=%u type=%u(%s)\n",
len,
hdr.nri, hdr.type, h264_nal_unit_name(hdr.type));
#endif

static const uint8_t sc3[] = {0, 0, 1};

int err = mbuf_write_mem(mb_frame, sc3, sizeof(sc3));
err |= mbuf_write_mem(mb_frame, mbuf_buf(mb_pkt), len);
if (err)
return err;

mbuf_advance(mb_pkt, len);
}

return 0;
}

0 comments on commit 54dd27f

Please sign in to comment.