Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rtmp hevc support - style fixes #203

Merged
merged 2 commits into from
May 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 68 additions & 72 deletions nginx-kmp-rtmp-module/src/ngx_kmp_rtmp_encoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@
#define NGX_RTMP_AVC_SEQUENCE_HEADER 0
#define NGX_RTMP_AVC_NALU 1

#define NGX_RTMP_EXT_HEADER_SIZE 8 /* (frame | packet type), pts_delay, fourcc */
#define NGX_RTMP_EXT_HEADER_SIZE 5 /* (frame | packet type), fourcc */
#define NGX_RTMP_EXT_HEADER_SIZE_NALU 8 /* + pts_delay */
#define NGX_RTMP_EXT_SEQUENCE_HEADER 0
#define NGX_RTMP_EXT_NALU 1
static const uint32_t NGX_RTMP_EXT_FOURCC_HVC1 = 0x31637668;

/* audio */
#define NGX_RTMP_AAC_HEADER_SIZE 2 /* sound_info + packet_type */
Expand All @@ -57,7 +57,7 @@ static const uint32_t NGX_RTMP_EXT_FOURCC_HVC1 = 0x31637668;


#define NGX_RTMP_FRAME_HEADER_MAX_SIZE (NGX_RTMP_HEADER_0_SIZE \
+ NGX_RTMP_EXT_TIMESTAMP_SIZE + NGX_RTMP_EXT_HEADER_SIZE)
+ NGX_RTMP_EXT_TIMESTAMP_SIZE + NGX_RTMP_EXT_HEADER_SIZE_NALU)


#define ngx_kmp_rtmp_chunk_count(mlen, chunk_size) \
Expand Down Expand Up @@ -489,10 +489,6 @@ static ngx_kmp_rtmp_amf_field_t ngx_kmp_rtmp_amf_onfi[] = {
};


static u_char *
ngx_kmp_rtmp_encoder_ext_header_write(uint32_t codec_id, u_char *p, u_char packet_type,
u_char key_frame, uint32_t pts_delay);

static ngx_inline u_char *
ngx_kmp_rtmp_encoder_write_header(u_char *p, ngx_kmp_rtmp_header_t *h)
{
Expand Down Expand Up @@ -901,6 +897,66 @@ ngx_kmp_rtmp_encoder_avc_sequence_write(u_char *p,
}


static u_char *
ngx_kmp_rtmp_encoder_ext_header_write(u_char *p, u_char packet_type,
u_char key_frame, uint32_t fourcc, uint32_t pts_delay)
{
u_char frame_type;

frame_type = key_frame ? NGX_RTMP_FRAME_TYPE_KEY
: NGX_RTMP_FRAME_TYPE_INTER;

*p++ = 0x80 | (frame_type << 4) | packet_type;

p = ngx_copy(p, &fourcc, sizeof(fourcc));

if (packet_type == NGX_RTMP_EXT_NALU) {
ngx_kmp_rtmp_amf_write_be24(p, pts_delay);
}

return p;
}


size_t
ngx_kmp_rtmp_encoder_ext_sequence_get_size(ngx_kmp_rtmp_stream_ctx_t *sc,
ngx_str_t *extra_data)
{
size_t mlen;

mlen = NGX_RTMP_EXT_HEADER_SIZE + extra_data->len;

return NGX_RTMP_HEADER_0_SIZE + mlen
+ (ngx_kmp_rtmp_chunk_count(mlen, sc->chunk_size) - 1)
* NGX_RTMP_HEADER_3_SIZE;
}


u_char *
ngx_kmp_rtmp_encoder_ext_sequence_write(u_char *p,
ngx_kmp_rtmp_stream_ctx_t *sc, uint32_t fourcc, ngx_str_t *extra_data)
{
u_char *body;
ngx_kmp_rtmp_header_t h;

ngx_memzero(&h, sizeof(h));
h.csid = sc->csid;
h.mlen = NGX_RTMP_EXT_HEADER_SIZE + extra_data->len;
h.type = NGX_RTMP_MSG_VIDEO;
h.msid = sc->msid;

p = ngx_kmp_rtmp_encoder_write_header(p, &h);

body = p;
p = ngx_kmp_rtmp_encoder_ext_header_write(p, NGX_RTMP_EXT_SEQUENCE_HEADER,
1, fourcc, 0);
ngx_memcpy(p, extra_data->data, extra_data->len);

return ngx_kmp_rtmp_encoder_add_chunk_headers(body, h.mlen, sc->chunk_size,
h.csid);
}


static u_char *
ngx_kmp_rtmp_encoder_aac_header_write(u_char *p, u_char sound_info,
u_char packet_type)
Expand Down Expand Up @@ -1014,6 +1070,7 @@ ngx_kmp_rtmp_encoder_frame_write(ngx_kmp_rtmp_stream_ctx_t *sc,
h.timestamp = NGX_RTMP_EXT_TIMESTAMP;
}

/* TODO: add support for "vp09" and "av01" */
switch (codec_id) {

case KMP_CODEC_VIDEO_H264:
Expand All @@ -1025,11 +1082,12 @@ ngx_kmp_rtmp_encoder_frame_write(ngx_kmp_rtmp_stream_ctx_t *sc,
break;

case KMP_CODEC_VIDEO_H265:
header_size = NGX_RTMP_EXT_HEADER_SIZE - 4;
header_size = NGX_RTMP_EXT_HEADER_SIZE_NALU;
h.type = NGX_RTMP_MSG_VIDEO;

p = ngx_kmp_rtmp_encoder_ext_header_write(codec_id, p, NGX_RTMP_AVC_NALU,
frame->flags & KMP_FRAME_FLAG_KEY, frame->pts_delay);
p = ngx_kmp_rtmp_encoder_ext_header_write(p, NGX_RTMP_EXT_NALU,
frame->flags & KMP_FRAME_FLAG_KEY, NGX_RTMP_EXT_FOURCC_HVC1,
frame->pts_delay);
break;

case KMP_CODEC_AUDIO_MP3:
Expand Down Expand Up @@ -1115,65 +1173,3 @@ ngx_kmp_rtmp_encoder_frame_write(ngx_kmp_rtmp_stream_ctx_t *sc,

return NGX_OK;
}


size_t
ngx_kmp_rtmp_encoder_ext_sequence_get_size(ngx_kmp_rtmp_stream_ctx_t *sc,
ngx_str_t *extra_data)
{
size_t mlen;

mlen = NGX_RTMP_EXT_HEADER_SIZE - 3 + extra_data->len;

return NGX_RTMP_HEADER_0_SIZE + mlen
+ (ngx_kmp_rtmp_chunk_count(mlen, sc->chunk_size) - 1)
* NGX_RTMP_HEADER_3_SIZE;
}


u_char *
ngx_kmp_rtmp_encoder_ext_sequence_write(uint32_t codec_id, u_char *p,
ngx_kmp_rtmp_stream_ctx_t *sc, ngx_str_t *extra_data)
{
u_char *body;
ngx_kmp_rtmp_header_t h;


ngx_memzero(&h, sizeof(h));
h.csid = sc->csid;
h.mlen = NGX_RTMP_EXT_HEADER_SIZE - 3 + extra_data->len;
h.type = NGX_RTMP_MSG_VIDEO;
h.msid = sc->msid;

p = ngx_kmp_rtmp_encoder_write_header(p, &h);

body = p;
p = ngx_kmp_rtmp_encoder_ext_header_write(codec_id, p, NGX_RTMP_EXT_SEQUENCE_HEADER,
1, 0);
ngx_memcpy(p, extra_data->data, extra_data->len);

return ngx_kmp_rtmp_encoder_add_chunk_headers(body, h.mlen, sc->chunk_size,
h.csid);
}


static u_char *
ngx_kmp_rtmp_encoder_ext_header_write(uint32_t codec_id, u_char *p, u_char packet_type,
u_char key_frame, uint32_t pts_delay)
{
u_char frame_type;

frame_type = key_frame ? NGX_RTMP_FRAME_TYPE_KEY
: NGX_RTMP_FRAME_TYPE_INTER;

*p++ = (frame_type << 4) | 0x80 | packet_type;

// TODO: support for “vp09” and “av01”
p = ngx_copy(p, &NGX_RTMP_EXT_FOURCC_HVC1, 4);

if(packet_type == NGX_RTMP_EXT_NALU) {
ngx_kmp_rtmp_amf_write_be24(p, pts_delay);
}

return p;
}
14 changes: 7 additions & 7 deletions nginx-kmp-rtmp-module/src/ngx_kmp_rtmp_encoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

#define NGX_KMP_RTMP_TIMESCALE (1000)

#define NGX_RTMP_EXT_FOURCC_HVC1 0x31637668


typedef ngx_int_t (*ngx_kmp_rtmp_write_pt)(void *data, void *buf, size_t size);

Expand Down Expand Up @@ -95,6 +97,11 @@ size_t ngx_kmp_rtmp_encoder_avc_sequence_get_size(
u_char *ngx_kmp_rtmp_encoder_avc_sequence_write(u_char *p,
ngx_kmp_rtmp_stream_ctx_t *sc, ngx_str_t *extra_data);

size_t ngx_kmp_rtmp_encoder_ext_sequence_get_size(
ngx_kmp_rtmp_stream_ctx_t *sc, ngx_str_t *extra_data);
u_char *ngx_kmp_rtmp_encoder_ext_sequence_write(u_char *p,
ngx_kmp_rtmp_stream_ctx_t *sc, uint32_t fourcc, ngx_str_t *extra_data);

size_t ngx_kmp_rtmp_encoder_aac_sequence_get_size(
ngx_kmp_rtmp_stream_ctx_t *sc, ngx_str_t *extra_data);
u_char *ngx_kmp_rtmp_encoder_aac_sequence_write(u_char *p,
Expand All @@ -110,11 +117,4 @@ ngx_int_t ngx_kmp_rtmp_encoder_frame_write(ngx_kmp_rtmp_stream_ctx_t *sc,
ngx_kmp_rtmp_frame_t *frame, uint32_t codec_id,
ngx_kmp_rtmp_write_pt write, void *data);


size_t ngx_kmp_rtmp_encoder_ext_sequence_get_size(
ngx_kmp_rtmp_stream_ctx_t *sc, ngx_str_t *extra_data);
u_char *ngx_kmp_rtmp_encoder_ext_sequence_write(uint32_t codec_id, u_char *p,
ngx_kmp_rtmp_stream_ctx_t *sc, ngx_str_t *extra_data);


#endif /* _NGX_KMP_RTMP_ENCODER_H_INCLUDED_ */
25 changes: 16 additions & 9 deletions nginx-kmp-rtmp-module/src/ngx_kmp_rtmp_stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,13 +185,17 @@ ngx_kmp_rtmp_stream_write_meta(ngx_kmp_rtmp_stream_t *stream)

size = ngx_kmp_rtmp_encoder_metadata_get_size(&stream->ctx, &meta);

if (meta.mi[KMP_MEDIA_VIDEO].codec_id == KMP_CODEC_VIDEO_H264) {
switch (meta.mi[KMP_MEDIA_VIDEO].codec_id) {

case KMP_CODEC_VIDEO_H264:
size += ngx_kmp_rtmp_encoder_avc_sequence_get_size(
&stream->ctx, &extra_data[KMP_MEDIA_VIDEO]);
}
break;

if (meta.mi[KMP_MEDIA_VIDEO].codec_id == KMP_CODEC_VIDEO_H265) {
size += ngx_kmp_rtmp_encoder_ext_sequence_get_size(&stream->ctx, &extra_data[KMP_MEDIA_VIDEO]);
case KMP_CODEC_VIDEO_H265:
size += ngx_kmp_rtmp_encoder_ext_sequence_get_size(
&stream->ctx, &extra_data[KMP_MEDIA_VIDEO]);
break;
}

if (meta.mi[KMP_MEDIA_AUDIO].codec_id == KMP_CODEC_AUDIO_AAC) {
Expand All @@ -208,14 +212,17 @@ ngx_kmp_rtmp_stream_write_meta(ngx_kmp_rtmp_stream_t *stream)

p = ngx_kmp_rtmp_encoder_metadata_write(start, &stream->ctx, &meta);

if (meta.mi[KMP_MEDIA_VIDEO].codec_id == KMP_CODEC_VIDEO_H264) {
switch (meta.mi[KMP_MEDIA_VIDEO].codec_id) {

case KMP_CODEC_VIDEO_H264:
p = ngx_kmp_rtmp_encoder_avc_sequence_write(p, &stream->ctx,
&extra_data[KMP_MEDIA_VIDEO]);
}
break;

if (meta.mi[KMP_MEDIA_VIDEO].codec_id == KMP_CODEC_VIDEO_H265) {
p = ngx_kmp_rtmp_encoder_ext_sequence_write(meta.mi[KMP_MEDIA_VIDEO].codec_id,
p, &stream->ctx, &extra_data[KMP_MEDIA_VIDEO]);
case KMP_CODEC_VIDEO_H265:
p = ngx_kmp_rtmp_encoder_ext_sequence_write(p, &stream->ctx,
NGX_RTMP_EXT_FOURCC_HVC1, &extra_data[KMP_MEDIA_VIDEO]);
break;
}

if (meta.mi[KMP_MEDIA_AUDIO].codec_id == KMP_CODEC_AUDIO_AAC) {
Expand Down
Loading
Loading