Skip to content

Commit

Permalink
h264: fix for Annex-B bitstreams with 4-byte startcode
Browse files Browse the repository at this point in the history
  • Loading branch information
alfredh committed Mar 26, 2024
1 parent c8ec56b commit c232cc6
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 12 deletions.
15 changes: 14 additions & 1 deletion src/h264/nal.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,8 @@ int h264_fu_hdr_decode(struct h264_fu *fu, struct mbuf *mb)
*
* @note: copied from ffmpeg source
*/
const uint8_t *h264_find_startcode(const uint8_t *p, const uint8_t *end)
static const uint8_t *h264_find_startcode_int(const uint8_t *p,
const uint8_t *end)
{
const uint8_t *a = p + 4 - ((size_t)p & 3);

Expand Down Expand Up @@ -191,6 +192,18 @@ const uint8_t *h264_find_startcode(const uint8_t *p, const uint8_t *end)
}


const uint8_t *h264_find_startcode(const uint8_t *p, const uint8_t *end)
{
const uint8_t *out = h264_find_startcode_int(p, end);

/* check for 4-byte startcode */
if (p<out && out<end && !out[-1])
--out;

return out;
}


static int rtp_send_data(const uint8_t *hdr, size_t hdr_sz,
const uint8_t *buf, size_t sz,
bool eof, uint64_t rtp_ts,
Expand Down
57 changes: 46 additions & 11 deletions test/h264.c
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,7 @@ struct state {
struct mbuf *mb;
size_t frag_start;
bool frag;
bool long_startcode;

/* test */
uint8_t buf[256];
Expand All @@ -506,8 +507,11 @@ static void fragment_rewind(struct state *vds)
static int depack_handle_h264(struct state *st, bool marker,
struct mbuf *src)
{
static const uint8_t nal_seq[3] = {0, 0, 1};
static const uint8_t nal_seq3[3] = {0, 0, 1};
static const uint8_t nal_seq4[4] = {0, 0, 0, 1};
struct h264_nal_header h264_hdr;
size_t nal_seq_len = st->long_startcode ?
sizeof(nal_seq4) : sizeof(nal_seq3);
int err;

err = h264_nal_header_decode(&h264_hdr, src);
Expand All @@ -533,7 +537,9 @@ static int depack_handle_h264(struct state *st, bool marker,
--src->pos;

/* prepend H.264 NAL start sequence */
err = mbuf_write_mem(st->mb, nal_seq, sizeof(nal_seq));
err = mbuf_write_mem(st->mb,
st->long_startcode ? nal_seq4 : nal_seq3,
nal_seq_len);

err |= mbuf_write_mem(st->mb, mbuf_buf(src),
mbuf_get_left(src));
Expand Down Expand Up @@ -561,7 +567,9 @@ static int depack_handle_h264(struct state *st, bool marker,
st->frag = true;

/* prepend H.264 NAL start sequence */
mbuf_write_mem(st->mb, nal_seq, sizeof(nal_seq));
mbuf_write_mem(st->mb,
st->long_startcode ? nal_seq4 : nal_seq3,
nal_seq_len);

/* encode NAL header back to buffer */
err = h264_nal_header_encode(st->mb, &h264_hdr);
Expand Down Expand Up @@ -601,7 +609,8 @@ static int depack_handle_h264(struct state *st, bool marker,
--src->pos;

err = mbuf_write_mem(st->mb,
nal_seq, sizeof(nal_seq));
st->long_startcode ? nal_seq4 : nal_seq3,
nal_seq_len);
err |= mbuf_write_mem(st->mb, mbuf_buf(src), len);
if (err)
goto out;
Expand Down Expand Up @@ -661,21 +670,18 @@ static int packet_handler(bool marker, uint64_t rtp_ts,
}


/* bitstream in Annex-B format (with startcode 00 00 01) */
static const char *bitstream = "000001650010e2238712983719283719823798";


int test_h264_packet(void)
static int test_h264_packet_base(const char *bs, bool long_startcode)
{
struct state state;
const size_t MAX_PKTSIZE = 8;
int err;

memset(&state, 0, sizeof(state));

state.len = strlen(bitstream)/2;
state.long_startcode = long_startcode;
state.len = strlen(bs)/2;

err = str_hex(state.buf, state.len, bitstream);
err = str_hex(state.buf, state.len, bs);
if (err)
return err;

Expand All @@ -696,3 +702,32 @@ int test_h264_packet(void)

return err;
}


/* bitstream in Annex-B format (with startcode 00 00 01) */
static const char *bitstream =
"0000016701020304"
"0000016801020304"
"000001650010e2238712983719283719823798";


/* bitstream in Annex-B format (with startcode 00 00 00 01) */
static const char *bitstream_long =
"000000016701020304"
"000000016801020304"
"00000001650010e2238712983719283719823798";


int test_h264_packet(void)
{
int err;

err = test_h264_packet_base(bitstream, false);
ASSERT_EQ(0, err);

err = test_h264_packet_base(bitstream_long, true);
ASSERT_EQ(0, err);

out:
return err;
}

0 comments on commit c232cc6

Please sign in to comment.